@quiltt/vue 5.1.2
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/LICENSE.md +9 -0
- package/README.md +212 -0
- package/dist/components/index.cjs +707 -0
- package/dist/components/index.d.ts +278 -0
- package/dist/components/index.js +703 -0
- package/dist/composables/index.cjs +617 -0
- package/dist/composables/index.d.ts +191 -0
- package/dist/composables/index.js +609 -0
- package/dist/index.cjs +75 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/plugin/index.cjs +176 -0
- package/dist/plugin/index.d.ts +48 -0
- package/dist/plugin/index.js +171 -0
- package/package.json +81 -0
- package/src/components/QuilttButton.ts +121 -0
- package/src/components/QuilttConnector.ts +215 -0
- package/src/components/QuilttContainer.ts +130 -0
- package/src/components/index.ts +3 -0
- package/src/composables/index.ts +7 -0
- package/src/composables/useQuilttConnector.ts +312 -0
- package/src/composables/useQuilttInstitutions.ts +114 -0
- package/src/composables/useQuilttResolvable.ts +94 -0
- package/src/composables/useQuilttSession.ts +239 -0
- package/src/composables/useQuilttSettings.ts +15 -0
- package/src/composables/useSession.ts +74 -0
- package/src/composables/useStorage.ts +47 -0
- package/src/constants/deprecation-warnings.ts +2 -0
- package/src/index.ts +34 -0
- package/src/plugin/QuilttPlugin.ts +204 -0
- package/src/plugin/index.ts +23 -0
- package/src/plugin/keys.ts +26 -0
- package/src/utils/index.ts +7 -0
- package/src/utils/telemetry.ts +73 -0
- package/src/version.ts +1 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quiltt Vue Plugin implementation
|
|
3
|
+
*
|
|
4
|
+
* Provides session state management via Vue's provide/inject system.
|
|
5
|
+
* Handles token parsing, storage synchronization, and automatic expiration.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { App, Plugin } from 'vue'
|
|
9
|
+
import { ref, watch } from 'vue'
|
|
10
|
+
|
|
11
|
+
import type { Maybe, PrivateClaims, QuilttJWT } from '@quiltt/core'
|
|
12
|
+
import { JsonWebTokenParse } from '@quiltt/core'
|
|
13
|
+
|
|
14
|
+
import type { QuilttPluginOptions } from './keys'
|
|
15
|
+
import { QuilttClientIdKey, QuilttSessionKey, QuilttSetSessionKey } from './keys'
|
|
16
|
+
|
|
17
|
+
// Initialize JWT parser with our specific claims type
|
|
18
|
+
const parse = JsonWebTokenParse<PrivateClaims>
|
|
19
|
+
|
|
20
|
+
// Storage key for session persistence
|
|
21
|
+
const STORAGE_KEY = 'quiltt:session'
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get stored token from localStorage (browser only)
|
|
25
|
+
*/
|
|
26
|
+
const getStoredToken = (): string | null => {
|
|
27
|
+
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
28
|
+
return null
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
return localStorage.getItem(STORAGE_KEY)
|
|
32
|
+
} catch {
|
|
33
|
+
return null
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Store token in localStorage (browser only)
|
|
39
|
+
*/
|
|
40
|
+
const setStoredToken = (token: string | null): void => {
|
|
41
|
+
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
if (token) {
|
|
46
|
+
localStorage.setItem(STORAGE_KEY, token)
|
|
47
|
+
} else {
|
|
48
|
+
localStorage.removeItem(STORAGE_KEY)
|
|
49
|
+
}
|
|
50
|
+
} catch {
|
|
51
|
+
// Storage not available
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Quiltt Vue Plugin
|
|
57
|
+
*
|
|
58
|
+
* Provides session management across your Vue application.
|
|
59
|
+
* Use with `app.use(QuilttPlugin, options)`.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* import { createApp } from 'vue'
|
|
64
|
+
* import { QuilttPlugin } from '@quiltt/vue'
|
|
65
|
+
*
|
|
66
|
+
* const app = createApp(App)
|
|
67
|
+
* app.use(QuilttPlugin, { token: '<SESSION_TOKEN>' })
|
|
68
|
+
* app.mount('#app')
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export const QuilttPlugin: Plugin<[QuilttPluginOptions?]> = {
|
|
72
|
+
install(app: App, options?: QuilttPluginOptions) {
|
|
73
|
+
// Instance-scoped timeout for session expiration
|
|
74
|
+
let sessionTimeout: ReturnType<typeof setTimeout> | undefined
|
|
75
|
+
let isCleanedUp = false
|
|
76
|
+
let stopSessionWatcher: (() => void) | undefined
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Clear the session timeout for this app instance
|
|
80
|
+
*/
|
|
81
|
+
const clearSessionTimeout = () => {
|
|
82
|
+
if (sessionTimeout) {
|
|
83
|
+
clearTimeout(sessionTimeout)
|
|
84
|
+
sessionTimeout = undefined
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Initialize with provided token or stored token
|
|
89
|
+
const initialToken = options?.token ?? getStoredToken()
|
|
90
|
+
const initialSession = parse(initialToken)
|
|
91
|
+
|
|
92
|
+
// Reactive session state
|
|
93
|
+
const session = ref<Maybe<QuilttJWT> | undefined>(initialSession)
|
|
94
|
+
const clientId = ref<string | undefined>(options?.clientId)
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Set session token
|
|
98
|
+
* Parses token, updates storage, and sets expiration timer
|
|
99
|
+
*/
|
|
100
|
+
const setSession = (token: Maybe<string>): void => {
|
|
101
|
+
const parsed = parse(token)
|
|
102
|
+
session.value = parsed
|
|
103
|
+
setStoredToken(token ?? null)
|
|
104
|
+
|
|
105
|
+
// Clear any existing expiration timer
|
|
106
|
+
clearSessionTimeout()
|
|
107
|
+
|
|
108
|
+
// Set new expiration timer if session is valid
|
|
109
|
+
if (parsed) {
|
|
110
|
+
const expirationMS = parsed.claims.exp * 1000
|
|
111
|
+
const timeUntilExpiry = expirationMS - Date.now()
|
|
112
|
+
|
|
113
|
+
if (timeUntilExpiry > 0) {
|
|
114
|
+
sessionTimeout = setTimeout(() => {
|
|
115
|
+
session.value = null
|
|
116
|
+
setStoredToken(null)
|
|
117
|
+
}, timeUntilExpiry)
|
|
118
|
+
} else {
|
|
119
|
+
// Token already expired
|
|
120
|
+
session.value = null
|
|
121
|
+
setStoredToken(null)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Storage event handler for cross-tab synchronization
|
|
127
|
+
let storageHandler: ((event: StorageEvent) => void) | undefined
|
|
128
|
+
|
|
129
|
+
// Listen for storage changes from other tabs/windows
|
|
130
|
+
if (typeof window !== 'undefined') {
|
|
131
|
+
storageHandler = (event: StorageEvent) => {
|
|
132
|
+
if (event.key === STORAGE_KEY) {
|
|
133
|
+
const newSession = parse(event.newValue)
|
|
134
|
+
session.value = newSession
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
window.addEventListener('storage', storageHandler)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Cleanup function for when the app is unmounted
|
|
141
|
+
const cleanup = () => {
|
|
142
|
+
if (isCleanedUp) {
|
|
143
|
+
return
|
|
144
|
+
}
|
|
145
|
+
isCleanedUp = true
|
|
146
|
+
|
|
147
|
+
clearSessionTimeout()
|
|
148
|
+
if (stopSessionWatcher) {
|
|
149
|
+
stopSessionWatcher()
|
|
150
|
+
stopSessionWatcher = undefined
|
|
151
|
+
}
|
|
152
|
+
if (typeof window !== 'undefined' && storageHandler) {
|
|
153
|
+
window.removeEventListener('storage', storageHandler)
|
|
154
|
+
storageHandler = undefined
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Register cleanup on app unmount (Vue 3.5+)
|
|
159
|
+
if (typeof app.onUnmount === 'function') {
|
|
160
|
+
app.onUnmount(cleanup)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Ensure cleanup runs on all supported Vue versions (3.3+)
|
|
164
|
+
if (typeof app.unmount === 'function') {
|
|
165
|
+
const originalUnmount = app.unmount.bind(app)
|
|
166
|
+
app.unmount = (...args: Parameters<typeof originalUnmount>) => {
|
|
167
|
+
cleanup()
|
|
168
|
+
return originalUnmount(...args)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Watch for session changes to update expiration timer
|
|
173
|
+
stopSessionWatcher = watch(
|
|
174
|
+
() => session.value,
|
|
175
|
+
(newSession) => {
|
|
176
|
+
if (!newSession) {
|
|
177
|
+
clearSessionTimeout()
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const expirationMS = newSession.claims.exp * 1000
|
|
182
|
+
const timeUntilExpiry = expirationMS - Date.now()
|
|
183
|
+
|
|
184
|
+
if (timeUntilExpiry <= 0) {
|
|
185
|
+
session.value = null
|
|
186
|
+
setStoredToken(null)
|
|
187
|
+
return
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
clearSessionTimeout()
|
|
191
|
+
sessionTimeout = setTimeout(() => {
|
|
192
|
+
session.value = null
|
|
193
|
+
setStoredToken(null)
|
|
194
|
+
}, timeUntilExpiry)
|
|
195
|
+
},
|
|
196
|
+
{ immediate: true }
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
// Provide session state to all components
|
|
200
|
+
app.provide(QuilttSessionKey, session)
|
|
201
|
+
app.provide(QuilttSetSessionKey, setSession)
|
|
202
|
+
app.provide(QuilttClientIdKey, clientId)
|
|
203
|
+
},
|
|
204
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @quiltt/vue - Vue 3 Plugin
|
|
3
|
+
*
|
|
4
|
+
* Provides Quiltt session management via Vue's provide/inject system.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { createApp } from 'vue'
|
|
9
|
+
* import { QuilttPlugin } from '@quiltt/vue'
|
|
10
|
+
*
|
|
11
|
+
* const app = createApp(App)
|
|
12
|
+
* app.use(QuilttPlugin, { token: '<SESSION_TOKEN>' })
|
|
13
|
+
* app.mount('#app')
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export {
|
|
18
|
+
QuilttClientIdKey,
|
|
19
|
+
type QuilttPluginOptions,
|
|
20
|
+
QuilttSessionKey,
|
|
21
|
+
QuilttSetSessionKey,
|
|
22
|
+
} from './keys'
|
|
23
|
+
export { QuilttPlugin } from './QuilttPlugin'
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Injection keys and types for Quiltt Vue plugin
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { InjectionKey, Ref } from 'vue'
|
|
6
|
+
|
|
7
|
+
import type { Maybe, QuilttJWT } from '@quiltt/core'
|
|
8
|
+
|
|
9
|
+
// Injection keys for Quiltt state
|
|
10
|
+
export const QuilttSessionKey: InjectionKey<Ref<Maybe<QuilttJWT> | undefined>> =
|
|
11
|
+
Symbol.for('quiltt-session')
|
|
12
|
+
export const QuilttSetSessionKey: InjectionKey<(token: Maybe<string>) => void> =
|
|
13
|
+
Symbol.for('quiltt-set-session')
|
|
14
|
+
export const QuilttClientIdKey: InjectionKey<Ref<string | undefined>> =
|
|
15
|
+
Symbol.for('quiltt-client-id')
|
|
16
|
+
|
|
17
|
+
export interface QuilttPluginOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Initial session token
|
|
20
|
+
*/
|
|
21
|
+
token?: string
|
|
22
|
+
/**
|
|
23
|
+
* Quiltt Client ID (Environment ID)
|
|
24
|
+
*/
|
|
25
|
+
clientId?: string
|
|
26
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { version as vueVersion } from 'vue'
|
|
2
|
+
|
|
3
|
+
import { getSDKAgent as coreGetSDKAgent, getBrowserInfo } from '@quiltt/core/utils'
|
|
4
|
+
|
|
5
|
+
// Re-export getBrowserInfo
|
|
6
|
+
export { getBrowserInfo }
|
|
7
|
+
|
|
8
|
+
// Capacitor global type declaration
|
|
9
|
+
declare global {
|
|
10
|
+
interface Window {
|
|
11
|
+
Capacitor?: {
|
|
12
|
+
isNativePlatform?: () => boolean
|
|
13
|
+
getPlatform?: () => string
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Gets the Vue version from the runtime
|
|
20
|
+
*/
|
|
21
|
+
export const getVueVersion = (): string => {
|
|
22
|
+
return vueVersion || 'unknown'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Detects if running in a Capacitor native environment
|
|
27
|
+
*/
|
|
28
|
+
export const getCapacitorInfo = (): string | null => {
|
|
29
|
+
if (typeof window === 'undefined') return null
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
if (window.Capacitor?.isNativePlatform?.()) {
|
|
33
|
+
const platform = window.Capacitor.getPlatform?.() || 'native'
|
|
34
|
+
// Map platform names to correct capitalization
|
|
35
|
+
const platformNames: Record<string, string> = {
|
|
36
|
+
ios: 'iOS',
|
|
37
|
+
android: 'Android',
|
|
38
|
+
web: 'Web',
|
|
39
|
+
}
|
|
40
|
+
const platformName = platformNames[platform.toLowerCase()] || platform
|
|
41
|
+
return `Capacitor/${platformName}`
|
|
42
|
+
}
|
|
43
|
+
} catch {
|
|
44
|
+
// Ignore errors
|
|
45
|
+
}
|
|
46
|
+
return null
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Generates platform information string for Vue web
|
|
51
|
+
* Format: Vue/<version>; <browser>/<version>
|
|
52
|
+
* Or with Capacitor: Vue/<version>; Capacitor/<platform>; <browser>/<version>
|
|
53
|
+
*/
|
|
54
|
+
export const getPlatformInfo = (): string => {
|
|
55
|
+
const versionStr = getVueVersion()
|
|
56
|
+
const capacitorInfo = getCapacitorInfo()
|
|
57
|
+
const browserInfo = getBrowserInfo()
|
|
58
|
+
|
|
59
|
+
if (capacitorInfo) {
|
|
60
|
+
return `Vue/${versionStr}; ${capacitorInfo}; ${browserInfo}`
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return `Vue/${versionStr}; ${browserInfo}`
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Generates User-Agent string for Vue SDK
|
|
68
|
+
* Format: Quiltt/<sdk-version> (Vue/<vue-version>; <browser>/<version>)
|
|
69
|
+
*/
|
|
70
|
+
export const getSDKAgent = (sdkVersion: string): string => {
|
|
71
|
+
const platformInfo = getPlatformInfo()
|
|
72
|
+
return coreGetSDKAgent(sdkVersion, platformInfo)
|
|
73
|
+
}
|
package/src/version.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { version } from '../package.json'
|