@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.esm.js CHANGED
@@ -2459,7 +2459,7 @@ function formatDecimal(value, decimals = 2) {
2459
2459
  return num.toFixed(decimals);
2460
2460
  }
2461
2461
 
2462
- const log$c = createPrefixedLogger('MTLS-HANDLER');
2462
+ const log$f = createPrefixedLogger('MTLS-HANDLER');
2463
2463
  class MtlsAuthHandler {
2464
2464
  constructor(mtlsAdapter, certificatePort) {
2465
2465
  this.mtlsAdapter = mtlsAdapter;
@@ -2501,7 +2501,7 @@ class MtlsAuthHandler {
2501
2501
  async makeRequest(url, config, jwtToken) {
2502
2502
  const requestKey = this.generateRequestKey(url, config, jwtToken);
2503
2503
  if (this.pendingRequests.has(requestKey)) {
2504
- log$c.debug('Deduplicating concurrent request:', url);
2504
+ log$f.debug('Deduplicating concurrent request:', url);
2505
2505
  return this.pendingRequests.get(requestKey);
2506
2506
  }
2507
2507
  const requestPromise = this.executeRequest(url, config, jwtToken, false);
@@ -2525,10 +2525,10 @@ class MtlsAuthHandler {
2525
2525
  };
2526
2526
  if (jwtToken) {
2527
2527
  headers['Authorization'] = `Bearer ${jwtToken}`;
2528
- log$c.debug('JWT token present:', jwtToken.substring(0, 20) + '...');
2528
+ log$f.debug('JWT token present:', jwtToken.substring(0, 20) + '...');
2529
2529
  }
2530
2530
  else {
2531
- log$c.warn('No JWT token provided for mTLS request');
2531
+ log$f.warn('No JWT token provided for mTLS request');
2532
2532
  }
2533
2533
  const fullUrl = this.constructMtlsUrl(url);
2534
2534
  const mtlsConfig = {
@@ -2539,25 +2539,25 @@ class MtlsAuthHandler {
2539
2539
  timeout: config.timeout,
2540
2540
  responseType: config.responseType,
2541
2541
  };
2542
- log$c.debug('header-mtls', headers);
2543
- log$c.debug(`${config.method} ${fullUrl}`);
2542
+ log$f.debug('header-mtls', headers);
2543
+ log$f.debug(`${config.method} ${fullUrl}`);
2544
2544
  if (config.data) {
2545
- log$c.debug('Request body:', config.data);
2545
+ log$f.debug('Request body:', config.data);
2546
2546
  }
2547
2547
  try {
2548
2548
  const response = await this.mtlsAdapter.request(mtlsConfig);
2549
- log$c.debug(`Response ${response.status} from ${fullUrl}`);
2549
+ log$f.debug(`Response ${response.status} from ${fullUrl}`);
2550
2550
  if (response.data) {
2551
- log$c.debug('Response body:', response.data);
2551
+ log$f.debug('Response body:', response.data);
2552
2552
  }
2553
2553
  return response.data;
2554
2554
  }
2555
2555
  catch (error) {
2556
- log$c.error(`Response error from ${fullUrl}:`, error);
2556
+ log$f.error(`Response error from ${fullUrl}:`, error);
2557
2557
  if (error && typeof error === 'object' && 'response' in error) {
2558
2558
  const axiosError = error;
2559
2559
  if (axiosError.response?.data) {
2560
- log$c.error('Response body:', axiosError.response.data);
2560
+ log$f.error('Response body:', axiosError.response.data);
2561
2561
  }
2562
2562
  }
2563
2563
  if (isRetryAttempt) {
@@ -2567,7 +2567,7 @@ class MtlsAuthHandler {
2567
2567
  if (!shouldRetry) {
2568
2568
  throw error;
2569
2569
  }
2570
- log$c.debug('Request failed, reconfiguring certificate and retrying...');
2570
+ log$f.debug('Request failed, reconfiguring certificate and retrying...');
2571
2571
  try {
2572
2572
  await this.configureCertificate(certificate);
2573
2573
  return await this.executeRequest(url, config, jwtToken, true);
@@ -3294,7 +3294,7 @@ function decompressData(data, compressed) {
3294
3294
  return new CompressionAdapter().decompress(data, compressed);
3295
3295
  }
3296
3296
 
3297
- const log$b = createPrefixedLogger('CACHE-RN');
3297
+ const log$e = createPrefixedLogger('CACHE-RN');
3298
3298
  /**
3299
3299
  * React Native cache adapter using SQLite (Expo or react-native-sqlite-storage)
3300
3300
  * Cache never expires - data persists until explicitly invalidated
@@ -3378,26 +3378,26 @@ class ReactNativeCacheAdapter {
3378
3378
  await this.runMigrations();
3379
3379
  }
3380
3380
  async runMigrations() {
3381
- log$b.debug('Running database migrations...');
3381
+ log$e.debug('Running database migrations...');
3382
3382
  try {
3383
3383
  // Check if compressed column exists
3384
3384
  this.hasCompressedColumn = await this.checkColumnExists('compressed');
3385
3385
  if (!this.hasCompressedColumn) {
3386
- log$b.debug('Adding compressed column to cache table');
3386
+ log$e.debug('Adding compressed column to cache table');
3387
3387
  const addColumnSQL = `ALTER TABLE ${ReactNativeCacheAdapter.TABLE_NAME} ADD COLUMN compressed INTEGER DEFAULT 0`;
3388
3388
  await this.executeSql(addColumnSQL);
3389
3389
  this.hasCompressedColumn = true;
3390
- log$b.debug('Successfully added compressed column');
3390
+ log$e.debug('Successfully added compressed column');
3391
3391
  }
3392
3392
  else {
3393
- log$b.debug('Compressed column already exists');
3393
+ log$e.debug('Compressed column already exists');
3394
3394
  }
3395
- log$b.debug('Database migrations completed', {
3395
+ log$e.debug('Database migrations completed', {
3396
3396
  hasCompressedColumn: this.hasCompressedColumn,
3397
3397
  });
3398
3398
  }
3399
3399
  catch (error) {
3400
- log$b.debug('Migration failed, disabling compression features', error);
3400
+ log$e.debug('Migration failed, disabling compression features', error);
3401
3401
  this.hasCompressedColumn = false;
3402
3402
  // Don't throw - allow the app to continue even if migration fails
3403
3403
  // The compressed feature will just be disabled
@@ -3408,20 +3408,20 @@ class ReactNativeCacheAdapter {
3408
3408
  const pragmaSQL = `PRAGMA table_info(${ReactNativeCacheAdapter.TABLE_NAME})`;
3409
3409
  const results = await this.executeSql(pragmaSQL);
3410
3410
  const columns = this.normalizeResults(results);
3411
- log$b.debug('Table columns found', { columns: columns.map((c) => c.name) });
3411
+ log$e.debug('Table columns found', { columns: columns.map((c) => c.name) });
3412
3412
  return columns.some((column) => column.name === columnName);
3413
3413
  }
3414
3414
  catch (error) {
3415
- log$b.debug('Error checking column existence', error);
3415
+ log$e.debug('Error checking column existence', error);
3416
3416
  return false;
3417
3417
  }
3418
3418
  }
3419
3419
  async get(key) {
3420
3420
  await this.ensureInitialized();
3421
3421
  const sql = `SELECT * FROM ${ReactNativeCacheAdapter.TABLE_NAME} WHERE cache_key = ?`;
3422
- log$b.debug('Executing get query', { sql, key });
3422
+ log$e.debug('Executing get query', { sql, key });
3423
3423
  const results = await this.executeSql(sql, [key]);
3424
- log$b.debug('Get query results', { key, hasResults: !!results });
3424
+ log$e.debug('Get query results', { key, hasResults: !!results });
3425
3425
  // Normalize results from different SQLite implementations
3426
3426
  const rows = this.normalizeResults(results);
3427
3427
  if (!rows || rows.length === 0) {
@@ -3444,7 +3444,7 @@ class ReactNativeCacheAdapter {
3444
3444
  data,
3445
3445
  timestamp: Date.now(),
3446
3446
  };
3447
- log$b.debug('Setting cache item', { key });
3447
+ log$e.debug('Setting cache item', { key });
3448
3448
  return this.setItem(key, item);
3449
3449
  }
3450
3450
  async setItem(key, item) {
@@ -3457,7 +3457,7 @@ class ReactNativeCacheAdapter {
3457
3457
  const compressionResult = compressData(serializedData, this.options.compressionThreshold);
3458
3458
  finalData = compressionResult.data;
3459
3459
  isCompressed = compressionResult.compressed;
3460
- log$b.debug('Compression result', {
3460
+ log$e.debug('Compression result', {
3461
3461
  key,
3462
3462
  originalSize: compressionResult.originalSize,
3463
3463
  compressedSize: compressionResult.compressedSize,
@@ -3465,7 +3465,7 @@ class ReactNativeCacheAdapter {
3465
3465
  savings: compressionResult.originalSize - compressionResult.compressedSize,
3466
3466
  });
3467
3467
  }
3468
- log$b.debug('Setting item with metadata', {
3468
+ log$e.debug('Setting item with metadata', {
3469
3469
  key,
3470
3470
  timestamp: item.timestamp,
3471
3471
  compressed: isCompressed,
@@ -3491,14 +3491,14 @@ class ReactNativeCacheAdapter {
3491
3491
  `;
3492
3492
  params = [key, finalData, item.timestamp];
3493
3493
  }
3494
- log$b.debug('Executing setItem SQL', { key, paramsCount: params.length });
3494
+ log$e.debug('Executing setItem SQL', { key, paramsCount: params.length });
3495
3495
  await this.executeSql(sql, params);
3496
3496
  }
3497
3497
  async setBatch(items) {
3498
3498
  if (items.length === 0)
3499
3499
  return;
3500
3500
  await this.ensureInitialized();
3501
- log$b.debug('Batch setting items', { count: items.length });
3501
+ log$e.debug('Batch setting items', { count: items.length });
3502
3502
  if (this.isExpo) {
3503
3503
  await this.db.withTransactionAsync(async () => {
3504
3504
  for (const [key, item] of items) {
@@ -3516,7 +3516,7 @@ class ReactNativeCacheAdapter {
3516
3516
  }, reject, () => resolve());
3517
3517
  });
3518
3518
  }
3519
- log$b.debug('Batch operation completed', { count: items.length });
3519
+ log$e.debug('Batch operation completed', { count: items.length });
3520
3520
  }
3521
3521
  async setBatchItem(key, item) {
3522
3522
  // Handle compression if enabled and compressed column is available
@@ -3690,10 +3690,10 @@ class MemoryCacheAdapter {
3690
3690
  return keySize + itemSize;
3691
3691
  }
3692
3692
  async get(key) {
3693
- log$b.debug('Getting cache item', { key });
3693
+ log$e.debug('Getting cache item', { key });
3694
3694
  const item = this.cache.get(key);
3695
3695
  if (!item) {
3696
- log$b.debug('Cache miss', { key });
3696
+ log$e.debug('Cache miss', { key });
3697
3697
  return null;
3698
3698
  }
3699
3699
  // Handle decompression if needed
@@ -3703,7 +3703,7 @@ class MemoryCacheAdapter {
3703
3703
  const decompressed = decompressData(item.data, true);
3704
3704
  finalData = JSON.parse(decompressed.data);
3705
3705
  }
3706
- log$b.debug('Cache hit', { key, compressed: isCompressed });
3706
+ log$e.debug('Cache hit', { key, compressed: isCompressed });
3707
3707
  return {
3708
3708
  ...item,
3709
3709
  data: finalData,
@@ -3711,7 +3711,7 @@ class MemoryCacheAdapter {
3711
3711
  };
3712
3712
  }
3713
3713
  async set(key, data) {
3714
- log$b.debug('Setting cache item', { key });
3714
+ log$e.debug('Setting cache item', { key });
3715
3715
  // Handle compression if enabled
3716
3716
  let finalData = data;
3717
3717
  let isCompressed = false;
@@ -3721,7 +3721,7 @@ class MemoryCacheAdapter {
3721
3721
  if (compressionResult.compressed) {
3722
3722
  finalData = compressionResult.data;
3723
3723
  isCompressed = true;
3724
- log$b.debug('Compression result', {
3724
+ log$e.debug('Compression result', {
3725
3725
  key,
3726
3726
  originalSize: compressionResult.originalSize,
3727
3727
  compressedSize: compressionResult.compressedSize,
@@ -3753,13 +3753,13 @@ class MemoryCacheAdapter {
3753
3753
  const oldestItemSize = this.calculateItemSize(oldestKey, oldestItem);
3754
3754
  this.totalBytes -= oldestItemSize;
3755
3755
  this.cache.delete(oldestKey);
3756
- log$b.debug('Removed oldest item for capacity', { oldestKey, freedBytes: oldestItemSize });
3756
+ log$e.debug('Removed oldest item for capacity', { oldestKey, freedBytes: oldestItemSize });
3757
3757
  }
3758
3758
  }
3759
3759
  // Set new item and update total size
3760
3760
  this.cache.set(key, item);
3761
3761
  this.totalBytes += newItemSize;
3762
- log$b.debug('Updated cache size', {
3762
+ log$e.debug('Updated cache size', {
3763
3763
  entries: this.cache.size,
3764
3764
  totalBytes: this.totalBytes,
3765
3765
  newItemSize,
@@ -3768,7 +3768,7 @@ class MemoryCacheAdapter {
3768
3768
  async setBatch(items) {
3769
3769
  if (items.length === 0)
3770
3770
  return;
3771
- log$b.debug('Batch setting items', { count: items.length });
3771
+ log$e.debug('Batch setting items', { count: items.length });
3772
3772
  let totalNewBytes = 0;
3773
3773
  let totalOldBytes = 0;
3774
3774
  const itemsToRemove = [];
@@ -3797,7 +3797,7 @@ class MemoryCacheAdapter {
3797
3797
  itemsToRemove.push(oldKey);
3798
3798
  }
3799
3799
  if (itemsToRemove.length > 0) {
3800
- log$b.debug('Removed items for batch capacity', {
3800
+ log$e.debug('Removed items for batch capacity', {
3801
3801
  removedCount: itemsToRemove.length,
3802
3802
  removedKeys: itemsToRemove,
3803
3803
  });
@@ -3809,7 +3809,7 @@ class MemoryCacheAdapter {
3809
3809
  for (const [key, item] of items) {
3810
3810
  this.cache.set(key, item);
3811
3811
  }
3812
- log$b.debug('Batch operation completed', {
3812
+ log$e.debug('Batch operation completed', {
3813
3813
  count: items.length,
3814
3814
  totalBytes: this.totalBytes,
3815
3815
  entries: this.cache.size,
@@ -3831,7 +3831,7 @@ class MemoryCacheAdapter {
3831
3831
  }
3832
3832
  }
3833
3833
  if (removed > 0) {
3834
- log$b.debug('Invalidation completed', {
3834
+ log$e.debug('Invalidation completed', {
3835
3835
  pattern,
3836
3836
  entriesRemoved: removed,
3837
3837
  bytesFreed,
@@ -3843,7 +3843,7 @@ class MemoryCacheAdapter {
3843
3843
  async clear() {
3844
3844
  this.cache.clear();
3845
3845
  this.totalBytes = 0;
3846
- log$b.debug('Cache cleared', { entries: 0, bytes: 0 });
3846
+ log$e.debug('Cache cleared', { entries: 0, bytes: 0 });
3847
3847
  }
3848
3848
  async getSize() {
3849
3849
  return {
@@ -4174,7 +4174,7 @@ replaceTraps((oldTraps) => ({
4174
4174
  },
4175
4175
  }));
4176
4176
 
4177
- const log$a = createPrefixedLogger('CACHE-WEB');
4177
+ const log$d = createPrefixedLogger('CACHE-WEB');
4178
4178
  /**
4179
4179
  * Web cache adapter using IndexedDB with automatic error recovery
4180
4180
  * Cache never expires - data persists until explicitly invalidated
@@ -4197,18 +4197,18 @@ class WebCacheAdapter {
4197
4197
  async initialize() {
4198
4198
  if (this.db)
4199
4199
  return;
4200
- log$a.debug('Initializing IndexedDB cache', {
4200
+ log$d.debug('Initializing IndexedDB cache', {
4201
4201
  dbName: WebCacheAdapter.DB_NAME,
4202
4202
  version: WebCacheAdapter.DB_VERSION,
4203
4203
  });
4204
4204
  try {
4205
4205
  this.db = await this.openDatabase();
4206
- log$a.debug('IndexedDB cache initialized successfully');
4206
+ log$d.debug('IndexedDB cache initialized successfully');
4207
4207
  this.retryCount = 0; // Reset retry count on success
4208
4208
  }
4209
4209
  catch (error) {
4210
4210
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
4211
- log$a.debug('Failed to initialize IndexedDB', { error: errorMessage });
4211
+ log$d.debug('Failed to initialize IndexedDB', { error: errorMessage });
4212
4212
  // Check if this is a version conflict error
4213
4213
  if (this.isVersionConflictError(errorMessage)) {
4214
4214
  await this.handleVersionConflict();
@@ -4221,32 +4221,32 @@ class WebCacheAdapter {
4221
4221
  async openDatabase() {
4222
4222
  return await openDB(WebCacheAdapter.DB_NAME, WebCacheAdapter.DB_VERSION, {
4223
4223
  upgrade: (db, oldVersion, newVersion, transaction) => {
4224
- log$a.debug('Database upgrade needed', { oldVersion, newVersion });
4224
+ log$d.debug('Database upgrade needed', { oldVersion, newVersion });
4225
4225
  this.handleUpgrade(db, oldVersion, newVersion, transaction);
4226
4226
  },
4227
4227
  blocked: () => {
4228
- log$a.debug('Database blocked - another tab may be open');
4228
+ log$d.debug('Database blocked - another tab may be open');
4229
4229
  },
4230
4230
  blocking: () => {
4231
- log$a.debug('Database blocking - will close connection');
4231
+ log$d.debug('Database blocking - will close connection');
4232
4232
  if (this.db) {
4233
4233
  this.db.close();
4234
4234
  this.db = null;
4235
4235
  }
4236
4236
  },
4237
4237
  terminated: () => {
4238
- log$a.debug('Database connection terminated unexpectedly');
4238
+ log$d.debug('Database connection terminated unexpectedly');
4239
4239
  this.db = null;
4240
4240
  },
4241
4241
  });
4242
4242
  }
4243
4243
  handleUpgrade(db, oldVersion, newVersion, transaction) {
4244
- log$a.debug('Handling database upgrade', { oldVersion, newVersion });
4244
+ log$d.debug('Handling database upgrade', { oldVersion, newVersion });
4245
4245
  // Create cache store if it doesn't exist (initial setup)
4246
4246
  if (!db.objectStoreNames.contains(WebCacheAdapter.STORE_NAME)) {
4247
4247
  const store = db.createObjectStore(WebCacheAdapter.STORE_NAME, { keyPath: 'key' });
4248
4248
  store.createIndex('timestamp', 'timestamp', { unique: false });
4249
- log$a.debug('Created cache store and timestamp index');
4249
+ log$d.debug('Created cache store and timestamp index');
4250
4250
  }
4251
4251
  // Handle migration from version 1 to 2
4252
4252
  if (oldVersion < 2) {
@@ -4257,16 +4257,16 @@ class WebCacheAdapter {
4257
4257
  try {
4258
4258
  if (store.indexNames.contains(indexName)) {
4259
4259
  store.deleteIndex(indexName);
4260
- log$a.debug(`Removed unused index: ${indexName}`);
4260
+ log$d.debug(`Removed unused index: ${indexName}`);
4261
4261
  }
4262
4262
  }
4263
4263
  catch (error) {
4264
4264
  // Ignore errors if indexes don't exist
4265
- log$a.debug(`Warning: Could not remove index ${indexName}`, error);
4265
+ log$d.debug(`Warning: Could not remove index ${indexName}`, error);
4266
4266
  }
4267
4267
  });
4268
4268
  }
4269
- log$a.debug('Database upgrade completed');
4269
+ log$d.debug('Database upgrade completed');
4270
4270
  }
4271
4271
  isVersionConflictError(errorMessage) {
4272
4272
  return (errorMessage.includes('less than the existing version') ||
@@ -4274,7 +4274,7 @@ class WebCacheAdapter {
4274
4274
  errorMessage.includes('VersionError'));
4275
4275
  }
4276
4276
  async handleVersionConflict() {
4277
- log$a.debug('Handling version conflict, attempting recovery...');
4277
+ log$d.debug('Handling version conflict, attempting recovery...');
4278
4278
  if (this.retryCount >= this.maxRetries) {
4279
4279
  throw new Error('Failed to resolve IndexedDB version conflict after multiple attempts');
4280
4280
  }
@@ -4286,19 +4286,19 @@ class WebCacheAdapter {
4286
4286
  this.db = null;
4287
4287
  }
4288
4288
  // Delete the problematic database
4289
- log$a.debug('Deleting problematic database to resolve version conflict');
4289
+ log$d.debug('Deleting problematic database to resolve version conflict');
4290
4290
  await deleteDB(WebCacheAdapter.DB_NAME);
4291
4291
  // Wait a bit for the deletion to complete
4292
4292
  await new Promise((resolve) => setTimeout(resolve, 200));
4293
4293
  // Try to open the database again
4294
- log$a.debug(`Retrying database initialization (attempt ${this.retryCount}/${this.maxRetries})`);
4294
+ log$d.debug(`Retrying database initialization (attempt ${this.retryCount}/${this.maxRetries})`);
4295
4295
  this.db = await this.openDatabase();
4296
- log$a.debug('Successfully recovered from version conflict');
4296
+ log$d.debug('Successfully recovered from version conflict');
4297
4297
  this.retryCount = 0; // Reset retry count on success
4298
4298
  }
4299
4299
  catch (retryError) {
4300
4300
  const retryErrorMessage = retryError instanceof Error ? retryError.message : 'Unknown error';
4301
- log$a.debug('Recovery attempt failed', { attempt: this.retryCount, error: retryErrorMessage });
4301
+ log$d.debug('Recovery attempt failed', { attempt: this.retryCount, error: retryErrorMessage });
4302
4302
  if (this.retryCount < this.maxRetries) {
4303
4303
  // Try again
4304
4304
  await this.handleVersionConflict();
@@ -4310,7 +4310,7 @@ class WebCacheAdapter {
4310
4310
  }
4311
4311
  async get(key) {
4312
4312
  await this.ensureInitialized();
4313
- log$a.debug('Getting cache item', { key });
4313
+ log$d.debug('Getting cache item', { key });
4314
4314
  try {
4315
4315
  const transaction = this.db.transaction([WebCacheAdapter.STORE_NAME], 'readonly');
4316
4316
  const store = transaction.objectStore(WebCacheAdapter.STORE_NAME);
@@ -4336,7 +4336,7 @@ class WebCacheAdapter {
4336
4336
  };
4337
4337
  }
4338
4338
  catch (error) {
4339
- log$a.debug('Error getting cache item', { key, error });
4339
+ log$d.debug('Error getting cache item', { key, error });
4340
4340
  return null; // Return null on error instead of throwing
4341
4341
  }
4342
4342
  }
@@ -4358,7 +4358,7 @@ class WebCacheAdapter {
4358
4358
  if (compressionResult.compressed) {
4359
4359
  finalData = compressionResult.data;
4360
4360
  isCompressed = true;
4361
- log$a.debug('Compression result', {
4361
+ log$d.debug('Compression result', {
4362
4362
  key,
4363
4363
  originalSize: compressionResult.originalSize,
4364
4364
  compressedSize: compressionResult.compressedSize,
@@ -4367,7 +4367,7 @@ class WebCacheAdapter {
4367
4367
  });
4368
4368
  }
4369
4369
  }
4370
- log$a.debug('Setting cache item', { key, timestamp: item.timestamp, compressed: isCompressed });
4370
+ log$d.debug('Setting cache item', { key, timestamp: item.timestamp, compressed: isCompressed });
4371
4371
  const storedItem = {
4372
4372
  key,
4373
4373
  data: finalData,
@@ -4380,7 +4380,7 @@ class WebCacheAdapter {
4380
4380
  await store.put(storedItem);
4381
4381
  }
4382
4382
  catch (error) {
4383
- log$a.debug('Error setting cache item', { key, error });
4383
+ log$d.debug('Error setting cache item', { key, error });
4384
4384
  // Silently fail for cache writes
4385
4385
  }
4386
4386
  }
@@ -4388,7 +4388,7 @@ class WebCacheAdapter {
4388
4388
  if (items.length === 0)
4389
4389
  return;
4390
4390
  await this.ensureInitialized();
4391
- log$a.debug('Batch setting items', { count: items.length });
4391
+ log$d.debug('Batch setting items', { count: items.length });
4392
4392
  try {
4393
4393
  const transaction = this.db.transaction([WebCacheAdapter.STORE_NAME], 'readwrite');
4394
4394
  const store = transaction.objectStore(WebCacheAdapter.STORE_NAME);
@@ -4398,10 +4398,10 @@ class WebCacheAdapter {
4398
4398
  return store.put(storedItem);
4399
4399
  });
4400
4400
  await Promise.all(promises);
4401
- log$a.debug('Batch operation completed', { count: items.length });
4401
+ log$d.debug('Batch operation completed', { count: items.length });
4402
4402
  }
4403
4403
  catch (error) {
4404
- log$a.debug('Error in batch operation', { count: items.length, error });
4404
+ log$d.debug('Error in batch operation', { count: items.length, error });
4405
4405
  // Silently fail for batch writes
4406
4406
  }
4407
4407
  }
@@ -4436,10 +4436,10 @@ class WebCacheAdapter {
4436
4436
  const transaction = this.db.transaction([WebCacheAdapter.STORE_NAME], 'readwrite');
4437
4437
  const store = transaction.objectStore(WebCacheAdapter.STORE_NAME);
4438
4438
  await store.clear();
4439
- log$a.debug('Cache cleared successfully');
4439
+ log$d.debug('Cache cleared successfully');
4440
4440
  }
4441
4441
  catch (error) {
4442
- log$a.debug('Error clearing cache', error);
4442
+ log$d.debug('Error clearing cache', error);
4443
4443
  // Silently fail for cache clear
4444
4444
  }
4445
4445
  }
@@ -4465,7 +4465,7 @@ class WebCacheAdapter {
4465
4465
  };
4466
4466
  }
4467
4467
  catch (error) {
4468
- log$a.debug('Error getting cache size', error);
4468
+ log$d.debug('Error getting cache size', error);
4469
4469
  return {
4470
4470
  entries: 0,
4471
4471
  bytes: 0,
@@ -4490,7 +4490,7 @@ class WebCacheAdapter {
4490
4490
  return allKeys.filter((key) => regex.test(key));
4491
4491
  }
4492
4492
  catch (error) {
4493
- log$a.debug('Error getting cache keys', error);
4493
+ log$d.debug('Error getting cache keys', error);
4494
4494
  return [];
4495
4495
  }
4496
4496
  }
@@ -4503,7 +4503,7 @@ class WebCacheAdapter {
4503
4503
  return true;
4504
4504
  }
4505
4505
  catch (error) {
4506
- log$a.debug('Error deleting cache item', { key, error });
4506
+ log$d.debug('Error deleting cache item', { key, error });
4507
4507
  return false;
4508
4508
  }
4509
4509
  }
@@ -4515,7 +4515,7 @@ class WebCacheAdapter {
4515
4515
  await this.initPromise;
4516
4516
  }
4517
4517
  catch (error) {
4518
- log$a.debug('Failed to ensure initialization', error);
4518
+ log$d.debug('Failed to ensure initialization', error);
4519
4519
  // Reset and try once more
4520
4520
  this.initPromise = null;
4521
4521
  this.db = null;
@@ -4534,7 +4534,7 @@ WebCacheAdapter.DB_NAME = 'acube_cache';
4534
4534
  WebCacheAdapter.DB_VERSION = 2;
4535
4535
  WebCacheAdapter.STORE_NAME = 'cache_entries';
4536
4536
 
4537
- const log$9 = createPrefixedLogger('CACHE-LOADER');
4537
+ const log$c = createPrefixedLogger('CACHE-LOADER');
4538
4538
  function loadCacheAdapter(platform) {
4539
4539
  try {
4540
4540
  switch (platform) {
@@ -4566,7 +4566,7 @@ function loadCacheAdapter(platform) {
4566
4566
  }
4567
4567
  }
4568
4568
  catch (error) {
4569
- log$9.warn(`Cache adapter not available for platform ${platform}:`, error);
4569
+ log$c.warn(`Cache adapter not available for platform ${platform}:`, error);
4570
4570
  return undefined;
4571
4571
  }
4572
4572
  }
@@ -4623,7 +4623,7 @@ class BaseSecureStorageAdapter {
4623
4623
  }
4624
4624
  }
4625
4625
 
4626
- const log$8 = createPrefixedLogger('NETWORK-BASE');
4626
+ const log$b = createPrefixedLogger('NETWORK-BASE');
4627
4627
  class NetworkBase {
4628
4628
  constructor(initialOnline = true, debounceMs = 300) {
4629
4629
  this.destroy$ = new Subject();
@@ -4643,14 +4643,14 @@ class NetworkBase {
4643
4643
  const current = this.statusSubject.getValue();
4644
4644
  if (current.online !== online) {
4645
4645
  this.statusSubject.next({ online, timestamp: Date.now() });
4646
- log$8.debug(`Network status changed: ${online ? 'online' : 'offline'}`);
4646
+ log$b.debug(`Network status changed: ${online ? 'online' : 'offline'}`);
4647
4647
  }
4648
4648
  }
4649
4649
  destroy() {
4650
4650
  this.destroy$.next();
4651
4651
  this.destroy$.complete();
4652
4652
  this.statusSubject.complete();
4653
- log$8.debug('Network monitor destroyed');
4653
+ log$b.debug('Network monitor destroyed');
4654
4654
  }
4655
4655
  }
4656
4656
 
@@ -4710,7 +4710,7 @@ class NodeSecureStorageAdapter extends BaseSecureStorageAdapter {
4710
4710
  }
4711
4711
  }
4712
4712
 
4713
- const log$7 = createPrefixedLogger('RN-STORAGE');
4713
+ const log$a = createPrefixedLogger('RN-STORAGE');
4714
4714
  /**
4715
4715
  * React Native storage adapter using AsyncStorage
4716
4716
  * Note: Uses native batch operations for better performance (not base class)
@@ -4742,7 +4742,7 @@ class ReactNativeStorageAdapter {
4742
4742
  return await this.AsyncStorage.getItem(key);
4743
4743
  }
4744
4744
  catch (error) {
4745
- log$7.error('Failed to get item from AsyncStorage:', error);
4745
+ log$a.error('Failed to get item from AsyncStorage:', error);
4746
4746
  return null;
4747
4747
  }
4748
4748
  }
@@ -4783,7 +4783,7 @@ class ReactNativeStorageAdapter {
4783
4783
  return await this.AsyncStorage.getAllKeys();
4784
4784
  }
4785
4785
  catch (error) {
4786
- log$7.error('Failed to get all keys:', error);
4786
+ log$a.error('Failed to get all keys:', error);
4787
4787
  return [];
4788
4788
  }
4789
4789
  }
@@ -4800,7 +4800,7 @@ class ReactNativeStorageAdapter {
4800
4800
  return result;
4801
4801
  }
4802
4802
  catch (error) {
4803
- log$7.error('Failed to get multiple items:', error);
4803
+ log$a.error('Failed to get multiple items:', error);
4804
4804
  const result = {};
4805
4805
  keys.forEach((key) => {
4806
4806
  result[key] = null;
@@ -4850,7 +4850,7 @@ class ReactNativeSecureStorageAdapter extends BaseSecureStorageAdapter {
4850
4850
  return;
4851
4851
  }
4852
4852
  catch {
4853
- log$7.debug('expo-secure-store not available, trying react-native-keychain');
4853
+ log$a.debug('expo-secure-store not available, trying react-native-keychain');
4854
4854
  }
4855
4855
  try {
4856
4856
  const Keychain = require('react-native-keychain');
@@ -4859,7 +4859,7 @@ class ReactNativeSecureStorageAdapter extends BaseSecureStorageAdapter {
4859
4859
  return;
4860
4860
  }
4861
4861
  catch {
4862
- log$7.error('react-native-keychain not available');
4862
+ log$a.error('react-native-keychain not available');
4863
4863
  }
4864
4864
  throw new Error('No secure storage available. Please install expo-secure-store or react-native-keychain');
4865
4865
  }
@@ -4877,7 +4877,7 @@ class ReactNativeSecureStorageAdapter extends BaseSecureStorageAdapter {
4877
4877
  }
4878
4878
  }
4879
4879
  catch (error) {
4880
- log$7.error('Failed to get secure item:', error);
4880
+ log$a.error('Failed to get secure item:', error);
4881
4881
  }
4882
4882
  return null;
4883
4883
  }
@@ -4914,10 +4914,10 @@ class ReactNativeSecureStorageAdapter extends BaseSecureStorageAdapter {
4914
4914
  }
4915
4915
  }
4916
4916
  async clear() {
4917
- log$7.warn('Clear all secure items not fully implemented for React Native');
4917
+ log$a.warn('Clear all secure items not fully implemented for React Native');
4918
4918
  }
4919
4919
  async getAllKeys() {
4920
- log$7.warn('Get all secure keys not implemented for React Native');
4920
+ log$a.warn('Get all secure keys not implemented for React Native');
4921
4921
  return [];
4922
4922
  }
4923
4923
  async isAvailable() {
@@ -5135,7 +5135,7 @@ class NodeNetworkMonitor extends NetworkBase {
5135
5135
  }
5136
5136
  }
5137
5137
 
5138
- const log$6 = createPrefixedLogger('RN-NETWORK');
5138
+ const log$9 = createPrefixedLogger('RN-NETWORK');
5139
5139
  /**
5140
5140
  * React Native network monitor using RxJS
5141
5141
  * Supports both @react-native-community/netinfo and expo-network
@@ -5148,7 +5148,7 @@ class ReactNativeNetworkMonitor extends NetworkBase {
5148
5148
  this.moduleReady$ = new Subject();
5149
5149
  this.isExpo = detectPlatform().isExpo;
5150
5150
  this.init().catch((error) => {
5151
- log$6.error('Network monitor initialization failed:', error);
5151
+ log$9.error('Network monitor initialization failed:', error);
5152
5152
  });
5153
5153
  }
5154
5154
  async init() {
@@ -5167,10 +5167,10 @@ class ReactNativeNetworkMonitor extends NetworkBase {
5167
5167
  try {
5168
5168
  const module = require('@react-native-community/netinfo');
5169
5169
  this.netInfoModule = module.default || module;
5170
- log$6.debug('Loaded @react-native-community/netinfo module');
5170
+ log$9.debug('Loaded @react-native-community/netinfo module');
5171
5171
  }
5172
5172
  catch (error) {
5173
- log$6.error('Failed to load React Native NetInfo module:', error);
5173
+ log$9.error('Failed to load React Native NetInfo module:', error);
5174
5174
  this.netInfoModule = null;
5175
5175
  }
5176
5176
  }
@@ -5178,10 +5178,10 @@ class ReactNativeNetworkMonitor extends NetworkBase {
5178
5178
  try {
5179
5179
  const module = require('expo-network');
5180
5180
  this.netInfoModule = module.default || module;
5181
- log$6.debug('Loaded expo-network module');
5181
+ log$9.debug('Loaded expo-network module');
5182
5182
  }
5183
5183
  catch (error) {
5184
- log$6.error('Failed to load Expo Network module:', error);
5184
+ log$9.error('Failed to load Expo Network module:', error);
5185
5185
  this.netInfoModule = null;
5186
5186
  }
5187
5187
  }
@@ -5198,16 +5198,16 @@ class ReactNativeNetworkMonitor extends NetworkBase {
5198
5198
  }
5199
5199
  const online = !!(state.isConnected && state.isInternetReachable !== false);
5200
5200
  this.updateStatus(online);
5201
- log$6.debug('Initial network state:', online ? 'online' : 'offline');
5201
+ log$9.debug('Initial network state:', online ? 'online' : 'offline');
5202
5202
  }
5203
5203
  catch (error) {
5204
- log$6.warn('Could not fetch initial network state:', error);
5204
+ log$9.warn('Could not fetch initial network state:', error);
5205
5205
  }
5206
5206
  }
5207
5207
  subscribeToStateChanges() {
5208
5208
  if (!this.netInfoModule)
5209
5209
  return;
5210
- log$6.debug('Subscribing to network state changes');
5210
+ log$9.debug('Subscribing to network state changes');
5211
5211
  const handleState = (state) => {
5212
5212
  const online = !!(state.isConnected && (state.isInternetReachable ?? true));
5213
5213
  this.updateStatus(online);
@@ -5249,7 +5249,7 @@ class ReactNativeNetworkMonitor extends NetworkBase {
5249
5249
  };
5250
5250
  }
5251
5251
  catch (error) {
5252
- log$6.error('Failed to fetch detailed network info:', error);
5252
+ log$9.error('Failed to fetch detailed network info:', error);
5253
5253
  return null;
5254
5254
  }
5255
5255
  }
@@ -5385,7 +5385,7 @@ class CertificateValidator {
5385
5385
  }
5386
5386
  }
5387
5387
 
5388
- const log$5 = createPrefixedLogger('RN-MTLS');
5388
+ const log$8 = createPrefixedLogger('RN-MTLS');
5389
5389
  /**
5390
5390
  * React Native mTLS Adapter using @a-cube-io/expo-mutual-tls
5391
5391
  */
@@ -5407,7 +5407,7 @@ class ReactNativeMTLSAdapter {
5407
5407
  this.expoMTLS = ExpoMutualTls;
5408
5408
  // Set up debug logging with the correct event signature
5409
5409
  const debugListener = ExpoMutualTls.onDebugLog((event) => {
5410
- log$5.debug(`${event.type}: ${event.message}`, {
5410
+ log$8.debug(`${event.type}: ${event.message}`, {
5411
5411
  method: event.method,
5412
5412
  url: event.url,
5413
5413
  statusCode: event.statusCode,
@@ -5417,28 +5417,28 @@ class ReactNativeMTLSAdapter {
5417
5417
  this.eventListeners.push(debugListener);
5418
5418
  // Set up error logging with the correct event signature
5419
5419
  const errorListener = ExpoMutualTls.onError((event) => {
5420
- log$5.error(event.message, {
5420
+ log$8.error(event.message, {
5421
5421
  code: event.code,
5422
5422
  });
5423
5423
  });
5424
5424
  this.eventListeners.push(errorListener);
5425
5425
  // Set up certificate expiry monitoring with the correct event signature
5426
5426
  const expiryListener = ExpoMutualTls.onCertificateExpiry((event) => {
5427
- log$5.warn(`Certificate ${event.subject} expires at ${new Date(event.expiry)}`, {
5427
+ log$8.warn(`Certificate ${event.subject} expires at ${new Date(event.expiry)}`, {
5428
5428
  alias: event.alias,
5429
5429
  warning: event.warning,
5430
5430
  });
5431
5431
  });
5432
5432
  this.eventListeners.push(expiryListener);
5433
- log$5.debug('Expo mTLS module loaded successfully');
5433
+ log$8.debug('Expo mTLS module loaded successfully');
5434
5434
  }
5435
5435
  catch (error) {
5436
- log$5.warn('@a-cube-io/expo-mutual-tls not available:', error);
5436
+ log$8.warn('@a-cube-io/expo-mutual-tls not available:', error);
5437
5437
  }
5438
5438
  }
5439
5439
  async isMTLSSupported() {
5440
5440
  const supported = this.expoMTLS !== null;
5441
- log$5.debug('mTLS support check:', {
5441
+ log$8.debug('mTLS support check:', {
5442
5442
  supported,
5443
5443
  platform: this.getPlatformInfo().platform,
5444
5444
  moduleAvailable: !!this.expoMTLS,
@@ -5450,7 +5450,7 @@ class ReactNativeMTLSAdapter {
5450
5450
  throw new MTLSError(MTLSErrorType$1.NOT_SUPPORTED, 'Expo mTLS module not available');
5451
5451
  }
5452
5452
  this.config = config;
5453
- log$5.debug('Initialized with config:', {
5453
+ log$8.debug('Initialized with config:', {
5454
5454
  baseUrl: config.baseUrl,
5455
5455
  port: config.port,
5456
5456
  timeout: config.timeout,
@@ -5464,7 +5464,7 @@ class ReactNativeMTLSAdapter {
5464
5464
  if (!this.config) {
5465
5465
  throw new MTLSError(MTLSErrorType$1.CONFIGURATION_ERROR, 'Adapter not initialized. Call initialize() first.');
5466
5466
  }
5467
- log$5.debug('Configuring certificate:', {
5467
+ log$8.debug('Configuring certificate:', {
5468
5468
  format: certificateData.format,
5469
5469
  hasPassword: !!certificateData.password,
5470
5470
  certificateLength: certificateData.certificate.length,
@@ -5481,14 +5481,14 @@ class ReactNativeMTLSAdapter {
5481
5481
  'client-key-service', // keyService
5482
5482
  true // enableLogging - let the native module handle its own debug logging
5483
5483
  );
5484
- log$5.debug('PEM services configured:', configResult);
5484
+ log$8.debug('PEM services configured:', configResult);
5485
5485
  if (!configResult.success) {
5486
5486
  throw new MTLSError(MTLSErrorType$1.CONFIGURATION_ERROR, `PEM configuration failed: ${configResult.state}`);
5487
5487
  }
5488
5488
  // Step 2: Store the actual PEM certificate and private key
5489
5489
  const storeResult = await this.expoMTLS.storePEM(certificateData.certificate, certificateData.privateKey, certificateData.password // passphrase (optional)
5490
5490
  );
5491
- log$5.debug('PEM certificate store result:', storeResult);
5491
+ log$8.debug('PEM certificate store result:', storeResult);
5492
5492
  if (!storeResult) {
5493
5493
  throw new MTLSError(MTLSErrorType$1.CERTIFICATE_INVALID, 'Failed to store PEM certificate');
5494
5494
  }
@@ -5501,14 +5501,14 @@ class ReactNativeMTLSAdapter {
5501
5501
  const configResult = await this.expoMTLS.configureP12('client-p12-service', // keychainService
5502
5502
  true // enableLogging - let the native module handle its own debug logging
5503
5503
  );
5504
- log$5.debug('P12 service configured:', configResult);
5504
+ log$8.debug('P12 service configured:', configResult);
5505
5505
  if (!configResult.success) {
5506
5506
  throw new MTLSError(MTLSErrorType$1.CONFIGURATION_ERROR, `P12 configuration failed: ${configResult.state}`);
5507
5507
  }
5508
5508
  // Step 2: Store the P12 certificate data
5509
5509
  const storeResult = await this.expoMTLS.storeP12(certificateData.certificate, // P12 data in certificate field
5510
5510
  certificateData.password);
5511
- log$5.debug('P12 certificate store result:', storeResult);
5511
+ log$8.debug('P12 certificate store result:', storeResult);
5512
5512
  if (!storeResult) {
5513
5513
  throw new MTLSError(MTLSErrorType$1.CERTIFICATE_INVALID, 'Failed to store P12 certificate');
5514
5514
  }
@@ -5522,7 +5522,7 @@ class ReactNativeMTLSAdapter {
5522
5522
  if (error instanceof MTLSError) {
5523
5523
  throw error;
5524
5524
  }
5525
- log$5.error('Certificate configuration failed:', error);
5525
+ log$8.error('Certificate configuration failed:', error);
5526
5526
  throw new MTLSError(MTLSErrorType$1.CONFIGURATION_ERROR, 'Failed to configure certificate', error);
5527
5527
  }
5528
5528
  }
@@ -5533,38 +5533,38 @@ class ReactNativeMTLSAdapter {
5533
5533
  try {
5534
5534
  // Use static method call
5535
5535
  const hasCert = await this.expoMTLS.hasCertificate();
5536
- log$5.debug('Certificate availability check:', hasCert);
5536
+ log$8.debug('Certificate availability check:', hasCert);
5537
5537
  return hasCert;
5538
5538
  }
5539
5539
  catch (error) {
5540
- log$5.error('Certificate check failed:', error);
5540
+ log$8.error('Certificate check failed:', error);
5541
5541
  return false;
5542
5542
  }
5543
5543
  }
5544
5544
  async getCertificateInfo() {
5545
5545
  if (!this.expoMTLS) {
5546
- log$5.debug('Certificate info requested but module not available');
5546
+ log$8.debug('Certificate info requested but module not available');
5547
5547
  return null;
5548
5548
  }
5549
5549
  try {
5550
5550
  const hasCert = await this.hasCertificate();
5551
5551
  if (!hasCert) {
5552
- log$5.debug('No certificate stored');
5552
+ log$8.debug('No certificate stored');
5553
5553
  return null;
5554
5554
  }
5555
5555
  // Use getCertificatesInfo to retrieve information about stored certificates
5556
5556
  const result = await this.expoMTLS.getCertificatesInfo();
5557
5557
  if (!result || !result.certificates || result.certificates.length === 0) {
5558
- log$5.debug('No certificate information available');
5558
+ log$8.debug('No certificate information available');
5559
5559
  return null;
5560
5560
  }
5561
5561
  // Get the first certificate (primary client certificate)
5562
5562
  const cert = result.certificates[0];
5563
5563
  if (!cert) {
5564
- log$5.debug('Certificate data is empty');
5564
+ log$8.debug('Certificate data is empty');
5565
5565
  return null;
5566
5566
  }
5567
- log$5.debug('Retrieved certificate info:', {
5567
+ log$8.debug('Retrieved certificate info:', {
5568
5568
  subject: cert.subject.commonName,
5569
5569
  issuer: cert.issuer.commonName,
5570
5570
  validFrom: new Date(cert.validFrom),
@@ -5583,7 +5583,7 @@ class ReactNativeMTLSAdapter {
5583
5583
  };
5584
5584
  }
5585
5585
  catch (error) {
5586
- log$5.error('Failed to get certificate info:', error);
5586
+ log$8.error('Failed to get certificate info:', error);
5587
5587
  return null;
5588
5588
  }
5589
5589
  }
@@ -5594,7 +5594,7 @@ class ReactNativeMTLSAdapter {
5594
5594
  */
5595
5595
  async parseCertificateData(certificateData) {
5596
5596
  if (!this.expoMTLS) {
5597
- log$5.debug('Parse certificate: Module not available');
5597
+ log$8.debug('Parse certificate: Module not available');
5598
5598
  return null;
5599
5599
  }
5600
5600
  try {
@@ -5611,14 +5611,14 @@ class ReactNativeMTLSAdapter {
5611
5611
  else {
5612
5612
  throw new MTLSError(MTLSErrorType$1.CERTIFICATE_INVALID, `Unsupported certificate format: ${certificateData.format}`);
5613
5613
  }
5614
- log$5.debug('Certificate parsed successfully:', {
5614
+ log$8.debug('Certificate parsed successfully:', {
5615
5615
  certificateCount: result.certificates.length,
5616
5616
  subjects: result.certificates.map((cert) => cert.subject.commonName),
5617
5617
  });
5618
5618
  return result;
5619
5619
  }
5620
5620
  catch (error) {
5621
- log$5.error('Failed to parse certificate:', error);
5621
+ log$8.error('Failed to parse certificate:', error);
5622
5622
  if (error instanceof MTLSError) {
5623
5623
  throw error;
5624
5624
  }
@@ -5633,7 +5633,7 @@ class ReactNativeMTLSAdapter {
5633
5633
  if (!hasCert) {
5634
5634
  throw new MTLSError(MTLSErrorType$1.CERTIFICATE_NOT_FOUND, 'No certificate configured');
5635
5635
  }
5636
- log$5.debug('Making mTLS request:', {
5636
+ log$8.debug('Making mTLS request:', {
5637
5637
  method: requestConfig.method || 'GET',
5638
5638
  url: requestConfig.url,
5639
5639
  headers: requestConfig.headers,
@@ -5641,7 +5641,7 @@ class ReactNativeMTLSAdapter {
5641
5641
  responseType: requestConfig.responseType,
5642
5642
  });
5643
5643
  if (requestConfig.data) {
5644
- log$5.debug('mTLS request body:', requestConfig.data);
5644
+ log$8.debug('mTLS request body:', requestConfig.data);
5645
5645
  }
5646
5646
  try {
5647
5647
  const response = await this.expoMTLS.request(requestConfig.url, {
@@ -5650,7 +5650,7 @@ class ReactNativeMTLSAdapter {
5650
5650
  body: requestConfig.data ? JSON.stringify(requestConfig.data) : undefined,
5651
5651
  responseType: requestConfig.responseType,
5652
5652
  });
5653
- log$5.debug('mTLS request successful:', response);
5653
+ log$8.debug('mTLS request successful:', response);
5654
5654
  if (!response.success) {
5655
5655
  throw new MTLSError(MTLSErrorType$1.CONNECTION_FAILED, `mTLS request failed: ${response.statusMessage} (${response.statusCode})`, undefined, response.statusCode);
5656
5656
  }
@@ -5662,7 +5662,7 @@ class ReactNativeMTLSAdapter {
5662
5662
  data = JSON.parse(response.body);
5663
5663
  }
5664
5664
  catch (parseError) {
5665
- log$5.warn('Failed to parse JSON response:', parseError);
5665
+ log$8.warn('Failed to parse JSON response:', parseError);
5666
5666
  // If parsing fails, keep raw body
5667
5667
  }
5668
5668
  }
@@ -5679,7 +5679,7 @@ class ReactNativeMTLSAdapter {
5679
5679
  };
5680
5680
  }
5681
5681
  catch (error) {
5682
- log$5.error('mTLS request failed:', error);
5682
+ log$8.error('mTLS request failed:', error);
5683
5683
  throw new MTLSError(MTLSErrorType$1.CONNECTION_FAILED, 'mTLS request failed', error);
5684
5684
  }
5685
5685
  }
@@ -5692,18 +5692,18 @@ class ReactNativeMTLSAdapter {
5692
5692
  */
5693
5693
  async testConnection() {
5694
5694
  if (!this.expoMTLS || !this.config) {
5695
- log$5.debug('Diagnostic test: No mTLS module or config available');
5695
+ log$8.debug('Diagnostic test: No mTLS module or config available');
5696
5696
  return false;
5697
5697
  }
5698
5698
  try {
5699
5699
  const hasCert = await this.hasCertificate();
5700
5700
  if (!hasCert) {
5701
- log$5.debug('Diagnostic test: No certificate configured');
5701
+ log$8.debug('Diagnostic test: No certificate configured');
5702
5702
  return false;
5703
5703
  }
5704
- log$5.debug('Running diagnostic test (may fail even if mTLS works):', this.config.baseUrl);
5704
+ log$8.debug('Running diagnostic test (may fail even if mTLS works):', this.config.baseUrl);
5705
5705
  const result = await this.expoMTLS.testConnection(this.config.baseUrl);
5706
- log$5.debug('Diagnostic test result (NOT validation):', {
5706
+ log$8.debug('Diagnostic test result (NOT validation):', {
5707
5707
  success: result.success,
5708
5708
  statusCode: result.statusCode,
5709
5709
  statusMessage: result.statusMessage,
@@ -5714,13 +5714,13 @@ class ReactNativeMTLSAdapter {
5714
5714
  return result.success;
5715
5715
  }
5716
5716
  catch (error) {
5717
- log$5.warn('Diagnostic test failed (this is expected):', error);
5717
+ log$8.warn('Diagnostic test failed (this is expected):', error);
5718
5718
  return false;
5719
5719
  }
5720
5720
  }
5721
5721
  async removeCertificate() {
5722
5722
  if (!this.expoMTLS) {
5723
- log$5.debug('Remove certificate: Module not available');
5723
+ log$8.debug('Remove certificate: Module not available');
5724
5724
  return;
5725
5725
  }
5726
5726
  try {
@@ -5729,10 +5729,10 @@ class ReactNativeMTLSAdapter {
5729
5729
  this.isConfigured = false;
5730
5730
  // Cleanup event listeners
5731
5731
  this.cleanupEventListeners();
5732
- log$5.debug('Certificate removed successfully');
5732
+ log$8.debug('Certificate removed successfully');
5733
5733
  }
5734
5734
  catch (error) {
5735
- log$5.error('Failed to remove certificate:', error);
5735
+ log$8.error('Failed to remove certificate:', error);
5736
5736
  throw new MTLSError(MTLSErrorType$1.CONFIGURATION_ERROR, 'Failed to remove certificate', error);
5737
5737
  }
5738
5738
  }
@@ -5741,7 +5741,7 @@ class ReactNativeMTLSAdapter {
5741
5741
  */
5742
5742
  cleanupEventListeners() {
5743
5743
  if (this.eventListeners.length > 0) {
5744
- log$5.debug(`Cleaning up ${this.eventListeners.length} event listeners`);
5744
+ log$8.debug(`Cleaning up ${this.eventListeners.length} event listeners`);
5745
5745
  }
5746
5746
  // Remove individual listeners if they have remove methods
5747
5747
  this.eventListeners.forEach((listener) => {
@@ -5778,7 +5778,7 @@ class ReactNativeMTLSAdapter {
5778
5778
  }
5779
5779
  }
5780
5780
 
5781
- const log$4 = createPrefixedLogger('WEB-MTLS');
5781
+ const log$7 = createPrefixedLogger('WEB-MTLS');
5782
5782
  /**
5783
5783
  * Web mTLS Adapter - Graceful fallback for web browsers
5784
5784
  *
@@ -5792,13 +5792,13 @@ const log$4 = createPrefixedLogger('WEB-MTLS');
5792
5792
  */
5793
5793
  class WebMTLSAdapter {
5794
5794
  constructor() {
5795
- log$4.warn('Web browsers do not support programmatic mTLS configuration');
5796
- log$4.info('Use JWT authentication or configure client certificates in browser settings');
5795
+ log$7.warn('Web browsers do not support programmatic mTLS configuration');
5796
+ log$7.info('Use JWT authentication or configure client certificates in browser settings');
5797
5797
  }
5798
5798
  async isMTLSSupported() {
5799
5799
  // mTLS is not supported programmatically in web browsers
5800
5800
  const supported = false;
5801
- log$4.debug('mTLS support check:', {
5801
+ log$7.debug('mTLS support check:', {
5802
5802
  supported,
5803
5803
  platform: this.getPlatformInfo().platform,
5804
5804
  reason: 'Browser security model prevents programmatic certificate configuration',
@@ -5807,14 +5807,14 @@ class WebMTLSAdapter {
5807
5807
  return supported;
5808
5808
  }
5809
5809
  async initialize(config) {
5810
- log$4.warn('Initialized but mTLS not available in web browsers:', {
5810
+ log$7.warn('Initialized but mTLS not available in web browsers:', {
5811
5811
  baseUrl: config.baseUrl,
5812
5812
  port: config.port,
5813
5813
  recommendation: 'Use standard HTTPS with JWT authentication',
5814
5814
  });
5815
5815
  }
5816
5816
  async configureCertificate(certificateData) {
5817
- log$4.error('Certificate configuration attempted:', {
5817
+ log$7.error('Certificate configuration attempted:', {
5818
5818
  format: certificateData.format,
5819
5819
  reason: 'Not supported in web browsers',
5820
5820
  alternatives: [
@@ -5829,15 +5829,15 @@ class WebMTLSAdapter {
5829
5829
  }
5830
5830
  async hasCertificate() {
5831
5831
  // We cannot detect if the browser has certificates configured
5832
- log$4.debug('Certificate availability check: Cannot detect browser certificates programmatically');
5832
+ log$7.debug('Certificate availability check: Cannot detect browser certificates programmatically');
5833
5833
  return false;
5834
5834
  }
5835
5835
  async getCertificateInfo() {
5836
- log$4.debug('Certificate info requested: Not accessible in web browsers');
5836
+ log$7.debug('Certificate info requested: Not accessible in web browsers');
5837
5837
  return null;
5838
5838
  }
5839
5839
  async request(requestConfig) {
5840
- log$4.error('mTLS request attempted:', {
5840
+ log$7.error('mTLS request attempted:', {
5841
5841
  method: requestConfig.method,
5842
5842
  url: requestConfig.url,
5843
5843
  reason: 'Not supported in web browsers',
@@ -5852,11 +5852,11 @@ class WebMTLSAdapter {
5852
5852
  'are properly configured in the browser certificate store.');
5853
5853
  }
5854
5854
  async testConnection() {
5855
- log$4.debug('Connection test: mTLS not available in web browsers');
5855
+ log$7.debug('Connection test: mTLS not available in web browsers');
5856
5856
  return false;
5857
5857
  }
5858
5858
  async removeCertificate() {
5859
- log$4.debug('Remove certificate: No certificates to remove (not supported in web browsers)');
5859
+ log$7.debug('Remove certificate: No certificates to remove (not supported in web browsers)');
5860
5860
  // No-op - cannot remove certificates programmatically in browsers
5861
5861
  }
5862
5862
  /**
@@ -5864,7 +5864,7 @@ class WebMTLSAdapter {
5864
5864
  * Always returns null for web browsers as mTLS is not supported
5865
5865
  */
5866
5866
  getBaseUrl() {
5867
- log$4.debug('Base URL requested: Not supported in web browsers');
5867
+ log$7.debug('Base URL requested: Not supported in web browsers');
5868
5868
  return null;
5869
5869
  }
5870
5870
  getPlatformInfo() {
@@ -5897,7 +5897,7 @@ class WebMTLSAdapter {
5897
5897
  }
5898
5898
  }
5899
5899
 
5900
- const log$3 = createPrefixedLogger('MTLS-LOADER');
5900
+ const log$6 = createPrefixedLogger('MTLS-LOADER');
5901
5901
  function loadMTLSAdapter(platform, config) {
5902
5902
  try {
5903
5903
  let adapter;
@@ -5931,7 +5931,7 @@ function loadMTLSAdapter(platform, config) {
5931
5931
  return adapter;
5932
5932
  }
5933
5933
  catch (error) {
5934
- log$3.warn(`mTLS adapter not available for platform ${platform}:`, error);
5934
+ log$6.warn(`mTLS adapter not available for platform ${platform}:`, error);
5935
5935
  return null;
5936
5936
  }
5937
5937
  }
@@ -5941,7 +5941,7 @@ async function initializeAdapterAsync(adapter, config) {
5941
5941
  if (isSupported) {
5942
5942
  await adapter.initialize(config);
5943
5943
  const platformInfo = adapter.getPlatformInfo();
5944
- log$3.debug('mTLS adapter initialized:', {
5944
+ log$6.debug('mTLS adapter initialized:', {
5945
5945
  platform: platformInfo.platform,
5946
5946
  mtlsSupported: platformInfo.mtlsSupported,
5947
5947
  certificateStorage: platformInfo.certificateStorage,
@@ -5950,20 +5950,20 @@ async function initializeAdapterAsync(adapter, config) {
5950
5950
  }
5951
5951
  }
5952
5952
  catch (error) {
5953
- log$3.warn('Failed to initialize mTLS adapter:', error);
5953
+ log$6.warn('Failed to initialize mTLS adapter:', error);
5954
5954
  }
5955
5955
  }
5956
5956
 
5957
- const log$2 = createPrefixedLogger('ADAPTER-LOADER');
5957
+ const log$5 = createPrefixedLogger('ADAPTER-LOADER');
5958
5958
  function loadPlatformAdapters(options = {}) {
5959
5959
  const { mtlsConfig } = options;
5960
5960
  const { platform } = detectPlatform();
5961
- log$2.debug('Loading adapters for platform:', platform);
5961
+ log$5.debug('Loading adapters for platform:', platform);
5962
5962
  const storageAdapters = loadStorageAdapters(platform);
5963
5963
  const networkMonitor = loadNetworkMonitor(platform);
5964
5964
  const cache = loadCacheAdapter(platform);
5965
5965
  const mtls = loadMTLSAdapter(platform, mtlsConfig);
5966
- log$2.debug('Adapters loaded:', {
5966
+ log$5.debug('Adapters loaded:', {
5967
5967
  platform,
5968
5968
  hasStorage: !!storageAdapters.storage,
5969
5969
  hasSecureStorage: !!storageAdapters.secureStorage,
@@ -6077,10 +6077,12 @@ class ACubeSDKError extends Error {
6077
6077
 
6078
6078
  const DI_TOKENS = {
6079
6079
  HTTP_PORT: Symbol('HTTP_PORT'),
6080
+ BASE_HTTP_PORT: Symbol('BASE_HTTP_PORT'),
6080
6081
  STORAGE_PORT: Symbol('STORAGE_PORT'),
6081
6082
  SECURE_STORAGE_PORT: Symbol('SECURE_STORAGE_PORT'),
6082
6083
  NETWORK_PORT: Symbol('NETWORK_PORT'),
6083
6084
  CACHE_PORT: Symbol('CACHE_PORT'),
6085
+ CACHE_KEY_GENERATOR: Symbol('CACHE_KEY_GENERATOR'),
6084
6086
  MTLS_PORT: Symbol('MTLS_PORT'),
6085
6087
  TOKEN_STORAGE_PORT: Symbol('TOKEN_STORAGE_PORT'),
6086
6088
  RECEIPT_REPOSITORY: Symbol('RECEIPT_REPOSITORY'),
@@ -6310,7 +6312,7 @@ class ReceiptRepositoryImpl {
6310
6312
  if (format === 'pdf') {
6311
6313
  const response = await this.http.get(`/mf1/receipts/${receiptUuid}/details`, {
6312
6314
  headers: { Accept: 'application/pdf' },
6313
- responseType: 'blob',
6315
+ responseType: 'arraybuffer',
6314
6316
  });
6315
6317
  return response.data;
6316
6318
  }
@@ -7073,7 +7075,465 @@ class TelemetryRepositoryImpl {
7073
7075
  }
7074
7076
  }
7075
7077
 
7076
- const log$1 = createPrefixedLogger('HTTP-MTLS');
7078
+ const log$4 = createPrefixedLogger('CACHE-KEY');
7079
+ const URL_PATTERNS = [
7080
+ // Receipt (mf1) - specific patterns first
7081
+ {
7082
+ pattern: /^\/mf1\/receipts\/([^/]+)\/returnable-items$/,
7083
+ resource: 'receipt',
7084
+ action: 'returnable',
7085
+ },
7086
+ {
7087
+ pattern: /^\/mf1\/receipts\/([^/]+)\/details$/,
7088
+ resource: 'receipt',
7089
+ action: 'details',
7090
+ },
7091
+ { pattern: /^\/mf1\/receipts\/([^/]+)$/, resource: 'receipt' },
7092
+ {
7093
+ pattern: /^\/mf1\/point-of-sales\/([^/]+)\/receipts$/,
7094
+ resource: 'receipt',
7095
+ parent: 'point-of-sale',
7096
+ isList: true,
7097
+ },
7098
+ { pattern: /^\/mf1\/receipts$/, resource: 'receipt', isList: true },
7099
+ // Merchant (mf2)
7100
+ { pattern: /^\/mf2\/merchants\/([^/]+)$/, resource: 'merchant' },
7101
+ { pattern: /^\/mf2\/merchants$/, resource: 'merchant', isList: true },
7102
+ // Cashier (mf1)
7103
+ { pattern: /^\/mf1\/cashiers\/me$/, resource: 'cashier', action: 'me' },
7104
+ { pattern: /^\/mf1\/cashiers\/([^/]+)$/, resource: 'cashier' },
7105
+ { pattern: /^\/mf1\/cashiers$/, resource: 'cashier', isList: true },
7106
+ // Cash Register (mf1)
7107
+ { pattern: /^\/mf1\/cash-registers\/([^/]+)$/, resource: 'cash-register' },
7108
+ { pattern: /^\/mf1\/cash-registers$/, resource: 'cash-register', isList: true },
7109
+ // Point of Sale (mf1)
7110
+ { pattern: /^\/mf1\/point-of-sales\/([^/]+)$/, resource: 'point-of-sale' },
7111
+ { pattern: /^\/mf1\/point-of-sales$/, resource: 'point-of-sale', isList: true },
7112
+ // Nested resources under merchant (mf2)
7113
+ {
7114
+ pattern: /^\/mf2\/merchants\/([^/]+)\/suppliers\/([^/]+)$/,
7115
+ resource: 'supplier',
7116
+ parent: 'merchant',
7117
+ },
7118
+ {
7119
+ pattern: /^\/mf2\/merchants\/([^/]+)\/suppliers$/,
7120
+ resource: 'supplier',
7121
+ parent: 'merchant',
7122
+ isList: true,
7123
+ },
7124
+ {
7125
+ pattern: /^\/mf2\/merchants\/([^/]+)\/daily-reports/,
7126
+ resource: 'daily-report',
7127
+ parent: 'merchant',
7128
+ isList: true,
7129
+ },
7130
+ {
7131
+ pattern: /^\/mf2\/merchants\/([^/]+)\/journals/,
7132
+ resource: 'journal',
7133
+ parent: 'merchant',
7134
+ isList: true,
7135
+ },
7136
+ // PEM (mf2)
7137
+ {
7138
+ pattern: /^\/mf2\/point-of-sales\/([^/]+)\/certificates$/,
7139
+ resource: 'pem',
7140
+ action: 'certificates',
7141
+ },
7142
+ { pattern: /^\/mf2\/point-of-sales\/([^/]+)$/, resource: 'pem' },
7143
+ // Others
7144
+ { pattern: /^\/mf1\/notifications/, resource: 'notification', isList: true },
7145
+ {
7146
+ pattern: /^\/mf1\/point-of-sales\/([^/]+)\/telemetry$/,
7147
+ resource: 'telemetry',
7148
+ },
7149
+ ];
7150
+ const DEFAULT_TTL_CONFIG = {
7151
+ // Data that rarely changes - 30 min TTL for items only
7152
+ merchant: { ttlMs: 30 * 60 * 1000, cacheList: false, cacheItem: true },
7153
+ 'point-of-sale': { ttlMs: 30 * 60 * 1000, cacheList: false, cacheItem: true },
7154
+ 'cash-register': { ttlMs: 30 * 60 * 1000, cacheList: false, cacheItem: true },
7155
+ pem: { ttlMs: 30 * 60 * 1000, cacheList: false, cacheItem: false },
7156
+ // Data that changes moderately - 10 min TTL for items only
7157
+ cashier: { ttlMs: 10 * 60 * 1000, cacheList: false, cacheItem: true },
7158
+ supplier: { ttlMs: 10 * 60 * 1000, cacheList: false, cacheItem: true },
7159
+ // Data that can change - 5 min TTL for items only
7160
+ receipt: { ttlMs: 5 * 60 * 1000, cacheList: false, cacheItem: true },
7161
+ 'daily-report': { ttlMs: 5 * 60 * 1000, cacheList: false, cacheItem: true },
7162
+ journal: { ttlMs: 5 * 60 * 1000, cacheList: false, cacheItem: true },
7163
+ // Real-time data - 1 min TTL
7164
+ notification: { ttlMs: 1 * 60 * 1000, cacheList: false, cacheItem: false },
7165
+ telemetry: { ttlMs: 1 * 60 * 1000, cacheList: false, cacheItem: false },
7166
+ };
7167
+ const DEFAULT_TTL = 5 * 60 * 1000; // 5 minutes
7168
+ class CacheKeyGenerator {
7169
+ constructor(customConfig) {
7170
+ this.config = { ...DEFAULT_TTL_CONFIG, ...customConfig };
7171
+ log$4.info('CacheKeyGenerator initialized with config:', {
7172
+ resources: Object.keys(this.config),
7173
+ });
7174
+ }
7175
+ generate(url, params) {
7176
+ const parsed = this.parseUrl(url);
7177
+ if (!parsed) {
7178
+ // Fallback: use URL as key
7179
+ const paramStr = params ? this.serializeParams(params) : '';
7180
+ const key = paramStr ? `${url}?${paramStr}` : url;
7181
+ log$4.debug('URL not matched, using fallback key:', { url, key });
7182
+ return key;
7183
+ }
7184
+ const { resource, ids, action, isList, parent } = parsed;
7185
+ if (isList) {
7186
+ const paramStr = params ? this.serializeParams(params) : '';
7187
+ const parentPart = parent && ids.length > 0 ? `${parent}=${ids[0]}&` : '';
7188
+ const key = `${resource}:list:${parentPart}${paramStr}`;
7189
+ log$4.debug('Generated list cache key:', { url, key, resource });
7190
+ return key;
7191
+ }
7192
+ // Single item
7193
+ if (ids.length === 0 && action) {
7194
+ // Special case for endpoints like /cashiers/me
7195
+ const key = `${resource}:${action}`;
7196
+ log$4.debug('Generated special action cache key:', { url, key, resource, action });
7197
+ return key;
7198
+ }
7199
+ let key = `${resource}:${ids.join(':')}`;
7200
+ if (action) {
7201
+ key += `:${action}`;
7202
+ }
7203
+ log$4.debug('Generated item cache key:', { url, key, resource, ids, action });
7204
+ return key;
7205
+ }
7206
+ parseResource(url) {
7207
+ const parsed = this.parseUrl(url);
7208
+ return parsed?.resource;
7209
+ }
7210
+ getTTL(url) {
7211
+ const resource = this.parseResource(url);
7212
+ if (!resource) {
7213
+ log$4.debug('No resource found for URL, using default TTL:', { url, ttl: DEFAULT_TTL });
7214
+ return DEFAULT_TTL;
7215
+ }
7216
+ const ttl = this.config[resource].ttlMs;
7217
+ log$4.debug('TTL for resource:', { url, resource, ttlMs: ttl, ttlMin: ttl / 60000 });
7218
+ return ttl;
7219
+ }
7220
+ shouldCache(url) {
7221
+ const parsed = this.parseUrl(url);
7222
+ if (!parsed) {
7223
+ log$4.debug('URL not recognized, should not cache:', { url });
7224
+ return false;
7225
+ }
7226
+ const { resource, isList } = parsed;
7227
+ const config = this.config[resource];
7228
+ if (isList) {
7229
+ log$4.debug('List endpoint cache decision:', {
7230
+ url,
7231
+ resource,
7232
+ isList: true,
7233
+ shouldCache: config.cacheList,
7234
+ });
7235
+ return config.cacheList;
7236
+ }
7237
+ log$4.debug('Item endpoint cache decision:', {
7238
+ url,
7239
+ resource,
7240
+ isList: false,
7241
+ shouldCache: config.cacheItem,
7242
+ });
7243
+ return config.cacheItem;
7244
+ }
7245
+ getInvalidationPatterns(url, method) {
7246
+ const parsed = this.parseUrl(url);
7247
+ if (!parsed) {
7248
+ log$4.debug('No patterns to invalidate for URL:', { url, method });
7249
+ return [];
7250
+ }
7251
+ const { resource, ids, parent } = parsed;
7252
+ const patterns = [];
7253
+ // Always invalidate list on mutations
7254
+ if (method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'DELETE') {
7255
+ if (parent && ids.length > 0) {
7256
+ patterns.push(`${resource}:list:${parent}=${ids[0]}*`);
7257
+ }
7258
+ patterns.push(`${resource}:list:*`);
7259
+ }
7260
+ // Invalidate specific item on PUT/PATCH/DELETE
7261
+ if (method === 'PUT' || method === 'PATCH' || method === 'DELETE') {
7262
+ if (ids.length > 0) {
7263
+ patterns.push(`${resource}:${ids.join(':')}*`);
7264
+ }
7265
+ }
7266
+ // Special cases
7267
+ if (resource === 'cashier' && (method === 'PUT' || method === 'DELETE')) {
7268
+ patterns.push('cashier:me');
7269
+ }
7270
+ log$4.debug('Invalidation patterns:', { url, method, patterns });
7271
+ return patterns;
7272
+ }
7273
+ parseUrl(url) {
7274
+ // Remove query string for pattern matching
7275
+ const urlPath = url.split('?')[0];
7276
+ for (const pattern of URL_PATTERNS) {
7277
+ const match = urlPath?.match(pattern.pattern);
7278
+ if (match) {
7279
+ // Extract IDs from capture groups
7280
+ const ids = match.slice(1).filter(Boolean);
7281
+ return {
7282
+ resource: pattern.resource,
7283
+ ids,
7284
+ action: pattern.action,
7285
+ isList: pattern.isList,
7286
+ parent: pattern.parent,
7287
+ };
7288
+ }
7289
+ }
7290
+ return null;
7291
+ }
7292
+ serializeParams(params) {
7293
+ const sortedKeys = Object.keys(params).sort();
7294
+ const parts = [];
7295
+ for (const key of sortedKeys) {
7296
+ const value = params[key];
7297
+ if (value !== undefined && value !== null) {
7298
+ parts.push(`${key}=${String(value)}`);
7299
+ }
7300
+ }
7301
+ return parts.join('&');
7302
+ }
7303
+ }
7304
+
7305
+ const log$3 = createPrefixedLogger('CACHE');
7306
+ class CachingHttpDecorator {
7307
+ constructor(http, cache, keyGenerator, networkMonitor, config = {}) {
7308
+ this.http = http;
7309
+ this.cache = cache;
7310
+ this.keyGenerator = keyGenerator;
7311
+ this.networkMonitor = networkMonitor;
7312
+ this.config = config;
7313
+ this.currentOnlineState = true;
7314
+ this.authToken = null;
7315
+ log$3.info('CachingHttpDecorator initialized', {
7316
+ enabled: config.enabled !== false,
7317
+ hasNetworkMonitor: !!networkMonitor,
7318
+ });
7319
+ this.setupNetworkMonitoring();
7320
+ }
7321
+ setupNetworkMonitoring() {
7322
+ if (this.networkMonitor) {
7323
+ this.networkSubscription = this.networkMonitor.online$.subscribe((online) => {
7324
+ if (this.currentOnlineState !== online) {
7325
+ log$3.info('Network state changed:', { online });
7326
+ }
7327
+ this.currentOnlineState = online;
7328
+ });
7329
+ }
7330
+ }
7331
+ isOnline() {
7332
+ if (this.networkMonitor) {
7333
+ return this.currentOnlineState;
7334
+ }
7335
+ if (typeof navigator !== 'undefined' && 'onLine' in navigator) {
7336
+ return navigator.onLine;
7337
+ }
7338
+ return true;
7339
+ }
7340
+ async get(url, config) {
7341
+ const startTime = Date.now();
7342
+ // Check if caching is disabled globally
7343
+ if (this.config.enabled === false) {
7344
+ log$3.debug('GET (cache disabled globally):', { url });
7345
+ return this.http.get(url, config);
7346
+ }
7347
+ // Check if this URL should be cached
7348
+ const shouldCache = this.keyGenerator.shouldCache(url);
7349
+ if (!shouldCache) {
7350
+ log$3.debug('GET (not cacheable - likely a list endpoint):', { url });
7351
+ return this.http.get(url, config);
7352
+ }
7353
+ const cacheKey = this.keyGenerator.generate(url, config?.params);
7354
+ const ttl = this.keyGenerator.getTTL(url);
7355
+ const resource = this.keyGenerator.parseResource(url);
7356
+ log$3.info('GET request starting:', {
7357
+ url,
7358
+ resource,
7359
+ cacheKey,
7360
+ ttlMs: ttl,
7361
+ ttlMin: Math.round(ttl / 60000),
7362
+ params: config?.params,
7363
+ });
7364
+ // Check cache
7365
+ let cached = null;
7366
+ try {
7367
+ cached = await this.cache.get(cacheKey);
7368
+ if (cached) {
7369
+ log$3.debug('Cache entry found:', {
7370
+ cacheKey,
7371
+ timestamp: new Date(cached.timestamp).toISOString(),
7372
+ ageMs: Date.now() - cached.timestamp,
7373
+ });
7374
+ }
7375
+ else {
7376
+ log$3.debug('Cache entry not found:', { cacheKey });
7377
+ }
7378
+ }
7379
+ catch (error) {
7380
+ log$3.warn('Cache lookup failed:', {
7381
+ cacheKey,
7382
+ error: error instanceof Error ? error.message : error,
7383
+ });
7384
+ }
7385
+ if (cached) {
7386
+ const age = Date.now() - cached.timestamp;
7387
+ const isExpired = age >= ttl;
7388
+ log$3.debug('Cache analysis:', {
7389
+ cacheKey,
7390
+ ageMs: age,
7391
+ ageSec: Math.round(age / 1000),
7392
+ ttlMs: ttl,
7393
+ isExpired,
7394
+ isOnline: this.isOnline(),
7395
+ });
7396
+ // If within TTL, return cached data
7397
+ if (!isExpired) {
7398
+ const duration = Date.now() - startTime;
7399
+ log$3.info('CACHE HIT:', {
7400
+ url,
7401
+ cacheKey,
7402
+ ageMs: age,
7403
+ durationMs: duration,
7404
+ });
7405
+ return {
7406
+ data: cached.data,
7407
+ status: 200,
7408
+ headers: { 'x-cache': 'HIT' },
7409
+ };
7410
+ }
7411
+ // If offline and cache is stale, return stale data
7412
+ if (!this.isOnline()) {
7413
+ const duration = Date.now() - startTime;
7414
+ log$3.info('CACHE STALE (offline):', {
7415
+ url,
7416
+ cacheKey,
7417
+ ageMs: age,
7418
+ durationMs: duration,
7419
+ });
7420
+ return {
7421
+ data: cached.data,
7422
+ status: 200,
7423
+ headers: { 'x-cache': 'STALE' },
7424
+ };
7425
+ }
7426
+ log$3.debug('Cache expired, fetching fresh data:', { cacheKey, ageMs: age, ttlMs: ttl });
7427
+ }
7428
+ // Fetch fresh data
7429
+ try {
7430
+ log$3.debug('Fetching from network:', { url });
7431
+ const response = await this.http.get(url, config);
7432
+ // Cache the response
7433
+ try {
7434
+ await this.cache.set(cacheKey, response.data);
7435
+ log$3.debug('Response cached successfully:', { cacheKey });
7436
+ }
7437
+ catch (error) {
7438
+ log$3.error('Failed to cache response:', {
7439
+ cacheKey,
7440
+ error: error instanceof Error ? error.message : error,
7441
+ });
7442
+ }
7443
+ const duration = Date.now() - startTime;
7444
+ log$3.info('CACHE MISS (fetched fresh):', {
7445
+ url,
7446
+ cacheKey,
7447
+ status: response.status,
7448
+ durationMs: duration,
7449
+ });
7450
+ return {
7451
+ ...response,
7452
+ headers: { ...response.headers, 'x-cache': 'MISS' },
7453
+ };
7454
+ }
7455
+ catch (error) {
7456
+ // On error, return stale cache if available
7457
+ if (cached) {
7458
+ const duration = Date.now() - startTime;
7459
+ log$3.warn('CACHE STALE (network error):', {
7460
+ url,
7461
+ cacheKey,
7462
+ error: error instanceof Error ? error.message : 'Unknown error',
7463
+ durationMs: duration,
7464
+ });
7465
+ return {
7466
+ data: cached.data,
7467
+ status: 200,
7468
+ headers: { 'x-cache': 'STALE' },
7469
+ };
7470
+ }
7471
+ log$3.error('Network error with no cache fallback:', {
7472
+ url,
7473
+ error: error instanceof Error ? error.message : error,
7474
+ });
7475
+ throw error;
7476
+ }
7477
+ }
7478
+ async post(url, data, config) {
7479
+ log$3.info('POST request:', { url });
7480
+ const response = await this.http.post(url, data, config);
7481
+ await this.invalidateRelated(url, 'POST');
7482
+ return response;
7483
+ }
7484
+ async put(url, data, config) {
7485
+ log$3.info('PUT request:', { url });
7486
+ const response = await this.http.put(url, data, config);
7487
+ await this.invalidateRelated(url, 'PUT');
7488
+ return response;
7489
+ }
7490
+ async patch(url, data, config) {
7491
+ log$3.info('PATCH request:', { url });
7492
+ const response = await this.http.patch(url, data, config);
7493
+ await this.invalidateRelated(url, 'PATCH');
7494
+ return response;
7495
+ }
7496
+ async delete(url, config) {
7497
+ log$3.info('DELETE request:', { url });
7498
+ const response = await this.http.delete(url, config);
7499
+ await this.invalidateRelated(url, 'DELETE');
7500
+ return response;
7501
+ }
7502
+ setAuthToken(token) {
7503
+ log$3.debug('Auth token updated:', { hasToken: !!token });
7504
+ this.authToken = token;
7505
+ this.http.setAuthToken(token);
7506
+ }
7507
+ getAuthToken() {
7508
+ return this.authToken;
7509
+ }
7510
+ async invalidateRelated(url, method) {
7511
+ const patterns = this.keyGenerator.getInvalidationPatterns(url, method);
7512
+ if (patterns.length === 0) {
7513
+ log$3.debug('No cache patterns to invalidate:', { url, method });
7514
+ return;
7515
+ }
7516
+ log$3.info('Invalidating cache patterns:', { url, method, patterns });
7517
+ for (const pattern of patterns) {
7518
+ try {
7519
+ await this.cache.invalidate(pattern);
7520
+ log$3.debug('Cache pattern invalidated:', { pattern });
7521
+ }
7522
+ catch (error) {
7523
+ log$3.error('Failed to invalidate pattern:', {
7524
+ pattern,
7525
+ error: error instanceof Error ? error.message : error,
7526
+ });
7527
+ }
7528
+ }
7529
+ }
7530
+ destroy() {
7531
+ log$3.debug('CachingHttpDecorator destroyed');
7532
+ this.networkSubscription?.unsubscribe();
7533
+ }
7534
+ }
7535
+
7536
+ const log$2 = createPrefixedLogger('HTTP-MTLS');
7077
7537
  class AxiosHttpAdapter {
7078
7538
  constructor(config) {
7079
7539
  this.authToken = null;
@@ -7091,11 +7551,11 @@ class AxiosHttpAdapter {
7091
7551
  }
7092
7552
  setMTLSAdapter(adapter) {
7093
7553
  this.mtlsAdapter = adapter;
7094
- log$1.debug('mTLS adapter configured:', !!adapter);
7554
+ log$2.debug('mTLS adapter configured:', !!adapter);
7095
7555
  }
7096
7556
  setAuthStrategy(strategy) {
7097
7557
  this.authStrategy = strategy;
7098
- log$1.debug('Auth strategy configured:', !!strategy);
7558
+ log$2.debug('Auth strategy configured:', !!strategy);
7099
7559
  }
7100
7560
  async shouldUseMTLS(url, method) {
7101
7561
  if (!this.mtlsAdapter) {
@@ -7103,7 +7563,7 @@ class AxiosHttpAdapter {
7103
7563
  }
7104
7564
  if (this.authStrategy) {
7105
7565
  const config = await this.authStrategy.determineAuthConfig(url, method);
7106
- log$1.debug(`Auth config for ${method} ${url}:`, config);
7566
+ log$2.debug(`Auth config for ${method} ${url}:`, config);
7107
7567
  return config.mode === 'mtls';
7108
7568
  }
7109
7569
  // Fallback: use mTLS for mf1/mf2 endpoints if no strategy
@@ -7120,10 +7580,10 @@ class AxiosHttpAdapter {
7120
7580
  };
7121
7581
  if (this.authToken) {
7122
7582
  headers['Authorization'] = `Bearer ${this.authToken}`;
7123
- log$1.debug('JWT token present for mTLS request');
7583
+ log$2.debug('JWT token present for mTLS request');
7124
7584
  }
7125
7585
  else {
7126
- log$1.warn('No JWT token for mTLS request');
7586
+ log$2.warn('No JWT token for mTLS request');
7127
7587
  }
7128
7588
  const mtlsConfig = {
7129
7589
  url: fullUrl,
@@ -7132,15 +7592,15 @@ class AxiosHttpAdapter {
7132
7592
  data,
7133
7593
  timeout: config?.timeout,
7134
7594
  };
7135
- log$1.debug(`mTLS ${method} ${fullUrl}`);
7595
+ log$2.debug(`mTLS ${method} ${fullUrl}`);
7136
7596
  if (data) {
7137
- log$1.debug('Request body:', data);
7597
+ log$2.debug('Request body:', data);
7138
7598
  }
7139
7599
  try {
7140
7600
  const response = await this.mtlsAdapter.request(mtlsConfig);
7141
- log$1.debug(`mTLS Response ${response.status} from ${fullUrl}`);
7601
+ log$2.debug(`mTLS Response ${response.status} from ${fullUrl}`);
7142
7602
  if (response.data) {
7143
- log$1.debug('Response body:', response.data);
7603
+ log$2.debug('Response body:', response.data);
7144
7604
  }
7145
7605
  return {
7146
7606
  data: response.data,
@@ -7149,11 +7609,11 @@ class AxiosHttpAdapter {
7149
7609
  };
7150
7610
  }
7151
7611
  catch (error) {
7152
- log$1.error(`mTLS Response error from ${fullUrl}:`, error);
7612
+ log$2.error(`mTLS Response error from ${fullUrl}:`, error);
7153
7613
  if (error && typeof error === 'object' && 'response' in error) {
7154
7614
  const axiosError = error;
7155
7615
  if (axiosError.response?.data) {
7156
- log$1.error('Response body:', axiosError.response.data);
7616
+ log$2.error('Response body:', axiosError.response.data);
7157
7617
  }
7158
7618
  }
7159
7619
  throw error;
@@ -7170,30 +7630,30 @@ class AxiosHttpAdapter {
7170
7630
  config.headers.Authorization = `Bearer ${this.authToken}`;
7171
7631
  }
7172
7632
  const method = config.method?.toUpperCase() ?? 'UNKNOWN';
7173
- log$1.debug(`→ ${method} ${config.url}`);
7633
+ log$2.debug(`→ ${method} ${config.url}`);
7174
7634
  if (config.params && Object.keys(config.params).length > 0) {
7175
- log$1.debug('Request params:', config.params);
7635
+ log$2.debug('Request params:', config.params);
7176
7636
  }
7177
7637
  if (config.data) {
7178
- log$1.debug('Request body:', config.data);
7638
+ log$2.debug('Request body:', config.data);
7179
7639
  }
7180
7640
  return config;
7181
7641
  }, (error) => {
7182
- log$1.error('Request error:', error);
7642
+ log$2.error('Request error:', error);
7183
7643
  return Promise.reject(error);
7184
7644
  });
7185
7645
  this.client.interceptors.response.use((response) => {
7186
7646
  const method = response.config.method?.toUpperCase() ?? 'UNKNOWN';
7187
- log$1.debug(`← ${method} ${response.status} ${response.config.url}`);
7647
+ log$2.debug(`← ${method} ${response.status} ${response.config.url}`);
7188
7648
  if (response.data) {
7189
- log$1.debug('Response body:', response.data);
7649
+ log$2.debug('Response body:', response.data);
7190
7650
  }
7191
7651
  return response;
7192
7652
  }, (error) => {
7193
7653
  const method = error.config?.method?.toUpperCase() ?? 'UNKNOWN';
7194
- log$1.error(`← ${method} ${error.response?.status ?? 'ERR'} ${error.config?.url ?? 'unknown'}`);
7654
+ log$2.error(`← ${method} ${error.response?.status ?? 'ERR'} ${error.config?.url ?? 'unknown'}`);
7195
7655
  if (error.response?.data) {
7196
- log$1.error('Response body:', error.response.data);
7656
+ log$2.error('Response body:', error.response.data);
7197
7657
  }
7198
7658
  return Promise.reject(error);
7199
7659
  });
@@ -7316,6 +7776,7 @@ class SDKFactory {
7316
7776
  baseUrl: config.baseUrl,
7317
7777
  timeout: config.timeout,
7318
7778
  });
7779
+ container.register(DI_TOKENS.BASE_HTTP_PORT, httpAdapter);
7319
7780
  container.register(DI_TOKENS.HTTP_PORT, httpAdapter);
7320
7781
  container.registerFactory(DI_TOKENS.RECEIPT_REPOSITORY, () => {
7321
7782
  const http = container.get(DI_TOKENS.HTTP_PORT);
@@ -7363,6 +7824,23 @@ class SDKFactory {
7363
7824
  });
7364
7825
  return container;
7365
7826
  }
7827
+ static registerCacheServices(container, cache, network) {
7828
+ container.register(DI_TOKENS.CACHE_PORT, cache);
7829
+ if (network) {
7830
+ container.register(DI_TOKENS.NETWORK_PORT, network);
7831
+ }
7832
+ const keyGenerator = new CacheKeyGenerator();
7833
+ container.register(DI_TOKENS.CACHE_KEY_GENERATOR, keyGenerator);
7834
+ const baseHttp = container.get(DI_TOKENS.BASE_HTTP_PORT);
7835
+ const cachingHttp = new CachingHttpDecorator(baseHttp, cache, keyGenerator, network);
7836
+ container.register(DI_TOKENS.HTTP_PORT, cachingHttp);
7837
+ }
7838
+ static getCacheKeyGenerator(container) {
7839
+ if (container.has(DI_TOKENS.CACHE_KEY_GENERATOR)) {
7840
+ return container.get(DI_TOKENS.CACHE_KEY_GENERATOR);
7841
+ }
7842
+ return undefined;
7843
+ }
7366
7844
  static registerAuthServices(container, secureStorage, config) {
7367
7845
  const tokenStorage = new TokenStorageAdapter(secureStorage);
7368
7846
  container.register(DI_TOKENS.TOKEN_STORAGE_PORT, tokenStorage);
@@ -7400,6 +7878,7 @@ class SDKFactory {
7400
7878
  }
7401
7879
  }
7402
7880
 
7881
+ const log$1 = createPrefixedLogger('SDK');
7403
7882
  class ACubeSDK {
7404
7883
  constructor(config, customAdapters, events = {}) {
7405
7884
  this.events = events;
@@ -7413,14 +7892,27 @@ class ACubeSDK {
7413
7892
  }
7414
7893
  async initialize() {
7415
7894
  if (this.isInitialized) {
7895
+ log$1.debug('SDK already initialized, skipping');
7416
7896
  return;
7417
7897
  }
7898
+ log$1.info('Initializing SDK', {
7899
+ apiUrl: this.config.getApiUrl(),
7900
+ authUrl: this.config.getAuthUrl(),
7901
+ debugEnabled: this.config.isDebugEnabled(),
7902
+ });
7418
7903
  try {
7419
7904
  if (!this.adapters) {
7905
+ log$1.debug('Loading platform adapters');
7420
7906
  const mtlsConfig = createACubeMTLSConfig(this.config.getApiUrl(), this.config.getTimeout(), true);
7421
7907
  this.adapters = loadPlatformAdapters({
7422
7908
  mtlsConfig,
7423
7909
  });
7910
+ log$1.info('Platform adapters loaded', {
7911
+ hasCache: !!this.adapters.cache,
7912
+ hasNetworkMonitor: !!this.adapters.networkMonitor,
7913
+ hasMtls: !!this.adapters.mtls,
7914
+ hasSecureStorage: !!this.adapters.secureStorage,
7915
+ });
7424
7916
  }
7425
7917
  const factoryConfig = {
7426
7918
  baseUrl: this.config.getApiUrl(),
@@ -7428,11 +7920,25 @@ class ACubeSDK {
7428
7920
  timeout: this.config.getTimeout(),
7429
7921
  debugEnabled: this.config.isDebugEnabled(),
7430
7922
  };
7923
+ log$1.debug('Creating DI container');
7431
7924
  this.container = SDKFactory.createContainer(factoryConfig);
7925
+ log$1.debug('Registering auth services');
7432
7926
  SDKFactory.registerAuthServices(this.container, this.adapters.secureStorage, factoryConfig);
7927
+ if (this.adapters.cache) {
7928
+ log$1.info('Registering cache services', {
7929
+ hasNetworkMonitor: !!this.adapters.networkMonitor,
7930
+ });
7931
+ SDKFactory.registerCacheServices(this.container, this.adapters.cache, this.adapters.networkMonitor);
7932
+ }
7933
+ else {
7934
+ log$1.debug('No cache adapter available, caching disabled');
7935
+ }
7936
+ log$1.debug('Initializing certificate service');
7433
7937
  this.certificateService = new CertificateService(this.adapters.secureStorage);
7434
7938
  const tokenStorage = this.container.get(DI_TOKENS.TOKEN_STORAGE_PORT);
7435
7939
  const httpPort = this.container.get(DI_TOKENS.HTTP_PORT);
7940
+ const baseHttpPort = this.container.get(DI_TOKENS.BASE_HTTP_PORT);
7941
+ log$1.debug('Initializing authentication service');
7436
7942
  this.authService = new AuthenticationService(httpPort, tokenStorage, {
7437
7943
  authUrl: this.config.getAuthUrl(),
7438
7944
  timeout: this.config.getTimeout(),
@@ -7442,6 +7948,7 @@ class ACubeSDK {
7442
7948
  this.events.onAuthError?.(new ACubeSDKError('AUTH_ERROR', error.message, error));
7443
7949
  },
7444
7950
  });
7951
+ log$1.debug('Initializing offline manager');
7445
7952
  const queueEvents = {
7446
7953
  onOperationAdded: (operation) => {
7447
7954
  this.events.onOfflineOperationAdded?.(operation.id);
@@ -7460,9 +7967,7 @@ class ACubeSDK {
7460
7967
  this.currentOnlineState = online;
7461
7968
  this.events.onNetworkStatusChanged?.(online);
7462
7969
  if (online && this.offlineManager) {
7463
- this.offlineManager.sync().catch(() => {
7464
- // Sync errors are handled internally by OfflineManager
7465
- });
7970
+ this.offlineManager.sync().catch(() => { });
7466
7971
  }
7467
7972
  });
7468
7973
  if (await this.authService.isAuthenticated()) {
@@ -7471,13 +7976,13 @@ class ACubeSDK {
7471
7976
  httpPort.setAuthToken(token);
7472
7977
  }
7473
7978
  }
7474
- // Connect mTLS adapter to HTTP port for /mf1 and /mf2 requests
7475
- if (this.adapters?.mtls && 'setMTLSAdapter' in httpPort) {
7476
- const httpWithMtls = httpPort;
7979
+ if (this.adapters?.mtls && 'setMTLSAdapter' in baseHttpPort) {
7980
+ log$1.debug('Connecting mTLS adapter to HTTP port');
7981
+ const httpWithMtls = baseHttpPort;
7477
7982
  httpWithMtls.setMTLSAdapter(this.adapters.mtls);
7478
7983
  }
7479
- // Create and connect AuthStrategy
7480
- if ('setAuthStrategy' in httpPort) {
7984
+ if ('setAuthStrategy' in baseHttpPort) {
7985
+ log$1.debug('Configuring auth strategy');
7481
7986
  const jwtHandler = new JwtAuthHandler(tokenStorage);
7482
7987
  const certificatePort = this.certificateService
7483
7988
  ? {
@@ -7508,7 +8013,7 @@ class ACubeSDK {
7508
8013
  },
7509
8014
  };
7510
8015
  const authStrategy = new AuthStrategy(jwtHandler, mtlsHandler, userProvider, this.adapters?.mtls || null);
7511
- const httpWithStrategy = httpPort;
8016
+ const httpWithStrategy = baseHttpPort;
7512
8017
  httpWithStrategy.setAuthStrategy(authStrategy);
7513
8018
  }
7514
8019
  if (this.adapters?.mtls && this.certificateService) {
@@ -7525,13 +8030,22 @@ class ACubeSDK {
7525
8030
  }
7526
8031
  }
7527
8032
  }
7528
- catch {
7529
- // Certificate auto-configuration failed, will retry on demand
8033
+ catch (certError) {
8034
+ log$1.warn('Certificate auto-configuration failed, will retry on demand', {
8035
+ error: certError instanceof Error ? certError.message : certError,
8036
+ });
7530
8037
  }
7531
8038
  }
7532
8039
  this.isInitialized = true;
8040
+ log$1.info('SDK initialized successfully', {
8041
+ hasCache: !!this.adapters.cache,
8042
+ hasMtls: !!this.adapters.mtls,
8043
+ });
7533
8044
  }
7534
8045
  catch (error) {
8046
+ log$1.error('SDK initialization failed', {
8047
+ error: error instanceof Error ? error.message : error,
8048
+ });
7535
8049
  throw new ACubeSDKError('SDK_INITIALIZATION_ERROR', `Failed to initialize SDK: ${error instanceof Error ? error.message : 'Unknown error'}`, error);
7536
8050
  }
7537
8051
  }
@@ -7585,15 +8099,19 @@ class ACubeSDK {
7585
8099
  }
7586
8100
  async login(credentials) {
7587
8101
  this.ensureInitialized();
8102
+ log$1.info('Login attempt', { email: credentials.email });
7588
8103
  const user = await this.authService.login(credentials);
8104
+ log$1.info('Login successful', { roles: user.roles });
7589
8105
  const token = await this.authService.getAccessToken();
7590
8106
  if (token) {
7591
8107
  this.httpPort.setAuthToken(token);
8108
+ log$1.debug('Auth token set on HTTP port');
7592
8109
  }
7593
8110
  return user;
7594
8111
  }
7595
8112
  async logout() {
7596
8113
  this.ensureInitialized();
8114
+ log$1.info('Logout');
7597
8115
  await this.authService.logout();
7598
8116
  this.httpPort.setAuthToken(null);
7599
8117
  }
@@ -7674,12 +8192,7 @@ class ACubeSDK {
7674
8192
  async clearCertificate() {
7675
8193
  this.ensureInitialized();
7676
8194
  if (this.adapters?.mtls) {
7677
- try {
7678
- await this.adapters.mtls.removeCertificate();
7679
- }
7680
- catch {
7681
- // No certificate to remove
7682
- }
8195
+ await this.adapters.mtls.removeCertificate().catch(() => { });
7683
8196
  }
7684
8197
  if (this.certificateService) {
7685
8198
  await this.certificateService.clearCertificate();
@@ -8014,17 +8527,16 @@ class NotificationService {
8014
8527
  }
8015
8528
 
8016
8529
  const DEFAULT_CONFIG = {
8017
- cacheKeyPrefix: 'acube_telemetry_',
8018
- cacheTtlMs: 300000,
8530
+ pollIntervalMs: 60000, // 1 minute default for telemetry
8019
8531
  };
8020
8532
  class TelemetryService {
8021
8533
  get state$() {
8022
8534
  return this.stateSubject.asObservable();
8023
8535
  }
8024
- constructor(repository, storagePort, networkPort, config) {
8536
+ constructor(repository, networkPort, config, events) {
8025
8537
  this.repository = repository;
8026
- this.storagePort = storagePort;
8027
8538
  this.networkPort = networkPort;
8539
+ this.events = events;
8028
8540
  this.stateSubject = new BehaviorSubject({
8029
8541
  data: null,
8030
8542
  isCached: false,
@@ -8032,29 +8544,69 @@ class TelemetryService {
8032
8544
  lastFetchedAt: null,
8033
8545
  });
8034
8546
  this.destroy$ = new Subject();
8035
- this.isOnline = true;
8036
8547
  this.config = { ...DEFAULT_CONFIG, ...config };
8037
8548
  this.setupNetworkMonitoring();
8038
8549
  }
8039
8550
  setupNetworkMonitoring() {
8040
- this.networkPort.online$.pipe(takeUntil(this.destroy$)).subscribe((online) => {
8041
- this.isOnline = online;
8551
+ this.networkSubscription = this.networkPort.online$
8552
+ .pipe(startWith(true), pairwise(), filter(([wasOnline, isNowOnline]) => !wasOnline && isNowOnline), takeUntil(this.destroy$))
8553
+ .subscribe(() => {
8554
+ this.triggerSync();
8042
8555
  });
8043
8556
  }
8557
+ startPolling(pemId) {
8558
+ if (this.pollingSubscription) {
8559
+ // If already polling for same pemId, do nothing
8560
+ if (this.currentPemId === pemId) {
8561
+ return;
8562
+ }
8563
+ // If polling for different pemId, stop and restart
8564
+ this.stopPolling();
8565
+ }
8566
+ this.currentPemId = pemId;
8567
+ this.pollingSubscription = interval(this.config.pollIntervalMs)
8568
+ .pipe(startWith(0), switchMap(() => this.fetchTelemetry()), takeUntil(this.destroy$))
8569
+ .subscribe();
8570
+ }
8571
+ stopPolling() {
8572
+ this.pollingSubscription?.unsubscribe();
8573
+ this.pollingSubscription = undefined;
8574
+ this.currentPemId = undefined;
8575
+ }
8576
+ async triggerSync() {
8577
+ if (!this.currentPemId) {
8578
+ return this.stateSubject.value;
8579
+ }
8580
+ return this.fetchTelemetry();
8581
+ }
8044
8582
  async getTelemetry(pemId) {
8045
- return this.fetchWithFallback(pemId);
8583
+ // Start polling if not already polling for this pemId
8584
+ if (this.currentPemId !== pemId) {
8585
+ this.startPolling(pemId);
8586
+ }
8587
+ return this.stateSubject.value;
8046
8588
  }
8047
8589
  async refreshTelemetry(pemId) {
8048
- if (!this.isOnline) {
8590
+ // Update pemId and fetch immediately
8591
+ if (this.currentPemId !== pemId) {
8592
+ this.startPolling(pemId);
8593
+ }
8594
+ else {
8595
+ return this.fetchTelemetry();
8596
+ }
8597
+ return this.stateSubject.value;
8598
+ }
8599
+ async fetchTelemetry() {
8600
+ if (!this.currentPemId) {
8049
8601
  return this.stateSubject.value;
8050
8602
  }
8051
8603
  this.stateSubject.next({
8052
8604
  ...this.stateSubject.value,
8053
8605
  isLoading: true,
8606
+ error: undefined,
8054
8607
  });
8055
8608
  try {
8056
- const data = await this.repository.getTelemetry(pemId);
8057
- await this.cacheData(pemId, data);
8609
+ const data = await this.repository.getTelemetry(this.currentPemId);
8058
8610
  const newState = {
8059
8611
  data,
8060
8612
  isCached: false,
@@ -8062,6 +8614,7 @@ class TelemetryService {
8062
8614
  lastFetchedAt: Date.now(),
8063
8615
  };
8064
8616
  this.stateSubject.next(newState);
8617
+ this.events?.onTelemetryUpdate?.(data);
8065
8618
  return newState;
8066
8619
  }
8067
8620
  catch (error) {
@@ -8072,89 +8625,25 @@ class TelemetryService {
8072
8625
  error: errorMessage,
8073
8626
  };
8074
8627
  this.stateSubject.next(newState);
8628
+ if (error instanceof Error) {
8629
+ this.events?.onSyncError?.(error);
8630
+ }
8075
8631
  return newState;
8076
8632
  }
8077
8633
  }
8078
- async fetchWithFallback(pemId) {
8634
+ clearTelemetry() {
8079
8635
  this.stateSubject.next({
8080
- ...this.stateSubject.value,
8081
- isLoading: true,
8082
- });
8083
- if (this.isOnline) {
8084
- try {
8085
- const data = await this.repository.getTelemetry(pemId);
8086
- await this.cacheData(pemId, data);
8087
- const newState = {
8088
- data,
8089
- isCached: false,
8090
- isLoading: false,
8091
- lastFetchedAt: Date.now(),
8092
- };
8093
- this.stateSubject.next(newState);
8094
- return newState;
8095
- }
8096
- catch (error) {
8097
- return this.loadFromCache(pemId, error);
8098
- }
8099
- }
8100
- return this.loadFromCache(pemId);
8101
- }
8102
- async loadFromCache(pemId, originalError) {
8103
- const cached = await this.getCachedData(pemId);
8104
- if (cached && this.isCacheValid(cached.timestamp)) {
8105
- const newState = {
8106
- data: cached.data,
8107
- isCached: true,
8108
- isLoading: false,
8109
- lastFetchedAt: cached.timestamp,
8110
- };
8111
- this.stateSubject.next(newState);
8112
- return newState;
8113
- }
8114
- const errorMessage = originalError instanceof Error ? originalError.message : 'No cached data available';
8115
- const newState = {
8116
8636
  data: null,
8117
8637
  isCached: false,
8118
8638
  isLoading: false,
8119
8639
  lastFetchedAt: null,
8120
- error: errorMessage,
8121
- };
8122
- this.stateSubject.next(newState);
8123
- return newState;
8124
- }
8125
- async cacheData(pemId, data) {
8126
- const cacheKey = this.getCacheKey(pemId);
8127
- const cached = {
8128
- data,
8129
- timestamp: Date.now(),
8130
- };
8131
- await this.storagePort.set(cacheKey, JSON.stringify(cached));
8132
- }
8133
- async getCachedData(pemId) {
8134
- const cacheKey = this.getCacheKey(pemId);
8135
- const stored = await this.storagePort.get(cacheKey);
8136
- if (!stored) {
8137
- return null;
8138
- }
8139
- try {
8140
- return JSON.parse(stored);
8141
- }
8142
- catch {
8143
- return null;
8144
- }
8145
- }
8146
- isCacheValid(timestamp) {
8147
- return Date.now() - timestamp < this.config.cacheTtlMs;
8148
- }
8149
- getCacheKey(pemId) {
8150
- return `${this.config.cacheKeyPrefix}${pemId}`;
8151
- }
8152
- clearCache(pemId) {
8153
- return this.storagePort.remove(this.getCacheKey(pemId));
8640
+ });
8154
8641
  }
8155
8642
  destroy() {
8156
8643
  this.destroy$.next();
8157
8644
  this.destroy$.complete();
8645
+ this.pollingSubscription?.unsubscribe();
8646
+ this.networkSubscription?.unsubscribe();
8158
8647
  }
8159
8648
  }
8160
8649
 
@@ -8164,7 +8653,7 @@ class TelemetryService {
8164
8653
  * Provides:
8165
8654
  * - Single initialization point
8166
8655
  * - Observable app state (NORMAL, WARNING, BLOCKED, OFFLINE)
8167
- * - Observable telemetry state
8656
+ * - Observable telemetry state with polling
8168
8657
  * - Simplified services for product use
8169
8658
  *
8170
8659
  * @example
@@ -8173,6 +8662,7 @@ class TelemetryService {
8173
8662
  * SDKManager.configure({
8174
8663
  * environment: 'sandbox',
8175
8664
  * notificationPollIntervalMs: 30000,
8665
+ * telemetryPollIntervalMs: 60000,
8176
8666
  * });
8177
8667
  *
8178
8668
  * // Initialize
@@ -8184,6 +8674,14 @@ class TelemetryService {
8184
8674
  * console.log('App mode:', state.mode);
8185
8675
  * });
8186
8676
  *
8677
+ * // Start telemetry polling for a specific PEM
8678
+ * manager.startTelemetryPolling('PEM-123');
8679
+ *
8680
+ * // Subscribe to telemetry updates
8681
+ * manager.telemetry$.subscribe(telemetry => {
8682
+ * console.log('Telemetry:', telemetry);
8683
+ * });
8684
+ *
8187
8685
  * // Cleanup
8188
8686
  * SDKManager.destroy();
8189
8687
  * ```
@@ -8239,43 +8737,34 @@ class SDKManager {
8239
8737
  * Must be called after configure()
8240
8738
  */
8241
8739
  async initialize() {
8242
- if (this.isInitialized) {
8740
+ if (this.isInitialized)
8243
8741
  return;
8244
- }
8245
- // Create and initialize SDK
8246
8742
  this.sdk = new ACubeSDK(this.config, this.adapters, this.events);
8247
8743
  await this.sdk.initialize();
8248
- // Get required adapters
8249
8744
  const adaptersRef = this.sdk.getAdapters();
8250
8745
  if (!adaptersRef) {
8251
8746
  throw new ACubeSDKError('ADAPTERS_NOT_AVAILABLE', 'Platform adapters not available');
8252
8747
  }
8253
8748
  const networkPort = adaptersRef.networkMonitor;
8254
- const storagePort = adaptersRef.storage;
8255
- // Get repositories from SDK
8256
8749
  const notificationRepo = this.sdk.notifications;
8257
8750
  const telemetryRepo = this.sdk.telemetry;
8258
- // Create NotificationService
8259
8751
  this.notificationService = new NotificationService(notificationRepo, networkPort, {
8260
8752
  pollIntervalMs: this.config.notificationPollIntervalMs ?? 30000,
8261
8753
  defaultPageSize: this.config.notificationPageSize ?? 30,
8262
8754
  });
8263
- // Create TelemetryService
8264
- this.telemetryService = new TelemetryService(telemetryRepo, storagePort, networkPort, {
8265
- cacheTtlMs: this.config.telemetryCacheTtlMs ?? 300000,
8755
+ this.telemetryService = new TelemetryService(telemetryRepo, networkPort, {
8756
+ pollIntervalMs: this.config.telemetryPollIntervalMs ?? 60000,
8266
8757
  });
8267
- // Create AppStateService
8268
8758
  this.appStateService = new AppStateService(this.notificationService.notifications$, networkPort);
8269
- // Subscribe to state changes for events
8270
8759
  if (this.events?.onAppStateChanged) {
8271
8760
  this.appStateService.state$.subscribe(this.events.onAppStateChanged);
8272
8761
  }
8273
8762
  if (this.events?.onTelemetryStateChanged) {
8274
8763
  this.telemetryService.state$.subscribe(this.events.onTelemetryStateChanged);
8275
8764
  }
8276
- // Start notification polling
8277
- this.notificationService.startPolling();
8278
8765
  this.isInitialized = true;
8766
+ this.notificationService.startPolling();
8767
+ this.startTelemetryPollingAuto();
8279
8768
  }
8280
8769
  /**
8281
8770
  * Observable stream of app state
@@ -8308,12 +8797,51 @@ class SDKManager {
8308
8797
  return this.appStateService.warning$;
8309
8798
  }
8310
8799
  /**
8311
- * Observable stream of telemetry state
8800
+ * Observable stream of telemetry state (data, isLoading, isCached, error)
8312
8801
  */
8313
8802
  get telemetryState$() {
8314
8803
  this.ensureInitialized();
8315
8804
  return this.telemetryService.state$;
8316
8805
  }
8806
+ /**
8807
+ * Get the pemId from the installed certificate
8808
+ */
8809
+ async getPemId() {
8810
+ this.ensureInitialized();
8811
+ try {
8812
+ const certInfo = await this.sdk.getCertificatesInfo();
8813
+ return certInfo?.pemId ?? null;
8814
+ }
8815
+ catch {
8816
+ return null;
8817
+ }
8818
+ }
8819
+ /**
8820
+ * Start polling telemetry using the pemId from installed certificate
8821
+ * Returns the pemId if successful, null if no certificate is installed
8822
+ */
8823
+ async startTelemetryPollingAuto() {
8824
+ this.ensureInitialized();
8825
+ const pemId = await this.getPemId();
8826
+ if (pemId) {
8827
+ this.telemetryService.startPolling(pemId);
8828
+ }
8829
+ return pemId;
8830
+ }
8831
+ /**
8832
+ * Start polling telemetry for a specific PEM
8833
+ */
8834
+ startTelemetryPolling(pemId) {
8835
+ this.ensureInitialized();
8836
+ this.telemetryService.startPolling(pemId);
8837
+ }
8838
+ /**
8839
+ * Stop telemetry polling
8840
+ */
8841
+ stopTelemetryPolling() {
8842
+ this.ensureInitialized();
8843
+ this.telemetryService.stopPolling();
8844
+ }
8317
8845
  /**
8318
8846
  * Get simplified services for product use
8319
8847
  */
@@ -8322,7 +8850,6 @@ class SDKManager {
8322
8850
  const sdk = this.sdk;
8323
8851
  const telemetryService = this.telemetryService;
8324
8852
  return {
8325
- // Business repositories
8326
8853
  receipts: sdk.receipts,
8327
8854
  merchants: sdk.merchants,
8328
8855
  cashiers: sdk.cashiers,
@@ -8332,22 +8859,23 @@ class SDKManager {
8332
8859
  pems: sdk.pems,
8333
8860
  dailyReports: sdk.dailyReports,
8334
8861
  journals: sdk.journals,
8335
- // Simplified telemetry operations
8336
8862
  telemetry: {
8863
+ startPollingAuto: () => this.startTelemetryPollingAuto(),
8864
+ startPolling: (pemId) => telemetryService.startPolling(pemId),
8865
+ stopPolling: () => telemetryService.stopPolling(),
8337
8866
  getTelemetry: (pemId) => telemetryService.getTelemetry(pemId),
8338
8867
  refreshTelemetry: (pemId) => telemetryService.refreshTelemetry(pemId),
8339
- clearCache: (pemId) => telemetryService.clearCache(pemId),
8868
+ triggerSync: () => telemetryService.triggerSync(),
8869
+ clearTelemetry: () => telemetryService.clearTelemetry(),
8870
+ getPemId: () => this.getPemId(),
8340
8871
  },
8341
- // Auth operations
8342
8872
  login: (credentials) => sdk.login(credentials),
8343
8873
  logout: () => sdk.logout(),
8344
8874
  getCurrentUser: () => sdk.getCurrentUser(),
8345
8875
  isAuthenticated: () => sdk.isAuthenticated(),
8346
- // Certificate operations
8347
8876
  storeCertificate: (certificate, privateKey, options) => sdk.storeCertificate(certificate, privateKey, options),
8348
8877
  hasCertificate: () => sdk.hasCertificate(),
8349
8878
  clearCertificate: () => sdk.clearCertificate(),
8350
- // Network status
8351
8879
  isOnline: () => sdk.isOnline(),
8352
8880
  };
8353
8881
  }
@@ -8359,12 +8887,11 @@ class SDKManager {
8359
8887
  await this.notificationService.triggerSync();
8360
8888
  }
8361
8889
  /**
8362
- * Get telemetry for a specific PEM
8890
+ * Manually trigger a telemetry sync
8363
8891
  */
8364
- async getTelemetry(pemId) {
8892
+ async syncTelemetry() {
8365
8893
  this.ensureInitialized();
8366
- const state = await this.telemetryService.getTelemetry(pemId);
8367
- return state.data;
8894
+ return this.telemetryService.triggerSync();
8368
8895
  }
8369
8896
  /**
8370
8897
  * Check if the manager is initialized