@oxyhq/core 1.0.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 (277) hide show
  1. package/README.md +50 -0
  2. package/dist/cjs/AuthManager.js +361 -0
  3. package/dist/cjs/CrossDomainAuth.js +258 -0
  4. package/dist/cjs/HttpService.js +618 -0
  5. package/dist/cjs/OxyServices.base.js +263 -0
  6. package/dist/cjs/OxyServices.errors.js +22 -0
  7. package/dist/cjs/OxyServices.js +63 -0
  8. package/dist/cjs/constants/version.js +16 -0
  9. package/dist/cjs/crypto/index.js +20 -0
  10. package/dist/cjs/crypto/keyManager.js +887 -0
  11. package/dist/cjs/crypto/polyfill.js +64 -0
  12. package/dist/cjs/crypto/recoveryPhrase.js +169 -0
  13. package/dist/cjs/crypto/signatureService.js +296 -0
  14. package/dist/cjs/i18n/index.js +73 -0
  15. package/dist/cjs/i18n/locales/ar-SA.json +120 -0
  16. package/dist/cjs/i18n/locales/ca-ES.json +120 -0
  17. package/dist/cjs/i18n/locales/de-DE.json +120 -0
  18. package/dist/cjs/i18n/locales/en-US.json +956 -0
  19. package/dist/cjs/i18n/locales/es-ES.json +944 -0
  20. package/dist/cjs/i18n/locales/fr-FR.json +120 -0
  21. package/dist/cjs/i18n/locales/it-IT.json +120 -0
  22. package/dist/cjs/i18n/locales/ja-JP.json +119 -0
  23. package/dist/cjs/i18n/locales/ko-KR.json +120 -0
  24. package/dist/cjs/i18n/locales/locales/ar-SA.json +120 -0
  25. package/dist/cjs/i18n/locales/locales/ca-ES.json +120 -0
  26. package/dist/cjs/i18n/locales/locales/de-DE.json +120 -0
  27. package/dist/cjs/i18n/locales/locales/en-US.json +956 -0
  28. package/dist/cjs/i18n/locales/locales/es-ES.json +944 -0
  29. package/dist/cjs/i18n/locales/locales/fr-FR.json +120 -0
  30. package/dist/cjs/i18n/locales/locales/it-IT.json +120 -0
  31. package/dist/cjs/i18n/locales/locales/ja-JP.json +119 -0
  32. package/dist/cjs/i18n/locales/locales/ko-KR.json +120 -0
  33. package/dist/cjs/i18n/locales/locales/pt-PT.json +120 -0
  34. package/dist/cjs/i18n/locales/locales/zh-CN.json +120 -0
  35. package/dist/cjs/i18n/locales/pt-PT.json +120 -0
  36. package/dist/cjs/i18n/locales/zh-CN.json +120 -0
  37. package/dist/cjs/index.js +153 -0
  38. package/dist/cjs/mixins/OxyServices.analytics.js +49 -0
  39. package/dist/cjs/mixins/OxyServices.assets.js +380 -0
  40. package/dist/cjs/mixins/OxyServices.auth.js +259 -0
  41. package/dist/cjs/mixins/OxyServices.developer.js +97 -0
  42. package/dist/cjs/mixins/OxyServices.devices.js +116 -0
  43. package/dist/cjs/mixins/OxyServices.features.js +309 -0
  44. package/dist/cjs/mixins/OxyServices.fedcm.js +435 -0
  45. package/dist/cjs/mixins/OxyServices.karma.js +108 -0
  46. package/dist/cjs/mixins/OxyServices.language.js +154 -0
  47. package/dist/cjs/mixins/OxyServices.location.js +43 -0
  48. package/dist/cjs/mixins/OxyServices.payment.js +158 -0
  49. package/dist/cjs/mixins/OxyServices.popup.js +371 -0
  50. package/dist/cjs/mixins/OxyServices.privacy.js +162 -0
  51. package/dist/cjs/mixins/OxyServices.redirect.js +345 -0
  52. package/dist/cjs/mixins/OxyServices.security.js +81 -0
  53. package/dist/cjs/mixins/OxyServices.user.js +355 -0
  54. package/dist/cjs/mixins/OxyServices.utility.js +156 -0
  55. package/dist/cjs/mixins/index.js +79 -0
  56. package/dist/cjs/mixins/mixinHelpers.js +53 -0
  57. package/dist/cjs/models/interfaces.js +20 -0
  58. package/dist/cjs/models/session.js +2 -0
  59. package/dist/cjs/shared/index.js +70 -0
  60. package/dist/cjs/shared/utils/colorUtils.js +153 -0
  61. package/dist/cjs/shared/utils/debugUtils.js +73 -0
  62. package/dist/cjs/shared/utils/errorUtils.js +183 -0
  63. package/dist/cjs/shared/utils/index.js +49 -0
  64. package/dist/cjs/shared/utils/networkUtils.js +183 -0
  65. package/dist/cjs/shared/utils/themeUtils.js +106 -0
  66. package/dist/cjs/utils/apiUtils.js +61 -0
  67. package/dist/cjs/utils/asyncUtils.js +194 -0
  68. package/dist/cjs/utils/cache.js +226 -0
  69. package/dist/cjs/utils/deviceManager.js +205 -0
  70. package/dist/cjs/utils/errorUtils.js +154 -0
  71. package/dist/cjs/utils/index.js +26 -0
  72. package/dist/cjs/utils/languageUtils.js +165 -0
  73. package/dist/cjs/utils/loggerUtils.js +126 -0
  74. package/dist/cjs/utils/platform.js +144 -0
  75. package/dist/cjs/utils/requestUtils.js +209 -0
  76. package/dist/cjs/utils/sessionUtils.js +181 -0
  77. package/dist/cjs/utils/validationUtils.js +173 -0
  78. package/dist/esm/AuthManager.js +356 -0
  79. package/dist/esm/CrossDomainAuth.js +253 -0
  80. package/dist/esm/HttpService.js +614 -0
  81. package/dist/esm/OxyServices.base.js +259 -0
  82. package/dist/esm/OxyServices.errors.js +17 -0
  83. package/dist/esm/OxyServices.js +59 -0
  84. package/dist/esm/constants/version.js +13 -0
  85. package/dist/esm/crypto/index.js +13 -0
  86. package/dist/esm/crypto/keyManager.js +850 -0
  87. package/dist/esm/crypto/polyfill.js +61 -0
  88. package/dist/esm/crypto/recoveryPhrase.js +132 -0
  89. package/dist/esm/crypto/signatureService.js +259 -0
  90. package/dist/esm/i18n/index.js +69 -0
  91. package/dist/esm/i18n/locales/ar-SA.json +120 -0
  92. package/dist/esm/i18n/locales/ca-ES.json +120 -0
  93. package/dist/esm/i18n/locales/de-DE.json +120 -0
  94. package/dist/esm/i18n/locales/en-US.json +956 -0
  95. package/dist/esm/i18n/locales/es-ES.json +944 -0
  96. package/dist/esm/i18n/locales/fr-FR.json +120 -0
  97. package/dist/esm/i18n/locales/it-IT.json +120 -0
  98. package/dist/esm/i18n/locales/ja-JP.json +119 -0
  99. package/dist/esm/i18n/locales/ko-KR.json +120 -0
  100. package/dist/esm/i18n/locales/locales/ar-SA.json +120 -0
  101. package/dist/esm/i18n/locales/locales/ca-ES.json +120 -0
  102. package/dist/esm/i18n/locales/locales/de-DE.json +120 -0
  103. package/dist/esm/i18n/locales/locales/en-US.json +956 -0
  104. package/dist/esm/i18n/locales/locales/es-ES.json +944 -0
  105. package/dist/esm/i18n/locales/locales/fr-FR.json +120 -0
  106. package/dist/esm/i18n/locales/locales/it-IT.json +120 -0
  107. package/dist/esm/i18n/locales/locales/ja-JP.json +119 -0
  108. package/dist/esm/i18n/locales/locales/ko-KR.json +120 -0
  109. package/dist/esm/i18n/locales/locales/pt-PT.json +120 -0
  110. package/dist/esm/i18n/locales/locales/zh-CN.json +120 -0
  111. package/dist/esm/i18n/locales/pt-PT.json +120 -0
  112. package/dist/esm/i18n/locales/zh-CN.json +120 -0
  113. package/dist/esm/index.js +55 -0
  114. package/dist/esm/mixins/OxyServices.analytics.js +46 -0
  115. package/dist/esm/mixins/OxyServices.assets.js +377 -0
  116. package/dist/esm/mixins/OxyServices.auth.js +256 -0
  117. package/dist/esm/mixins/OxyServices.developer.js +94 -0
  118. package/dist/esm/mixins/OxyServices.devices.js +113 -0
  119. package/dist/esm/mixins/OxyServices.features.js +306 -0
  120. package/dist/esm/mixins/OxyServices.fedcm.js +433 -0
  121. package/dist/esm/mixins/OxyServices.karma.js +105 -0
  122. package/dist/esm/mixins/OxyServices.language.js +118 -0
  123. package/dist/esm/mixins/OxyServices.location.js +40 -0
  124. package/dist/esm/mixins/OxyServices.payment.js +155 -0
  125. package/dist/esm/mixins/OxyServices.popup.js +369 -0
  126. package/dist/esm/mixins/OxyServices.privacy.js +159 -0
  127. package/dist/esm/mixins/OxyServices.redirect.js +343 -0
  128. package/dist/esm/mixins/OxyServices.security.js +78 -0
  129. package/dist/esm/mixins/OxyServices.user.js +352 -0
  130. package/dist/esm/mixins/OxyServices.utility.js +153 -0
  131. package/dist/esm/mixins/index.js +76 -0
  132. package/dist/esm/mixins/mixinHelpers.js +48 -0
  133. package/dist/esm/models/interfaces.js +17 -0
  134. package/dist/esm/models/session.js +1 -0
  135. package/dist/esm/shared/index.js +31 -0
  136. package/dist/esm/shared/utils/colorUtils.js +143 -0
  137. package/dist/esm/shared/utils/debugUtils.js +65 -0
  138. package/dist/esm/shared/utils/errorUtils.js +170 -0
  139. package/dist/esm/shared/utils/index.js +15 -0
  140. package/dist/esm/shared/utils/networkUtils.js +173 -0
  141. package/dist/esm/shared/utils/themeUtils.js +98 -0
  142. package/dist/esm/utils/apiUtils.js +55 -0
  143. package/dist/esm/utils/asyncUtils.js +179 -0
  144. package/dist/esm/utils/cache.js +218 -0
  145. package/dist/esm/utils/deviceManager.js +168 -0
  146. package/dist/esm/utils/errorUtils.js +146 -0
  147. package/dist/esm/utils/index.js +7 -0
  148. package/dist/esm/utils/languageUtils.js +158 -0
  149. package/dist/esm/utils/loggerUtils.js +115 -0
  150. package/dist/esm/utils/platform.js +102 -0
  151. package/dist/esm/utils/requestUtils.js +203 -0
  152. package/dist/esm/utils/sessionUtils.js +171 -0
  153. package/dist/esm/utils/validationUtils.js +153 -0
  154. package/dist/types/AuthManager.d.ts +143 -0
  155. package/dist/types/CrossDomainAuth.d.ts +160 -0
  156. package/dist/types/HttpService.d.ts +163 -0
  157. package/dist/types/OxyServices.base.d.ts +126 -0
  158. package/dist/types/OxyServices.d.ts +81 -0
  159. package/dist/types/OxyServices.errors.d.ts +11 -0
  160. package/dist/types/constants/version.d.ts +13 -0
  161. package/dist/types/crypto/index.d.ts +11 -0
  162. package/dist/types/crypto/keyManager.d.ts +189 -0
  163. package/dist/types/crypto/polyfill.d.ts +11 -0
  164. package/dist/types/crypto/recoveryPhrase.d.ts +58 -0
  165. package/dist/types/crypto/signatureService.d.ts +86 -0
  166. package/dist/types/i18n/index.d.ts +3 -0
  167. package/dist/types/index.d.ts +50 -0
  168. package/dist/types/mixins/OxyServices.analytics.d.ts +66 -0
  169. package/dist/types/mixins/OxyServices.assets.d.ts +135 -0
  170. package/dist/types/mixins/OxyServices.auth.d.ts +186 -0
  171. package/dist/types/mixins/OxyServices.developer.d.ts +99 -0
  172. package/dist/types/mixins/OxyServices.devices.d.ts +96 -0
  173. package/dist/types/mixins/OxyServices.features.d.ts +228 -0
  174. package/dist/types/mixins/OxyServices.fedcm.d.ts +200 -0
  175. package/dist/types/mixins/OxyServices.karma.d.ts +85 -0
  176. package/dist/types/mixins/OxyServices.language.d.ts +81 -0
  177. package/dist/types/mixins/OxyServices.location.d.ts +64 -0
  178. package/dist/types/mixins/OxyServices.payment.d.ts +111 -0
  179. package/dist/types/mixins/OxyServices.popup.d.ts +205 -0
  180. package/dist/types/mixins/OxyServices.privacy.d.ts +122 -0
  181. package/dist/types/mixins/OxyServices.redirect.d.ts +245 -0
  182. package/dist/types/mixins/OxyServices.security.d.ts +78 -0
  183. package/dist/types/mixins/OxyServices.user.d.ts +182 -0
  184. package/dist/types/mixins/OxyServices.utility.d.ts +93 -0
  185. package/dist/types/mixins/index.d.ts +30 -0
  186. package/dist/types/mixins/mixinHelpers.d.ts +31 -0
  187. package/dist/types/models/interfaces.d.ts +415 -0
  188. package/dist/types/models/session.d.ts +27 -0
  189. package/dist/types/shared/index.d.ts +28 -0
  190. package/dist/types/shared/utils/colorUtils.d.ts +104 -0
  191. package/dist/types/shared/utils/debugUtils.d.ts +48 -0
  192. package/dist/types/shared/utils/errorUtils.d.ts +97 -0
  193. package/dist/types/shared/utils/index.d.ts +13 -0
  194. package/dist/types/shared/utils/networkUtils.d.ts +139 -0
  195. package/dist/types/shared/utils/themeUtils.d.ts +90 -0
  196. package/dist/types/utils/apiUtils.d.ts +53 -0
  197. package/dist/types/utils/asyncUtils.d.ts +58 -0
  198. package/dist/types/utils/cache.d.ts +127 -0
  199. package/dist/types/utils/deviceManager.d.ts +65 -0
  200. package/dist/types/utils/errorUtils.d.ts +46 -0
  201. package/dist/types/utils/index.d.ts +6 -0
  202. package/dist/types/utils/languageUtils.d.ts +37 -0
  203. package/dist/types/utils/loggerUtils.d.ts +48 -0
  204. package/dist/types/utils/platform.d.ts +40 -0
  205. package/dist/types/utils/requestUtils.d.ts +123 -0
  206. package/dist/types/utils/sessionUtils.d.ts +54 -0
  207. package/dist/types/utils/validationUtils.d.ts +85 -0
  208. package/package.json +84 -0
  209. package/src/AuthManager.ts +436 -0
  210. package/src/CrossDomainAuth.ts +307 -0
  211. package/src/HttpService.ts +752 -0
  212. package/src/OxyServices.base.ts +334 -0
  213. package/src/OxyServices.errors.ts +26 -0
  214. package/src/OxyServices.ts +129 -0
  215. package/src/constants/version.ts +15 -0
  216. package/src/crypto/index.ts +25 -0
  217. package/src/crypto/keyManager.ts +962 -0
  218. package/src/crypto/polyfill.ts +70 -0
  219. package/src/crypto/recoveryPhrase.ts +166 -0
  220. package/src/crypto/signatureService.ts +323 -0
  221. package/src/i18n/index.ts +75 -0
  222. package/src/i18n/locales/ar-SA.json +120 -0
  223. package/src/i18n/locales/ca-ES.json +120 -0
  224. package/src/i18n/locales/de-DE.json +120 -0
  225. package/src/i18n/locales/en-US.json +956 -0
  226. package/src/i18n/locales/es-ES.json +944 -0
  227. package/src/i18n/locales/fr-FR.json +120 -0
  228. package/src/i18n/locales/it-IT.json +120 -0
  229. package/src/i18n/locales/ja-JP.json +119 -0
  230. package/src/i18n/locales/ko-KR.json +120 -0
  231. package/src/i18n/locales/pt-PT.json +120 -0
  232. package/src/i18n/locales/zh-CN.json +120 -0
  233. package/src/index.ts +153 -0
  234. package/src/mixins/OxyServices.analytics.ts +53 -0
  235. package/src/mixins/OxyServices.assets.ts +412 -0
  236. package/src/mixins/OxyServices.auth.ts +358 -0
  237. package/src/mixins/OxyServices.developer.ts +114 -0
  238. package/src/mixins/OxyServices.devices.ts +119 -0
  239. package/src/mixins/OxyServices.features.ts +428 -0
  240. package/src/mixins/OxyServices.fedcm.ts +494 -0
  241. package/src/mixins/OxyServices.karma.ts +111 -0
  242. package/src/mixins/OxyServices.language.ts +127 -0
  243. package/src/mixins/OxyServices.location.ts +46 -0
  244. package/src/mixins/OxyServices.payment.ts +163 -0
  245. package/src/mixins/OxyServices.popup.ts +443 -0
  246. package/src/mixins/OxyServices.privacy.ts +182 -0
  247. package/src/mixins/OxyServices.redirect.ts +397 -0
  248. package/src/mixins/OxyServices.security.ts +103 -0
  249. package/src/mixins/OxyServices.user.ts +392 -0
  250. package/src/mixins/OxyServices.utility.ts +191 -0
  251. package/src/mixins/index.ts +91 -0
  252. package/src/mixins/mixinHelpers.ts +69 -0
  253. package/src/models/interfaces.ts +511 -0
  254. package/src/models/session.ts +30 -0
  255. package/src/shared/index.ts +82 -0
  256. package/src/shared/utils/colorUtils.ts +155 -0
  257. package/src/shared/utils/debugUtils.ts +73 -0
  258. package/src/shared/utils/errorUtils.ts +181 -0
  259. package/src/shared/utils/index.ts +59 -0
  260. package/src/shared/utils/networkUtils.ts +248 -0
  261. package/src/shared/utils/themeUtils.ts +115 -0
  262. package/src/types/bip39.d.ts +32 -0
  263. package/src/types/buffer.d.ts +97 -0
  264. package/src/types/color.d.ts +20 -0
  265. package/src/types/elliptic.d.ts +62 -0
  266. package/src/utils/apiUtils.ts +88 -0
  267. package/src/utils/asyncUtils.ts +252 -0
  268. package/src/utils/cache.ts +264 -0
  269. package/src/utils/deviceManager.ts +198 -0
  270. package/src/utils/errorUtils.ts +216 -0
  271. package/src/utils/index.ts +21 -0
  272. package/src/utils/languageUtils.ts +174 -0
  273. package/src/utils/loggerUtils.ts +153 -0
  274. package/src/utils/platform.ts +117 -0
  275. package/src/utils/requestUtils.ts +237 -0
  276. package/src/utils/sessionUtils.ts +206 -0
  277. package/src/utils/validationUtils.ts +174 -0
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Request utilities for HTTP clients
3
+ *
4
+ * Provides reusable components for request deduplication, queuing, and logging
5
+ */
6
+ /**
7
+ * Request deduplication - prevents duplicate concurrent requests
8
+ *
9
+ * When multiple requests with the same key are made simultaneously,
10
+ * only one request is executed and all callers receive the same result.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const deduplicator = new RequestDeduplicator();
15
+ *
16
+ * // Multiple calls with same key will share the same promise
17
+ * const promise1 = deduplicator.deduplicate('user-123', () => fetchUser('123'));
18
+ * const promise2 = deduplicator.deduplicate('user-123', () => fetchUser('123'));
19
+ * // promise1 === promise2, only one API call is made
20
+ * ```
21
+ */
22
+ export class RequestDeduplicator {
23
+ constructor() {
24
+ this.pendingRequests = new Map();
25
+ }
26
+ /**
27
+ * Deduplicate a request by key
28
+ * @param key Unique key for the request
29
+ * @param requestFn Function that returns a promise
30
+ * @returns Promise that will be shared if key already exists
31
+ */
32
+ async deduplicate(key, requestFn) {
33
+ const existing = this.pendingRequests.get(key);
34
+ if (existing) {
35
+ return existing;
36
+ }
37
+ const promise = requestFn()
38
+ .finally(() => {
39
+ this.pendingRequests.delete(key);
40
+ });
41
+ this.pendingRequests.set(key, promise);
42
+ return promise;
43
+ }
44
+ /**
45
+ * Clear all pending requests
46
+ */
47
+ clear() {
48
+ this.pendingRequests.clear();
49
+ }
50
+ /**
51
+ * Get number of pending requests
52
+ */
53
+ size() {
54
+ return this.pendingRequests.size;
55
+ }
56
+ }
57
+ /**
58
+ * Request queue with concurrency control
59
+ *
60
+ * Limits the number of concurrent requests and queues excess requests.
61
+ * Useful for rate limiting and preventing request flooding.
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * const queue = new RequestQueue(5, 100); // Max 5 concurrent, queue up to 100
66
+ *
67
+ * // All requests will be queued and processed with max 5 concurrent
68
+ * await queue.enqueue(() => fetchUser('1'));
69
+ * await queue.enqueue(() => fetchUser('2'));
70
+ * // ...
71
+ * ```
72
+ */
73
+ export class RequestQueue {
74
+ /**
75
+ * Create a new request queue
76
+ * @param maxConcurrent Maximum number of concurrent requests (default: 10)
77
+ * @param maxQueueSize Maximum queue size (default: 100)
78
+ */
79
+ constructor(maxConcurrent = 10, maxQueueSize = 100) {
80
+ this.queue = [];
81
+ this.running = 0;
82
+ this.maxConcurrent = maxConcurrent;
83
+ this.maxQueueSize = maxQueueSize;
84
+ }
85
+ /**
86
+ * Enqueue a request
87
+ * @param requestFn Function that returns a promise
88
+ * @returns Promise that resolves when request completes
89
+ */
90
+ async enqueue(requestFn) {
91
+ if (this.queue.length >= this.maxQueueSize) {
92
+ throw new Error('Request queue is full');
93
+ }
94
+ return new Promise((resolve, reject) => {
95
+ this.queue.push(async () => {
96
+ try {
97
+ const result = await requestFn();
98
+ resolve(result);
99
+ }
100
+ catch (error) {
101
+ reject(error);
102
+ }
103
+ });
104
+ this.process();
105
+ });
106
+ }
107
+ /**
108
+ * Process queued requests
109
+ */
110
+ async process() {
111
+ if (this.running >= this.maxConcurrent || this.queue.length === 0) {
112
+ return;
113
+ }
114
+ this.running++;
115
+ const requestFn = this.queue.shift();
116
+ if (requestFn) {
117
+ try {
118
+ await requestFn();
119
+ }
120
+ finally {
121
+ this.running--;
122
+ this.process();
123
+ }
124
+ }
125
+ else {
126
+ this.running--;
127
+ }
128
+ }
129
+ /**
130
+ * Clear all queued requests
131
+ */
132
+ clear() {
133
+ this.queue = [];
134
+ }
135
+ /**
136
+ * Get queue size
137
+ */
138
+ size() {
139
+ return this.queue.length;
140
+ }
141
+ /**
142
+ * Get number of currently running requests
143
+ */
144
+ runningCount() {
145
+ return this.running;
146
+ }
147
+ }
148
+ /**
149
+ * Simple logger with level support
150
+ *
151
+ * Lightweight logger for HTTP clients and utilities.
152
+ * For more advanced logging, use loggerUtils.ts
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * const logger = new SimpleLogger(true, 'debug');
157
+ * logger.debug('Debug message');
158
+ * logger.info('Info message');
159
+ * logger.error('Error message');
160
+ * ```
161
+ */
162
+ export class SimpleLogger {
163
+ /**
164
+ * Create a new simple logger
165
+ * @param enabled Whether logging is enabled
166
+ * @param level Minimum log level
167
+ * @param prefix Prefix for log messages (default: '')
168
+ */
169
+ constructor(enabled = false, level = 'error', prefix = '') {
170
+ this.enabled = enabled;
171
+ this.level = level;
172
+ this.prefix = prefix;
173
+ }
174
+ shouldLog(level) {
175
+ if (!this.enabled || this.level === 'none')
176
+ return false;
177
+ const levels = ['none', 'error', 'warn', 'info', 'debug'];
178
+ return levels.indexOf(level) <= levels.indexOf(this.level);
179
+ }
180
+ formatMessage(...args) {
181
+ return this.prefix ? [`[${this.prefix}]`, ...args] : args;
182
+ }
183
+ error(...args) {
184
+ if (this.shouldLog('error')) {
185
+ console.error(...this.formatMessage(...args));
186
+ }
187
+ }
188
+ warn(...args) {
189
+ if (this.shouldLog('warn')) {
190
+ console.warn(...this.formatMessage(...args));
191
+ }
192
+ }
193
+ info(...args) {
194
+ if (this.shouldLog('info')) {
195
+ console.info(...this.formatMessage(...args));
196
+ }
197
+ }
198
+ debug(...args) {
199
+ if (this.shouldLog('debug')) {
200
+ console.log(...this.formatMessage(...args));
201
+ }
202
+ }
203
+ }
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Session management utilities
3
+ *
4
+ * Provides consistent session normalization, deduplication, and sorting
5
+ * to ensure sessions are always displayed in a predictable order.
6
+ */
7
+ /**
8
+ * Normalize a session to ensure all required fields are present
9
+ */
10
+ export function normalizeSession(session) {
11
+ const now = new Date().toISOString();
12
+ return {
13
+ sessionId: session.sessionId,
14
+ deviceId: session.deviceId || '',
15
+ expiresAt: session.expiresAt || now,
16
+ lastActive: session.lastActive || now,
17
+ userId: session.userId || '',
18
+ };
19
+ }
20
+ /**
21
+ * Compare two sessions for equality
22
+ */
23
+ export function sessionsEqual(a, b) {
24
+ return a.sessionId === b.sessionId;
25
+ }
26
+ /**
27
+ * Sort sessions by lastActive (most recent first), then by sessionId for stability
28
+ */
29
+ export function sortSessions(sessions) {
30
+ return [...sessions].sort((a, b) => {
31
+ // Sort by lastActive descending (most recent first)
32
+ const timeA = new Date(a.lastActive).getTime();
33
+ const timeB = new Date(b.lastActive).getTime();
34
+ if (timeA !== timeB) {
35
+ return timeB - timeA; // Descending order
36
+ }
37
+ // If lastActive is the same, sort by sessionId for stability
38
+ return a.sessionId.localeCompare(b.sessionId);
39
+ });
40
+ }
41
+ /**
42
+ * Deduplicate sessions by sessionId, keeping the most recent version
43
+ */
44
+ export function deduplicateSessions(sessions) {
45
+ const sessionMap = new Map();
46
+ for (const session of sessions) {
47
+ const existing = sessionMap.get(session.sessionId);
48
+ if (!existing) {
49
+ sessionMap.set(session.sessionId, session);
50
+ }
51
+ else {
52
+ // Keep the one with more recent lastActive
53
+ const existingTime = new Date(existing.lastActive).getTime();
54
+ const currentTime = new Date(session.lastActive).getTime();
55
+ if (currentTime > existingTime) {
56
+ sessionMap.set(session.sessionId, session);
57
+ }
58
+ }
59
+ }
60
+ return Array.from(sessionMap.values());
61
+ }
62
+ /**
63
+ * Deduplicate sessions by userId, keeping only one session per user
64
+ * Priority: 1) Active session (if provided), 2) Most recent session
65
+ * This prevents showing duplicate accounts for the same user
66
+ */
67
+ export function deduplicateSessionsByUserId(sessions, activeSessionId) {
68
+ if (!sessions.length)
69
+ return [];
70
+ const userSessionMap = new Map();
71
+ for (const session of sessions) {
72
+ if (!session.userId)
73
+ continue; // Skip sessions without userId
74
+ const existing = userSessionMap.get(session.userId);
75
+ if (!existing) {
76
+ userSessionMap.set(session.userId, session);
77
+ }
78
+ else {
79
+ // Prioritize active session
80
+ const isCurrentActive = activeSessionId && session.sessionId === activeSessionId;
81
+ const isExistingActive = activeSessionId && existing.sessionId === activeSessionId;
82
+ if (isCurrentActive && !isExistingActive) {
83
+ userSessionMap.set(session.userId, session);
84
+ }
85
+ else if (!isCurrentActive && isExistingActive) {
86
+ // Keep existing (active) session
87
+ continue;
88
+ }
89
+ else {
90
+ // Neither is active, keep the one with more recent lastActive
91
+ const existingTime = new Date(existing.lastActive).getTime();
92
+ const currentTime = new Date(session.lastActive).getTime();
93
+ if (currentTime > existingTime) {
94
+ userSessionMap.set(session.userId, session);
95
+ }
96
+ }
97
+ }
98
+ }
99
+ return Array.from(userSessionMap.values());
100
+ }
101
+ /**
102
+ * Normalize, deduplicate, and sort sessions
103
+ * This ensures consistent session ordering across the application
104
+ *
105
+ * @param sessions - Array of sessions to normalize
106
+ * @param activeSessionId - Optional active session ID to prioritize
107
+ * @param deduplicateByUserId - If true, deduplicate by userId (one account per user). Default: true
108
+ */
109
+ export function normalizeAndSortSessions(sessions, activeSessionId, deduplicateByUserId = true) {
110
+ if (!sessions.length)
111
+ return [];
112
+ // Normalize all sessions
113
+ const normalized = sessions.map(normalizeSession);
114
+ // First deduplicate by sessionId (exact duplicates)
115
+ const deduplicatedBySessionId = deduplicateSessions(normalized);
116
+ // Then deduplicate by userId if requested (one account per user)
117
+ const finalSessions = deduplicateByUserId
118
+ ? deduplicateSessionsByUserId(deduplicatedBySessionId, activeSessionId)
119
+ : deduplicatedBySessionId;
120
+ // Sort consistently
121
+ return sortSessions(finalSessions);
122
+ }
123
+ /**
124
+ * Merge two session arrays, prioritizing newer data
125
+ * Returns normalized, deduplicated, and sorted sessions
126
+ *
127
+ * @param existing - Existing sessions array
128
+ * @param incoming - New sessions to merge in
129
+ * @param activeSessionId - Optional active session ID to prioritize
130
+ * @param deduplicateByUserId - If true, deduplicate by userId (one account per user). Default: true
131
+ */
132
+ export function mergeSessions(existing, incoming, activeSessionId, deduplicateByUserId = true) {
133
+ if (!existing.length && !incoming.length)
134
+ return [];
135
+ if (!existing.length)
136
+ return normalizeAndSortSessions(incoming, activeSessionId, deduplicateByUserId);
137
+ if (!incoming.length)
138
+ return normalizeAndSortSessions(existing, activeSessionId, deduplicateByUserId);
139
+ // Normalize both arrays
140
+ const normalizedExisting = existing.map(normalizeSession);
141
+ const normalizedIncoming = incoming.map(normalizeSession);
142
+ // Create a map with existing sessions (by sessionId)
143
+ const sessionMap = new Map();
144
+ // Add existing sessions first
145
+ for (const session of normalizedExisting) {
146
+ sessionMap.set(session.sessionId, session);
147
+ }
148
+ // Merge incoming sessions - backend data always replaces existing
149
+ for (const session of normalizedIncoming) {
150
+ sessionMap.set(session.sessionId, session);
151
+ }
152
+ // Convert to array
153
+ const merged = Array.from(sessionMap.values());
154
+ // Apply userId deduplication if requested
155
+ const finalSessions = deduplicateByUserId
156
+ ? deduplicateSessionsByUserId(merged, activeSessionId)
157
+ : merged;
158
+ // Sort consistently
159
+ return sortSessions(finalSessions);
160
+ }
161
+ /**
162
+ * Check if two session arrays are equal (same sessionIds in same order)
163
+ */
164
+ export function sessionsArraysEqual(a, b) {
165
+ if (a.length !== b.length) {
166
+ return false;
167
+ }
168
+ const sortedA = sortSessions(a);
169
+ const sortedB = sortSessions(b);
170
+ return sortedA.every((session, index) => sessionsEqual(session, sortedB[index]));
171
+ }
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Validation utilities for common data validation patterns
3
+ */
4
+ /**
5
+ * Email validation regex
6
+ */
7
+ export const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
8
+ /**
9
+ * Username validation regex (alphanumeric, underscores, and hyphens, 3-30 chars)
10
+ */
11
+ export const USERNAME_REGEX = /^[a-zA-Z0-9_-]{3,30}$/;
12
+ /**
13
+ * Password validation regex (at least 8 chars, 1 uppercase, 1 lowercase, 1 number)
14
+ */
15
+ // At least 8 characters (tests expect len>=8 without complexity requirements)
16
+ export const PASSWORD_REGEX = /^.{8,}$/;
17
+ /**
18
+ * Validate email format
19
+ */
20
+ export function isValidEmail(email) {
21
+ return EMAIL_REGEX.test(email);
22
+ }
23
+ /**
24
+ * Validate username format
25
+ */
26
+ export function isValidUsername(username) {
27
+ return USERNAME_REGEX.test(username);
28
+ }
29
+ /**
30
+ * Validate password strength
31
+ */
32
+ export function isValidPassword(password) {
33
+ return PASSWORD_REGEX.test(password);
34
+ }
35
+ /**
36
+ * Validate required string
37
+ */
38
+ export function isRequiredString(value) {
39
+ return typeof value === 'string' && value.trim().length > 0;
40
+ }
41
+ /**
42
+ * Validate required number
43
+ */
44
+ export function isRequiredNumber(value) {
45
+ return typeof value === 'number' && !Number.isNaN(value);
46
+ }
47
+ /**
48
+ * Validate required boolean
49
+ */
50
+ export function isRequiredBoolean(value) {
51
+ return typeof value === 'boolean';
52
+ }
53
+ /**
54
+ * Validate array
55
+ */
56
+ export function isValidArray(value) {
57
+ return Array.isArray(value);
58
+ }
59
+ /**
60
+ * Validate object
61
+ */
62
+ export function isValidObject(value) {
63
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
64
+ }
65
+ /**
66
+ * Validate UUID format
67
+ */
68
+ export function isValidUUID(uuid) {
69
+ const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
70
+ return UUID_REGEX.test(uuid);
71
+ }
72
+ /**
73
+ * Validate URL format
74
+ */
75
+ export function isValidURL(url) {
76
+ try {
77
+ new URL(url);
78
+ return true;
79
+ }
80
+ catch {
81
+ return false;
82
+ }
83
+ }
84
+ /**
85
+ * Validate date string
86
+ */
87
+ export function isValidDate(dateString) {
88
+ const date = new Date(dateString);
89
+ return !Number.isNaN(date.getTime());
90
+ }
91
+ /**
92
+ * Validate file size (in bytes)
93
+ */
94
+ export function isValidFileSize(size, maxSize) {
95
+ return size > 0 && size <= maxSize;
96
+ }
97
+ /**
98
+ * Validate file type
99
+ */
100
+ export function isValidFileType(filename, allowedTypes) {
101
+ const extension = filename.split('.').pop()?.toLowerCase();
102
+ return extension ? allowedTypes.includes(extension) : false;
103
+ }
104
+ /**
105
+ * Sanitize string input
106
+ */
107
+ export function sanitizeString(input) {
108
+ // Remove HTML tags entirely and trim whitespace
109
+ return input.trim().replace(/<[^>]*>/g, '');
110
+ }
111
+ /**
112
+ * Sanitize HTML input
113
+ */
114
+ export function sanitizeHTML(input) {
115
+ return input
116
+ .replace(/&/g, '&amp;')
117
+ .replace(/</g, '&lt;')
118
+ .replace(/>/g, '&gt;')
119
+ .replace(/"/g, '&quot;')
120
+ .replace(/'/g, '&#x27;');
121
+ }
122
+ /**
123
+ * Validate MongoDB ObjectId format
124
+ * Note: This is a basic format check. For full validation, use mongoose.Types.ObjectId.isValid()
125
+ * This function works in environments where mongoose may not be available (e.g., client-side)
126
+ */
127
+ export function isValidObjectId(id) {
128
+ if (typeof id !== 'string') {
129
+ return false;
130
+ }
131
+ // MongoDB ObjectId is 24 hex characters
132
+ const OBJECT_ID_REGEX = /^[0-9a-fA-F]{24}$/;
133
+ return OBJECT_ID_REGEX.test(id);
134
+ }
135
+ /**
136
+ * Validate and sanitize user input
137
+ */
138
+ export function validateAndSanitizeUserInput(input, type) {
139
+ if (typeof input !== 'string') {
140
+ return null;
141
+ }
142
+ const sanitized = sanitizeString(input);
143
+ switch (type) {
144
+ case 'email':
145
+ return isValidEmail(sanitized) ? sanitized : null;
146
+ case 'username':
147
+ return isValidUsername(sanitized) ? sanitized : null;
148
+ case 'string':
149
+ return isRequiredString(sanitized) ? sanitized : null;
150
+ default:
151
+ return null;
152
+ }
153
+ }
@@ -0,0 +1,143 @@
1
+ /**
2
+ * AuthManager - Centralized Authentication Manager
3
+ *
4
+ * Provides a unified authentication interface for all platforms.
5
+ * Handles token storage, session management, and auth state changes.
6
+ *
7
+ * @module core/AuthManager
8
+ */
9
+ import type { OxyServices } from './OxyServices';
10
+ import type { SessionLoginResponse, MinimalUserData } from './models/session';
11
+ /**
12
+ * Storage adapter interface for platform-agnostic storage.
13
+ */
14
+ export interface StorageAdapter {
15
+ getItem: (key: string) => Promise<string | null> | string | null;
16
+ setItem: (key: string, value: string) => Promise<void> | void;
17
+ removeItem: (key: string) => Promise<void> | void;
18
+ }
19
+ /**
20
+ * Auth state change callback type.
21
+ */
22
+ export type AuthStateChangeCallback = (user: MinimalUserData | null) => void;
23
+ /**
24
+ * Auth method types.
25
+ */
26
+ export type AuthMethod = 'fedcm' | 'popup' | 'redirect' | 'credentials' | 'identity';
27
+ /**
28
+ * Auth manager configuration.
29
+ */
30
+ export interface AuthManagerConfig {
31
+ /** Storage adapter (localStorage, AsyncStorage, etc.) */
32
+ storage?: StorageAdapter;
33
+ /** Whether to auto-refresh tokens */
34
+ autoRefresh?: boolean;
35
+ /** Token refresh interval in milliseconds (default: 5 minutes before expiry) */
36
+ refreshBuffer?: number;
37
+ }
38
+ /**
39
+ * AuthManager - Centralized authentication management.
40
+ *
41
+ * Provides a single point of control for:
42
+ * - Token storage and retrieval
43
+ * - Session management
44
+ * - Auth state change notifications
45
+ * - Multiple auth method support
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * const authManager = new AuthManager(oxyServices);
50
+ *
51
+ * // Listen for auth changes
52
+ * authManager.onAuthStateChange((user) => {
53
+ * console.log('Auth state changed:', user);
54
+ * });
55
+ *
56
+ * // Handle successful auth
57
+ * await authManager.handleAuthSuccess(session);
58
+ *
59
+ * // Sign out
60
+ * await authManager.signOut();
61
+ * ```
62
+ */
63
+ export declare class AuthManager {
64
+ private oxyServices;
65
+ private storage;
66
+ private listeners;
67
+ private currentUser;
68
+ private refreshTimer;
69
+ private config;
70
+ constructor(oxyServices: OxyServices, config?: AuthManagerConfig);
71
+ /**
72
+ * Get default storage based on environment.
73
+ */
74
+ private getDefaultStorage;
75
+ /**
76
+ * Subscribe to auth state changes.
77
+ *
78
+ * @param callback - Function called when auth state changes
79
+ * @returns Unsubscribe function
80
+ */
81
+ onAuthStateChange(callback: AuthStateChangeCallback): () => void;
82
+ /**
83
+ * Notify all listeners of auth state change.
84
+ */
85
+ private notifyListeners;
86
+ /**
87
+ * Handle successful authentication.
88
+ *
89
+ * @param session - Session response from auth
90
+ * @param method - Auth method used
91
+ */
92
+ handleAuthSuccess(session: SessionLoginResponse, method?: AuthMethod): Promise<void>;
93
+ /**
94
+ * Setup automatic token refresh.
95
+ */
96
+ private setupTokenRefresh;
97
+ /**
98
+ * Refresh the access token.
99
+ */
100
+ refreshToken(): Promise<boolean>;
101
+ /**
102
+ * Sign out and clear all auth data.
103
+ */
104
+ signOut(): Promise<void>;
105
+ /**
106
+ * Clear session data from storage.
107
+ */
108
+ private clearSession;
109
+ /**
110
+ * Get current user.
111
+ */
112
+ getCurrentUser(): MinimalUserData | null;
113
+ /**
114
+ * Check if user is authenticated.
115
+ */
116
+ isAuthenticated(): boolean;
117
+ /**
118
+ * Get stored access token.
119
+ */
120
+ getAccessToken(): Promise<string | null>;
121
+ /**
122
+ * Get the auth method used for current session.
123
+ */
124
+ getAuthMethod(): Promise<AuthMethod | null>;
125
+ /**
126
+ * Initialize auth state from storage.
127
+ *
128
+ * Call this on app startup to restore previous session.
129
+ */
130
+ initialize(): Promise<MinimalUserData | null>;
131
+ /**
132
+ * Destroy the auth manager and clean up resources.
133
+ */
134
+ destroy(): void;
135
+ }
136
+ /**
137
+ * Create an AuthManager instance.
138
+ *
139
+ * @param oxyServices - OxyServices instance
140
+ * @param config - Optional configuration
141
+ * @returns AuthManager instance
142
+ */
143
+ export declare function createAuthManager(oxyServices: OxyServices, config?: AuthManagerConfig): AuthManager;