timeback 0.0.0-alpha.2 → 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 (100) hide show
  1. package/README.md +211 -7
  2. package/dist/client/adapters/react/SignInButton.d.ts +60 -0
  3. package/dist/client/adapters/react/SignInButton.d.ts.map +1 -0
  4. package/dist/client/adapters/react/index.d.ts +43 -0
  5. package/dist/client/adapters/react/index.d.ts.map +1 -0
  6. package/dist/client/adapters/react/index.js +478 -0
  7. package/dist/client/adapters/react/provider.d.ts +74 -0
  8. package/dist/client/adapters/react/provider.d.ts.map +1 -0
  9. package/dist/client/adapters/solid/SignInButton.d.ts +52 -0
  10. package/dist/client/adapters/solid/SignInButton.d.ts.map +1 -0
  11. package/dist/client/adapters/solid/SignInButton.tsx +321 -0
  12. package/dist/client/adapters/solid/context.d.ts +73 -0
  13. package/dist/client/adapters/solid/context.d.ts.map +1 -0
  14. package/dist/client/adapters/solid/context.tsx +91 -0
  15. package/dist/client/adapters/solid/index.d.ts +42 -0
  16. package/dist/client/adapters/solid/index.d.ts.map +1 -0
  17. package/dist/client/adapters/solid/index.ts +46 -0
  18. package/dist/client/adapters/svelte/SignInButton.svelte +234 -0
  19. package/dist/client/adapters/svelte/SignInButton.svelte.d.ts +24 -0
  20. package/dist/client/adapters/svelte/index.d.ts +33 -0
  21. package/dist/client/adapters/svelte/index.d.ts.map +1 -0
  22. package/dist/client/adapters/svelte/index.ts +38 -0
  23. package/dist/client/adapters/svelte/stores.d.ts +62 -0
  24. package/dist/client/adapters/svelte/stores.d.ts.map +1 -0
  25. package/dist/client/adapters/svelte/stores.ts +139 -0
  26. package/dist/client/index.d.ts +9 -0
  27. package/dist/client/index.d.ts.map +1 -0
  28. package/dist/client/lib/activity/activity.class.d.ts +73 -0
  29. package/dist/client/lib/activity/activity.class.d.ts.map +1 -0
  30. package/dist/client/lib/activity/activity.d.ts +16 -0
  31. package/dist/client/lib/activity/activity.d.ts.map +1 -0
  32. package/dist/client/lib/activity/index.d.ts +6 -0
  33. package/dist/client/lib/activity/index.d.ts.map +1 -0
  34. package/dist/client/lib/utils.d.ts +20 -0
  35. package/dist/client/lib/utils.d.ts.map +1 -0
  36. package/dist/client/namespaces/activity.d.ts +37 -0
  37. package/dist/client/namespaces/activity.d.ts.map +1 -0
  38. package/dist/client/namespaces/auth.d.ts +33 -0
  39. package/dist/client/namespaces/auth.d.ts.map +1 -0
  40. package/dist/client/namespaces/index.d.ts +7 -0
  41. package/dist/client/namespaces/index.d.ts.map +1 -0
  42. package/dist/client/namespaces/user.d.ts +29 -0
  43. package/dist/client/namespaces/user.d.ts.map +1 -0
  44. package/dist/client/timeback-client.class.d.ts +37 -0
  45. package/dist/client/timeback-client.class.d.ts.map +1 -0
  46. package/dist/client/timeback-client.d.ts +29 -0
  47. package/dist/client/timeback-client.d.ts.map +1 -0
  48. package/dist/client.d.ts +30 -0
  49. package/dist/client.d.ts.map +1 -0
  50. package/dist/client.js +198 -0
  51. package/dist/index.d.ts +27 -14
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +1137 -11
  54. package/dist/server/adapters/express.d.ts +62 -0
  55. package/dist/server/adapters/express.d.ts.map +1 -0
  56. package/dist/server/adapters/express.js +565 -0
  57. package/dist/server/adapters/native.d.ts +45 -0
  58. package/dist/server/adapters/native.d.ts.map +1 -0
  59. package/dist/server/adapters/native.js +509 -0
  60. package/dist/server/adapters/nextjs.d.ts +30 -0
  61. package/dist/server/adapters/nextjs.d.ts.map +1 -0
  62. package/dist/server/adapters/nextjs.js +521 -0
  63. package/dist/server/adapters/solid-start.d.ts +61 -0
  64. package/dist/server/adapters/solid-start.d.ts.map +1 -0
  65. package/dist/server/adapters/solid-start.js +551 -0
  66. package/dist/server/adapters/svelte-kit.d.ts +82 -0
  67. package/dist/server/adapters/svelte-kit.d.ts.map +1 -0
  68. package/dist/server/adapters/svelte-kit.js +572 -0
  69. package/dist/server/adapters/tanstack-start.js +522 -0
  70. package/dist/server/adapters/types.d.ts +212 -0
  71. package/dist/server/adapters/types.d.ts.map +1 -0
  72. package/dist/server/adapters/utils.d.ts +15 -0
  73. package/dist/server/adapters/utils.d.ts.map +1 -0
  74. package/dist/server/handlers/activity.d.ts +28 -0
  75. package/dist/server/handlers/activity.d.ts.map +1 -0
  76. package/dist/server/handlers/identity.d.ts +24 -0
  77. package/dist/server/handlers/identity.d.ts.map +1 -0
  78. package/dist/server/handlers/index.d.ts +9 -0
  79. package/dist/server/handlers/index.d.ts.map +1 -0
  80. package/dist/server/handlers/user.d.ts +30 -0
  81. package/dist/server/handlers/user.d.ts.map +1 -0
  82. package/dist/server/index.d.ts +10 -0
  83. package/dist/server/index.d.ts.map +1 -0
  84. package/dist/server/lib/index.d.ts +9 -0
  85. package/dist/server/lib/index.d.ts.map +1 -0
  86. package/dist/server/lib/logger.d.ts +21 -0
  87. package/dist/server/lib/logger.d.ts.map +1 -0
  88. package/dist/server/lib/oidc.d.ts +76 -0
  89. package/dist/server/lib/oidc.d.ts.map +1 -0
  90. package/dist/server/lib/utils.d.ts +39 -0
  91. package/dist/server/lib/utils.d.ts.map +1 -0
  92. package/dist/server/timeback.d.ts +48 -0
  93. package/dist/server/timeback.d.ts.map +1 -0
  94. package/dist/server/types.d.ts +300 -0
  95. package/dist/server/types.d.ts.map +1 -0
  96. package/dist/shared/constants.d.ts +18 -0
  97. package/dist/shared/constants.d.ts.map +1 -0
  98. package/dist/shared/types.d.ts +100 -0
  99. package/dist/shared/types.d.ts.map +1 -0
  100. package/package.json +92 -28
@@ -0,0 +1,234 @@
1
+ <!--
2
+ Sign In with Timeback Button
3
+
4
+ A pre-styled button for Timeback SSO authentication.
5
+ Fully customizable via CSS variables.
6
+
7
+ @example
8
+ ```svelte
9
+ <script>
10
+ import SignInButton from 'timeback/svelte/SignInButton.svelte'
11
+ </script>
12
+
13
+ <SignInButton />
14
+ <SignInButton variant="outline">Continue with Timeback</SignInButton>
15
+ ```
16
+ -->
17
+ <script lang="ts">
18
+ import { timeback } from 'timeback/svelte'
19
+
20
+ /** Additional CSS class names */
21
+ let className: string = ''
22
+ export { className as class }
23
+
24
+ /** Disabled state */
25
+ export let disabled: boolean = false
26
+
27
+ /** Show loading spinner when clicked */
28
+ export let showLoading: boolean = true
29
+
30
+ /** Button variant */
31
+ export let variant: 'default' | 'outline' | 'minimal' = 'default'
32
+
33
+ /** Button size */
34
+ export let size: 'sm' | 'md' | 'lg' = 'md'
35
+
36
+ /** Show Timeback logo */
37
+ export let showLogo: boolean = true
38
+
39
+ /** Click handler - can call e.preventDefault() to prevent sign-in redirect */
40
+ export let onclick: ((e: MouseEvent) => void) | undefined = undefined
41
+
42
+ let isLoading = false
43
+
44
+ function handleClick(e: MouseEvent) {
45
+ if (onclick) {
46
+ onclick(e)
47
+ if (e.defaultPrevented) {
48
+ return
49
+ }
50
+ }
51
+
52
+ if (showLoading) {
53
+ isLoading = true
54
+ }
55
+ $timeback?.auth.signIn()
56
+ }
57
+
58
+ $: isReady = !!$timeback
59
+ $: classes = [
60
+ 'timeback-signin-btn',
61
+ variant !== 'default' && `timeback-signin-btn--${variant}`,
62
+ size !== 'md' && `timeback-signin-btn--${size}`,
63
+ className,
64
+ ]
65
+ .filter(Boolean)
66
+ .join(' ')
67
+ </script>
68
+
69
+ <button
70
+ type="button"
71
+ class={classes}
72
+ disabled={disabled || !isReady || isLoading}
73
+ aria-busy={isLoading}
74
+ on:click={handleClick}
75
+ >
76
+ {#if isLoading}
77
+ <svg
78
+ class="timeback-signin-btn__spinner"
79
+ width="16"
80
+ height="16"
81
+ viewBox="0 0 24 24"
82
+ fill="none"
83
+ xmlns="http://www.w3.org/2000/svg"
84
+ aria-hidden="true"
85
+ >
86
+ <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" stroke-opacity="0.25" />
87
+ <path d="M12 2C6.48 2 2 6.48 2 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
88
+ </svg>
89
+ {:else if showLogo}
90
+ <svg
91
+ class="timeback-signin-btn__logo"
92
+ width="20"
93
+ height="18"
94
+ viewBox="0 0 199 180"
95
+ fill="none"
96
+ xmlns="http://www.w3.org/2000/svg"
97
+ aria-hidden="true"
98
+ >
99
+ <g clip-path="url(#tb-logo-clip-svelte)">
100
+ <path
101
+ d="M121.432 179.456C110.607 177.871 101.153 173.91 92.4882 168.085C91.1274 167.17 89.4598 165.404 89.4375 164.008C89.2123 149.891 89.3002 135.77 89.3002 119.86C93.1365 123.255 95.8538 125.706 98.6224 128.099C103.151 132.012 107.437 136.28 112.314 139.703C126.466 149.635 145.037 147.25 156.045 134.448C166.919 121.803 167.226 101.374 155.695 89.6399C145.727 79.4958 134.693 70.3995 123.251 60.0438C123.251 77.8871 123.251 94.5637 123.251 112.15C121.428 110.999 120.279 110.479 119.383 109.676C110.329 101.573 101.241 93.5044 92.3634 85.2109C90.8519 83.7988 89.4363 81.3758 89.4209 79.4084C89.2249 54.4218 89.2905 29.4332 89.3061 4.44502C89.3066 3.64954 89.3061 2.22136 89.3061 1.47755C90.8061 1.47755 92.694 1.47857 94.1427 1.47755C118.131 1.46071 142.12 1.52088 166.108 1.39821C169.235 1.38222 171.33 2.18661 173.251 4.75826C180.607 14.6032 188.189 24.279 196.266 34.7705C179.79 34.7705 164.169 34.7705 148.548 34.7705C147.871 34.7705 147.366 34.7705 146.866 34.7705C147.866 35.7705 150.35 38.3018 151.61 39.4825C162.643 49.8249 174.663 59.3807 184.245 70.947C202.474 92.9508 203.539 118.134 191.204 143.046C178.598 168.508 156.61 180.302 128.298 180.295C126.154 180.295 124.011 179.778 121.432 179.456Z"
102
+ fill="currentColor"
103
+ />
104
+ <circle cx="40" cy="133" r="39" fill="currentColor" />
105
+ <circle cx="39" cy="39" r="39" fill="currentColor" />
106
+ </g>
107
+ <defs>
108
+ <clipPath id="tb-logo-clip-svelte">
109
+ <rect width="199" height="180" fill="currentColor" />
110
+ </clipPath>
111
+ </defs>
112
+ </svg>
113
+ {/if}
114
+ <slot>Sign in with Timeback</slot>
115
+ </button>
116
+
117
+ <style>
118
+ .timeback-signin-btn {
119
+ /* Colors */
120
+ --tb-btn-bg: #0f172a;
121
+ --tb-btn-bg-hover: #1e293b;
122
+ --tb-btn-text: #ffffff;
123
+ --tb-btn-border: transparent;
124
+
125
+ /* Outline variant */
126
+ --tb-btn-outline-bg: transparent;
127
+ --tb-btn-outline-bg-hover: #f1f5f9;
128
+ --tb-btn-outline-text: #0f172a;
129
+ --tb-btn-outline-border: #e2e8f0;
130
+
131
+ /* Minimal variant */
132
+ --tb-btn-minimal-bg: transparent;
133
+ --tb-btn-minimal-bg-hover: #f1f5f9;
134
+ --tb-btn-minimal-text: #0f172a;
135
+
136
+ /* Sizing */
137
+ --tb-btn-padding-x: 1rem;
138
+ --tb-btn-padding-y: 0.625rem;
139
+ --tb-btn-font-size: 0.875rem;
140
+ --tb-btn-border-radius: 0.5rem;
141
+ --tb-btn-gap: 0.5rem;
142
+
143
+ /* Transitions */
144
+ --tb-btn-transition: all 150ms ease;
145
+
146
+ /* Focus ring */
147
+ --tb-btn-focus-ring: #3b82f6;
148
+ --tb-btn-focus-ring-offset: 2px;
149
+
150
+ /* Base styles */
151
+ display: inline-flex;
152
+ align-items: center;
153
+ justify-content: center;
154
+ gap: var(--tb-btn-gap);
155
+ padding: var(--tb-btn-padding-y) var(--tb-btn-padding-x);
156
+ font-size: var(--tb-btn-font-size);
157
+ font-weight: 500;
158
+ font-family: inherit;
159
+ line-height: 1.5;
160
+ border-radius: var(--tb-btn-border-radius);
161
+ border: 1px solid var(--tb-btn-border);
162
+ background-color: var(--tb-btn-bg);
163
+ color: var(--tb-btn-text);
164
+ cursor: pointer;
165
+ transition: var(--tb-btn-transition);
166
+ text-decoration: none;
167
+ white-space: nowrap;
168
+ }
169
+
170
+ .timeback-signin-btn:hover:not(:disabled) {
171
+ background-color: var(--tb-btn-bg-hover);
172
+ }
173
+
174
+ .timeback-signin-btn:focus-visible {
175
+ outline: 2px solid var(--tb-btn-focus-ring);
176
+ outline-offset: var(--tb-btn-focus-ring-offset);
177
+ }
178
+
179
+ .timeback-signin-btn:disabled {
180
+ opacity: 0.6;
181
+ cursor: not-allowed;
182
+ }
183
+
184
+ /* Outline variant */
185
+ .timeback-signin-btn--outline {
186
+ --tb-btn-bg: var(--tb-btn-outline-bg);
187
+ --tb-btn-bg-hover: var(--tb-btn-outline-bg-hover);
188
+ --tb-btn-text: var(--tb-btn-outline-text);
189
+ --tb-btn-border: var(--tb-btn-outline-border);
190
+ }
191
+
192
+ /* Minimal variant */
193
+ .timeback-signin-btn--minimal {
194
+ --tb-btn-bg: var(--tb-btn-minimal-bg);
195
+ --tb-btn-bg-hover: var(--tb-btn-minimal-bg-hover);
196
+ --tb-btn-text: var(--tb-btn-minimal-text);
197
+ --tb-btn-border: transparent;
198
+ }
199
+
200
+ /* Sizes */
201
+ .timeback-signin-btn--sm {
202
+ --tb-btn-padding-x: 0.75rem;
203
+ --tb-btn-padding-y: 0.375rem;
204
+ --tb-btn-font-size: 0.75rem;
205
+ --tb-btn-gap: 0.375rem;
206
+ }
207
+
208
+ .timeback-signin-btn--lg {
209
+ --tb-btn-padding-x: 1.5rem;
210
+ --tb-btn-padding-y: 0.75rem;
211
+ --tb-btn-font-size: 1rem;
212
+ --tb-btn-gap: 0.625rem;
213
+ }
214
+
215
+ /* Logo */
216
+ .timeback-signin-btn__logo {
217
+ flex-shrink: 0;
218
+ }
219
+
220
+ /* Loading spinner */
221
+ .timeback-signin-btn__spinner {
222
+ animation: timeback-spin 1s linear infinite;
223
+ }
224
+
225
+ @keyframes timeback-spin {
226
+ from {
227
+ transform: rotate(0deg);
228
+ }
229
+ to {
230
+ transform: rotate(360deg);
231
+ }
232
+ }
233
+ </style>
234
+
@@ -0,0 +1,24 @@
1
+ import type { SvelteComponentTyped } from 'svelte'
2
+
3
+ export interface SignInButtonProps {
4
+ /** Additional CSS class names (maps to the `class` attribute) */
5
+ class?: string
6
+ /** Disabled state */
7
+ disabled?: boolean
8
+ /** Show loading spinner when clicked */
9
+ showLoading?: boolean
10
+ /** Button variant */
11
+ variant?: 'default' | 'outline' | 'minimal'
12
+ /** Button size */
13
+ size?: 'sm' | 'md' | 'lg'
14
+ /** Show Timeback logo */
15
+ showLogo?: boolean
16
+ /** Click handler - can call e.preventDefault() to prevent sign-in redirect */
17
+ onclick?: (e: MouseEvent) => void
18
+ }
19
+
20
+ export default class SignInButton extends SvelteComponentTyped<
21
+ SignInButtonProps,
22
+ { click: MouseEvent },
23
+ { default: {} }
24
+ > {}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Svelte Client Module
3
+ *
4
+ * Svelte-specific exports for Timeback SDK.
5
+ *
6
+ * @example
7
+ * ```svelte
8
+ * <script>
9
+ * import { timeback, SignInButton } from 'timeback/svelte'
10
+ *
11
+ * function handleSignIn() {
12
+ * $timeback?.auth.signIn()
13
+ * }
14
+ *
15
+ * async function handleFetchProfile() {
16
+ * const profile = await $timeback?.user.fetch()
17
+ * }
18
+ *
19
+ * function handleStartActivity() {
20
+ * const activity = $timeback?.activity.new({ id: 'lesson-1', name: 'Intro', courseCode: 'MATH' })
21
+ * activity?.start()
22
+ * }
23
+ * </script>
24
+ *
25
+ * <SignInButton />
26
+ * ```
27
+ */
28
+ export { Activity, createClient, TimebackClient } from 'timeback/client';
29
+ export type { ActivityMetrics, ActivityParams, TimebackUser } from 'timeback/client';
30
+ export { initTimeback, timeback } from './stores';
31
+ export { default as SignInButton } from './SignInButton.svelte';
32
+ export type { SignInButtonProps } from './SignInButton.svelte';
33
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/client/adapters/svelte/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACxE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAGpF,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAGjD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAC/D,YAAY,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Svelte Client Module
3
+ *
4
+ * Svelte-specific exports for Timeback SDK.
5
+ *
6
+ * @example
7
+ * ```svelte
8
+ * <script>
9
+ * import { timeback, SignInButton } from 'timeback/svelte'
10
+ *
11
+ * function handleSignIn() {
12
+ * $timeback?.auth.signIn()
13
+ * }
14
+ *
15
+ * async function handleFetchProfile() {
16
+ * const profile = await $timeback?.user.fetch()
17
+ * }
18
+ *
19
+ * function handleStartActivity() {
20
+ * const activity = $timeback?.activity.new({ id: 'lesson-1', name: 'Intro', courseCode: 'MATH' })
21
+ * activity?.start()
22
+ * }
23
+ * </script>
24
+ *
25
+ * <SignInButton />
26
+ * ```
27
+ */
28
+
29
+ // Re-export from timeback/client for convenience
30
+ export { Activity, createClient, TimebackClient } from 'timeback/client'
31
+ export type { ActivityMetrics, ActivityParams, TimebackUser } from 'timeback/client'
32
+
33
+ // Svelte-specific
34
+ export { initTimeback, timeback } from './stores'
35
+
36
+ // Components
37
+ export { default as SignInButton } from './SignInButton.svelte'
38
+ export type { SignInButtonProps } from './SignInButton.svelte'
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Svelte Stores
3
+ *
4
+ * Svelte stores for Timeback SDK reactivity.
5
+ */
6
+ import { TimebackClient } from 'timeback/client';
7
+ /**
8
+ * Minimal Svelte-compatible store interface.
9
+ *
10
+ * This allows the SDK to work without a direct Svelte dependency.
11
+ */
12
+ interface Readable<T> {
13
+ subscribe: (run: (value: T) => void) => () => void;
14
+ }
15
+ /**
16
+ * Initialize the Timeback client.
17
+ *
18
+ * Call this in your root layout or app initialization.
19
+ *
20
+ * @param client - Optional custom client instance
21
+ *
22
+ * @example
23
+ * ```svelte
24
+ * <script>
25
+ * import { initTimeback } from 'timeback/svelte'
26
+ * import { onMount } from 'svelte'
27
+ *
28
+ * onMount(() => {
29
+ * initTimeback()
30
+ * })
31
+ * </script>
32
+ * ```
33
+ */
34
+ export declare function initTimeback(client?: TimebackClient): void;
35
+ /**
36
+ * Store containing the Timeback client.
37
+ *
38
+ * Use this to access all Timeback functionality: auth, user, activities.
39
+ *
40
+ * @example
41
+ * ```svelte
42
+ * <script>
43
+ * import { timeback } from 'timeback/svelte'
44
+ *
45
+ * function handleSignIn() {
46
+ * $timeback?.auth.signIn()
47
+ * }
48
+ *
49
+ * async function handleFetchProfile() {
50
+ * const profile = await $timeback?.user.fetch()
51
+ * }
52
+ *
53
+ * function handleStartActivity() {
54
+ * const activity = $timeback?.activity.new({ id: 'lesson-1', name: 'Intro', courseCode: 'MATH' })
55
+ * activity?.start()
56
+ * }
57
+ * </script>
58
+ * ```
59
+ */
60
+ export declare const timeback: Readable<TimebackClient | undefined>;
61
+ export {};
62
+ //# sourceMappingURL=stores.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stores.d.ts","sourceRoot":"","sources":["../../../../src/client/adapters/svelte/stores.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEhD;;;;GAIG;AACH,UAAU,QAAQ,CAAC,CAAC;IACnB,SAAS,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,KAAK,MAAM,IAAI,CAAA;CAClD;AAqDD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,cAAc,GAAG,IAAI,CAQ1D;AAkBD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,QAAQ,EAAE,QAAQ,CAAC,cAAc,GAAG,SAAS,CAAe,CAAA"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Svelte Stores
3
+ *
4
+ * Svelte stores for Timeback SDK reactivity.
5
+ */
6
+
7
+ import { TimebackClient } from 'timeback/client'
8
+
9
+ /**
10
+ * Minimal Svelte-compatible store interface.
11
+ *
12
+ * This allows the SDK to work without a direct Svelte dependency.
13
+ */
14
+ interface Readable<T> {
15
+ subscribe: (run: (value: T) => void) => () => void
16
+ }
17
+
18
+ interface Writable<T> extends Readable<T> {
19
+ set: (value: T) => void
20
+ update: (updater: (value: T) => T) => void
21
+ }
22
+
23
+ /**
24
+ * Create a minimal writable store implementation.
25
+ *
26
+ * @param initialValue - Initial store value
27
+ * @returns Writable store
28
+ */
29
+ function writable<T>(initialValue: T): Writable<T> {
30
+ let value = initialValue
31
+ const subscribers = new Set<(value: T) => void>()
32
+
33
+ return {
34
+ subscribe(run) {
35
+ subscribers.add(run)
36
+ run(value)
37
+ return () => subscribers.delete(run)
38
+ },
39
+ set(newValue) {
40
+ value = newValue
41
+ subscribers.forEach(fn => fn(value))
42
+ },
43
+ update(updater) {
44
+ value = updater(value)
45
+ subscribers.forEach(fn => fn(value))
46
+ },
47
+ }
48
+ }
49
+
50
+ let clientInstance: TimebackClient | undefined
51
+
52
+ /**
53
+ * Get or create the singleton Timeback client.
54
+ *
55
+ * @returns TimebackClient instance
56
+ */
57
+ function getOrCreateClient(): TimebackClient {
58
+ if (!clientInstance) {
59
+ clientInstance = new TimebackClient()
60
+ }
61
+ return clientInstance
62
+ }
63
+
64
+ /**
65
+ * Internal client store.
66
+ */
67
+ const clientStore = writable<TimebackClient | undefined>(undefined)
68
+
69
+ /**
70
+ * Initialize the Timeback client.
71
+ *
72
+ * Call this in your root layout or app initialization.
73
+ *
74
+ * @param client - Optional custom client instance
75
+ *
76
+ * @example
77
+ * ```svelte
78
+ * <script>
79
+ * import { initTimeback } from 'timeback/svelte'
80
+ * import { onMount } from 'svelte'
81
+ *
82
+ * onMount(() => {
83
+ * initTimeback()
84
+ * })
85
+ * </script>
86
+ * ```
87
+ */
88
+ export function initTimeback(client?: TimebackClient): void {
89
+ if (client) {
90
+ clientInstance = client
91
+ clientStore.set(client)
92
+ return
93
+ }
94
+
95
+ clientStore.set(getOrCreateClient())
96
+ }
97
+
98
+ /**
99
+ * Check if we're running in the browser.
100
+ *
101
+ * @returns True if in browser
102
+ */
103
+ function isBrowser(): boolean {
104
+ return typeof window !== 'undefined'
105
+ }
106
+
107
+ /**
108
+ * Auto-initialize on first access in browser.
109
+ */
110
+ if (isBrowser()) {
111
+ initTimeback()
112
+ }
113
+
114
+ /**
115
+ * Store containing the Timeback client.
116
+ *
117
+ * Use this to access all Timeback functionality: auth, user, activities.
118
+ *
119
+ * @example
120
+ * ```svelte
121
+ * <script>
122
+ * import { timeback } from 'timeback/svelte'
123
+ *
124
+ * function handleSignIn() {
125
+ * $timeback?.auth.signIn()
126
+ * }
127
+ *
128
+ * async function handleFetchProfile() {
129
+ * const profile = await $timeback?.user.fetch()
130
+ * }
131
+ *
132
+ * function handleStartActivity() {
133
+ * const activity = $timeback?.activity.new({ id: 'lesson-1', name: 'Intro', courseCode: 'MATH' })
134
+ * activity?.start()
135
+ * }
136
+ * </script>
137
+ * ```
138
+ */
139
+ export const timeback: Readable<TimebackClient | undefined> = clientStore
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Client Module
3
+ *
4
+ * Framework-agnostic client exports.
5
+ */
6
+ export { createClient } from './timeback-client';
7
+ export { TimebackClient } from './timeback-client.class';
8
+ export { createActivity, Activity } from './lib/activity';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAGxD,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Activity Class
3
+ *
4
+ * Client-side activity tracking logic.
5
+ */
6
+ import type { ActivityEndPayload, ActivityMetrics, ActivityParams } from '../../../shared/types';
7
+ /**
8
+ * Activity tracker that tracks time spent on an activity.
9
+ */
10
+ export declare class Activity {
11
+ private readonly params;
12
+ private readonly sendActivity;
13
+ private _startedAt;
14
+ private _isPaused;
15
+ private _pausedAt;
16
+ private _totalPausedMs;
17
+ private _ended;
18
+ /**
19
+ * Create a new activity tracker.
20
+ *
21
+ * The activity is created but not started. Call `.start()` to begin tracking.
22
+ *
23
+ * @param params - Activity parameters
24
+ * @param sendActivity - Function to send activity to server
25
+ */
26
+ constructor(params: ActivityParams, sendActivity: (payload: ActivityEndPayload) => Promise<void>);
27
+ /**
28
+ * Whether the activity has been started.
29
+ *
30
+ * @returns True if started
31
+ */
32
+ get isStarted(): boolean;
33
+ /**
34
+ * When the activity was started.
35
+ *
36
+ * @returns Start date or undefined if not started
37
+ */
38
+ get startedAt(): Date | undefined;
39
+ /**
40
+ * Start tracking the activity.
41
+ *
42
+ * @returns This activity for chaining
43
+ */
44
+ start(): this;
45
+ /**
46
+ * Whether the activity is currently paused.
47
+ *
48
+ * @returns True if paused
49
+ */
50
+ get isPaused(): boolean;
51
+ /**
52
+ * Total elapsed time in milliseconds (excluding paused time).
53
+ *
54
+ * @returns Elapsed milliseconds (0 if not started)
55
+ */
56
+ get elapsedMs(): number;
57
+ /**
58
+ * Pause the activity timer.
59
+ */
60
+ pause(): void;
61
+ /**
62
+ * Resume the activity timer.
63
+ */
64
+ resume(): void;
65
+ /**
66
+ * End the activity and send to server.
67
+ *
68
+ * @param metrics - Activity metrics (required)
69
+ * @throws Error if activity was never started
70
+ */
71
+ end(metrics: ActivityMetrics): Promise<void>;
72
+ }
73
+ //# sourceMappingURL=activity.class.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.class.d.ts","sourceRoot":"","sources":["../../../../src/client/lib/activity/activity.class.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAEhG;;GAEG;AACH,qBAAa,QAAQ;IAgBnB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAhB9B,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,cAAc,CAAI;IAC1B,OAAO,CAAC,MAAM,CAAQ;IAEtB;;;;;;;OAOG;IACH,YACkB,MAAM,EAAE,cAAc,EACtB,YAAY,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,EAC1E;IAEJ;;;;OAIG;IACH,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED;;;;OAIG;IACH,IAAI,SAAS,IAAI,IAAI,GAAG,SAAS,CAEhC;IAED;;;;OAIG;IACH,KAAK,IAAI,IAAI,CAIZ;IAED;;;;OAIG;IACH,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED;;;;OAIG;IACH,IAAI,SAAS,IAAI,MAAM,CAatB;IAED;;OAEG;IACH,KAAK,IAAI,IAAI,CAIZ;IAED;;OAEG;IACH,MAAM,IAAI,IAAI,CAKb;IAED;;;;;OAKG;IACG,GAAG,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BjD;CACD"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Activity Factory
3
+ *
4
+ * Factory function for creating activity trackers.
5
+ */
6
+ import { Activity } from './activity.class';
7
+ import type { ActivityEndPayload, ActivityParams } from '../../../shared/types';
8
+ /**
9
+ * Create an activity tracker.
10
+ *
11
+ * @param params - Activity parameters
12
+ * @param sendActivity - Function to send activity to server
13
+ * @returns Activity handle
14
+ */
15
+ export declare function createActivity(params: ActivityParams, sendActivity: (payload: ActivityEndPayload) => Promise<void>): Activity;
16
+ //# sourceMappingURL=activity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../../../../src/client/lib/activity/activity.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAE3C,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAE/E;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC7B,MAAM,EAAE,cAAc,EACtB,YAAY,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,GAC1D,QAAQ,CAEV"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Activity Module
3
+ */
4
+ export { createActivity } from './activity';
5
+ export { Activity } from './activity.class';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/client/lib/activity/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Client Utilities
3
+ *
4
+ * Internal utility functions for the client SDK.
5
+ */
6
+ /**
7
+ * Check if we're in a browser environment.
8
+ *
9
+ * @returns True if in browser
10
+ */
11
+ export declare function isBrowser(): boolean;
12
+ /**
13
+ * Get the default base URL.
14
+ *
15
+ * Returns undefined during SSR - baseURL is resolved lazily on first API call.
16
+ *
17
+ * @returns The default base URL or undefined during SSR
18
+ */
19
+ export declare function getDefaultBaseURL(): string | undefined;
20
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/client/lib/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAMtD"}