@qikdev/sdk 0.1.201 → 0.1.203

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.
@@ -0,0 +1,306 @@
1
+ /**
2
+ * Storage abstraction layer for handling both localStorage and httpOnly cookie storage
3
+ * @module QikStorage
4
+ */
5
+
6
+ /**
7
+ * Base storage interface
8
+ */
9
+ class StorageAdapter {
10
+ constructor() {
11
+ if (this.constructor === StorageAdapter) {
12
+ throw new Error("StorageAdapter is an abstract class and cannot be instantiated directly");
13
+ }
14
+ }
15
+
16
+ /**
17
+ * Get user session data
18
+ * @returns {Object|null} User session object
19
+ */
20
+ getUser() {
21
+ throw new Error("getUser method must be implemented");
22
+ }
23
+
24
+ /**
25
+ * Set user session data
26
+ * @param {Object} user User session object
27
+ */
28
+ setUser(user) {
29
+ throw new Error("setUser method must be implemented");
30
+ }
31
+
32
+ /**
33
+ * Clear user session data
34
+ */
35
+ clearUser() {
36
+ throw new Error("clearUser method must be implemented");
37
+ }
38
+
39
+ /**
40
+ * Get current access token
41
+ * @returns {String|null} Access token
42
+ */
43
+ getAccessToken() {
44
+ throw new Error("getAccessToken method must be implemented");
45
+ }
46
+
47
+ /**
48
+ * Get current refresh token
49
+ * @returns {String|null} Refresh token
50
+ */
51
+ getRefreshToken() {
52
+ throw new Error("getRefreshToken method must be implemented");
53
+ }
54
+
55
+ /**
56
+ * Get token expiry date
57
+ * @returns {String|null} Token expiry date
58
+ */
59
+ getTokenExpiry() {
60
+ throw new Error("getTokenExpiry method must be implemented");
61
+ }
62
+
63
+ /**
64
+ * Check if storage is available
65
+ * @returns {Boolean} Whether storage is available
66
+ */
67
+ isAvailable() {
68
+ throw new Error("isAvailable method must be implemented");
69
+ }
70
+ }
71
+
72
+ /**
73
+ * localStorage-based storage adapter (current behavior)
74
+ */
75
+ class LocalStorageAdapter extends StorageAdapter {
76
+ constructor() {
77
+ super();
78
+ this.storage = {};
79
+ }
80
+
81
+ getUser() {
82
+ return this.storage.user || null;
83
+ }
84
+
85
+ setUser(user) {
86
+ this.storage.user = user;
87
+ }
88
+
89
+ clearUser() {
90
+ delete this.storage.user;
91
+ }
92
+
93
+ getAccessToken() {
94
+ const user = this.getUser();
95
+ return user?.token?.accessToken || null;
96
+ }
97
+
98
+ getRefreshToken() {
99
+ const user = this.getUser();
100
+ return user?.token?.refreshToken || null;
101
+ }
102
+
103
+ getTokenExpiry() {
104
+ const user = this.getUser();
105
+ return user?.token?.expires || null;
106
+ }
107
+
108
+ isAvailable() {
109
+ return true; // Always available as it uses in-memory storage
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Cookie-based storage adapter for httpOnly cookies
115
+ */
116
+ class CookieStorageAdapter extends StorageAdapter {
117
+ constructor(options = {}) {
118
+ super();
119
+ this.options = {
120
+ domain: options.domain || this._detectDomain(),
121
+ secure: options.secure !== false, // Default to true
122
+ sameSite: options.sameSite || 'lax',
123
+ ...options
124
+ };
125
+ this.sessionStorage = {}; // In-memory storage for session data
126
+ }
127
+
128
+ /**
129
+ * Auto-detect appropriate cookie domain
130
+ * @private
131
+ */
132
+ _detectDomain() {
133
+ if (typeof window === 'undefined') return null;
134
+
135
+ const hostname = window.location.hostname;
136
+
137
+ // For localhost, don't set domain
138
+ if (hostname === 'localhost' || hostname === '127.0.0.1') {
139
+ return null;
140
+ }
141
+
142
+ // For IP addresses, don't set domain
143
+ if (/^\d+\.\d+\.\d+\.\d+$/.test(hostname)) {
144
+ return null;
145
+ }
146
+
147
+ // For subdomains, use parent domain (e.g., .example.com)
148
+ const parts = hostname.split('.');
149
+ if (parts.length > 2) {
150
+ return '.' + parts.slice(-2).join('.');
151
+ }
152
+
153
+ return null; // Let browser handle single domain
154
+ }
155
+
156
+ /**
157
+ * Read a cookie value
158
+ * @private
159
+ */
160
+ _getCookie(name) {
161
+ if (typeof document === 'undefined') return null;
162
+
163
+ const value = `; ${document.cookie}`;
164
+ const parts = value.split(`; ${name}=`);
165
+ if (parts.length === 2) {
166
+ return parts.pop().split(';').shift();
167
+ }
168
+ return null;
169
+ }
170
+
171
+ /**
172
+ * Set a cookie value (for non-httpOnly cookies only)
173
+ * @private
174
+ */
175
+ _setCookie(name, value, options = {}) {
176
+ if (typeof document === 'undefined') return;
177
+
178
+ const opts = { ...this.options, ...options };
179
+ let cookieString = `${name}=${value}`;
180
+
181
+ if (opts.domain) {
182
+ cookieString += `; Domain=${opts.domain}`;
183
+ }
184
+
185
+ if (opts.secure) {
186
+ cookieString += '; Secure';
187
+ }
188
+
189
+ if (opts.sameSite) {
190
+ cookieString += `; SameSite=${opts.sameSite}`;
191
+ }
192
+
193
+ if (opts.maxAge) {
194
+ cookieString += `; Max-Age=${opts.maxAge}`;
195
+ }
196
+
197
+ document.cookie = cookieString;
198
+ }
199
+
200
+ /**
201
+ * Delete a cookie
202
+ * @private
203
+ */
204
+ _deleteCookie(name) {
205
+ this._setCookie(name, '', { maxAge: 0 });
206
+ }
207
+
208
+ getUser() {
209
+ return this.sessionStorage.user || null;
210
+ }
211
+
212
+ setUser(user) {
213
+ if (user) {
214
+ // Store session data in memory (accessible to JavaScript)
215
+ const { token, ...sessionData } = user;
216
+ this.sessionStorage.user = sessionData;
217
+
218
+ // Tokens are handled by httpOnly cookies set by the server
219
+ // We don't store them in JavaScript for security
220
+ } else {
221
+ this.sessionStorage.user = null;
222
+ }
223
+ }
224
+
225
+ clearUser() {
226
+ delete this.sessionStorage.user;
227
+ // Note: httpOnly cookies will be cleared by server response
228
+ // But we can clear any non-httpOnly cookies we might have set
229
+ this._deleteCookie('qik_session_id');
230
+ }
231
+
232
+ getAccessToken() {
233
+ // In cookie mode, we can't access httpOnly cookies from JavaScript
234
+ // The browser will automatically include them in requests
235
+ // Return null to indicate tokens are handled by cookies
236
+ return null;
237
+ }
238
+
239
+ getRefreshToken() {
240
+ // Same as access token - handled by httpOnly cookies
241
+ return null;
242
+ }
243
+
244
+ getTokenExpiry() {
245
+ // We can't read httpOnly cookie expiry from JavaScript
246
+ // The server will handle token expiry validation
247
+ return null;
248
+ }
249
+
250
+ isAvailable() {
251
+ // Check if we're in a browser environment and cookies are enabled
252
+ if (typeof document === 'undefined') return false;
253
+
254
+ try {
255
+ // Test if we can set/read cookies
256
+ const testCookie = 'qik_test_cookie';
257
+ this._setCookie(testCookie, 'test');
258
+ const canRead = this._getCookie(testCookie) === 'test';
259
+ this._deleteCookie(testCookie);
260
+ return canRead;
261
+ } catch (e) {
262
+ return false;
263
+ }
264
+ }
265
+
266
+ /**
267
+ * Check if we're in cookie mode
268
+ * @returns {Boolean}
269
+ */
270
+ isCookieMode() {
271
+ return true;
272
+ }
273
+
274
+ /**
275
+ * Get cookie configuration options
276
+ * @returns {Object}
277
+ */
278
+ getCookieOptions() {
279
+ return { ...this.options };
280
+ }
281
+ }
282
+
283
+ /**
284
+ * Factory function to create appropriate storage adapter
285
+ * @param {Object} options Configuration options
286
+ * @param {Boolean} options.useHttpOnlyCookies Whether to use cookie storage
287
+ * @param {Object} options.cookieConfig Cookie configuration options
288
+ * @returns {StorageAdapter} Storage adapter instance
289
+ */
290
+ export function createStorageAdapter(options = {}) {
291
+ if (options.useHttpOnlyCookies) {
292
+ const cookieAdapter = new CookieStorageAdapter(options.cookieConfig);
293
+
294
+ // Fallback to localStorage if cookies aren't available
295
+ if (!cookieAdapter.isAvailable()) {
296
+ console.warn('Qik SDK: Cookies not available, falling back to localStorage mode');
297
+ return new LocalStorageAdapter();
298
+ }
299
+
300
+ return cookieAdapter;
301
+ }
302
+
303
+ return new LocalStorageAdapter();
304
+ }
305
+
306
+ export { StorageAdapter, LocalStorageAdapter, CookieStorageAdapter };
@@ -1464,8 +1464,11 @@ service.machineName = function (string) {
1464
1464
  }
1465
1465
 
1466
1466
  var regexp = /[^a-zA-Z0-9-_]+/g;
1467
- var cleaned = String(string).replace(regexp, " ").trim();
1468
- return _camelCase(cleaned);
1467
+ return String(string)
1468
+ .replace(regexp, " ")
1469
+ .split("_")
1470
+ .map((part) => _camelCase(part))
1471
+ .join("_");
1469
1472
  };
1470
1473
 
1471
1474
  /////////////////////////////////////////////
package/src/version.js CHANGED
@@ -1 +1 @@
1
- export const version = "0.1.201";
1
+ export const version = "0.1.203";