@nocios/crudify-ui 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name in all)
10
13
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -28,6 +31,1211 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
31
  ));
29
32
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
33
 
34
+ // src/components/CrudifyLogin/utils/cookies.ts
35
+ var getCookie;
36
+ var init_cookies = __esm({
37
+ "src/components/CrudifyLogin/utils/cookies.ts"() {
38
+ "use strict";
39
+ getCookie = (name) => {
40
+ const match = document.cookie.match(new RegExp("(^|;)\\s*" + name + "=([^;]+)"));
41
+ return match ? match[2] : null;
42
+ };
43
+ }
44
+ });
45
+
46
+ // src/components/CrudifyLogin/utils/secureStorage.ts
47
+ var import_crypto_js, SecureStorage, secureSessionStorage, secureLocalStorage;
48
+ var init_secureStorage = __esm({
49
+ "src/components/CrudifyLogin/utils/secureStorage.ts"() {
50
+ "use strict";
51
+ import_crypto_js = __toESM(require("crypto-js"));
52
+ SecureStorage = class {
53
+ constructor(storageType = "sessionStorage") {
54
+ this.encryptionKey = this.generateEncryptionKey();
55
+ this.storage = storageType === "localStorage" ? window.localStorage : window.sessionStorage;
56
+ }
57
+ generateEncryptionKey() {
58
+ const browserFingerprint = [
59
+ navigator.userAgent,
60
+ navigator.language,
61
+ (/* @__PURE__ */ new Date()).getTimezoneOffset(),
62
+ screen.colorDepth,
63
+ screen.width,
64
+ screen.height,
65
+ "crudify-login"
66
+ ].join("|");
67
+ return import_crypto_js.default.SHA256(browserFingerprint).toString();
68
+ }
69
+ setItem(key, value, expiryMinutes) {
70
+ try {
71
+ const encrypted = import_crypto_js.default.AES.encrypt(value, this.encryptionKey).toString();
72
+ this.storage.setItem(key, encrypted);
73
+ if (expiryMinutes) {
74
+ const expiryTime = (/* @__PURE__ */ new Date()).getTime() + expiryMinutes * 60 * 1e3;
75
+ this.storage.setItem(`${key}_expiry`, expiryTime.toString());
76
+ }
77
+ } catch (error) {
78
+ console.error("Failed to encrypt and store data:", error);
79
+ }
80
+ }
81
+ getItem(key) {
82
+ try {
83
+ const expiryKey = `${key}_expiry`;
84
+ const expiry = this.storage.getItem(expiryKey);
85
+ if (expiry) {
86
+ const expiryTime = parseInt(expiry, 10);
87
+ if ((/* @__PURE__ */ new Date()).getTime() > expiryTime) {
88
+ this.removeItem(key);
89
+ return null;
90
+ }
91
+ }
92
+ const encrypted = this.storage.getItem(key);
93
+ if (!encrypted) return null;
94
+ const decrypted = import_crypto_js.default.AES.decrypt(encrypted, this.encryptionKey);
95
+ const result = decrypted.toString(import_crypto_js.default.enc.Utf8);
96
+ if (!result) {
97
+ console.warn("Failed to decrypt stored data - may be corrupted");
98
+ this.removeItem(key);
99
+ return null;
100
+ }
101
+ return result;
102
+ } catch (error) {
103
+ console.error("Failed to decrypt data:", error);
104
+ this.removeItem(key);
105
+ return null;
106
+ }
107
+ }
108
+ removeItem(key) {
109
+ this.storage.removeItem(key);
110
+ this.storage.removeItem(`${key}_expiry`);
111
+ }
112
+ setToken(token) {
113
+ try {
114
+ const parts = token.split(".");
115
+ if (parts.length === 3) {
116
+ const payload = JSON.parse(atob(parts[1]));
117
+ if (payload.exp) {
118
+ const expiryTime = payload.exp * 1e3;
119
+ const now = (/* @__PURE__ */ new Date()).getTime();
120
+ const minutesUntilExpiry = Math.floor((expiryTime - now) / (60 * 1e3));
121
+ if (minutesUntilExpiry > 0) {
122
+ this.setItem("authToken", token, minutesUntilExpiry);
123
+ return;
124
+ }
125
+ }
126
+ }
127
+ } catch (error) {
128
+ console.warn("Failed to parse token expiry, using default expiry");
129
+ }
130
+ this.setItem("authToken", token, 24 * 60);
131
+ }
132
+ getToken() {
133
+ const token = this.getItem("authToken");
134
+ if (token) {
135
+ try {
136
+ const parts = token.split(".");
137
+ if (parts.length === 3) {
138
+ const payload = JSON.parse(atob(parts[1]));
139
+ if (payload.exp) {
140
+ const now = Math.floor(Date.now() / 1e3);
141
+ if (payload.exp < now) {
142
+ this.removeItem("authToken");
143
+ return null;
144
+ }
145
+ }
146
+ }
147
+ } catch (error) {
148
+ console.warn("Failed to validate token expiry");
149
+ this.removeItem("authToken");
150
+ return null;
151
+ }
152
+ }
153
+ return token;
154
+ }
155
+ };
156
+ secureSessionStorage = new SecureStorage("sessionStorage");
157
+ secureLocalStorage = new SecureStorage("localStorage");
158
+ }
159
+ });
160
+
161
+ // src/core/ConfigurationManager.ts
162
+ var _ConfigurationManager, ConfigurationManager, configurationManager;
163
+ var init_ConfigurationManager = __esm({
164
+ "src/core/ConfigurationManager.ts"() {
165
+ "use strict";
166
+ init_cookies();
167
+ _ConfigurationManager = class _ConfigurationManager {
168
+ constructor() {
169
+ this.resolvedConfig = null;
170
+ this.configError = null;
171
+ }
172
+ /**
173
+ * Singleton pattern to ensure consistent configuration across the app
174
+ */
175
+ static getInstance() {
176
+ if (!_ConfigurationManager.instance) {
177
+ _ConfigurationManager.instance = new _ConfigurationManager();
178
+ }
179
+ return _ConfigurationManager.instance;
180
+ }
181
+ /**
182
+ * Reset the singleton instance (useful for testing)
183
+ */
184
+ static resetInstance() {
185
+ _ConfigurationManager.instance = null;
186
+ }
187
+ /**
188
+ * Resolve configuration from all sources with proper priority
189
+ */
190
+ resolveConfig(propsConfig = {}) {
191
+ if (this.resolvedConfig && this.isConfigStillValid(propsConfig)) {
192
+ return this.resolvedConfig;
193
+ }
194
+ try {
195
+ this.configError = null;
196
+ const envConfig = this.getEnvConfig();
197
+ const cookieConfig = this.getCookieConfig();
198
+ const configSource = {
199
+ env: "default",
200
+ publicApiKey: "default",
201
+ loginActions: "default",
202
+ appName: "default",
203
+ logo: "default",
204
+ colors: "default"
205
+ };
206
+ const env = this.resolveValue("env", propsConfig.env, envConfig.env, cookieConfig.env, "prod", configSource);
207
+ const publicApiKey = this.resolveValue("publicApiKey", propsConfig.publicApiKey, envConfig.publicApiKey, cookieConfig.publicApiKey, void 0, configSource);
208
+ const loginActions = this.resolveValue("loginActions", propsConfig.loginActions, envConfig.loginActions, cookieConfig.loginActions, [], configSource);
209
+ const appName = this.resolveValue("appName", propsConfig.appName, envConfig.appName, cookieConfig.appName, "Crudify App", configSource);
210
+ const logo = this.resolveValue("logo", propsConfig.logo, envConfig.logo, cookieConfig.logo, "", configSource);
211
+ const colors = this.resolveValue("colors", propsConfig.colors, envConfig.colors, cookieConfig.colors, {}, configSource);
212
+ if (!publicApiKey) {
213
+ throw new Error(
214
+ "publicApiKey is required. Provide it via:\n1. Props: <CrudifyDataProvider publicApiKey={...} />\n2. Environment: VITE_TEST_PUBLIC_API_KEY\n3. Cookie: publicApiKey"
215
+ );
216
+ }
217
+ this.resolvedConfig = {
218
+ env,
219
+ publicApiKey,
220
+ loginActions,
221
+ appName,
222
+ logo,
223
+ colors,
224
+ configSource,
225
+ rawConfig: {
226
+ props: propsConfig,
227
+ env: envConfig,
228
+ cookies: cookieConfig
229
+ }
230
+ };
231
+ console.log("\u{1F527} ConfigurationManager - Configuration resolved:", {
232
+ config: {
233
+ env: this.resolvedConfig.env,
234
+ publicApiKey: `${this.resolvedConfig.publicApiKey.substring(0, 8)}...`,
235
+ appName: this.resolvedConfig.appName,
236
+ loginActionsCount: this.resolvedConfig.loginActions.length
237
+ },
238
+ sources: this.resolvedConfig.configSource
239
+ });
240
+ return this.resolvedConfig;
241
+ } catch (error) {
242
+ this.configError = error instanceof Error ? error.message : "Unknown configuration error";
243
+ console.error("\u{1F527} ConfigurationManager - Configuration error:", this.configError);
244
+ this.resolvedConfig = {
245
+ env: "prod",
246
+ publicApiKey: "",
247
+ loginActions: [],
248
+ appName: "Crudify App",
249
+ logo: "",
250
+ colors: {},
251
+ configSource: {
252
+ env: "default",
253
+ publicApiKey: "default",
254
+ loginActions: "default",
255
+ appName: "default",
256
+ logo: "default",
257
+ colors: "default"
258
+ },
259
+ rawConfig: {
260
+ props: propsConfig,
261
+ env: {},
262
+ cookies: {},
263
+ error: this.configError
264
+ }
265
+ };
266
+ return this.resolvedConfig;
267
+ }
268
+ }
269
+ /**
270
+ * Check if current configuration is still valid for the given props
271
+ */
272
+ isConfigStillValid(propsConfig) {
273
+ if (!this.resolvedConfig) return false;
274
+ const currentProps = this.resolvedConfig.rawConfig.props;
275
+ return JSON.stringify(currentProps) === JSON.stringify(propsConfig);
276
+ }
277
+ /**
278
+ * Resolve a single config value with priority and source tracking
279
+ */
280
+ resolveValue(key, propsValue, envValue, cookieValue, defaultValue, configSource) {
281
+ if (propsValue !== void 0) {
282
+ configSource[key] = "props";
283
+ return propsValue;
284
+ }
285
+ if (envValue !== void 0) {
286
+ configSource[key] = "env";
287
+ return envValue;
288
+ }
289
+ if (cookieValue !== void 0) {
290
+ configSource[key] = "cookies";
291
+ return cookieValue;
292
+ }
293
+ configSource[key] = "default";
294
+ return defaultValue;
295
+ }
296
+ /**
297
+ * Get configuration from environment variables
298
+ */
299
+ getEnvConfig() {
300
+ const config = {};
301
+ try {
302
+ } catch (error) {
303
+ console.warn("\u{1F527} ConfigurationManager - Environment variables not available:", error);
304
+ }
305
+ return config;
306
+ }
307
+ /**
308
+ * Get configuration from cookies (multi-tenant support)
309
+ */
310
+ getCookieConfig() {
311
+ const config = {};
312
+ try {
313
+ const env = getCookie("environment");
314
+ if (env && ["dev", "stg", "prod"].includes(env)) {
315
+ config.env = env;
316
+ }
317
+ const publicApiKey = getCookie("publicApiKey");
318
+ if (publicApiKey) {
319
+ config.publicApiKey = publicApiKey;
320
+ }
321
+ const appName = getCookie("appName");
322
+ if (appName) {
323
+ config.appName = appName;
324
+ }
325
+ const loginActions = getCookie("loginActions");
326
+ if (loginActions) {
327
+ config.loginActions = loginActions.split(",").map((action) => action.trim()).filter(Boolean);
328
+ }
329
+ const logo = getCookie("logo");
330
+ if (logo) {
331
+ config.logo = logo;
332
+ }
333
+ const colors = getCookie("colors");
334
+ if (colors) {
335
+ try {
336
+ config.colors = JSON.parse(colors);
337
+ } catch (error) {
338
+ console.warn("\u{1F527} ConfigurationManager - Failed to parse colors from cookie:", error);
339
+ }
340
+ }
341
+ } catch (error) {
342
+ console.warn("\u{1F527} ConfigurationManager - Error reading cookies:", error);
343
+ }
344
+ return config;
345
+ }
346
+ /**
347
+ * Get the current resolved configuration
348
+ */
349
+ getConfig() {
350
+ return this.resolvedConfig;
351
+ }
352
+ /**
353
+ * Get any configuration errors
354
+ */
355
+ getConfigError() {
356
+ return this.configError;
357
+ }
358
+ /**
359
+ * Check if configuration is valid (no errors and has required fields)
360
+ */
361
+ isConfigured() {
362
+ return this.resolvedConfig !== null && this.configError === null && !!this.resolvedConfig.publicApiKey;
363
+ }
364
+ /**
365
+ * Clear the current configuration (useful for testing or reconfiguration)
366
+ */
367
+ clearConfig() {
368
+ this.resolvedConfig = null;
369
+ this.configError = null;
370
+ }
371
+ };
372
+ _ConfigurationManager.instance = null;
373
+ ConfigurationManager = _ConfigurationManager;
374
+ configurationManager = ConfigurationManager.getInstance();
375
+ }
376
+ });
377
+
378
+ // src/core/CrudifyInitializer.ts
379
+ var import_crudify_browser2, _CrudifyInitializer, CrudifyInitializer, crudifyInitializer;
380
+ var init_CrudifyInitializer = __esm({
381
+ "src/core/CrudifyInitializer.ts"() {
382
+ "use strict";
383
+ import_crudify_browser2 = __toESM(require("@nocios/crudify-browser"));
384
+ _CrudifyInitializer = class _CrudifyInitializer {
385
+ constructor() {
386
+ this.state = {
387
+ isInitialized: false,
388
+ isInitializing: false,
389
+ initializationError: null,
390
+ config: null,
391
+ initializationPromise: null
392
+ };
393
+ console.log("\u{1F680} CrudifyInitializer - Instance created");
394
+ }
395
+ /**
396
+ * Singleton pattern to ensure global initialization coordination
397
+ */
398
+ static getInstance() {
399
+ if (!_CrudifyInitializer.instance) {
400
+ _CrudifyInitializer.instance = new _CrudifyInitializer();
401
+ }
402
+ return _CrudifyInitializer.instance;
403
+ }
404
+ /**
405
+ * Reset the singleton instance (useful for testing)
406
+ */
407
+ static resetInstance() {
408
+ _CrudifyInitializer.instance = null;
409
+ }
410
+ /**
411
+ * Initialize crudify with the given configuration
412
+ * This method is idempotent and thread-safe
413
+ */
414
+ async initialize(config) {
415
+ if (this.state.isInitialized && this.isConfigurationSame(config)) {
416
+ console.log("\u{1F680} CrudifyInitializer - Already initialized with same config");
417
+ return;
418
+ }
419
+ if (this.state.isInitializing && this.state.initializationPromise) {
420
+ console.log("\u{1F680} CrudifyInitializer - Waiting for ongoing initialization");
421
+ await this.state.initializationPromise;
422
+ return;
423
+ }
424
+ if (this.state.isInitialized && !this.isConfigurationSame(config)) {
425
+ console.log("\u{1F680} CrudifyInitializer - Configuration changed, re-initializing");
426
+ this.reset();
427
+ }
428
+ this.state.isInitializing = true;
429
+ this.state.initializationError = null;
430
+ this.state.initializationPromise = this.performInitialization(config);
431
+ try {
432
+ await this.state.initializationPromise;
433
+ this.state.isInitialized = true;
434
+ this.state.config = { ...config };
435
+ console.log("\u{1F680} CrudifyInitializer - Initialization completed successfully");
436
+ } catch (error) {
437
+ this.state.initializationError = error instanceof Error ? error.message : "Unknown initialization error";
438
+ console.error("\u{1F680} CrudifyInitializer - Initialization failed:", this.state.initializationError);
439
+ throw error;
440
+ } finally {
441
+ this.state.isInitializing = false;
442
+ this.state.initializationPromise = null;
443
+ }
444
+ }
445
+ /**
446
+ * Perform the actual initialization process
447
+ */
448
+ async performInitialization(config) {
449
+ if (!config.publicApiKey) {
450
+ throw new Error("publicApiKey is required for crudify initialization");
451
+ }
452
+ console.log("\u{1F680} CrudifyInitializer - Starting initialization with config:", {
453
+ env: config.env,
454
+ publicApiKey: `${config.publicApiKey.substring(0, 8)}...`,
455
+ appName: config.appName
456
+ });
457
+ try {
458
+ const environment = config.env || "prod";
459
+ console.log("\u{1F680} CrudifyInitializer - Step 1: Configuring environment:", environment);
460
+ await import_crudify_browser2.default.config(environment);
461
+ console.log("\u{1F680} CrudifyInitializer - Step 2: Initializing with API key");
462
+ await import_crudify_browser2.default.init(config.publicApiKey, "none");
463
+ console.log("\u{1F680} CrudifyInitializer - Step 3: Verifying initialization");
464
+ await this.verifyInitialization();
465
+ console.log("\u{1F680} CrudifyInitializer - All initialization steps completed");
466
+ } catch (error) {
467
+ console.error("\u{1F680} CrudifyInitializer - Initialization failed at step:", error);
468
+ throw new Error(
469
+ `Crudify initialization failed: ${error instanceof Error ? error.message : "Unknown error"}. Please check your configuration (env: ${config.env || "prod"}, publicApiKey: ${config.publicApiKey ? "provided" : "missing"})`
470
+ );
471
+ }
472
+ }
473
+ /**
474
+ * Verify that crudify is properly initialized by checking core methods
475
+ */
476
+ async verifyInitialization() {
477
+ const requiredMethods = ["readItems", "readItem", "createItem", "updateItem", "deleteItem", "login", "transaction"];
478
+ const missingMethods = [];
479
+ for (const method of requiredMethods) {
480
+ if (typeof import_crudify_browser2.default[method] !== "function") {
481
+ missingMethods.push(method);
482
+ }
483
+ }
484
+ if (missingMethods.length > 0) {
485
+ throw new Error(
486
+ `Crudify initialization incomplete. Missing methods: ${missingMethods.join(", ")}. This usually indicates a configuration or network issue.`
487
+ );
488
+ }
489
+ console.log("\u{1F680} CrudifyInitializer - Verification successful (test call skipped for performance)");
490
+ }
491
+ /**
492
+ * Check if the given configuration is the same as the current one
493
+ */
494
+ isConfigurationSame(config) {
495
+ if (!this.state.config) return false;
496
+ return this.state.config.env === config.env && this.state.config.publicApiKey === config.publicApiKey;
497
+ }
498
+ /**
499
+ * Reset the initialization state (useful for testing or configuration changes)
500
+ */
501
+ reset() {
502
+ console.log("\u{1F680} CrudifyInitializer - Resetting initialization state");
503
+ this.state = {
504
+ isInitialized: false,
505
+ isInitializing: false,
506
+ initializationError: null,
507
+ config: null,
508
+ initializationPromise: null
509
+ };
510
+ }
511
+ /**
512
+ * Get the current initialization status
513
+ */
514
+ getStatus() {
515
+ return {
516
+ isInitialized: this.state.isInitialized,
517
+ isInitializing: this.state.isInitializing,
518
+ initializationError: this.state.initializationError,
519
+ config: this.state.config
520
+ };
521
+ }
522
+ /**
523
+ * Check if crudify is ready to use
524
+ */
525
+ isReady() {
526
+ return this.state.isInitialized && !this.state.initializationError;
527
+ }
528
+ /**
529
+ * Get the current initialization error, if any
530
+ */
531
+ getError() {
532
+ return this.state.initializationError;
533
+ }
534
+ /**
535
+ * Force re-initialization (useful when configuration changes)
536
+ */
537
+ async reinitialize(config) {
538
+ console.log("\u{1F680} CrudifyInitializer - Forcing re-initialization");
539
+ this.reset();
540
+ await this.initialize(config);
541
+ }
542
+ /**
543
+ * Check if initialization is currently in progress
544
+ */
545
+ isInitializing() {
546
+ return this.state.isInitializing;
547
+ }
548
+ /**
549
+ * Wait for any ongoing initialization to complete
550
+ */
551
+ async waitForInitialization() {
552
+ if (this.state.initializationPromise) {
553
+ await this.state.initializationPromise;
554
+ }
555
+ }
556
+ };
557
+ _CrudifyInitializer.instance = null;
558
+ CrudifyInitializer = _CrudifyInitializer;
559
+ crudifyInitializer = CrudifyInitializer.getInstance();
560
+ }
561
+ });
562
+
563
+ // src/utils/jwtUtils.ts
564
+ var decodeJwtSafely, getCurrentUserEmail, isTokenExpired;
565
+ var init_jwtUtils = __esm({
566
+ "src/utils/jwtUtils.ts"() {
567
+ "use strict";
568
+ decodeJwtSafely = (token) => {
569
+ try {
570
+ const parts = token.split(".");
571
+ if (parts.length !== 3) {
572
+ console.warn("Invalid JWT format: token must have 3 parts");
573
+ return null;
574
+ }
575
+ const payload = parts[1];
576
+ const paddedPayload = payload + "=".repeat((4 - payload.length % 4) % 4);
577
+ const decodedPayload = JSON.parse(atob(paddedPayload));
578
+ return decodedPayload;
579
+ } catch (error) {
580
+ console.warn("Failed to decode JWT token:", error);
581
+ return null;
582
+ }
583
+ };
584
+ getCurrentUserEmail = () => {
585
+ try {
586
+ let token = null;
587
+ token = sessionStorage.getItem("authToken");
588
+ console.log("\u{1F50D} getCurrentUserEmail - authToken:", token ? `${token.substring(0, 20)}...` : null);
589
+ if (!token) {
590
+ token = sessionStorage.getItem("token");
591
+ console.log("\u{1F50D} getCurrentUserEmail - token:", token ? `${token.substring(0, 20)}...` : null);
592
+ }
593
+ if (!token) {
594
+ token = localStorage.getItem("authToken") || localStorage.getItem("token");
595
+ console.log("\u{1F50D} getCurrentUserEmail - localStorage:", token ? `${token.substring(0, 20)}...` : null);
596
+ }
597
+ if (!token) {
598
+ console.warn("\u{1F50D} getCurrentUserEmail - No token found in any storage");
599
+ return null;
600
+ }
601
+ const payload = decodeJwtSafely(token);
602
+ if (!payload) {
603
+ console.warn("\u{1F50D} getCurrentUserEmail - Failed to decode token");
604
+ return null;
605
+ }
606
+ const email = payload.email || payload["cognito:username"] || null;
607
+ console.log("\u{1F50D} getCurrentUserEmail - Extracted email:", email);
608
+ return email;
609
+ } catch (error) {
610
+ console.warn("Failed to get current user email:", error);
611
+ return null;
612
+ }
613
+ };
614
+ isTokenExpired = (token) => {
615
+ try {
616
+ const payload = decodeJwtSafely(token);
617
+ if (!payload || !payload.exp) return true;
618
+ const currentTime = Math.floor(Date.now() / 1e3);
619
+ return payload.exp < currentTime;
620
+ } catch {
621
+ return true;
622
+ }
623
+ };
624
+ }
625
+ });
626
+
627
+ // src/core/TokenManager.ts
628
+ var import_crudify_browser3, _TokenManager, TokenManager, tokenManager;
629
+ var init_TokenManager = __esm({
630
+ "src/core/TokenManager.ts"() {
631
+ "use strict";
632
+ import_crudify_browser3 = __toESM(require("@nocios/crudify-browser"));
633
+ init_secureStorage();
634
+ init_jwtUtils();
635
+ _TokenManager = class _TokenManager {
636
+ constructor() {
637
+ this.TOKEN_KEY = "authToken";
638
+ // Compatible with crudia-ui
639
+ this.tokenCache = null;
640
+ this.parsedTokenCache = null;
641
+ this.expirationCheckInterval = null;
642
+ this.storageEventListener = null;
643
+ this.initializeTokenManager();
644
+ }
645
+ /**
646
+ * Singleton pattern to ensure consistent token management
647
+ */
648
+ static getInstance() {
649
+ if (!_TokenManager.instance) {
650
+ _TokenManager.instance = new _TokenManager();
651
+ }
652
+ return _TokenManager.instance;
653
+ }
654
+ /**
655
+ * Reset the singleton instance (useful for testing)
656
+ */
657
+ static resetInstance() {
658
+ if (_TokenManager.instance) {
659
+ _TokenManager.instance.cleanup();
660
+ }
661
+ _TokenManager.instance = null;
662
+ }
663
+ /**
664
+ * Initialize the token manager with storage synchronization
665
+ */
666
+ initializeTokenManager() {
667
+ console.log("\u{1F510} TokenManager - Initializing token management");
668
+ this.migrateFromLocalStorage();
669
+ this.loadTokenFromStorage();
670
+ this.setupExpirationCheck();
671
+ this.setupStorageListener();
672
+ console.log("\u{1F510} TokenManager - Initialization complete");
673
+ }
674
+ /**
675
+ * Migrate tokens from localStorage to sessionStorage for better security
676
+ * This ensures compatibility with older implementations
677
+ */
678
+ migrateFromLocalStorage() {
679
+ try {
680
+ const legacyKeys = ["authToken", "token", "jwt", "jwtToken"];
681
+ for (const key of legacyKeys) {
682
+ const token = localStorage.getItem(key);
683
+ if (token && !secureSessionStorage.getToken()) {
684
+ console.log(`\u{1F510} TokenManager - Migrating token from localStorage key: ${key}`);
685
+ secureSessionStorage.setToken(token);
686
+ localStorage.removeItem(key);
687
+ break;
688
+ }
689
+ }
690
+ } catch (error) {
691
+ console.warn("\u{1F510} TokenManager - Token migration failed:", error);
692
+ }
693
+ }
694
+ /**
695
+ * Load token from storage and synchronize with crudify
696
+ */
697
+ loadTokenFromStorage() {
698
+ console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Entry point - loading token from storage");
699
+ try {
700
+ console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Getting token from secure session storage");
701
+ const storedToken = secureSessionStorage.getToken();
702
+ console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Stored token exists:", !!storedToken);
703
+ if (storedToken && this.isTokenValid(storedToken)) {
704
+ console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Stored token is valid, updating cache");
705
+ this.tokenCache = storedToken;
706
+ this.parsedTokenCache = this.parseToken(storedToken);
707
+ this.syncTokenWithCrudify(storedToken);
708
+ console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Token loaded from storage and synchronized");
709
+ } else if (storedToken) {
710
+ console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Stored token exists but is invalid/expired, clearing");
711
+ this.clearToken();
712
+ } else {
713
+ console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: No stored token found");
714
+ }
715
+ } catch (error) {
716
+ console.warn("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Error loading token from storage:", error);
717
+ this.clearToken();
718
+ }
719
+ }
720
+ /**
721
+ * Set up automatic token expiration checking
722
+ */
723
+ setupExpirationCheck() {
724
+ this.expirationCheckInterval = window.setInterval(() => {
725
+ if (this.tokenCache && !this.isTokenValid(this.tokenCache)) {
726
+ console.log("\u{1F510} TokenManager - Token expired, clearing automatically");
727
+ this.clearToken();
728
+ }
729
+ }, 3e4);
730
+ }
731
+ /**
732
+ * Set up storage event listener for cross-tab synchronization
733
+ */
734
+ setupStorageListener() {
735
+ this.storageEventListener = (event) => {
736
+ if (event.key === this.TOKEN_KEY) {
737
+ console.log("\u{1F510} TokenManager - Token change detected from another tab");
738
+ this.loadTokenFromStorage();
739
+ }
740
+ };
741
+ window.addEventListener("storage", this.storageEventListener);
742
+ }
743
+ /**
744
+ * Set a new JWT token with automatic synchronization
745
+ */
746
+ setToken(token) {
747
+ console.log("\u{1F510} TokenManager - SET_TOKEN: Entry point - setting token:", token ? "provided" : "null");
748
+ try {
749
+ if (!token) {
750
+ console.log("\u{1F510} TokenManager - SET_TOKEN: No token provided, clearing token");
751
+ this.clearToken();
752
+ return;
753
+ }
754
+ console.log("\u{1F510} TokenManager - SET_TOKEN: Validating token before setting");
755
+ if (!this.isTokenValid(token)) {
756
+ console.warn("\u{1F510} TokenManager - SET_TOKEN: Attempted to set invalid or expired token");
757
+ this.clearToken();
758
+ return;
759
+ }
760
+ console.log("\u{1F510} TokenManager - SET_TOKEN: Token is valid, updating cache");
761
+ this.tokenCache = token;
762
+ this.parsedTokenCache = this.parseToken(token);
763
+ console.log("\u{1F510} TokenManager - SET_TOKEN: Storing token in secure storage");
764
+ secureSessionStorage.setToken(token);
765
+ console.log("\u{1F510} TokenManager - SET_TOKEN: Synchronizing with crudify");
766
+ this.syncTokenWithCrudify(token);
767
+ console.log("\u{1F510} TokenManager - SET_TOKEN: Token set and synchronized successfully");
768
+ } catch (error) {
769
+ console.error("\u{1F510} TokenManager - SET_TOKEN: Error setting token:", error);
770
+ this.clearToken();
771
+ }
772
+ }
773
+ /**
774
+ * Get the current JWT token
775
+ */
776
+ getToken() {
777
+ console.log("\u{1F510} TokenManager - GET_TOKEN: Entry point - checking cache");
778
+ if (this.tokenCache) {
779
+ console.log("\u{1F510} TokenManager - GET_TOKEN: Cache exists, validating token");
780
+ if (this.isTokenValid(this.tokenCache)) {
781
+ console.log("\u{1F510} TokenManager - GET_TOKEN: Cache valid, returning cached token");
782
+ return this.tokenCache;
783
+ } else {
784
+ console.log("\u{1F510} TokenManager - GET_TOKEN: Cache invalid, clearing cache");
785
+ this.tokenCache = null;
786
+ }
787
+ } else {
788
+ console.log("\u{1F510} TokenManager - GET_TOKEN: No cache, loading from storage");
789
+ }
790
+ console.log("\u{1F510} TokenManager - GET_TOKEN: Loading from storage");
791
+ this.loadTokenFromStorage();
792
+ console.log("\u{1F510} TokenManager - GET_TOKEN: Returning final token:", !!this.tokenCache);
793
+ return this.tokenCache;
794
+ }
795
+ /**
796
+ * Parse the current JWT token
797
+ */
798
+ parseToken(token) {
799
+ console.log("\u{1F510} TokenManager - PARSE_TOKEN: Entry point - parsing token");
800
+ const targetToken = token !== void 0 ? token : this.tokenCache;
801
+ console.log("\u{1F510} TokenManager - PARSE_TOKEN: Target token exists:", !!targetToken);
802
+ if (!targetToken) {
803
+ console.log("\u{1F510} TokenManager - PARSE_TOKEN: No target token, returning null");
804
+ return null;
805
+ }
806
+ if (this.tokenCache === targetToken && this.parsedTokenCache) {
807
+ console.log("\u{1F510} TokenManager - PARSE_TOKEN: Returning cached parsed token");
808
+ return this.parsedTokenCache;
809
+ }
810
+ console.log("\u{1F510} TokenManager - PARSE_TOKEN: Cache miss, parsing token with decodeJwtSafely");
811
+ const parsed = decodeJwtSafely(targetToken);
812
+ console.log("\u{1F510} TokenManager - PARSE_TOKEN: Token parsed successfully:", !!parsed);
813
+ if (targetToken === this.tokenCache) {
814
+ console.log("\u{1F510} TokenManager - PARSE_TOKEN: Updating parsed token cache");
815
+ this.parsedTokenCache = parsed;
816
+ }
817
+ return parsed;
818
+ }
819
+ /**
820
+ * Check if a token is valid (properly formatted and not expired)
821
+ */
822
+ isTokenValid(token) {
823
+ console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Entry point - checking token validity");
824
+ const targetToken = token !== void 0 ? token : this.tokenCache;
825
+ console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Target token exists:", !!targetToken);
826
+ if (!targetToken) {
827
+ console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: No token, returning false");
828
+ return false;
829
+ }
830
+ try {
831
+ console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Checking if token is expired");
832
+ if (isTokenExpired(targetToken)) {
833
+ console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Token is expired, returning false");
834
+ return false;
835
+ }
836
+ console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Token not expired, checking if can be parsed");
837
+ const parsed = decodeJwtSafely(targetToken);
838
+ const isValid = parsed !== null;
839
+ console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Token parsing result:", isValid);
840
+ return isValid;
841
+ } catch (error) {
842
+ console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Error validating token:", error);
843
+ return false;
844
+ }
845
+ }
846
+ /**
847
+ * Get token expiration time as Date object
848
+ */
849
+ getTokenExpiration() {
850
+ const token = this.getToken();
851
+ if (!token) return null;
852
+ const parsed = this.parseToken(token);
853
+ if (!parsed?.exp) return null;
854
+ return new Date(parsed.exp * 1e3);
855
+ }
856
+ /**
857
+ * Clear the current token from all storages and crudify
858
+ */
859
+ clearToken() {
860
+ console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Entry point - clearing all tokens");
861
+ try {
862
+ console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Clearing cache");
863
+ this.tokenCache = null;
864
+ this.parsedTokenCache = null;
865
+ console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Clearing from secure storage");
866
+ secureSessionStorage.removeItem(this.TOKEN_KEY);
867
+ console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Clearing from crudify");
868
+ import_crudify_browser3.default.setToken("");
869
+ console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Token cleared from all storages successfully");
870
+ } catch (error) {
871
+ console.warn("\u{1F510} TokenManager - CLEAR_TOKEN: Error clearing token:", error);
872
+ }
873
+ }
874
+ /**
875
+ * Synchronize token with crudify library
876
+ */
877
+ syncTokenWithCrudify(token) {
878
+ try {
879
+ import_crudify_browser3.default.setToken(token);
880
+ console.log("\u{1F510} TokenManager - Token synchronized with crudify");
881
+ } catch (error) {
882
+ console.warn("\u{1F510} TokenManager - Failed to sync token with crudify:", error);
883
+ }
884
+ }
885
+ /**
886
+ * Refresh token (placeholder for future implementation)
887
+ */
888
+ async refreshToken() {
889
+ throw new Error("Token refresh not yet implemented");
890
+ }
891
+ /**
892
+ * Get user information from the current token
893
+ */
894
+ getUserInfo() {
895
+ const parsed = this.parseToken();
896
+ if (!parsed) {
897
+ return {
898
+ email: null,
899
+ userId: null,
900
+ userIdentifier: null,
901
+ username: null
902
+ };
903
+ }
904
+ return {
905
+ email: parsed.email || null,
906
+ userId: parsed.sub || null,
907
+ userIdentifier: parsed["cognito:username"] || parsed.email || parsed.sub || null,
908
+ username: parsed["cognito:username"] || null
909
+ };
910
+ }
911
+ /**
912
+ * Check if user is currently authenticated
913
+ */
914
+ isAuthenticated() {
915
+ return this.isTokenValid();
916
+ }
917
+ /**
918
+ * Get time until token expires in minutes
919
+ */
920
+ getTimeUntilExpiration() {
921
+ const expiration = this.getTokenExpiration();
922
+ if (!expiration) return null;
923
+ const now = /* @__PURE__ */ new Date();
924
+ const minutesUntilExpiry = Math.floor((expiration.getTime() - now.getTime()) / (60 * 1e3));
925
+ return Math.max(0, minutesUntilExpiry);
926
+ }
927
+ /**
928
+ * Cleanup resources (call when the component unmounts)
929
+ */
930
+ cleanup() {
931
+ if (this.expirationCheckInterval) {
932
+ window.clearInterval(this.expirationCheckInterval);
933
+ this.expirationCheckInterval = null;
934
+ }
935
+ if (this.storageEventListener) {
936
+ window.removeEventListener("storage", this.storageEventListener);
937
+ this.storageEventListener = null;
938
+ }
939
+ console.log("\u{1F510} TokenManager - Cleanup completed");
940
+ }
941
+ /**
942
+ * Get debug information about the current token state
943
+ */
944
+ getDebugInfo() {
945
+ const token = this.getToken();
946
+ const parsed = this.parseToken();
947
+ const expiration = this.getTokenExpiration();
948
+ return {
949
+ hasToken: !!token,
950
+ tokenLength: token?.length || 0,
951
+ isValid: this.isTokenValid(),
952
+ isAuthenticated: this.isAuthenticated(),
953
+ expiration: expiration?.toISOString() || null,
954
+ minutesUntilExpiry: this.getTimeUntilExpiration(),
955
+ userInfo: this.getUserInfo(),
956
+ parsedTokenKeys: parsed ? Object.keys(parsed) : []
957
+ };
958
+ }
959
+ };
960
+ _TokenManager.instance = null;
961
+ TokenManager = _TokenManager;
962
+ tokenManager = TokenManager.getInstance();
963
+ }
964
+ });
965
+
966
+ // src/providers/CrudifyDataProvider.tsx
967
+ var CrudifyDataProvider_exports = {};
968
+ __export(CrudifyDataProvider_exports, {
969
+ CrudifyDataProvider: () => CrudifyDataProvider,
970
+ configurationManager: () => configurationManager,
971
+ crudifyInitializer: () => crudifyInitializer,
972
+ tokenManager: () => tokenManager,
973
+ useCrudifyDataContext: () => useCrudifyDataContext
974
+ });
975
+ var import_react5, import_jsx_runtime4, CrudifyDataContext, CrudifyDataProvider, useCrudifyDataContext;
976
+ var init_CrudifyDataProvider = __esm({
977
+ "src/providers/CrudifyDataProvider.tsx"() {
978
+ "use strict";
979
+ import_react5 = require("react");
980
+ init_ConfigurationManager();
981
+ init_CrudifyInitializer();
982
+ init_TokenManager();
983
+ import_jsx_runtime4 = require("react/jsx-runtime");
984
+ CrudifyDataContext = (0, import_react5.createContext)(null);
985
+ CrudifyDataProvider = ({
986
+ children,
987
+ env,
988
+ publicApiKey,
989
+ loginActions,
990
+ appName,
991
+ logo,
992
+ colors
993
+ }) => {
994
+ const [config, setConfig] = (0, import_react5.useState)(null);
995
+ const [isConfigured, setIsConfigured] = (0, import_react5.useState)(false);
996
+ const [configError, setConfigError] = (0, import_react5.useState)(null);
997
+ const [isInitialized, setIsInitialized] = (0, import_react5.useState)(false);
998
+ const [isInitializing, setIsInitializing] = (0, import_react5.useState)(false);
999
+ const [initializationError, setInitializationError] = (0, import_react5.useState)(null);
1000
+ const [isAuthenticated, setIsAuthenticated] = (0, import_react5.useState)(false);
1001
+ const [token, setTokenState] = (0, import_react5.useState)(null);
1002
+ const [user, setUser] = (0, import_react5.useState)(null);
1003
+ const [tokenExpiration, setTokenExpiration] = (0, import_react5.useState)(null);
1004
+ const initializeConfiguration = (0, import_react5.useCallback)(() => {
1005
+ try {
1006
+ console.log("\u{1F30D} CrudifyDataProvider - Initializing configuration");
1007
+ const propsConfig = {
1008
+ env,
1009
+ publicApiKey,
1010
+ loginActions,
1011
+ appName,
1012
+ logo,
1013
+ colors
1014
+ };
1015
+ const resolvedConfig = configurationManager.resolveConfig(propsConfig);
1016
+ const error = configurationManager.getConfigError();
1017
+ setConfig(resolvedConfig);
1018
+ setConfigError(error);
1019
+ setIsConfigured(configurationManager.isConfigured());
1020
+ console.log("\u{1F30D} CrudifyDataProvider - Configuration initialized:", {
1021
+ isConfigured: configurationManager.isConfigured(),
1022
+ error,
1023
+ sources: resolvedConfig.configSource
1024
+ });
1025
+ return resolvedConfig;
1026
+ } catch (error) {
1027
+ const errorMessage = error instanceof Error ? error.message : "Configuration initialization failed";
1028
+ console.error("\u{1F30D} CrudifyDataProvider - Configuration error:", errorMessage);
1029
+ setConfigError(errorMessage);
1030
+ setIsConfigured(false);
1031
+ return null;
1032
+ }
1033
+ }, [env, publicApiKey, loginActions, appName, logo, colors]);
1034
+ const initializeCrudify = (0, import_react5.useCallback)(async (resolvedConfig) => {
1035
+ if (!resolvedConfig || !resolvedConfig.publicApiKey) {
1036
+ setInitializationError("Cannot initialize crudify without valid configuration");
1037
+ return;
1038
+ }
1039
+ try {
1040
+ setIsInitializing(true);
1041
+ setInitializationError(null);
1042
+ console.log("\u{1F680} CrudifyDataProvider - Starting crudify initialization");
1043
+ await crudifyInitializer.initialize({
1044
+ env: resolvedConfig.env,
1045
+ publicApiKey: resolvedConfig.publicApiKey,
1046
+ loginActions: resolvedConfig.loginActions,
1047
+ appName: resolvedConfig.appName,
1048
+ logo: resolvedConfig.logo,
1049
+ colors: resolvedConfig.colors
1050
+ });
1051
+ setIsInitialized(true);
1052
+ console.log("\u{1F680} CrudifyDataProvider - Crudify initialization completed");
1053
+ } catch (error) {
1054
+ const errorMessage = error instanceof Error ? error.message : "Crudify initialization failed";
1055
+ console.error("\u{1F680} CrudifyDataProvider - Initialization error:", errorMessage);
1056
+ setInitializationError(errorMessage);
1057
+ setIsInitialized(false);
1058
+ } finally {
1059
+ setIsInitializing(false);
1060
+ }
1061
+ }, []);
1062
+ const updateAuthenticationState = (0, import_react5.useCallback)(() => {
1063
+ console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Starting authentication state update");
1064
+ try {
1065
+ console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Getting token from TokenManager");
1066
+ const currentToken = tokenManager.getToken();
1067
+ console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Token retrieved:", !!currentToken);
1068
+ console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Parsing token");
1069
+ const parsedUser = tokenManager.parseToken();
1070
+ console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Token parsed:", !!parsedUser);
1071
+ console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Getting expiration");
1072
+ const expiration = tokenManager.getTokenExpiration();
1073
+ console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Expiration retrieved:", !!expiration);
1074
+ console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Checking authentication");
1075
+ const authenticated = tokenManager.isAuthenticated();
1076
+ console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Authentication checked:", authenticated);
1077
+ console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Updating state variables");
1078
+ setTokenState(currentToken);
1079
+ setUser(parsedUser);
1080
+ setTokenExpiration(expiration);
1081
+ setIsAuthenticated(authenticated);
1082
+ console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Authentication state updated successfully:", {
1083
+ hasToken: !!currentToken,
1084
+ isAuthenticated: authenticated,
1085
+ userEmail: parsedUser?.email || null,
1086
+ expiration: expiration?.toISOString() || null
1087
+ });
1088
+ } catch (error) {
1089
+ console.error("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Error updating authentication state:", error);
1090
+ }
1091
+ }, []);
1092
+ const setToken = (0, import_react5.useCallback)((newToken) => {
1093
+ console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: ===== STARTING TOKEN SET =====");
1094
+ console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: New token:", newToken ? `${newToken.substring(0, 20)}...` : "null");
1095
+ console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: Setting token in TokenManager...");
1096
+ tokenManager.setToken(newToken);
1097
+ console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: Updating state using newToken directly");
1098
+ if (newToken) {
1099
+ const parsedUser = tokenManager.parseToken(newToken);
1100
+ const expiration = tokenManager.getTokenExpiration();
1101
+ const authenticated = tokenManager.isTokenValid(newToken);
1102
+ console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: Setting state values:");
1103
+ console.log(" - setTokenState:", newToken ? `${newToken.substring(0, 20)}...` : "null");
1104
+ console.log(" - setUser:", parsedUser?.email || "null");
1105
+ console.log(" - setIsAuthenticated:", authenticated);
1106
+ setTokenState(newToken);
1107
+ setUser(parsedUser);
1108
+ setTokenExpiration(expiration);
1109
+ setIsAuthenticated(authenticated);
1110
+ console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: \u2705 Token set, state updated", {
1111
+ hasToken: true,
1112
+ isAuthenticated: authenticated,
1113
+ userEmail: parsedUser?.email || null
1114
+ });
1115
+ } else {
1116
+ console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: Clearing all states");
1117
+ setTokenState(null);
1118
+ setUser(null);
1119
+ setTokenExpiration(null);
1120
+ setIsAuthenticated(false);
1121
+ console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: \u2705 Token cleared, state reset");
1122
+ }
1123
+ console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: ===== TOKEN SET COMPLETE =====");
1124
+ }, []);
1125
+ const logout = (0, import_react5.useCallback)(() => {
1126
+ console.log("\u{1F510} CrudifyDataProvider - LOGOUT_CALLBACK: Logging out user");
1127
+ tokenManager.clearToken();
1128
+ console.log("\u{1F510} CrudifyDataProvider - LOGOUT_CALLBACK: Updating state directly");
1129
+ setTokenState(null);
1130
+ setUser(null);
1131
+ setTokenExpiration(null);
1132
+ setIsAuthenticated(false);
1133
+ console.log("\u{1F510} CrudifyDataProvider - LOGOUT_CALLBACK: User logged out, state cleared");
1134
+ }, []);
1135
+ const refreshConfig = (0, import_react5.useCallback)(() => {
1136
+ console.log("\u{1F30D} CrudifyDataProvider - Refreshing configuration");
1137
+ configurationManager.clearConfig();
1138
+ const newConfig = initializeConfiguration();
1139
+ if (newConfig && newConfig.publicApiKey) {
1140
+ initializeCrudify(newConfig);
1141
+ }
1142
+ }, [initializeConfiguration, initializeCrudify]);
1143
+ const reinitialize = (0, import_react5.useCallback)(async () => {
1144
+ if (!config || !config.publicApiKey) {
1145
+ console.warn("\u{1F680} CrudifyDataProvider - Cannot reinitialize without valid configuration");
1146
+ return;
1147
+ }
1148
+ console.log("\u{1F680} CrudifyDataProvider - Force reinitializing crudify");
1149
+ crudifyInitializer.reset();
1150
+ await initializeCrudify(config);
1151
+ }, [config, initializeCrudify]);
1152
+ const getDebugInfo = (0, import_react5.useCallback)(() => {
1153
+ return {
1154
+ provider: {
1155
+ isConfigured,
1156
+ configError,
1157
+ isInitialized,
1158
+ isInitializing,
1159
+ initializationError,
1160
+ isAuthenticated
1161
+ },
1162
+ configuration: {
1163
+ config: config ? {
1164
+ env: config.env,
1165
+ publicApiKey: `${config.publicApiKey.substring(0, 8)}...`,
1166
+ appName: config.appName,
1167
+ loginActionsCount: config.loginActions.length,
1168
+ hasLogo: !!config.logo,
1169
+ colorsCount: Object.keys(config.colors).length
1170
+ } : null,
1171
+ sources: config?.configSource || null,
1172
+ rawConfig: config?.rawConfig || null
1173
+ },
1174
+ authentication: {
1175
+ hasToken: !!token,
1176
+ tokenLength: token?.length || 0,
1177
+ userEmail: user?.email || null,
1178
+ userId: user?.sub || null,
1179
+ expiration: tokenExpiration?.toISOString() || null,
1180
+ minutesUntilExpiry: tokenManager.getTimeUntilExpiration()
1181
+ },
1182
+ tokenManager: tokenManager.getDebugInfo(),
1183
+ crudifyInitializer: crudifyInitializer.getStatus()
1184
+ };
1185
+ }, [isConfigured, configError, isInitialized, isInitializing, initializationError, isAuthenticated, config, token, user, tokenExpiration]);
1186
+ (0, import_react5.useEffect)(() => {
1187
+ console.log("\u{1F30D} CrudifyDataProvider - Provider mounting, starting initialization");
1188
+ const resolvedConfig = initializeConfiguration();
1189
+ updateAuthenticationState();
1190
+ if (resolvedConfig && resolvedConfig.publicApiKey) {
1191
+ initializeCrudify(resolvedConfig);
1192
+ }
1193
+ return () => {
1194
+ console.log("\u{1F30D} CrudifyDataProvider - Provider unmounting, cleaning up");
1195
+ tokenManager.cleanup();
1196
+ };
1197
+ }, []);
1198
+ (0, import_react5.useEffect)(() => {
1199
+ console.log("\u{1F510} CrudifyDataProvider - INITIAL_AUTH_EFFECT: Loading initial authentication state");
1200
+ updateAuthenticationState();
1201
+ }, []);
1202
+ const contextValue = {
1203
+ // Configuration
1204
+ config,
1205
+ isConfigured,
1206
+ configError,
1207
+ configSource: config ? JSON.stringify(config.configSource) : "none",
1208
+ // Initialization
1209
+ isInitialized,
1210
+ isInitializing,
1211
+ initializationError,
1212
+ // Authentication
1213
+ isAuthenticated,
1214
+ token,
1215
+ user,
1216
+ tokenExpiration,
1217
+ // Actions
1218
+ setToken,
1219
+ logout,
1220
+ refreshConfig,
1221
+ reinitialize,
1222
+ // Debug
1223
+ getDebugInfo
1224
+ };
1225
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CrudifyDataContext.Provider, { value: contextValue, children });
1226
+ };
1227
+ useCrudifyDataContext = () => {
1228
+ const context = (0, import_react5.useContext)(CrudifyDataContext);
1229
+ if (!context) {
1230
+ throw new Error(
1231
+ "useCrudifyDataContext must be used within a CrudifyDataProvider. Make sure to wrap your app with <CrudifyDataProvider>."
1232
+ );
1233
+ }
1234
+ return context;
1235
+ };
1236
+ }
1237
+ });
1238
+
31
1239
  // src/index.ts
32
1240
  var index_exports = {};
33
1241
  __export(index_exports, {
@@ -41,6 +1249,8 @@ __export(index_exports, {
41
1249
  crudifyInitializer: () => crudifyInitializer,
42
1250
  decodeJwtSafely: () => decodeJwtSafely,
43
1251
  getCookie: () => getCookie,
1252
+ getCrudifyInstanceAsync: () => getCrudifyInstanceAsync,
1253
+ getCrudifyInstanceSync: () => getCrudifyInstanceSync,
44
1254
  getCurrentUserEmail: () => getCurrentUserEmail,
45
1255
  getErrorMessage: () => getErrorMessage,
46
1256
  handleCrudifyError: () => handleCrudifyError,
@@ -218,14 +1428,7 @@ var useCrudify = () => {
218
1428
 
219
1429
  // src/components/CrudifyLogin/context/LoginStateProvider.tsx
220
1430
  var import_react4 = require("react");
221
-
222
- // src/components/CrudifyLogin/utils/cookies.ts
223
- var getCookie = (name) => {
224
- const match = document.cookie.match(new RegExp("(^|;)\\s*" + name + "=([^;]+)"));
225
- return match ? match[2] : null;
226
- };
227
-
228
- // src/components/CrudifyLogin/context/LoginStateProvider.tsx
1431
+ init_cookies();
229
1432
  var import_jsx_runtime3 = require("react/jsx-runtime");
230
1433
  var initialState = {
231
1434
  currentScreen: "login",
@@ -450,115 +1653,7 @@ var useLoginState = () => {
450
1653
  // src/components/CrudifyLogin/Forms/LoginForm.tsx
451
1654
  var import_react6 = require("react");
452
1655
  var import_material = require("@mui/material");
453
-
454
- // src/components/CrudifyLogin/utils/secureStorage.ts
455
- var import_crypto_js = __toESM(require("crypto-js"));
456
- var SecureStorage = class {
457
- constructor(storageType = "sessionStorage") {
458
- this.encryptionKey = this.generateEncryptionKey();
459
- this.storage = storageType === "localStorage" ? window.localStorage : window.sessionStorage;
460
- }
461
- generateEncryptionKey() {
462
- const browserFingerprint = [
463
- navigator.userAgent,
464
- navigator.language,
465
- (/* @__PURE__ */ new Date()).getTimezoneOffset(),
466
- screen.colorDepth,
467
- screen.width,
468
- screen.height,
469
- "crudify-login"
470
- ].join("|");
471
- return import_crypto_js.default.SHA256(browserFingerprint).toString();
472
- }
473
- setItem(key, value, expiryMinutes) {
474
- try {
475
- const encrypted = import_crypto_js.default.AES.encrypt(value, this.encryptionKey).toString();
476
- this.storage.setItem(key, encrypted);
477
- if (expiryMinutes) {
478
- const expiryTime = (/* @__PURE__ */ new Date()).getTime() + expiryMinutes * 60 * 1e3;
479
- this.storage.setItem(`${key}_expiry`, expiryTime.toString());
480
- }
481
- } catch (error) {
482
- console.error("Failed to encrypt and store data:", error);
483
- }
484
- }
485
- getItem(key) {
486
- try {
487
- const expiryKey = `${key}_expiry`;
488
- const expiry = this.storage.getItem(expiryKey);
489
- if (expiry) {
490
- const expiryTime = parseInt(expiry, 10);
491
- if ((/* @__PURE__ */ new Date()).getTime() > expiryTime) {
492
- this.removeItem(key);
493
- return null;
494
- }
495
- }
496
- const encrypted = this.storage.getItem(key);
497
- if (!encrypted) return null;
498
- const decrypted = import_crypto_js.default.AES.decrypt(encrypted, this.encryptionKey);
499
- const result = decrypted.toString(import_crypto_js.default.enc.Utf8);
500
- if (!result) {
501
- console.warn("Failed to decrypt stored data - may be corrupted");
502
- this.removeItem(key);
503
- return null;
504
- }
505
- return result;
506
- } catch (error) {
507
- console.error("Failed to decrypt data:", error);
508
- this.removeItem(key);
509
- return null;
510
- }
511
- }
512
- removeItem(key) {
513
- this.storage.removeItem(key);
514
- this.storage.removeItem(`${key}_expiry`);
515
- }
516
- setToken(token) {
517
- try {
518
- const parts = token.split(".");
519
- if (parts.length === 3) {
520
- const payload = JSON.parse(atob(parts[1]));
521
- if (payload.exp) {
522
- const expiryTime = payload.exp * 1e3;
523
- const now = (/* @__PURE__ */ new Date()).getTime();
524
- const minutesUntilExpiry = Math.floor((expiryTime - now) / (60 * 1e3));
525
- if (minutesUntilExpiry > 0) {
526
- this.setItem("authToken", token, minutesUntilExpiry);
527
- return;
528
- }
529
- }
530
- }
531
- } catch (error) {
532
- console.warn("Failed to parse token expiry, using default expiry");
533
- }
534
- this.setItem("authToken", token, 24 * 60);
535
- }
536
- getToken() {
537
- const token = this.getItem("authToken");
538
- if (token) {
539
- try {
540
- const parts = token.split(".");
541
- if (parts.length === 3) {
542
- const payload = JSON.parse(atob(parts[1]));
543
- if (payload.exp) {
544
- const now = Math.floor(Date.now() / 1e3);
545
- if (payload.exp < now) {
546
- this.removeItem("authToken");
547
- return null;
548
- }
549
- }
550
- }
551
- } catch (error) {
552
- console.warn("Failed to validate token expiry");
553
- this.removeItem("authToken");
554
- return null;
555
- }
556
- }
557
- return token;
558
- }
559
- };
560
- var secureSessionStorage = new SecureStorage("sessionStorage");
561
- var secureLocalStorage = new SecureStorage("localStorage");
1656
+ init_secureStorage();
562
1657
 
563
1658
  // src/utils/errorHandler.ts
564
1659
  var ERROR_CODES = {
@@ -673,1202 +1768,165 @@ function parseApiError(response) {
673
1768
  messages.forEach((msg) => {
674
1769
  if (typeof msg === "string") {
675
1770
  const errorCode = isValidErrorCode(msg) ? msg : ERROR_CODES.BAD_REQUEST;
676
- errors.push({
677
- code: errorCode,
678
- message: getErrorMessage(errorCode),
679
- severity: ERROR_SEVERITY_MAP[errorCode] || "warning"
680
- });
681
- }
682
- });
683
- } else {
684
- errors.push({
685
- code: ERROR_CODES.FIELD_ERROR,
686
- message: typeof messages[0] === "string" ? messages[0] : "Validation error",
687
- severity: "warning",
688
- field
689
- });
690
- }
691
- }
692
- });
693
- }
694
- }
695
- if (errors.length === 0 && apiResponse.success === false) {
696
- errors.push({
697
- code: ERROR_CODES.BAD_REQUEST,
698
- message: "Request failed",
699
- severity: "warning"
700
- });
701
- }
702
- } catch (error) {
703
- errors.push({
704
- code: ERROR_CODES.INTERNAL_SERVER_ERROR,
705
- message: "Failed to parse error response",
706
- severity: "error",
707
- details: { originalError: error }
708
- });
709
- }
710
- return errors.length > 0 ? errors : [
711
- {
712
- code: ERROR_CODES.INTERNAL_SERVER_ERROR,
713
- message: "Unknown error occurred",
714
- severity: "error"
715
- }
716
- ];
717
- }
718
- function parseTransactionError(response) {
719
- try {
720
- const transactionResponse = response;
721
- if (transactionResponse.data && Array.isArray(transactionResponse.data)) {
722
- const errors = [];
723
- transactionResponse.data.forEach((item, index) => {
724
- if (item.response?.status === "TOO_MANY_REQUESTS") {
725
- errors.push({
726
- code: ERROR_CODES.TOO_MANY_REQUESTS,
727
- message: getErrorMessage(ERROR_CODES.TOO_MANY_REQUESTS),
728
- severity: "warning",
729
- details: { transactionIndex: index }
730
- });
731
- } else if (!item.response || item.response.status !== "OK") {
732
- errors.push({
733
- code: ERROR_CODES.BAD_REQUEST,
734
- message: "Transaction failed",
735
- severity: "warning",
736
- details: { transactionIndex: index, response: item.response }
737
- });
738
- }
739
- });
740
- return errors;
741
- }
742
- return parseApiError(response);
743
- } catch (error) {
744
- return [
745
- {
746
- code: ERROR_CODES.INTERNAL_SERVER_ERROR,
747
- message: "Failed to parse transaction error",
748
- severity: "error",
749
- details: { originalError: error }
750
- }
751
- ];
752
- }
753
- }
754
- function isValidErrorCode(code) {
755
- return Object.values(ERROR_CODES).includes(code);
756
- }
757
- function getErrorMessage(code) {
758
- const messages = {
759
- [ERROR_CODES.INVALID_CREDENTIALS]: "Invalid email or password",
760
- [ERROR_CODES.UNAUTHORIZED]: "You are not authorized to perform this action",
761
- [ERROR_CODES.INVALID_API_KEY]: "Invalid API key",
762
- [ERROR_CODES.USER_NOT_FOUND]: "User not found",
763
- [ERROR_CODES.USER_NOT_ACTIVE]: "User account is not active",
764
- [ERROR_CODES.NO_PERMISSION]: "You do not have permission to perform this action",
765
- [ERROR_CODES.ITEM_NOT_FOUND]: "Item not found",
766
- [ERROR_CODES.NOT_FOUND]: "Resource not found",
767
- [ERROR_CODES.IN_USE]: "Resource is currently in use",
768
- [ERROR_CODES.FIELD_ERROR]: "Validation error",
769
- [ERROR_CODES.BAD_REQUEST]: "Invalid request",
770
- [ERROR_CODES.INVALID_EMAIL]: "Please enter a valid email address",
771
- [ERROR_CODES.INVALID_CODE]: "Invalid or expired code",
772
- [ERROR_CODES.INTERNAL_SERVER_ERROR]: "Internal server error",
773
- [ERROR_CODES.DATABASE_CONNECTION_ERROR]: "Database connection error",
774
- [ERROR_CODES.INVALID_CONFIGURATION]: "Invalid configuration",
775
- [ERROR_CODES.UNKNOWN_OPERATION]: "Unknown operation",
776
- [ERROR_CODES.TOO_MANY_REQUESTS]: "Too many requests. Please try again later.",
777
- [ERROR_CODES.NETWORK_ERROR]: "Network error. Please check your connection.",
778
- [ERROR_CODES.TIMEOUT_ERROR]: "Request timed out. Please try again."
779
- };
780
- return messages[code] || "An unknown error occurred";
781
- }
782
- function parseJavaScriptError(error) {
783
- if (error instanceof Error) {
784
- if (error.name === "AbortError") {
785
- return {
786
- code: ERROR_CODES.TIMEOUT_ERROR,
787
- message: "Request was cancelled",
788
- severity: "info"
789
- };
790
- }
791
- if (error.message.includes("NetworkError") || error.message.includes("Failed to fetch")) {
792
- return {
793
- code: ERROR_CODES.NETWORK_ERROR,
794
- message: getErrorMessage(ERROR_CODES.NETWORK_ERROR),
795
- severity: "error"
796
- };
797
- }
798
- return {
799
- code: ERROR_CODES.INTERNAL_SERVER_ERROR,
800
- message: error.message || "An unexpected error occurred",
801
- severity: "error",
802
- details: { originalError: error }
803
- };
804
- }
805
- return {
806
- code: ERROR_CODES.INTERNAL_SERVER_ERROR,
807
- message: "An unknown error occurred",
808
- severity: "error",
809
- details: { originalError: error }
810
- };
811
- }
812
- function handleCrudifyError(error) {
813
- if (error instanceof Error) {
814
- return [parseJavaScriptError(error)];
815
- }
816
- if (typeof error === "object" && error !== null) {
817
- const response = error;
818
- if (response.data && Array.isArray(response.data)) {
819
- return parseTransactionError(error);
820
- }
821
- return parseApiError(error);
822
- }
823
- return [
824
- {
825
- code: ERROR_CODES.INTERNAL_SERVER_ERROR,
826
- message: "An unknown error occurred",
827
- severity: "error",
828
- details: { originalError: error }
829
- }
830
- ];
831
- }
832
-
833
- // src/providers/CrudifyDataProvider.tsx
834
- var import_react5 = require("react");
835
-
836
- // src/core/ConfigurationManager.ts
837
- var _ConfigurationManager = class _ConfigurationManager {
838
- constructor() {
839
- this.resolvedConfig = null;
840
- this.configError = null;
841
- }
842
- /**
843
- * Singleton pattern to ensure consistent configuration across the app
844
- */
845
- static getInstance() {
846
- if (!_ConfigurationManager.instance) {
847
- _ConfigurationManager.instance = new _ConfigurationManager();
848
- }
849
- return _ConfigurationManager.instance;
850
- }
851
- /**
852
- * Reset the singleton instance (useful for testing)
853
- */
854
- static resetInstance() {
855
- _ConfigurationManager.instance = null;
856
- }
857
- /**
858
- * Resolve configuration from all sources with proper priority
859
- */
860
- resolveConfig(propsConfig = {}) {
861
- if (this.resolvedConfig && this.isConfigStillValid(propsConfig)) {
862
- return this.resolvedConfig;
863
- }
864
- try {
865
- this.configError = null;
866
- const envConfig = this.getEnvConfig();
867
- const cookieConfig = this.getCookieConfig();
868
- const configSource = {
869
- env: "default",
870
- publicApiKey: "default",
871
- loginActions: "default",
872
- appName: "default",
873
- logo: "default",
874
- colors: "default"
875
- };
876
- const env = this.resolveValue("env", propsConfig.env, envConfig.env, cookieConfig.env, "prod", configSource);
877
- const publicApiKey = this.resolveValue("publicApiKey", propsConfig.publicApiKey, envConfig.publicApiKey, cookieConfig.publicApiKey, void 0, configSource);
878
- const loginActions = this.resolveValue("loginActions", propsConfig.loginActions, envConfig.loginActions, cookieConfig.loginActions, [], configSource);
879
- const appName = this.resolveValue("appName", propsConfig.appName, envConfig.appName, cookieConfig.appName, "Crudify App", configSource);
880
- const logo = this.resolveValue("logo", propsConfig.logo, envConfig.logo, cookieConfig.logo, "", configSource);
881
- const colors = this.resolveValue("colors", propsConfig.colors, envConfig.colors, cookieConfig.colors, {}, configSource);
882
- if (!publicApiKey) {
883
- throw new Error(
884
- "publicApiKey is required. Provide it via:\n1. Props: <CrudifyDataProvider publicApiKey={...} />\n2. Environment: VITE_TEST_PUBLIC_API_KEY\n3. Cookie: publicApiKey"
885
- );
886
- }
887
- this.resolvedConfig = {
888
- env,
889
- publicApiKey,
890
- loginActions,
891
- appName,
892
- logo,
893
- colors,
894
- configSource,
895
- rawConfig: {
896
- props: propsConfig,
897
- env: envConfig,
898
- cookies: cookieConfig
899
- }
900
- };
901
- console.log("\u{1F527} ConfigurationManager - Configuration resolved:", {
902
- config: {
903
- env: this.resolvedConfig.env,
904
- publicApiKey: `${this.resolvedConfig.publicApiKey.substring(0, 8)}...`,
905
- appName: this.resolvedConfig.appName,
906
- loginActionsCount: this.resolvedConfig.loginActions.length
907
- },
908
- sources: this.resolvedConfig.configSource
909
- });
910
- return this.resolvedConfig;
911
- } catch (error) {
912
- this.configError = error instanceof Error ? error.message : "Unknown configuration error";
913
- console.error("\u{1F527} ConfigurationManager - Configuration error:", this.configError);
914
- this.resolvedConfig = {
915
- env: "prod",
916
- publicApiKey: "",
917
- loginActions: [],
918
- appName: "Crudify App",
919
- logo: "",
920
- colors: {},
921
- configSource: {
922
- env: "default",
923
- publicApiKey: "default",
924
- loginActions: "default",
925
- appName: "default",
926
- logo: "default",
927
- colors: "default"
928
- },
929
- rawConfig: {
930
- props: propsConfig,
931
- env: {},
932
- cookies: {},
933
- error: this.configError
934
- }
935
- };
936
- return this.resolvedConfig;
937
- }
938
- }
939
- /**
940
- * Check if current configuration is still valid for the given props
941
- */
942
- isConfigStillValid(propsConfig) {
943
- if (!this.resolvedConfig) return false;
944
- const currentProps = this.resolvedConfig.rawConfig.props;
945
- return JSON.stringify(currentProps) === JSON.stringify(propsConfig);
946
- }
947
- /**
948
- * Resolve a single config value with priority and source tracking
949
- */
950
- resolveValue(key, propsValue, envValue, cookieValue, defaultValue, configSource) {
951
- if (propsValue !== void 0) {
952
- configSource[key] = "props";
953
- return propsValue;
954
- }
955
- if (envValue !== void 0) {
956
- configSource[key] = "env";
957
- return envValue;
958
- }
959
- if (cookieValue !== void 0) {
960
- configSource[key] = "cookies";
961
- return cookieValue;
962
- }
963
- configSource[key] = "default";
964
- return defaultValue;
965
- }
966
- /**
967
- * Get configuration from environment variables
968
- */
969
- getEnvConfig() {
970
- const config = {};
971
- try {
972
- } catch (error) {
973
- console.warn("\u{1F527} ConfigurationManager - Environment variables not available:", error);
974
- }
975
- return config;
976
- }
977
- /**
978
- * Get configuration from cookies (multi-tenant support)
979
- */
980
- getCookieConfig() {
981
- const config = {};
982
- try {
983
- const env = getCookie("environment");
984
- if (env && ["dev", "stg", "prod"].includes(env)) {
985
- config.env = env;
986
- }
987
- const publicApiKey = getCookie("publicApiKey");
988
- if (publicApiKey) {
989
- config.publicApiKey = publicApiKey;
990
- }
991
- const appName = getCookie("appName");
992
- if (appName) {
993
- config.appName = appName;
994
- }
995
- const loginActions = getCookie("loginActions");
996
- if (loginActions) {
997
- config.loginActions = loginActions.split(",").map((action) => action.trim()).filter(Boolean);
998
- }
999
- const logo = getCookie("logo");
1000
- if (logo) {
1001
- config.logo = logo;
1002
- }
1003
- const colors = getCookie("colors");
1004
- if (colors) {
1005
- try {
1006
- config.colors = JSON.parse(colors);
1007
- } catch (error) {
1008
- console.warn("\u{1F527} ConfigurationManager - Failed to parse colors from cookie:", error);
1009
- }
1010
- }
1011
- } catch (error) {
1012
- console.warn("\u{1F527} ConfigurationManager - Error reading cookies:", error);
1013
- }
1014
- return config;
1015
- }
1016
- /**
1017
- * Get the current resolved configuration
1018
- */
1019
- getConfig() {
1020
- return this.resolvedConfig;
1021
- }
1022
- /**
1023
- * Get any configuration errors
1024
- */
1025
- getConfigError() {
1026
- return this.configError;
1027
- }
1028
- /**
1029
- * Check if configuration is valid (no errors and has required fields)
1030
- */
1031
- isConfigured() {
1032
- return this.resolvedConfig !== null && this.configError === null && !!this.resolvedConfig.publicApiKey;
1033
- }
1034
- /**
1035
- * Clear the current configuration (useful for testing or reconfiguration)
1036
- */
1037
- clearConfig() {
1038
- this.resolvedConfig = null;
1039
- this.configError = null;
1040
- }
1041
- };
1042
- _ConfigurationManager.instance = null;
1043
- var ConfigurationManager = _ConfigurationManager;
1044
- var configurationManager = ConfigurationManager.getInstance();
1045
-
1046
- // src/core/CrudifyInitializer.ts
1047
- var import_crudify_browser2 = __toESM(require("@nocios/crudify-browser"));
1048
- var _CrudifyInitializer = class _CrudifyInitializer {
1049
- constructor() {
1050
- this.state = {
1051
- isInitialized: false,
1052
- isInitializing: false,
1053
- initializationError: null,
1054
- config: null,
1055
- initializationPromise: null
1056
- };
1057
- console.log("\u{1F680} CrudifyInitializer - Instance created");
1058
- }
1059
- /**
1060
- * Singleton pattern to ensure global initialization coordination
1061
- */
1062
- static getInstance() {
1063
- if (!_CrudifyInitializer.instance) {
1064
- _CrudifyInitializer.instance = new _CrudifyInitializer();
1065
- }
1066
- return _CrudifyInitializer.instance;
1067
- }
1068
- /**
1069
- * Reset the singleton instance (useful for testing)
1070
- */
1071
- static resetInstance() {
1072
- _CrudifyInitializer.instance = null;
1073
- }
1074
- /**
1075
- * Initialize crudify with the given configuration
1076
- * This method is idempotent and thread-safe
1077
- */
1078
- async initialize(config) {
1079
- if (this.state.isInitialized && this.isConfigurationSame(config)) {
1080
- console.log("\u{1F680} CrudifyInitializer - Already initialized with same config");
1081
- return;
1082
- }
1083
- if (this.state.isInitializing && this.state.initializationPromise) {
1084
- console.log("\u{1F680} CrudifyInitializer - Waiting for ongoing initialization");
1085
- await this.state.initializationPromise;
1086
- return;
1087
- }
1088
- if (this.state.isInitialized && !this.isConfigurationSame(config)) {
1089
- console.log("\u{1F680} CrudifyInitializer - Configuration changed, re-initializing");
1090
- this.reset();
1091
- }
1092
- this.state.isInitializing = true;
1093
- this.state.initializationError = null;
1094
- this.state.initializationPromise = this.performInitialization(config);
1095
- try {
1096
- await this.state.initializationPromise;
1097
- this.state.isInitialized = true;
1098
- this.state.config = { ...config };
1099
- console.log("\u{1F680} CrudifyInitializer - Initialization completed successfully");
1100
- } catch (error) {
1101
- this.state.initializationError = error instanceof Error ? error.message : "Unknown initialization error";
1102
- console.error("\u{1F680} CrudifyInitializer - Initialization failed:", this.state.initializationError);
1103
- throw error;
1104
- } finally {
1105
- this.state.isInitializing = false;
1106
- this.state.initializationPromise = null;
1107
- }
1108
- }
1109
- /**
1110
- * Perform the actual initialization process
1111
- */
1112
- async performInitialization(config) {
1113
- if (!config.publicApiKey) {
1114
- throw new Error("publicApiKey is required for crudify initialization");
1115
- }
1116
- console.log("\u{1F680} CrudifyInitializer - Starting initialization with config:", {
1117
- env: config.env,
1118
- publicApiKey: `${config.publicApiKey.substring(0, 8)}...`,
1119
- appName: config.appName
1120
- });
1121
- try {
1122
- const environment = config.env || "prod";
1123
- console.log("\u{1F680} CrudifyInitializer - Step 1: Configuring environment:", environment);
1124
- await import_crudify_browser2.default.config(environment);
1125
- console.log("\u{1F680} CrudifyInitializer - Step 2: Initializing with API key");
1126
- await import_crudify_browser2.default.init(config.publicApiKey, "none");
1127
- console.log("\u{1F680} CrudifyInitializer - Step 3: Verifying initialization");
1128
- await this.verifyInitialization();
1129
- console.log("\u{1F680} CrudifyInitializer - All initialization steps completed");
1130
- } catch (error) {
1131
- console.error("\u{1F680} CrudifyInitializer - Initialization failed at step:", error);
1132
- throw new Error(
1133
- `Crudify initialization failed: ${error instanceof Error ? error.message : "Unknown error"}. Please check your configuration (env: ${config.env || "prod"}, publicApiKey: ${config.publicApiKey ? "provided" : "missing"})`
1134
- );
1135
- }
1136
- }
1137
- /**
1138
- * Verify that crudify is properly initialized by checking core methods
1139
- */
1140
- async verifyInitialization() {
1141
- const requiredMethods = ["readItems", "readItem", "createItem", "updateItem", "deleteItem", "login", "transaction"];
1142
- const missingMethods = [];
1143
- for (const method of requiredMethods) {
1144
- if (typeof import_crudify_browser2.default[method] !== "function") {
1145
- missingMethods.push(method);
1146
- }
1147
- }
1148
- if (missingMethods.length > 0) {
1149
- throw new Error(
1150
- `Crudify initialization incomplete. Missing methods: ${missingMethods.join(", ")}. This usually indicates a configuration or network issue.`
1151
- );
1152
- }
1153
- console.log("\u{1F680} CrudifyInitializer - Verification successful (test call skipped for performance)");
1154
- }
1155
- /**
1156
- * Check if the given configuration is the same as the current one
1157
- */
1158
- isConfigurationSame(config) {
1159
- if (!this.state.config) return false;
1160
- return this.state.config.env === config.env && this.state.config.publicApiKey === config.publicApiKey;
1161
- }
1162
- /**
1163
- * Reset the initialization state (useful for testing or configuration changes)
1164
- */
1165
- reset() {
1166
- console.log("\u{1F680} CrudifyInitializer - Resetting initialization state");
1167
- this.state = {
1168
- isInitialized: false,
1169
- isInitializing: false,
1170
- initializationError: null,
1171
- config: null,
1172
- initializationPromise: null
1173
- };
1174
- }
1175
- /**
1176
- * Get the current initialization status
1177
- */
1178
- getStatus() {
1179
- return {
1180
- isInitialized: this.state.isInitialized,
1181
- isInitializing: this.state.isInitializing,
1182
- initializationError: this.state.initializationError,
1183
- config: this.state.config
1184
- };
1185
- }
1186
- /**
1187
- * Check if crudify is ready to use
1188
- */
1189
- isReady() {
1190
- return this.state.isInitialized && !this.state.initializationError;
1191
- }
1192
- /**
1193
- * Get the current initialization error, if any
1194
- */
1195
- getError() {
1196
- return this.state.initializationError;
1197
- }
1198
- /**
1199
- * Force re-initialization (useful when configuration changes)
1200
- */
1201
- async reinitialize(config) {
1202
- console.log("\u{1F680} CrudifyInitializer - Forcing re-initialization");
1203
- this.reset();
1204
- await this.initialize(config);
1205
- }
1206
- /**
1207
- * Check if initialization is currently in progress
1208
- */
1209
- isInitializing() {
1210
- return this.state.isInitializing;
1211
- }
1212
- /**
1213
- * Wait for any ongoing initialization to complete
1214
- */
1215
- async waitForInitialization() {
1216
- if (this.state.initializationPromise) {
1217
- await this.state.initializationPromise;
1218
- }
1219
- }
1220
- };
1221
- _CrudifyInitializer.instance = null;
1222
- var CrudifyInitializer = _CrudifyInitializer;
1223
- var crudifyInitializer = CrudifyInitializer.getInstance();
1224
-
1225
- // src/core/TokenManager.ts
1226
- var import_crudify_browser3 = __toESM(require("@nocios/crudify-browser"));
1227
-
1228
- // src/utils/jwtUtils.ts
1229
- var decodeJwtSafely = (token) => {
1230
- try {
1231
- const parts = token.split(".");
1232
- if (parts.length !== 3) {
1233
- console.warn("Invalid JWT format: token must have 3 parts");
1234
- return null;
1235
- }
1236
- const payload = parts[1];
1237
- const paddedPayload = payload + "=".repeat((4 - payload.length % 4) % 4);
1238
- const decodedPayload = JSON.parse(atob(paddedPayload));
1239
- return decodedPayload;
1240
- } catch (error) {
1241
- console.warn("Failed to decode JWT token:", error);
1242
- return null;
1243
- }
1244
- };
1245
- var getCurrentUserEmail = () => {
1246
- try {
1247
- let token = null;
1248
- token = sessionStorage.getItem("authToken");
1249
- console.log("\u{1F50D} getCurrentUserEmail - authToken:", token ? `${token.substring(0, 20)}...` : null);
1250
- if (!token) {
1251
- token = sessionStorage.getItem("token");
1252
- console.log("\u{1F50D} getCurrentUserEmail - token:", token ? `${token.substring(0, 20)}...` : null);
1253
- }
1254
- if (!token) {
1255
- token = localStorage.getItem("authToken") || localStorage.getItem("token");
1256
- console.log("\u{1F50D} getCurrentUserEmail - localStorage:", token ? `${token.substring(0, 20)}...` : null);
1257
- }
1258
- if (!token) {
1259
- console.warn("\u{1F50D} getCurrentUserEmail - No token found in any storage");
1260
- return null;
1261
- }
1262
- const payload = decodeJwtSafely(token);
1263
- if (!payload) {
1264
- console.warn("\u{1F50D} getCurrentUserEmail - Failed to decode token");
1265
- return null;
1266
- }
1267
- const email = payload.email || payload["cognito:username"] || null;
1268
- console.log("\u{1F50D} getCurrentUserEmail - Extracted email:", email);
1269
- return email;
1270
- } catch (error) {
1271
- console.warn("Failed to get current user email:", error);
1272
- return null;
1273
- }
1274
- };
1275
- var isTokenExpired = (token) => {
1276
- try {
1277
- const payload = decodeJwtSafely(token);
1278
- if (!payload || !payload.exp) return true;
1279
- const currentTime = Math.floor(Date.now() / 1e3);
1280
- return payload.exp < currentTime;
1281
- } catch {
1282
- return true;
1283
- }
1284
- };
1285
-
1286
- // src/core/TokenManager.ts
1287
- var _TokenManager = class _TokenManager {
1288
- constructor() {
1289
- this.TOKEN_KEY = "authToken";
1290
- // Compatible with crudia-ui
1291
- this.tokenCache = null;
1292
- this.parsedTokenCache = null;
1293
- this.expirationCheckInterval = null;
1294
- this.storageEventListener = null;
1295
- this.initializeTokenManager();
1296
- }
1297
- /**
1298
- * Singleton pattern to ensure consistent token management
1299
- */
1300
- static getInstance() {
1301
- if (!_TokenManager.instance) {
1302
- _TokenManager.instance = new _TokenManager();
1303
- }
1304
- return _TokenManager.instance;
1305
- }
1306
- /**
1307
- * Reset the singleton instance (useful for testing)
1308
- */
1309
- static resetInstance() {
1310
- if (_TokenManager.instance) {
1311
- _TokenManager.instance.cleanup();
1312
- }
1313
- _TokenManager.instance = null;
1314
- }
1315
- /**
1316
- * Initialize the token manager with storage synchronization
1317
- */
1318
- initializeTokenManager() {
1319
- console.log("\u{1F510} TokenManager - Initializing token management");
1320
- this.migrateFromLocalStorage();
1321
- this.loadTokenFromStorage();
1322
- this.setupExpirationCheck();
1323
- this.setupStorageListener();
1324
- console.log("\u{1F510} TokenManager - Initialization complete");
1325
- }
1326
- /**
1327
- * Migrate tokens from localStorage to sessionStorage for better security
1328
- * This ensures compatibility with older implementations
1329
- */
1330
- migrateFromLocalStorage() {
1331
- try {
1332
- const legacyKeys = ["authToken", "token", "jwt", "jwtToken"];
1333
- for (const key of legacyKeys) {
1334
- const token = localStorage.getItem(key);
1335
- if (token && !secureSessionStorage.getToken()) {
1336
- console.log(`\u{1F510} TokenManager - Migrating token from localStorage key: ${key}`);
1337
- secureSessionStorage.setToken(token);
1338
- localStorage.removeItem(key);
1339
- break;
1340
- }
1341
- }
1342
- } catch (error) {
1343
- console.warn("\u{1F510} TokenManager - Token migration failed:", error);
1344
- }
1345
- }
1346
- /**
1347
- * Load token from storage and synchronize with crudify
1348
- */
1349
- loadTokenFromStorage() {
1350
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Entry point - loading token from storage");
1351
- try {
1352
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Getting token from secure session storage");
1353
- const storedToken = secureSessionStorage.getToken();
1354
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Stored token exists:", !!storedToken);
1355
- if (storedToken && this.isTokenValid(storedToken)) {
1356
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Stored token is valid, updating cache");
1357
- this.tokenCache = storedToken;
1358
- this.parsedTokenCache = this.parseToken(storedToken);
1359
- this.syncTokenWithCrudify(storedToken);
1360
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Token loaded from storage and synchronized");
1361
- } else if (storedToken) {
1362
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Stored token exists but is invalid/expired, clearing");
1363
- this.clearToken();
1364
- } else {
1365
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: No stored token found");
1366
- }
1367
- } catch (error) {
1368
- console.warn("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Error loading token from storage:", error);
1369
- this.clearToken();
1370
- }
1371
- }
1372
- /**
1373
- * Set up automatic token expiration checking
1374
- */
1375
- setupExpirationCheck() {
1376
- this.expirationCheckInterval = window.setInterval(() => {
1377
- if (this.tokenCache && !this.isTokenValid(this.tokenCache)) {
1378
- console.log("\u{1F510} TokenManager - Token expired, clearing automatically");
1379
- this.clearToken();
1380
- }
1381
- }, 3e4);
1382
- }
1383
- /**
1384
- * Set up storage event listener for cross-tab synchronization
1385
- */
1386
- setupStorageListener() {
1387
- this.storageEventListener = (event) => {
1388
- if (event.key === this.TOKEN_KEY) {
1389
- console.log("\u{1F510} TokenManager - Token change detected from another tab");
1390
- this.loadTokenFromStorage();
1391
- }
1392
- };
1393
- window.addEventListener("storage", this.storageEventListener);
1394
- }
1395
- /**
1396
- * Set a new JWT token with automatic synchronization
1397
- */
1398
- setToken(token) {
1399
- console.log("\u{1F510} TokenManager - SET_TOKEN: Entry point - setting token:", token ? "provided" : "null");
1400
- try {
1401
- if (!token) {
1402
- console.log("\u{1F510} TokenManager - SET_TOKEN: No token provided, clearing token");
1403
- this.clearToken();
1404
- return;
1405
- }
1406
- console.log("\u{1F510} TokenManager - SET_TOKEN: Validating token before setting");
1407
- if (!this.isTokenValid(token)) {
1408
- console.warn("\u{1F510} TokenManager - SET_TOKEN: Attempted to set invalid or expired token");
1409
- this.clearToken();
1410
- return;
1771
+ errors.push({
1772
+ code: errorCode,
1773
+ message: getErrorMessage(errorCode),
1774
+ severity: ERROR_SEVERITY_MAP[errorCode] || "warning"
1775
+ });
1776
+ }
1777
+ });
1778
+ } else {
1779
+ errors.push({
1780
+ code: ERROR_CODES.FIELD_ERROR,
1781
+ message: typeof messages[0] === "string" ? messages[0] : "Validation error",
1782
+ severity: "warning",
1783
+ field
1784
+ });
1785
+ }
1786
+ }
1787
+ });
1411
1788
  }
1412
- console.log("\u{1F510} TokenManager - SET_TOKEN: Token is valid, updating cache");
1413
- this.tokenCache = token;
1414
- this.parsedTokenCache = this.parseToken(token);
1415
- console.log("\u{1F510} TokenManager - SET_TOKEN: Storing token in secure storage");
1416
- secureSessionStorage.setToken(token);
1417
- console.log("\u{1F510} TokenManager - SET_TOKEN: Synchronizing with crudify");
1418
- this.syncTokenWithCrudify(token);
1419
- console.log("\u{1F510} TokenManager - SET_TOKEN: Token set and synchronized successfully");
1420
- } catch (error) {
1421
- console.error("\u{1F510} TokenManager - SET_TOKEN: Error setting token:", error);
1422
- this.clearToken();
1423
1789
  }
1424
- }
1425
- /**
1426
- * Get the current JWT token
1427
- */
1428
- getToken() {
1429
- console.log("\u{1F510} TokenManager - GET_TOKEN: Entry point - checking cache");
1430
- if (this.tokenCache) {
1431
- console.log("\u{1F510} TokenManager - GET_TOKEN: Cache exists, validating token");
1432
- if (this.isTokenValid(this.tokenCache)) {
1433
- console.log("\u{1F510} TokenManager - GET_TOKEN: Cache valid, returning cached token");
1434
- return this.tokenCache;
1435
- } else {
1436
- console.log("\u{1F510} TokenManager - GET_TOKEN: Cache invalid, clearing cache");
1437
- this.tokenCache = null;
1438
- }
1439
- } else {
1440
- console.log("\u{1F510} TokenManager - GET_TOKEN: No cache, loading from storage");
1790
+ if (errors.length === 0 && apiResponse.success === false) {
1791
+ errors.push({
1792
+ code: ERROR_CODES.BAD_REQUEST,
1793
+ message: "Request failed",
1794
+ severity: "warning"
1795
+ });
1441
1796
  }
1442
- console.log("\u{1F510} TokenManager - GET_TOKEN: Loading from storage");
1443
- this.loadTokenFromStorage();
1444
- console.log("\u{1F510} TokenManager - GET_TOKEN: Returning final token:", !!this.tokenCache);
1445
- return this.tokenCache;
1446
- }
1447
- /**
1448
- * Parse the current JWT token
1449
- */
1450
- parseToken(token) {
1451
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Entry point - parsing token");
1452
- const targetToken = token !== void 0 ? token : this.tokenCache;
1453
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Target token exists:", !!targetToken);
1454
- if (!targetToken) {
1455
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: No target token, returning null");
1456
- return null;
1457
- }
1458
- if (this.tokenCache === targetToken && this.parsedTokenCache) {
1459
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Returning cached parsed token");
1460
- return this.parsedTokenCache;
1461
- }
1462
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Cache miss, parsing token with decodeJwtSafely");
1463
- const parsed = decodeJwtSafely(targetToken);
1464
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Token parsed successfully:", !!parsed);
1465
- if (targetToken === this.tokenCache) {
1466
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Updating parsed token cache");
1467
- this.parsedTokenCache = parsed;
1468
- }
1469
- return parsed;
1797
+ } catch (error) {
1798
+ errors.push({
1799
+ code: ERROR_CODES.INTERNAL_SERVER_ERROR,
1800
+ message: "Failed to parse error response",
1801
+ severity: "error",
1802
+ details: { originalError: error }
1803
+ });
1470
1804
  }
1471
- /**
1472
- * Check if a token is valid (properly formatted and not expired)
1473
- */
1474
- isTokenValid(token) {
1475
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Entry point - checking token validity");
1476
- const targetToken = token !== void 0 ? token : this.tokenCache;
1477
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Target token exists:", !!targetToken);
1478
- if (!targetToken) {
1479
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: No token, returning false");
1480
- return false;
1481
- }
1482
- try {
1483
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Checking if token is expired");
1484
- if (isTokenExpired(targetToken)) {
1485
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Token is expired, returning false");
1486
- return false;
1487
- }
1488
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Token not expired, checking if can be parsed");
1489
- const parsed = decodeJwtSafely(targetToken);
1490
- const isValid = parsed !== null;
1491
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Token parsing result:", isValid);
1492
- return isValid;
1493
- } catch (error) {
1494
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Error validating token:", error);
1495
- return false;
1805
+ return errors.length > 0 ? errors : [
1806
+ {
1807
+ code: ERROR_CODES.INTERNAL_SERVER_ERROR,
1808
+ message: "Unknown error occurred",
1809
+ severity: "error"
1496
1810
  }
1497
- }
1498
- /**
1499
- * Get token expiration time as Date object
1500
- */
1501
- getTokenExpiration() {
1502
- const token = this.getToken();
1503
- if (!token) return null;
1504
- const parsed = this.parseToken(token);
1505
- if (!parsed?.exp) return null;
1506
- return new Date(parsed.exp * 1e3);
1507
- }
1508
- /**
1509
- * Clear the current token from all storages and crudify
1510
- */
1511
- clearToken() {
1512
- console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Entry point - clearing all tokens");
1513
- try {
1514
- console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Clearing cache");
1515
- this.tokenCache = null;
1516
- this.parsedTokenCache = null;
1517
- console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Clearing from secure storage");
1518
- secureSessionStorage.removeItem(this.TOKEN_KEY);
1519
- console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Clearing from crudify");
1520
- import_crudify_browser3.default.setToken("");
1521
- console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Token cleared from all storages successfully");
1522
- } catch (error) {
1523
- console.warn("\u{1F510} TokenManager - CLEAR_TOKEN: Error clearing token:", error);
1811
+ ];
1812
+ }
1813
+ function parseTransactionError(response) {
1814
+ try {
1815
+ const transactionResponse = response;
1816
+ if (transactionResponse.data && Array.isArray(transactionResponse.data)) {
1817
+ const errors = [];
1818
+ transactionResponse.data.forEach((item, index) => {
1819
+ if (item.response?.status === "TOO_MANY_REQUESTS") {
1820
+ errors.push({
1821
+ code: ERROR_CODES.TOO_MANY_REQUESTS,
1822
+ message: getErrorMessage(ERROR_CODES.TOO_MANY_REQUESTS),
1823
+ severity: "warning",
1824
+ details: { transactionIndex: index }
1825
+ });
1826
+ } else if (!item.response || item.response.status !== "OK") {
1827
+ errors.push({
1828
+ code: ERROR_CODES.BAD_REQUEST,
1829
+ message: "Transaction failed",
1830
+ severity: "warning",
1831
+ details: { transactionIndex: index, response: item.response }
1832
+ });
1833
+ }
1834
+ });
1835
+ return errors;
1524
1836
  }
1837
+ return parseApiError(response);
1838
+ } catch (error) {
1839
+ return [
1840
+ {
1841
+ code: ERROR_CODES.INTERNAL_SERVER_ERROR,
1842
+ message: "Failed to parse transaction error",
1843
+ severity: "error",
1844
+ details: { originalError: error }
1845
+ }
1846
+ ];
1525
1847
  }
1526
- /**
1527
- * Synchronize token with crudify library
1528
- */
1529
- syncTokenWithCrudify(token) {
1530
- try {
1531
- import_crudify_browser3.default.setToken(token);
1532
- console.log("\u{1F510} TokenManager - Token synchronized with crudify");
1533
- } catch (error) {
1534
- console.warn("\u{1F510} TokenManager - Failed to sync token with crudify:", error);
1848
+ }
1849
+ function isValidErrorCode(code) {
1850
+ return Object.values(ERROR_CODES).includes(code);
1851
+ }
1852
+ function getErrorMessage(code) {
1853
+ const messages = {
1854
+ [ERROR_CODES.INVALID_CREDENTIALS]: "Invalid email or password",
1855
+ [ERROR_CODES.UNAUTHORIZED]: "You are not authorized to perform this action",
1856
+ [ERROR_CODES.INVALID_API_KEY]: "Invalid API key",
1857
+ [ERROR_CODES.USER_NOT_FOUND]: "User not found",
1858
+ [ERROR_CODES.USER_NOT_ACTIVE]: "User account is not active",
1859
+ [ERROR_CODES.NO_PERMISSION]: "You do not have permission to perform this action",
1860
+ [ERROR_CODES.ITEM_NOT_FOUND]: "Item not found",
1861
+ [ERROR_CODES.NOT_FOUND]: "Resource not found",
1862
+ [ERROR_CODES.IN_USE]: "Resource is currently in use",
1863
+ [ERROR_CODES.FIELD_ERROR]: "Validation error",
1864
+ [ERROR_CODES.BAD_REQUEST]: "Invalid request",
1865
+ [ERROR_CODES.INVALID_EMAIL]: "Please enter a valid email address",
1866
+ [ERROR_CODES.INVALID_CODE]: "Invalid or expired code",
1867
+ [ERROR_CODES.INTERNAL_SERVER_ERROR]: "Internal server error",
1868
+ [ERROR_CODES.DATABASE_CONNECTION_ERROR]: "Database connection error",
1869
+ [ERROR_CODES.INVALID_CONFIGURATION]: "Invalid configuration",
1870
+ [ERROR_CODES.UNKNOWN_OPERATION]: "Unknown operation",
1871
+ [ERROR_CODES.TOO_MANY_REQUESTS]: "Too many requests. Please try again later.",
1872
+ [ERROR_CODES.NETWORK_ERROR]: "Network error. Please check your connection.",
1873
+ [ERROR_CODES.TIMEOUT_ERROR]: "Request timed out. Please try again."
1874
+ };
1875
+ return messages[code] || "An unknown error occurred";
1876
+ }
1877
+ function parseJavaScriptError(error) {
1878
+ if (error instanceof Error) {
1879
+ if (error.name === "AbortError") {
1880
+ return {
1881
+ code: ERROR_CODES.TIMEOUT_ERROR,
1882
+ message: "Request was cancelled",
1883
+ severity: "info"
1884
+ };
1535
1885
  }
1536
- }
1537
- /**
1538
- * Refresh token (placeholder for future implementation)
1539
- */
1540
- async refreshToken() {
1541
- throw new Error("Token refresh not yet implemented");
1542
- }
1543
- /**
1544
- * Get user information from the current token
1545
- */
1546
- getUserInfo() {
1547
- const parsed = this.parseToken();
1548
- if (!parsed) {
1886
+ if (error.message.includes("NetworkError") || error.message.includes("Failed to fetch")) {
1549
1887
  return {
1550
- email: null,
1551
- userId: null,
1552
- userIdentifier: null,
1553
- username: null
1888
+ code: ERROR_CODES.NETWORK_ERROR,
1889
+ message: getErrorMessage(ERROR_CODES.NETWORK_ERROR),
1890
+ severity: "error"
1554
1891
  };
1555
1892
  }
1556
1893
  return {
1557
- email: parsed.email || null,
1558
- userId: parsed.sub || null,
1559
- userIdentifier: parsed["cognito:username"] || parsed.email || parsed.sub || null,
1560
- username: parsed["cognito:username"] || null
1894
+ code: ERROR_CODES.INTERNAL_SERVER_ERROR,
1895
+ message: error.message || "An unexpected error occurred",
1896
+ severity: "error",
1897
+ details: { originalError: error }
1561
1898
  };
1562
1899
  }
1563
- /**
1564
- * Check if user is currently authenticated
1565
- */
1566
- isAuthenticated() {
1567
- return this.isTokenValid();
1568
- }
1569
- /**
1570
- * Get time until token expires in minutes
1571
- */
1572
- getTimeUntilExpiration() {
1573
- const expiration = this.getTokenExpiration();
1574
- if (!expiration) return null;
1575
- const now = /* @__PURE__ */ new Date();
1576
- const minutesUntilExpiry = Math.floor((expiration.getTime() - now.getTime()) / (60 * 1e3));
1577
- return Math.max(0, minutesUntilExpiry);
1578
- }
1579
- /**
1580
- * Cleanup resources (call when the component unmounts)
1581
- */
1582
- cleanup() {
1583
- if (this.expirationCheckInterval) {
1584
- window.clearInterval(this.expirationCheckInterval);
1585
- this.expirationCheckInterval = null;
1586
- }
1587
- if (this.storageEventListener) {
1588
- window.removeEventListener("storage", this.storageEventListener);
1589
- this.storageEventListener = null;
1590
- }
1591
- console.log("\u{1F510} TokenManager - Cleanup completed");
1592
- }
1593
- /**
1594
- * Get debug information about the current token state
1595
- */
1596
- getDebugInfo() {
1597
- const token = this.getToken();
1598
- const parsed = this.parseToken();
1599
- const expiration = this.getTokenExpiration();
1600
- return {
1601
- hasToken: !!token,
1602
- tokenLength: token?.length || 0,
1603
- isValid: this.isTokenValid(),
1604
- isAuthenticated: this.isAuthenticated(),
1605
- expiration: expiration?.toISOString() || null,
1606
- minutesUntilExpiry: this.getTimeUntilExpiration(),
1607
- userInfo: this.getUserInfo(),
1608
- parsedTokenKeys: parsed ? Object.keys(parsed) : []
1609
- };
1900
+ return {
1901
+ code: ERROR_CODES.INTERNAL_SERVER_ERROR,
1902
+ message: "An unknown error occurred",
1903
+ severity: "error",
1904
+ details: { originalError: error }
1905
+ };
1906
+ }
1907
+ function handleCrudifyError(error) {
1908
+ if (error instanceof Error) {
1909
+ return [parseJavaScriptError(error)];
1610
1910
  }
1611
- };
1612
- _TokenManager.instance = null;
1613
- var TokenManager = _TokenManager;
1614
- var tokenManager = TokenManager.getInstance();
1615
-
1616
- // src/providers/CrudifyDataProvider.tsx
1617
- var import_jsx_runtime4 = require("react/jsx-runtime");
1618
- var CrudifyDataContext = (0, import_react5.createContext)(null);
1619
- var CrudifyDataProvider = ({
1620
- children,
1621
- env,
1622
- publicApiKey,
1623
- loginActions,
1624
- appName,
1625
- logo,
1626
- colors
1627
- }) => {
1628
- const [config, setConfig] = (0, import_react5.useState)(null);
1629
- const [isConfigured, setIsConfigured] = (0, import_react5.useState)(false);
1630
- const [configError, setConfigError] = (0, import_react5.useState)(null);
1631
- const [isInitialized, setIsInitialized] = (0, import_react5.useState)(false);
1632
- const [isInitializing, setIsInitializing] = (0, import_react5.useState)(false);
1633
- const [initializationError, setInitializationError] = (0, import_react5.useState)(null);
1634
- const [isAuthenticated, setIsAuthenticated] = (0, import_react5.useState)(false);
1635
- const [token, setTokenState] = (0, import_react5.useState)(null);
1636
- const [user, setUser] = (0, import_react5.useState)(null);
1637
- const [tokenExpiration, setTokenExpiration] = (0, import_react5.useState)(null);
1638
- const initializeConfiguration = (0, import_react5.useCallback)(() => {
1639
- try {
1640
- console.log("\u{1F30D} CrudifyDataProvider - Initializing configuration");
1641
- const propsConfig = {
1642
- env,
1643
- publicApiKey,
1644
- loginActions,
1645
- appName,
1646
- logo,
1647
- colors
1648
- };
1649
- const resolvedConfig = configurationManager.resolveConfig(propsConfig);
1650
- const error = configurationManager.getConfigError();
1651
- setConfig(resolvedConfig);
1652
- setConfigError(error);
1653
- setIsConfigured(configurationManager.isConfigured());
1654
- console.log("\u{1F30D} CrudifyDataProvider - Configuration initialized:", {
1655
- isConfigured: configurationManager.isConfigured(),
1656
- error,
1657
- sources: resolvedConfig.configSource
1658
- });
1659
- return resolvedConfig;
1660
- } catch (error) {
1661
- const errorMessage = error instanceof Error ? error.message : "Configuration initialization failed";
1662
- console.error("\u{1F30D} CrudifyDataProvider - Configuration error:", errorMessage);
1663
- setConfigError(errorMessage);
1664
- setIsConfigured(false);
1665
- return null;
1666
- }
1667
- }, [env, publicApiKey, loginActions, appName, logo, colors]);
1668
- const initializeCrudify = (0, import_react5.useCallback)(async (resolvedConfig) => {
1669
- if (!resolvedConfig || !resolvedConfig.publicApiKey) {
1670
- setInitializationError("Cannot initialize crudify without valid configuration");
1671
- return;
1672
- }
1673
- try {
1674
- setIsInitializing(true);
1675
- setInitializationError(null);
1676
- console.log("\u{1F680} CrudifyDataProvider - Starting crudify initialization");
1677
- await crudifyInitializer.initialize({
1678
- env: resolvedConfig.env,
1679
- publicApiKey: resolvedConfig.publicApiKey,
1680
- loginActions: resolvedConfig.loginActions,
1681
- appName: resolvedConfig.appName,
1682
- logo: resolvedConfig.logo,
1683
- colors: resolvedConfig.colors
1684
- });
1685
- setIsInitialized(true);
1686
- console.log("\u{1F680} CrudifyDataProvider - Crudify initialization completed");
1687
- } catch (error) {
1688
- const errorMessage = error instanceof Error ? error.message : "Crudify initialization failed";
1689
- console.error("\u{1F680} CrudifyDataProvider - Initialization error:", errorMessage);
1690
- setInitializationError(errorMessage);
1691
- setIsInitialized(false);
1692
- } finally {
1693
- setIsInitializing(false);
1694
- }
1695
- }, []);
1696
- const updateAuthenticationState = (0, import_react5.useCallback)(() => {
1697
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Starting authentication state update");
1698
- try {
1699
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Getting token from TokenManager");
1700
- const currentToken = tokenManager.getToken();
1701
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Token retrieved:", !!currentToken);
1702
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Parsing token");
1703
- const parsedUser = tokenManager.parseToken();
1704
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Token parsed:", !!parsedUser);
1705
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Getting expiration");
1706
- const expiration = tokenManager.getTokenExpiration();
1707
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Expiration retrieved:", !!expiration);
1708
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Checking authentication");
1709
- const authenticated = tokenManager.isAuthenticated();
1710
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Authentication checked:", authenticated);
1711
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Updating state variables");
1712
- setTokenState(currentToken);
1713
- setUser(parsedUser);
1714
- setTokenExpiration(expiration);
1715
- setIsAuthenticated(authenticated);
1716
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Authentication state updated successfully:", {
1717
- hasToken: !!currentToken,
1718
- isAuthenticated: authenticated,
1719
- userEmail: parsedUser?.email || null,
1720
- expiration: expiration?.toISOString() || null
1721
- });
1722
- } catch (error) {
1723
- console.error("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Error updating authentication state:", error);
1724
- }
1725
- }, []);
1726
- const setToken = (0, import_react5.useCallback)((newToken) => {
1727
- console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: ===== STARTING TOKEN SET =====");
1728
- console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: New token:", newToken ? `${newToken.substring(0, 20)}...` : "null");
1729
- console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: Setting token in TokenManager...");
1730
- tokenManager.setToken(newToken);
1731
- console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: Updating state using newToken directly");
1732
- if (newToken) {
1733
- const parsedUser = tokenManager.parseToken(newToken);
1734
- const expiration = tokenManager.getTokenExpiration();
1735
- const authenticated = tokenManager.isTokenValid(newToken);
1736
- console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: Setting state values:");
1737
- console.log(" - setTokenState:", newToken ? `${newToken.substring(0, 20)}...` : "null");
1738
- console.log(" - setUser:", parsedUser?.email || "null");
1739
- console.log(" - setIsAuthenticated:", authenticated);
1740
- setTokenState(newToken);
1741
- setUser(parsedUser);
1742
- setTokenExpiration(expiration);
1743
- setIsAuthenticated(authenticated);
1744
- console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: \u2705 Token set, state updated", {
1745
- hasToken: true,
1746
- isAuthenticated: authenticated,
1747
- userEmail: parsedUser?.email || null
1748
- });
1749
- } else {
1750
- console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: Clearing all states");
1751
- setTokenState(null);
1752
- setUser(null);
1753
- setTokenExpiration(null);
1754
- setIsAuthenticated(false);
1755
- console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: \u2705 Token cleared, state reset");
1756
- }
1757
- console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: ===== TOKEN SET COMPLETE =====");
1758
- }, []);
1759
- const logout = (0, import_react5.useCallback)(() => {
1760
- console.log("\u{1F510} CrudifyDataProvider - LOGOUT_CALLBACK: Logging out user");
1761
- tokenManager.clearToken();
1762
- console.log("\u{1F510} CrudifyDataProvider - LOGOUT_CALLBACK: Updating state directly");
1763
- setTokenState(null);
1764
- setUser(null);
1765
- setTokenExpiration(null);
1766
- setIsAuthenticated(false);
1767
- console.log("\u{1F510} CrudifyDataProvider - LOGOUT_CALLBACK: User logged out, state cleared");
1768
- }, []);
1769
- const refreshConfig = (0, import_react5.useCallback)(() => {
1770
- console.log("\u{1F30D} CrudifyDataProvider - Refreshing configuration");
1771
- configurationManager.clearConfig();
1772
- const newConfig = initializeConfiguration();
1773
- if (newConfig && newConfig.publicApiKey) {
1774
- initializeCrudify(newConfig);
1775
- }
1776
- }, [initializeConfiguration, initializeCrudify]);
1777
- const reinitialize = (0, import_react5.useCallback)(async () => {
1778
- if (!config || !config.publicApiKey) {
1779
- console.warn("\u{1F680} CrudifyDataProvider - Cannot reinitialize without valid configuration");
1780
- return;
1781
- }
1782
- console.log("\u{1F680} CrudifyDataProvider - Force reinitializing crudify");
1783
- crudifyInitializer.reset();
1784
- await initializeCrudify(config);
1785
- }, [config, initializeCrudify]);
1786
- const getDebugInfo = (0, import_react5.useCallback)(() => {
1787
- return {
1788
- provider: {
1789
- isConfigured,
1790
- configError,
1791
- isInitialized,
1792
- isInitializing,
1793
- initializationError,
1794
- isAuthenticated
1795
- },
1796
- configuration: {
1797
- config: config ? {
1798
- env: config.env,
1799
- publicApiKey: `${config.publicApiKey.substring(0, 8)}...`,
1800
- appName: config.appName,
1801
- loginActionsCount: config.loginActions.length,
1802
- hasLogo: !!config.logo,
1803
- colorsCount: Object.keys(config.colors).length
1804
- } : null,
1805
- sources: config?.configSource || null,
1806
- rawConfig: config?.rawConfig || null
1807
- },
1808
- authentication: {
1809
- hasToken: !!token,
1810
- tokenLength: token?.length || 0,
1811
- userEmail: user?.email || null,
1812
- userId: user?.sub || null,
1813
- expiration: tokenExpiration?.toISOString() || null,
1814
- minutesUntilExpiry: tokenManager.getTimeUntilExpiration()
1815
- },
1816
- tokenManager: tokenManager.getDebugInfo(),
1817
- crudifyInitializer: crudifyInitializer.getStatus()
1818
- };
1819
- }, [isConfigured, configError, isInitialized, isInitializing, initializationError, isAuthenticated, config, token, user, tokenExpiration]);
1820
- (0, import_react5.useEffect)(() => {
1821
- console.log("\u{1F30D} CrudifyDataProvider - Provider mounting, starting initialization");
1822
- const resolvedConfig = initializeConfiguration();
1823
- updateAuthenticationState();
1824
- if (resolvedConfig && resolvedConfig.publicApiKey) {
1825
- initializeCrudify(resolvedConfig);
1911
+ if (typeof error === "object" && error !== null) {
1912
+ const response = error;
1913
+ if (response.data && Array.isArray(response.data)) {
1914
+ return parseTransactionError(error);
1826
1915
  }
1827
- return () => {
1828
- console.log("\u{1F30D} CrudifyDataProvider - Provider unmounting, cleaning up");
1829
- tokenManager.cleanup();
1830
- };
1831
- }, []);
1832
- (0, import_react5.useEffect)(() => {
1833
- console.log("\u{1F510} CrudifyDataProvider - INITIAL_AUTH_EFFECT: Loading initial authentication state");
1834
- updateAuthenticationState();
1835
- }, []);
1836
- const contextValue = {
1837
- // Configuration
1838
- config,
1839
- isConfigured,
1840
- configError,
1841
- configSource: config ? JSON.stringify(config.configSource) : "none",
1842
- // Initialization
1843
- isInitialized,
1844
- isInitializing,
1845
- initializationError,
1846
- // Authentication
1847
- isAuthenticated,
1848
- token,
1849
- user,
1850
- tokenExpiration,
1851
- // Actions
1852
- setToken,
1853
- logout,
1854
- refreshConfig,
1855
- reinitialize,
1856
- // Debug
1857
- getDebugInfo
1858
- };
1859
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CrudifyDataContext.Provider, { value: contextValue, children });
1860
- };
1861
- var useCrudifyDataContext = () => {
1862
- const context = (0, import_react5.useContext)(CrudifyDataContext);
1863
- if (!context) {
1864
- throw new Error(
1865
- "useCrudifyDataContext must be used within a CrudifyDataProvider. Make sure to wrap your app with <CrudifyDataProvider>."
1866
- );
1916
+ return parseApiError(error);
1867
1917
  }
1868
- return context;
1869
- };
1918
+ return [
1919
+ {
1920
+ code: ERROR_CODES.INTERNAL_SERVER_ERROR,
1921
+ message: "An unknown error occurred",
1922
+ severity: "error",
1923
+ details: { originalError: error }
1924
+ }
1925
+ ];
1926
+ }
1870
1927
 
1871
1928
  // src/hooks/useCrudifyAuth.ts
1929
+ init_CrudifyDataProvider();
1872
1930
  var useCrudifyAuth = () => {
1873
1931
  const {
1874
1932
  isAuthenticated,
@@ -2718,6 +2776,7 @@ var CrudifyInitializer2 = ({ children, fallback }) => {
2718
2776
 
2719
2777
  // src/components/CrudifyLogin/hooks/useCrudifyLogin.ts
2720
2778
  var import_react10 = require("react");
2779
+ init_cookies();
2721
2780
  var useCrudifyLogin = (config, _options = {}) => {
2722
2781
  const finalConfig = (0, import_react10.useMemo)(() => {
2723
2782
  const publicApiKey = config.publicApiKey || getCookie("publicApiKey") || null;
@@ -2844,6 +2903,7 @@ var import_icons_material = require("@mui/icons-material");
2844
2903
  // src/hooks/useUserProfile.ts
2845
2904
  var import_react11 = require("react");
2846
2905
  var import_crudify_browser4 = __toESM(require("@nocios/crudify-browser"));
2906
+ init_jwtUtils();
2847
2907
  var useUserProfile = (options = {}) => {
2848
2908
  const { autoFetch = true, retryOnError = false, maxRetries = 3 } = options;
2849
2909
  const [userProfile, setUserProfile] = (0, import_react11.useState)(null);
@@ -3144,9 +3204,13 @@ var UserProfileDisplay = ({
3144
3204
  };
3145
3205
  var UserProfileDisplay_default = UserProfileDisplay;
3146
3206
 
3207
+ // src/index.ts
3208
+ init_CrudifyDataProvider();
3209
+
3147
3210
  // src/hooks/useCrudifyUser.ts
3148
3211
  var import_react13 = require("react");
3149
3212
  var import_crudify_browser5 = __toESM(require("@nocios/crudify-browser"));
3213
+ init_CrudifyDataProvider();
3150
3214
  var useCrudifyUser = (options = {}) => {
3151
3215
  const { autoFetch = true, retryOnError = false, maxRetries = 3 } = options;
3152
3216
  const {
@@ -3351,6 +3415,7 @@ var useCrudifyUser = (options = {}) => {
3351
3415
  // src/hooks/useCrudifyData.ts
3352
3416
  var import_react14 = require("react");
3353
3417
  var import_crudify_browser6 = __toESM(require("@nocios/crudify-browser"));
3418
+ init_CrudifyDataProvider();
3354
3419
  var useCrudifyData = () => {
3355
3420
  const {
3356
3421
  isInitialized,
@@ -3502,6 +3567,7 @@ var useCrudifyData = () => {
3502
3567
  };
3503
3568
 
3504
3569
  // src/hooks/useCrudifyConfig.ts
3570
+ init_CrudifyDataProvider();
3505
3571
  var useCrudifyConfig = () => {
3506
3572
  const {
3507
3573
  config,
@@ -3525,6 +3591,7 @@ var useCrudifyConfig = () => {
3525
3591
  // src/hooks/useCrudifyInstance.ts
3526
3592
  var import_react15 = require("react");
3527
3593
  var import_crudify_browser7 = __toESM(require("@nocios/crudify-browser"));
3594
+ init_CrudifyDataProvider();
3528
3595
  var useCrudifyInstance = () => {
3529
3596
  const {
3530
3597
  isInitialized,
@@ -3533,28 +3600,32 @@ var useCrudifyInstance = () => {
3533
3600
  } = useCrudifyDataContext();
3534
3601
  const isReady = isInitialized && !initializationError && !isInitializing;
3535
3602
  const waitForReady = (0, import_react15.useCallback)(async () => {
3536
- if (isReady) return;
3603
+ console.log("\u{1F504} useCrudifyInstance - waitForReady: Starting wait");
3604
+ console.log(" - isReady:", isReady);
3605
+ console.log(" - isInitialized:", isInitialized);
3606
+ console.log(" - isInitializing:", isInitializing);
3607
+ console.log(" - initializationError:", initializationError);
3608
+ if (isReady) {
3609
+ console.log("\u2705 useCrudifyInstance - waitForReady: Already ready, returning immediately");
3610
+ return;
3611
+ }
3537
3612
  if (initializationError) {
3538
3613
  throw new Error(`Crudify initialization failed: ${initializationError}`);
3539
3614
  }
3540
- return new Promise((resolve, reject) => {
3541
- const maxWaitTime = 1e4;
3542
- const checkInterval = 100;
3543
- let elapsed = 0;
3544
- const check = () => {
3545
- if (isInitialized && !initializationError && !isInitializing) {
3546
- resolve();
3547
- } else if (initializationError) {
3548
- reject(new Error(`Crudify initialization failed: ${initializationError}`));
3549
- } else if (elapsed >= maxWaitTime) {
3550
- reject(new Error("Timeout waiting for crudify initialization"));
3551
- } else {
3552
- elapsed += checkInterval;
3553
- setTimeout(check, checkInterval);
3554
- }
3555
- };
3556
- check();
3557
- });
3615
+ try {
3616
+ console.log("\u{1F504} useCrudifyInstance - waitForReady: Using CrudifyInitializer.waitForInitialization()");
3617
+ const { crudifyInitializer: crudifyInitializer2 } = await Promise.resolve().then(() => (init_CrudifyDataProvider(), CrudifyDataProvider_exports));
3618
+ await crudifyInitializer2.waitForInitialization();
3619
+ console.log("\u2705 useCrudifyInstance - waitForReady: CrudifyInitializer completed");
3620
+ if (!crudifyInitializer2.isReady()) {
3621
+ const error = crudifyInitializer2.getError();
3622
+ throw new Error(`Crudify initialization failed: ${error || "Unknown error"}`);
3623
+ }
3624
+ console.log("\u2705 useCrudifyInstance - waitForReady: Verification successful");
3625
+ } catch (error) {
3626
+ console.error("\u274C useCrudifyInstance - waitForReady: Error during wait:", error);
3627
+ throw error;
3628
+ }
3558
3629
  }, [isReady, initializationError, isInitialized, isInitializing]);
3559
3630
  const ensureReady = (0, import_react15.useCallback)(async (operationName) => {
3560
3631
  if (!isReady) {
@@ -3683,6 +3754,39 @@ var useCrudifyInstance = () => {
3683
3754
  waitForReady
3684
3755
  };
3685
3756
  };
3757
+ var getCrudifyInstanceAsync = async () => {
3758
+ console.log("\u{1F504} getCrudifyInstanceAsync - Starting");
3759
+ const { crudifyInitializer: crudifyInitializer2 } = await Promise.resolve().then(() => (init_CrudifyDataProvider(), CrudifyDataProvider_exports));
3760
+ console.log("\u{1F504} getCrudifyInstanceAsync - Checking if ready");
3761
+ console.log(" - crudifyInitializer.isReady():", crudifyInitializer2.isReady());
3762
+ console.log(" - crudifyInitializer.getStatus():", crudifyInitializer2.getStatus());
3763
+ if (!crudifyInitializer2.isReady()) {
3764
+ console.log("\u{1F504} getCrudifyInstanceAsync - Waiting for crudify initialization...");
3765
+ await crudifyInitializer2.waitForInitialization();
3766
+ if (!crudifyInitializer2.isReady()) {
3767
+ const error = crudifyInitializer2.getError();
3768
+ throw new Error(`Crudify initialization failed: ${error || "Unknown error after waiting"}`);
3769
+ }
3770
+ console.log("\u2705 getCrudifyInstanceAsync - Crudify is ready after waiting");
3771
+ } else {
3772
+ console.log("\u2705 getCrudifyInstanceAsync - Already ready, no wait needed");
3773
+ }
3774
+ console.log("\u2705 getCrudifyInstanceAsync - Returning crudify instance");
3775
+ return import_crudify_browser7.default;
3776
+ };
3777
+ var getCrudifyInstanceSync = async () => {
3778
+ const { crudifyInitializer: crudifyInitializer2 } = await Promise.resolve().then(() => (init_CrudifyDataProvider(), CrudifyDataProvider_exports));
3779
+ if (!crudifyInitializer2.isReady()) {
3780
+ throw new Error("Crudify not ready. Use getCrudifyInstanceAsync() or call this from within a React component using useCrudifyInstance()");
3781
+ }
3782
+ return import_crudify_browser7.default;
3783
+ };
3784
+
3785
+ // src/index.ts
3786
+ init_CrudifyDataProvider();
3787
+ init_jwtUtils();
3788
+ init_cookies();
3789
+ init_secureStorage();
3686
3790
  // Annotate the CommonJS export names for ESM import in node:
3687
3791
  0 && (module.exports = {
3688
3792
  CrudifyDataProvider,
@@ -3695,6 +3799,8 @@ var useCrudifyInstance = () => {
3695
3799
  crudifyInitializer,
3696
3800
  decodeJwtSafely,
3697
3801
  getCookie,
3802
+ getCrudifyInstanceAsync,
3803
+ getCrudifyInstanceSync,
3698
3804
  getCurrentUserEmail,
3699
3805
  getErrorMessage,
3700
3806
  handleCrudifyError,