reslib 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 (200) hide show
  1. package/README.md +298 -0
  2. package/build/auth/index.d.ts +2034 -0
  3. package/build/auth/index.js +5 -0
  4. package/build/auth/types.d.ts +465 -0
  5. package/build/auth/types.js +1 -0
  6. package/build/countries/countries.d.ts +1454 -0
  7. package/build/countries/countries.js +1 -0
  8. package/build/countries/index.d.ts +159 -0
  9. package/build/countries/index.js +5 -0
  10. package/build/countries/types.d.ts +65 -0
  11. package/build/countries/types.js +1 -0
  12. package/build/currency/currencies.d.ts +8 -0
  13. package/build/currency/currencies.js +1 -0
  14. package/build/currency/index.d.ts +51 -0
  15. package/build/currency/index.js +5 -0
  16. package/build/currency/session.d.ts +23 -0
  17. package/build/currency/session.js +5 -0
  18. package/build/currency/types.d.ts +1039 -0
  19. package/build/currency/types.js +1 -0
  20. package/build/currency/utils.d.ts +25 -0
  21. package/build/currency/utils.js +1 -0
  22. package/build/i18n/index.d.ts +640 -0
  23. package/build/i18n/index.js +5 -0
  24. package/build/inputFormatter/index.d.ts +396 -0
  25. package/build/inputFormatter/index.js +5 -0
  26. package/build/inputFormatter/types.d.ts +544 -0
  27. package/build/inputFormatter/types.js +1 -0
  28. package/build/logger/index.d.ts +235 -0
  29. package/build/logger/index.js +5 -0
  30. package/build/observable/index.d.ts +329 -0
  31. package/build/observable/index.js +1 -0
  32. package/build/platform/index.d.ts +32 -0
  33. package/build/platform/index.js +1 -0
  34. package/build/resources/ResourcePaginationHelper.d.ts +537 -0
  35. package/build/resources/ResourcePaginationHelper.js +2 -0
  36. package/build/resources/decorators/create.decorator.d.ts +20 -0
  37. package/build/resources/decorators/create.decorator.js +1 -0
  38. package/build/resources/decorators/index.d.ts +41 -0
  39. package/build/resources/decorators/index.js +1 -0
  40. package/build/resources/fields/index.d.ts +33 -0
  41. package/build/resources/fields/index.js +1 -0
  42. package/build/resources/filters.d.ts +62 -0
  43. package/build/resources/filters.js +1 -0
  44. package/build/resources/index.d.ts +854 -0
  45. package/build/resources/index.js +6 -0
  46. package/build/resources/types/filters.d.ts +508 -0
  47. package/build/resources/types/filters.js +1 -0
  48. package/build/resources/types/index.d.ts +4138 -0
  49. package/build/resources/types/index.js +1 -0
  50. package/build/session/index.d.ts +1474 -0
  51. package/build/session/index.js +1 -0
  52. package/build/translations/auth.en.d.ts +3 -0
  53. package/build/translations/auth.en.js +1 -0
  54. package/build/translations/countries.en.d.ts +6 -0
  55. package/build/translations/countries.en.js +1 -0
  56. package/build/translations/currencies.en.d.ts +5 -0
  57. package/build/translations/currencies.en.js +1 -0
  58. package/build/translations/date.en.d.ts +19 -0
  59. package/build/translations/date.en.js +1 -0
  60. package/build/translations/index.d.ts +1583 -0
  61. package/build/translations/index.js +5 -0
  62. package/build/translations/resources.en.d.ts +6 -0
  63. package/build/translations/resources.en.js +1 -0
  64. package/build/translations/validator.en.d.ts +104 -0
  65. package/build/translations/validator.en.js +5 -0
  66. package/build/types/date.d.ts +44 -0
  67. package/build/types/date.js +1 -0
  68. package/build/types/dictionary.d.ts +29 -0
  69. package/build/types/dictionary.js +1 -0
  70. package/build/types/i18n.d.ts +121 -0
  71. package/build/types/i18n.js +1 -0
  72. package/build/types/index.d.ts +145 -0
  73. package/build/types/index.js +1 -0
  74. package/build/utils/areEquals.d.ts +19 -0
  75. package/build/utils/areEquals.js +1 -0
  76. package/build/utils/date/dateHelper.d.ts +371 -0
  77. package/build/utils/date/dateHelper.js +5 -0
  78. package/build/utils/date/index.d.ts +212 -0
  79. package/build/utils/date/index.js +5 -0
  80. package/build/utils/date/isDateObj.d.ts +14 -0
  81. package/build/utils/date/isDateObj.js +1 -0
  82. package/build/utils/debounce.d.ts +52 -0
  83. package/build/utils/debounce.js +1 -0
  84. package/build/utils/defaultArray.d.ts +18 -0
  85. package/build/utils/defaultArray.js +1 -0
  86. package/build/utils/defaultBool.d.ts +14 -0
  87. package/build/utils/defaultBool.js +1 -0
  88. package/build/utils/defaultStr.d.ts +17 -0
  89. package/build/utils/defaultStr.js +1 -0
  90. package/build/utils/defaultVal.d.ts +18 -0
  91. package/build/utils/defaultVal.js +1 -0
  92. package/build/utils/dom/index.d.ts +65 -0
  93. package/build/utils/dom/index.js +1 -0
  94. package/build/utils/dom/isDOMElement.d.ts +11 -0
  95. package/build/utils/dom/isDOMElement.js +1 -0
  96. package/build/utils/file/index.d.ts +26 -0
  97. package/build/utils/file/index.js +1 -0
  98. package/build/utils/global.d.ts +53 -0
  99. package/build/utils/global.js +1 -0
  100. package/build/utils/image.d.ts +56 -0
  101. package/build/utils/image.js +1 -0
  102. package/build/utils/index.d.ts +39 -0
  103. package/build/utils/index.js +6 -0
  104. package/build/utils/interpolate.d.ts +105 -0
  105. package/build/utils/interpolate.js +1 -0
  106. package/build/utils/isEmail.d.ts +57 -0
  107. package/build/utils/isEmail.js +1 -0
  108. package/build/utils/isEmpty.d.ts +18 -0
  109. package/build/utils/isEmpty.js +1 -0
  110. package/build/utils/isNonNullString.d.ts +17 -0
  111. package/build/utils/isNonNullString.js +1 -0
  112. package/build/utils/isNullable.d.ts +7 -0
  113. package/build/utils/isNullable.js +1 -0
  114. package/build/utils/isNumber.d.ts +36 -0
  115. package/build/utils/isNumber.js +1 -0
  116. package/build/utils/isPrimitive.d.ts +16 -0
  117. package/build/utils/isPrimitive.js +1 -0
  118. package/build/utils/isPromise.d.ts +14 -0
  119. package/build/utils/isPromise.js +1 -0
  120. package/build/utils/isRegex.d.ts +15 -0
  121. package/build/utils/isRegex.js +1 -0
  122. package/build/utils/isTime.d.ts +18 -0
  123. package/build/utils/isTime.js +1 -0
  124. package/build/utils/json.d.ts +224 -0
  125. package/build/utils/json.js +1 -0
  126. package/build/utils/numbers.d.ts +148 -0
  127. package/build/utils/numbers.js +5 -0
  128. package/build/utils/object.d.ts +567 -0
  129. package/build/utils/object.js +1 -0
  130. package/build/utils/sort.d.ts +67 -0
  131. package/build/utils/sort.js +1 -0
  132. package/build/utils/string.d.ts +165 -0
  133. package/build/utils/string.js +1 -0
  134. package/build/utils/stringify.d.ts +23 -0
  135. package/build/utils/stringify.js +1 -0
  136. package/build/utils/uniqid.d.ts +18 -0
  137. package/build/utils/uniqid.js +1 -0
  138. package/build/utils/uri/index.d.ts +333 -0
  139. package/build/utils/uri/index.js +2 -0
  140. package/build/validator/index.d.ts +4 -0
  141. package/build/validator/index.js +6 -0
  142. package/build/validator/rules/array.d.ts +848 -0
  143. package/build/validator/rules/array.js +5 -0
  144. package/build/validator/rules/boolean.d.ts +87 -0
  145. package/build/validator/rules/boolean.js +5 -0
  146. package/build/validator/rules/date.d.ts +551 -0
  147. package/build/validator/rules/date.js +5 -0
  148. package/build/validator/rules/default.d.ts +367 -0
  149. package/build/validator/rules/default.js +5 -0
  150. package/build/validator/rules/enum.d.ts +155 -0
  151. package/build/validator/rules/enum.js +5 -0
  152. package/build/validator/rules/file.d.ts +356 -0
  153. package/build/validator/rules/file.js +5 -0
  154. package/build/validator/rules/format.d.ts +2825 -0
  155. package/build/validator/rules/format.js +6 -0
  156. package/build/validator/rules/index.d.ts +16 -0
  157. package/build/validator/rules/index.js +6 -0
  158. package/build/validator/rules/multiRules.d.ts +475 -0
  159. package/build/validator/rules/multiRules.js +5 -0
  160. package/build/validator/rules/numeric.d.ts +1135 -0
  161. package/build/validator/rules/numeric.js +5 -0
  162. package/build/validator/rules/string.d.ts +504 -0
  163. package/build/validator/rules/string.js +5 -0
  164. package/build/validator/rules/target.d.ts +137 -0
  165. package/build/validator/rules/target.js +5 -0
  166. package/build/validator/rules/utils.d.ts +1 -0
  167. package/build/validator/rules/utils.js +1 -0
  168. package/build/validator/rulesMarkers.d.ts +11 -0
  169. package/build/validator/rulesMarkers.js +1 -0
  170. package/build/validator/types.d.ts +2906 -0
  171. package/build/validator/types.js +1 -0
  172. package/build/validator/validator.d.ts +3692 -0
  173. package/build/validator/validator.js +5 -0
  174. package/lib/cjs/auth.js +1 -0
  175. package/lib/cjs/countries.js +1 -0
  176. package/lib/cjs/currency.js +1 -0
  177. package/lib/cjs/i18n.js +1 -0
  178. package/lib/cjs/inputFormatter.js +1 -0
  179. package/lib/cjs/logger.js +1 -0
  180. package/lib/cjs/observable.js +1 -0
  181. package/lib/cjs/platform.js +1 -0
  182. package/lib/cjs/resources.js +1 -0
  183. package/lib/cjs/session.js +1 -0
  184. package/lib/cjs/types.js +1 -0
  185. package/lib/cjs/utils.js +1 -0
  186. package/lib/cjs/validator.js +1 -0
  187. package/lib/esm/auth.mjs +1 -0
  188. package/lib/esm/countries.mjs +1 -0
  189. package/lib/esm/currency.mjs +1 -0
  190. package/lib/esm/i18n.mjs +1 -0
  191. package/lib/esm/inputFormatter.mjs +1 -0
  192. package/lib/esm/logger.mjs +1 -0
  193. package/lib/esm/observable.mjs +1 -0
  194. package/lib/esm/platform.mjs +1 -0
  195. package/lib/esm/resources.mjs +1 -0
  196. package/lib/esm/session.mjs +1 -0
  197. package/lib/esm/types.mjs +1 -0
  198. package/lib/esm/utils.mjs +1 -0
  199. package/lib/esm/validator.mjs +1 -0
  200. package/package.json +244 -0
@@ -0,0 +1,1474 @@
1
+ import 'reflect-metadata';
2
+ import { ClassConstructor } from '../types/index';
3
+ declare class Manager {
4
+ static readonly sessionStorageMetaData: unique symbol;
5
+ /**
6
+ * The storage object used by the session manager.
7
+ *
8
+ * This property is initialized lazily when the `storage` getter is called.
9
+ */
10
+ private static _storage;
11
+ /**
12
+ * The namespace prefix to use for all keys in the session storage.
13
+ *
14
+ * This property is optional and can be set using the `keyNamespace` setter.
15
+ */
16
+ private static _keyNamespace?;
17
+ /**
18
+ * Retrieves or initializes the session storage implementation used by the Manager.
19
+ *
20
+ * This getter implements a sophisticated storage initialization strategy with multiple fallback mechanisms
21
+ * to ensure reliable session storage across different environments and platforms. The method follows
22
+ * a priority-based approach to determine the most suitable storage implementation available.
23
+ *
24
+ * ### Storage Priority Order:
25
+ * 1. **Custom Attached Storage** - Storage registered via {@link AttachSessionStorage} decorator
26
+ * 2. **Browser localStorage** - Native browser localStorage (client-side only)
27
+ * 3. **In-Memory Storage** - Fallback dictionary-based storage (server-side or fallback)
28
+ *
29
+ * ### Initialization Process:
30
+ * The getter performs the following steps in order:
31
+ * 1. Checks for custom storage registered via reflection metadata
32
+ * 2. Validates the custom storage using {@link isValidStorage}
33
+ * 3. Falls back to browser localStorage if available and valid
34
+ * 4. Creates in-memory storage as the final fallback option
35
+ * 5. Caches the initialized storage for subsequent calls
36
+ *
37
+ * ### Platform Detection:
38
+ * Uses {@link Platform.isClientSide} to detect the execution environment and choose
39
+ * appropriate storage mechanisms. This ensures compatibility across:
40
+ * - **Browser environments** - Uses localStorage when available
41
+ * - **Server-side rendering** - Uses in-memory storage
42
+ * - **Node.js environments** - Uses in-memory storage
43
+ * - **React Native** - Can use custom storage implementations
44
+ *
45
+ * @returns The active session storage implementation conforming to {@link SessionStorage}
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * // Basic usage - get the current storage
50
+ * const storage = Manager.storage;
51
+ *
52
+ * // Use storage directly
53
+ * storage.set('userToken', 'abc123');
54
+ * const token = storage.get('userToken');
55
+ * storage.remove('userToken');
56
+ * ```
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * // Storage will automatically use localStorage in browser
61
+ * if (Platform.isClientSide()) {
62
+ * const storage = Manager.storage; // Uses localStorage
63
+ * storage.set('preferences', { theme: 'dark', lang: 'en' });
64
+ *
65
+ * // Data persists across page reloads
66
+ * window.location.reload();
67
+ * const prefs = storage.get('preferences'); // Still available
68
+ * }
69
+ * ```
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * // Server-side usage automatically uses in-memory storage
74
+ * import { Manager } from 'reslib/session';
75
+ *
76
+ * // In Node.js environment
77
+ * const storage = Manager.storage; // Uses in-memory storage
78
+ * storage.set('sessionData', { userId: 123 });
79
+ *
80
+ * // Data only persists during application lifetime
81
+ * const data = storage.get('sessionData');
82
+ * console.log(data); // { userId: 123 }
83
+ * ```
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * // Custom storage integration example
88
+ * @AttachSessionStorage()
89
+ * class RedisStorage implements SessionStorage {
90
+ * constructor(private redis: RedisClient) {}
91
+ *
92
+ * get(key: string): any {
93
+ * return this.redis.get(key);
94
+ * }
95
+ *
96
+ * set(key: string, value: any): any {
97
+ * this.redis.set(key, JSON.stringify(value));
98
+ * return value;
99
+ * }
100
+ *
101
+ * remove(key: string): any {
102
+ * const value = this.get(key);
103
+ * this.redis.del(key);
104
+ * return value;
105
+ * }
106
+ *
107
+ * removeAll(): any {
108
+ * this.redis.flushall();
109
+ * }
110
+ * }
111
+ *
112
+ * // Now Manager.storage will use Redis
113
+ * const storage = Manager.storage; // Returns RedisStorage instance
114
+ * ```
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * // Storage with error handling
119
+ * try {
120
+ * const storage = Manager.storage;
121
+ *
122
+ * // Attempt to store large object
123
+ * const largeData = new Array(1000000).fill('data');
124
+ * storage.set('largeObject', largeData);
125
+ *
126
+ * } catch (error) {
127
+ * console.error('Storage quota exceeded:', error);
128
+ *
129
+ * // Fallback to essential data only
130
+ * const storage = Manager.storage;
131
+ * storage.set('essentialData', { id: 1 });
132
+ * }
133
+ * ```
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * // Checking storage capabilities
138
+ * const storage = Manager.storage;
139
+ *
140
+ * // Test if storage is persistent (localStorage) or temporary (in-memory)
141
+ * storage.set('test', 'value');
142
+ *
143
+ * if (Platform.isClientSide() && window.localStorage) {
144
+ * console.log('Using persistent localStorage');
145
+ * // Data will survive page reloads
146
+ * } else {
147
+ * console.log('Using temporary in-memory storage');
148
+ * // Data will be lost on page reload
149
+ * }
150
+ * ```
151
+ *
152
+ * @example
153
+ * ```typescript
154
+ * // Advanced: Storage introspection
155
+ * const storage = Manager.storage;
156
+ *
157
+ * // Check which storage implementation is active
158
+ * if ('localStorage' in storage.get.toString()) {
159
+ * console.log('Using browser localStorage');
160
+ * } else if ('InMemoryStorage' in storage.get.toString()) {
161
+ * console.log('Using in-memory storage');
162
+ * } else {
163
+ * console.log('Using custom storage implementation');
164
+ * }
165
+ * ```
166
+ *
167
+ * @see {@link SessionStorage} - Interface that all storage implementations must follow
168
+ * @see {@link AttachSessionStorage} - Decorator for registering custom storage implementations
169
+ * @see {@link isValidStorage} - Function used to validate storage implementations
170
+ * @see {@link Platform.isClientSide} - Platform detection utility
171
+ * @see {@link JsonHelper} - JSON serialization utilities used by storage
172
+ *
173
+ *
174
+ * @public
175
+ *
176
+ * @remarks
177
+ * **Important Behavior Notes:**
178
+ * - The storage is initialized lazily on first access for optimal performance
179
+ * - Once initialized, the same storage instance is reused for all subsequent calls
180
+ * - Custom storage registered via {@link AttachSessionStorage} takes highest priority
181
+ * - Browser localStorage is only used in client-side environments with proper window object
182
+ * - In-memory storage is automatically garbage collected when the application ends
183
+ *
184
+ * **Browser Compatibility:**
185
+ * - Checks for `window.localStorage` availability before attempting to use it
186
+ * - Gracefully degrades to in-memory storage if localStorage is disabled/unavailable
187
+ * - Works in all major browsers including legacy versions
188
+ * - Supports private/incognito browsing modes that may disable localStorage
189
+ *
190
+ * **Performance Characteristics:**
191
+ * - **localStorage**: Synchronous, persistent, ~5-10MB limit per origin
192
+ * - **In-memory**: Synchronous, non-persistent, limited by available RAM
193
+ * - **Custom storage**: Performance depends on implementation (can be async)
194
+ *
195
+ * **Security Considerations:**
196
+ * - localStorage data is accessible to all scripts on the same origin
197
+ * - In-memory storage is more secure as it's not persistent
198
+ * - Custom storage implementations should implement appropriate security measures
199
+ * - Consider encryption for sensitive data regardless of storage type
200
+ *
201
+ * **Thread Safety:**
202
+ * - localStorage operations are synchronous and atomic
203
+ * - In-memory storage access is synchronous but not thread-safe across workers
204
+ * - Custom storage implementations should handle concurrency appropriately
205
+ */
206
+ static get storage(): SessionStorage;
207
+ /**
208
+ * Sets the storage object used by the session manager.
209
+ *
210
+ * The provided storage object must be valid and have the required methods.
211
+ *
212
+ * @param {SessionStorage} storage - The storage object to use.
213
+ */
214
+ static set storage(storage: SessionStorage);
215
+ /**
216
+ * Gets the current namespace prefix used for all session storage keys.
217
+ *
218
+ * This getter provides access to the global namespace prefix that is automatically prepended
219
+ * to all session storage keys when they are sanitized. Namespacing is essential for creating
220
+ * isolated storage contexts in applications that share the same storage backend, preventing
221
+ * key collisions between different modules, features, or application instances.
222
+ *
223
+ * ### Key Benefits:
224
+ * - **Isolation**: Prevents key conflicts between different application parts
225
+ * - **Organization**: Groups related storage keys under a common prefix
226
+ * - **Multi-tenancy**: Enables separate storage contexts for different users/tenants
227
+ * - **Environment Separation**: Allows different prefixes for dev/staging/production
228
+ *
229
+ * ### Namespace Format:
230
+ * The namespace is returned as a clean string without any trailing separators.
231
+ * The system automatically adds the `-` separator when constructing the final key.
232
+ *
233
+ * @returns The current namespace prefix as a string, or empty string if no namespace is set
234
+ *
235
+ * @example
236
+ * ```typescript
237
+ * // Get the current namespace
238
+ * const namespace = Manager.keyNamespace;
239
+ * console.log(namespace); // "" (empty by default)
240
+ *
241
+ * // Set a namespace first
242
+ * Manager.keyNamespace = "myapp";
243
+ * console.log(Manager.keyNamespace); // "myapp"
244
+ * ```
245
+ *
246
+ * @example
247
+ * ```typescript
248
+ * // Multi-tenant application example
249
+ * class TenantSessionManager {
250
+ * static setTenant(tenantId: string) {
251
+ * Manager.keyNamespace = `tenant-${tenantId}`;
252
+ * }
253
+ *
254
+ * static getCurrentTenant(): string {
255
+ * const namespace = Manager.keyNamespace;
256
+ * return namespace.replace('tenant-', '');
257
+ * }
258
+ * }
259
+ *
260
+ * // Usage
261
+ * TenantSessionManager.setTenant('acme-corp');
262
+ * console.log(Manager.keyNamespace); // "tenant-acme-corp"
263
+ *
264
+ * // All session operations now use this namespace
265
+ * Session.set('userPrefs', { theme: 'dark' });
266
+ * // Stored as key: "tenant-acme-corp-userPrefs"
267
+ * ```
268
+ *
269
+ * @example
270
+ * ```typescript
271
+ * // Environment-based namespacing
272
+ * const environment = process.env.NODE_ENV || 'development';
273
+ * const appVersion = process.env.APP_VERSION || '1.0.0';
274
+ *
275
+ * Manager.keyNamespace = `${environment}-v${appVersion}`;
276
+ * console.log(Manager.keyNamespace); // "production-v2.1.0"
277
+ *
278
+ * // All storage operations are now environment-scoped
279
+ * Session.set('cache', data); // Stored as "production-v2.1.0-cache"
280
+ * ```
281
+ *
282
+ * @example
283
+ * ```typescript
284
+ * // Dynamic namespace checking
285
+ * function ensureNamespace(requiredNamespace: string) {
286
+ * const current = Manager.keyNamespace;
287
+ * if (current !== requiredNamespace) {
288
+ * throw new Error(`Expected namespace '${requiredNamespace}', got '${current}'`);
289
+ * }
290
+ * }
291
+ *
292
+ * // Usage in critical operations
293
+ * Manager.keyNamespace = "secure-context";
294
+ * ensureNamespace("secure-context"); // Passes
295
+ * Session.set('sensitiveData', encryptedData);
296
+ * ```
297
+ *
298
+ * @example
299
+ * ```typescript
300
+ * // Namespace validation and formatting
301
+ * function validateNamespace(): boolean {
302
+ * const namespace = Manager.keyNamespace;
303
+ *
304
+ * // Check for valid format
305
+ * const isValidFormat = /^[a-z0-9-]+$/.test(namespace);
306
+ * const hasNoConsecutiveDashes = !namespace.includes('--');
307
+ * const doesNotStartOrEndWithDash = !namespace.startsWith('-') && !namespace.endsWith('-');
308
+ *
309
+ * return isValidFormat && hasNoConsecutiveDashes && doesNotStartOrEndWithDash;
310
+ * }
311
+ *
312
+ * Manager.keyNamespace = "my-app-v1";
313
+ * console.log(validateNamespace()); // true
314
+ *
315
+ * Manager.keyNamespace = "invalid--namespace-";
316
+ * console.log(validateNamespace()); // false
317
+ * ```
318
+ *
319
+ * @see {@link keyNamespace} (setter) - Method to set the namespace prefix
320
+ * @see {@link sanitizeKey} - Method that applies the namespace to keys
321
+ * @see {@link Session.set} - Session storage method that uses namespaced keys
322
+ * @see {@link Session.get} - Session retrieval method that uses namespaced keys
323
+ *
324
+ *
325
+ * @public
326
+ *
327
+ * @remarks
328
+ * **Important Considerations:**
329
+ * - The namespace affects ALL subsequent session operations
330
+ * - Changing the namespace will effectively "switch" to a different storage context
331
+ * - Keys stored with one namespace won't be accessible with a different namespace
332
+ * - The namespace is stored globally and persists until explicitly changed
333
+ * - An empty namespace means no prefixing is applied to keys
334
+ *
335
+ * **Best Practices:**
336
+ * - Set the namespace early in your application lifecycle
337
+ * - Use consistent naming conventions (lowercase, hyphens for separation)
338
+ * - Consider including version numbers for schema evolution
339
+ * - Avoid changing namespaces frequently during application runtime
340
+ * - Document your namespace strategy for team members
341
+ *
342
+ * **Thread Safety:**
343
+ * - Reading the namespace is thread-safe
344
+ * - The value is cached until explicitly changed
345
+ * - Multiple reads return the same value consistently
346
+ */
347
+ static get keyNamespace(): string;
348
+ /**
349
+ * Sets the namespace prefix that will be prepended to all session storage keys.
350
+ *
351
+ * This setter allows you to configure a global namespace prefix that will be automatically
352
+ * applied to all session storage keys when they are sanitized. Setting a namespace is crucial
353
+ * for applications that need to maintain separate storage contexts, avoid key collisions,
354
+ * or implement multi-tenant architectures where different users or application instances
355
+ * should have isolated storage spaces.
356
+ *
357
+ * ### Namespace Validation:
358
+ * The setter validates the input using {@link isNonNullString} to ensure only valid,
359
+ * non-empty strings are accepted. Invalid inputs (null, undefined, empty strings) are
360
+ * silently ignored, preserving the current namespace value.
361
+ *
362
+ * ### Impact on Storage Operations:
363
+ * Once a namespace is set, ALL subsequent session storage operations will use the
364
+ * namespaced keys. This includes {@link Session.get}, {@link Session.set},
365
+ * {@link Session.remove}, and all other storage methods.
366
+ *
367
+ * @param prefix - The namespace prefix to use for all storage keys
368
+ *
369
+ * @example
370
+ * ```typescript
371
+ * // Basic namespace setup
372
+ * Manager.keyNamespace = "myapp";
373
+ *
374
+ * // Now all storage operations use the namespace
375
+ * Session.set('user', { id: 1, name: 'John' });
376
+ * // Stored with key: "myapp-user"
377
+ *
378
+ * const user = Session.get('user');
379
+ * // Retrieves using key: "myapp-user"
380
+ * ```
381
+ *
382
+ * @example
383
+ * ```typescript
384
+ * // Multi-environment configuration
385
+ * const environment = process.env.NODE_ENV;
386
+ * const version = process.env.APP_VERSION;
387
+ *
388
+ * // Set environment-specific namespace
389
+ * Manager.keyNamespace = `${environment}-${version}`;
390
+ *
391
+ * // Examples:
392
+ * // Development: "development-1.0.0"
393
+ * // Production: "production-2.1.5"
394
+ * // Testing: "testing-1.2.0-beta"
395
+ *
396
+ * Session.set('config', appConfig);
397
+ * // Stored as "production-2.1.5-config"
398
+ * ```
399
+ *
400
+ * @example
401
+ * ```typescript
402
+ * // User-specific namespacing for multi-tenant apps
403
+ * class UserSessionManager {
404
+ * static loginUser(userId: string, organizationId: string) {
405
+ * // Create unique namespace for this user context
406
+ * Manager.keyNamespace = `org-${organizationId}-user-${userId}`;
407
+ *
408
+ * // All subsequent storage is user-specific
409
+ * Session.set('preferences', userPreferences);
410
+ * Session.set('cache', userData);
411
+ * }
412
+ *
413
+ * static logoutUser() {
414
+ * // Clear user-specific data
415
+ * Session.removeAll();
416
+ *
417
+ * // Reset to global namespace
418
+ * Manager.keyNamespace = "global";
419
+ * }
420
+ * }
421
+ *
422
+ * // Usage
423
+ * UserSessionManager.loginUser('john123', 'acme-corp');
424
+ * // Namespace: "org-acme-corp-user-john123"
425
+ *
426
+ * Session.set('lastAction', 'document_created');
427
+ * // Stored as: "org-acme-corp-user-john123-lastAction"
428
+ * ```
429
+ *
430
+ * @example
431
+ * ```typescript
432
+ * // Feature-based namespacing
433
+ * class FeatureFlags {
434
+ * private static originalNamespace: string;
435
+ *
436
+ * static enableFeature(featureName: string) {
437
+ * // Save current namespace
438
+ * this.originalNamespace = Manager.keyNamespace;
439
+ *
440
+ * // Switch to feature-specific namespace
441
+ * Manager.keyNamespace = `feature-${featureName}`;
442
+ *
443
+ * return {
444
+ * store: (key: string, value: any) => Session.set(key, value),
445
+ * retrieve: (key: string) => Session.get(key),
446
+ * cleanup: () => {
447
+ * Session.removeAll();
448
+ * Manager.keyNamespace = this.originalNamespace;
449
+ * }
450
+ * };
451
+ * }
452
+ * }
453
+ *
454
+ * // Usage
455
+ * const betaFeature = FeatureFlags.enableFeature('beta-dashboard');
456
+ * betaFeature.store('userProgress', progressData);
457
+ * // Stored as: "feature-beta-dashboard-userProgress"
458
+ *
459
+ * betaFeature.cleanup(); // Removes all feature data and restores namespace
460
+ * ```
461
+ *
462
+ * @example
463
+ * ```typescript
464
+ * // Namespace migration for application updates
465
+ * class NamespaceMigration {
466
+ * static migrateFrom(oldNamespace: string, newNamespace: string) {
467
+ * // Step 1: Read all data from old namespace
468
+ * Manager.keyNamespace = oldNamespace;
469
+ * const oldData = this.getAllStorageData();
470
+ *
471
+ * // Step 2: Switch to new namespace and write data
472
+ * Manager.keyNamespace = newNamespace;
473
+ * Object.entries(oldData).forEach(([key, value]) => {
474
+ * Session.set(key, value);
475
+ * });
476
+ *
477
+ * // Step 3: Clean up old namespace
478
+ * Manager.keyNamespace = oldNamespace;
479
+ * Session.removeAll();
480
+ *
481
+ * // Step 4: Set new namespace as active
482
+ * Manager.keyNamespace = newNamespace;
483
+ * }
484
+ *
485
+ * private static getAllStorageData(): Record<string, any> {
486
+ * // Implementation would depend on storage backend
487
+ * // This is a simplified example
488
+ * return {};
489
+ * }
490
+ * }
491
+ *
492
+ * // Usage during app update
493
+ * NamespaceMigration.migrateFrom('v1.0', 'v2.0');
494
+ * ```
495
+ *
496
+ * @example
497
+ * ```typescript
498
+ * // Namespace validation and sanitization
499
+ * function setSecureNamespace(rawNamespace: string): boolean {
500
+ * // Sanitize the namespace
501
+ * const sanitized = rawNamespace
502
+ * .toLowerCase()
503
+ * .replace(/[^a-z0-9-]/g, '-')
504
+ * .replace(/-+/g, '-')
505
+ * .replace(/^-|-$/g, '');
506
+ *
507
+ * if (sanitized.length < 3) {
508
+ * console.warn('Namespace too short, using default');
509
+ * Manager.keyNamespace = 'default';
510
+ * return false;
511
+ * }
512
+ *
513
+ * Manager.keyNamespace = sanitized;
514
+ * return true;
515
+ * }
516
+ *
517
+ * // Usage
518
+ * setSecureNamespace('My App!! v2.0'); // Sets to "my-app-v2-0"
519
+ * setSecureNamespace('x'); // Sets to "default" (too short)
520
+ * ```
521
+ *
522
+ * @see {@link keyNamespace} (getter) - Method to retrieve the current namespace
523
+ * @see {@link sanitizeKey} - Method that applies the namespace to keys
524
+ * @see {@link isNonNullString} - Validation function used for input checking
525
+ * @see {@link Session} - Session utilities that use the namespaced keys
526
+ *
527
+ *
528
+ * @public
529
+ *
530
+ * @remarks
531
+ * **Critical Behavior Notes:**
532
+ * - Only valid, non-empty strings are accepted as namespace values
533
+ * - Invalid inputs (null, undefined, empty strings) are silently ignored
534
+ * - The namespace change affects ALL subsequent storage operations immediately
535
+ * - Previously stored data under different namespaces becomes inaccessible
536
+ * - The namespace is stored globally and persists until explicitly changed
537
+ *
538
+ * **Security Considerations:**
539
+ * - Ensure namespace values don't contain sensitive information
540
+ * - Validate namespace inputs in security-critical applications
541
+ * - Consider namespace as part of your access control strategy
542
+ * - Be aware that namespace switching can expose or hide data
543
+ *
544
+ * **Performance Impact:**
545
+ * - Namespace setting is a lightweight operation
546
+ * - The namespace is cached and doesn't impact storage operation performance
547
+ * - Frequent namespace changes can lead to memory fragmentation in some storage backends
548
+ *
549
+ * **Best Practices:**
550
+ * - Set the namespace once during application initialization
551
+ * - Use consistent, predictable naming patterns
552
+ * - Document your namespace strategy and conventions
553
+ * - Consider versioning in your namespace for future migrations
554
+ * - Test namespace switching thoroughly in your application
555
+ */
556
+ static set keyNamespace(prefix: string);
557
+ /**
558
+ * Sanitizes and prepares a storage key by removing whitespace and applying the global namespace prefix.
559
+ *
560
+ * This method is the core key processing function that ensures all session storage keys are
561
+ * properly formatted and consistently namespaced. It performs essential cleaning operations
562
+ * to prevent storage errors and applies the global namespace to create isolated storage contexts.
563
+ *
564
+ * The sanitization process is critical for maintaining data integrity and preventing conflicts
565
+ * in shared storage environments. This method is automatically called by all session storage
566
+ * operations, ensuring consistent key handling throughout the application.
567
+ *
568
+ * ### Sanitization Process:
569
+ * 1. **Validation**: Checks if the key is valid using {@link isNonNullString}
570
+ * 2. **Trimming**: Removes leading and trailing whitespace
571
+ * 3. **Whitespace Removal**: Removes all internal whitespace characters
572
+ * 4. **Namespace Application**: Prepends the global namespace with a hyphen separator
573
+ * 5. **Return**: Provides the final, storage-ready key
574
+ *
575
+ * ### Key Format:
576
+ * - **Without namespace**: `"cleankey"`
577
+ * - **With namespace**: `"namespace-cleankey"`
578
+ * - **Invalid input**: `""` (empty string)
579
+ *
580
+ * @param key - The raw key string to sanitize (optional)
581
+ *
582
+ * @returns The sanitized key string ready for storage operations, or empty string if input is invalid
583
+ *
584
+ * @example
585
+ * ```typescript
586
+ * // Basic key sanitization
587
+ * const clean1 = Manager.sanitizeKey("userToken");
588
+ * console.log(clean1); // "userToken"
589
+ *
590
+ * const clean2 = Manager.sanitizeKey("user profile");
591
+ * console.log(clean2); // "userprofile"
592
+ *
593
+ * const clean3 = Manager.sanitizeKey(" spaced key ");
594
+ * console.log(clean3); // "spacedkey"
595
+ * ```
596
+ *
597
+ * @example
598
+ * ```typescript
599
+ * // Namespace application
600
+ * Manager.keyNamespace = "myapp";
601
+ *
602
+ * const key1 = Manager.sanitizeKey("settings");
603
+ * console.log(key1); // "myapp-settings"
604
+ *
605
+ * const key2 = Manager.sanitizeKey("user preferences");
606
+ * console.log(key2); // "myapp-userpreferences"
607
+ *
608
+ * const key3 = Manager.sanitizeKey("cache data");
609
+ * console.log(key3); // "myapp-cachedata"
610
+ * ```
611
+ *
612
+ * @example
613
+ * ```typescript
614
+ * // Invalid input handling
615
+ * const invalid1 = Manager.sanitizeKey("");
616
+ * console.log(invalid1); // ""
617
+ *
618
+ * const invalid2 = Manager.sanitizeKey(null);
619
+ * console.log(invalid2); // ""
620
+ *
621
+ * const invalid3 = Manager.sanitizeKey(undefined);
622
+ * console.log(invalid3); // ""
623
+ *
624
+ * const invalid4 = Manager.sanitizeKey(" ");
625
+ * console.log(invalid4); // ""
626
+ * ```
627
+ *
628
+ * @example
629
+ * ```typescript
630
+ * // Complex whitespace handling
631
+ * const complex1 = Manager.sanitizeKey("user\tprofile\ndata");
632
+ * console.log(complex1); // "userprofiledata"
633
+ *
634
+ * const complex2 = Manager.sanitizeKey("multi space key");
635
+ * console.log(complex2); // "multispacekey"
636
+ *
637
+ * const complex3 = Manager.sanitizeKey(" \t\n mixed \r\n whitespace \t ");
638
+ * console.log(complex3); // "mixedwhitespace"
639
+ * ```
640
+ *
641
+ * @example
642
+ * ```typescript
643
+ * // Usage in custom storage operations
644
+ * class CustomStorage {
645
+ * static setWithMetadata(key: string, value: any, metadata: object) {
646
+ * const cleanKey = Manager.sanitizeKey(key);
647
+ * const metaKey = Manager.sanitizeKey(`${key}_meta`);
648
+ *
649
+ * Session.set(cleanKey, value);
650
+ * Session.set(metaKey, metadata);
651
+ * }
652
+ *
653
+ * static getWithMetadata(key: string) {
654
+ * const cleanKey = Manager.sanitizeKey(key);
655
+ * const metaKey = Manager.sanitizeKey(`${key}_meta`);
656
+ *
657
+ * return {
658
+ * value: Session.get(cleanKey),
659
+ * metadata: Session.get(metaKey)
660
+ * };
661
+ * }
662
+ * }
663
+ *
664
+ * // Usage
665
+ * Manager.keyNamespace = "app";
666
+ * CustomStorage.setWithMetadata("user data", userData, { created: Date.now() });
667
+ * // Stores: "app-userdata" and "app-userdata_meta"
668
+ *
669
+ * const result = CustomStorage.getWithMetadata("user data");
670
+ * console.log(result.value, result.metadata);
671
+ * ```
672
+ *
673
+ * @example
674
+ * ```typescript
675
+ * // Key collision prevention
676
+ * class StorageKeyManager {
677
+ * static generateUniqueKey(baseKey: string, identifier: string): string {
678
+ * const timestamp = Date.now();
679
+ * const randomSuffix = Math.random().toString(36).substr(2, 9);
680
+ * const rawKey = `${baseKey}_${identifier}_${timestamp}_${randomSuffix}`;
681
+ *
682
+ * return Manager.sanitizeKey(rawKey);
683
+ * }
684
+ *
685
+ * static isKeyValid(key: string): boolean {
686
+ * const sanitized = Manager.sanitizeKey(key);
687
+ * return sanitized.length > 0 && sanitized === Manager.sanitizeKey(sanitized);
688
+ * }
689
+ * }
690
+ *
691
+ * // Usage
692
+ * const uniqueKey = StorageKeyManager.generateUniqueKey("temp cache", "user123");
693
+ * console.log(uniqueKey); // "namespace-tempcache_user123_1642123456789_abc123def"
694
+ *
695
+ * console.log(StorageKeyManager.isKeyValid("valid key")); // true
696
+ * console.log(StorageKeyManager.isKeyValid("")); // false
697
+ * ```
698
+ *
699
+ * @example
700
+ * ```typescript
701
+ * // Debugging key transformations
702
+ * function debugKeySanitization(rawKey: string) {
703
+ * console.log('=== Key Sanitization Debug ===');
704
+ * console.log('Input:', JSON.stringify(rawKey));
705
+ * console.log('Current namespace:', Manager.keyNamespace);
706
+ *
707
+ * const sanitized = Manager.sanitizeKey(rawKey);
708
+ * console.log('Output:', JSON.stringify(sanitized));
709
+ *
710
+ * const steps = {
711
+ * 'Original': rawKey,
712
+ * 'After trim': rawKey?.trim(),
713
+ * 'After whitespace removal': rawKey?.trim().replace(/\s+/g, ""),
714
+ * 'With namespace': sanitized
715
+ * };
716
+ *
717
+ * Object.entries(steps).forEach(([step, value]) => {
718
+ * console.log(`${step}: "${value}"`);
719
+ * });
720
+ * }
721
+ *
722
+ * // Usage
723
+ * Manager.keyNamespace = "debug";
724
+ * debugKeySanitization(" test key with spaces ");
725
+ * ```
726
+ *
727
+ * @see {@link keyNamespace} - The namespace property applied to keys
728
+ * @see {@link isNonNullString} - Validation function for key input
729
+ * @see {@link Session.set} - Method that uses sanitized keys for storage
730
+ * @see {@link Session.get} - Method that uses sanitized keys for retrieval
731
+ * @see {@link sanitizeKey} - Standalone function wrapper for this method
732
+ *
733
+ *
734
+ * @public
735
+ *
736
+ * @remarks
737
+ * **Key Behavior Notes:**
738
+ * - All whitespace characters (spaces, tabs, newlines, etc.) are completely removed
739
+ * - The method is case-sensitive - no case transformation is performed
740
+ * - Namespace application is automatic when a namespace is set
741
+ * - Empty or invalid inputs always return an empty string
742
+ * - The method is idempotent - sanitizing a sanitized key produces the same result
743
+ *
744
+ * **Performance Characteristics:**
745
+ * - Very fast operation, primarily string manipulation
746
+ * - No external dependencies or async operations
747
+ * - Minimal memory allocation for most inputs
748
+ * - Regex operations are optimized for common whitespace patterns
749
+ *
750
+ * **Integration Points:**
751
+ * - Called automatically by all Session storage methods
752
+ * - Used by the standalone {@link sanitizeKey} function
753
+ * - Can be called directly for key validation or preview
754
+ * - Essential for custom storage implementations
755
+ *
756
+ * **Whitespace Handling:**
757
+ * - **Spaces**: ` ` → removed
758
+ * - **Tabs**: `\t` → removed
759
+ * - **Newlines**: `\n`, `\r\n` → removed
760
+ * - **Form feeds**: `\f` → removed
761
+ * - **Vertical tabs**: `\v` → removed
762
+ * - **Unicode whitespace**: Various Unicode space characters → removed
763
+ */
764
+ static sanitizeKey(key?: string): string;
765
+ }
766
+ /**
767
+ * Sanitizes a string for session storage.
768
+ *
769
+ * This function trims and removes whitespace from the key, and adds the namespace prefix if set.
770
+ * \nExample
771
+ * ```typescript
772
+ Manager.keyNamespace = "my-prefix";
773
+ const prefixedKey = sanitizeKey("my-key");
774
+ console.log(prefixedKey); // "my-prefix-my-key"
775
+ * ````
776
+ * @param {string} key - The key to sanitize.
777
+ * @returns {string} The sanitized key.
778
+ */
779
+ declare function sanitizeKey(key: string): string;
780
+ /**
781
+ * Interface for a session storage object.
782
+ *
783
+ * This interface defines the methods for setting, getting, and removing values from a session storage object.
784
+ */
785
+ export interface SessionStorage {
786
+ /**
787
+ * Sets a value in the session storage object.
788
+ *
789
+ * @param {string} key - The key to set the value for.
790
+ * @param {any} value - The value to set.
791
+ * @param {boolean} [decycle] - Optional parameter to decycle the value.
792
+ * @returns {any} The set value.
793
+ */
794
+ set: (key: string, value: any, decycle?: boolean) => any;
795
+ /**
796
+ * Gets a value from the session storage object.
797
+ *
798
+ * @param {string} key - The key to get the value for.
799
+ * @returns {any} The value associated with the key.
800
+ */
801
+ get: (key: string) => any;
802
+ /**
803
+ * Removes a value from the session storage object.
804
+ *
805
+ * @param {string} key - The key to remove the value for.
806
+ * @returns {any} The removed value.
807
+ */
808
+ remove: (key: string) => any;
809
+ /**
810
+ * Removes all values from the session storage object.
811
+ *
812
+ */
813
+ removeAll: () => any;
814
+ }
815
+ /**
816
+ * Session management utilities providing comprehensive storage operations with automatic serialization and namespace support.
817
+ *
818
+ * The Session object serves as the primary interface for all session storage operations in the application.
819
+ * It provides a clean, consistent API that abstracts away the complexity of different storage backends while
820
+ * offering advanced features like automatic JSON serialization, key sanitization, namespace management,
821
+ * and support for both synchronous and asynchronous storage operations.
822
+ *
823
+ * ### Core Features:
824
+ * - **Automatic Serialization**: JSON serialization/deserialization with decycling support
825
+ * - **Key Sanitization**: Automatic key cleaning and namespace prefixing
826
+ * - **Storage Abstraction**: Works with any storage backend implementing SessionStorage
827
+ * - **Type Safety**: Full TypeScript support with intelligent type inference
828
+ * - **Async Support**: Seamless handling of both sync and async storage operations
829
+ * - **Error Resilience**: Graceful handling of storage failures and edge cases
830
+ *
831
+ * @namespace Session
832
+ *
833
+ * @public
834
+ */
835
+ export declare const Session: {
836
+ get: (key: string) => any;
837
+ /**
838
+ * Stores a value in session storage with automatic serialization and key sanitization.
839
+ *
840
+ * This method is the primary interface for persisting data to session storage. It provides
841
+ * intelligent handling of complex data types through JSON serialization, automatic key
842
+ * sanitization with namespace support, and optional object decycling to handle circular
843
+ * references safely.
844
+ *
845
+ * The method leverages the configured storage backend through the Manager, ensuring that
846
+ * your data is stored consistently regardless of whether you're using localStorage,
847
+ * sessionStorage, IndexedDB, or a custom storage implementation.
848
+ *
849
+ * ### Key Processing Pipeline:
850
+ * 1. **Key Sanitization**: Applies {@link sanitizeKey} to clean and prefix the key
851
+ * 2. **Value Processing**: Uses {@link handleSetValue} for JSON serialization
852
+ * 3. **Storage Delegation**: Passes processed data to the configured storage backend
853
+ * 4. **Result Return**: Returns the result from the underlying storage operation
854
+ *
855
+ * ### Serialization Features:
856
+ * - **JSON Serialization**: Converts objects, arrays, and primitives to JSON strings
857
+ * - **Circular Reference Handling**: Optional decycling prevents infinite recursion
858
+ * - **Type Preservation**: Maintains data types through intelligent parsing on retrieval
859
+ * - **Null/Undefined Handling**: Graceful handling of empty values
860
+ *
861
+ * @param key - The storage key identifier for the value
862
+ * @param value - The data to store (objects, arrays, primitives, etc.)
863
+ * @param decycle - Whether to remove circular references during serialization
864
+ *
865
+ * @returns The result of the storage operation (implementation-dependent)
866
+ *
867
+ * @example
868
+ * ```typescript
869
+ * // Basic primitive value storage
870
+ * Session.set('username', 'john_doe');
871
+ * Session.set('user_id', 12345);
872
+ * Session.set('is_authenticated', true);
873
+ * Session.set('last_login', new Date());
874
+ *
875
+ * console.log(Session.get('username')); // 'john_doe'
876
+ * console.log(Session.get('user_id')); // 12345
877
+ * console.log(Session.get('is_authenticated')); // true
878
+ * ```
879
+ *
880
+ * @example
881
+ * ```typescript
882
+ * // Complex object storage with automatic serialization
883
+ * const userProfile = {
884
+ * id: 1001,
885
+ * name: 'Alice Johnson',
886
+ * email: 'alice@example.com',
887
+ * preferences: {
888
+ * theme: 'dark',
889
+ * language: 'en',
890
+ * notifications: {
891
+ * email: true,
892
+ * push: false,
893
+ * sms: true
894
+ * }
895
+ * },
896
+ * roles: ['user', 'moderator'],
897
+ * metadata: {
898
+ * created_at: '2023-01-15T10:30:00Z',
899
+ * last_updated: '2023-07-20T14:45:30Z'
900
+ * }
901
+ * };
902
+ *
903
+ * // Store complex object - automatically serialized
904
+ * Session.set('user_profile', userProfile);
905
+ *
906
+ * // Retrieve and use - automatically deserialized
907
+ * const retrievedProfile = Session.get('user_profile');
908
+ * console.log(retrievedProfile.name); // 'Alice Johnson'
909
+ * console.log(retrievedProfile.preferences.theme); // 'dark'
910
+ * console.log(retrievedProfile.roles.length); // 2
911
+ * ```
912
+ *
913
+ * @example
914
+ * ```typescript
915
+ * // Array storage and manipulation
916
+ * const shoppingCart = [
917
+ * { id: 'prod1', name: 'Laptop', price: 999.99, quantity: 1 },
918
+ * { id: 'prod2', name: 'Mouse', price: 29.99, quantity: 2 },
919
+ * { id: 'prod3', name: 'Keyboard', price: 79.99, quantity: 1 }
920
+ * ];
921
+ *
922
+ * Session.set('shopping_cart', shoppingCart);
923
+ *
924
+ * // Retrieve and work with array
925
+ * const cart = Session.get('shopping_cart');
926
+ * const totalItems = cart.reduce((sum, item) => sum + item.quantity, 0);
927
+ * const totalPrice = cart.reduce((sum, item) => sum + (item.price * item.quantity), 0);
928
+ *
929
+ * console.log(`Cart has ${totalItems} items, total: $${totalPrice.toFixed(2)}`);
930
+ * ```
931
+ *
932
+ * @example
933
+ * ```typescript
934
+ * // Handling circular references with decycling
935
+ * interface Node {
936
+ * id: string;
937
+ * name: string;
938
+ * parent?: Node;
939
+ * children: Node[];
940
+ * }
941
+ *
942
+ * const parentNode: Node = {
943
+ * id: 'parent',
944
+ * name: 'Parent Node',
945
+ * children: []
946
+ * };
947
+ *
948
+ * const childNode: Node = {
949
+ * id: 'child',
950
+ * name: 'Child Node',
951
+ * parent: parentNode,
952
+ * children: []
953
+ * };
954
+ *
955
+ * parentNode.children.push(childNode);
956
+ *
957
+ * // Store with decycling enabled (default) to handle circular reference
958
+ * Session.set('node_tree', parentNode, true);
959
+ *
960
+ * // Store without decycling (use with caution for circular data)
961
+ * // Session.set('node_tree', parentNode, false); // May cause errors
962
+ * ```
963
+ *
964
+ * @example
965
+ * ```typescript
966
+ * // Application state management
967
+ * interface AppState {
968
+ * currentView: 'dashboard' | 'profile' | 'settings';
969
+ * user: {
970
+ * id: number;
971
+ * name: string;
972
+ * permissions: string[];
973
+ * };
974
+ * uiState: {
975
+ * sidebarCollapsed: boolean;
976
+ * activeTab: string;
977
+ * filters: Record<string, any>;
978
+ * };
979
+ * }
980
+ *
981
+ * const appState: AppState = {
982
+ * currentView: 'dashboard',
983
+ * user: {
984
+ * id: 123,
985
+ * name: 'John Doe',
986
+ * permissions: ['read', 'write', 'admin']
987
+ * },
988
+ * uiState: {
989
+ * sidebarCollapsed: false,
990
+ * activeTab: 'overview',
991
+ * filters: {
992
+ * dateRange: '30days',
993
+ * category: 'all',
994
+ * status: 'active'
995
+ * }
996
+ * }
997
+ * };
998
+ *
999
+ * // Persist entire application state
1000
+ * Session.set('app_state', appState);
1001
+ *
1002
+ * // Later, restore application state
1003
+ * const restoredState = Session.get('app_state') as AppState;
1004
+ * if (restoredState) {
1005
+ * console.log(`Welcome back, ${restoredState.user.name}!`);
1006
+ * console.log(`Current view: ${restoredState.currentView}`);
1007
+ * }
1008
+ * ```
1009
+ *
1010
+ * @example
1011
+ * ```typescript
1012
+ * // Form data persistence for better UX
1013
+ * interface FormData {
1014
+ * personalInfo: {
1015
+ * firstName: string;
1016
+ * lastName: string;
1017
+ * email: string;
1018
+ * phone: string;
1019
+ * };
1020
+ * address: {
1021
+ * street: string;
1022
+ * city: string;
1023
+ * state: string;
1024
+ * zipCode: string;
1025
+ * };
1026
+ * preferences: {
1027
+ * newsletter: boolean;
1028
+ * notifications: boolean;
1029
+ * };
1030
+ * }
1031
+ *
1032
+ * // Save form data as user types (draft functionality)
1033
+ * function saveFormDraft(formData: Partial<FormData>) {
1034
+ * const existingDraft = Session.get('form_draft') || {};
1035
+ * const updatedDraft = { ...existingDraft, ...formData };
1036
+ * Session.set('form_draft', updatedDraft);
1037
+ * console.log('Draft saved automatically');
1038
+ * }
1039
+ *
1040
+ * // Restore form data when user returns
1041
+ * function restoreFormDraft(): Partial<FormData> | null {
1042
+ * return Session.get('form_draft');
1043
+ * }
1044
+ *
1045
+ * // Clear draft after successful submission
1046
+ * function clearFormDraft() {
1047
+ * Session.remove('form_draft');
1048
+ * }
1049
+ * ```
1050
+ *
1051
+ * @example
1052
+ * ```typescript
1053
+ * // Configuration and settings management
1054
+ * interface UserSettings {
1055
+ * appearance: {
1056
+ * theme: 'light' | 'dark' | 'auto';
1057
+ * fontSize: 'small' | 'medium' | 'large';
1058
+ * accentColor: string;
1059
+ * };
1060
+ * behavior: {
1061
+ * autoSave: boolean;
1062
+ * confirmDeletes: boolean;
1063
+ * showTooltips: boolean;
1064
+ * };
1065
+ * privacy: {
1066
+ * shareUsageData: boolean;
1067
+ * allowCookies: boolean;
1068
+ * };
1069
+ * }
1070
+ *
1071
+ * const defaultSettings: UserSettings = {
1072
+ * appearance: {
1073
+ * theme: 'auto',
1074
+ * fontSize: 'medium',
1075
+ * accentColor: '#007bff'
1076
+ * },
1077
+ * behavior: {
1078
+ * autoSave: true,
1079
+ * confirmDeletes: true,
1080
+ * showTooltips: true
1081
+ * },
1082
+ * privacy: {
1083
+ * shareUsageData: false,
1084
+ * allowCookies: true
1085
+ * }
1086
+ * };
1087
+ *
1088
+ * // Initialize or update settings
1089
+ * function updateUserSettings(newSettings: Partial<UserSettings>) {
1090
+ * const currentSettings = Session.get('user_settings') || defaultSettings;
1091
+ * const mergedSettings = deepMerge(currentSettings, newSettings);
1092
+ * Session.set('user_settings', mergedSettings);
1093
+ * return mergedSettings;
1094
+ * }
1095
+ *
1096
+ * // Helper function for deep merging
1097
+ * function deepMerge(target: any, source: any): any {
1098
+ * const result = { ...target };
1099
+ * for (const key in source) {
1100
+ * if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
1101
+ * result[key] = deepMerge(target[key] || {}, source[key]);
1102
+ * } else {
1103
+ * result[key] = source[key];
1104
+ * }
1105
+ * }
1106
+ * return result;
1107
+ * }
1108
+ * ```
1109
+ *
1110
+ * @example
1111
+ * ```typescript
1112
+ * // Cache management for API responses
1113
+ * interface CacheEntry<T> {
1114
+ * data: T;
1115
+ * timestamp: number;
1116
+ * ttl: number; // time to live in milliseconds
1117
+ * }
1118
+ *
1119
+ * function setCachedData<T>(key: string, data: T, ttlMinutes: number = 30) {
1120
+ * const cacheEntry: CacheEntry<T> = {
1121
+ * data,
1122
+ * timestamp: Date.now(),
1123
+ * ttl: ttlMinutes * 60 * 1000
1124
+ * };
1125
+ *
1126
+ * Session.set(`cache_${key}`, cacheEntry);
1127
+ * console.log(`Cached data for ${key} (TTL: ${ttlMinutes} minutes)`);
1128
+ * }
1129
+ *
1130
+ * function getCachedData<T>(key: string): T | null {
1131
+ * const cacheEntry = Session.get(`cache_${key}`) as CacheEntry<T>;
1132
+ *
1133
+ * if (!cacheEntry) return null;
1134
+ *
1135
+ * const isExpired = Date.now() - cacheEntry.timestamp > cacheEntry.ttl;
1136
+ * if (isExpired) {
1137
+ * Session.remove(`cache_${key}`);
1138
+ * return null;
1139
+ * }
1140
+ *
1141
+ * return cacheEntry.data;
1142
+ * }
1143
+ *
1144
+ * // Usage example
1145
+ * interface User {
1146
+ * id: number;
1147
+ * name: string;
1148
+ * email: string;
1149
+ * }
1150
+ *
1151
+ * async function fetchUser(id: number): Promise<User> {
1152
+ * // Check cache first
1153
+ * const cached = getCachedData<User>(`user_${id}`);
1154
+ * if (cached) {
1155
+ * console.log('Returning cached user data');
1156
+ * return cached;
1157
+ * }
1158
+ *
1159
+ * // Fetch from API
1160
+ * const response = await fetch(`/api/users/${id}`);
1161
+ * const user: User = await response.json();
1162
+ *
1163
+ * // Cache for 15 minutes
1164
+ * setCachedData(`user_${id}`, user, 15);
1165
+ *
1166
+ * return user;
1167
+ * }
1168
+ * ```
1169
+ *
1170
+ * @example
1171
+ * ```typescript
1172
+ * // Advanced usage with namespacing
1173
+ * // Set namespace for application context
1174
+ * Session.Manager.keyNamespace = 'myapp';
1175
+ *
1176
+ * // All keys will be automatically prefixed
1177
+ * Session.set('user_data', { id: 1, name: 'John' });
1178
+ * // Actual key stored: 'myapp-user-data'
1179
+ *
1180
+ * Session.set('app settings', { theme: 'dark' });
1181
+ * // Actual key stored: 'myapp-app-settings' (spaces replaced with hyphens)
1182
+ *
1183
+ * // Switch namespace for different context
1184
+ * Session.Manager.keyNamespace = 'admin';
1185
+ * Session.set('permissions', ['read', 'write', 'delete']);
1186
+ * // Actual key stored: 'admin-permissions'
1187
+ *
1188
+ * // Clear namespace
1189
+ * Session.Manager.keyNamespace = '';
1190
+ * Session.set('global_config', { version: '1.0.0' });
1191
+ * // Actual key stored: 'global-config' (no prefix)
1192
+ * ```
1193
+ *
1194
+ * @see {@link get} - Retrieve values from session storage
1195
+ * @see {@link remove} - Remove specific values from storage
1196
+ * @see {@link removeAll} - Clear all session storage
1197
+ * @see {@link sanitizeKey} - Key sanitization and namespace handling
1198
+ * @see {@link handleSetValue} - Value serialization with decycling support
1199
+ * @see {@link Manager} - Global session manager configuration
1200
+ * @see {@link SessionStorage} - Storage backend interface
1201
+ *
1202
+ *
1203
+ * @public
1204
+ *
1205
+ * @remarks
1206
+ * **Important Implementation Details:**
1207
+ * - Keys are automatically sanitized and may be prefixed with namespace
1208
+ * - Values are JSON-serialized unless they're already strings
1209
+ * - Circular references are handled when decycle is true (default)
1210
+ * - Storage operations depend on the configured storage backend
1211
+ * - Return value format depends on the underlying storage implementation
1212
+ *
1213
+ * **Performance Considerations:**
1214
+ * - **Serialization Overhead**: Large objects take more time to serialize
1215
+ * - **Storage Limits**: Be aware of storage quotas (localStorage ~5-10MB)
1216
+ * - **Key Length**: Very long keys may impact performance
1217
+ * - **Decycling Cost**: Circular reference detection adds processing time
1218
+ *
1219
+ * **Error Handling:**
1220
+ * - Invalid JSON serialization may throw errors
1221
+ * - Storage quota exceeded errors are passed through
1222
+ * - Null/undefined Manager.storage results in no operation
1223
+ * - Circular references without decycling may cause infinite recursion
1224
+ *
1225
+ * **Browser Compatibility:**
1226
+ * - Works with any storage backend implementing SessionStorage
1227
+ * - JSON serialization uses native JSON.stringify/parse
1228
+ * - No dependencies on specific browser APIs
1229
+ * - Graceful degradation when storage is unavailable
1230
+ */
1231
+ set: (key: string, value: any, decycle?: boolean) => any;
1232
+ remove: (key: string) => any;
1233
+ handleGetValue: any;
1234
+ sanitizeKey: typeof sanitizeKey;
1235
+ handleSetValue: (value: any, decycle?: boolean) => any;
1236
+ isValidStorage: (storage?: SessionStorage) => boolean;
1237
+ Manager: typeof Manager;
1238
+ removeAll: () => any;
1239
+ };
1240
+ /**
1241
+ * Class decorator that attaches a custom session storage implementation to the global session Manager.
1242
+ *
1243
+ * This decorator provides a clean and declarative way to register custom storage implementations
1244
+ * that will be used throughout the application for session management. When applied to a class,
1245
+ * it automatically instantiates the class and registers it as the global storage provider.
1246
+ *
1247
+ * The decorator implements the Dependency Injection pattern for storage providers, allowing
1248
+ * applications to easily swap between different storage implementations (localStorage,
1249
+ * sessionStorage, IndexedDB, in-memory storage, etc.) without changing the core session logic.
1250
+ *
1251
+ * ### Features:
1252
+ * - **Automatic Registration**: Instantiates and registers the storage class automatically
1253
+ * - **Validation**: Ensures the storage implementation meets the required interface
1254
+ * - **Error Handling**: Gracefully handles instantiation failures
1255
+ * - **Type Safety**: Enforces SessionStorage interface compliance at compile time
1256
+ * - **Global Scope**: Makes the storage available throughout the entire application
1257
+ *
1258
+ * ### Storage Requirements:
1259
+ * The decorated class must implement the {@link SessionStorage} interface with these methods:
1260
+ * - `get(key: string): any` - Retrieve a value by key
1261
+ * - `set(key: string, value: any, decycle?: boolean): any` - Store a value with optional decycling
1262
+ * - `remove(key: string): any` - Remove a value by key
1263
+ * - `removeAll(): any` - Clear all stored values
1264
+ *
1265
+ * @decorator
1266
+ * @param target - The class constructor that implements {@link SessionStorage}
1267
+ *
1268
+ * @returns A class decorator function that registers the storage implementation
1269
+ *
1270
+ * @throws {Error} Logs error to console if storage instantiation fails, but doesn't throw
1271
+ *
1272
+ * @example
1273
+ * ```typescript
1274
+ * // Basic localStorage implementation
1275
+ * @AttachSessionStorage()
1276
+ * class LocalStorageProvider implements SessionStorage {
1277
+ * get(key: string): any {
1278
+ * return localStorage.getItem(key);
1279
+ * }
1280
+ *
1281
+ * set(key: string, value: any): any {
1282
+ * localStorage.setItem(key, String(value));
1283
+ * return value;
1284
+ * }
1285
+ *
1286
+ * remove(key: string): any {
1287
+ * const value = this.get(key);
1288
+ * localStorage.removeItem(key);
1289
+ * return value;
1290
+ * }
1291
+ *
1292
+ * removeAll(): any {
1293
+ * localStorage.clear();
1294
+ * }
1295
+ * }
1296
+ *
1297
+ * // Now Session.get(), Session.set(), etc. will use localStorage
1298
+ * Session.set('user', { id: 1, name: 'John' });
1299
+ * const user = Session.get('user'); // Retrieves from localStorage
1300
+ * ```
1301
+ *
1302
+ * @example
1303
+ * ```typescript
1304
+ * // Custom encrypted storage implementation
1305
+ * @AttachSessionStorage()
1306
+ * class EncryptedStorageProvider implements SessionStorage {
1307
+ * private encrypt(value: string): string {
1308
+ * // Your encryption logic here
1309
+ * return btoa(value); // Simple base64 for demo
1310
+ * }
1311
+ *
1312
+ * private decrypt(value: string): string {
1313
+ * // Your decryption logic here
1314
+ * return atob(value); // Simple base64 decode for demo
1315
+ * }
1316
+ *
1317
+ * get(key: string): any {
1318
+ * const encrypted = localStorage.getItem(key);
1319
+ * return encrypted ? this.decrypt(encrypted) : null;
1320
+ * }
1321
+ *
1322
+ * set(key: string, value: any): any {
1323
+ * const encrypted = this.encrypt(String(value));
1324
+ * localStorage.setItem(key, encrypted);
1325
+ * return value;
1326
+ * }
1327
+ *
1328
+ * remove(key: string): any {
1329
+ * const value = this.get(key);
1330
+ * localStorage.removeItem(key);
1331
+ * return value;
1332
+ * }
1333
+ *
1334
+ * removeAll(): any {
1335
+ * localStorage.clear();
1336
+ * }
1337
+ * }
1338
+ * ```
1339
+ *
1340
+ * @example
1341
+ * ```typescript
1342
+ * // In-memory storage with expiration
1343
+ * @AttachSessionStorage()
1344
+ * class ExpiringMemoryStorage implements SessionStorage {
1345
+ * private storage = new Map<string, { value: any; expires: number }>();
1346
+ *
1347
+ * get(key: string): any {
1348
+ * const item = this.storage.get(key);
1349
+ * if (!item) return null;
1350
+ *
1351
+ * if (Date.now() > item.expires) {
1352
+ * this.storage.delete(key);
1353
+ * return null;
1354
+ * }
1355
+ *
1356
+ * return item.value;
1357
+ * }
1358
+ *
1359
+ * set(key: string, value: any, ttl: number = 3600000): any { // 1 hour default
1360
+ * this.storage.set(key, {
1361
+ * value,
1362
+ * expires: Date.now() + ttl
1363
+ * });
1364
+ * return value;
1365
+ * }
1366
+ *
1367
+ * remove(key: string): any {
1368
+ * const item = this.storage.get(key);
1369
+ * this.storage.delete(key);
1370
+ * return item?.value;
1371
+ * }
1372
+ *
1373
+ * removeAll(): any {
1374
+ * this.storage.clear();
1375
+ * }
1376
+ * }
1377
+ * ```
1378
+ *
1379
+ * @example
1380
+ * ```typescript
1381
+ * // Database-backed storage implementation
1382
+ * @AttachSessionStorage()
1383
+ * class DatabaseStorageProvider implements SessionStorage {
1384
+ * constructor(private db: Database) {}
1385
+ *
1386
+ * async get(key: string): Promise<any> {
1387
+ * const result = await this.db.query('SELECT value FROM sessions WHERE key = ?', [key]);
1388
+ * return result.length ? JSON.parse(result[0].value) : null;
1389
+ * }
1390
+ *
1391
+ * async set(key: string, value: any): Promise<any> {
1392
+ * const serialized = JSON.stringify(value);
1393
+ * await this.db.query(
1394
+ * 'INSERT OR REPLACE INTO sessions (key, value) VALUES (?, ?)',
1395
+ * [key, serialized]
1396
+ * );
1397
+ * return value;
1398
+ * }
1399
+ *
1400
+ * async remove(key: string): Promise<any> {
1401
+ * const value = await this.get(key);
1402
+ * await this.db.query('DELETE FROM sessions WHERE key = ?', [key]);
1403
+ * return value;
1404
+ * }
1405
+ *
1406
+ * async removeAll(): Promise<any> {
1407
+ * await this.db.query('DELETE FROM sessions');
1408
+ * }
1409
+ * }
1410
+ * ```
1411
+ *
1412
+ * @example
1413
+ * ```typescript
1414
+ * // Testing with mock storage
1415
+ * @AttachSessionStorage()
1416
+ * class MockStorageProvider implements SessionStorage {
1417
+ * private mockData = new Map<string, any>();
1418
+ *
1419
+ * get(key: string): any {
1420
+ * console.log(`[MOCK] Getting key: ${key}`);
1421
+ * return this.mockData.get(key);
1422
+ * }
1423
+ *
1424
+ * set(key: string, value: any): any {
1425
+ * console.log(`[MOCK] Setting key: ${key}, value:`, value);
1426
+ * this.mockData.set(key, value);
1427
+ * return value;
1428
+ * }
1429
+ *
1430
+ * remove(key: string): any {
1431
+ * console.log(`[MOCK] Removing key: ${key}`);
1432
+ * const value = this.mockData.get(key);
1433
+ * this.mockData.delete(key);
1434
+ * return value;
1435
+ * }
1436
+ *
1437
+ * removeAll(): any {
1438
+ * console.log(`[MOCK] Clearing all data`);
1439
+ * this.mockData.clear();
1440
+ * }
1441
+ * }
1442
+ * ```
1443
+ *
1444
+ * @see {@link SessionStorage} - The interface that storage implementations must implement
1445
+ * @see {@link Manager} - The session manager that uses the attached storage
1446
+ * @see {@link Session} - The exported session utilities that use the attached storage
1447
+ * @see {@link isValidStorage} - Function used to validate storage implementations
1448
+ *
1449
+ *
1450
+ * @public
1451
+ *
1452
+ * @remarks
1453
+ * **Important Notes:**
1454
+ * - Only one storage implementation can be active at a time
1455
+ * - The decorator should be applied before any session operations are performed
1456
+ * - Storage validation is performed automatically - invalid implementations are ignored
1457
+ * - If no custom storage is attached, the system falls back to localStorage or in-memory storage
1458
+ * - The storage instance is created immediately when the decorator is processed
1459
+ *
1460
+ * **Best Practices:**
1461
+ * - Implement proper error handling in your storage methods
1462
+ * - Consider implementing data serialization/deserialization for complex objects
1463
+ * - Add logging for debugging purposes in development environments
1464
+ * - Use appropriate storage mechanisms based on your application's needs
1465
+ * - Test your storage implementation thoroughly, especially error scenarios
1466
+ *
1467
+ * **Performance Considerations:**
1468
+ * - Storage operations should be fast as they're used frequently
1469
+ * - Consider implementing caching for expensive storage operations
1470
+ * - Be mindful of storage size limits (especially for localStorage)
1471
+ * - Implement cleanup strategies for temporary data
1472
+ */
1473
+ export declare function AttachSessionStorage(): (target: ClassConstructor<SessionStorage>) => void;
1474
+ export {};