@nocios/crudify-ui 1.0.96 → 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, {
@@ -37,10 +1245,12 @@ __export(index_exports, {
37
1245
  ERROR_SEVERITY_MAP: () => ERROR_SEVERITY_MAP,
38
1246
  UserProfileDisplay: () => UserProfileDisplay_default,
39
1247
  configurationManager: () => configurationManager,
40
- crudify: () => import_crudify_browser7.default,
1248
+ crudify: () => import_crudify_browser8.default,
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,
@@ -55,12 +1265,13 @@ __export(index_exports, {
55
1265
  useCrudifyConfig: () => useCrudifyConfig,
56
1266
  useCrudifyData: () => useCrudifyData,
57
1267
  useCrudifyDataContext: () => useCrudifyDataContext,
1268
+ useCrudifyInstance: () => useCrudifyInstance,
58
1269
  useCrudifyLogin: () => useCrudifyLogin,
59
1270
  useCrudifyUser: () => useCrudifyUser,
60
1271
  useUserProfile: () => useUserProfile
61
1272
  });
62
1273
  module.exports = __toCommonJS(index_exports);
63
- var import_crudify_browser7 = __toESM(require("@nocios/crudify-browser"));
1274
+ var import_crudify_browser8 = __toESM(require("@nocios/crudify-browser"));
64
1275
  __reExport(index_exports, require("@nocios/crudify-browser"), module.exports);
65
1276
 
66
1277
  // src/components/CrudifyLogin/index.tsx
@@ -217,14 +1428,7 @@ var useCrudify = () => {
217
1428
 
218
1429
  // src/components/CrudifyLogin/context/LoginStateProvider.tsx
219
1430
  var import_react4 = require("react");
220
-
221
- // src/components/CrudifyLogin/utils/cookies.ts
222
- var getCookie = (name) => {
223
- const match = document.cookie.match(new RegExp("(^|;)\\s*" + name + "=([^;]+)"));
224
- return match ? match[2] : null;
225
- };
226
-
227
- // src/components/CrudifyLogin/context/LoginStateProvider.tsx
1431
+ init_cookies();
228
1432
  var import_jsx_runtime3 = require("react/jsx-runtime");
229
1433
  var initialState = {
230
1434
  currentScreen: "login",
@@ -449,115 +1653,7 @@ var useLoginState = () => {
449
1653
  // src/components/CrudifyLogin/Forms/LoginForm.tsx
450
1654
  var import_react6 = require("react");
451
1655
  var import_material = require("@mui/material");
452
-
453
- // src/components/CrudifyLogin/utils/secureStorage.ts
454
- var import_crypto_js = __toESM(require("crypto-js"));
455
- var SecureStorage = class {
456
- constructor(storageType = "sessionStorage") {
457
- this.encryptionKey = this.generateEncryptionKey();
458
- this.storage = storageType === "localStorage" ? window.localStorage : window.sessionStorage;
459
- }
460
- generateEncryptionKey() {
461
- const browserFingerprint = [
462
- navigator.userAgent,
463
- navigator.language,
464
- (/* @__PURE__ */ new Date()).getTimezoneOffset(),
465
- screen.colorDepth,
466
- screen.width,
467
- screen.height,
468
- "crudify-login"
469
- ].join("|");
470
- return import_crypto_js.default.SHA256(browserFingerprint).toString();
471
- }
472
- setItem(key, value, expiryMinutes) {
473
- try {
474
- const encrypted = import_crypto_js.default.AES.encrypt(value, this.encryptionKey).toString();
475
- this.storage.setItem(key, encrypted);
476
- if (expiryMinutes) {
477
- const expiryTime = (/* @__PURE__ */ new Date()).getTime() + expiryMinutes * 60 * 1e3;
478
- this.storage.setItem(`${key}_expiry`, expiryTime.toString());
479
- }
480
- } catch (error) {
481
- console.error("Failed to encrypt and store data:", error);
482
- }
483
- }
484
- getItem(key) {
485
- try {
486
- const expiryKey = `${key}_expiry`;
487
- const expiry = this.storage.getItem(expiryKey);
488
- if (expiry) {
489
- const expiryTime = parseInt(expiry, 10);
490
- if ((/* @__PURE__ */ new Date()).getTime() > expiryTime) {
491
- this.removeItem(key);
492
- return null;
493
- }
494
- }
495
- const encrypted = this.storage.getItem(key);
496
- if (!encrypted) return null;
497
- const decrypted = import_crypto_js.default.AES.decrypt(encrypted, this.encryptionKey);
498
- const result = decrypted.toString(import_crypto_js.default.enc.Utf8);
499
- if (!result) {
500
- console.warn("Failed to decrypt stored data - may be corrupted");
501
- this.removeItem(key);
502
- return null;
503
- }
504
- return result;
505
- } catch (error) {
506
- console.error("Failed to decrypt data:", error);
507
- this.removeItem(key);
508
- return null;
509
- }
510
- }
511
- removeItem(key) {
512
- this.storage.removeItem(key);
513
- this.storage.removeItem(`${key}_expiry`);
514
- }
515
- setToken(token) {
516
- try {
517
- const parts = token.split(".");
518
- if (parts.length === 3) {
519
- const payload = JSON.parse(atob(parts[1]));
520
- if (payload.exp) {
521
- const expiryTime = payload.exp * 1e3;
522
- const now = (/* @__PURE__ */ new Date()).getTime();
523
- const minutesUntilExpiry = Math.floor((expiryTime - now) / (60 * 1e3));
524
- if (minutesUntilExpiry > 0) {
525
- this.setItem("authToken", token, minutesUntilExpiry);
526
- return;
527
- }
528
- }
529
- }
530
- } catch (error) {
531
- console.warn("Failed to parse token expiry, using default expiry");
532
- }
533
- this.setItem("authToken", token, 24 * 60);
534
- }
535
- getToken() {
536
- const token = this.getItem("authToken");
537
- if (token) {
538
- try {
539
- const parts = token.split(".");
540
- if (parts.length === 3) {
541
- const payload = JSON.parse(atob(parts[1]));
542
- if (payload.exp) {
543
- const now = Math.floor(Date.now() / 1e3);
544
- if (payload.exp < now) {
545
- this.removeItem("authToken");
546
- return null;
547
- }
548
- }
549
- }
550
- } catch (error) {
551
- console.warn("Failed to validate token expiry");
552
- this.removeItem("authToken");
553
- return null;
554
- }
555
- }
556
- return token;
557
- }
558
- };
559
- var secureSessionStorage = new SecureStorage("sessionStorage");
560
- var secureLocalStorage = new SecureStorage("localStorage");
1656
+ init_secureStorage();
561
1657
 
562
1658
  // src/utils/errorHandler.ts
563
1659
  var ERROR_CODES = {
@@ -727,1139 +1823,110 @@ function parseTransactionError(response) {
727
1823
  severity: "warning",
728
1824
  details: { transactionIndex: index }
729
1825
  });
730
- } else if (!item.response || item.response.status !== "OK") {
731
- errors.push({
732
- code: ERROR_CODES.BAD_REQUEST,
733
- message: "Transaction failed",
734
- severity: "warning",
735
- details: { transactionIndex: index, response: item.response }
736
- });
737
- }
738
- });
739
- return errors;
740
- }
741
- return parseApiError(response);
742
- } catch (error) {
743
- return [
744
- {
745
- code: ERROR_CODES.INTERNAL_SERVER_ERROR,
746
- message: "Failed to parse transaction error",
747
- severity: "error",
748
- details: { originalError: error }
749
- }
750
- ];
751
- }
752
- }
753
- function isValidErrorCode(code) {
754
- return Object.values(ERROR_CODES).includes(code);
755
- }
756
- function getErrorMessage(code) {
757
- const messages = {
758
- [ERROR_CODES.INVALID_CREDENTIALS]: "Invalid email or password",
759
- [ERROR_CODES.UNAUTHORIZED]: "You are not authorized to perform this action",
760
- [ERROR_CODES.INVALID_API_KEY]: "Invalid API key",
761
- [ERROR_CODES.USER_NOT_FOUND]: "User not found",
762
- [ERROR_CODES.USER_NOT_ACTIVE]: "User account is not active",
763
- [ERROR_CODES.NO_PERMISSION]: "You do not have permission to perform this action",
764
- [ERROR_CODES.ITEM_NOT_FOUND]: "Item not found",
765
- [ERROR_CODES.NOT_FOUND]: "Resource not found",
766
- [ERROR_CODES.IN_USE]: "Resource is currently in use",
767
- [ERROR_CODES.FIELD_ERROR]: "Validation error",
768
- [ERROR_CODES.BAD_REQUEST]: "Invalid request",
769
- [ERROR_CODES.INVALID_EMAIL]: "Please enter a valid email address",
770
- [ERROR_CODES.INVALID_CODE]: "Invalid or expired code",
771
- [ERROR_CODES.INTERNAL_SERVER_ERROR]: "Internal server error",
772
- [ERROR_CODES.DATABASE_CONNECTION_ERROR]: "Database connection error",
773
- [ERROR_CODES.INVALID_CONFIGURATION]: "Invalid configuration",
774
- [ERROR_CODES.UNKNOWN_OPERATION]: "Unknown operation",
775
- [ERROR_CODES.TOO_MANY_REQUESTS]: "Too many requests. Please try again later.",
776
- [ERROR_CODES.NETWORK_ERROR]: "Network error. Please check your connection.",
777
- [ERROR_CODES.TIMEOUT_ERROR]: "Request timed out. Please try again."
778
- };
779
- return messages[code] || "An unknown error occurred";
780
- }
781
- function parseJavaScriptError(error) {
782
- if (error instanceof Error) {
783
- if (error.name === "AbortError") {
784
- return {
785
- code: ERROR_CODES.TIMEOUT_ERROR,
786
- message: "Request was cancelled",
787
- severity: "info"
788
- };
789
- }
790
- if (error.message.includes("NetworkError") || error.message.includes("Failed to fetch")) {
791
- return {
792
- code: ERROR_CODES.NETWORK_ERROR,
793
- message: getErrorMessage(ERROR_CODES.NETWORK_ERROR),
794
- severity: "error"
795
- };
796
- }
797
- return {
798
- code: ERROR_CODES.INTERNAL_SERVER_ERROR,
799
- message: error.message || "An unexpected error occurred",
800
- severity: "error",
801
- details: { originalError: error }
802
- };
803
- }
804
- return {
805
- code: ERROR_CODES.INTERNAL_SERVER_ERROR,
806
- message: "An unknown error occurred",
807
- severity: "error",
808
- details: { originalError: error }
809
- };
810
- }
811
- function handleCrudifyError(error) {
812
- if (error instanceof Error) {
813
- return [parseJavaScriptError(error)];
814
- }
815
- if (typeof error === "object" && error !== null) {
816
- const response = error;
817
- if (response.data && Array.isArray(response.data)) {
818
- return parseTransactionError(error);
819
- }
820
- return parseApiError(error);
821
- }
822
- return [
823
- {
824
- code: ERROR_CODES.INTERNAL_SERVER_ERROR,
825
- message: "An unknown error occurred",
826
- severity: "error",
827
- details: { originalError: error }
828
- }
829
- ];
830
- }
831
-
832
- // src/providers/CrudifyDataProvider.tsx
833
- var import_react5 = require("react");
834
-
835
- // src/core/ConfigurationManager.ts
836
- var _ConfigurationManager = class _ConfigurationManager {
837
- constructor() {
838
- this.resolvedConfig = null;
839
- this.configError = null;
840
- }
841
- /**
842
- * Singleton pattern to ensure consistent configuration across the app
843
- */
844
- static getInstance() {
845
- if (!_ConfigurationManager.instance) {
846
- _ConfigurationManager.instance = new _ConfigurationManager();
847
- }
848
- return _ConfigurationManager.instance;
849
- }
850
- /**
851
- * Reset the singleton instance (useful for testing)
852
- */
853
- static resetInstance() {
854
- _ConfigurationManager.instance = null;
855
- }
856
- /**
857
- * Resolve configuration from all sources with proper priority
858
- */
859
- resolveConfig(propsConfig = {}) {
860
- if (this.resolvedConfig && this.isConfigStillValid(propsConfig)) {
861
- return this.resolvedConfig;
862
- }
863
- try {
864
- this.configError = null;
865
- const envConfig = this.getEnvConfig();
866
- const cookieConfig = this.getCookieConfig();
867
- const configSource = {
868
- env: "default",
869
- publicApiKey: "default",
870
- loginActions: "default",
871
- appName: "default",
872
- logo: "default",
873
- colors: "default"
874
- };
875
- const env = this.resolveValue("env", propsConfig.env, envConfig.env, cookieConfig.env, "prod", configSource);
876
- const publicApiKey = this.resolveValue("publicApiKey", propsConfig.publicApiKey, envConfig.publicApiKey, cookieConfig.publicApiKey, void 0, configSource);
877
- const loginActions = this.resolveValue("loginActions", propsConfig.loginActions, envConfig.loginActions, cookieConfig.loginActions, [], configSource);
878
- const appName = this.resolveValue("appName", propsConfig.appName, envConfig.appName, cookieConfig.appName, "Crudify App", configSource);
879
- const logo = this.resolveValue("logo", propsConfig.logo, envConfig.logo, cookieConfig.logo, "", configSource);
880
- const colors = this.resolveValue("colors", propsConfig.colors, envConfig.colors, cookieConfig.colors, {}, configSource);
881
- if (!publicApiKey) {
882
- throw new Error(
883
- "publicApiKey is required. Provide it via:\n1. Props: <CrudifyDataProvider publicApiKey={...} />\n2. Environment: VITE_TEST_PUBLIC_API_KEY\n3. Cookie: publicApiKey"
884
- );
885
- }
886
- this.resolvedConfig = {
887
- env,
888
- publicApiKey,
889
- loginActions,
890
- appName,
891
- logo,
892
- colors,
893
- configSource,
894
- rawConfig: {
895
- props: propsConfig,
896
- env: envConfig,
897
- cookies: cookieConfig
898
- }
899
- };
900
- console.log("\u{1F527} ConfigurationManager - Configuration resolved:", {
901
- config: {
902
- env: this.resolvedConfig.env,
903
- publicApiKey: `${this.resolvedConfig.publicApiKey.substring(0, 8)}...`,
904
- appName: this.resolvedConfig.appName,
905
- loginActionsCount: this.resolvedConfig.loginActions.length
906
- },
907
- sources: this.resolvedConfig.configSource
908
- });
909
- return this.resolvedConfig;
910
- } catch (error) {
911
- this.configError = error instanceof Error ? error.message : "Unknown configuration error";
912
- console.error("\u{1F527} ConfigurationManager - Configuration error:", this.configError);
913
- this.resolvedConfig = {
914
- env: "prod",
915
- publicApiKey: "",
916
- loginActions: [],
917
- appName: "Crudify App",
918
- logo: "",
919
- colors: {},
920
- configSource: {
921
- env: "default",
922
- publicApiKey: "default",
923
- loginActions: "default",
924
- appName: "default",
925
- logo: "default",
926
- colors: "default"
927
- },
928
- rawConfig: {
929
- props: propsConfig,
930
- env: {},
931
- cookies: {},
932
- error: this.configError
933
- }
934
- };
935
- return this.resolvedConfig;
936
- }
937
- }
938
- /**
939
- * Check if current configuration is still valid for the given props
940
- */
941
- isConfigStillValid(propsConfig) {
942
- if (!this.resolvedConfig) return false;
943
- const currentProps = this.resolvedConfig.rawConfig.props;
944
- return JSON.stringify(currentProps) === JSON.stringify(propsConfig);
945
- }
946
- /**
947
- * Resolve a single config value with priority and source tracking
948
- */
949
- resolveValue(key, propsValue, envValue, cookieValue, defaultValue, configSource) {
950
- if (propsValue !== void 0) {
951
- configSource[key] = "props";
952
- return propsValue;
953
- }
954
- if (envValue !== void 0) {
955
- configSource[key] = "env";
956
- return envValue;
957
- }
958
- if (cookieValue !== void 0) {
959
- configSource[key] = "cookies";
960
- return cookieValue;
961
- }
962
- configSource[key] = "default";
963
- return defaultValue;
964
- }
965
- /**
966
- * Get configuration from environment variables
967
- */
968
- getEnvConfig() {
969
- const config = {};
970
- try {
971
- } catch (error) {
972
- console.warn("\u{1F527} ConfigurationManager - Environment variables not available:", error);
973
- }
974
- return config;
975
- }
976
- /**
977
- * Get configuration from cookies (multi-tenant support)
978
- */
979
- getCookieConfig() {
980
- const config = {};
981
- try {
982
- const env = getCookie("environment");
983
- if (env && ["dev", "stg", "prod"].includes(env)) {
984
- config.env = env;
985
- }
986
- const publicApiKey = getCookie("publicApiKey");
987
- if (publicApiKey) {
988
- config.publicApiKey = publicApiKey;
989
- }
990
- const appName = getCookie("appName");
991
- if (appName) {
992
- config.appName = appName;
993
- }
994
- const loginActions = getCookie("loginActions");
995
- if (loginActions) {
996
- config.loginActions = loginActions.split(",").map((action) => action.trim()).filter(Boolean);
997
- }
998
- const logo = getCookie("logo");
999
- if (logo) {
1000
- config.logo = logo;
1001
- }
1002
- const colors = getCookie("colors");
1003
- if (colors) {
1004
- try {
1005
- config.colors = JSON.parse(colors);
1006
- } catch (error) {
1007
- console.warn("\u{1F527} ConfigurationManager - Failed to parse colors from cookie:", error);
1008
- }
1009
- }
1010
- } catch (error) {
1011
- console.warn("\u{1F527} ConfigurationManager - Error reading cookies:", error);
1012
- }
1013
- return config;
1014
- }
1015
- /**
1016
- * Get the current resolved configuration
1017
- */
1018
- getConfig() {
1019
- return this.resolvedConfig;
1020
- }
1021
- /**
1022
- * Get any configuration errors
1023
- */
1024
- getConfigError() {
1025
- return this.configError;
1026
- }
1027
- /**
1028
- * Check if configuration is valid (no errors and has required fields)
1029
- */
1030
- isConfigured() {
1031
- return this.resolvedConfig !== null && this.configError === null && !!this.resolvedConfig.publicApiKey;
1032
- }
1033
- /**
1034
- * Clear the current configuration (useful for testing or reconfiguration)
1035
- */
1036
- clearConfig() {
1037
- this.resolvedConfig = null;
1038
- this.configError = null;
1039
- }
1040
- };
1041
- _ConfigurationManager.instance = null;
1042
- var ConfigurationManager = _ConfigurationManager;
1043
- var configurationManager = ConfigurationManager.getInstance();
1044
-
1045
- // src/core/CrudifyInitializer.ts
1046
- var import_crudify_browser2 = __toESM(require("@nocios/crudify-browser"));
1047
- var _CrudifyInitializer = class _CrudifyInitializer {
1048
- constructor() {
1049
- this.state = {
1050
- isInitialized: false,
1051
- isInitializing: false,
1052
- initializationError: null,
1053
- config: null,
1054
- initializationPromise: null
1055
- };
1056
- console.log("\u{1F680} CrudifyInitializer - Instance created");
1057
- }
1058
- /**
1059
- * Singleton pattern to ensure global initialization coordination
1060
- */
1061
- static getInstance() {
1062
- if (!_CrudifyInitializer.instance) {
1063
- _CrudifyInitializer.instance = new _CrudifyInitializer();
1064
- }
1065
- return _CrudifyInitializer.instance;
1066
- }
1067
- /**
1068
- * Reset the singleton instance (useful for testing)
1069
- */
1070
- static resetInstance() {
1071
- _CrudifyInitializer.instance = null;
1072
- }
1073
- /**
1074
- * Initialize crudify with the given configuration
1075
- * This method is idempotent and thread-safe
1076
- */
1077
- async initialize(config) {
1078
- if (this.state.isInitialized && this.isConfigurationSame(config)) {
1079
- console.log("\u{1F680} CrudifyInitializer - Already initialized with same config");
1080
- return;
1081
- }
1082
- if (this.state.isInitializing && this.state.initializationPromise) {
1083
- console.log("\u{1F680} CrudifyInitializer - Waiting for ongoing initialization");
1084
- await this.state.initializationPromise;
1085
- return;
1086
- }
1087
- if (this.state.isInitialized && !this.isConfigurationSame(config)) {
1088
- console.log("\u{1F680} CrudifyInitializer - Configuration changed, re-initializing");
1089
- this.reset();
1090
- }
1091
- this.state.isInitializing = true;
1092
- this.state.initializationError = null;
1093
- this.state.initializationPromise = this.performInitialization(config);
1094
- try {
1095
- await this.state.initializationPromise;
1096
- this.state.isInitialized = true;
1097
- this.state.config = { ...config };
1098
- console.log("\u{1F680} CrudifyInitializer - Initialization completed successfully");
1099
- } catch (error) {
1100
- this.state.initializationError = error instanceof Error ? error.message : "Unknown initialization error";
1101
- console.error("\u{1F680} CrudifyInitializer - Initialization failed:", this.state.initializationError);
1102
- throw error;
1103
- } finally {
1104
- this.state.isInitializing = false;
1105
- this.state.initializationPromise = null;
1106
- }
1107
- }
1108
- /**
1109
- * Perform the actual initialization process
1110
- */
1111
- async performInitialization(config) {
1112
- if (!config.publicApiKey) {
1113
- throw new Error("publicApiKey is required for crudify initialization");
1114
- }
1115
- console.log("\u{1F680} CrudifyInitializer - Starting initialization with config:", {
1116
- env: config.env,
1117
- publicApiKey: `${config.publicApiKey.substring(0, 8)}...`,
1118
- appName: config.appName
1119
- });
1120
- try {
1121
- const environment = config.env || "prod";
1122
- console.log("\u{1F680} CrudifyInitializer - Step 1: Configuring environment:", environment);
1123
- await import_crudify_browser2.default.config(environment);
1124
- console.log("\u{1F680} CrudifyInitializer - Step 2: Initializing with API key");
1125
- await import_crudify_browser2.default.init(config.publicApiKey, "none");
1126
- console.log("\u{1F680} CrudifyInitializer - Step 3: Verifying initialization");
1127
- await this.verifyInitialization();
1128
- console.log("\u{1F680} CrudifyInitializer - All initialization steps completed");
1129
- } catch (error) {
1130
- console.error("\u{1F680} CrudifyInitializer - Initialization failed at step:", error);
1131
- throw new Error(
1132
- `Crudify initialization failed: ${error instanceof Error ? error.message : "Unknown error"}. Please check your configuration (env: ${config.env || "prod"}, publicApiKey: ${config.publicApiKey ? "provided" : "missing"})`
1133
- );
1134
- }
1135
- }
1136
- /**
1137
- * Verify that crudify is properly initialized by checking core methods
1138
- */
1139
- async verifyInitialization() {
1140
- const requiredMethods = ["readItems", "readItem", "createItem", "updateItem", "deleteItem", "login", "transaction"];
1141
- const missingMethods = [];
1142
- for (const method of requiredMethods) {
1143
- if (typeof import_crudify_browser2.default[method] !== "function") {
1144
- missingMethods.push(method);
1145
- }
1146
- }
1147
- if (missingMethods.length > 0) {
1148
- throw new Error(
1149
- `Crudify initialization incomplete. Missing methods: ${missingMethods.join(", ")}. This usually indicates a configuration or network issue.`
1150
- );
1151
- }
1152
- console.log("\u{1F680} CrudifyInitializer - Verification successful (test call skipped for performance)");
1153
- }
1154
- /**
1155
- * Check if the given configuration is the same as the current one
1156
- */
1157
- isConfigurationSame(config) {
1158
- if (!this.state.config) return false;
1159
- return this.state.config.env === config.env && this.state.config.publicApiKey === config.publicApiKey;
1160
- }
1161
- /**
1162
- * Reset the initialization state (useful for testing or configuration changes)
1163
- */
1164
- reset() {
1165
- console.log("\u{1F680} CrudifyInitializer - Resetting initialization state");
1166
- this.state = {
1167
- isInitialized: false,
1168
- isInitializing: false,
1169
- initializationError: null,
1170
- config: null,
1171
- initializationPromise: null
1172
- };
1173
- }
1174
- /**
1175
- * Get the current initialization status
1176
- */
1177
- getStatus() {
1178
- return {
1179
- isInitialized: this.state.isInitialized,
1180
- isInitializing: this.state.isInitializing,
1181
- initializationError: this.state.initializationError,
1182
- config: this.state.config
1183
- };
1184
- }
1185
- /**
1186
- * Check if crudify is ready to use
1187
- */
1188
- isReady() {
1189
- return this.state.isInitialized && !this.state.initializationError;
1190
- }
1191
- /**
1192
- * Get the current initialization error, if any
1193
- */
1194
- getError() {
1195
- return this.state.initializationError;
1196
- }
1197
- /**
1198
- * Force re-initialization (useful when configuration changes)
1199
- */
1200
- async reinitialize(config) {
1201
- console.log("\u{1F680} CrudifyInitializer - Forcing re-initialization");
1202
- this.reset();
1203
- await this.initialize(config);
1204
- }
1205
- /**
1206
- * Check if initialization is currently in progress
1207
- */
1208
- isInitializing() {
1209
- return this.state.isInitializing;
1210
- }
1211
- /**
1212
- * Wait for any ongoing initialization to complete
1213
- */
1214
- async waitForInitialization() {
1215
- if (this.state.initializationPromise) {
1216
- await this.state.initializationPromise;
1217
- }
1218
- }
1219
- };
1220
- _CrudifyInitializer.instance = null;
1221
- var CrudifyInitializer = _CrudifyInitializer;
1222
- var crudifyInitializer = CrudifyInitializer.getInstance();
1223
-
1224
- // src/core/TokenManager.ts
1225
- var import_crudify_browser3 = __toESM(require("@nocios/crudify-browser"));
1226
-
1227
- // src/utils/jwtUtils.ts
1228
- var decodeJwtSafely = (token) => {
1229
- try {
1230
- const parts = token.split(".");
1231
- if (parts.length !== 3) {
1232
- console.warn("Invalid JWT format: token must have 3 parts");
1233
- return null;
1234
- }
1235
- const payload = parts[1];
1236
- const paddedPayload = payload + "=".repeat((4 - payload.length % 4) % 4);
1237
- const decodedPayload = JSON.parse(atob(paddedPayload));
1238
- return decodedPayload;
1239
- } catch (error) {
1240
- console.warn("Failed to decode JWT token:", error);
1241
- return null;
1242
- }
1243
- };
1244
- var getCurrentUserEmail = () => {
1245
- try {
1246
- let token = null;
1247
- token = sessionStorage.getItem("authToken");
1248
- console.log("\u{1F50D} getCurrentUserEmail - authToken:", token ? `${token.substring(0, 20)}...` : null);
1249
- if (!token) {
1250
- token = sessionStorage.getItem("token");
1251
- console.log("\u{1F50D} getCurrentUserEmail - token:", token ? `${token.substring(0, 20)}...` : null);
1252
- }
1253
- if (!token) {
1254
- token = localStorage.getItem("authToken") || localStorage.getItem("token");
1255
- console.log("\u{1F50D} getCurrentUserEmail - localStorage:", token ? `${token.substring(0, 20)}...` : null);
1256
- }
1257
- if (!token) {
1258
- console.warn("\u{1F50D} getCurrentUserEmail - No token found in any storage");
1259
- return null;
1260
- }
1261
- const payload = decodeJwtSafely(token);
1262
- if (!payload) {
1263
- console.warn("\u{1F50D} getCurrentUserEmail - Failed to decode token");
1264
- return null;
1265
- }
1266
- const email = payload.email || payload["cognito:username"] || null;
1267
- console.log("\u{1F50D} getCurrentUserEmail - Extracted email:", email);
1268
- return email;
1269
- } catch (error) {
1270
- console.warn("Failed to get current user email:", error);
1271
- return null;
1272
- }
1273
- };
1274
- var isTokenExpired = (token) => {
1275
- try {
1276
- const payload = decodeJwtSafely(token);
1277
- if (!payload || !payload.exp) return true;
1278
- const currentTime = Math.floor(Date.now() / 1e3);
1279
- return payload.exp < currentTime;
1280
- } catch {
1281
- return true;
1282
- }
1283
- };
1284
-
1285
- // src/core/TokenManager.ts
1286
- var _TokenManager = class _TokenManager {
1287
- constructor() {
1288
- this.TOKEN_KEY = "authToken";
1289
- // Compatible with crudia-ui
1290
- this.tokenCache = null;
1291
- this.parsedTokenCache = null;
1292
- this.expirationCheckInterval = null;
1293
- this.storageEventListener = null;
1294
- this.initializeTokenManager();
1295
- }
1296
- /**
1297
- * Singleton pattern to ensure consistent token management
1298
- */
1299
- static getInstance() {
1300
- if (!_TokenManager.instance) {
1301
- _TokenManager.instance = new _TokenManager();
1302
- }
1303
- return _TokenManager.instance;
1304
- }
1305
- /**
1306
- * Reset the singleton instance (useful for testing)
1307
- */
1308
- static resetInstance() {
1309
- if (_TokenManager.instance) {
1310
- _TokenManager.instance.cleanup();
1311
- }
1312
- _TokenManager.instance = null;
1313
- }
1314
- /**
1315
- * Initialize the token manager with storage synchronization
1316
- */
1317
- initializeTokenManager() {
1318
- console.log("\u{1F510} TokenManager - Initializing token management");
1319
- this.migrateFromLocalStorage();
1320
- this.loadTokenFromStorage();
1321
- this.setupExpirationCheck();
1322
- this.setupStorageListener();
1323
- console.log("\u{1F510} TokenManager - Initialization complete");
1324
- }
1325
- /**
1326
- * Migrate tokens from localStorage to sessionStorage for better security
1327
- * This ensures compatibility with older implementations
1328
- */
1329
- migrateFromLocalStorage() {
1330
- try {
1331
- const legacyKeys = ["authToken", "token", "jwt", "jwtToken"];
1332
- for (const key of legacyKeys) {
1333
- const token = localStorage.getItem(key);
1334
- if (token && !secureSessionStorage.getToken()) {
1335
- console.log(`\u{1F510} TokenManager - Migrating token from localStorage key: ${key}`);
1336
- secureSessionStorage.setToken(token);
1337
- localStorage.removeItem(key);
1338
- break;
1339
- }
1340
- }
1341
- } catch (error) {
1342
- console.warn("\u{1F510} TokenManager - Token migration failed:", error);
1343
- }
1344
- }
1345
- /**
1346
- * Load token from storage and synchronize with crudify
1347
- */
1348
- loadTokenFromStorage() {
1349
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Entry point - loading token from storage");
1350
- try {
1351
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Getting token from secure session storage");
1352
- const storedToken = secureSessionStorage.getToken();
1353
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Stored token exists:", !!storedToken);
1354
- if (storedToken && this.isTokenValid(storedToken)) {
1355
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Stored token is valid, updating cache");
1356
- this.tokenCache = storedToken;
1357
- this.parsedTokenCache = this.parseToken(storedToken);
1358
- this.syncTokenWithCrudify(storedToken);
1359
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Token loaded from storage and synchronized");
1360
- } else if (storedToken) {
1361
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Stored token exists but is invalid/expired, clearing");
1362
- this.clearToken();
1363
- } else {
1364
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: No stored token found");
1365
- }
1366
- } catch (error) {
1367
- console.warn("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Error loading token from storage:", error);
1368
- this.clearToken();
1369
- }
1370
- }
1371
- /**
1372
- * Set up automatic token expiration checking
1373
- */
1374
- setupExpirationCheck() {
1375
- this.expirationCheckInterval = window.setInterval(() => {
1376
- if (this.tokenCache && !this.isTokenValid(this.tokenCache)) {
1377
- console.log("\u{1F510} TokenManager - Token expired, clearing automatically");
1378
- this.clearToken();
1379
- }
1380
- }, 3e4);
1381
- }
1382
- /**
1383
- * Set up storage event listener for cross-tab synchronization
1384
- */
1385
- setupStorageListener() {
1386
- this.storageEventListener = (event) => {
1387
- if (event.key === this.TOKEN_KEY) {
1388
- console.log("\u{1F510} TokenManager - Token change detected from another tab");
1389
- this.loadTokenFromStorage();
1390
- }
1391
- };
1392
- window.addEventListener("storage", this.storageEventListener);
1393
- }
1394
- /**
1395
- * Set a new JWT token with automatic synchronization
1396
- */
1397
- setToken(token) {
1398
- console.log("\u{1F510} TokenManager - SET_TOKEN: Entry point - setting token:", token ? "provided" : "null");
1399
- try {
1400
- if (!token) {
1401
- console.log("\u{1F510} TokenManager - SET_TOKEN: No token provided, clearing token");
1402
- this.clearToken();
1403
- return;
1404
- }
1405
- console.log("\u{1F510} TokenManager - SET_TOKEN: Validating token before setting");
1406
- if (!this.isTokenValid(token)) {
1407
- console.warn("\u{1F510} TokenManager - SET_TOKEN: Attempted to set invalid or expired token");
1408
- this.clearToken();
1409
- return;
1410
- }
1411
- console.log("\u{1F510} TokenManager - SET_TOKEN: Token is valid, updating cache");
1412
- this.tokenCache = token;
1413
- this.parsedTokenCache = this.parseToken(token);
1414
- console.log("\u{1F510} TokenManager - SET_TOKEN: Storing token in secure storage");
1415
- secureSessionStorage.setToken(token);
1416
- console.log("\u{1F510} TokenManager - SET_TOKEN: Synchronizing with crudify");
1417
- this.syncTokenWithCrudify(token);
1418
- console.log("\u{1F510} TokenManager - SET_TOKEN: Token set and synchronized successfully");
1419
- } catch (error) {
1420
- console.error("\u{1F510} TokenManager - SET_TOKEN: Error setting token:", error);
1421
- this.clearToken();
1422
- }
1423
- }
1424
- /**
1425
- * Get the current JWT token
1426
- */
1427
- getToken() {
1428
- console.log("\u{1F510} TokenManager - GET_TOKEN: Entry point - checking cache");
1429
- if (this.tokenCache) {
1430
- console.log("\u{1F510} TokenManager - GET_TOKEN: Cache exists, validating token");
1431
- if (this.isTokenValid(this.tokenCache)) {
1432
- console.log("\u{1F510} TokenManager - GET_TOKEN: Cache valid, returning cached token");
1433
- return this.tokenCache;
1434
- } else {
1435
- console.log("\u{1F510} TokenManager - GET_TOKEN: Cache invalid, clearing cache");
1436
- this.tokenCache = null;
1437
- }
1438
- } else {
1439
- console.log("\u{1F510} TokenManager - GET_TOKEN: No cache, loading from storage");
1440
- }
1441
- console.log("\u{1F510} TokenManager - GET_TOKEN: Loading from storage");
1442
- this.loadTokenFromStorage();
1443
- console.log("\u{1F510} TokenManager - GET_TOKEN: Returning final token:", !!this.tokenCache);
1444
- return this.tokenCache;
1445
- }
1446
- /**
1447
- * Parse the current JWT token
1448
- */
1449
- parseToken(token) {
1450
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Entry point - parsing token");
1451
- const targetToken = token !== void 0 ? token : this.tokenCache;
1452
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Target token exists:", !!targetToken);
1453
- if (!targetToken) {
1454
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: No target token, returning null");
1455
- return null;
1456
- }
1457
- if (this.tokenCache === targetToken && this.parsedTokenCache) {
1458
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Returning cached parsed token");
1459
- return this.parsedTokenCache;
1460
- }
1461
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Cache miss, parsing token with decodeJwtSafely");
1462
- const parsed = decodeJwtSafely(targetToken);
1463
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Token parsed successfully:", !!parsed);
1464
- if (targetToken === this.tokenCache) {
1465
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Updating parsed token cache");
1466
- this.parsedTokenCache = parsed;
1467
- }
1468
- return parsed;
1469
- }
1470
- /**
1471
- * Check if a token is valid (properly formatted and not expired)
1472
- */
1473
- isTokenValid(token) {
1474
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Entry point - checking token validity");
1475
- const targetToken = token !== void 0 ? token : this.tokenCache;
1476
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Target token exists:", !!targetToken);
1477
- if (!targetToken) {
1478
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: No token, returning false");
1479
- return false;
1480
- }
1481
- try {
1482
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Checking if token is expired");
1483
- if (isTokenExpired(targetToken)) {
1484
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Token is expired, returning false");
1485
- return false;
1486
- }
1487
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Token not expired, checking if can be parsed");
1488
- const parsed = decodeJwtSafely(targetToken);
1489
- const isValid = parsed !== null;
1490
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Token parsing result:", isValid);
1491
- return isValid;
1492
- } catch (error) {
1493
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Error validating token:", error);
1494
- return false;
1495
- }
1496
- }
1497
- /**
1498
- * Get token expiration time as Date object
1499
- */
1500
- getTokenExpiration() {
1501
- const token = this.getToken();
1502
- if (!token) return null;
1503
- const parsed = this.parseToken(token);
1504
- if (!parsed?.exp) return null;
1505
- return new Date(parsed.exp * 1e3);
1506
- }
1507
- /**
1508
- * Clear the current token from all storages and crudify
1509
- */
1510
- clearToken() {
1511
- console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Entry point - clearing all tokens");
1512
- try {
1513
- console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Clearing cache");
1514
- this.tokenCache = null;
1515
- this.parsedTokenCache = null;
1516
- console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Clearing from secure storage");
1517
- secureSessionStorage.removeItem(this.TOKEN_KEY);
1518
- console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Clearing from crudify");
1519
- import_crudify_browser3.default.setToken("");
1520
- console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Token cleared from all storages successfully");
1521
- } catch (error) {
1522
- console.warn("\u{1F510} TokenManager - CLEAR_TOKEN: Error clearing token:", error);
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;
1523
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
+ ];
1524
1847
  }
1525
- /**
1526
- * Synchronize token with crudify library
1527
- */
1528
- syncTokenWithCrudify(token) {
1529
- try {
1530
- import_crudify_browser3.default.setToken(token);
1531
- console.log("\u{1F510} TokenManager - Token synchronized with crudify");
1532
- } catch (error) {
1533
- 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
+ };
1534
1885
  }
1535
- }
1536
- /**
1537
- * Refresh token (placeholder for future implementation)
1538
- */
1539
- async refreshToken() {
1540
- throw new Error("Token refresh not yet implemented");
1541
- }
1542
- /**
1543
- * Get user information from the current token
1544
- */
1545
- getUserInfo() {
1546
- const parsed = this.parseToken();
1547
- if (!parsed) {
1886
+ if (error.message.includes("NetworkError") || error.message.includes("Failed to fetch")) {
1548
1887
  return {
1549
- email: null,
1550
- userId: null,
1551
- userIdentifier: null,
1552
- username: null
1888
+ code: ERROR_CODES.NETWORK_ERROR,
1889
+ message: getErrorMessage(ERROR_CODES.NETWORK_ERROR),
1890
+ severity: "error"
1553
1891
  };
1554
1892
  }
1555
1893
  return {
1556
- email: parsed.email || null,
1557
- userId: parsed.sub || null,
1558
- userIdentifier: parsed["cognito:username"] || parsed.email || parsed.sub || null,
1559
- 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 }
1560
1898
  };
1561
1899
  }
1562
- /**
1563
- * Check if user is currently authenticated
1564
- */
1565
- isAuthenticated() {
1566
- return this.isTokenValid();
1567
- }
1568
- /**
1569
- * Get time until token expires in minutes
1570
- */
1571
- getTimeUntilExpiration() {
1572
- const expiration = this.getTokenExpiration();
1573
- if (!expiration) return null;
1574
- const now = /* @__PURE__ */ new Date();
1575
- const minutesUntilExpiry = Math.floor((expiration.getTime() - now.getTime()) / (60 * 1e3));
1576
- return Math.max(0, minutesUntilExpiry);
1577
- }
1578
- /**
1579
- * Cleanup resources (call when the component unmounts)
1580
- */
1581
- cleanup() {
1582
- if (this.expirationCheckInterval) {
1583
- window.clearInterval(this.expirationCheckInterval);
1584
- this.expirationCheckInterval = null;
1585
- }
1586
- if (this.storageEventListener) {
1587
- window.removeEventListener("storage", this.storageEventListener);
1588
- this.storageEventListener = null;
1589
- }
1590
- console.log("\u{1F510} TokenManager - Cleanup completed");
1591
- }
1592
- /**
1593
- * Get debug information about the current token state
1594
- */
1595
- getDebugInfo() {
1596
- const token = this.getToken();
1597
- const parsed = this.parseToken();
1598
- const expiration = this.getTokenExpiration();
1599
- return {
1600
- hasToken: !!token,
1601
- tokenLength: token?.length || 0,
1602
- isValid: this.isTokenValid(),
1603
- isAuthenticated: this.isAuthenticated(),
1604
- expiration: expiration?.toISOString() || null,
1605
- minutesUntilExpiry: this.getTimeUntilExpiration(),
1606
- userInfo: this.getUserInfo(),
1607
- parsedTokenKeys: parsed ? Object.keys(parsed) : []
1608
- };
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)];
1609
1910
  }
1610
- };
1611
- _TokenManager.instance = null;
1612
- var TokenManager = _TokenManager;
1613
- var tokenManager = TokenManager.getInstance();
1614
-
1615
- // src/providers/CrudifyDataProvider.tsx
1616
- var import_jsx_runtime4 = require("react/jsx-runtime");
1617
- var CrudifyDataContext = (0, import_react5.createContext)(null);
1618
- var CrudifyDataProvider = ({
1619
- children,
1620
- env,
1621
- publicApiKey,
1622
- loginActions,
1623
- appName,
1624
- logo,
1625
- colors
1626
- }) => {
1627
- const [config, setConfig] = (0, import_react5.useState)(null);
1628
- const [isConfigured, setIsConfigured] = (0, import_react5.useState)(false);
1629
- const [configError, setConfigError] = (0, import_react5.useState)(null);
1630
- const [isInitialized, setIsInitialized] = (0, import_react5.useState)(false);
1631
- const [isInitializing, setIsInitializing] = (0, import_react5.useState)(false);
1632
- const [initializationError, setInitializationError] = (0, import_react5.useState)(null);
1633
- const [isAuthenticated, setIsAuthenticated] = (0, import_react5.useState)(false);
1634
- const [token, setTokenState] = (0, import_react5.useState)(null);
1635
- const [user, setUser] = (0, import_react5.useState)(null);
1636
- const [tokenExpiration, setTokenExpiration] = (0, import_react5.useState)(null);
1637
- const initializeConfiguration = (0, import_react5.useCallback)(() => {
1638
- try {
1639
- console.log("\u{1F30D} CrudifyDataProvider - Initializing configuration");
1640
- const propsConfig = {
1641
- env,
1642
- publicApiKey,
1643
- loginActions,
1644
- appName,
1645
- logo,
1646
- colors
1647
- };
1648
- const resolvedConfig = configurationManager.resolveConfig(propsConfig);
1649
- const error = configurationManager.getConfigError();
1650
- setConfig(resolvedConfig);
1651
- setConfigError(error);
1652
- setIsConfigured(configurationManager.isConfigured());
1653
- console.log("\u{1F30D} CrudifyDataProvider - Configuration initialized:", {
1654
- isConfigured: configurationManager.isConfigured(),
1655
- error,
1656
- sources: resolvedConfig.configSource
1657
- });
1658
- return resolvedConfig;
1659
- } catch (error) {
1660
- const errorMessage = error instanceof Error ? error.message : "Configuration initialization failed";
1661
- console.error("\u{1F30D} CrudifyDataProvider - Configuration error:", errorMessage);
1662
- setConfigError(errorMessage);
1663
- setIsConfigured(false);
1664
- return null;
1665
- }
1666
- }, [env, publicApiKey, loginActions, appName, logo, colors]);
1667
- const initializeCrudify = (0, import_react5.useCallback)(async (resolvedConfig) => {
1668
- if (!resolvedConfig || !resolvedConfig.publicApiKey) {
1669
- setInitializationError("Cannot initialize crudify without valid configuration");
1670
- return;
1671
- }
1672
- try {
1673
- setIsInitializing(true);
1674
- setInitializationError(null);
1675
- console.log("\u{1F680} CrudifyDataProvider - Starting crudify initialization");
1676
- await crudifyInitializer.initialize({
1677
- env: resolvedConfig.env,
1678
- publicApiKey: resolvedConfig.publicApiKey,
1679
- loginActions: resolvedConfig.loginActions,
1680
- appName: resolvedConfig.appName,
1681
- logo: resolvedConfig.logo,
1682
- colors: resolvedConfig.colors
1683
- });
1684
- setIsInitialized(true);
1685
- console.log("\u{1F680} CrudifyDataProvider - Crudify initialization completed");
1686
- } catch (error) {
1687
- const errorMessage = error instanceof Error ? error.message : "Crudify initialization failed";
1688
- console.error("\u{1F680} CrudifyDataProvider - Initialization error:", errorMessage);
1689
- setInitializationError(errorMessage);
1690
- setIsInitialized(false);
1691
- } finally {
1692
- setIsInitializing(false);
1693
- }
1694
- }, []);
1695
- const updateAuthenticationState = (0, import_react5.useCallback)(() => {
1696
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Starting authentication state update");
1697
- try {
1698
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Getting token from TokenManager");
1699
- const currentToken = tokenManager.getToken();
1700
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Token retrieved:", !!currentToken);
1701
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Parsing token");
1702
- const parsedUser = tokenManager.parseToken();
1703
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Token parsed:", !!parsedUser);
1704
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Getting expiration");
1705
- const expiration = tokenManager.getTokenExpiration();
1706
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Expiration retrieved:", !!expiration);
1707
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Checking authentication");
1708
- const authenticated = tokenManager.isAuthenticated();
1709
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Authentication checked:", authenticated);
1710
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Updating state variables");
1711
- setTokenState(currentToken);
1712
- setUser(parsedUser);
1713
- setTokenExpiration(expiration);
1714
- setIsAuthenticated(authenticated);
1715
- console.log("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Authentication state updated successfully:", {
1716
- hasToken: !!currentToken,
1717
- isAuthenticated: authenticated,
1718
- userEmail: parsedUser?.email || null,
1719
- expiration: expiration?.toISOString() || null
1720
- });
1721
- } catch (error) {
1722
- console.error("\u{1F510} CrudifyDataProvider - UPDATE_AUTH_STATE: Error updating authentication state:", error);
1723
- }
1724
- }, []);
1725
- const setToken = (0, import_react5.useCallback)((newToken) => {
1726
- console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: Setting new token:", newToken ? "provided" : "null");
1727
- tokenManager.setToken(newToken);
1728
- console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: Updating state using newToken directly");
1729
- if (newToken) {
1730
- const parsedUser = tokenManager.parseToken(newToken);
1731
- const expiration = tokenManager.getTokenExpiration();
1732
- const authenticated = tokenManager.isTokenValid(newToken);
1733
- setTokenState(newToken);
1734
- setUser(parsedUser);
1735
- setTokenExpiration(expiration);
1736
- setIsAuthenticated(authenticated);
1737
- console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: Token set, state updated", {
1738
- hasToken: true,
1739
- isAuthenticated: authenticated,
1740
- userEmail: parsedUser?.email || null
1741
- });
1742
- } else {
1743
- setTokenState(null);
1744
- setUser(null);
1745
- setTokenExpiration(null);
1746
- setIsAuthenticated(false);
1747
- console.log("\u{1F510} CrudifyDataProvider - SET_TOKEN_CALLBACK: Token cleared, state reset");
1748
- }
1749
- }, []);
1750
- const logout = (0, import_react5.useCallback)(() => {
1751
- console.log("\u{1F510} CrudifyDataProvider - LOGOUT_CALLBACK: Logging out user");
1752
- tokenManager.clearToken();
1753
- console.log("\u{1F510} CrudifyDataProvider - LOGOUT_CALLBACK: Updating state directly");
1754
- setTokenState(null);
1755
- setUser(null);
1756
- setTokenExpiration(null);
1757
- setIsAuthenticated(false);
1758
- console.log("\u{1F510} CrudifyDataProvider - LOGOUT_CALLBACK: User logged out, state cleared");
1759
- }, []);
1760
- const refreshConfig = (0, import_react5.useCallback)(() => {
1761
- console.log("\u{1F30D} CrudifyDataProvider - Refreshing configuration");
1762
- configurationManager.clearConfig();
1763
- const newConfig = initializeConfiguration();
1764
- if (newConfig && newConfig.publicApiKey) {
1765
- initializeCrudify(newConfig);
1766
- }
1767
- }, [initializeConfiguration, initializeCrudify]);
1768
- const reinitialize = (0, import_react5.useCallback)(async () => {
1769
- if (!config || !config.publicApiKey) {
1770
- console.warn("\u{1F680} CrudifyDataProvider - Cannot reinitialize without valid configuration");
1771
- return;
1772
- }
1773
- console.log("\u{1F680} CrudifyDataProvider - Force reinitializing crudify");
1774
- crudifyInitializer.reset();
1775
- await initializeCrudify(config);
1776
- }, [config, initializeCrudify]);
1777
- const getDebugInfo = (0, import_react5.useCallback)(() => {
1778
- return {
1779
- provider: {
1780
- isConfigured,
1781
- configError,
1782
- isInitialized,
1783
- isInitializing,
1784
- initializationError,
1785
- isAuthenticated
1786
- },
1787
- configuration: {
1788
- config: config ? {
1789
- env: config.env,
1790
- publicApiKey: `${config.publicApiKey.substring(0, 8)}...`,
1791
- appName: config.appName,
1792
- loginActionsCount: config.loginActions.length,
1793
- hasLogo: !!config.logo,
1794
- colorsCount: Object.keys(config.colors).length
1795
- } : null,
1796
- sources: config?.configSource || null,
1797
- rawConfig: config?.rawConfig || null
1798
- },
1799
- authentication: {
1800
- hasToken: !!token,
1801
- tokenLength: token?.length || 0,
1802
- userEmail: user?.email || null,
1803
- userId: user?.sub || null,
1804
- expiration: tokenExpiration?.toISOString() || null,
1805
- minutesUntilExpiry: tokenManager.getTimeUntilExpiration()
1806
- },
1807
- tokenManager: tokenManager.getDebugInfo(),
1808
- crudifyInitializer: crudifyInitializer.getStatus()
1809
- };
1810
- }, [isConfigured, configError, isInitialized, isInitializing, initializationError, isAuthenticated, config, token, user, tokenExpiration]);
1811
- (0, import_react5.useEffect)(() => {
1812
- console.log("\u{1F30D} CrudifyDataProvider - Provider mounting, starting initialization");
1813
- const resolvedConfig = initializeConfiguration();
1814
- updateAuthenticationState();
1815
- if (resolvedConfig && resolvedConfig.publicApiKey) {
1816
- 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);
1817
1915
  }
1818
- return () => {
1819
- console.log("\u{1F30D} CrudifyDataProvider - Provider unmounting, cleaning up");
1820
- tokenManager.cleanup();
1821
- };
1822
- }, []);
1823
- (0, import_react5.useEffect)(() => {
1824
- console.log("\u{1F510} CrudifyDataProvider - INITIAL_AUTH_EFFECT: Loading initial authentication state");
1825
- updateAuthenticationState();
1826
- }, []);
1827
- const contextValue = {
1828
- // Configuration
1829
- config,
1830
- isConfigured,
1831
- configError,
1832
- configSource: config ? JSON.stringify(config.configSource) : "none",
1833
- // Initialization
1834
- isInitialized,
1835
- isInitializing,
1836
- initializationError,
1837
- // Authentication
1838
- isAuthenticated,
1839
- token,
1840
- user,
1841
- tokenExpiration,
1842
- // Actions
1843
- setToken,
1844
- logout,
1845
- refreshConfig,
1846
- reinitialize,
1847
- // Debug
1848
- getDebugInfo
1849
- };
1850
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CrudifyDataContext.Provider, { value: contextValue, children });
1851
- };
1852
- var useCrudifyDataContext = () => {
1853
- const context = (0, import_react5.useContext)(CrudifyDataContext);
1854
- if (!context) {
1855
- throw new Error(
1856
- "useCrudifyDataContext must be used within a CrudifyDataProvider. Make sure to wrap your app with <CrudifyDataProvider>."
1857
- );
1916
+ return parseApiError(error);
1858
1917
  }
1859
- return context;
1860
- };
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
+ }
1861
1927
 
1862
1928
  // src/hooks/useCrudifyAuth.ts
1929
+ init_CrudifyDataProvider();
1863
1930
  var useCrudifyAuth = () => {
1864
1931
  const {
1865
1932
  isAuthenticated,
@@ -1891,7 +1958,7 @@ var useCrudifyAuth = () => {
1891
1958
  // src/components/CrudifyLogin/Forms/LoginForm.tsx
1892
1959
  var import_jsx_runtime5 = require("react/jsx-runtime");
1893
1960
  var LoginForm = ({ onScreenChange, onExternalNavigate, onLoginSuccess, onError, redirectUrl = "/" }) => {
1894
- const { crudify: crudify7 } = useCrudify();
1961
+ const { crudify: crudify8 } = useCrudify();
1895
1962
  const { state, updateFormData, setFieldError, clearErrors, setLoading } = useLoginState();
1896
1963
  const { setToken } = useCrudifyAuth();
1897
1964
  const { t } = useTranslation();
@@ -1943,16 +2010,21 @@ var LoginForm = ({ onScreenChange, onExternalNavigate, onLoginSuccess, onError,
1943
2010
  clearErrors();
1944
2011
  setLoading(true);
1945
2012
  try {
1946
- if (!crudify7) {
2013
+ if (!crudify8) {
1947
2014
  throw new Error("Crudify not initialized");
1948
2015
  }
1949
- const response = await crudify7.login(state.formData.username, state.formData.password);
2016
+ const response = await crudify8.login(state.formData.username, state.formData.password);
1950
2017
  setLoading(false);
1951
2018
  if (response.success) {
2019
+ console.log("\u{1F510} LoginForm - Login successful, setting tokens");
1952
2020
  secureSessionStorage.setToken(response.data.token);
2021
+ console.log("\u{1F510} LoginForm - Token set in secureSessionStorage");
2022
+ console.log("\u{1F510} LoginForm - Setting token in CrudifyDataProvider via setToken hook");
1953
2023
  setToken(response.data.token);
2024
+ console.log("\u{1F510} LoginForm - Token set in CrudifyDataProvider");
1954
2025
  const finalRedirectUrl = getRedirectUrl();
1955
2026
  setTimeout(() => {
2027
+ console.log("\u{1F510} LoginForm - Calling onLoginSuccess after delay");
1956
2028
  if (onLoginSuccess) {
1957
2029
  onLoginSuccess(response.data, finalRedirectUrl);
1958
2030
  }
@@ -2104,7 +2176,7 @@ var import_react7 = require("react");
2104
2176
  var import_material2 = require("@mui/material");
2105
2177
  var import_jsx_runtime6 = require("react/jsx-runtime");
2106
2178
  var ForgotPasswordForm = ({ onScreenChange, onError }) => {
2107
- const { crudify: crudify7 } = useCrudify();
2179
+ const { crudify: crudify8 } = useCrudify();
2108
2180
  const [email, setEmail] = (0, import_react7.useState)("");
2109
2181
  const [loading, setLoading] = (0, import_react7.useState)(false);
2110
2182
  const [errors, setErrors] = (0, import_react7.useState)([]);
@@ -2133,7 +2205,7 @@ var ForgotPasswordForm = ({ onScreenChange, onError }) => {
2133
2205
  return emailRegex.test(email2);
2134
2206
  };
2135
2207
  const handleSubmit = async () => {
2136
- if (loading || !crudify7) return;
2208
+ if (loading || !crudify8) return;
2137
2209
  setErrors([]);
2138
2210
  setHelperTextEmail(null);
2139
2211
  if (!email) {
@@ -2147,7 +2219,7 @@ var ForgotPasswordForm = ({ onScreenChange, onError }) => {
2147
2219
  setLoading(true);
2148
2220
  try {
2149
2221
  const data = [{ operation: "requestPasswordReset", data: { email } }];
2150
- const response = await crudify7.transaction(data);
2222
+ const response = await crudify8.transaction(data);
2151
2223
  if (response.success) {
2152
2224
  if (response.data && response.data.existingCodeValid) {
2153
2225
  setCodeAlreadyExists(true);
@@ -2250,7 +2322,7 @@ var import_react8 = require("react");
2250
2322
  var import_material3 = require("@mui/material");
2251
2323
  var import_jsx_runtime7 = require("react/jsx-runtime");
2252
2324
  var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess }) => {
2253
- const { crudify: crudify7 } = useCrudify();
2325
+ const { crudify: crudify8 } = useCrudify();
2254
2326
  const [newPassword, setNewPassword] = (0, import_react8.useState)("");
2255
2327
  const [confirmPassword, setConfirmPassword] = (0, import_react8.useState)("");
2256
2328
  const [loading, setLoading] = (0, import_react8.useState)(false);
@@ -2330,9 +2402,9 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
2330
2402
  setErrors([t("resetPassword.invalidCode")]);
2331
2403
  setValidatingCode(false);
2332
2404
  setTimeout(() => onScreenChange?.("forgotPassword"), 3e3);
2333
- }, [searchParams, crudify7, t, onScreenChange]);
2405
+ }, [searchParams, crudify8, t, onScreenChange]);
2334
2406
  (0, import_react8.useEffect)(() => {
2335
- if (crudify7 && pendingValidation && !isValidating) {
2407
+ if (crudify8 && pendingValidation && !isValidating) {
2336
2408
  setIsValidating(true);
2337
2409
  const validateCode = async (emailToValidate, codeToValidate) => {
2338
2410
  try {
@@ -2342,7 +2414,7 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
2342
2414
  data: { email: emailToValidate, codePassword: codeToValidate }
2343
2415
  }
2344
2416
  ];
2345
- const response = await crudify7.transaction(data);
2417
+ const response = await crudify8.transaction(data);
2346
2418
  if (response.data && Array.isArray(response.data)) {
2347
2419
  const validationResult = response.data[0];
2348
2420
  if (validationResult && validationResult.response && validationResult.response.status === "OK") {
@@ -2371,7 +2443,7 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
2371
2443
  };
2372
2444
  validateCode(pendingValidation.email, pendingValidation.code);
2373
2445
  }
2374
- }, [crudify7, pendingValidation, t, onScreenChange]);
2446
+ }, [crudify8, pendingValidation, t, onScreenChange]);
2375
2447
  const validatePassword = (password) => {
2376
2448
  if (password.length < 8) {
2377
2449
  return t("resetPassword.passwordTooShort");
@@ -2379,7 +2451,7 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
2379
2451
  return null;
2380
2452
  };
2381
2453
  const handleSubmit = async () => {
2382
- if (loading || !crudify7) return;
2454
+ if (loading || !crudify8) return;
2383
2455
  setErrors([]);
2384
2456
  setHelperTextNewPassword(null);
2385
2457
  setHelperTextConfirmPassword(null);
@@ -2410,7 +2482,7 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
2410
2482
  data: { email, codePassword: code, newPassword }
2411
2483
  }
2412
2484
  ];
2413
- const response = await crudify7.transaction(data);
2485
+ const response = await crudify8.transaction(data);
2414
2486
  if (response.success) {
2415
2487
  setErrors([]);
2416
2488
  setTimeout(() => {
@@ -2521,7 +2593,7 @@ var import_react9 = require("react");
2521
2593
  var import_material4 = require("@mui/material");
2522
2594
  var import_jsx_runtime8 = require("react/jsx-runtime");
2523
2595
  var CheckCodeForm = ({ onScreenChange, onError, searchParams }) => {
2524
- const { crudify: crudify7 } = useCrudify();
2596
+ const { crudify: crudify8 } = useCrudify();
2525
2597
  const [code, setCode] = (0, import_react9.useState)("");
2526
2598
  const [loading, setLoading] = (0, import_react9.useState)(false);
2527
2599
  const [errors, setErrors] = (0, import_react9.useState)([]);
@@ -2560,7 +2632,7 @@ var CheckCodeForm = ({ onScreenChange, onError, searchParams }) => {
2560
2632
  }
2561
2633
  }, [searchParams, onScreenChange]);
2562
2634
  const handleSubmit = async () => {
2563
- if (loading || !crudify7) return;
2635
+ if (loading || !crudify8) return;
2564
2636
  setErrors([]);
2565
2637
  setHelperTextCode(null);
2566
2638
  if (!code) {
@@ -2579,7 +2651,7 @@ var CheckCodeForm = ({ onScreenChange, onError, searchParams }) => {
2579
2651
  data: { email, codePassword: code }
2580
2652
  }
2581
2653
  ];
2582
- const response = await crudify7.transaction(data);
2654
+ const response = await crudify8.transaction(data);
2583
2655
  if (response.success) {
2584
2656
  onScreenChange?.("resetPassword", { email, code, fromCodeVerification: "true" });
2585
2657
  } else {
@@ -2704,6 +2776,7 @@ var CrudifyInitializer2 = ({ children, fallback }) => {
2704
2776
 
2705
2777
  // src/components/CrudifyLogin/hooks/useCrudifyLogin.ts
2706
2778
  var import_react10 = require("react");
2779
+ init_cookies();
2707
2780
  var useCrudifyLogin = (config, _options = {}) => {
2708
2781
  const finalConfig = (0, import_react10.useMemo)(() => {
2709
2782
  const publicApiKey = config.publicApiKey || getCookie("publicApiKey") || null;
@@ -2830,6 +2903,7 @@ var import_icons_material = require("@mui/icons-material");
2830
2903
  // src/hooks/useUserProfile.ts
2831
2904
  var import_react11 = require("react");
2832
2905
  var import_crudify_browser4 = __toESM(require("@nocios/crudify-browser"));
2906
+ init_jwtUtils();
2833
2907
  var useUserProfile = (options = {}) => {
2834
2908
  const { autoFetch = true, retryOnError = false, maxRetries = 3 } = options;
2835
2909
  const [userProfile, setUserProfile] = (0, import_react11.useState)(null);
@@ -3130,9 +3204,13 @@ var UserProfileDisplay = ({
3130
3204
  };
3131
3205
  var UserProfileDisplay_default = UserProfileDisplay;
3132
3206
 
3207
+ // src/index.ts
3208
+ init_CrudifyDataProvider();
3209
+
3133
3210
  // src/hooks/useCrudifyUser.ts
3134
3211
  var import_react13 = require("react");
3135
3212
  var import_crudify_browser5 = __toESM(require("@nocios/crudify-browser"));
3213
+ init_CrudifyDataProvider();
3136
3214
  var useCrudifyUser = (options = {}) => {
3137
3215
  const { autoFetch = true, retryOnError = false, maxRetries = 3 } = options;
3138
3216
  const {
@@ -3337,6 +3415,7 @@ var useCrudifyUser = (options = {}) => {
3337
3415
  // src/hooks/useCrudifyData.ts
3338
3416
  var import_react14 = require("react");
3339
3417
  var import_crudify_browser6 = __toESM(require("@nocios/crudify-browser"));
3418
+ init_CrudifyDataProvider();
3340
3419
  var useCrudifyData = () => {
3341
3420
  const {
3342
3421
  isInitialized,
@@ -3378,7 +3457,14 @@ var useCrudifyData = () => {
3378
3457
  }, [isReady, initializationError, isInitializing]);
3379
3458
  const readItems = (0, import_react14.useCallback)(async (moduleKey, filter, options) => {
3380
3459
  ensureReady("readItems");
3381
- console.log("\u{1F4CA} useCrudifyData - readItems:", { moduleKey, filter, options });
3460
+ console.log("\u{1F4CA} useCrudifyData - readItems called with:");
3461
+ console.log(" - moduleKey:", moduleKey);
3462
+ console.log(" - filter:", filter);
3463
+ console.log(" - options:", options);
3464
+ if (moduleKey === "__test_connection__") {
3465
+ console.error("\u{1F6A8} FOUND TEST CONNECTION CALL! Stack trace:");
3466
+ console.error(new Error().stack);
3467
+ }
3382
3468
  try {
3383
3469
  const response = await import_crudify_browser6.default.readItems(moduleKey, filter || {}, options);
3384
3470
  console.log("\u{1F4CA} useCrudifyData - readItems response:", response);
@@ -3481,6 +3567,7 @@ var useCrudifyData = () => {
3481
3567
  };
3482
3568
 
3483
3569
  // src/hooks/useCrudifyConfig.ts
3570
+ init_CrudifyDataProvider();
3484
3571
  var useCrudifyConfig = () => {
3485
3572
  const {
3486
3573
  config,
@@ -3500,6 +3587,206 @@ var useCrudifyConfig = () => {
3500
3587
  getDebugInfo
3501
3588
  };
3502
3589
  };
3590
+
3591
+ // src/hooks/useCrudifyInstance.ts
3592
+ var import_react15 = require("react");
3593
+ var import_crudify_browser7 = __toESM(require("@nocios/crudify-browser"));
3594
+ init_CrudifyDataProvider();
3595
+ var useCrudifyInstance = () => {
3596
+ const {
3597
+ isInitialized,
3598
+ isInitializing,
3599
+ initializationError
3600
+ } = useCrudifyDataContext();
3601
+ const isReady = isInitialized && !initializationError && !isInitializing;
3602
+ const waitForReady = (0, import_react15.useCallback)(async () => {
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
+ }
3612
+ if (initializationError) {
3613
+ throw new Error(`Crudify initialization failed: ${initializationError}`);
3614
+ }
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
+ }
3629
+ }, [isReady, initializationError, isInitialized, isInitializing]);
3630
+ const ensureReady = (0, import_react15.useCallback)(async (operationName) => {
3631
+ if (!isReady) {
3632
+ console.log(`\u{1F504} useCrudifyInstance - ${operationName}: Waiting for crudify to be ready...`);
3633
+ await waitForReady();
3634
+ console.log(`\u2705 useCrudifyInstance - ${operationName}: Crudify is ready`);
3635
+ }
3636
+ }, [isReady, waitForReady]);
3637
+ const getStructure = (0, import_react15.useCallback)(async (options) => {
3638
+ console.log("\u{1F4E1} useCrudifyInstance - getStructure: Starting");
3639
+ await ensureReady("getStructure");
3640
+ try {
3641
+ console.log("\u{1F4E1} useCrudifyInstance - getStructure: Calling crudify.getStructure");
3642
+ const response = await import_crudify_browser7.default.getStructure(options);
3643
+ console.log("\u{1F4E1} useCrudifyInstance - getStructure: Response received", response);
3644
+ return response;
3645
+ } catch (error) {
3646
+ console.error("\u{1F4E1} useCrudifyInstance - getStructure: Error", error);
3647
+ throw error;
3648
+ }
3649
+ }, [ensureReady]);
3650
+ const getStructurePublic = (0, import_react15.useCallback)(async (options) => {
3651
+ console.log("\u{1F4E1} useCrudifyInstance - getStructurePublic: Starting");
3652
+ await ensureReady("getStructurePublic");
3653
+ try {
3654
+ console.log("\u{1F4E1} useCrudifyInstance - getStructurePublic: Calling crudify.getStructurePublic");
3655
+ const response = await import_crudify_browser7.default.getStructurePublic(options);
3656
+ console.log("\u{1F4E1} useCrudifyInstance - getStructurePublic: Response received", response);
3657
+ return response;
3658
+ } catch (error) {
3659
+ console.error("\u{1F4E1} useCrudifyInstance - getStructurePublic: Error", error);
3660
+ throw error;
3661
+ }
3662
+ }, [ensureReady]);
3663
+ const readItems = (0, import_react15.useCallback)(async (moduleKey, filter, options) => {
3664
+ await ensureReady("readItems");
3665
+ if (moduleKey === "__test_connection__") {
3666
+ console.error("\u{1F6A8} FOUND TEST CONNECTION CALL in useCrudifyInstance! Stack trace:");
3667
+ console.error(new Error().stack);
3668
+ }
3669
+ try {
3670
+ const response = await import_crudify_browser7.default.readItems(moduleKey, filter || {}, options);
3671
+ return response;
3672
+ } catch (error) {
3673
+ console.error("\u{1F4CA} useCrudifyInstance - readItems error:", error);
3674
+ throw error;
3675
+ }
3676
+ }, [ensureReady]);
3677
+ const readItem = (0, import_react15.useCallback)(async (moduleKey, filter, options) => {
3678
+ await ensureReady("readItem");
3679
+ try {
3680
+ const response = await import_crudify_browser7.default.readItem(moduleKey, filter, options);
3681
+ return response;
3682
+ } catch (error) {
3683
+ console.error("\u{1F4CA} useCrudifyInstance - readItem error:", error);
3684
+ throw error;
3685
+ }
3686
+ }, [ensureReady]);
3687
+ const createItem = (0, import_react15.useCallback)(async (moduleKey, data, options) => {
3688
+ await ensureReady("createItem");
3689
+ try {
3690
+ const response = await import_crudify_browser7.default.createItem(moduleKey, data, options);
3691
+ return response;
3692
+ } catch (error) {
3693
+ console.error("\u{1F4CA} useCrudifyInstance - createItem error:", error);
3694
+ throw error;
3695
+ }
3696
+ }, [ensureReady]);
3697
+ const updateItem = (0, import_react15.useCallback)(async (moduleKey, data, options) => {
3698
+ await ensureReady("updateItem");
3699
+ try {
3700
+ const response = await import_crudify_browser7.default.updateItem(moduleKey, data, options);
3701
+ return response;
3702
+ } catch (error) {
3703
+ console.error("\u{1F4CA} useCrudifyInstance - updateItem error:", error);
3704
+ throw error;
3705
+ }
3706
+ }, [ensureReady]);
3707
+ const deleteItem = (0, import_react15.useCallback)(async (moduleKey, id, options) => {
3708
+ await ensureReady("deleteItem");
3709
+ try {
3710
+ const response = await import_crudify_browser7.default.deleteItem(moduleKey, id, options);
3711
+ return response;
3712
+ } catch (error) {
3713
+ console.error("\u{1F4CA} useCrudifyInstance - deleteItem error:", error);
3714
+ throw error;
3715
+ }
3716
+ }, [ensureReady]);
3717
+ const transaction = (0, import_react15.useCallback)(async (operations, options) => {
3718
+ await ensureReady("transaction");
3719
+ try {
3720
+ const response = await import_crudify_browser7.default.transaction(operations, options);
3721
+ return response;
3722
+ } catch (error) {
3723
+ console.error("\u{1F4CA} useCrudifyInstance - transaction error:", error);
3724
+ throw error;
3725
+ }
3726
+ }, [ensureReady]);
3727
+ const login = (0, import_react15.useCallback)(async (email, password) => {
3728
+ await ensureReady("login");
3729
+ try {
3730
+ const response = await import_crudify_browser7.default.login(email, password);
3731
+ return response;
3732
+ } catch (error) {
3733
+ console.error("\u{1F4CA} useCrudifyInstance - login error:", error);
3734
+ throw error;
3735
+ }
3736
+ }, [ensureReady]);
3737
+ return {
3738
+ // Core operations
3739
+ getStructure,
3740
+ getStructurePublic,
3741
+ readItems,
3742
+ readItem,
3743
+ createItem,
3744
+ updateItem,
3745
+ deleteItem,
3746
+ transaction,
3747
+ login,
3748
+ // State information
3749
+ isReady,
3750
+ isInitialized,
3751
+ isInitializing,
3752
+ initializationError,
3753
+ // Utility methods
3754
+ waitForReady
3755
+ };
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();
3503
3790
  // Annotate the CommonJS export names for ESM import in node:
3504
3791
  0 && (module.exports = {
3505
3792
  CrudifyDataProvider,
@@ -3512,6 +3799,8 @@ var useCrudifyConfig = () => {
3512
3799
  crudifyInitializer,
3513
3800
  decodeJwtSafely,
3514
3801
  getCookie,
3802
+ getCrudifyInstanceAsync,
3803
+ getCrudifyInstanceSync,
3515
3804
  getCurrentUserEmail,
3516
3805
  getErrorMessage,
3517
3806
  handleCrudifyError,
@@ -3526,6 +3815,7 @@ var useCrudifyConfig = () => {
3526
3815
  useCrudifyConfig,
3527
3816
  useCrudifyData,
3528
3817
  useCrudifyDataContext,
3818
+ useCrudifyInstance,
3529
3819
  useCrudifyLogin,
3530
3820
  useCrudifyUser,
3531
3821
  useUserProfile,