@a-cube-io/ereceipts-js-sdk 2.0.2 → 2.0.3

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.cjs.js CHANGED
@@ -2482,7 +2482,7 @@ function formatDecimal(value, decimals = 2) {
2482
2482
  return num.toFixed(decimals);
2483
2483
  }
2484
2484
 
2485
- const log$c = createPrefixedLogger('MTLS-HANDLER');
2485
+ const log$f = createPrefixedLogger('MTLS-HANDLER');
2486
2486
  class MtlsAuthHandler {
2487
2487
  constructor(mtlsAdapter, certificatePort) {
2488
2488
  this.mtlsAdapter = mtlsAdapter;
@@ -2524,7 +2524,7 @@ class MtlsAuthHandler {
2524
2524
  async makeRequest(url, config, jwtToken) {
2525
2525
  const requestKey = this.generateRequestKey(url, config, jwtToken);
2526
2526
  if (this.pendingRequests.has(requestKey)) {
2527
- log$c.debug('Deduplicating concurrent request:', url);
2527
+ log$f.debug('Deduplicating concurrent request:', url);
2528
2528
  return this.pendingRequests.get(requestKey);
2529
2529
  }
2530
2530
  const requestPromise = this.executeRequest(url, config, jwtToken, false);
@@ -2548,10 +2548,10 @@ class MtlsAuthHandler {
2548
2548
  };
2549
2549
  if (jwtToken) {
2550
2550
  headers['Authorization'] = `Bearer ${jwtToken}`;
2551
- log$c.debug('JWT token present:', jwtToken.substring(0, 20) + '...');
2551
+ log$f.debug('JWT token present:', jwtToken.substring(0, 20) + '...');
2552
2552
  }
2553
2553
  else {
2554
- log$c.warn('No JWT token provided for mTLS request');
2554
+ log$f.warn('No JWT token provided for mTLS request');
2555
2555
  }
2556
2556
  const fullUrl = this.constructMtlsUrl(url);
2557
2557
  const mtlsConfig = {
@@ -2562,25 +2562,25 @@ class MtlsAuthHandler {
2562
2562
  timeout: config.timeout,
2563
2563
  responseType: config.responseType,
2564
2564
  };
2565
- log$c.debug('header-mtls', headers);
2566
- log$c.debug(`${config.method} ${fullUrl}`);
2565
+ log$f.debug('header-mtls', headers);
2566
+ log$f.debug(`${config.method} ${fullUrl}`);
2567
2567
  if (config.data) {
2568
- log$c.debug('Request body:', config.data);
2568
+ log$f.debug('Request body:', config.data);
2569
2569
  }
2570
2570
  try {
2571
2571
  const response = await this.mtlsAdapter.request(mtlsConfig);
2572
- log$c.debug(`Response ${response.status} from ${fullUrl}`);
2572
+ log$f.debug(`Response ${response.status} from ${fullUrl}`);
2573
2573
  if (response.data) {
2574
- log$c.debug('Response body:', response.data);
2574
+ log$f.debug('Response body:', response.data);
2575
2575
  }
2576
2576
  return response.data;
2577
2577
  }
2578
2578
  catch (error) {
2579
- log$c.error(`Response error from ${fullUrl}:`, error);
2579
+ log$f.error(`Response error from ${fullUrl}:`, error);
2580
2580
  if (error && typeof error === 'object' && 'response' in error) {
2581
2581
  const axiosError = error;
2582
2582
  if (axiosError.response?.data) {
2583
- log$c.error('Response body:', axiosError.response.data);
2583
+ log$f.error('Response body:', axiosError.response.data);
2584
2584
  }
2585
2585
  }
2586
2586
  if (isRetryAttempt) {
@@ -2590,7 +2590,7 @@ class MtlsAuthHandler {
2590
2590
  if (!shouldRetry) {
2591
2591
  throw error;
2592
2592
  }
2593
- log$c.debug('Request failed, reconfiguring certificate and retrying...');
2593
+ log$f.debug('Request failed, reconfiguring certificate and retrying...');
2594
2594
  try {
2595
2595
  await this.configureCertificate(certificate);
2596
2596
  return await this.executeRequest(url, config, jwtToken, true);
@@ -3317,7 +3317,7 @@ function decompressData(data, compressed) {
3317
3317
  return new CompressionAdapter().decompress(data, compressed);
3318
3318
  }
3319
3319
 
3320
- const log$b = createPrefixedLogger('CACHE-RN');
3320
+ const log$e = createPrefixedLogger('CACHE-RN');
3321
3321
  /**
3322
3322
  * React Native cache adapter using SQLite (Expo or react-native-sqlite-storage)
3323
3323
  * Cache never expires - data persists until explicitly invalidated
@@ -3401,26 +3401,26 @@ class ReactNativeCacheAdapter {
3401
3401
  await this.runMigrations();
3402
3402
  }
3403
3403
  async runMigrations() {
3404
- log$b.debug('Running database migrations...');
3404
+ log$e.debug('Running database migrations...');
3405
3405
  try {
3406
3406
  // Check if compressed column exists
3407
3407
  this.hasCompressedColumn = await this.checkColumnExists('compressed');
3408
3408
  if (!this.hasCompressedColumn) {
3409
- log$b.debug('Adding compressed column to cache table');
3409
+ log$e.debug('Adding compressed column to cache table');
3410
3410
  const addColumnSQL = `ALTER TABLE ${ReactNativeCacheAdapter.TABLE_NAME} ADD COLUMN compressed INTEGER DEFAULT 0`;
3411
3411
  await this.executeSql(addColumnSQL);
3412
3412
  this.hasCompressedColumn = true;
3413
- log$b.debug('Successfully added compressed column');
3413
+ log$e.debug('Successfully added compressed column');
3414
3414
  }
3415
3415
  else {
3416
- log$b.debug('Compressed column already exists');
3416
+ log$e.debug('Compressed column already exists');
3417
3417
  }
3418
- log$b.debug('Database migrations completed', {
3418
+ log$e.debug('Database migrations completed', {
3419
3419
  hasCompressedColumn: this.hasCompressedColumn,
3420
3420
  });
3421
3421
  }
3422
3422
  catch (error) {
3423
- log$b.debug('Migration failed, disabling compression features', error);
3423
+ log$e.debug('Migration failed, disabling compression features', error);
3424
3424
  this.hasCompressedColumn = false;
3425
3425
  // Don't throw - allow the app to continue even if migration fails
3426
3426
  // The compressed feature will just be disabled
@@ -3431,20 +3431,20 @@ class ReactNativeCacheAdapter {
3431
3431
  const pragmaSQL = `PRAGMA table_info(${ReactNativeCacheAdapter.TABLE_NAME})`;
3432
3432
  const results = await this.executeSql(pragmaSQL);
3433
3433
  const columns = this.normalizeResults(results);
3434
- log$b.debug('Table columns found', { columns: columns.map((c) => c.name) });
3434
+ log$e.debug('Table columns found', { columns: columns.map((c) => c.name) });
3435
3435
  return columns.some((column) => column.name === columnName);
3436
3436
  }
3437
3437
  catch (error) {
3438
- log$b.debug('Error checking column existence', error);
3438
+ log$e.debug('Error checking column existence', error);
3439
3439
  return false;
3440
3440
  }
3441
3441
  }
3442
3442
  async get(key) {
3443
3443
  await this.ensureInitialized();
3444
3444
  const sql = `SELECT * FROM ${ReactNativeCacheAdapter.TABLE_NAME} WHERE cache_key = ?`;
3445
- log$b.debug('Executing get query', { sql, key });
3445
+ log$e.debug('Executing get query', { sql, key });
3446
3446
  const results = await this.executeSql(sql, [key]);
3447
- log$b.debug('Get query results', { key, hasResults: !!results });
3447
+ log$e.debug('Get query results', { key, hasResults: !!results });
3448
3448
  // Normalize results from different SQLite implementations
3449
3449
  const rows = this.normalizeResults(results);
3450
3450
  if (!rows || rows.length === 0) {
@@ -3467,7 +3467,7 @@ class ReactNativeCacheAdapter {
3467
3467
  data,
3468
3468
  timestamp: Date.now(),
3469
3469
  };
3470
- log$b.debug('Setting cache item', { key });
3470
+ log$e.debug('Setting cache item', { key });
3471
3471
  return this.setItem(key, item);
3472
3472
  }
3473
3473
  async setItem(key, item) {
@@ -3480,7 +3480,7 @@ class ReactNativeCacheAdapter {
3480
3480
  const compressionResult = compressData(serializedData, this.options.compressionThreshold);
3481
3481
  finalData = compressionResult.data;
3482
3482
  isCompressed = compressionResult.compressed;
3483
- log$b.debug('Compression result', {
3483
+ log$e.debug('Compression result', {
3484
3484
  key,
3485
3485
  originalSize: compressionResult.originalSize,
3486
3486
  compressedSize: compressionResult.compressedSize,
@@ -3488,7 +3488,7 @@ class ReactNativeCacheAdapter {
3488
3488
  savings: compressionResult.originalSize - compressionResult.compressedSize,
3489
3489
  });
3490
3490
  }
3491
- log$b.debug('Setting item with metadata', {
3491
+ log$e.debug('Setting item with metadata', {
3492
3492
  key,
3493
3493
  timestamp: item.timestamp,
3494
3494
  compressed: isCompressed,
@@ -3514,14 +3514,14 @@ class ReactNativeCacheAdapter {
3514
3514
  `;
3515
3515
  params = [key, finalData, item.timestamp];
3516
3516
  }
3517
- log$b.debug('Executing setItem SQL', { key, paramsCount: params.length });
3517
+ log$e.debug('Executing setItem SQL', { key, paramsCount: params.length });
3518
3518
  await this.executeSql(sql, params);
3519
3519
  }
3520
3520
  async setBatch(items) {
3521
3521
  if (items.length === 0)
3522
3522
  return;
3523
3523
  await this.ensureInitialized();
3524
- log$b.debug('Batch setting items', { count: items.length });
3524
+ log$e.debug('Batch setting items', { count: items.length });
3525
3525
  if (this.isExpo) {
3526
3526
  await this.db.withTransactionAsync(async () => {
3527
3527
  for (const [key, item] of items) {
@@ -3539,7 +3539,7 @@ class ReactNativeCacheAdapter {
3539
3539
  }, reject, () => resolve());
3540
3540
  });
3541
3541
  }
3542
- log$b.debug('Batch operation completed', { count: items.length });
3542
+ log$e.debug('Batch operation completed', { count: items.length });
3543
3543
  }
3544
3544
  async setBatchItem(key, item) {
3545
3545
  // Handle compression if enabled and compressed column is available
@@ -3713,10 +3713,10 @@ class MemoryCacheAdapter {
3713
3713
  return keySize + itemSize;
3714
3714
  }
3715
3715
  async get(key) {
3716
- log$b.debug('Getting cache item', { key });
3716
+ log$e.debug('Getting cache item', { key });
3717
3717
  const item = this.cache.get(key);
3718
3718
  if (!item) {
3719
- log$b.debug('Cache miss', { key });
3719
+ log$e.debug('Cache miss', { key });
3720
3720
  return null;
3721
3721
  }
3722
3722
  // Handle decompression if needed
@@ -3726,7 +3726,7 @@ class MemoryCacheAdapter {
3726
3726
  const decompressed = decompressData(item.data, true);
3727
3727
  finalData = JSON.parse(decompressed.data);
3728
3728
  }
3729
- log$b.debug('Cache hit', { key, compressed: isCompressed });
3729
+ log$e.debug('Cache hit', { key, compressed: isCompressed });
3730
3730
  return {
3731
3731
  ...item,
3732
3732
  data: finalData,
@@ -3734,7 +3734,7 @@ class MemoryCacheAdapter {
3734
3734
  };
3735
3735
  }
3736
3736
  async set(key, data) {
3737
- log$b.debug('Setting cache item', { key });
3737
+ log$e.debug('Setting cache item', { key });
3738
3738
  // Handle compression if enabled
3739
3739
  let finalData = data;
3740
3740
  let isCompressed = false;
@@ -3744,7 +3744,7 @@ class MemoryCacheAdapter {
3744
3744
  if (compressionResult.compressed) {
3745
3745
  finalData = compressionResult.data;
3746
3746
  isCompressed = true;
3747
- log$b.debug('Compression result', {
3747
+ log$e.debug('Compression result', {
3748
3748
  key,
3749
3749
  originalSize: compressionResult.originalSize,
3750
3750
  compressedSize: compressionResult.compressedSize,
@@ -3776,13 +3776,13 @@ class MemoryCacheAdapter {
3776
3776
  const oldestItemSize = this.calculateItemSize(oldestKey, oldestItem);
3777
3777
  this.totalBytes -= oldestItemSize;
3778
3778
  this.cache.delete(oldestKey);
3779
- log$b.debug('Removed oldest item for capacity', { oldestKey, freedBytes: oldestItemSize });
3779
+ log$e.debug('Removed oldest item for capacity', { oldestKey, freedBytes: oldestItemSize });
3780
3780
  }
3781
3781
  }
3782
3782
  // Set new item and update total size
3783
3783
  this.cache.set(key, item);
3784
3784
  this.totalBytes += newItemSize;
3785
- log$b.debug('Updated cache size', {
3785
+ log$e.debug('Updated cache size', {
3786
3786
  entries: this.cache.size,
3787
3787
  totalBytes: this.totalBytes,
3788
3788
  newItemSize,
@@ -3791,7 +3791,7 @@ class MemoryCacheAdapter {
3791
3791
  async setBatch(items) {
3792
3792
  if (items.length === 0)
3793
3793
  return;
3794
- log$b.debug('Batch setting items', { count: items.length });
3794
+ log$e.debug('Batch setting items', { count: items.length });
3795
3795
  let totalNewBytes = 0;
3796
3796
  let totalOldBytes = 0;
3797
3797
  const itemsToRemove = [];
@@ -3820,7 +3820,7 @@ class MemoryCacheAdapter {
3820
3820
  itemsToRemove.push(oldKey);
3821
3821
  }
3822
3822
  if (itemsToRemove.length > 0) {
3823
- log$b.debug('Removed items for batch capacity', {
3823
+ log$e.debug('Removed items for batch capacity', {
3824
3824
  removedCount: itemsToRemove.length,
3825
3825
  removedKeys: itemsToRemove,
3826
3826
  });
@@ -3832,7 +3832,7 @@ class MemoryCacheAdapter {
3832
3832
  for (const [key, item] of items) {
3833
3833
  this.cache.set(key, item);
3834
3834
  }
3835
- log$b.debug('Batch operation completed', {
3835
+ log$e.debug('Batch operation completed', {
3836
3836
  count: items.length,
3837
3837
  totalBytes: this.totalBytes,
3838
3838
  entries: this.cache.size,
@@ -3854,7 +3854,7 @@ class MemoryCacheAdapter {
3854
3854
  }
3855
3855
  }
3856
3856
  if (removed > 0) {
3857
- log$b.debug('Invalidation completed', {
3857
+ log$e.debug('Invalidation completed', {
3858
3858
  pattern,
3859
3859
  entriesRemoved: removed,
3860
3860
  bytesFreed,
@@ -3866,7 +3866,7 @@ class MemoryCacheAdapter {
3866
3866
  async clear() {
3867
3867
  this.cache.clear();
3868
3868
  this.totalBytes = 0;
3869
- log$b.debug('Cache cleared', { entries: 0, bytes: 0 });
3869
+ log$e.debug('Cache cleared', { entries: 0, bytes: 0 });
3870
3870
  }
3871
3871
  async getSize() {
3872
3872
  return {
@@ -4197,7 +4197,7 @@ replaceTraps((oldTraps) => ({
4197
4197
  },
4198
4198
  }));
4199
4199
 
4200
- const log$a = createPrefixedLogger('CACHE-WEB');
4200
+ const log$d = createPrefixedLogger('CACHE-WEB');
4201
4201
  /**
4202
4202
  * Web cache adapter using IndexedDB with automatic error recovery
4203
4203
  * Cache never expires - data persists until explicitly invalidated
@@ -4220,18 +4220,18 @@ class WebCacheAdapter {
4220
4220
  async initialize() {
4221
4221
  if (this.db)
4222
4222
  return;
4223
- log$a.debug('Initializing IndexedDB cache', {
4223
+ log$d.debug('Initializing IndexedDB cache', {
4224
4224
  dbName: WebCacheAdapter.DB_NAME,
4225
4225
  version: WebCacheAdapter.DB_VERSION,
4226
4226
  });
4227
4227
  try {
4228
4228
  this.db = await this.openDatabase();
4229
- log$a.debug('IndexedDB cache initialized successfully');
4229
+ log$d.debug('IndexedDB cache initialized successfully');
4230
4230
  this.retryCount = 0; // Reset retry count on success
4231
4231
  }
4232
4232
  catch (error) {
4233
4233
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
4234
- log$a.debug('Failed to initialize IndexedDB', { error: errorMessage });
4234
+ log$d.debug('Failed to initialize IndexedDB', { error: errorMessage });
4235
4235
  // Check if this is a version conflict error
4236
4236
  if (this.isVersionConflictError(errorMessage)) {
4237
4237
  await this.handleVersionConflict();
@@ -4244,32 +4244,32 @@ class WebCacheAdapter {
4244
4244
  async openDatabase() {
4245
4245
  return await openDB(WebCacheAdapter.DB_NAME, WebCacheAdapter.DB_VERSION, {
4246
4246
  upgrade: (db, oldVersion, newVersion, transaction) => {
4247
- log$a.debug('Database upgrade needed', { oldVersion, newVersion });
4247
+ log$d.debug('Database upgrade needed', { oldVersion, newVersion });
4248
4248
  this.handleUpgrade(db, oldVersion, newVersion, transaction);
4249
4249
  },
4250
4250
  blocked: () => {
4251
- log$a.debug('Database blocked - another tab may be open');
4251
+ log$d.debug('Database blocked - another tab may be open');
4252
4252
  },
4253
4253
  blocking: () => {
4254
- log$a.debug('Database blocking - will close connection');
4254
+ log$d.debug('Database blocking - will close connection');
4255
4255
  if (this.db) {
4256
4256
  this.db.close();
4257
4257
  this.db = null;
4258
4258
  }
4259
4259
  },
4260
4260
  terminated: () => {
4261
- log$a.debug('Database connection terminated unexpectedly');
4261
+ log$d.debug('Database connection terminated unexpectedly');
4262
4262
  this.db = null;
4263
4263
  },
4264
4264
  });
4265
4265
  }
4266
4266
  handleUpgrade(db, oldVersion, newVersion, transaction) {
4267
- log$a.debug('Handling database upgrade', { oldVersion, newVersion });
4267
+ log$d.debug('Handling database upgrade', { oldVersion, newVersion });
4268
4268
  // Create cache store if it doesn't exist (initial setup)
4269
4269
  if (!db.objectStoreNames.contains(WebCacheAdapter.STORE_NAME)) {
4270
4270
  const store = db.createObjectStore(WebCacheAdapter.STORE_NAME, { keyPath: 'key' });
4271
4271
  store.createIndex('timestamp', 'timestamp', { unique: false });
4272
- log$a.debug('Created cache store and timestamp index');
4272
+ log$d.debug('Created cache store and timestamp index');
4273
4273
  }
4274
4274
  // Handle migration from version 1 to 2
4275
4275
  if (oldVersion < 2) {
@@ -4280,16 +4280,16 @@ class WebCacheAdapter {
4280
4280
  try {
4281
4281
  if (store.indexNames.contains(indexName)) {
4282
4282
  store.deleteIndex(indexName);
4283
- log$a.debug(`Removed unused index: ${indexName}`);
4283
+ log$d.debug(`Removed unused index: ${indexName}`);
4284
4284
  }
4285
4285
  }
4286
4286
  catch (error) {
4287
4287
  // Ignore errors if indexes don't exist
4288
- log$a.debug(`Warning: Could not remove index ${indexName}`, error);
4288
+ log$d.debug(`Warning: Could not remove index ${indexName}`, error);
4289
4289
  }
4290
4290
  });
4291
4291
  }
4292
- log$a.debug('Database upgrade completed');
4292
+ log$d.debug('Database upgrade completed');
4293
4293
  }
4294
4294
  isVersionConflictError(errorMessage) {
4295
4295
  return (errorMessage.includes('less than the existing version') ||
@@ -4297,7 +4297,7 @@ class WebCacheAdapter {
4297
4297
  errorMessage.includes('VersionError'));
4298
4298
  }
4299
4299
  async handleVersionConflict() {
4300
- log$a.debug('Handling version conflict, attempting recovery...');
4300
+ log$d.debug('Handling version conflict, attempting recovery...');
4301
4301
  if (this.retryCount >= this.maxRetries) {
4302
4302
  throw new Error('Failed to resolve IndexedDB version conflict after multiple attempts');
4303
4303
  }
@@ -4309,19 +4309,19 @@ class WebCacheAdapter {
4309
4309
  this.db = null;
4310
4310
  }
4311
4311
  // Delete the problematic database
4312
- log$a.debug('Deleting problematic database to resolve version conflict');
4312
+ log$d.debug('Deleting problematic database to resolve version conflict');
4313
4313
  await deleteDB(WebCacheAdapter.DB_NAME);
4314
4314
  // Wait a bit for the deletion to complete
4315
4315
  await new Promise((resolve) => setTimeout(resolve, 200));
4316
4316
  // Try to open the database again
4317
- log$a.debug(`Retrying database initialization (attempt ${this.retryCount}/${this.maxRetries})`);
4317
+ log$d.debug(`Retrying database initialization (attempt ${this.retryCount}/${this.maxRetries})`);
4318
4318
  this.db = await this.openDatabase();
4319
- log$a.debug('Successfully recovered from version conflict');
4319
+ log$d.debug('Successfully recovered from version conflict');
4320
4320
  this.retryCount = 0; // Reset retry count on success
4321
4321
  }
4322
4322
  catch (retryError) {
4323
4323
  const retryErrorMessage = retryError instanceof Error ? retryError.message : 'Unknown error';
4324
- log$a.debug('Recovery attempt failed', { attempt: this.retryCount, error: retryErrorMessage });
4324
+ log$d.debug('Recovery attempt failed', { attempt: this.retryCount, error: retryErrorMessage });
4325
4325
  if (this.retryCount < this.maxRetries) {
4326
4326
  // Try again
4327
4327
  await this.handleVersionConflict();
@@ -4333,7 +4333,7 @@ class WebCacheAdapter {
4333
4333
  }
4334
4334
  async get(key) {
4335
4335
  await this.ensureInitialized();
4336
- log$a.debug('Getting cache item', { key });
4336
+ log$d.debug('Getting cache item', { key });
4337
4337
  try {
4338
4338
  const transaction = this.db.transaction([WebCacheAdapter.STORE_NAME], 'readonly');
4339
4339
  const store = transaction.objectStore(WebCacheAdapter.STORE_NAME);
@@ -4359,7 +4359,7 @@ class WebCacheAdapter {
4359
4359
  };
4360
4360
  }
4361
4361
  catch (error) {
4362
- log$a.debug('Error getting cache item', { key, error });
4362
+ log$d.debug('Error getting cache item', { key, error });
4363
4363
  return null; // Return null on error instead of throwing
4364
4364
  }
4365
4365
  }
@@ -4381,7 +4381,7 @@ class WebCacheAdapter {
4381
4381
  if (compressionResult.compressed) {
4382
4382
  finalData = compressionResult.data;
4383
4383
  isCompressed = true;
4384
- log$a.debug('Compression result', {
4384
+ log$d.debug('Compression result', {
4385
4385
  key,
4386
4386
  originalSize: compressionResult.originalSize,
4387
4387
  compressedSize: compressionResult.compressedSize,
@@ -4390,7 +4390,7 @@ class WebCacheAdapter {
4390
4390
  });
4391
4391
  }
4392
4392
  }
4393
- log$a.debug('Setting cache item', { key, timestamp: item.timestamp, compressed: isCompressed });
4393
+ log$d.debug('Setting cache item', { key, timestamp: item.timestamp, compressed: isCompressed });
4394
4394
  const storedItem = {
4395
4395
  key,
4396
4396
  data: finalData,
@@ -4403,7 +4403,7 @@ class WebCacheAdapter {
4403
4403
  await store.put(storedItem);
4404
4404
  }
4405
4405
  catch (error) {
4406
- log$a.debug('Error setting cache item', { key, error });
4406
+ log$d.debug('Error setting cache item', { key, error });
4407
4407
  // Silently fail for cache writes
4408
4408
  }
4409
4409
  }
@@ -4411,7 +4411,7 @@ class WebCacheAdapter {
4411
4411
  if (items.length === 0)
4412
4412
  return;
4413
4413
  await this.ensureInitialized();
4414
- log$a.debug('Batch setting items', { count: items.length });
4414
+ log$d.debug('Batch setting items', { count: items.length });
4415
4415
  try {
4416
4416
  const transaction = this.db.transaction([WebCacheAdapter.STORE_NAME], 'readwrite');
4417
4417
  const store = transaction.objectStore(WebCacheAdapter.STORE_NAME);
@@ -4421,10 +4421,10 @@ class WebCacheAdapter {
4421
4421
  return store.put(storedItem);
4422
4422
  });
4423
4423
  await Promise.all(promises);
4424
- log$a.debug('Batch operation completed', { count: items.length });
4424
+ log$d.debug('Batch operation completed', { count: items.length });
4425
4425
  }
4426
4426
  catch (error) {
4427
- log$a.debug('Error in batch operation', { count: items.length, error });
4427
+ log$d.debug('Error in batch operation', { count: items.length, error });
4428
4428
  // Silently fail for batch writes
4429
4429
  }
4430
4430
  }
@@ -4459,10 +4459,10 @@ class WebCacheAdapter {
4459
4459
  const transaction = this.db.transaction([WebCacheAdapter.STORE_NAME], 'readwrite');
4460
4460
  const store = transaction.objectStore(WebCacheAdapter.STORE_NAME);
4461
4461
  await store.clear();
4462
- log$a.debug('Cache cleared successfully');
4462
+ log$d.debug('Cache cleared successfully');
4463
4463
  }
4464
4464
  catch (error) {
4465
- log$a.debug('Error clearing cache', error);
4465
+ log$d.debug('Error clearing cache', error);
4466
4466
  // Silently fail for cache clear
4467
4467
  }
4468
4468
  }
@@ -4488,7 +4488,7 @@ class WebCacheAdapter {
4488
4488
  };
4489
4489
  }
4490
4490
  catch (error) {
4491
- log$a.debug('Error getting cache size', error);
4491
+ log$d.debug('Error getting cache size', error);
4492
4492
  return {
4493
4493
  entries: 0,
4494
4494
  bytes: 0,
@@ -4513,7 +4513,7 @@ class WebCacheAdapter {
4513
4513
  return allKeys.filter((key) => regex.test(key));
4514
4514
  }
4515
4515
  catch (error) {
4516
- log$a.debug('Error getting cache keys', error);
4516
+ log$d.debug('Error getting cache keys', error);
4517
4517
  return [];
4518
4518
  }
4519
4519
  }
@@ -4526,7 +4526,7 @@ class WebCacheAdapter {
4526
4526
  return true;
4527
4527
  }
4528
4528
  catch (error) {
4529
- log$a.debug('Error deleting cache item', { key, error });
4529
+ log$d.debug('Error deleting cache item', { key, error });
4530
4530
  return false;
4531
4531
  }
4532
4532
  }
@@ -4538,7 +4538,7 @@ class WebCacheAdapter {
4538
4538
  await this.initPromise;
4539
4539
  }
4540
4540
  catch (error) {
4541
- log$a.debug('Failed to ensure initialization', error);
4541
+ log$d.debug('Failed to ensure initialization', error);
4542
4542
  // Reset and try once more
4543
4543
  this.initPromise = null;
4544
4544
  this.db = null;
@@ -4557,7 +4557,7 @@ WebCacheAdapter.DB_NAME = 'acube_cache';
4557
4557
  WebCacheAdapter.DB_VERSION = 2;
4558
4558
  WebCacheAdapter.STORE_NAME = 'cache_entries';
4559
4559
 
4560
- const log$9 = createPrefixedLogger('CACHE-LOADER');
4560
+ const log$c = createPrefixedLogger('CACHE-LOADER');
4561
4561
  function loadCacheAdapter(platform) {
4562
4562
  try {
4563
4563
  switch (platform) {
@@ -4589,7 +4589,7 @@ function loadCacheAdapter(platform) {
4589
4589
  }
4590
4590
  }
4591
4591
  catch (error) {
4592
- log$9.warn(`Cache adapter not available for platform ${platform}:`, error);
4592
+ log$c.warn(`Cache adapter not available for platform ${platform}:`, error);
4593
4593
  return undefined;
4594
4594
  }
4595
4595
  }
@@ -4646,7 +4646,7 @@ class BaseSecureStorageAdapter {
4646
4646
  }
4647
4647
  }
4648
4648
 
4649
- const log$8 = createPrefixedLogger('NETWORK-BASE');
4649
+ const log$b = createPrefixedLogger('NETWORK-BASE');
4650
4650
  class NetworkBase {
4651
4651
  constructor(initialOnline = true, debounceMs = 300) {
4652
4652
  this.destroy$ = new Subject();
@@ -4666,14 +4666,14 @@ class NetworkBase {
4666
4666
  const current = this.statusSubject.getValue();
4667
4667
  if (current.online !== online) {
4668
4668
  this.statusSubject.next({ online, timestamp: Date.now() });
4669
- log$8.debug(`Network status changed: ${online ? 'online' : 'offline'}`);
4669
+ log$b.debug(`Network status changed: ${online ? 'online' : 'offline'}`);
4670
4670
  }
4671
4671
  }
4672
4672
  destroy() {
4673
4673
  this.destroy$.next();
4674
4674
  this.destroy$.complete();
4675
4675
  this.statusSubject.complete();
4676
- log$8.debug('Network monitor destroyed');
4676
+ log$b.debug('Network monitor destroyed');
4677
4677
  }
4678
4678
  }
4679
4679
 
@@ -4733,7 +4733,7 @@ class NodeSecureStorageAdapter extends BaseSecureStorageAdapter {
4733
4733
  }
4734
4734
  }
4735
4735
 
4736
- const log$7 = createPrefixedLogger('RN-STORAGE');
4736
+ const log$a = createPrefixedLogger('RN-STORAGE');
4737
4737
  /**
4738
4738
  * React Native storage adapter using AsyncStorage
4739
4739
  * Note: Uses native batch operations for better performance (not base class)
@@ -4765,7 +4765,7 @@ class ReactNativeStorageAdapter {
4765
4765
  return await this.AsyncStorage.getItem(key);
4766
4766
  }
4767
4767
  catch (error) {
4768
- log$7.error('Failed to get item from AsyncStorage:', error);
4768
+ log$a.error('Failed to get item from AsyncStorage:', error);
4769
4769
  return null;
4770
4770
  }
4771
4771
  }
@@ -4806,7 +4806,7 @@ class ReactNativeStorageAdapter {
4806
4806
  return await this.AsyncStorage.getAllKeys();
4807
4807
  }
4808
4808
  catch (error) {
4809
- log$7.error('Failed to get all keys:', error);
4809
+ log$a.error('Failed to get all keys:', error);
4810
4810
  return [];
4811
4811
  }
4812
4812
  }
@@ -4823,7 +4823,7 @@ class ReactNativeStorageAdapter {
4823
4823
  return result;
4824
4824
  }
4825
4825
  catch (error) {
4826
- log$7.error('Failed to get multiple items:', error);
4826
+ log$a.error('Failed to get multiple items:', error);
4827
4827
  const result = {};
4828
4828
  keys.forEach((key) => {
4829
4829
  result[key] = null;
@@ -4873,7 +4873,7 @@ class ReactNativeSecureStorageAdapter extends BaseSecureStorageAdapter {
4873
4873
  return;
4874
4874
  }
4875
4875
  catch {
4876
- log$7.debug('expo-secure-store not available, trying react-native-keychain');
4876
+ log$a.debug('expo-secure-store not available, trying react-native-keychain');
4877
4877
  }
4878
4878
  try {
4879
4879
  const Keychain = require('react-native-keychain');
@@ -4882,7 +4882,7 @@ class ReactNativeSecureStorageAdapter extends BaseSecureStorageAdapter {
4882
4882
  return;
4883
4883
  }
4884
4884
  catch {
4885
- log$7.error('react-native-keychain not available');
4885
+ log$a.error('react-native-keychain not available');
4886
4886
  }
4887
4887
  throw new Error('No secure storage available. Please install expo-secure-store or react-native-keychain');
4888
4888
  }
@@ -4900,7 +4900,7 @@ class ReactNativeSecureStorageAdapter extends BaseSecureStorageAdapter {
4900
4900
  }
4901
4901
  }
4902
4902
  catch (error) {
4903
- log$7.error('Failed to get secure item:', error);
4903
+ log$a.error('Failed to get secure item:', error);
4904
4904
  }
4905
4905
  return null;
4906
4906
  }
@@ -4937,10 +4937,10 @@ class ReactNativeSecureStorageAdapter extends BaseSecureStorageAdapter {
4937
4937
  }
4938
4938
  }
4939
4939
  async clear() {
4940
- log$7.warn('Clear all secure items not fully implemented for React Native');
4940
+ log$a.warn('Clear all secure items not fully implemented for React Native');
4941
4941
  }
4942
4942
  async getAllKeys() {
4943
- log$7.warn('Get all secure keys not implemented for React Native');
4943
+ log$a.warn('Get all secure keys not implemented for React Native');
4944
4944
  return [];
4945
4945
  }
4946
4946
  async isAvailable() {
@@ -5158,7 +5158,7 @@ class NodeNetworkMonitor extends NetworkBase {
5158
5158
  }
5159
5159
  }
5160
5160
 
5161
- const log$6 = createPrefixedLogger('RN-NETWORK');
5161
+ const log$9 = createPrefixedLogger('RN-NETWORK');
5162
5162
  /**
5163
5163
  * React Native network monitor using RxJS
5164
5164
  * Supports both @react-native-community/netinfo and expo-network
@@ -5171,7 +5171,7 @@ class ReactNativeNetworkMonitor extends NetworkBase {
5171
5171
  this.moduleReady$ = new Subject();
5172
5172
  this.isExpo = detectPlatform().isExpo;
5173
5173
  this.init().catch((error) => {
5174
- log$6.error('Network monitor initialization failed:', error);
5174
+ log$9.error('Network monitor initialization failed:', error);
5175
5175
  });
5176
5176
  }
5177
5177
  async init() {
@@ -5190,10 +5190,10 @@ class ReactNativeNetworkMonitor extends NetworkBase {
5190
5190
  try {
5191
5191
  const module = require('@react-native-community/netinfo');
5192
5192
  this.netInfoModule = module.default || module;
5193
- log$6.debug('Loaded @react-native-community/netinfo module');
5193
+ log$9.debug('Loaded @react-native-community/netinfo module');
5194
5194
  }
5195
5195
  catch (error) {
5196
- log$6.error('Failed to load React Native NetInfo module:', error);
5196
+ log$9.error('Failed to load React Native NetInfo module:', error);
5197
5197
  this.netInfoModule = null;
5198
5198
  }
5199
5199
  }
@@ -5201,10 +5201,10 @@ class ReactNativeNetworkMonitor extends NetworkBase {
5201
5201
  try {
5202
5202
  const module = require('expo-network');
5203
5203
  this.netInfoModule = module.default || module;
5204
- log$6.debug('Loaded expo-network module');
5204
+ log$9.debug('Loaded expo-network module');
5205
5205
  }
5206
5206
  catch (error) {
5207
- log$6.error('Failed to load Expo Network module:', error);
5207
+ log$9.error('Failed to load Expo Network module:', error);
5208
5208
  this.netInfoModule = null;
5209
5209
  }
5210
5210
  }
@@ -5221,16 +5221,16 @@ class ReactNativeNetworkMonitor extends NetworkBase {
5221
5221
  }
5222
5222
  const online = !!(state.isConnected && state.isInternetReachable !== false);
5223
5223
  this.updateStatus(online);
5224
- log$6.debug('Initial network state:', online ? 'online' : 'offline');
5224
+ log$9.debug('Initial network state:', online ? 'online' : 'offline');
5225
5225
  }
5226
5226
  catch (error) {
5227
- log$6.warn('Could not fetch initial network state:', error);
5227
+ log$9.warn('Could not fetch initial network state:', error);
5228
5228
  }
5229
5229
  }
5230
5230
  subscribeToStateChanges() {
5231
5231
  if (!this.netInfoModule)
5232
5232
  return;
5233
- log$6.debug('Subscribing to network state changes');
5233
+ log$9.debug('Subscribing to network state changes');
5234
5234
  const handleState = (state) => {
5235
5235
  const online = !!(state.isConnected && (state.isInternetReachable ?? true));
5236
5236
  this.updateStatus(online);
@@ -5272,7 +5272,7 @@ class ReactNativeNetworkMonitor extends NetworkBase {
5272
5272
  };
5273
5273
  }
5274
5274
  catch (error) {
5275
- log$6.error('Failed to fetch detailed network info:', error);
5275
+ log$9.error('Failed to fetch detailed network info:', error);
5276
5276
  return null;
5277
5277
  }
5278
5278
  }
@@ -5408,7 +5408,7 @@ class CertificateValidator {
5408
5408
  }
5409
5409
  }
5410
5410
 
5411
- const log$5 = createPrefixedLogger('RN-MTLS');
5411
+ const log$8 = createPrefixedLogger('RN-MTLS');
5412
5412
  /**
5413
5413
  * React Native mTLS Adapter using @a-cube-io/expo-mutual-tls
5414
5414
  */
@@ -5430,7 +5430,7 @@ class ReactNativeMTLSAdapter {
5430
5430
  this.expoMTLS = ExpoMutualTls;
5431
5431
  // Set up debug logging with the correct event signature
5432
5432
  const debugListener = ExpoMutualTls.onDebugLog((event) => {
5433
- log$5.debug(`${event.type}: ${event.message}`, {
5433
+ log$8.debug(`${event.type}: ${event.message}`, {
5434
5434
  method: event.method,
5435
5435
  url: event.url,
5436
5436
  statusCode: event.statusCode,
@@ -5440,28 +5440,28 @@ class ReactNativeMTLSAdapter {
5440
5440
  this.eventListeners.push(debugListener);
5441
5441
  // Set up error logging with the correct event signature
5442
5442
  const errorListener = ExpoMutualTls.onError((event) => {
5443
- log$5.error(event.message, {
5443
+ log$8.error(event.message, {
5444
5444
  code: event.code,
5445
5445
  });
5446
5446
  });
5447
5447
  this.eventListeners.push(errorListener);
5448
5448
  // Set up certificate expiry monitoring with the correct event signature
5449
5449
  const expiryListener = ExpoMutualTls.onCertificateExpiry((event) => {
5450
- log$5.warn(`Certificate ${event.subject} expires at ${new Date(event.expiry)}`, {
5450
+ log$8.warn(`Certificate ${event.subject} expires at ${new Date(event.expiry)}`, {
5451
5451
  alias: event.alias,
5452
5452
  warning: event.warning,
5453
5453
  });
5454
5454
  });
5455
5455
  this.eventListeners.push(expiryListener);
5456
- log$5.debug('Expo mTLS module loaded successfully');
5456
+ log$8.debug('Expo mTLS module loaded successfully');
5457
5457
  }
5458
5458
  catch (error) {
5459
- log$5.warn('@a-cube-io/expo-mutual-tls not available:', error);
5459
+ log$8.warn('@a-cube-io/expo-mutual-tls not available:', error);
5460
5460
  }
5461
5461
  }
5462
5462
  async isMTLSSupported() {
5463
5463
  const supported = this.expoMTLS !== null;
5464
- log$5.debug('mTLS support check:', {
5464
+ log$8.debug('mTLS support check:', {
5465
5465
  supported,
5466
5466
  platform: this.getPlatformInfo().platform,
5467
5467
  moduleAvailable: !!this.expoMTLS,
@@ -5473,7 +5473,7 @@ class ReactNativeMTLSAdapter {
5473
5473
  throw new MTLSError(exports.MTLSErrorType.NOT_SUPPORTED, 'Expo mTLS module not available');
5474
5474
  }
5475
5475
  this.config = config;
5476
- log$5.debug('Initialized with config:', {
5476
+ log$8.debug('Initialized with config:', {
5477
5477
  baseUrl: config.baseUrl,
5478
5478
  port: config.port,
5479
5479
  timeout: config.timeout,
@@ -5487,7 +5487,7 @@ class ReactNativeMTLSAdapter {
5487
5487
  if (!this.config) {
5488
5488
  throw new MTLSError(exports.MTLSErrorType.CONFIGURATION_ERROR, 'Adapter not initialized. Call initialize() first.');
5489
5489
  }
5490
- log$5.debug('Configuring certificate:', {
5490
+ log$8.debug('Configuring certificate:', {
5491
5491
  format: certificateData.format,
5492
5492
  hasPassword: !!certificateData.password,
5493
5493
  certificateLength: certificateData.certificate.length,
@@ -5504,14 +5504,14 @@ class ReactNativeMTLSAdapter {
5504
5504
  'client-key-service', // keyService
5505
5505
  true // enableLogging - let the native module handle its own debug logging
5506
5506
  );
5507
- log$5.debug('PEM services configured:', configResult);
5507
+ log$8.debug('PEM services configured:', configResult);
5508
5508
  if (!configResult.success) {
5509
5509
  throw new MTLSError(exports.MTLSErrorType.CONFIGURATION_ERROR, `PEM configuration failed: ${configResult.state}`);
5510
5510
  }
5511
5511
  // Step 2: Store the actual PEM certificate and private key
5512
5512
  const storeResult = await this.expoMTLS.storePEM(certificateData.certificate, certificateData.privateKey, certificateData.password // passphrase (optional)
5513
5513
  );
5514
- log$5.debug('PEM certificate store result:', storeResult);
5514
+ log$8.debug('PEM certificate store result:', storeResult);
5515
5515
  if (!storeResult) {
5516
5516
  throw new MTLSError(exports.MTLSErrorType.CERTIFICATE_INVALID, 'Failed to store PEM certificate');
5517
5517
  }
@@ -5524,14 +5524,14 @@ class ReactNativeMTLSAdapter {
5524
5524
  const configResult = await this.expoMTLS.configureP12('client-p12-service', // keychainService
5525
5525
  true // enableLogging - let the native module handle its own debug logging
5526
5526
  );
5527
- log$5.debug('P12 service configured:', configResult);
5527
+ log$8.debug('P12 service configured:', configResult);
5528
5528
  if (!configResult.success) {
5529
5529
  throw new MTLSError(exports.MTLSErrorType.CONFIGURATION_ERROR, `P12 configuration failed: ${configResult.state}`);
5530
5530
  }
5531
5531
  // Step 2: Store the P12 certificate data
5532
5532
  const storeResult = await this.expoMTLS.storeP12(certificateData.certificate, // P12 data in certificate field
5533
5533
  certificateData.password);
5534
- log$5.debug('P12 certificate store result:', storeResult);
5534
+ log$8.debug('P12 certificate store result:', storeResult);
5535
5535
  if (!storeResult) {
5536
5536
  throw new MTLSError(exports.MTLSErrorType.CERTIFICATE_INVALID, 'Failed to store P12 certificate');
5537
5537
  }
@@ -5545,7 +5545,7 @@ class ReactNativeMTLSAdapter {
5545
5545
  if (error instanceof MTLSError) {
5546
5546
  throw error;
5547
5547
  }
5548
- log$5.error('Certificate configuration failed:', error);
5548
+ log$8.error('Certificate configuration failed:', error);
5549
5549
  throw new MTLSError(exports.MTLSErrorType.CONFIGURATION_ERROR, 'Failed to configure certificate', error);
5550
5550
  }
5551
5551
  }
@@ -5556,38 +5556,38 @@ class ReactNativeMTLSAdapter {
5556
5556
  try {
5557
5557
  // Use static method call
5558
5558
  const hasCert = await this.expoMTLS.hasCertificate();
5559
- log$5.debug('Certificate availability check:', hasCert);
5559
+ log$8.debug('Certificate availability check:', hasCert);
5560
5560
  return hasCert;
5561
5561
  }
5562
5562
  catch (error) {
5563
- log$5.error('Certificate check failed:', error);
5563
+ log$8.error('Certificate check failed:', error);
5564
5564
  return false;
5565
5565
  }
5566
5566
  }
5567
5567
  async getCertificateInfo() {
5568
5568
  if (!this.expoMTLS) {
5569
- log$5.debug('Certificate info requested but module not available');
5569
+ log$8.debug('Certificate info requested but module not available');
5570
5570
  return null;
5571
5571
  }
5572
5572
  try {
5573
5573
  const hasCert = await this.hasCertificate();
5574
5574
  if (!hasCert) {
5575
- log$5.debug('No certificate stored');
5575
+ log$8.debug('No certificate stored');
5576
5576
  return null;
5577
5577
  }
5578
5578
  // Use getCertificatesInfo to retrieve information about stored certificates
5579
5579
  const result = await this.expoMTLS.getCertificatesInfo();
5580
5580
  if (!result || !result.certificates || result.certificates.length === 0) {
5581
- log$5.debug('No certificate information available');
5581
+ log$8.debug('No certificate information available');
5582
5582
  return null;
5583
5583
  }
5584
5584
  // Get the first certificate (primary client certificate)
5585
5585
  const cert = result.certificates[0];
5586
5586
  if (!cert) {
5587
- log$5.debug('Certificate data is empty');
5587
+ log$8.debug('Certificate data is empty');
5588
5588
  return null;
5589
5589
  }
5590
- log$5.debug('Retrieved certificate info:', {
5590
+ log$8.debug('Retrieved certificate info:', {
5591
5591
  subject: cert.subject.commonName,
5592
5592
  issuer: cert.issuer.commonName,
5593
5593
  validFrom: new Date(cert.validFrom),
@@ -5606,7 +5606,7 @@ class ReactNativeMTLSAdapter {
5606
5606
  };
5607
5607
  }
5608
5608
  catch (error) {
5609
- log$5.error('Failed to get certificate info:', error);
5609
+ log$8.error('Failed to get certificate info:', error);
5610
5610
  return null;
5611
5611
  }
5612
5612
  }
@@ -5617,7 +5617,7 @@ class ReactNativeMTLSAdapter {
5617
5617
  */
5618
5618
  async parseCertificateData(certificateData) {
5619
5619
  if (!this.expoMTLS) {
5620
- log$5.debug('Parse certificate: Module not available');
5620
+ log$8.debug('Parse certificate: Module not available');
5621
5621
  return null;
5622
5622
  }
5623
5623
  try {
@@ -5634,14 +5634,14 @@ class ReactNativeMTLSAdapter {
5634
5634
  else {
5635
5635
  throw new MTLSError(exports.MTLSErrorType.CERTIFICATE_INVALID, `Unsupported certificate format: ${certificateData.format}`);
5636
5636
  }
5637
- log$5.debug('Certificate parsed successfully:', {
5637
+ log$8.debug('Certificate parsed successfully:', {
5638
5638
  certificateCount: result.certificates.length,
5639
5639
  subjects: result.certificates.map((cert) => cert.subject.commonName),
5640
5640
  });
5641
5641
  return result;
5642
5642
  }
5643
5643
  catch (error) {
5644
- log$5.error('Failed to parse certificate:', error);
5644
+ log$8.error('Failed to parse certificate:', error);
5645
5645
  if (error instanceof MTLSError) {
5646
5646
  throw error;
5647
5647
  }
@@ -5656,7 +5656,7 @@ class ReactNativeMTLSAdapter {
5656
5656
  if (!hasCert) {
5657
5657
  throw new MTLSError(exports.MTLSErrorType.CERTIFICATE_NOT_FOUND, 'No certificate configured');
5658
5658
  }
5659
- log$5.debug('Making mTLS request:', {
5659
+ log$8.debug('Making mTLS request:', {
5660
5660
  method: requestConfig.method || 'GET',
5661
5661
  url: requestConfig.url,
5662
5662
  headers: requestConfig.headers,
@@ -5664,7 +5664,7 @@ class ReactNativeMTLSAdapter {
5664
5664
  responseType: requestConfig.responseType,
5665
5665
  });
5666
5666
  if (requestConfig.data) {
5667
- log$5.debug('mTLS request body:', requestConfig.data);
5667
+ log$8.debug('mTLS request body:', requestConfig.data);
5668
5668
  }
5669
5669
  try {
5670
5670
  const response = await this.expoMTLS.request(requestConfig.url, {
@@ -5673,7 +5673,7 @@ class ReactNativeMTLSAdapter {
5673
5673
  body: requestConfig.data ? JSON.stringify(requestConfig.data) : undefined,
5674
5674
  responseType: requestConfig.responseType,
5675
5675
  });
5676
- log$5.debug('mTLS request successful:', response);
5676
+ log$8.debug('mTLS request successful:', response);
5677
5677
  if (!response.success) {
5678
5678
  throw new MTLSError(exports.MTLSErrorType.CONNECTION_FAILED, `mTLS request failed: ${response.statusMessage} (${response.statusCode})`, undefined, response.statusCode);
5679
5679
  }
@@ -5685,7 +5685,7 @@ class ReactNativeMTLSAdapter {
5685
5685
  data = JSON.parse(response.body);
5686
5686
  }
5687
5687
  catch (parseError) {
5688
- log$5.warn('Failed to parse JSON response:', parseError);
5688
+ log$8.warn('Failed to parse JSON response:', parseError);
5689
5689
  // If parsing fails, keep raw body
5690
5690
  }
5691
5691
  }
@@ -5702,7 +5702,7 @@ class ReactNativeMTLSAdapter {
5702
5702
  };
5703
5703
  }
5704
5704
  catch (error) {
5705
- log$5.error('mTLS request failed:', error);
5705
+ log$8.error('mTLS request failed:', error);
5706
5706
  throw new MTLSError(exports.MTLSErrorType.CONNECTION_FAILED, 'mTLS request failed', error);
5707
5707
  }
5708
5708
  }
@@ -5715,18 +5715,18 @@ class ReactNativeMTLSAdapter {
5715
5715
  */
5716
5716
  async testConnection() {
5717
5717
  if (!this.expoMTLS || !this.config) {
5718
- log$5.debug('Diagnostic test: No mTLS module or config available');
5718
+ log$8.debug('Diagnostic test: No mTLS module or config available');
5719
5719
  return false;
5720
5720
  }
5721
5721
  try {
5722
5722
  const hasCert = await this.hasCertificate();
5723
5723
  if (!hasCert) {
5724
- log$5.debug('Diagnostic test: No certificate configured');
5724
+ log$8.debug('Diagnostic test: No certificate configured');
5725
5725
  return false;
5726
5726
  }
5727
- log$5.debug('Running diagnostic test (may fail even if mTLS works):', this.config.baseUrl);
5727
+ log$8.debug('Running diagnostic test (may fail even if mTLS works):', this.config.baseUrl);
5728
5728
  const result = await this.expoMTLS.testConnection(this.config.baseUrl);
5729
- log$5.debug('Diagnostic test result (NOT validation):', {
5729
+ log$8.debug('Diagnostic test result (NOT validation):', {
5730
5730
  success: result.success,
5731
5731
  statusCode: result.statusCode,
5732
5732
  statusMessage: result.statusMessage,
@@ -5737,13 +5737,13 @@ class ReactNativeMTLSAdapter {
5737
5737
  return result.success;
5738
5738
  }
5739
5739
  catch (error) {
5740
- log$5.warn('Diagnostic test failed (this is expected):', error);
5740
+ log$8.warn('Diagnostic test failed (this is expected):', error);
5741
5741
  return false;
5742
5742
  }
5743
5743
  }
5744
5744
  async removeCertificate() {
5745
5745
  if (!this.expoMTLS) {
5746
- log$5.debug('Remove certificate: Module not available');
5746
+ log$8.debug('Remove certificate: Module not available');
5747
5747
  return;
5748
5748
  }
5749
5749
  try {
@@ -5752,10 +5752,10 @@ class ReactNativeMTLSAdapter {
5752
5752
  this.isConfigured = false;
5753
5753
  // Cleanup event listeners
5754
5754
  this.cleanupEventListeners();
5755
- log$5.debug('Certificate removed successfully');
5755
+ log$8.debug('Certificate removed successfully');
5756
5756
  }
5757
5757
  catch (error) {
5758
- log$5.error('Failed to remove certificate:', error);
5758
+ log$8.error('Failed to remove certificate:', error);
5759
5759
  throw new MTLSError(exports.MTLSErrorType.CONFIGURATION_ERROR, 'Failed to remove certificate', error);
5760
5760
  }
5761
5761
  }
@@ -5764,7 +5764,7 @@ class ReactNativeMTLSAdapter {
5764
5764
  */
5765
5765
  cleanupEventListeners() {
5766
5766
  if (this.eventListeners.length > 0) {
5767
- log$5.debug(`Cleaning up ${this.eventListeners.length} event listeners`);
5767
+ log$8.debug(`Cleaning up ${this.eventListeners.length} event listeners`);
5768
5768
  }
5769
5769
  // Remove individual listeners if they have remove methods
5770
5770
  this.eventListeners.forEach((listener) => {
@@ -5801,7 +5801,7 @@ class ReactNativeMTLSAdapter {
5801
5801
  }
5802
5802
  }
5803
5803
 
5804
- const log$4 = createPrefixedLogger('WEB-MTLS');
5804
+ const log$7 = createPrefixedLogger('WEB-MTLS');
5805
5805
  /**
5806
5806
  * Web mTLS Adapter - Graceful fallback for web browsers
5807
5807
  *
@@ -5815,13 +5815,13 @@ const log$4 = createPrefixedLogger('WEB-MTLS');
5815
5815
  */
5816
5816
  class WebMTLSAdapter {
5817
5817
  constructor() {
5818
- log$4.warn('Web browsers do not support programmatic mTLS configuration');
5819
- log$4.info('Use JWT authentication or configure client certificates in browser settings');
5818
+ log$7.warn('Web browsers do not support programmatic mTLS configuration');
5819
+ log$7.info('Use JWT authentication or configure client certificates in browser settings');
5820
5820
  }
5821
5821
  async isMTLSSupported() {
5822
5822
  // mTLS is not supported programmatically in web browsers
5823
5823
  const supported = false;
5824
- log$4.debug('mTLS support check:', {
5824
+ log$7.debug('mTLS support check:', {
5825
5825
  supported,
5826
5826
  platform: this.getPlatformInfo().platform,
5827
5827
  reason: 'Browser security model prevents programmatic certificate configuration',
@@ -5830,14 +5830,14 @@ class WebMTLSAdapter {
5830
5830
  return supported;
5831
5831
  }
5832
5832
  async initialize(config) {
5833
- log$4.warn('Initialized but mTLS not available in web browsers:', {
5833
+ log$7.warn('Initialized but mTLS not available in web browsers:', {
5834
5834
  baseUrl: config.baseUrl,
5835
5835
  port: config.port,
5836
5836
  recommendation: 'Use standard HTTPS with JWT authentication',
5837
5837
  });
5838
5838
  }
5839
5839
  async configureCertificate(certificateData) {
5840
- log$4.error('Certificate configuration attempted:', {
5840
+ log$7.error('Certificate configuration attempted:', {
5841
5841
  format: certificateData.format,
5842
5842
  reason: 'Not supported in web browsers',
5843
5843
  alternatives: [
@@ -5852,15 +5852,15 @@ class WebMTLSAdapter {
5852
5852
  }
5853
5853
  async hasCertificate() {
5854
5854
  // We cannot detect if the browser has certificates configured
5855
- log$4.debug('Certificate availability check: Cannot detect browser certificates programmatically');
5855
+ log$7.debug('Certificate availability check: Cannot detect browser certificates programmatically');
5856
5856
  return false;
5857
5857
  }
5858
5858
  async getCertificateInfo() {
5859
- log$4.debug('Certificate info requested: Not accessible in web browsers');
5859
+ log$7.debug('Certificate info requested: Not accessible in web browsers');
5860
5860
  return null;
5861
5861
  }
5862
5862
  async request(requestConfig) {
5863
- log$4.error('mTLS request attempted:', {
5863
+ log$7.error('mTLS request attempted:', {
5864
5864
  method: requestConfig.method,
5865
5865
  url: requestConfig.url,
5866
5866
  reason: 'Not supported in web browsers',
@@ -5875,11 +5875,11 @@ class WebMTLSAdapter {
5875
5875
  'are properly configured in the browser certificate store.');
5876
5876
  }
5877
5877
  async testConnection() {
5878
- log$4.debug('Connection test: mTLS not available in web browsers');
5878
+ log$7.debug('Connection test: mTLS not available in web browsers');
5879
5879
  return false;
5880
5880
  }
5881
5881
  async removeCertificate() {
5882
- log$4.debug('Remove certificate: No certificates to remove (not supported in web browsers)');
5882
+ log$7.debug('Remove certificate: No certificates to remove (not supported in web browsers)');
5883
5883
  // No-op - cannot remove certificates programmatically in browsers
5884
5884
  }
5885
5885
  /**
@@ -5887,7 +5887,7 @@ class WebMTLSAdapter {
5887
5887
  * Always returns null for web browsers as mTLS is not supported
5888
5888
  */
5889
5889
  getBaseUrl() {
5890
- log$4.debug('Base URL requested: Not supported in web browsers');
5890
+ log$7.debug('Base URL requested: Not supported in web browsers');
5891
5891
  return null;
5892
5892
  }
5893
5893
  getPlatformInfo() {
@@ -5920,7 +5920,7 @@ class WebMTLSAdapter {
5920
5920
  }
5921
5921
  }
5922
5922
 
5923
- const log$3 = createPrefixedLogger('MTLS-LOADER');
5923
+ const log$6 = createPrefixedLogger('MTLS-LOADER');
5924
5924
  function loadMTLSAdapter(platform, config) {
5925
5925
  try {
5926
5926
  let adapter;
@@ -5954,7 +5954,7 @@ function loadMTLSAdapter(platform, config) {
5954
5954
  return adapter;
5955
5955
  }
5956
5956
  catch (error) {
5957
- log$3.warn(`mTLS adapter not available for platform ${platform}:`, error);
5957
+ log$6.warn(`mTLS adapter not available for platform ${platform}:`, error);
5958
5958
  return null;
5959
5959
  }
5960
5960
  }
@@ -5964,7 +5964,7 @@ async function initializeAdapterAsync(adapter, config) {
5964
5964
  if (isSupported) {
5965
5965
  await adapter.initialize(config);
5966
5966
  const platformInfo = adapter.getPlatformInfo();
5967
- log$3.debug('mTLS adapter initialized:', {
5967
+ log$6.debug('mTLS adapter initialized:', {
5968
5968
  platform: platformInfo.platform,
5969
5969
  mtlsSupported: platformInfo.mtlsSupported,
5970
5970
  certificateStorage: platformInfo.certificateStorage,
@@ -5973,20 +5973,20 @@ async function initializeAdapterAsync(adapter, config) {
5973
5973
  }
5974
5974
  }
5975
5975
  catch (error) {
5976
- log$3.warn('Failed to initialize mTLS adapter:', error);
5976
+ log$6.warn('Failed to initialize mTLS adapter:', error);
5977
5977
  }
5978
5978
  }
5979
5979
 
5980
- const log$2 = createPrefixedLogger('ADAPTER-LOADER');
5980
+ const log$5 = createPrefixedLogger('ADAPTER-LOADER');
5981
5981
  function loadPlatformAdapters(options = {}) {
5982
5982
  const { mtlsConfig } = options;
5983
5983
  const { platform } = detectPlatform();
5984
- log$2.debug('Loading adapters for platform:', platform);
5984
+ log$5.debug('Loading adapters for platform:', platform);
5985
5985
  const storageAdapters = loadStorageAdapters(platform);
5986
5986
  const networkMonitor = loadNetworkMonitor(platform);
5987
5987
  const cache = loadCacheAdapter(platform);
5988
5988
  const mtls = loadMTLSAdapter(platform, mtlsConfig);
5989
- log$2.debug('Adapters loaded:', {
5989
+ log$5.debug('Adapters loaded:', {
5990
5990
  platform,
5991
5991
  hasStorage: !!storageAdapters.storage,
5992
5992
  hasSecureStorage: !!storageAdapters.secureStorage,
@@ -6100,10 +6100,12 @@ class ACubeSDKError extends Error {
6100
6100
 
6101
6101
  const DI_TOKENS = {
6102
6102
  HTTP_PORT: Symbol('HTTP_PORT'),
6103
+ BASE_HTTP_PORT: Symbol('BASE_HTTP_PORT'),
6103
6104
  STORAGE_PORT: Symbol('STORAGE_PORT'),
6104
6105
  SECURE_STORAGE_PORT: Symbol('SECURE_STORAGE_PORT'),
6105
6106
  NETWORK_PORT: Symbol('NETWORK_PORT'),
6106
6107
  CACHE_PORT: Symbol('CACHE_PORT'),
6108
+ CACHE_KEY_GENERATOR: Symbol('CACHE_KEY_GENERATOR'),
6107
6109
  MTLS_PORT: Symbol('MTLS_PORT'),
6108
6110
  TOKEN_STORAGE_PORT: Symbol('TOKEN_STORAGE_PORT'),
6109
6111
  RECEIPT_REPOSITORY: Symbol('RECEIPT_REPOSITORY'),
@@ -6333,7 +6335,7 @@ class ReceiptRepositoryImpl {
6333
6335
  if (format === 'pdf') {
6334
6336
  const response = await this.http.get(`/mf1/receipts/${receiptUuid}/details`, {
6335
6337
  headers: { Accept: 'application/pdf' },
6336
- responseType: 'blob',
6338
+ responseType: 'arraybuffer',
6337
6339
  });
6338
6340
  return response.data;
6339
6341
  }
@@ -7096,7 +7098,465 @@ class TelemetryRepositoryImpl {
7096
7098
  }
7097
7099
  }
7098
7100
 
7099
- const log$1 = createPrefixedLogger('HTTP-MTLS');
7101
+ const log$4 = createPrefixedLogger('CACHE-KEY');
7102
+ const URL_PATTERNS = [
7103
+ // Receipt (mf1) - specific patterns first
7104
+ {
7105
+ pattern: /^\/mf1\/receipts\/([^/]+)\/returnable-items$/,
7106
+ resource: 'receipt',
7107
+ action: 'returnable',
7108
+ },
7109
+ {
7110
+ pattern: /^\/mf1\/receipts\/([^/]+)\/details$/,
7111
+ resource: 'receipt',
7112
+ action: 'details',
7113
+ },
7114
+ { pattern: /^\/mf1\/receipts\/([^/]+)$/, resource: 'receipt' },
7115
+ {
7116
+ pattern: /^\/mf1\/point-of-sales\/([^/]+)\/receipts$/,
7117
+ resource: 'receipt',
7118
+ parent: 'point-of-sale',
7119
+ isList: true,
7120
+ },
7121
+ { pattern: /^\/mf1\/receipts$/, resource: 'receipt', isList: true },
7122
+ // Merchant (mf2)
7123
+ { pattern: /^\/mf2\/merchants\/([^/]+)$/, resource: 'merchant' },
7124
+ { pattern: /^\/mf2\/merchants$/, resource: 'merchant', isList: true },
7125
+ // Cashier (mf1)
7126
+ { pattern: /^\/mf1\/cashiers\/me$/, resource: 'cashier', action: 'me' },
7127
+ { pattern: /^\/mf1\/cashiers\/([^/]+)$/, resource: 'cashier' },
7128
+ { pattern: /^\/mf1\/cashiers$/, resource: 'cashier', isList: true },
7129
+ // Cash Register (mf1)
7130
+ { pattern: /^\/mf1\/cash-registers\/([^/]+)$/, resource: 'cash-register' },
7131
+ { pattern: /^\/mf1\/cash-registers$/, resource: 'cash-register', isList: true },
7132
+ // Point of Sale (mf1)
7133
+ { pattern: /^\/mf1\/point-of-sales\/([^/]+)$/, resource: 'point-of-sale' },
7134
+ { pattern: /^\/mf1\/point-of-sales$/, resource: 'point-of-sale', isList: true },
7135
+ // Nested resources under merchant (mf2)
7136
+ {
7137
+ pattern: /^\/mf2\/merchants\/([^/]+)\/suppliers\/([^/]+)$/,
7138
+ resource: 'supplier',
7139
+ parent: 'merchant',
7140
+ },
7141
+ {
7142
+ pattern: /^\/mf2\/merchants\/([^/]+)\/suppliers$/,
7143
+ resource: 'supplier',
7144
+ parent: 'merchant',
7145
+ isList: true,
7146
+ },
7147
+ {
7148
+ pattern: /^\/mf2\/merchants\/([^/]+)\/daily-reports/,
7149
+ resource: 'daily-report',
7150
+ parent: 'merchant',
7151
+ isList: true,
7152
+ },
7153
+ {
7154
+ pattern: /^\/mf2\/merchants\/([^/]+)\/journals/,
7155
+ resource: 'journal',
7156
+ parent: 'merchant',
7157
+ isList: true,
7158
+ },
7159
+ // PEM (mf2)
7160
+ {
7161
+ pattern: /^\/mf2\/point-of-sales\/([^/]+)\/certificates$/,
7162
+ resource: 'pem',
7163
+ action: 'certificates',
7164
+ },
7165
+ { pattern: /^\/mf2\/point-of-sales\/([^/]+)$/, resource: 'pem' },
7166
+ // Others
7167
+ { pattern: /^\/mf1\/notifications/, resource: 'notification', isList: true },
7168
+ {
7169
+ pattern: /^\/mf1\/point-of-sales\/([^/]+)\/telemetry$/,
7170
+ resource: 'telemetry',
7171
+ },
7172
+ ];
7173
+ const DEFAULT_TTL_CONFIG = {
7174
+ // Data that rarely changes - 30 min TTL for items only
7175
+ merchant: { ttlMs: 30 * 60 * 1000, cacheList: false, cacheItem: true },
7176
+ 'point-of-sale': { ttlMs: 30 * 60 * 1000, cacheList: false, cacheItem: true },
7177
+ 'cash-register': { ttlMs: 30 * 60 * 1000, cacheList: false, cacheItem: true },
7178
+ pem: { ttlMs: 30 * 60 * 1000, cacheList: false, cacheItem: false },
7179
+ // Data that changes moderately - 10 min TTL for items only
7180
+ cashier: { ttlMs: 10 * 60 * 1000, cacheList: false, cacheItem: true },
7181
+ supplier: { ttlMs: 10 * 60 * 1000, cacheList: false, cacheItem: true },
7182
+ // Data that can change - 5 min TTL for items only
7183
+ receipt: { ttlMs: 5 * 60 * 1000, cacheList: false, cacheItem: true },
7184
+ 'daily-report': { ttlMs: 5 * 60 * 1000, cacheList: false, cacheItem: true },
7185
+ journal: { ttlMs: 5 * 60 * 1000, cacheList: false, cacheItem: true },
7186
+ // Real-time data - 1 min TTL
7187
+ notification: { ttlMs: 1 * 60 * 1000, cacheList: false, cacheItem: false },
7188
+ telemetry: { ttlMs: 1 * 60 * 1000, cacheList: false, cacheItem: false },
7189
+ };
7190
+ const DEFAULT_TTL = 5 * 60 * 1000; // 5 minutes
7191
+ class CacheKeyGenerator {
7192
+ constructor(customConfig) {
7193
+ this.config = { ...DEFAULT_TTL_CONFIG, ...customConfig };
7194
+ log$4.info('CacheKeyGenerator initialized with config:', {
7195
+ resources: Object.keys(this.config),
7196
+ });
7197
+ }
7198
+ generate(url, params) {
7199
+ const parsed = this.parseUrl(url);
7200
+ if (!parsed) {
7201
+ // Fallback: use URL as key
7202
+ const paramStr = params ? this.serializeParams(params) : '';
7203
+ const key = paramStr ? `${url}?${paramStr}` : url;
7204
+ log$4.debug('URL not matched, using fallback key:', { url, key });
7205
+ return key;
7206
+ }
7207
+ const { resource, ids, action, isList, parent } = parsed;
7208
+ if (isList) {
7209
+ const paramStr = params ? this.serializeParams(params) : '';
7210
+ const parentPart = parent && ids.length > 0 ? `${parent}=${ids[0]}&` : '';
7211
+ const key = `${resource}:list:${parentPart}${paramStr}`;
7212
+ log$4.debug('Generated list cache key:', { url, key, resource });
7213
+ return key;
7214
+ }
7215
+ // Single item
7216
+ if (ids.length === 0 && action) {
7217
+ // Special case for endpoints like /cashiers/me
7218
+ const key = `${resource}:${action}`;
7219
+ log$4.debug('Generated special action cache key:', { url, key, resource, action });
7220
+ return key;
7221
+ }
7222
+ let key = `${resource}:${ids.join(':')}`;
7223
+ if (action) {
7224
+ key += `:${action}`;
7225
+ }
7226
+ log$4.debug('Generated item cache key:', { url, key, resource, ids, action });
7227
+ return key;
7228
+ }
7229
+ parseResource(url) {
7230
+ const parsed = this.parseUrl(url);
7231
+ return parsed?.resource;
7232
+ }
7233
+ getTTL(url) {
7234
+ const resource = this.parseResource(url);
7235
+ if (!resource) {
7236
+ log$4.debug('No resource found for URL, using default TTL:', { url, ttl: DEFAULT_TTL });
7237
+ return DEFAULT_TTL;
7238
+ }
7239
+ const ttl = this.config[resource].ttlMs;
7240
+ log$4.debug('TTL for resource:', { url, resource, ttlMs: ttl, ttlMin: ttl / 60000 });
7241
+ return ttl;
7242
+ }
7243
+ shouldCache(url) {
7244
+ const parsed = this.parseUrl(url);
7245
+ if (!parsed) {
7246
+ log$4.debug('URL not recognized, should not cache:', { url });
7247
+ return false;
7248
+ }
7249
+ const { resource, isList } = parsed;
7250
+ const config = this.config[resource];
7251
+ if (isList) {
7252
+ log$4.debug('List endpoint cache decision:', {
7253
+ url,
7254
+ resource,
7255
+ isList: true,
7256
+ shouldCache: config.cacheList,
7257
+ });
7258
+ return config.cacheList;
7259
+ }
7260
+ log$4.debug('Item endpoint cache decision:', {
7261
+ url,
7262
+ resource,
7263
+ isList: false,
7264
+ shouldCache: config.cacheItem,
7265
+ });
7266
+ return config.cacheItem;
7267
+ }
7268
+ getInvalidationPatterns(url, method) {
7269
+ const parsed = this.parseUrl(url);
7270
+ if (!parsed) {
7271
+ log$4.debug('No patterns to invalidate for URL:', { url, method });
7272
+ return [];
7273
+ }
7274
+ const { resource, ids, parent } = parsed;
7275
+ const patterns = [];
7276
+ // Always invalidate list on mutations
7277
+ if (method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'DELETE') {
7278
+ if (parent && ids.length > 0) {
7279
+ patterns.push(`${resource}:list:${parent}=${ids[0]}*`);
7280
+ }
7281
+ patterns.push(`${resource}:list:*`);
7282
+ }
7283
+ // Invalidate specific item on PUT/PATCH/DELETE
7284
+ if (method === 'PUT' || method === 'PATCH' || method === 'DELETE') {
7285
+ if (ids.length > 0) {
7286
+ patterns.push(`${resource}:${ids.join(':')}*`);
7287
+ }
7288
+ }
7289
+ // Special cases
7290
+ if (resource === 'cashier' && (method === 'PUT' || method === 'DELETE')) {
7291
+ patterns.push('cashier:me');
7292
+ }
7293
+ log$4.debug('Invalidation patterns:', { url, method, patterns });
7294
+ return patterns;
7295
+ }
7296
+ parseUrl(url) {
7297
+ // Remove query string for pattern matching
7298
+ const urlPath = url.split('?')[0];
7299
+ for (const pattern of URL_PATTERNS) {
7300
+ const match = urlPath?.match(pattern.pattern);
7301
+ if (match) {
7302
+ // Extract IDs from capture groups
7303
+ const ids = match.slice(1).filter(Boolean);
7304
+ return {
7305
+ resource: pattern.resource,
7306
+ ids,
7307
+ action: pattern.action,
7308
+ isList: pattern.isList,
7309
+ parent: pattern.parent,
7310
+ };
7311
+ }
7312
+ }
7313
+ return null;
7314
+ }
7315
+ serializeParams(params) {
7316
+ const sortedKeys = Object.keys(params).sort();
7317
+ const parts = [];
7318
+ for (const key of sortedKeys) {
7319
+ const value = params[key];
7320
+ if (value !== undefined && value !== null) {
7321
+ parts.push(`${key}=${String(value)}`);
7322
+ }
7323
+ }
7324
+ return parts.join('&');
7325
+ }
7326
+ }
7327
+
7328
+ const log$3 = createPrefixedLogger('CACHE');
7329
+ class CachingHttpDecorator {
7330
+ constructor(http, cache, keyGenerator, networkMonitor, config = {}) {
7331
+ this.http = http;
7332
+ this.cache = cache;
7333
+ this.keyGenerator = keyGenerator;
7334
+ this.networkMonitor = networkMonitor;
7335
+ this.config = config;
7336
+ this.currentOnlineState = true;
7337
+ this.authToken = null;
7338
+ log$3.info('CachingHttpDecorator initialized', {
7339
+ enabled: config.enabled !== false,
7340
+ hasNetworkMonitor: !!networkMonitor,
7341
+ });
7342
+ this.setupNetworkMonitoring();
7343
+ }
7344
+ setupNetworkMonitoring() {
7345
+ if (this.networkMonitor) {
7346
+ this.networkSubscription = this.networkMonitor.online$.subscribe((online) => {
7347
+ if (this.currentOnlineState !== online) {
7348
+ log$3.info('Network state changed:', { online });
7349
+ }
7350
+ this.currentOnlineState = online;
7351
+ });
7352
+ }
7353
+ }
7354
+ isOnline() {
7355
+ if (this.networkMonitor) {
7356
+ return this.currentOnlineState;
7357
+ }
7358
+ if (typeof navigator !== 'undefined' && 'onLine' in navigator) {
7359
+ return navigator.onLine;
7360
+ }
7361
+ return true;
7362
+ }
7363
+ async get(url, config) {
7364
+ const startTime = Date.now();
7365
+ // Check if caching is disabled globally
7366
+ if (this.config.enabled === false) {
7367
+ log$3.debug('GET (cache disabled globally):', { url });
7368
+ return this.http.get(url, config);
7369
+ }
7370
+ // Check if this URL should be cached
7371
+ const shouldCache = this.keyGenerator.shouldCache(url);
7372
+ if (!shouldCache) {
7373
+ log$3.debug('GET (not cacheable - likely a list endpoint):', { url });
7374
+ return this.http.get(url, config);
7375
+ }
7376
+ const cacheKey = this.keyGenerator.generate(url, config?.params);
7377
+ const ttl = this.keyGenerator.getTTL(url);
7378
+ const resource = this.keyGenerator.parseResource(url);
7379
+ log$3.info('GET request starting:', {
7380
+ url,
7381
+ resource,
7382
+ cacheKey,
7383
+ ttlMs: ttl,
7384
+ ttlMin: Math.round(ttl / 60000),
7385
+ params: config?.params,
7386
+ });
7387
+ // Check cache
7388
+ let cached = null;
7389
+ try {
7390
+ cached = await this.cache.get(cacheKey);
7391
+ if (cached) {
7392
+ log$3.debug('Cache entry found:', {
7393
+ cacheKey,
7394
+ timestamp: new Date(cached.timestamp).toISOString(),
7395
+ ageMs: Date.now() - cached.timestamp,
7396
+ });
7397
+ }
7398
+ else {
7399
+ log$3.debug('Cache entry not found:', { cacheKey });
7400
+ }
7401
+ }
7402
+ catch (error) {
7403
+ log$3.warn('Cache lookup failed:', {
7404
+ cacheKey,
7405
+ error: error instanceof Error ? error.message : error,
7406
+ });
7407
+ }
7408
+ if (cached) {
7409
+ const age = Date.now() - cached.timestamp;
7410
+ const isExpired = age >= ttl;
7411
+ log$3.debug('Cache analysis:', {
7412
+ cacheKey,
7413
+ ageMs: age,
7414
+ ageSec: Math.round(age / 1000),
7415
+ ttlMs: ttl,
7416
+ isExpired,
7417
+ isOnline: this.isOnline(),
7418
+ });
7419
+ // If within TTL, return cached data
7420
+ if (!isExpired) {
7421
+ const duration = Date.now() - startTime;
7422
+ log$3.info('CACHE HIT:', {
7423
+ url,
7424
+ cacheKey,
7425
+ ageMs: age,
7426
+ durationMs: duration,
7427
+ });
7428
+ return {
7429
+ data: cached.data,
7430
+ status: 200,
7431
+ headers: { 'x-cache': 'HIT' },
7432
+ };
7433
+ }
7434
+ // If offline and cache is stale, return stale data
7435
+ if (!this.isOnline()) {
7436
+ const duration = Date.now() - startTime;
7437
+ log$3.info('CACHE STALE (offline):', {
7438
+ url,
7439
+ cacheKey,
7440
+ ageMs: age,
7441
+ durationMs: duration,
7442
+ });
7443
+ return {
7444
+ data: cached.data,
7445
+ status: 200,
7446
+ headers: { 'x-cache': 'STALE' },
7447
+ };
7448
+ }
7449
+ log$3.debug('Cache expired, fetching fresh data:', { cacheKey, ageMs: age, ttlMs: ttl });
7450
+ }
7451
+ // Fetch fresh data
7452
+ try {
7453
+ log$3.debug('Fetching from network:', { url });
7454
+ const response = await this.http.get(url, config);
7455
+ // Cache the response
7456
+ try {
7457
+ await this.cache.set(cacheKey, response.data);
7458
+ log$3.debug('Response cached successfully:', { cacheKey });
7459
+ }
7460
+ catch (error) {
7461
+ log$3.error('Failed to cache response:', {
7462
+ cacheKey,
7463
+ error: error instanceof Error ? error.message : error,
7464
+ });
7465
+ }
7466
+ const duration = Date.now() - startTime;
7467
+ log$3.info('CACHE MISS (fetched fresh):', {
7468
+ url,
7469
+ cacheKey,
7470
+ status: response.status,
7471
+ durationMs: duration,
7472
+ });
7473
+ return {
7474
+ ...response,
7475
+ headers: { ...response.headers, 'x-cache': 'MISS' },
7476
+ };
7477
+ }
7478
+ catch (error) {
7479
+ // On error, return stale cache if available
7480
+ if (cached) {
7481
+ const duration = Date.now() - startTime;
7482
+ log$3.warn('CACHE STALE (network error):', {
7483
+ url,
7484
+ cacheKey,
7485
+ error: error instanceof Error ? error.message : 'Unknown error',
7486
+ durationMs: duration,
7487
+ });
7488
+ return {
7489
+ data: cached.data,
7490
+ status: 200,
7491
+ headers: { 'x-cache': 'STALE' },
7492
+ };
7493
+ }
7494
+ log$3.error('Network error with no cache fallback:', {
7495
+ url,
7496
+ error: error instanceof Error ? error.message : error,
7497
+ });
7498
+ throw error;
7499
+ }
7500
+ }
7501
+ async post(url, data, config) {
7502
+ log$3.info('POST request:', { url });
7503
+ const response = await this.http.post(url, data, config);
7504
+ await this.invalidateRelated(url, 'POST');
7505
+ return response;
7506
+ }
7507
+ async put(url, data, config) {
7508
+ log$3.info('PUT request:', { url });
7509
+ const response = await this.http.put(url, data, config);
7510
+ await this.invalidateRelated(url, 'PUT');
7511
+ return response;
7512
+ }
7513
+ async patch(url, data, config) {
7514
+ log$3.info('PATCH request:', { url });
7515
+ const response = await this.http.patch(url, data, config);
7516
+ await this.invalidateRelated(url, 'PATCH');
7517
+ return response;
7518
+ }
7519
+ async delete(url, config) {
7520
+ log$3.info('DELETE request:', { url });
7521
+ const response = await this.http.delete(url, config);
7522
+ await this.invalidateRelated(url, 'DELETE');
7523
+ return response;
7524
+ }
7525
+ setAuthToken(token) {
7526
+ log$3.debug('Auth token updated:', { hasToken: !!token });
7527
+ this.authToken = token;
7528
+ this.http.setAuthToken(token);
7529
+ }
7530
+ getAuthToken() {
7531
+ return this.authToken;
7532
+ }
7533
+ async invalidateRelated(url, method) {
7534
+ const patterns = this.keyGenerator.getInvalidationPatterns(url, method);
7535
+ if (patterns.length === 0) {
7536
+ log$3.debug('No cache patterns to invalidate:', { url, method });
7537
+ return;
7538
+ }
7539
+ log$3.info('Invalidating cache patterns:', { url, method, patterns });
7540
+ for (const pattern of patterns) {
7541
+ try {
7542
+ await this.cache.invalidate(pattern);
7543
+ log$3.debug('Cache pattern invalidated:', { pattern });
7544
+ }
7545
+ catch (error) {
7546
+ log$3.error('Failed to invalidate pattern:', {
7547
+ pattern,
7548
+ error: error instanceof Error ? error.message : error,
7549
+ });
7550
+ }
7551
+ }
7552
+ }
7553
+ destroy() {
7554
+ log$3.debug('CachingHttpDecorator destroyed');
7555
+ this.networkSubscription?.unsubscribe();
7556
+ }
7557
+ }
7558
+
7559
+ const log$2 = createPrefixedLogger('HTTP-MTLS');
7100
7560
  class AxiosHttpAdapter {
7101
7561
  constructor(config) {
7102
7562
  this.authToken = null;
@@ -7114,11 +7574,11 @@ class AxiosHttpAdapter {
7114
7574
  }
7115
7575
  setMTLSAdapter(adapter) {
7116
7576
  this.mtlsAdapter = adapter;
7117
- log$1.debug('mTLS adapter configured:', !!adapter);
7577
+ log$2.debug('mTLS adapter configured:', !!adapter);
7118
7578
  }
7119
7579
  setAuthStrategy(strategy) {
7120
7580
  this.authStrategy = strategy;
7121
- log$1.debug('Auth strategy configured:', !!strategy);
7581
+ log$2.debug('Auth strategy configured:', !!strategy);
7122
7582
  }
7123
7583
  async shouldUseMTLS(url, method) {
7124
7584
  if (!this.mtlsAdapter) {
@@ -7126,7 +7586,7 @@ class AxiosHttpAdapter {
7126
7586
  }
7127
7587
  if (this.authStrategy) {
7128
7588
  const config = await this.authStrategy.determineAuthConfig(url, method);
7129
- log$1.debug(`Auth config for ${method} ${url}:`, config);
7589
+ log$2.debug(`Auth config for ${method} ${url}:`, config);
7130
7590
  return config.mode === 'mtls';
7131
7591
  }
7132
7592
  // Fallback: use mTLS for mf1/mf2 endpoints if no strategy
@@ -7143,10 +7603,10 @@ class AxiosHttpAdapter {
7143
7603
  };
7144
7604
  if (this.authToken) {
7145
7605
  headers['Authorization'] = `Bearer ${this.authToken}`;
7146
- log$1.debug('JWT token present for mTLS request');
7606
+ log$2.debug('JWT token present for mTLS request');
7147
7607
  }
7148
7608
  else {
7149
- log$1.warn('No JWT token for mTLS request');
7609
+ log$2.warn('No JWT token for mTLS request');
7150
7610
  }
7151
7611
  const mtlsConfig = {
7152
7612
  url: fullUrl,
@@ -7155,15 +7615,15 @@ class AxiosHttpAdapter {
7155
7615
  data,
7156
7616
  timeout: config?.timeout,
7157
7617
  };
7158
- log$1.debug(`mTLS ${method} ${fullUrl}`);
7618
+ log$2.debug(`mTLS ${method} ${fullUrl}`);
7159
7619
  if (data) {
7160
- log$1.debug('Request body:', data);
7620
+ log$2.debug('Request body:', data);
7161
7621
  }
7162
7622
  try {
7163
7623
  const response = await this.mtlsAdapter.request(mtlsConfig);
7164
- log$1.debug(`mTLS Response ${response.status} from ${fullUrl}`);
7624
+ log$2.debug(`mTLS Response ${response.status} from ${fullUrl}`);
7165
7625
  if (response.data) {
7166
- log$1.debug('Response body:', response.data);
7626
+ log$2.debug('Response body:', response.data);
7167
7627
  }
7168
7628
  return {
7169
7629
  data: response.data,
@@ -7172,11 +7632,11 @@ class AxiosHttpAdapter {
7172
7632
  };
7173
7633
  }
7174
7634
  catch (error) {
7175
- log$1.error(`mTLS Response error from ${fullUrl}:`, error);
7635
+ log$2.error(`mTLS Response error from ${fullUrl}:`, error);
7176
7636
  if (error && typeof error === 'object' && 'response' in error) {
7177
7637
  const axiosError = error;
7178
7638
  if (axiosError.response?.data) {
7179
- log$1.error('Response body:', axiosError.response.data);
7639
+ log$2.error('Response body:', axiosError.response.data);
7180
7640
  }
7181
7641
  }
7182
7642
  throw error;
@@ -7193,30 +7653,30 @@ class AxiosHttpAdapter {
7193
7653
  config.headers.Authorization = `Bearer ${this.authToken}`;
7194
7654
  }
7195
7655
  const method = config.method?.toUpperCase() ?? 'UNKNOWN';
7196
- log$1.debug(`→ ${method} ${config.url}`);
7656
+ log$2.debug(`→ ${method} ${config.url}`);
7197
7657
  if (config.params && Object.keys(config.params).length > 0) {
7198
- log$1.debug('Request params:', config.params);
7658
+ log$2.debug('Request params:', config.params);
7199
7659
  }
7200
7660
  if (config.data) {
7201
- log$1.debug('Request body:', config.data);
7661
+ log$2.debug('Request body:', config.data);
7202
7662
  }
7203
7663
  return config;
7204
7664
  }, (error) => {
7205
- log$1.error('Request error:', error);
7665
+ log$2.error('Request error:', error);
7206
7666
  return Promise.reject(error);
7207
7667
  });
7208
7668
  this.client.interceptors.response.use((response) => {
7209
7669
  const method = response.config.method?.toUpperCase() ?? 'UNKNOWN';
7210
- log$1.debug(`← ${method} ${response.status} ${response.config.url}`);
7670
+ log$2.debug(`← ${method} ${response.status} ${response.config.url}`);
7211
7671
  if (response.data) {
7212
- log$1.debug('Response body:', response.data);
7672
+ log$2.debug('Response body:', response.data);
7213
7673
  }
7214
7674
  return response;
7215
7675
  }, (error) => {
7216
7676
  const method = error.config?.method?.toUpperCase() ?? 'UNKNOWN';
7217
- log$1.error(`← ${method} ${error.response?.status ?? 'ERR'} ${error.config?.url ?? 'unknown'}`);
7677
+ log$2.error(`← ${method} ${error.response?.status ?? 'ERR'} ${error.config?.url ?? 'unknown'}`);
7218
7678
  if (error.response?.data) {
7219
- log$1.error('Response body:', error.response.data);
7679
+ log$2.error('Response body:', error.response.data);
7220
7680
  }
7221
7681
  return Promise.reject(error);
7222
7682
  });
@@ -7339,6 +7799,7 @@ class SDKFactory {
7339
7799
  baseUrl: config.baseUrl,
7340
7800
  timeout: config.timeout,
7341
7801
  });
7802
+ container.register(DI_TOKENS.BASE_HTTP_PORT, httpAdapter);
7342
7803
  container.register(DI_TOKENS.HTTP_PORT, httpAdapter);
7343
7804
  container.registerFactory(DI_TOKENS.RECEIPT_REPOSITORY, () => {
7344
7805
  const http = container.get(DI_TOKENS.HTTP_PORT);
@@ -7386,6 +7847,23 @@ class SDKFactory {
7386
7847
  });
7387
7848
  return container;
7388
7849
  }
7850
+ static registerCacheServices(container, cache, network) {
7851
+ container.register(DI_TOKENS.CACHE_PORT, cache);
7852
+ if (network) {
7853
+ container.register(DI_TOKENS.NETWORK_PORT, network);
7854
+ }
7855
+ const keyGenerator = new CacheKeyGenerator();
7856
+ container.register(DI_TOKENS.CACHE_KEY_GENERATOR, keyGenerator);
7857
+ const baseHttp = container.get(DI_TOKENS.BASE_HTTP_PORT);
7858
+ const cachingHttp = new CachingHttpDecorator(baseHttp, cache, keyGenerator, network);
7859
+ container.register(DI_TOKENS.HTTP_PORT, cachingHttp);
7860
+ }
7861
+ static getCacheKeyGenerator(container) {
7862
+ if (container.has(DI_TOKENS.CACHE_KEY_GENERATOR)) {
7863
+ return container.get(DI_TOKENS.CACHE_KEY_GENERATOR);
7864
+ }
7865
+ return undefined;
7866
+ }
7389
7867
  static registerAuthServices(container, secureStorage, config) {
7390
7868
  const tokenStorage = new TokenStorageAdapter(secureStorage);
7391
7869
  container.register(DI_TOKENS.TOKEN_STORAGE_PORT, tokenStorage);
@@ -7423,6 +7901,7 @@ class SDKFactory {
7423
7901
  }
7424
7902
  }
7425
7903
 
7904
+ const log$1 = createPrefixedLogger('SDK');
7426
7905
  class ACubeSDK {
7427
7906
  constructor(config, customAdapters, events = {}) {
7428
7907
  this.events = events;
@@ -7436,14 +7915,27 @@ class ACubeSDK {
7436
7915
  }
7437
7916
  async initialize() {
7438
7917
  if (this.isInitialized) {
7918
+ log$1.debug('SDK already initialized, skipping');
7439
7919
  return;
7440
7920
  }
7921
+ log$1.info('Initializing SDK', {
7922
+ apiUrl: this.config.getApiUrl(),
7923
+ authUrl: this.config.getAuthUrl(),
7924
+ debugEnabled: this.config.isDebugEnabled(),
7925
+ });
7441
7926
  try {
7442
7927
  if (!this.adapters) {
7928
+ log$1.debug('Loading platform adapters');
7443
7929
  const mtlsConfig = createACubeMTLSConfig(this.config.getApiUrl(), this.config.getTimeout(), true);
7444
7930
  this.adapters = loadPlatformAdapters({
7445
7931
  mtlsConfig,
7446
7932
  });
7933
+ log$1.info('Platform adapters loaded', {
7934
+ hasCache: !!this.adapters.cache,
7935
+ hasNetworkMonitor: !!this.adapters.networkMonitor,
7936
+ hasMtls: !!this.adapters.mtls,
7937
+ hasSecureStorage: !!this.adapters.secureStorage,
7938
+ });
7447
7939
  }
7448
7940
  const factoryConfig = {
7449
7941
  baseUrl: this.config.getApiUrl(),
@@ -7451,11 +7943,25 @@ class ACubeSDK {
7451
7943
  timeout: this.config.getTimeout(),
7452
7944
  debugEnabled: this.config.isDebugEnabled(),
7453
7945
  };
7946
+ log$1.debug('Creating DI container');
7454
7947
  this.container = SDKFactory.createContainer(factoryConfig);
7948
+ log$1.debug('Registering auth services');
7455
7949
  SDKFactory.registerAuthServices(this.container, this.adapters.secureStorage, factoryConfig);
7950
+ if (this.adapters.cache) {
7951
+ log$1.info('Registering cache services', {
7952
+ hasNetworkMonitor: !!this.adapters.networkMonitor,
7953
+ });
7954
+ SDKFactory.registerCacheServices(this.container, this.adapters.cache, this.adapters.networkMonitor);
7955
+ }
7956
+ else {
7957
+ log$1.debug('No cache adapter available, caching disabled');
7958
+ }
7959
+ log$1.debug('Initializing certificate service');
7456
7960
  this.certificateService = new CertificateService(this.adapters.secureStorage);
7457
7961
  const tokenStorage = this.container.get(DI_TOKENS.TOKEN_STORAGE_PORT);
7458
7962
  const httpPort = this.container.get(DI_TOKENS.HTTP_PORT);
7963
+ const baseHttpPort = this.container.get(DI_TOKENS.BASE_HTTP_PORT);
7964
+ log$1.debug('Initializing authentication service');
7459
7965
  this.authService = new AuthenticationService(httpPort, tokenStorage, {
7460
7966
  authUrl: this.config.getAuthUrl(),
7461
7967
  timeout: this.config.getTimeout(),
@@ -7465,6 +7971,7 @@ class ACubeSDK {
7465
7971
  this.events.onAuthError?.(new ACubeSDKError('AUTH_ERROR', error.message, error));
7466
7972
  },
7467
7973
  });
7974
+ log$1.debug('Initializing offline manager');
7468
7975
  const queueEvents = {
7469
7976
  onOperationAdded: (operation) => {
7470
7977
  this.events.onOfflineOperationAdded?.(operation.id);
@@ -7483,9 +7990,7 @@ class ACubeSDK {
7483
7990
  this.currentOnlineState = online;
7484
7991
  this.events.onNetworkStatusChanged?.(online);
7485
7992
  if (online && this.offlineManager) {
7486
- this.offlineManager.sync().catch(() => {
7487
- // Sync errors are handled internally by OfflineManager
7488
- });
7993
+ this.offlineManager.sync().catch(() => { });
7489
7994
  }
7490
7995
  });
7491
7996
  if (await this.authService.isAuthenticated()) {
@@ -7494,13 +7999,13 @@ class ACubeSDK {
7494
7999
  httpPort.setAuthToken(token);
7495
8000
  }
7496
8001
  }
7497
- // Connect mTLS adapter to HTTP port for /mf1 and /mf2 requests
7498
- if (this.adapters?.mtls && 'setMTLSAdapter' in httpPort) {
7499
- const httpWithMtls = httpPort;
8002
+ if (this.adapters?.mtls && 'setMTLSAdapter' in baseHttpPort) {
8003
+ log$1.debug('Connecting mTLS adapter to HTTP port');
8004
+ const httpWithMtls = baseHttpPort;
7500
8005
  httpWithMtls.setMTLSAdapter(this.adapters.mtls);
7501
8006
  }
7502
- // Create and connect AuthStrategy
7503
- if ('setAuthStrategy' in httpPort) {
8007
+ if ('setAuthStrategy' in baseHttpPort) {
8008
+ log$1.debug('Configuring auth strategy');
7504
8009
  const jwtHandler = new JwtAuthHandler(tokenStorage);
7505
8010
  const certificatePort = this.certificateService
7506
8011
  ? {
@@ -7531,7 +8036,7 @@ class ACubeSDK {
7531
8036
  },
7532
8037
  };
7533
8038
  const authStrategy = new AuthStrategy(jwtHandler, mtlsHandler, userProvider, this.adapters?.mtls || null);
7534
- const httpWithStrategy = httpPort;
8039
+ const httpWithStrategy = baseHttpPort;
7535
8040
  httpWithStrategy.setAuthStrategy(authStrategy);
7536
8041
  }
7537
8042
  if (this.adapters?.mtls && this.certificateService) {
@@ -7548,13 +8053,22 @@ class ACubeSDK {
7548
8053
  }
7549
8054
  }
7550
8055
  }
7551
- catch {
7552
- // Certificate auto-configuration failed, will retry on demand
8056
+ catch (certError) {
8057
+ log$1.warn('Certificate auto-configuration failed, will retry on demand', {
8058
+ error: certError instanceof Error ? certError.message : certError,
8059
+ });
7553
8060
  }
7554
8061
  }
7555
8062
  this.isInitialized = true;
8063
+ log$1.info('SDK initialized successfully', {
8064
+ hasCache: !!this.adapters.cache,
8065
+ hasMtls: !!this.adapters.mtls,
8066
+ });
7556
8067
  }
7557
8068
  catch (error) {
8069
+ log$1.error('SDK initialization failed', {
8070
+ error: error instanceof Error ? error.message : error,
8071
+ });
7558
8072
  throw new ACubeSDKError('SDK_INITIALIZATION_ERROR', `Failed to initialize SDK: ${error instanceof Error ? error.message : 'Unknown error'}`, error);
7559
8073
  }
7560
8074
  }
@@ -7608,15 +8122,19 @@ class ACubeSDK {
7608
8122
  }
7609
8123
  async login(credentials) {
7610
8124
  this.ensureInitialized();
8125
+ log$1.info('Login attempt', { email: credentials.email });
7611
8126
  const user = await this.authService.login(credentials);
8127
+ log$1.info('Login successful', { roles: user.roles });
7612
8128
  const token = await this.authService.getAccessToken();
7613
8129
  if (token) {
7614
8130
  this.httpPort.setAuthToken(token);
8131
+ log$1.debug('Auth token set on HTTP port');
7615
8132
  }
7616
8133
  return user;
7617
8134
  }
7618
8135
  async logout() {
7619
8136
  this.ensureInitialized();
8137
+ log$1.info('Logout');
7620
8138
  await this.authService.logout();
7621
8139
  this.httpPort.setAuthToken(null);
7622
8140
  }
@@ -7697,12 +8215,7 @@ class ACubeSDK {
7697
8215
  async clearCertificate() {
7698
8216
  this.ensureInitialized();
7699
8217
  if (this.adapters?.mtls) {
7700
- try {
7701
- await this.adapters.mtls.removeCertificate();
7702
- }
7703
- catch {
7704
- // No certificate to remove
7705
- }
8218
+ await this.adapters.mtls.removeCertificate().catch(() => { });
7706
8219
  }
7707
8220
  if (this.certificateService) {
7708
8221
  await this.certificateService.clearCertificate();
@@ -8037,17 +8550,16 @@ class NotificationService {
8037
8550
  }
8038
8551
 
8039
8552
  const DEFAULT_CONFIG = {
8040
- cacheKeyPrefix: 'acube_telemetry_',
8041
- cacheTtlMs: 300000,
8553
+ pollIntervalMs: 60000, // 1 minute default for telemetry
8042
8554
  };
8043
8555
  class TelemetryService {
8044
8556
  get state$() {
8045
8557
  return this.stateSubject.asObservable();
8046
8558
  }
8047
- constructor(repository, storagePort, networkPort, config) {
8559
+ constructor(repository, networkPort, config, events) {
8048
8560
  this.repository = repository;
8049
- this.storagePort = storagePort;
8050
8561
  this.networkPort = networkPort;
8562
+ this.events = events;
8051
8563
  this.stateSubject = new BehaviorSubject({
8052
8564
  data: null,
8053
8565
  isCached: false,
@@ -8055,29 +8567,69 @@ class TelemetryService {
8055
8567
  lastFetchedAt: null,
8056
8568
  });
8057
8569
  this.destroy$ = new Subject();
8058
- this.isOnline = true;
8059
8570
  this.config = { ...DEFAULT_CONFIG, ...config };
8060
8571
  this.setupNetworkMonitoring();
8061
8572
  }
8062
8573
  setupNetworkMonitoring() {
8063
- this.networkPort.online$.pipe(takeUntil(this.destroy$)).subscribe((online) => {
8064
- this.isOnline = online;
8574
+ this.networkSubscription = this.networkPort.online$
8575
+ .pipe(startWith(true), pairwise(), filter(([wasOnline, isNowOnline]) => !wasOnline && isNowOnline), takeUntil(this.destroy$))
8576
+ .subscribe(() => {
8577
+ this.triggerSync();
8065
8578
  });
8066
8579
  }
8580
+ startPolling(pemId) {
8581
+ if (this.pollingSubscription) {
8582
+ // If already polling for same pemId, do nothing
8583
+ if (this.currentPemId === pemId) {
8584
+ return;
8585
+ }
8586
+ // If polling for different pemId, stop and restart
8587
+ this.stopPolling();
8588
+ }
8589
+ this.currentPemId = pemId;
8590
+ this.pollingSubscription = interval(this.config.pollIntervalMs)
8591
+ .pipe(startWith(0), switchMap(() => this.fetchTelemetry()), takeUntil(this.destroy$))
8592
+ .subscribe();
8593
+ }
8594
+ stopPolling() {
8595
+ this.pollingSubscription?.unsubscribe();
8596
+ this.pollingSubscription = undefined;
8597
+ this.currentPemId = undefined;
8598
+ }
8599
+ async triggerSync() {
8600
+ if (!this.currentPemId) {
8601
+ return this.stateSubject.value;
8602
+ }
8603
+ return this.fetchTelemetry();
8604
+ }
8067
8605
  async getTelemetry(pemId) {
8068
- return this.fetchWithFallback(pemId);
8606
+ // Start polling if not already polling for this pemId
8607
+ if (this.currentPemId !== pemId) {
8608
+ this.startPolling(pemId);
8609
+ }
8610
+ return this.stateSubject.value;
8069
8611
  }
8070
8612
  async refreshTelemetry(pemId) {
8071
- if (!this.isOnline) {
8613
+ // Update pemId and fetch immediately
8614
+ if (this.currentPemId !== pemId) {
8615
+ this.startPolling(pemId);
8616
+ }
8617
+ else {
8618
+ return this.fetchTelemetry();
8619
+ }
8620
+ return this.stateSubject.value;
8621
+ }
8622
+ async fetchTelemetry() {
8623
+ if (!this.currentPemId) {
8072
8624
  return this.stateSubject.value;
8073
8625
  }
8074
8626
  this.stateSubject.next({
8075
8627
  ...this.stateSubject.value,
8076
8628
  isLoading: true,
8629
+ error: undefined,
8077
8630
  });
8078
8631
  try {
8079
- const data = await this.repository.getTelemetry(pemId);
8080
- await this.cacheData(pemId, data);
8632
+ const data = await this.repository.getTelemetry(this.currentPemId);
8081
8633
  const newState = {
8082
8634
  data,
8083
8635
  isCached: false,
@@ -8085,6 +8637,7 @@ class TelemetryService {
8085
8637
  lastFetchedAt: Date.now(),
8086
8638
  };
8087
8639
  this.stateSubject.next(newState);
8640
+ this.events?.onTelemetryUpdate?.(data);
8088
8641
  return newState;
8089
8642
  }
8090
8643
  catch (error) {
@@ -8095,89 +8648,25 @@ class TelemetryService {
8095
8648
  error: errorMessage,
8096
8649
  };
8097
8650
  this.stateSubject.next(newState);
8651
+ if (error instanceof Error) {
8652
+ this.events?.onSyncError?.(error);
8653
+ }
8098
8654
  return newState;
8099
8655
  }
8100
8656
  }
8101
- async fetchWithFallback(pemId) {
8657
+ clearTelemetry() {
8102
8658
  this.stateSubject.next({
8103
- ...this.stateSubject.value,
8104
- isLoading: true,
8105
- });
8106
- if (this.isOnline) {
8107
- try {
8108
- const data = await this.repository.getTelemetry(pemId);
8109
- await this.cacheData(pemId, data);
8110
- const newState = {
8111
- data,
8112
- isCached: false,
8113
- isLoading: false,
8114
- lastFetchedAt: Date.now(),
8115
- };
8116
- this.stateSubject.next(newState);
8117
- return newState;
8118
- }
8119
- catch (error) {
8120
- return this.loadFromCache(pemId, error);
8121
- }
8122
- }
8123
- return this.loadFromCache(pemId);
8124
- }
8125
- async loadFromCache(pemId, originalError) {
8126
- const cached = await this.getCachedData(pemId);
8127
- if (cached && this.isCacheValid(cached.timestamp)) {
8128
- const newState = {
8129
- data: cached.data,
8130
- isCached: true,
8131
- isLoading: false,
8132
- lastFetchedAt: cached.timestamp,
8133
- };
8134
- this.stateSubject.next(newState);
8135
- return newState;
8136
- }
8137
- const errorMessage = originalError instanceof Error ? originalError.message : 'No cached data available';
8138
- const newState = {
8139
8659
  data: null,
8140
8660
  isCached: false,
8141
8661
  isLoading: false,
8142
8662
  lastFetchedAt: null,
8143
- error: errorMessage,
8144
- };
8145
- this.stateSubject.next(newState);
8146
- return newState;
8147
- }
8148
- async cacheData(pemId, data) {
8149
- const cacheKey = this.getCacheKey(pemId);
8150
- const cached = {
8151
- data,
8152
- timestamp: Date.now(),
8153
- };
8154
- await this.storagePort.set(cacheKey, JSON.stringify(cached));
8155
- }
8156
- async getCachedData(pemId) {
8157
- const cacheKey = this.getCacheKey(pemId);
8158
- const stored = await this.storagePort.get(cacheKey);
8159
- if (!stored) {
8160
- return null;
8161
- }
8162
- try {
8163
- return JSON.parse(stored);
8164
- }
8165
- catch {
8166
- return null;
8167
- }
8168
- }
8169
- isCacheValid(timestamp) {
8170
- return Date.now() - timestamp < this.config.cacheTtlMs;
8171
- }
8172
- getCacheKey(pemId) {
8173
- return `${this.config.cacheKeyPrefix}${pemId}`;
8174
- }
8175
- clearCache(pemId) {
8176
- return this.storagePort.remove(this.getCacheKey(pemId));
8663
+ });
8177
8664
  }
8178
8665
  destroy() {
8179
8666
  this.destroy$.next();
8180
8667
  this.destroy$.complete();
8668
+ this.pollingSubscription?.unsubscribe();
8669
+ this.networkSubscription?.unsubscribe();
8181
8670
  }
8182
8671
  }
8183
8672
 
@@ -8187,7 +8676,7 @@ class TelemetryService {
8187
8676
  * Provides:
8188
8677
  * - Single initialization point
8189
8678
  * - Observable app state (NORMAL, WARNING, BLOCKED, OFFLINE)
8190
- * - Observable telemetry state
8679
+ * - Observable telemetry state with polling
8191
8680
  * - Simplified services for product use
8192
8681
  *
8193
8682
  * @example
@@ -8196,6 +8685,7 @@ class TelemetryService {
8196
8685
  * SDKManager.configure({
8197
8686
  * environment: 'sandbox',
8198
8687
  * notificationPollIntervalMs: 30000,
8688
+ * telemetryPollIntervalMs: 60000,
8199
8689
  * });
8200
8690
  *
8201
8691
  * // Initialize
@@ -8207,6 +8697,14 @@ class TelemetryService {
8207
8697
  * console.log('App mode:', state.mode);
8208
8698
  * });
8209
8699
  *
8700
+ * // Start telemetry polling for a specific PEM
8701
+ * manager.startTelemetryPolling('PEM-123');
8702
+ *
8703
+ * // Subscribe to telemetry updates
8704
+ * manager.telemetry$.subscribe(telemetry => {
8705
+ * console.log('Telemetry:', telemetry);
8706
+ * });
8707
+ *
8210
8708
  * // Cleanup
8211
8709
  * SDKManager.destroy();
8212
8710
  * ```
@@ -8262,43 +8760,34 @@ class SDKManager {
8262
8760
  * Must be called after configure()
8263
8761
  */
8264
8762
  async initialize() {
8265
- if (this.isInitialized) {
8763
+ if (this.isInitialized)
8266
8764
  return;
8267
- }
8268
- // Create and initialize SDK
8269
8765
  this.sdk = new ACubeSDK(this.config, this.adapters, this.events);
8270
8766
  await this.sdk.initialize();
8271
- // Get required adapters
8272
8767
  const adaptersRef = this.sdk.getAdapters();
8273
8768
  if (!adaptersRef) {
8274
8769
  throw new ACubeSDKError('ADAPTERS_NOT_AVAILABLE', 'Platform adapters not available');
8275
8770
  }
8276
8771
  const networkPort = adaptersRef.networkMonitor;
8277
- const storagePort = adaptersRef.storage;
8278
- // Get repositories from SDK
8279
8772
  const notificationRepo = this.sdk.notifications;
8280
8773
  const telemetryRepo = this.sdk.telemetry;
8281
- // Create NotificationService
8282
8774
  this.notificationService = new NotificationService(notificationRepo, networkPort, {
8283
8775
  pollIntervalMs: this.config.notificationPollIntervalMs ?? 30000,
8284
8776
  defaultPageSize: this.config.notificationPageSize ?? 30,
8285
8777
  });
8286
- // Create TelemetryService
8287
- this.telemetryService = new TelemetryService(telemetryRepo, storagePort, networkPort, {
8288
- cacheTtlMs: this.config.telemetryCacheTtlMs ?? 300000,
8778
+ this.telemetryService = new TelemetryService(telemetryRepo, networkPort, {
8779
+ pollIntervalMs: this.config.telemetryPollIntervalMs ?? 60000,
8289
8780
  });
8290
- // Create AppStateService
8291
8781
  this.appStateService = new AppStateService(this.notificationService.notifications$, networkPort);
8292
- // Subscribe to state changes for events
8293
8782
  if (this.events?.onAppStateChanged) {
8294
8783
  this.appStateService.state$.subscribe(this.events.onAppStateChanged);
8295
8784
  }
8296
8785
  if (this.events?.onTelemetryStateChanged) {
8297
8786
  this.telemetryService.state$.subscribe(this.events.onTelemetryStateChanged);
8298
8787
  }
8299
- // Start notification polling
8300
- this.notificationService.startPolling();
8301
8788
  this.isInitialized = true;
8789
+ this.notificationService.startPolling();
8790
+ this.startTelemetryPollingAuto();
8302
8791
  }
8303
8792
  /**
8304
8793
  * Observable stream of app state
@@ -8331,12 +8820,51 @@ class SDKManager {
8331
8820
  return this.appStateService.warning$;
8332
8821
  }
8333
8822
  /**
8334
- * Observable stream of telemetry state
8823
+ * Observable stream of telemetry state (data, isLoading, isCached, error)
8335
8824
  */
8336
8825
  get telemetryState$() {
8337
8826
  this.ensureInitialized();
8338
8827
  return this.telemetryService.state$;
8339
8828
  }
8829
+ /**
8830
+ * Get the pemId from the installed certificate
8831
+ */
8832
+ async getPemId() {
8833
+ this.ensureInitialized();
8834
+ try {
8835
+ const certInfo = await this.sdk.getCertificatesInfo();
8836
+ return certInfo?.pemId ?? null;
8837
+ }
8838
+ catch {
8839
+ return null;
8840
+ }
8841
+ }
8842
+ /**
8843
+ * Start polling telemetry using the pemId from installed certificate
8844
+ * Returns the pemId if successful, null if no certificate is installed
8845
+ */
8846
+ async startTelemetryPollingAuto() {
8847
+ this.ensureInitialized();
8848
+ const pemId = await this.getPemId();
8849
+ if (pemId) {
8850
+ this.telemetryService.startPolling(pemId);
8851
+ }
8852
+ return pemId;
8853
+ }
8854
+ /**
8855
+ * Start polling telemetry for a specific PEM
8856
+ */
8857
+ startTelemetryPolling(pemId) {
8858
+ this.ensureInitialized();
8859
+ this.telemetryService.startPolling(pemId);
8860
+ }
8861
+ /**
8862
+ * Stop telemetry polling
8863
+ */
8864
+ stopTelemetryPolling() {
8865
+ this.ensureInitialized();
8866
+ this.telemetryService.stopPolling();
8867
+ }
8340
8868
  /**
8341
8869
  * Get simplified services for product use
8342
8870
  */
@@ -8345,7 +8873,6 @@ class SDKManager {
8345
8873
  const sdk = this.sdk;
8346
8874
  const telemetryService = this.telemetryService;
8347
8875
  return {
8348
- // Business repositories
8349
8876
  receipts: sdk.receipts,
8350
8877
  merchants: sdk.merchants,
8351
8878
  cashiers: sdk.cashiers,
@@ -8355,22 +8882,23 @@ class SDKManager {
8355
8882
  pems: sdk.pems,
8356
8883
  dailyReports: sdk.dailyReports,
8357
8884
  journals: sdk.journals,
8358
- // Simplified telemetry operations
8359
8885
  telemetry: {
8886
+ startPollingAuto: () => this.startTelemetryPollingAuto(),
8887
+ startPolling: (pemId) => telemetryService.startPolling(pemId),
8888
+ stopPolling: () => telemetryService.stopPolling(),
8360
8889
  getTelemetry: (pemId) => telemetryService.getTelemetry(pemId),
8361
8890
  refreshTelemetry: (pemId) => telemetryService.refreshTelemetry(pemId),
8362
- clearCache: (pemId) => telemetryService.clearCache(pemId),
8891
+ triggerSync: () => telemetryService.triggerSync(),
8892
+ clearTelemetry: () => telemetryService.clearTelemetry(),
8893
+ getPemId: () => this.getPemId(),
8363
8894
  },
8364
- // Auth operations
8365
8895
  login: (credentials) => sdk.login(credentials),
8366
8896
  logout: () => sdk.logout(),
8367
8897
  getCurrentUser: () => sdk.getCurrentUser(),
8368
8898
  isAuthenticated: () => sdk.isAuthenticated(),
8369
- // Certificate operations
8370
8899
  storeCertificate: (certificate, privateKey, options) => sdk.storeCertificate(certificate, privateKey, options),
8371
8900
  hasCertificate: () => sdk.hasCertificate(),
8372
8901
  clearCertificate: () => sdk.clearCertificate(),
8373
- // Network status
8374
8902
  isOnline: () => sdk.isOnline(),
8375
8903
  };
8376
8904
  }
@@ -8382,12 +8910,11 @@ class SDKManager {
8382
8910
  await this.notificationService.triggerSync();
8383
8911
  }
8384
8912
  /**
8385
- * Get telemetry for a specific PEM
8913
+ * Manually trigger a telemetry sync
8386
8914
  */
8387
- async getTelemetry(pemId) {
8915
+ async syncTelemetry() {
8388
8916
  this.ensureInitialized();
8389
- const state = await this.telemetryService.getTelemetry(pemId);
8390
- return state.data;
8917
+ return this.telemetryService.triggerSync();
8391
8918
  }
8392
8919
  /**
8393
8920
  * Check if the manager is initialized