@a-cube-io/ereceipts-js-sdk 2.0.7 → 2.0.8

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.
@@ -1,5 +1,5 @@
1
- import axios from 'axios';
2
1
  import * as z from 'zod';
2
+ import axios from 'axios';
3
3
 
4
4
  /******************************************************************************
5
5
  Copyright (c) Microsoft Corporation.
@@ -1838,135 +1838,440 @@ function extractRoles(jwtRoles) {
1838
1838
  return allRoles;
1839
1839
  }
1840
1840
 
1841
- class AuthenticationService {
1842
- get user$() {
1843
- return this.userSubject.asObservable();
1844
- }
1845
- get isAuthenticated$() {
1846
- return this.userSubject.pipe(map((user) => user !== null), distinctUntilChanged(), takeUntil(this.destroy$));
1847
- }
1848
- get authState$() {
1849
- return this.authStateSubject.asObservable();
1841
+ function clearObject(input) {
1842
+ if (input === null || input === undefined || input === '') {
1843
+ return undefined;
1850
1844
  }
1851
- constructor(httpPort, tokenStorage, config, events = {}) {
1852
- this.httpPort = httpPort;
1853
- this.tokenStorage = tokenStorage;
1854
- this.config = config;
1855
- this.events = events;
1856
- this.userSubject = new BehaviorSubject(null);
1857
- this.authStateSubject = new BehaviorSubject('idle');
1858
- this.destroy$ = new Subject();
1845
+ if (Array.isArray(input)) {
1846
+ const cleanedArray = input
1847
+ .map((item) => clearObject(item))
1848
+ .filter((item) => item !== undefined);
1849
+ return cleanedArray;
1859
1850
  }
1860
- async login(credentials) {
1861
- this.authStateSubject.next('authenticating');
1862
- try {
1863
- const response = await this.httpPort.post(`${this.config.authUrl}/login`, {
1864
- email: credentials.email,
1865
- password: credentials.password,
1866
- });
1867
- const jwtPayload = parseJwt(response.data.token);
1868
- const expiresAt = jwtPayload.exp * 1000;
1869
- await this.tokenStorage.saveAccessToken(response.data.token, expiresAt);
1870
- const user = this.createUserFromPayload(jwtPayload);
1871
- await this.tokenStorage.saveUser(user);
1872
- this.userSubject.next(user);
1873
- this.authStateSubject.next('authenticated');
1874
- this.events.onUserChanged?.(user);
1875
- return user;
1876
- }
1877
- catch (error) {
1878
- this.authStateSubject.next('error');
1879
- throw error;
1851
+ if (typeof input === 'object' && input.constructor === Object) {
1852
+ const cleaned = {};
1853
+ for (const [key, value] of Object.entries(input)) {
1854
+ const cleanedValue = clearObject(value);
1855
+ if (cleanedValue !== undefined) {
1856
+ cleaned[key] = cleanedValue;
1857
+ }
1880
1858
  }
1859
+ return cleaned;
1881
1860
  }
1882
- async logout() {
1883
- await this.tokenStorage.clearTokens();
1884
- this.userSubject.next(null);
1885
- this.authStateSubject.next('idle');
1886
- this.events.onUserChanged?.(null);
1861
+ return input;
1862
+ }
1863
+ function clearObjectShallow(obj) {
1864
+ if (!obj || typeof obj !== 'object') {
1865
+ return {};
1887
1866
  }
1888
- async getCurrentUser() {
1889
- const currentUser = this.userSubject.value;
1890
- if (currentUser) {
1891
- return currentUser;
1892
- }
1893
- const storedUser = await this.tokenStorage.getUser();
1894
- if (storedUser) {
1895
- this.userSubject.next(storedUser);
1896
- this.authStateSubject.next('authenticated');
1897
- return storedUser;
1898
- }
1899
- const token = await this.tokenStorage.getAccessToken();
1900
- if (!token) {
1901
- return null;
1902
- }
1903
- const jwtPayload = parseJwt(token);
1904
- if (isTokenExpired(jwtPayload)) {
1905
- await this.tokenStorage.clearTokens();
1906
- return null;
1867
+ const cleaned = {};
1868
+ for (const [key, value] of Object.entries(obj)) {
1869
+ if (value !== null && value !== undefined && value !== '') {
1870
+ cleaned[key] = value;
1907
1871
  }
1908
- const user = this.createUserFromPayload(jwtPayload);
1909
- await this.tokenStorage.saveUser(user);
1910
- this.userSubject.next(user);
1911
- this.authStateSubject.next('authenticated');
1912
- return user;
1913
1872
  }
1914
- async isAuthenticated() {
1915
- const token = await this.tokenStorage.getAccessToken();
1916
- if (!token) {
1917
- return false;
1918
- }
1919
- const jwtPayload = parseJwt(token);
1920
- return !isTokenExpired(jwtPayload);
1873
+ return cleaned;
1874
+ }
1875
+ function isEmpty(value) {
1876
+ return value === null || value === undefined || value === '';
1877
+ }
1878
+ function hasNonEmptyValues(obj) {
1879
+ if (!obj || typeof obj !== 'object') {
1880
+ return false;
1921
1881
  }
1922
- async getAccessToken() {
1923
- const token = await this.tokenStorage.getAccessToken();
1924
- if (!token) {
1925
- return null;
1926
- }
1927
- const jwtPayload = parseJwt(token);
1928
- if (isTokenExpired(jwtPayload)) {
1929
- await this.tokenStorage.clearTokens();
1930
- this.userSubject.next(null);
1931
- this.authStateSubject.next('idle');
1932
- this.events.onUserChanged?.(null);
1933
- return null;
1934
- }
1935
- return token;
1882
+ return Object.values(obj).some((value) => !isEmpty(value));
1883
+ }
1884
+
1885
+ /**
1886
+ * Platform detection utilities
1887
+ */
1888
+ /**
1889
+ * Detect the current platform
1890
+ */
1891
+ function detectPlatform() {
1892
+ // Check for React Native
1893
+ if (typeof global !== 'undefined' &&
1894
+ global.__DEV__ !== undefined &&
1895
+ typeof global.navigator !== 'undefined' &&
1896
+ global.navigator.product === 'ReactNative') {
1897
+ return {
1898
+ platform: 'react-native',
1899
+ isReactNative: true,
1900
+ isWeb: false,
1901
+ isNode: false,
1902
+ isExpo: checkExpo(),
1903
+ };
1936
1904
  }
1937
- createUserFromPayload(jwtPayload) {
1905
+ // Check for Web/Browser
1906
+ if (typeof window !== 'undefined' &&
1907
+ typeof window.document !== 'undefined' &&
1908
+ typeof window.navigator !== 'undefined') {
1938
1909
  return {
1939
- id: jwtPayload.uid.toString(),
1940
- email: jwtPayload.username,
1941
- username: jwtPayload.username,
1942
- roles: jwtPayload.roles,
1943
- fid: jwtPayload.fid,
1944
- pid: jwtPayload.pid,
1945
- expiresAt: jwtPayload.exp * 1000,
1910
+ platform: 'web',
1911
+ isReactNative: false,
1912
+ isWeb: true,
1913
+ isNode: false,
1914
+ isExpo: false,
1946
1915
  };
1947
1916
  }
1948
- destroy() {
1949
- this.destroy$.next();
1950
- this.destroy$.complete();
1917
+ // Check for Node.js
1918
+ if (typeof process !== 'undefined' && process.versions && process.versions.node) {
1919
+ return {
1920
+ platform: 'node',
1921
+ isReactNative: false,
1922
+ isWeb: false,
1923
+ isNode: true,
1924
+ isExpo: false,
1925
+ };
1951
1926
  }
1927
+ // Unknown platform
1928
+ return {
1929
+ platform: 'unknown',
1930
+ isReactNative: false,
1931
+ isWeb: false,
1932
+ isNode: false,
1933
+ isExpo: false,
1934
+ };
1952
1935
  }
1953
-
1954
- const CERTIFICATE_KEY = 'acube_certificate';
1955
- class CertificateService {
1956
- get certificate$() {
1957
- return this.certificateSubject.asObservable();
1936
+ /**
1937
+ * Check if running in Expo
1938
+ */
1939
+ function checkExpo() {
1940
+ try {
1941
+ return (typeof global !== 'undefined' &&
1942
+ (typeof global.Expo !== 'undefined' || typeof global.expo !== 'undefined'));
1958
1943
  }
1959
- get hasCertificate$() {
1960
- return this.certificateSubject.pipe(map((cert) => cert !== null), distinctUntilChanged());
1944
+ catch {
1945
+ return false;
1961
1946
  }
1962
- get state$() {
1963
- return this.stateSubject.asObservable();
1947
+ }
1948
+
1949
+ function getDefaultExportFromCjs (x) {
1950
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
1951
+ }
1952
+
1953
+ var picocolors_browser = {exports: {}};
1954
+
1955
+ var x=String;
1956
+ var create=function() {return {isColorSupported:false,reset:x,bold:x,dim:x,italic:x,underline:x,inverse:x,hidden:x,strikethrough:x,black:x,red:x,green:x,yellow:x,blue:x,magenta:x,cyan:x,white:x,gray:x,bgBlack:x,bgRed:x,bgGreen:x,bgYellow:x,bgBlue:x,bgMagenta:x,bgCyan:x,bgWhite:x,blackBright:x,redBright:x,greenBright:x,yellowBright:x,blueBright:x,magentaBright:x,cyanBright:x,whiteBright:x,bgBlackBright:x,bgRedBright:x,bgGreenBright:x,bgYellowBright:x,bgBlueBright:x,bgMagentaBright:x,bgCyanBright:x,bgWhiteBright:x}};
1957
+ picocolors_browser.exports=create();
1958
+ picocolors_browser.exports.createColors = create;
1959
+
1960
+ var picocolors_browserExports = picocolors_browser.exports;
1961
+ var pc = /*@__PURE__*/getDefaultExportFromCjs(picocolors_browserExports);
1962
+
1963
+ const levelColors = {
1964
+ debug: {
1965
+ prefix: pc.gray,
1966
+ message: pc.gray,
1967
+ data: pc.dim,
1968
+ },
1969
+ info: {
1970
+ prefix: pc.cyan,
1971
+ message: pc.white,
1972
+ data: pc.dim,
1973
+ },
1974
+ warn: {
1975
+ prefix: pc.yellow,
1976
+ message: pc.yellow,
1977
+ data: pc.dim,
1978
+ },
1979
+ error: {
1980
+ prefix: pc.red,
1981
+ message: pc.red,
1982
+ data: pc.dim,
1983
+ },
1984
+ };
1985
+ const levelIcons = {
1986
+ debug: '🔍',
1987
+ info: 'ℹ️ ',
1988
+ warn: '⚠️ ',
1989
+ error: '❌',
1990
+ };
1991
+ /**
1992
+ * Format data for pretty display in logs
1993
+ */
1994
+ function formatData(data, level) {
1995
+ if (data === undefined || data === null) {
1996
+ return String(data);
1964
1997
  }
1965
- constructor(secureStorage) {
1966
- this.secureStorage = secureStorage;
1967
- this.certificateSubject = new BehaviorSubject(null);
1968
- this.stateSubject = new BehaviorSubject('idle');
1969
- this.destroy$ = new Subject();
1998
+ // For primitive types, just return as string
1999
+ if (typeof data !== 'object') {
2000
+ return String(data);
2001
+ }
2002
+ // For Error objects, format nicely
2003
+ if (data instanceof Error) {
2004
+ return `${data.name}: ${data.message}${data.stack ? `\n${pc.dim(data.stack)}` : ''}`;
2005
+ }
2006
+ try {
2007
+ // Apply level-specific coloring
2008
+ const colors = levelColors[level];
2009
+ return colors.data(JSON.stringify(data, null, 2));
2010
+ }
2011
+ catch {
2012
+ // Fallback to JSON.stringify if pretty-format fails
2013
+ try {
2014
+ return JSON.stringify(data, null, 2);
2015
+ }
2016
+ catch {
2017
+ return String(data);
2018
+ }
2019
+ }
2020
+ }
2021
+ class Logger {
2022
+ constructor() {
2023
+ this.enabled = false;
2024
+ }
2025
+ setEnabled(enabled) {
2026
+ this.enabled = enabled;
2027
+ }
2028
+ isEnabled() {
2029
+ return this.enabled;
2030
+ }
2031
+ debug(prefix, message, data) {
2032
+ if (!this.enabled)
2033
+ return;
2034
+ this.log('debug', prefix, message, data);
2035
+ }
2036
+ info(prefix, message, data) {
2037
+ if (!this.enabled)
2038
+ return;
2039
+ this.log('info', prefix, message, data);
2040
+ }
2041
+ warn(prefix, message, data) {
2042
+ this.log('warn', prefix, message, data);
2043
+ }
2044
+ error(prefix, message, data) {
2045
+ this.log('error', prefix, message, data);
2046
+ }
2047
+ log(level, prefix, message, data) {
2048
+ const colors = levelColors[level];
2049
+ const icon = levelIcons[level];
2050
+ const isoTime = new Date().toISOString().split('T')[1] ?? '';
2051
+ const timestamp = pc.dim(isoTime.slice(0, 12));
2052
+ const formattedPrefix = colors.prefix(`[${prefix}]`);
2053
+ const formattedMessage = colors.message(message);
2054
+ const consoleMethod = level === 'debug'
2055
+ ? console.debug
2056
+ : level === 'info'
2057
+ ? console.info
2058
+ : level === 'warn'
2059
+ ? console.warn
2060
+ : console.error;
2061
+ const header = `${timestamp} ${icon} ${formattedPrefix} ${formattedMessage}`;
2062
+ if (data !== undefined) {
2063
+ const formattedData = formatData(data, level);
2064
+ // Check if data is an object (multi-line) or primitive (single-line)
2065
+ const isMultiLine = typeof data === 'object' && data !== null;
2066
+ if (isMultiLine) {
2067
+ consoleMethod(`${header}\n${formattedData}`);
2068
+ }
2069
+ else {
2070
+ consoleMethod(`${header}`, formattedData);
2071
+ }
2072
+ }
2073
+ else {
2074
+ consoleMethod(header);
2075
+ }
2076
+ }
2077
+ }
2078
+ const logger = new Logger();
2079
+ function createPrefixedLogger(prefix) {
2080
+ return {
2081
+ debug: (message, data) => logger.debug(prefix, message, data),
2082
+ info: (message, data) => logger.info(prefix, message, data),
2083
+ warn: (message, data) => logger.warn(prefix, message, data),
2084
+ error: (message, data) => logger.error(prefix, message, data),
2085
+ };
2086
+ }
2087
+
2088
+ /**
2089
+ * Formats a numeric string value to have exactly the specified number of decimal places.
2090
+ * E.g., "1" → "1.00", "10" → "10.00", "1.5" → "1.50"
2091
+ * Returns undefined for undefined input (preserves optional fields).
2092
+ *
2093
+ * @param value - The string value to format
2094
+ * @param decimals - Number of decimal places (default: 2)
2095
+ * @returns Formatted string or undefined if input is undefined
2096
+ */
2097
+ function formatDecimal(value, decimals = 2) {
2098
+ if (value === undefined)
2099
+ return undefined;
2100
+ const num = parseFloat(value);
2101
+ if (isNaN(num))
2102
+ return value;
2103
+ return num.toFixed(decimals);
2104
+ }
2105
+
2106
+ const log$g = createPrefixedLogger('AUTH-SERVICE');
2107
+ class AuthenticationService {
2108
+ get user$() {
2109
+ return this.userSubject.asObservable();
2110
+ }
2111
+ get isAuthenticated$() {
2112
+ return this.userSubject.pipe(map((user) => user !== null), distinctUntilChanged(), takeUntil(this.destroy$));
2113
+ }
2114
+ get authState$() {
2115
+ return this.authStateSubject.asObservable();
2116
+ }
2117
+ constructor(httpPort, tokenStorage, config, events = {}) {
2118
+ this.httpPort = httpPort;
2119
+ this.tokenStorage = tokenStorage;
2120
+ this.config = config;
2121
+ this.events = events;
2122
+ this.userSubject = new BehaviorSubject(null);
2123
+ this.authStateSubject = new BehaviorSubject('idle');
2124
+ this.destroy$ = new Subject();
2125
+ }
2126
+ async login(credentials) {
2127
+ this.authStateSubject.next('authenticating');
2128
+ log$g.info('Login attempt', {
2129
+ authUrl: this.config.authUrl,
2130
+ email: credentials.email,
2131
+ });
2132
+ try {
2133
+ const response = await this.httpPort.post(`${this.config.authUrl}/login`, {
2134
+ email: credentials.email,
2135
+ password: credentials.password,
2136
+ });
2137
+ const jwtPayload = parseJwt(response.data.token);
2138
+ const expiresAt = jwtPayload.exp * 1000;
2139
+ log$g.info('Login successful', {
2140
+ authUrl: this.config.authUrl,
2141
+ tokenPrefix: response.data.token.substring(0, 30) + '...',
2142
+ expiresAt: new Date(expiresAt).toISOString(),
2143
+ });
2144
+ await this.tokenStorage.saveAccessToken(response.data.token, expiresAt);
2145
+ const user = this.createUserFromPayload(jwtPayload);
2146
+ await this.tokenStorage.saveUser(user);
2147
+ this.userSubject.next(user);
2148
+ this.authStateSubject.next('authenticated');
2149
+ this.events.onUserChanged?.(user);
2150
+ return user;
2151
+ }
2152
+ catch (error) {
2153
+ this.authStateSubject.next('error');
2154
+ throw error;
2155
+ }
2156
+ }
2157
+ async logout() {
2158
+ await this.tokenStorage.clearTokens();
2159
+ this.userSubject.next(null);
2160
+ this.authStateSubject.next('idle');
2161
+ this.events.onUserChanged?.(null);
2162
+ }
2163
+ async getCurrentUser() {
2164
+ // Always verify token is valid before returning user
2165
+ const token = await this.tokenStorage.getAccessToken();
2166
+ if (!token) {
2167
+ // No token - clear any stale user state
2168
+ log$g.debug('getCurrentUser: No token in storage');
2169
+ if (this.userSubject.value) {
2170
+ this.userSubject.next(null);
2171
+ this.authStateSubject.next('idle');
2172
+ }
2173
+ return null;
2174
+ }
2175
+ log$g.debug('getCurrentUser: Token found', {
2176
+ tokenPrefix: token.substring(0, 30) + '...',
2177
+ tokenLength: token.length,
2178
+ });
2179
+ const jwtPayload = parseJwt(token);
2180
+ if (isTokenExpired(jwtPayload)) {
2181
+ // Token expired - clear everything
2182
+ log$g.warn('getCurrentUser: Token expired');
2183
+ await this.tokenStorage.clearTokens();
2184
+ this.userSubject.next(null);
2185
+ this.authStateSubject.next('idle');
2186
+ this.events.onUserChanged?.(null);
2187
+ return null;
2188
+ }
2189
+ // Token is valid - return cached user if available
2190
+ const currentUser = this.userSubject.value;
2191
+ if (currentUser) {
2192
+ log$g.debug('getCurrentUser: Returning cached user', {
2193
+ email: currentUser.email,
2194
+ roles: currentUser.roles,
2195
+ });
2196
+ return currentUser;
2197
+ }
2198
+ // Check stored user
2199
+ const storedUser = await this.tokenStorage.getUser();
2200
+ if (storedUser) {
2201
+ this.userSubject.next(storedUser);
2202
+ this.authStateSubject.next('authenticated');
2203
+ return storedUser;
2204
+ }
2205
+ // Create user from token
2206
+ const user = this.createUserFromPayload(jwtPayload);
2207
+ await this.tokenStorage.saveUser(user);
2208
+ this.userSubject.next(user);
2209
+ this.authStateSubject.next('authenticated');
2210
+ return user;
2211
+ }
2212
+ async isAuthenticated() {
2213
+ const token = await this.tokenStorage.getAccessToken();
2214
+ if (!token) {
2215
+ log$g.debug('isAuthenticated: No token in storage');
2216
+ return false;
2217
+ }
2218
+ const jwtPayload = parseJwt(token);
2219
+ const expired = isTokenExpired(jwtPayload);
2220
+ log$g.debug('isAuthenticated: Token check', {
2221
+ hasToken: true,
2222
+ expired,
2223
+ expiresAt: new Date(jwtPayload.exp * 1000).toISOString(),
2224
+ });
2225
+ return !expired;
2226
+ }
2227
+ async getAccessToken() {
2228
+ const token = await this.tokenStorage.getAccessToken();
2229
+ if (!token) {
2230
+ return null;
2231
+ }
2232
+ const jwtPayload = parseJwt(token);
2233
+ if (isTokenExpired(jwtPayload)) {
2234
+ await this.tokenStorage.clearTokens();
2235
+ this.userSubject.next(null);
2236
+ this.authStateSubject.next('idle');
2237
+ this.events.onUserChanged?.(null);
2238
+ return null;
2239
+ }
2240
+ return token;
2241
+ }
2242
+ createUserFromPayload(jwtPayload) {
2243
+ return {
2244
+ id: jwtPayload.uid.toString(),
2245
+ email: jwtPayload.username,
2246
+ username: jwtPayload.username,
2247
+ roles: jwtPayload.roles,
2248
+ fid: jwtPayload.fid,
2249
+ pid: jwtPayload.pid,
2250
+ expiresAt: jwtPayload.exp * 1000,
2251
+ };
2252
+ }
2253
+ destroy() {
2254
+ this.destroy$.next();
2255
+ this.destroy$.complete();
2256
+ }
2257
+ }
2258
+
2259
+ const CERTIFICATE_KEY = 'acube_certificate';
2260
+ class CertificateService {
2261
+ get certificate$() {
2262
+ return this.certificateSubject.asObservable();
2263
+ }
2264
+ get hasCertificate$() {
2265
+ return this.certificateSubject.pipe(map((cert) => cert !== null), distinctUntilChanged());
2266
+ }
2267
+ get state$() {
2268
+ return this.stateSubject.asObservable();
2269
+ }
2270
+ constructor(secureStorage) {
2271
+ this.secureStorage = secureStorage;
2272
+ this.certificateSubject = new BehaviorSubject(null);
2273
+ this.stateSubject = new BehaviorSubject('idle');
2274
+ this.destroy$ = new Subject();
1970
2275
  }
1971
2276
  async hasCertificate() {
1972
2277
  const cert = await this.getCertificate();
@@ -2057,409 +2362,680 @@ function hasAnyRole(userRoles, required) {
2057
2362
  return Object.values(userRoles).some((roles) => required.some((role) => roles.includes(role)));
2058
2363
  }
2059
2364
 
2060
- class AuthStrategy {
2061
- constructor(jwtHandler, mtlsHandler, userProvider, mtlsAdapter) {
2062
- this.jwtHandler = jwtHandler;
2063
- this.mtlsHandler = mtlsHandler;
2064
- this.userProvider = userProvider;
2065
- this.mtlsAdapter = mtlsAdapter;
2365
+ class ConfigManager {
2366
+ constructor(userConfig) {
2367
+ this.config = this.buildConfig(userConfig);
2066
2368
  }
2067
- async determineAuthConfig(url, method, explicitMode) {
2068
- if (this.isNotificationEndpoint(url) || this.isTelemetryEndpoint(url)) {
2069
- return { mode: 'mtls', usePort444: true };
2070
- }
2071
- const platform = this.detectPlatform();
2072
- const userRole = await this.getUserRole();
2073
- const isReceiptEndpoint = this.isReceiptEndpoint(url);
2074
- if (userRole === 'SUPPLIER') {
2075
- return { mode: 'jwt', usePort444: false };
2076
- }
2077
- if (userRole === 'CASHIER') {
2078
- if (!isReceiptEndpoint) {
2079
- return { mode: 'jwt', usePort444: false };
2080
- }
2081
- if (platform === 'mobile') {
2082
- return { mode: 'mtls', usePort444: true };
2083
- }
2084
- return { mode: 'jwt', usePort444: true };
2085
- }
2086
- if (userRole === 'MERCHANT') {
2087
- if (!isReceiptEndpoint) {
2088
- return { mode: 'jwt', usePort444: false };
2089
- }
2090
- if (this.isReturnableItemsEndpoint(url)) {
2091
- return { mode: 'mtls', usePort444: true };
2092
- }
2093
- if (method === 'GET') {
2094
- if (this.isDetailedReceiptEndpoint(url)) {
2095
- if (platform === 'mobile') {
2096
- return { mode: 'mtls', usePort444: true };
2097
- }
2098
- return { mode: 'jwt', usePort444: true };
2099
- }
2100
- return { mode: 'jwt', usePort444: false };
2101
- }
2102
- if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) {
2103
- if (platform === 'mobile') {
2104
- return { mode: 'mtls', usePort444: true };
2105
- }
2106
- return { mode: 'jwt', usePort444: true };
2107
- }
2108
- return { mode: 'jwt', usePort444: false };
2109
- }
2110
- if (explicitMode) {
2111
- if (userRole === 'SUPPLIER' && explicitMode === 'mtls') {
2112
- return { mode: 'jwt', usePort444: false };
2113
- }
2114
- return {
2115
- mode: explicitMode,
2116
- usePort444: explicitMode === 'mtls' || (platform === 'web' && isReceiptEndpoint),
2117
- };
2118
- }
2119
- if (platform === 'web') {
2120
- return { mode: 'jwt', usePort444: isReceiptEndpoint };
2121
- }
2122
- if (isReceiptEndpoint && platform === 'mobile') {
2123
- return { mode: 'mtls', usePort444: true };
2124
- }
2125
- return { mode: 'jwt', usePort444: false };
2126
- }
2127
- async getAuthHeaders() {
2128
- return this.jwtHandler.getAuthHeaders();
2129
- }
2130
- getMtlsHandler() {
2131
- return this.mtlsHandler;
2132
- }
2133
- getJwtHandler() {
2134
- return this.jwtHandler;
2369
+ buildConfig(userConfig) {
2370
+ return {
2371
+ environment: userConfig.environment,
2372
+ apiUrl: this.getDefaultApiUrl(userConfig.environment),
2373
+ authUrl: this.getDefaultAuthUrl(userConfig.environment),
2374
+ timeout: 30000,
2375
+ retryAttempts: 3,
2376
+ debug: userConfig.debug ?? false,
2377
+ customHeaders: {},
2378
+ };
2135
2379
  }
2136
- detectPlatform() {
2137
- if (!this.mtlsAdapter) {
2138
- return 'web';
2380
+ getDefaultApiUrl(environment) {
2381
+ switch (environment) {
2382
+ case 'production':
2383
+ return 'https://ereceipts-it.acubeapi.com';
2384
+ case 'development':
2385
+ return 'https://ereceipts-it.dev.acubeapi.com';
2386
+ case 'sandbox':
2387
+ default:
2388
+ return 'https://ereceipts-it-sandbox.acubeapi.com';
2139
2389
  }
2140
- const platformInfo = this.mtlsAdapter.getPlatformInfo();
2141
- return platformInfo.platform === 'web' ? 'web' : 'mobile';
2142
2390
  }
2143
- async getUserRole() {
2144
- if (!this.userProvider) {
2145
- return null;
2146
- }
2147
- const user = await this.userProvider.getCurrentUser();
2148
- if (!user || !user.roles) {
2149
- return null;
2150
- }
2151
- if (hasRole(user.roles, 'ROLE_SUPPLIER')) {
2152
- return 'SUPPLIER';
2153
- }
2154
- if (hasRole(user.roles, 'ROLE_MERCHANT')) {
2155
- return 'MERCHANT';
2156
- }
2157
- if (hasRole(user.roles, 'ROLE_CASHIER')) {
2158
- return 'CASHIER';
2391
+ getDefaultAuthUrl(environment) {
2392
+ switch (environment) {
2393
+ case 'production':
2394
+ return 'https://common.api.acubeapi.com';
2395
+ case 'development':
2396
+ case 'sandbox':
2397
+ default:
2398
+ return 'https://common-sandbox.api.acubeapi.com';
2159
2399
  }
2160
- return null;
2161
2400
  }
2162
- isReceiptEndpoint(url) {
2163
- return url.includes('/receipts') || url.includes('/mf1/receipts');
2164
- }
2165
- isReturnableItemsEndpoint(url) {
2166
- return !!(url.match(/\/receipts\/[a-f0-9-]+\/returnable-items$/) ||
2167
- url.match(/\/mf1\/receipts\/[a-f0-9-]+\/returnable-items$/));
2168
- }
2169
- isDetailedReceiptEndpoint(url) {
2170
- return !!(url.match(/\/receipts\/[a-f0-9-]+\/details$/) ||
2171
- url.match(/\/mf1\/receipts\/[a-f0-9-]+\/details$/));
2401
+ getConfig() {
2402
+ return {
2403
+ environment: this.config.environment,
2404
+ debug: this.config.debug,
2405
+ };
2172
2406
  }
2173
- isNotificationEndpoint(url) {
2174
- return url.includes('/mf1/notifications');
2407
+ getApiUrl() {
2408
+ return this.config.apiUrl;
2175
2409
  }
2176
- isTelemetryEndpoint(url) {
2177
- return !!url.match(/\/mf1\/pems\/[^/]+\/telemetry/);
2410
+ getAuthUrl() {
2411
+ return this.config.authUrl;
2178
2412
  }
2179
- }
2180
-
2181
- class JwtAuthHandler {
2182
- constructor(tokenStorage) {
2183
- this.tokenStorage = tokenStorage;
2413
+ getEnvironment() {
2414
+ return this.config.environment;
2184
2415
  }
2185
- async getAuthConfig(_url, _method) {
2186
- return { mode: 'jwt', usePort444: false };
2416
+ isDebugEnabled() {
2417
+ return this.config.debug;
2187
2418
  }
2188
- async getAuthHeaders() {
2189
- const token = await this.tokenStorage.getAccessToken();
2190
- if (!token) {
2191
- return {};
2192
- }
2193
- return { Authorization: `Bearer ${token}` };
2419
+ getTimeout() {
2420
+ return this.config.timeout;
2194
2421
  }
2195
- }
2196
-
2197
- function clearObject(input) {
2198
- if (input === null || input === undefined || input === '') {
2199
- return undefined;
2422
+ getRetryAttempts() {
2423
+ return this.config.retryAttempts;
2200
2424
  }
2201
- if (Array.isArray(input)) {
2202
- const cleanedArray = input
2203
- .map((item) => clearObject(item))
2204
- .filter((item) => item !== undefined);
2205
- return cleanedArray;
2425
+ getCustomHeaders() {
2426
+ return { ...this.config.customHeaders };
2206
2427
  }
2207
- if (typeof input === 'object' && input.constructor === Object) {
2208
- const cleaned = {};
2209
- for (const [key, value] of Object.entries(input)) {
2210
- const cleanedValue = clearObject(value);
2211
- if (cleanedValue !== undefined) {
2212
- cleaned[key] = cleanedValue;
2213
- }
2428
+ updateConfig(updates) {
2429
+ if (updates.environment) {
2430
+ this.config.environment = updates.environment;
2431
+ this.config.apiUrl = this.getDefaultApiUrl(updates.environment);
2432
+ this.config.authUrl = this.getDefaultAuthUrl(updates.environment);
2214
2433
  }
2215
- return cleaned;
2216
- }
2217
- return input;
2218
- }
2219
- function clearObjectShallow(obj) {
2220
- if (!obj || typeof obj !== 'object') {
2221
- return {};
2222
- }
2223
- const cleaned = {};
2224
- for (const [key, value] of Object.entries(obj)) {
2225
- if (value !== null && value !== undefined && value !== '') {
2226
- cleaned[key] = value;
2434
+ if (updates.debug !== undefined) {
2435
+ this.config.debug = updates.debug;
2227
2436
  }
2228
2437
  }
2229
- return cleaned;
2230
- }
2231
- function isEmpty(value) {
2232
- return value === null || value === undefined || value === '';
2233
- }
2234
- function hasNonEmptyValues(obj) {
2235
- if (!obj || typeof obj !== 'object') {
2236
- return false;
2237
- }
2238
- return Object.values(obj).some((value) => !isEmpty(value));
2239
2438
  }
2240
2439
 
2241
- /**
2242
- * Platform detection utilities
2243
- */
2244
- /**
2245
- * Detect the current platform
2246
- */
2247
- function detectPlatform() {
2248
- // Check for React Native
2249
- if (typeof global !== 'undefined' &&
2250
- global.__DEV__ !== undefined &&
2251
- typeof global.navigator !== 'undefined' &&
2252
- global.navigator.product === 'ReactNative') {
2253
- return {
2254
- platform: 'react-native',
2255
- isReactNative: true,
2256
- isWeb: false,
2257
- isNode: false,
2258
- isExpo: checkExpo(),
2259
- };
2260
- }
2261
- // Check for Web/Browser
2262
- if (typeof window !== 'undefined' &&
2263
- typeof window.document !== 'undefined' &&
2264
- typeof window.navigator !== 'undefined') {
2265
- return {
2266
- platform: 'web',
2267
- isReactNative: false,
2268
- isWeb: true,
2269
- isNode: false,
2270
- isExpo: false,
2271
- };
2272
- }
2273
- // Check for Node.js
2274
- if (typeof process !== 'undefined' && process.versions && process.versions.node) {
2275
- return {
2276
- platform: 'node',
2277
- isReactNative: false,
2278
- isWeb: false,
2279
- isNode: true,
2280
- isExpo: false,
2281
- };
2282
- }
2283
- // Unknown platform
2284
- return {
2285
- platform: 'unknown',
2286
- isReactNative: false,
2287
- isWeb: false,
2288
- isNode: false,
2289
- isExpo: false,
2290
- };
2291
- }
2292
- /**
2293
- * Check if running in Expo
2294
- */
2295
- function checkExpo() {
2296
- try {
2297
- return (typeof global !== 'undefined' &&
2298
- (typeof global.Expo !== 'undefined' || typeof global.expo !== 'undefined'));
2440
+ // Enum options arrays
2441
+ const VAT_RATE_CODE_OPTIONS = [
2442
+ '4.00',
2443
+ '5.00',
2444
+ '10.00',
2445
+ '22.00',
2446
+ '2.00',
2447
+ '6.40',
2448
+ '7.00',
2449
+ '7.30',
2450
+ '7.50',
2451
+ '7.65',
2452
+ '7.95',
2453
+ '8.30',
2454
+ '8.50',
2455
+ '8.80',
2456
+ '9.50',
2457
+ '12.30',
2458
+ 'N1',
2459
+ 'N2',
2460
+ 'N3',
2461
+ 'N4',
2462
+ 'N5',
2463
+ 'N6',
2464
+ ];
2465
+ const GOOD_OR_SERVICE_OPTIONS = ['goods', 'service'];
2466
+ const RECEIPT_PROOF_TYPE_OPTIONS = ['POS', 'VR', 'ND'];
2467
+ // Enum types for receipt validation
2468
+ const VatRateCodeSchema = z.enum(VAT_RATE_CODE_OPTIONS);
2469
+ const GoodOrServiceSchema = z.enum(GOOD_OR_SERVICE_OPTIONS);
2470
+ const ReceiptProofTypeSchema = z.enum(RECEIPT_PROOF_TYPE_OPTIONS);
2471
+ // Receipt Item Schema
2472
+ const ReceiptItemSchema = z.object({
2473
+ type: GoodOrServiceSchema.optional(),
2474
+ quantity: z.string().min(1, { error: 'fieldIsRequired' }),
2475
+ description: z.string().min(1, { error: 'fieldIsRequired' }),
2476
+ unit_price: z.string().min(1, { error: 'fieldIsRequired' }),
2477
+ vat_rate_code: VatRateCodeSchema.optional(),
2478
+ simplified_vat_allocation: z.boolean().optional(),
2479
+ discount: z.string().nullable().optional(),
2480
+ is_down_payment_or_voucher_redemption: z.boolean().optional(),
2481
+ complimentary: z.boolean().optional(),
2482
+ });
2483
+ // Main Receipt Input Schema
2484
+ const ReceiptInputSchema = z
2485
+ .object({
2486
+ items: z.array(ReceiptItemSchema).min(1, { error: 'arrayMin1' }),
2487
+ customer_tax_code: z.string().optional(),
2488
+ customer_lottery_code: z.string().optional(),
2489
+ discount: z.string().nullable().optional(),
2490
+ invoice_issuing: z.boolean().optional(),
2491
+ uncollected_dcr_to_ssn: z.boolean().optional(),
2492
+ services_uncollected_amount: z.string().nullable().optional(),
2493
+ goods_uncollected_amount: z.string().nullable().optional(),
2494
+ cash_payment_amount: z.string().nullable().optional(),
2495
+ electronic_payment_amount: z.string().nullable().optional(),
2496
+ ticket_restaurant_payment_amount: z.string().nullable().optional(),
2497
+ ticket_restaurant_quantity: z.number().optional(),
2498
+ })
2499
+ .refine((data) => {
2500
+ // At least one payment method should be provided
2501
+ const hasCashPayment = data.cash_payment_amount && parseFloat(data.cash_payment_amount) > 0;
2502
+ const hasElectronicPayment = data.electronic_payment_amount && parseFloat(data.electronic_payment_amount) > 0;
2503
+ const hasTicketPayment = data.ticket_restaurant_payment_amount &&
2504
+ parseFloat(data.ticket_restaurant_payment_amount) > 0;
2505
+ return hasCashPayment || hasElectronicPayment || hasTicketPayment;
2506
+ }, {
2507
+ error: 'At least one payment method is required',
2508
+ path: ['payment_methods'],
2509
+ })
2510
+ .refine((data) => {
2511
+ // only one between customer_tax_code and customer_lottery_code can be provided
2512
+ return !data.customer_tax_code || !data.customer_lottery_code;
2513
+ }, {
2514
+ error: 'Only one between customer_tax_code and customer_lottery_code can be provided',
2515
+ path: ['customer_tax_code', 'customer_lottery_code'],
2516
+ });
2517
+ // Receipt Return or Void via PEM Schema
2518
+ const ReceiptReturnOrVoidViaPEMInputSchema = z.object({
2519
+ device_id: z.string().optional(),
2520
+ items: z.array(ReceiptItemSchema).min(1, { error: 'arrayMin1' }),
2521
+ document_number: z.string().min(1, { error: 'fieldIsRequired' }),
2522
+ document_datetime: z.string().optional(),
2523
+ lottery_code: z.string().optional(),
2524
+ });
2525
+ // Receipt Return or Void with Proof Schema
2526
+ const ReceiptReturnOrVoidWithProofInputSchema = z.object({
2527
+ items: z.array(ReceiptItemSchema).min(1, { error: 'arrayMin1' }),
2528
+ proof: ReceiptProofTypeSchema,
2529
+ document_datetime: z.string().min(1, { error: 'fieldIsRequired' }),
2530
+ });
2531
+ // Void Receipt Schema
2532
+ const VoidReceiptInputSchema = z.object({
2533
+ document_number: z.string().min(1, { error: 'fieldIsRequired' }),
2534
+ });
2535
+ const ReceiptReturnItemSchema = z
2536
+ .array(z.object({
2537
+ id: z.number(),
2538
+ quantity: z.string().min(1, { error: 'fieldIsRequired' }),
2539
+ }))
2540
+ .min(1, { error: 'arrayMin1' });
2541
+ // Receipt Return Schema
2542
+ const ReceiptReturnInputSchema = z.object({
2543
+ items: z.array(ReceiptReturnItemSchema).min(1, { error: 'arrayMin1' }),
2544
+ document_number: z.string().min(1, { error: 'fieldIsRequired' }),
2545
+ });
2546
+
2547
+ // Cashier Create Input Schema (MF1)
2548
+ const CashierCreateInputSchema = z.object({
2549
+ email: z
2550
+ .string()
2551
+ .min(1, { error: 'fieldIsRequired' })
2552
+ .max(255, { error: 'emailMaxLength' })
2553
+ .email({ error: 'invalidEmail' }),
2554
+ password: z
2555
+ .string()
2556
+ .min(8, { error: 'passwordMinLength' })
2557
+ .max(40, { error: 'passwordMaxLength' }),
2558
+ name: z.string().min(1, { error: 'fieldIsRequired' }).max(255, { error: 'nameMaxLength' }),
2559
+ display_name: z
2560
+ .string()
2561
+ .min(1, { error: 'fieldIsRequired' })
2562
+ .max(255, { error: 'displayNameMaxLength' }),
2563
+ });
2564
+
2565
+ // Enum options arrays
2566
+ const PEM_STATUS_OPTIONS = [
2567
+ 'NEW',
2568
+ 'REGISTERED',
2569
+ 'ACTIVATED',
2570
+ 'ONLINE',
2571
+ 'OFFLINE',
2572
+ 'DISCARDED',
2573
+ ];
2574
+ // Address Schema (reusable)
2575
+ const AddressSchema = z.object({
2576
+ street_address: z.string().min(1, { error: 'fieldIsRequired' }),
2577
+ street_number: z.string().min(1, { error: 'fieldIsRequired' }),
2578
+ zip_code: z
2579
+ .string()
2580
+ .min(1, { error: 'fieldIsRequired' })
2581
+ .regex(/^\d{5}$/, { error: 'invalidZipCode' }),
2582
+ city: z.string().min(1, { error: 'fieldIsRequired' }),
2583
+ province: z
2584
+ .string()
2585
+ .min(2, { error: 'provinceMinLength' })
2586
+ .max(2, { error: 'provinceMaxLength' })
2587
+ .toUpperCase(),
2588
+ });
2589
+ // PEM Status Schema
2590
+ const PEMStatusSchema = z.enum(PEM_STATUS_OPTIONS);
2591
+ // Activation Request Schema
2592
+ const ActivationRequestSchema = z.object({
2593
+ registration_key: z.string().min(1, { error: 'fieldIsRequired' }),
2594
+ });
2595
+ // PEM Status Offline Request Schema
2596
+ const PEMStatusOfflineRequestSchema = z.object({
2597
+ timestamp: z
2598
+ .string()
2599
+ .min(1, { error: 'fieldIsRequired' })
2600
+ .refine((val) => !isNaN(Date.parse(val)), {
2601
+ error: 'invalidDateFormat',
2602
+ }),
2603
+ reason: z.string().min(1, { error: 'fieldIsRequired' }),
2604
+ });
2605
+
2606
+ // Cash Register Create Schema
2607
+ const CashRegisterCreateSchema = z.object({
2608
+ pem_serial_number: z.string().min(1, { error: 'fieldIsRequired' }),
2609
+ name: z.string().min(1, { error: 'fieldIsRequired' }).max(100, { error: 'nameMaxLength' }),
2610
+ });
2611
+
2612
+ // VAT number validation regex (Partita IVA - 11 digits)
2613
+ const VAT_NUMBER_REGEX = /^\d{11}$/;
2614
+ // Fiscal code validation regex (Codice Fiscale - 11 digits only for merchants)
2615
+ const FISCAL_CODE_REGEX = /^\d{11}$/;
2616
+ // Password validation regex (from OpenAPI spec)
2617
+ const PASSWORD_REGEX = /^((?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{10,}).*)$/;
2618
+ // Merchant Create Input Schema
2619
+ const MerchantCreateInputSchema = z
2620
+ .object({
2621
+ vat_number: z
2622
+ .string()
2623
+ .min(1, { error: 'fieldIsRequired' })
2624
+ .regex(VAT_NUMBER_REGEX, { error: 'invalidVatNumber' }),
2625
+ fiscal_code: z.string().regex(FISCAL_CODE_REGEX, { error: 'invalidFiscalCode' }).optional(),
2626
+ business_name: z.string().max(200, { error: 'businessNameMaxLength' }).optional().nullable(),
2627
+ first_name: z.string().max(100, { error: 'firstNameMaxLength' }).optional().nullable(),
2628
+ last_name: z.string().max(100, { error: 'lastNameMaxLength' }).optional().nullable(),
2629
+ email: z.string().min(1, { error: 'fieldIsRequired' }).email({ error: 'invalidEmail' }),
2630
+ password: z
2631
+ .string()
2632
+ .min(1, { error: 'fieldIsRequired' })
2633
+ .regex(PASSWORD_REGEX, { error: 'passwordComplexity' }),
2634
+ address: AddressSchema.optional(),
2635
+ })
2636
+ .refine((data) => {
2637
+ const hasBusinessName = data.business_name && data.business_name.trim() !== '';
2638
+ const hasPersonalNames = (data.first_name && data.first_name.trim() !== '') ||
2639
+ (data.last_name && data.last_name.trim() !== '');
2640
+ // If business name is set, first/last name must not be provided
2641
+ if (hasBusinessName && hasPersonalNames) {
2642
+ return false;
2299
2643
  }
2300
- catch {
2644
+ // At least one naming method must be provided
2645
+ if (!hasBusinessName && !hasPersonalNames) {
2301
2646
  return false;
2302
2647
  }
2303
- }
2648
+ return true;
2649
+ }, {
2650
+ error: 'businessNameOrPersonalNamesRequired',
2651
+ path: ['business_name'],
2652
+ });
2653
+ // Merchant Update Input Schema
2654
+ const MerchantUpdateInputSchema = z.object({
2655
+ business_name: z.string().max(200, { error: 'businessNameMaxLength' }).optional().nullable(),
2656
+ first_name: z.string().max(100, { error: 'firstNameMaxLength' }).optional().nullable(),
2657
+ last_name: z.string().max(100, { error: 'lastNameMaxLength' }).optional().nullable(),
2658
+ address: AddressSchema.optional().nullable(),
2659
+ });
2660
+
2661
+ // Enum options arrays
2662
+ const PEM_TYPE_OPTIONS = ['AP', 'SP', 'TM', 'PV'];
2663
+ // PEM Data Schema
2664
+ const PemDataSchema = z.object({
2665
+ version: z.string().min(1, { error: 'fieldIsRequired' }),
2666
+ type: z.enum(PEM_TYPE_OPTIONS, {
2667
+ error: 'invalidPemType',
2668
+ }),
2669
+ });
2670
+ // PEM Create Input Schema
2671
+ const PemCreateInputSchema = z.object({
2672
+ merchant_uuid: z.string().min(1, { error: 'fieldIsRequired' }).uuid({ error: 'invalidUuid' }),
2673
+ address: AddressSchema.optional(),
2674
+ /* external_pem_data: PemDataSchema.optional(), */
2675
+ });
2676
+
2677
+ // Italian Fiscal ID validation regex (Codice Fiscale for individuals or Partita IVA for companies)
2678
+ const FISCAL_ID_REGEX = /^([A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]|[0-9]{11})$/;
2679
+ // Supplier Create Input Schema
2680
+ const SupplierCreateInputSchema = z.object({
2681
+ fiscal_id: z
2682
+ .string()
2683
+ .min(1, { error: 'fieldIsRequired' })
2684
+ .regex(FISCAL_ID_REGEX, { error: 'invalidFiscalId' })
2685
+ .toUpperCase(),
2686
+ name: z.string().min(1, { error: 'fieldIsRequired' }).max(200, { error: 'nameMaxLength' }),
2687
+ address: AddressSchema.optional(),
2688
+ });
2689
+ // Supplier Update Input Schema
2690
+ const SupplierUpdateInputSchema = z.object({
2691
+ name: z.string().min(1, { error: 'fieldIsRequired' }).max(200, { error: 'nameMaxLength' }),
2692
+ address: AddressSchema.optional(),
2693
+ });
2694
+
2695
+ // Journal Close Input Schema
2696
+ const JournalCloseInputSchema = z.object({
2697
+ closing_timestamp: z
2698
+ .string()
2699
+ .min(1, { error: 'fieldIsRequired' })
2700
+ .refine((val) => !isNaN(Date.parse(val)), {
2701
+ error: 'invalidDateFormat',
2702
+ }),
2703
+ reason: z.string().max(255, { error: 'reasonMaxLength' }).optional(),
2704
+ });
2705
+
2706
+ // Daily Report Status Options
2707
+ const DAILY_REPORT_STATUS_OPTIONS = ['pending', 'sent', 'error'];
2708
+ // Daily Report Status Schema
2709
+ const DailyReportStatusSchema = z.enum(DAILY_REPORT_STATUS_OPTIONS, {
2710
+ error: 'invalidDailyReportStatus',
2711
+ });
2712
+ // Daily Reports List Parameters Schema
2713
+ const DailyReportsParamsSchema = z.object({
2714
+ pem_serial_number: z.string().min(1, { error: 'fieldIsRequired' }).optional(),
2715
+ date_from: z
2716
+ .string()
2717
+ .refine((val) => !isNaN(Date.parse(val)), {
2718
+ error: 'invalidDateFormat',
2719
+ })
2720
+ .optional(),
2721
+ date_to: z
2722
+ .string()
2723
+ .refine((val) => !isNaN(Date.parse(val)), {
2724
+ error: 'invalidDateFormat',
2725
+ })
2726
+ .optional(),
2727
+ status: DailyReportStatusSchema.optional(),
2728
+ page: z.number().min(1, { error: 'pageMinValue' }).optional(),
2729
+ });
2730
+
2731
+ const NotificationScopeSchema = z.object({
2732
+ type: z.literal('global'),
2733
+ });
2734
+ const PemStatusSchema = z.enum(['ONLINE', 'OFFLINE']);
2735
+ const NotificationDataBlockAtSchema = z.object({
2736
+ block_at: z.string(),
2737
+ });
2738
+ const NotificationDataPemStatusSchema = z.object({
2739
+ from: PemStatusSchema,
2740
+ to: PemStatusSchema,
2741
+ });
2742
+ const NotificationBaseSchema = z.object({
2743
+ uuid: z.string().uuid({ error: 'invalidUuid' }),
2744
+ scope: NotificationScopeSchema,
2745
+ source: z.enum(['system', 'Italian Tax Authority']),
2746
+ level: z.enum(['info', 'warning', 'error', 'critical']),
2747
+ created_at: z.string(),
2748
+ });
2749
+ const NotificationMf2UnreachableSchema = NotificationBaseSchema.extend({
2750
+ type: z.literal('INTERNAL_COMMUNICATION_FAILURE'),
2751
+ code: z.literal('SYS-W-01'),
2752
+ data: NotificationDataBlockAtSchema,
2753
+ });
2754
+ const NotificationPemsBlockedSchema = NotificationBaseSchema.extend({
2755
+ type: z.literal('PEM_STATUS_CHANGED'),
2756
+ code: z.literal('SYS-C-01'),
2757
+ data: NotificationDataPemStatusSchema,
2758
+ });
2759
+ const NotificationPemBackOnlineSchema = NotificationBaseSchema.extend({
2760
+ type: z.literal('PEM_STATUS_CHANGED'),
2761
+ code: z.literal('SYS-I-01'),
2762
+ data: NotificationDataPemStatusSchema,
2763
+ });
2764
+ const NotificationSchema = z.discriminatedUnion('code', [
2765
+ NotificationMf2UnreachableSchema,
2766
+ NotificationPemsBlockedSchema,
2767
+ NotificationPemBackOnlineSchema,
2768
+ ]);
2769
+ const NotificationListResponseSchema = z.object({
2770
+ members: z.array(NotificationSchema),
2771
+ });
2772
+
2773
+ const TelemetryMerchantSchema = z.object({
2774
+ vat_number: z.string(),
2775
+ fiscal_code: z.string().nullable(),
2776
+ business_name: z.string(),
2777
+ });
2778
+ const TelemetrySupplierSchema = z.object({
2779
+ vat_number: z.string(),
2780
+ fiscal_code: z.string().nullable(),
2781
+ business_name: z.string(),
2782
+ });
2783
+ const TelemetrySoftwareVersionSchema = z.object({
2784
+ version: z.string(),
2785
+ swid: z.string(),
2786
+ installed_at: z.string(),
2787
+ status: z.enum(['active', 'inactive', 'archived']),
2788
+ });
2789
+ const TelemetrySoftwareSchema = z.object({
2790
+ code: z.string(),
2791
+ name: z.string(),
2792
+ approval_reference: z.string(),
2793
+ version_info: TelemetrySoftwareVersionSchema,
2794
+ });
2795
+ const PendingReceiptsSchema = z.object({
2796
+ count: z.number().int().nonnegative(),
2797
+ total_amount: z.string(),
2798
+ });
2799
+ const TransmissionSchema = z.object({
2800
+ attempted_at: z.string(),
2801
+ outcome: z.enum(['success', 'failed', 'pending']),
2802
+ });
2803
+ const MessageSchema = z.object({
2804
+ received_at: z.string(),
2805
+ content: z.string(),
2806
+ });
2807
+ const LotterySecretRequestSchema = z.object({
2808
+ requested_at: z.string(),
2809
+ outcome: z.enum(['success', 'failed', 'pending']),
2810
+ });
2811
+ const LotterySchema = z.object({
2812
+ last_transmission: TransmissionSchema,
2813
+ secret_request: LotterySecretRequestSchema,
2814
+ });
2815
+ const TelemetrySchema = z.object({
2816
+ pem_id: z.string(),
2817
+ pem_status: z.enum(['ONLINE', 'OFFLINE', 'ERROR']),
2818
+ pem_status_changed_at: z.string(),
2819
+ merchant: TelemetryMerchantSchema,
2820
+ supplier: TelemetrySupplierSchema,
2821
+ software: TelemetrySoftwareSchema,
2822
+ last_communication_at: z.string(),
2823
+ pending_receipts: PendingReceiptsSchema,
2824
+ last_receipt_transmission: TransmissionSchema,
2825
+ last_message_from_mf2: MessageSchema,
2826
+ ade_corrispettivi_transmission: TransmissionSchema,
2827
+ last_message_from_ade: MessageSchema,
2828
+ lottery: LotterySchema,
2829
+ });
2830
+
2831
+ // Receipt schemas and types
2832
+ // Common validation utilities
2833
+ const ValidationMessages = {
2834
+ fieldIsRequired: 'This field is required',
2835
+ arrayMin1: 'At least one item is required',
2836
+ paymentMethodRequired: 'At least one payment method is required',
2837
+ invalidEmail: 'Please enter a valid email address',
2838
+ passwordMinLength: 'Password must be at least 8 characters long',
2839
+ passwordComplexity: 'Password must contain at least one uppercase letter, one lowercase letter, one number, and one special character',
2840
+ invalidZipCode: 'Please enter a valid 5-digit zip code',
2841
+ provinceMinLength: 'Province code must be 2 characters',
2842
+ provinceMaxLength: 'Province code must be 2 characters',
2843
+ invalidDateFormat: 'Please enter a valid date',
2844
+ nameMaxLength: 'Name is too long',
2845
+ invalidFiscalId: 'Please enter a valid Italian fiscal ID (Codice Fiscale or Partita IVA)',
2846
+ invalidVatNumber: 'Please enter a valid VAT number (11 digits)',
2847
+ invalidFiscalCode: 'Please enter a valid fiscal code (11 digits)',
2848
+ businessNameMaxLength: 'Business name is too long (max 200 characters)',
2849
+ businessNameOrPersonalNamesRequired: 'Please provide either a business name or first/last name, but not both',
2850
+ firstNameMaxLength: 'First name is too long (max 100 characters)',
2851
+ lastNameMaxLength: 'Last name is too long (max 100 characters)',
2852
+ invalidUuid: 'Please enter a valid UUID',
2853
+ invalidPemType: 'PEM type must be one of: AP, SP, TM, PV',
2854
+ reasonMaxLength: 'Reason is too long (max 255 characters)',
2855
+ pageMinValue: 'Page number must be at least 1',
2856
+ invalidDailyReportStatus: 'Daily report status must be one of: pending, sent, error',
2857
+ displayNameMaxLength: 'Display name is too long (max 255 characters)',
2858
+ };
2859
+ // Validation helper functions
2860
+ const validateInput = (schema, data) => {
2861
+ const result = schema.safeParse(data);
2862
+ if (!result.success) {
2863
+ const errors = result.error.issues.map((error) => ({
2864
+ field: error.path.join('.'),
2865
+ message: error.message,
2866
+ code: error.code,
2867
+ }));
2868
+ return {
2869
+ success: false,
2870
+ errors,
2871
+ data: null,
2872
+ };
2873
+ }
2874
+ return {
2875
+ success: true,
2876
+ errors: [],
2877
+ data: result.data,
2878
+ };
2879
+ };
2304
2880
 
2305
- function getDefaultExportFromCjs (x) {
2306
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
2881
+ class ACubeSDKError extends Error {
2882
+ constructor(type, message, originalError, statusCode, violations) {
2883
+ super(message);
2884
+ this.type = type;
2885
+ this.originalError = originalError;
2886
+ this.statusCode = statusCode;
2887
+ this.name = 'ACubeSDKError';
2888
+ this.violations = violations;
2889
+ }
2307
2890
  }
2308
2891
 
2309
- var picocolors_browser = {exports: {}};
2310
-
2311
- var x=String;
2312
- var create=function() {return {isColorSupported:false,reset:x,bold:x,dim:x,italic:x,underline:x,inverse:x,hidden:x,strikethrough:x,black:x,red:x,green:x,yellow:x,blue:x,magenta:x,cyan:x,white:x,gray:x,bgBlack:x,bgRed:x,bgGreen:x,bgYellow:x,bgBlue:x,bgMagenta:x,bgCyan:x,bgWhite:x,blackBright:x,redBright:x,greenBright:x,yellowBright:x,blueBright:x,magentaBright:x,cyanBright:x,whiteBright:x,bgBlackBright:x,bgRedBright:x,bgGreenBright:x,bgYellowBright:x,bgBlueBright:x,bgMagentaBright:x,bgCyanBright:x,bgWhiteBright:x}};
2313
- picocolors_browser.exports=create();
2314
- picocolors_browser.exports.createColors = create;
2315
-
2316
- var picocolors_browserExports = picocolors_browser.exports;
2317
- var pc = /*@__PURE__*/getDefaultExportFromCjs(picocolors_browserExports);
2318
-
2319
- const levelColors = {
2320
- debug: {
2321
- prefix: pc.gray,
2322
- message: pc.gray,
2323
- data: pc.dim,
2324
- },
2325
- info: {
2326
- prefix: pc.cyan,
2327
- message: pc.white,
2328
- data: pc.dim,
2329
- },
2330
- warn: {
2331
- prefix: pc.yellow,
2332
- message: pc.yellow,
2333
- data: pc.dim,
2334
- },
2335
- error: {
2336
- prefix: pc.red,
2337
- message: pc.red,
2338
- data: pc.dim,
2339
- },
2340
- };
2341
- const levelIcons = {
2342
- debug: '🔍',
2343
- info: 'ℹ️ ',
2344
- warn: '⚠️ ',
2345
- error: '❌',
2346
- };
2347
- /**
2348
- * Format data for pretty display in logs
2349
- */
2350
- function formatData(data, level) {
2351
- if (data === undefined || data === null) {
2352
- return String(data);
2892
+ const log$f = createPrefixedLogger('AUTH-STRATEGY');
2893
+ class AuthStrategy {
2894
+ constructor(jwtHandler, mtlsHandler, userProvider, mtlsAdapter) {
2895
+ this.jwtHandler = jwtHandler;
2896
+ this.mtlsHandler = mtlsHandler;
2897
+ this.userProvider = userProvider;
2898
+ this.mtlsAdapter = mtlsAdapter;
2353
2899
  }
2354
- // For primitive types, just return as string
2355
- if (typeof data !== 'object') {
2356
- return String(data);
2900
+ async determineAuthConfig(url, method, explicitMode) {
2901
+ if (this.isNotificationEndpoint(url) || this.isTelemetryEndpoint(url)) {
2902
+ return { mode: 'mtls', usePort444: true };
2903
+ }
2904
+ const platform = this.detectPlatform();
2905
+ const userRole = await this.getUserRole();
2906
+ const isReceiptEndpoint = this.isReceiptEndpoint(url);
2907
+ log$f.debug('Determining auth config', {
2908
+ url,
2909
+ method,
2910
+ platform,
2911
+ userRole,
2912
+ isReceiptEndpoint,
2913
+ explicitMode,
2914
+ });
2915
+ if (userRole === 'SUPPLIER') {
2916
+ return { mode: 'jwt', usePort444: false };
2917
+ }
2918
+ if (userRole === 'CASHIER') {
2919
+ if (!isReceiptEndpoint) {
2920
+ return { mode: 'jwt', usePort444: false };
2921
+ }
2922
+ if (platform === 'mobile') {
2923
+ return { mode: 'mtls', usePort444: true };
2924
+ }
2925
+ return { mode: 'jwt', usePort444: true };
2926
+ }
2927
+ if (userRole === 'MERCHANT') {
2928
+ if (!isReceiptEndpoint) {
2929
+ return { mode: 'jwt', usePort444: false };
2930
+ }
2931
+ if (this.isReturnableItemsEndpoint(url)) {
2932
+ return { mode: 'mtls', usePort444: true };
2933
+ }
2934
+ if (method === 'GET') {
2935
+ if (this.isDetailedReceiptEndpoint(url)) {
2936
+ if (platform === 'mobile') {
2937
+ return { mode: 'mtls', usePort444: true };
2938
+ }
2939
+ return { mode: 'jwt', usePort444: true };
2940
+ }
2941
+ return { mode: 'jwt', usePort444: false };
2942
+ }
2943
+ if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) {
2944
+ if (platform === 'mobile') {
2945
+ return { mode: 'mtls', usePort444: true };
2946
+ }
2947
+ return { mode: 'jwt', usePort444: true };
2948
+ }
2949
+ return { mode: 'jwt', usePort444: false };
2950
+ }
2951
+ if (explicitMode) {
2952
+ if (userRole === 'SUPPLIER' && explicitMode === 'mtls') {
2953
+ return { mode: 'jwt', usePort444: false };
2954
+ }
2955
+ return {
2956
+ mode: explicitMode,
2957
+ usePort444: explicitMode === 'mtls' || (platform === 'web' && isReceiptEndpoint),
2958
+ };
2959
+ }
2960
+ if (platform === 'web') {
2961
+ return { mode: 'jwt', usePort444: isReceiptEndpoint };
2962
+ }
2963
+ if (isReceiptEndpoint && platform === 'mobile') {
2964
+ return { mode: 'mtls', usePort444: true };
2965
+ }
2966
+ return { mode: 'jwt', usePort444: false };
2357
2967
  }
2358
- // For Error objects, format nicely
2359
- if (data instanceof Error) {
2360
- return `${data.name}: ${data.message}${data.stack ? `\n${pc.dim(data.stack)}` : ''}`;
2968
+ async getAuthHeaders() {
2969
+ return this.jwtHandler.getAuthHeaders();
2361
2970
  }
2362
- try {
2363
- // Apply level-specific coloring
2364
- const colors = levelColors[level];
2365
- return colors.data(JSON.stringify(data, null, 2));
2971
+ getMtlsHandler() {
2972
+ return this.mtlsHandler;
2366
2973
  }
2367
- catch {
2368
- // Fallback to JSON.stringify if pretty-format fails
2369
- try {
2370
- return JSON.stringify(data, null, 2);
2974
+ getJwtHandler() {
2975
+ return this.jwtHandler;
2976
+ }
2977
+ detectPlatform() {
2978
+ if (!this.mtlsAdapter) {
2979
+ return 'web';
2371
2980
  }
2372
- catch {
2373
- return String(data);
2981
+ const platformInfo = this.mtlsAdapter.getPlatformInfo();
2982
+ return platformInfo.platform === 'web' ? 'web' : 'mobile';
2983
+ }
2984
+ async getUserRole() {
2985
+ if (!this.userProvider) {
2986
+ return null;
2987
+ }
2988
+ const user = await this.userProvider.getCurrentUser();
2989
+ if (!user || !user.roles) {
2990
+ return null;
2991
+ }
2992
+ if (hasRole(user.roles, 'ROLE_SUPPLIER')) {
2993
+ return 'SUPPLIER';
2994
+ }
2995
+ if (hasRole(user.roles, 'ROLE_MERCHANT')) {
2996
+ return 'MERCHANT';
2374
2997
  }
2998
+ if (hasRole(user.roles, 'ROLE_CASHIER')) {
2999
+ return 'CASHIER';
3000
+ }
3001
+ return null;
2375
3002
  }
2376
- }
2377
- class Logger {
2378
- constructor() {
2379
- this.enabled = false;
3003
+ isReceiptEndpoint(url) {
3004
+ return url.includes('/receipts') || url.includes('/mf1/receipts');
2380
3005
  }
2381
- setEnabled(enabled) {
2382
- this.enabled = enabled;
3006
+ isReturnableItemsEndpoint(url) {
3007
+ return !!(url.match(/\/receipts\/[a-f0-9-]+\/returnable-items$/) ||
3008
+ url.match(/\/mf1\/receipts\/[a-f0-9-]+\/returnable-items$/));
2383
3009
  }
2384
- isEnabled() {
2385
- return this.enabled;
3010
+ isDetailedReceiptEndpoint(url) {
3011
+ return !!(url.match(/\/receipts\/[a-f0-9-]+\/details$/) ||
3012
+ url.match(/\/mf1\/receipts\/[a-f0-9-]+\/details$/));
2386
3013
  }
2387
- debug(prefix, message, data) {
2388
- if (!this.enabled)
2389
- return;
2390
- this.log('debug', prefix, message, data);
3014
+ isNotificationEndpoint(url) {
3015
+ return url.includes('/mf1/notifications');
2391
3016
  }
2392
- info(prefix, message, data) {
2393
- if (!this.enabled)
2394
- return;
2395
- this.log('info', prefix, message, data);
3017
+ isTelemetryEndpoint(url) {
3018
+ return !!url.match(/\/mf1\/pems\/[^/]+\/telemetry/);
2396
3019
  }
2397
- warn(prefix, message, data) {
2398
- this.log('warn', prefix, message, data);
3020
+ }
3021
+
3022
+ class JwtAuthHandler {
3023
+ constructor(tokenStorage) {
3024
+ this.tokenStorage = tokenStorage;
2399
3025
  }
2400
- error(prefix, message, data) {
2401
- this.log('error', prefix, message, data);
3026
+ async getAuthConfig(_url, _method) {
3027
+ return { mode: 'jwt', usePort444: false };
2402
3028
  }
2403
- log(level, prefix, message, data) {
2404
- const colors = levelColors[level];
2405
- const icon = levelIcons[level];
2406
- const isoTime = new Date().toISOString().split('T')[1] ?? '';
2407
- const timestamp = pc.dim(isoTime.slice(0, 12));
2408
- const formattedPrefix = colors.prefix(`[${prefix}]`);
2409
- const formattedMessage = colors.message(message);
2410
- const consoleMethod = level === 'debug'
2411
- ? console.debug
2412
- : level === 'info'
2413
- ? console.info
2414
- : level === 'warn'
2415
- ? console.warn
2416
- : console.error;
2417
- const header = `${timestamp} ${icon} ${formattedPrefix} ${formattedMessage}`;
2418
- if (data !== undefined) {
2419
- const formattedData = formatData(data, level);
2420
- // Check if data is an object (multi-line) or primitive (single-line)
2421
- const isMultiLine = typeof data === 'object' && data !== null;
2422
- if (isMultiLine) {
2423
- consoleMethod(`${header}\n${formattedData}`);
2424
- }
2425
- else {
2426
- consoleMethod(`${header}`, formattedData);
2427
- }
2428
- }
2429
- else {
2430
- consoleMethod(header);
3029
+ async getAuthHeaders() {
3030
+ const token = await this.tokenStorage.getAccessToken();
3031
+ if (!token) {
3032
+ return {};
2431
3033
  }
3034
+ return { Authorization: `Bearer ${token}` };
2432
3035
  }
2433
3036
  }
2434
- const logger = new Logger();
2435
- function createPrefixedLogger(prefix) {
2436
- return {
2437
- debug: (message, data) => logger.debug(prefix, message, data),
2438
- info: (message, data) => logger.info(prefix, message, data),
2439
- warn: (message, data) => logger.warn(prefix, message, data),
2440
- error: (message, data) => logger.error(prefix, message, data),
2441
- };
2442
- }
2443
-
2444
- /**
2445
- * Formats a numeric string value to have exactly the specified number of decimal places.
2446
- * E.g., "1" → "1.00", "10" → "10.00", "1.5" → "1.50"
2447
- * Returns undefined for undefined input (preserves optional fields).
2448
- *
2449
- * @param value - The string value to format
2450
- * @param decimals - Number of decimal places (default: 2)
2451
- * @returns Formatted string or undefined if input is undefined
2452
- */
2453
- function formatDecimal(value, decimals = 2) {
2454
- if (value === undefined)
2455
- return undefined;
2456
- const num = parseFloat(value);
2457
- if (isNaN(num))
2458
- return value;
2459
- return num.toFixed(decimals);
2460
- }
2461
3037
 
2462
- const log$f = createPrefixedLogger('MTLS-HANDLER');
3038
+ const log$e = createPrefixedLogger('MTLS-HANDLER');
2463
3039
  class MtlsAuthHandler {
2464
3040
  constructor(mtlsAdapter, certificatePort) {
2465
3041
  this.mtlsAdapter = mtlsAdapter;
@@ -2501,7 +3077,7 @@ class MtlsAuthHandler {
2501
3077
  async makeRequest(url, config, jwtToken) {
2502
3078
  const requestKey = this.generateRequestKey(url, config, jwtToken);
2503
3079
  if (this.pendingRequests.has(requestKey)) {
2504
- log$f.debug('Deduplicating concurrent request:', url);
3080
+ log$e.debug('Deduplicating concurrent request:', url);
2505
3081
  return this.pendingRequests.get(requestKey);
2506
3082
  }
2507
3083
  const requestPromise = this.executeRequest(url, config, jwtToken, false);
@@ -2525,10 +3101,10 @@ class MtlsAuthHandler {
2525
3101
  };
2526
3102
  if (jwtToken) {
2527
3103
  headers['Authorization'] = `Bearer ${jwtToken}`;
2528
- log$f.debug('JWT token present:', jwtToken.substring(0, 20) + '...');
3104
+ log$e.debug('JWT token present:', jwtToken.substring(0, 20) + '...');
2529
3105
  }
2530
3106
  else {
2531
- log$f.warn('No JWT token provided for mTLS request');
3107
+ log$e.warn('No JWT token provided for mTLS request');
2532
3108
  }
2533
3109
  const fullUrl = this.constructMtlsUrl(url);
2534
3110
  const mtlsConfig = {
@@ -2539,25 +3115,25 @@ class MtlsAuthHandler {
2539
3115
  timeout: config.timeout,
2540
3116
  responseType: config.responseType,
2541
3117
  };
2542
- log$f.debug('header-mtls', headers);
2543
- log$f.debug(`${config.method} ${fullUrl}`);
3118
+ log$e.debug('header-mtls', headers);
3119
+ log$e.debug(`${config.method} ${fullUrl}`);
2544
3120
  if (config.data) {
2545
- log$f.debug('Request body:', config.data);
3121
+ log$e.debug('Request body:', config.data);
2546
3122
  }
2547
3123
  try {
2548
3124
  const response = await this.mtlsAdapter.request(mtlsConfig);
2549
- log$f.debug(`Response ${response.status} from ${fullUrl}`);
3125
+ log$e.debug(`Response ${response.status} from ${fullUrl}`);
2550
3126
  if (response.data) {
2551
- log$f.debug('Response body:', response.data);
3127
+ log$e.debug('Response body:', response.data);
2552
3128
  }
2553
3129
  return response.data;
2554
3130
  }
2555
3131
  catch (error) {
2556
- log$f.error(`Response error from ${fullUrl}:`, error);
3132
+ log$e.error(`Response error from ${fullUrl}:`, error);
2557
3133
  if (error && typeof error === 'object' && 'response' in error) {
2558
3134
  const axiosError = error;
2559
3135
  if (axiosError.response?.data) {
2560
- log$f.error('Response body:', axiosError.response.data);
3136
+ log$e.error('Response body:', axiosError.response.data);
2561
3137
  }
2562
3138
  }
2563
3139
  if (isRetryAttempt) {
@@ -2567,7 +3143,7 @@ class MtlsAuthHandler {
2567
3143
  if (!shouldRetry) {
2568
3144
  throw error;
2569
3145
  }
2570
- log$f.debug('Request failed, reconfiguring certificate and retrying...');
3146
+ log$e.debug('Request failed, reconfiguring certificate and retrying...');
2571
3147
  try {
2572
3148
  await this.configureCertificate(certificate);
2573
3149
  return await this.executeRequest(url, config, jwtToken, true);
@@ -3294,7 +3870,7 @@ function decompressData(data, compressed) {
3294
3870
  return new CompressionAdapter().decompress(data, compressed);
3295
3871
  }
3296
3872
 
3297
- const log$e = createPrefixedLogger('CACHE-RN');
3873
+ const log$d = createPrefixedLogger('CACHE-RN');
3298
3874
  /**
3299
3875
  * React Native cache adapter using SQLite (Expo or react-native-sqlite-storage)
3300
3876
  * Cache never expires - data persists until explicitly invalidated
@@ -3378,26 +3954,26 @@ class ReactNativeCacheAdapter {
3378
3954
  await this.runMigrations();
3379
3955
  }
3380
3956
  async runMigrations() {
3381
- log$e.debug('Running database migrations...');
3957
+ log$d.debug('Running database migrations...');
3382
3958
  try {
3383
3959
  // Check if compressed column exists
3384
3960
  this.hasCompressedColumn = await this.checkColumnExists('compressed');
3385
3961
  if (!this.hasCompressedColumn) {
3386
- log$e.debug('Adding compressed column to cache table');
3962
+ log$d.debug('Adding compressed column to cache table');
3387
3963
  const addColumnSQL = `ALTER TABLE ${ReactNativeCacheAdapter.TABLE_NAME} ADD COLUMN compressed INTEGER DEFAULT 0`;
3388
3964
  await this.executeSql(addColumnSQL);
3389
3965
  this.hasCompressedColumn = true;
3390
- log$e.debug('Successfully added compressed column');
3966
+ log$d.debug('Successfully added compressed column');
3391
3967
  }
3392
3968
  else {
3393
- log$e.debug('Compressed column already exists');
3969
+ log$d.debug('Compressed column already exists');
3394
3970
  }
3395
- log$e.debug('Database migrations completed', {
3971
+ log$d.debug('Database migrations completed', {
3396
3972
  hasCompressedColumn: this.hasCompressedColumn,
3397
3973
  });
3398
3974
  }
3399
3975
  catch (error) {
3400
- log$e.debug('Migration failed, disabling compression features', error);
3976
+ log$d.debug('Migration failed, disabling compression features', error);
3401
3977
  this.hasCompressedColumn = false;
3402
3978
  // Don't throw - allow the app to continue even if migration fails
3403
3979
  // The compressed feature will just be disabled
@@ -3408,20 +3984,20 @@ class ReactNativeCacheAdapter {
3408
3984
  const pragmaSQL = `PRAGMA table_info(${ReactNativeCacheAdapter.TABLE_NAME})`;
3409
3985
  const results = await this.executeSql(pragmaSQL);
3410
3986
  const columns = this.normalizeResults(results);
3411
- log$e.debug('Table columns found', { columns: columns.map((c) => c.name) });
3987
+ log$d.debug('Table columns found', { columns: columns.map((c) => c.name) });
3412
3988
  return columns.some((column) => column.name === columnName);
3413
3989
  }
3414
3990
  catch (error) {
3415
- log$e.debug('Error checking column existence', error);
3991
+ log$d.debug('Error checking column existence', error);
3416
3992
  return false;
3417
3993
  }
3418
3994
  }
3419
3995
  async get(key) {
3420
3996
  await this.ensureInitialized();
3421
3997
  const sql = `SELECT * FROM ${ReactNativeCacheAdapter.TABLE_NAME} WHERE cache_key = ?`;
3422
- log$e.debug('Executing get query', { sql, key });
3998
+ log$d.debug('Executing get query', { sql, key });
3423
3999
  const results = await this.executeSql(sql, [key]);
3424
- log$e.debug('Get query results', { key, hasResults: !!results });
4000
+ log$d.debug('Get query results', { key, hasResults: !!results });
3425
4001
  // Normalize results from different SQLite implementations
3426
4002
  const rows = this.normalizeResults(results);
3427
4003
  if (!rows || rows.length === 0) {
@@ -3444,7 +4020,7 @@ class ReactNativeCacheAdapter {
3444
4020
  data,
3445
4021
  timestamp: Date.now(),
3446
4022
  };
3447
- log$e.debug('Setting cache item', { key });
4023
+ log$d.debug('Setting cache item', { key });
3448
4024
  return this.setItem(key, item);
3449
4025
  }
3450
4026
  async setItem(key, item) {
@@ -3457,7 +4033,7 @@ class ReactNativeCacheAdapter {
3457
4033
  const compressionResult = compressData(serializedData, this.options.compressionThreshold);
3458
4034
  finalData = compressionResult.data;
3459
4035
  isCompressed = compressionResult.compressed;
3460
- log$e.debug('Compression result', {
4036
+ log$d.debug('Compression result', {
3461
4037
  key,
3462
4038
  originalSize: compressionResult.originalSize,
3463
4039
  compressedSize: compressionResult.compressedSize,
@@ -3465,7 +4041,7 @@ class ReactNativeCacheAdapter {
3465
4041
  savings: compressionResult.originalSize - compressionResult.compressedSize,
3466
4042
  });
3467
4043
  }
3468
- log$e.debug('Setting item with metadata', {
4044
+ log$d.debug('Setting item with metadata', {
3469
4045
  key,
3470
4046
  timestamp: item.timestamp,
3471
4047
  compressed: isCompressed,
@@ -3491,14 +4067,14 @@ class ReactNativeCacheAdapter {
3491
4067
  `;
3492
4068
  params = [key, finalData, item.timestamp];
3493
4069
  }
3494
- log$e.debug('Executing setItem SQL', { key, paramsCount: params.length });
4070
+ log$d.debug('Executing setItem SQL', { key, paramsCount: params.length });
3495
4071
  await this.executeSql(sql, params);
3496
4072
  }
3497
4073
  async setBatch(items) {
3498
4074
  if (items.length === 0)
3499
4075
  return;
3500
4076
  await this.ensureInitialized();
3501
- log$e.debug('Batch setting items', { count: items.length });
4077
+ log$d.debug('Batch setting items', { count: items.length });
3502
4078
  if (this.isExpo) {
3503
4079
  await this.db.withTransactionAsync(async () => {
3504
4080
  for (const [key, item] of items) {
@@ -3516,7 +4092,7 @@ class ReactNativeCacheAdapter {
3516
4092
  }, reject, () => resolve());
3517
4093
  });
3518
4094
  }
3519
- log$e.debug('Batch operation completed', { count: items.length });
4095
+ log$d.debug('Batch operation completed', { count: items.length });
3520
4096
  }
3521
4097
  async setBatchItem(key, item) {
3522
4098
  // Handle compression if enabled and compressed column is available
@@ -3690,10 +4266,10 @@ class MemoryCacheAdapter {
3690
4266
  return keySize + itemSize;
3691
4267
  }
3692
4268
  async get(key) {
3693
- log$e.debug('Getting cache item', { key });
4269
+ log$d.debug('Getting cache item', { key });
3694
4270
  const item = this.cache.get(key);
3695
4271
  if (!item) {
3696
- log$e.debug('Cache miss', { key });
4272
+ log$d.debug('Cache miss', { key });
3697
4273
  return null;
3698
4274
  }
3699
4275
  // Handle decompression if needed
@@ -3703,7 +4279,7 @@ class MemoryCacheAdapter {
3703
4279
  const decompressed = decompressData(item.data, true);
3704
4280
  finalData = JSON.parse(decompressed.data);
3705
4281
  }
3706
- log$e.debug('Cache hit', { key, compressed: isCompressed });
4282
+ log$d.debug('Cache hit', { key, compressed: isCompressed });
3707
4283
  return {
3708
4284
  ...item,
3709
4285
  data: finalData,
@@ -3711,7 +4287,7 @@ class MemoryCacheAdapter {
3711
4287
  };
3712
4288
  }
3713
4289
  async set(key, data) {
3714
- log$e.debug('Setting cache item', { key });
4290
+ log$d.debug('Setting cache item', { key });
3715
4291
  // Handle compression if enabled
3716
4292
  let finalData = data;
3717
4293
  let isCompressed = false;
@@ -3721,7 +4297,7 @@ class MemoryCacheAdapter {
3721
4297
  if (compressionResult.compressed) {
3722
4298
  finalData = compressionResult.data;
3723
4299
  isCompressed = true;
3724
- log$e.debug('Compression result', {
4300
+ log$d.debug('Compression result', {
3725
4301
  key,
3726
4302
  originalSize: compressionResult.originalSize,
3727
4303
  compressedSize: compressionResult.compressedSize,
@@ -3753,13 +4329,13 @@ class MemoryCacheAdapter {
3753
4329
  const oldestItemSize = this.calculateItemSize(oldestKey, oldestItem);
3754
4330
  this.totalBytes -= oldestItemSize;
3755
4331
  this.cache.delete(oldestKey);
3756
- log$e.debug('Removed oldest item for capacity', { oldestKey, freedBytes: oldestItemSize });
4332
+ log$d.debug('Removed oldest item for capacity', { oldestKey, freedBytes: oldestItemSize });
3757
4333
  }
3758
4334
  }
3759
4335
  // Set new item and update total size
3760
4336
  this.cache.set(key, item);
3761
4337
  this.totalBytes += newItemSize;
3762
- log$e.debug('Updated cache size', {
4338
+ log$d.debug('Updated cache size', {
3763
4339
  entries: this.cache.size,
3764
4340
  totalBytes: this.totalBytes,
3765
4341
  newItemSize,
@@ -3768,7 +4344,7 @@ class MemoryCacheAdapter {
3768
4344
  async setBatch(items) {
3769
4345
  if (items.length === 0)
3770
4346
  return;
3771
- log$e.debug('Batch setting items', { count: items.length });
4347
+ log$d.debug('Batch setting items', { count: items.length });
3772
4348
  let totalNewBytes = 0;
3773
4349
  let totalOldBytes = 0;
3774
4350
  const itemsToRemove = [];
@@ -3797,7 +4373,7 @@ class MemoryCacheAdapter {
3797
4373
  itemsToRemove.push(oldKey);
3798
4374
  }
3799
4375
  if (itemsToRemove.length > 0) {
3800
- log$e.debug('Removed items for batch capacity', {
4376
+ log$d.debug('Removed items for batch capacity', {
3801
4377
  removedCount: itemsToRemove.length,
3802
4378
  removedKeys: itemsToRemove,
3803
4379
  });
@@ -3809,7 +4385,7 @@ class MemoryCacheAdapter {
3809
4385
  for (const [key, item] of items) {
3810
4386
  this.cache.set(key, item);
3811
4387
  }
3812
- log$e.debug('Batch operation completed', {
4388
+ log$d.debug('Batch operation completed', {
3813
4389
  count: items.length,
3814
4390
  totalBytes: this.totalBytes,
3815
4391
  entries: this.cache.size,
@@ -3831,7 +4407,7 @@ class MemoryCacheAdapter {
3831
4407
  }
3832
4408
  }
3833
4409
  if (removed > 0) {
3834
- log$e.debug('Invalidation completed', {
4410
+ log$d.debug('Invalidation completed', {
3835
4411
  pattern,
3836
4412
  entriesRemoved: removed,
3837
4413
  bytesFreed,
@@ -3843,7 +4419,7 @@ class MemoryCacheAdapter {
3843
4419
  async clear() {
3844
4420
  this.cache.clear();
3845
4421
  this.totalBytes = 0;
3846
- log$e.debug('Cache cleared', { entries: 0, bytes: 0 });
4422
+ log$d.debug('Cache cleared', { entries: 0, bytes: 0 });
3847
4423
  }
3848
4424
  async getSize() {
3849
4425
  return {
@@ -4174,7 +4750,7 @@ replaceTraps((oldTraps) => ({
4174
4750
  },
4175
4751
  }));
4176
4752
 
4177
- const log$d = createPrefixedLogger('CACHE-WEB');
4753
+ const log$c = createPrefixedLogger('CACHE-WEB');
4178
4754
  /**
4179
4755
  * Web cache adapter using IndexedDB with automatic error recovery
4180
4756
  * Cache never expires - data persists until explicitly invalidated
@@ -4197,18 +4773,18 @@ class WebCacheAdapter {
4197
4773
  async initialize() {
4198
4774
  if (this.db)
4199
4775
  return;
4200
- log$d.debug('Initializing IndexedDB cache', {
4776
+ log$c.debug('Initializing IndexedDB cache', {
4201
4777
  dbName: WebCacheAdapter.DB_NAME,
4202
4778
  version: WebCacheAdapter.DB_VERSION,
4203
4779
  });
4204
4780
  try {
4205
4781
  this.db = await this.openDatabase();
4206
- log$d.debug('IndexedDB cache initialized successfully');
4782
+ log$c.debug('IndexedDB cache initialized successfully');
4207
4783
  this.retryCount = 0; // Reset retry count on success
4208
4784
  }
4209
4785
  catch (error) {
4210
4786
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
4211
- log$d.debug('Failed to initialize IndexedDB', { error: errorMessage });
4787
+ log$c.debug('Failed to initialize IndexedDB', { error: errorMessage });
4212
4788
  // Check if this is a version conflict error
4213
4789
  if (this.isVersionConflictError(errorMessage)) {
4214
4790
  await this.handleVersionConflict();
@@ -4221,32 +4797,32 @@ class WebCacheAdapter {
4221
4797
  async openDatabase() {
4222
4798
  return await openDB(WebCacheAdapter.DB_NAME, WebCacheAdapter.DB_VERSION, {
4223
4799
  upgrade: (db, oldVersion, newVersion, transaction) => {
4224
- log$d.debug('Database upgrade needed', { oldVersion, newVersion });
4800
+ log$c.debug('Database upgrade needed', { oldVersion, newVersion });
4225
4801
  this.handleUpgrade(db, oldVersion, newVersion, transaction);
4226
4802
  },
4227
4803
  blocked: () => {
4228
- log$d.debug('Database blocked - another tab may be open');
4804
+ log$c.debug('Database blocked - another tab may be open');
4229
4805
  },
4230
4806
  blocking: () => {
4231
- log$d.debug('Database blocking - will close connection');
4807
+ log$c.debug('Database blocking - will close connection');
4232
4808
  if (this.db) {
4233
4809
  this.db.close();
4234
4810
  this.db = null;
4235
4811
  }
4236
4812
  },
4237
4813
  terminated: () => {
4238
- log$d.debug('Database connection terminated unexpectedly');
4814
+ log$c.debug('Database connection terminated unexpectedly');
4239
4815
  this.db = null;
4240
4816
  },
4241
4817
  });
4242
4818
  }
4243
4819
  handleUpgrade(db, oldVersion, newVersion, transaction) {
4244
- log$d.debug('Handling database upgrade', { oldVersion, newVersion });
4820
+ log$c.debug('Handling database upgrade', { oldVersion, newVersion });
4245
4821
  // Create cache store if it doesn't exist (initial setup)
4246
4822
  if (!db.objectStoreNames.contains(WebCacheAdapter.STORE_NAME)) {
4247
4823
  const store = db.createObjectStore(WebCacheAdapter.STORE_NAME, { keyPath: 'key' });
4248
4824
  store.createIndex('timestamp', 'timestamp', { unique: false });
4249
- log$d.debug('Created cache store and timestamp index');
4825
+ log$c.debug('Created cache store and timestamp index');
4250
4826
  }
4251
4827
  // Handle migration from version 1 to 2
4252
4828
  if (oldVersion < 2) {
@@ -4257,16 +4833,16 @@ class WebCacheAdapter {
4257
4833
  try {
4258
4834
  if (store.indexNames.contains(indexName)) {
4259
4835
  store.deleteIndex(indexName);
4260
- log$d.debug(`Removed unused index: ${indexName}`);
4836
+ log$c.debug(`Removed unused index: ${indexName}`);
4261
4837
  }
4262
4838
  }
4263
4839
  catch (error) {
4264
4840
  // Ignore errors if indexes don't exist
4265
- log$d.debug(`Warning: Could not remove index ${indexName}`, error);
4841
+ log$c.debug(`Warning: Could not remove index ${indexName}`, error);
4266
4842
  }
4267
4843
  });
4268
4844
  }
4269
- log$d.debug('Database upgrade completed');
4845
+ log$c.debug('Database upgrade completed');
4270
4846
  }
4271
4847
  isVersionConflictError(errorMessage) {
4272
4848
  return (errorMessage.includes('less than the existing version') ||
@@ -4274,7 +4850,7 @@ class WebCacheAdapter {
4274
4850
  errorMessage.includes('VersionError'));
4275
4851
  }
4276
4852
  async handleVersionConflict() {
4277
- log$d.debug('Handling version conflict, attempting recovery...');
4853
+ log$c.debug('Handling version conflict, attempting recovery...');
4278
4854
  if (this.retryCount >= this.maxRetries) {
4279
4855
  throw new Error('Failed to resolve IndexedDB version conflict after multiple attempts');
4280
4856
  }
@@ -4286,19 +4862,19 @@ class WebCacheAdapter {
4286
4862
  this.db = null;
4287
4863
  }
4288
4864
  // Delete the problematic database
4289
- log$d.debug('Deleting problematic database to resolve version conflict');
4865
+ log$c.debug('Deleting problematic database to resolve version conflict');
4290
4866
  await deleteDB(WebCacheAdapter.DB_NAME);
4291
4867
  // Wait a bit for the deletion to complete
4292
4868
  await new Promise((resolve) => setTimeout(resolve, 200));
4293
4869
  // Try to open the database again
4294
- log$d.debug(`Retrying database initialization (attempt ${this.retryCount}/${this.maxRetries})`);
4870
+ log$c.debug(`Retrying database initialization (attempt ${this.retryCount}/${this.maxRetries})`);
4295
4871
  this.db = await this.openDatabase();
4296
- log$d.debug('Successfully recovered from version conflict');
4872
+ log$c.debug('Successfully recovered from version conflict');
4297
4873
  this.retryCount = 0; // Reset retry count on success
4298
4874
  }
4299
4875
  catch (retryError) {
4300
4876
  const retryErrorMessage = retryError instanceof Error ? retryError.message : 'Unknown error';
4301
- log$d.debug('Recovery attempt failed', { attempt: this.retryCount, error: retryErrorMessage });
4877
+ log$c.debug('Recovery attempt failed', { attempt: this.retryCount, error: retryErrorMessage });
4302
4878
  if (this.retryCount < this.maxRetries) {
4303
4879
  // Try again
4304
4880
  await this.handleVersionConflict();
@@ -4310,7 +4886,7 @@ class WebCacheAdapter {
4310
4886
  }
4311
4887
  async get(key) {
4312
4888
  await this.ensureInitialized();
4313
- log$d.debug('Getting cache item', { key });
4889
+ log$c.debug('Getting cache item', { key });
4314
4890
  try {
4315
4891
  const transaction = this.db.transaction([WebCacheAdapter.STORE_NAME], 'readonly');
4316
4892
  const store = transaction.objectStore(WebCacheAdapter.STORE_NAME);
@@ -4336,7 +4912,7 @@ class WebCacheAdapter {
4336
4912
  };
4337
4913
  }
4338
4914
  catch (error) {
4339
- log$d.debug('Error getting cache item', { key, error });
4915
+ log$c.debug('Error getting cache item', { key, error });
4340
4916
  return null; // Return null on error instead of throwing
4341
4917
  }
4342
4918
  }
@@ -4358,7 +4934,7 @@ class WebCacheAdapter {
4358
4934
  if (compressionResult.compressed) {
4359
4935
  finalData = compressionResult.data;
4360
4936
  isCompressed = true;
4361
- log$d.debug('Compression result', {
4937
+ log$c.debug('Compression result', {
4362
4938
  key,
4363
4939
  originalSize: compressionResult.originalSize,
4364
4940
  compressedSize: compressionResult.compressedSize,
@@ -4367,7 +4943,7 @@ class WebCacheAdapter {
4367
4943
  });
4368
4944
  }
4369
4945
  }
4370
- log$d.debug('Setting cache item', { key, timestamp: item.timestamp, compressed: isCompressed });
4946
+ log$c.debug('Setting cache item', { key, timestamp: item.timestamp, compressed: isCompressed });
4371
4947
  const storedItem = {
4372
4948
  key,
4373
4949
  data: finalData,
@@ -4380,7 +4956,7 @@ class WebCacheAdapter {
4380
4956
  await store.put(storedItem);
4381
4957
  }
4382
4958
  catch (error) {
4383
- log$d.debug('Error setting cache item', { key, error });
4959
+ log$c.debug('Error setting cache item', { key, error });
4384
4960
  // Silently fail for cache writes
4385
4961
  }
4386
4962
  }
@@ -4388,7 +4964,7 @@ class WebCacheAdapter {
4388
4964
  if (items.length === 0)
4389
4965
  return;
4390
4966
  await this.ensureInitialized();
4391
- log$d.debug('Batch setting items', { count: items.length });
4967
+ log$c.debug('Batch setting items', { count: items.length });
4392
4968
  try {
4393
4969
  const transaction = this.db.transaction([WebCacheAdapter.STORE_NAME], 'readwrite');
4394
4970
  const store = transaction.objectStore(WebCacheAdapter.STORE_NAME);
@@ -4398,10 +4974,10 @@ class WebCacheAdapter {
4398
4974
  return store.put(storedItem);
4399
4975
  });
4400
4976
  await Promise.all(promises);
4401
- log$d.debug('Batch operation completed', { count: items.length });
4977
+ log$c.debug('Batch operation completed', { count: items.length });
4402
4978
  }
4403
4979
  catch (error) {
4404
- log$d.debug('Error in batch operation', { count: items.length, error });
4980
+ log$c.debug('Error in batch operation', { count: items.length, error });
4405
4981
  // Silently fail for batch writes
4406
4982
  }
4407
4983
  }
@@ -4436,10 +5012,10 @@ class WebCacheAdapter {
4436
5012
  const transaction = this.db.transaction([WebCacheAdapter.STORE_NAME], 'readwrite');
4437
5013
  const store = transaction.objectStore(WebCacheAdapter.STORE_NAME);
4438
5014
  await store.clear();
4439
- log$d.debug('Cache cleared successfully');
5015
+ log$c.debug('Cache cleared successfully');
4440
5016
  }
4441
5017
  catch (error) {
4442
- log$d.debug('Error clearing cache', error);
5018
+ log$c.debug('Error clearing cache', error);
4443
5019
  // Silently fail for cache clear
4444
5020
  }
4445
5021
  }
@@ -4465,7 +5041,7 @@ class WebCacheAdapter {
4465
5041
  };
4466
5042
  }
4467
5043
  catch (error) {
4468
- log$d.debug('Error getting cache size', error);
5044
+ log$c.debug('Error getting cache size', error);
4469
5045
  return {
4470
5046
  entries: 0,
4471
5047
  bytes: 0,
@@ -4490,7 +5066,7 @@ class WebCacheAdapter {
4490
5066
  return allKeys.filter((key) => regex.test(key));
4491
5067
  }
4492
5068
  catch (error) {
4493
- log$d.debug('Error getting cache keys', error);
5069
+ log$c.debug('Error getting cache keys', error);
4494
5070
  return [];
4495
5071
  }
4496
5072
  }
@@ -4503,7 +5079,7 @@ class WebCacheAdapter {
4503
5079
  return true;
4504
5080
  }
4505
5081
  catch (error) {
4506
- log$d.debug('Error deleting cache item', { key, error });
5082
+ log$c.debug('Error deleting cache item', { key, error });
4507
5083
  return false;
4508
5084
  }
4509
5085
  }
@@ -4515,7 +5091,7 @@ class WebCacheAdapter {
4515
5091
  await this.initPromise;
4516
5092
  }
4517
5093
  catch (error) {
4518
- log$d.debug('Failed to ensure initialization', error);
5094
+ log$c.debug('Failed to ensure initialization', error);
4519
5095
  // Reset and try once more
4520
5096
  this.initPromise = null;
4521
5097
  this.db = null;
@@ -4534,7 +5110,7 @@ WebCacheAdapter.DB_NAME = 'acube_cache';
4534
5110
  WebCacheAdapter.DB_VERSION = 2;
4535
5111
  WebCacheAdapter.STORE_NAME = 'cache_entries';
4536
5112
 
4537
- const log$c = createPrefixedLogger('CACHE-LOADER');
5113
+ const log$b = createPrefixedLogger('CACHE-LOADER');
4538
5114
  function loadCacheAdapter(platform) {
4539
5115
  try {
4540
5116
  switch (platform) {
@@ -4566,7 +5142,7 @@ function loadCacheAdapter(platform) {
4566
5142
  }
4567
5143
  }
4568
5144
  catch (error) {
4569
- log$c.warn(`Cache adapter not available for platform ${platform}:`, error);
5145
+ log$b.warn(`Cache adapter not available for platform ${platform}:`, error);
4570
5146
  return undefined;
4571
5147
  }
4572
5148
  }
@@ -4623,7 +5199,7 @@ class BaseSecureStorageAdapter {
4623
5199
  }
4624
5200
  }
4625
5201
 
4626
- const log$b = createPrefixedLogger('NETWORK-BASE');
5202
+ const log$a = createPrefixedLogger('NETWORK-BASE');
4627
5203
  class NetworkBase {
4628
5204
  constructor(initialOnline = true, debounceMs = 300) {
4629
5205
  this.destroy$ = new Subject();
@@ -4643,14 +5219,14 @@ class NetworkBase {
4643
5219
  const current = this.statusSubject.getValue();
4644
5220
  if (current.online !== online) {
4645
5221
  this.statusSubject.next({ online, timestamp: Date.now() });
4646
- log$b.debug(`Network status changed: ${online ? 'online' : 'offline'}`);
5222
+ log$a.debug(`Network status changed: ${online ? 'online' : 'offline'}`);
4647
5223
  }
4648
5224
  }
4649
5225
  destroy() {
4650
5226
  this.destroy$.next();
4651
5227
  this.destroy$.complete();
4652
5228
  this.statusSubject.complete();
4653
- log$b.debug('Network monitor destroyed');
5229
+ log$a.debug('Network monitor destroyed');
4654
5230
  }
4655
5231
  }
4656
5232
 
@@ -4710,7 +5286,7 @@ class NodeSecureStorageAdapter extends BaseSecureStorageAdapter {
4710
5286
  }
4711
5287
  }
4712
5288
 
4713
- const log$a = createPrefixedLogger('RN-STORAGE');
5289
+ const log$9 = createPrefixedLogger('RN-STORAGE');
4714
5290
  /**
4715
5291
  * React Native storage adapter using AsyncStorage
4716
5292
  * Note: Uses native batch operations for better performance (not base class)
@@ -4742,7 +5318,7 @@ class ReactNativeStorageAdapter {
4742
5318
  return await this.AsyncStorage.getItem(key);
4743
5319
  }
4744
5320
  catch (error) {
4745
- log$a.error('Failed to get item from AsyncStorage:', error);
5321
+ log$9.error('Failed to get item from AsyncStorage:', error);
4746
5322
  return null;
4747
5323
  }
4748
5324
  }
@@ -4783,7 +5359,7 @@ class ReactNativeStorageAdapter {
4783
5359
  return await this.AsyncStorage.getAllKeys();
4784
5360
  }
4785
5361
  catch (error) {
4786
- log$a.error('Failed to get all keys:', error);
5362
+ log$9.error('Failed to get all keys:', error);
4787
5363
  return [];
4788
5364
  }
4789
5365
  }
@@ -4800,7 +5376,7 @@ class ReactNativeStorageAdapter {
4800
5376
  return result;
4801
5377
  }
4802
5378
  catch (error) {
4803
- log$a.error('Failed to get multiple items:', error);
5379
+ log$9.error('Failed to get multiple items:', error);
4804
5380
  const result = {};
4805
5381
  keys.forEach((key) => {
4806
5382
  result[key] = null;
@@ -4850,7 +5426,7 @@ class ReactNativeSecureStorageAdapter extends BaseSecureStorageAdapter {
4850
5426
  return;
4851
5427
  }
4852
5428
  catch {
4853
- log$a.debug('expo-secure-store not available, trying react-native-keychain');
5429
+ log$9.debug('expo-secure-store not available, trying react-native-keychain');
4854
5430
  }
4855
5431
  try {
4856
5432
  const Keychain = require('react-native-keychain');
@@ -4859,7 +5435,7 @@ class ReactNativeSecureStorageAdapter extends BaseSecureStorageAdapter {
4859
5435
  return;
4860
5436
  }
4861
5437
  catch {
4862
- log$a.error('react-native-keychain not available');
5438
+ log$9.error('react-native-keychain not available');
4863
5439
  }
4864
5440
  throw new Error('No secure storage available. Please install expo-secure-store or react-native-keychain');
4865
5441
  }
@@ -4877,7 +5453,7 @@ class ReactNativeSecureStorageAdapter extends BaseSecureStorageAdapter {
4877
5453
  }
4878
5454
  }
4879
5455
  catch (error) {
4880
- log$a.error('Failed to get secure item:', error);
5456
+ log$9.error('Failed to get secure item:', error);
4881
5457
  }
4882
5458
  return null;
4883
5459
  }
@@ -4914,10 +5490,10 @@ class ReactNativeSecureStorageAdapter extends BaseSecureStorageAdapter {
4914
5490
  }
4915
5491
  }
4916
5492
  async clear() {
4917
- log$a.warn('Clear all secure items not fully implemented for React Native');
5493
+ log$9.warn('Clear all secure items not fully implemented for React Native');
4918
5494
  }
4919
5495
  async getAllKeys() {
4920
- log$a.warn('Get all secure keys not implemented for React Native');
5496
+ log$9.warn('Get all secure keys not implemented for React Native');
4921
5497
  return [];
4922
5498
  }
4923
5499
  async isAvailable() {
@@ -5135,7 +5711,7 @@ class NodeNetworkMonitor extends NetworkBase {
5135
5711
  }
5136
5712
  }
5137
5713
 
5138
- const log$9 = createPrefixedLogger('RN-NETWORK');
5714
+ const log$8 = createPrefixedLogger('RN-NETWORK');
5139
5715
  /**
5140
5716
  * React Native network monitor using RxJS
5141
5717
  * Supports both @react-native-community/netinfo and expo-network
@@ -5148,7 +5724,7 @@ class ReactNativeNetworkMonitor extends NetworkBase {
5148
5724
  this.moduleReady$ = new Subject();
5149
5725
  this.isExpo = detectPlatform().isExpo;
5150
5726
  this.init().catch((error) => {
5151
- log$9.error('Network monitor initialization failed:', error);
5727
+ log$8.error('Network monitor initialization failed:', error);
5152
5728
  });
5153
5729
  }
5154
5730
  async init() {
@@ -5167,10 +5743,10 @@ class ReactNativeNetworkMonitor extends NetworkBase {
5167
5743
  try {
5168
5744
  const module = require('@react-native-community/netinfo');
5169
5745
  this.netInfoModule = module.default || module;
5170
- log$9.debug('Loaded @react-native-community/netinfo module');
5746
+ log$8.debug('Loaded @react-native-community/netinfo module');
5171
5747
  }
5172
5748
  catch (error) {
5173
- log$9.error('Failed to load React Native NetInfo module:', error);
5749
+ log$8.error('Failed to load React Native NetInfo module:', error);
5174
5750
  this.netInfoModule = null;
5175
5751
  }
5176
5752
  }
@@ -5178,10 +5754,10 @@ class ReactNativeNetworkMonitor extends NetworkBase {
5178
5754
  try {
5179
5755
  const module = require('expo-network');
5180
5756
  this.netInfoModule = module.default || module;
5181
- log$9.debug('Loaded expo-network module');
5757
+ log$8.debug('Loaded expo-network module');
5182
5758
  }
5183
5759
  catch (error) {
5184
- log$9.error('Failed to load Expo Network module:', error);
5760
+ log$8.error('Failed to load Expo Network module:', error);
5185
5761
  this.netInfoModule = null;
5186
5762
  }
5187
5763
  }
@@ -5198,16 +5774,16 @@ class ReactNativeNetworkMonitor extends NetworkBase {
5198
5774
  }
5199
5775
  const online = !!(state.isConnected && state.isInternetReachable !== false);
5200
5776
  this.updateStatus(online);
5201
- log$9.debug('Initial network state:', online ? 'online' : 'offline');
5777
+ log$8.debug('Initial network state:', online ? 'online' : 'offline');
5202
5778
  }
5203
5779
  catch (error) {
5204
- log$9.warn('Could not fetch initial network state:', error);
5780
+ log$8.warn('Could not fetch initial network state:', error);
5205
5781
  }
5206
5782
  }
5207
5783
  subscribeToStateChanges() {
5208
5784
  if (!this.netInfoModule)
5209
5785
  return;
5210
- log$9.debug('Subscribing to network state changes');
5786
+ log$8.debug('Subscribing to network state changes');
5211
5787
  const handleState = (state) => {
5212
5788
  const online = !!(state.isConnected && (state.isInternetReachable ?? true));
5213
5789
  this.updateStatus(online);
@@ -5249,7 +5825,7 @@ class ReactNativeNetworkMonitor extends NetworkBase {
5249
5825
  };
5250
5826
  }
5251
5827
  catch (error) {
5252
- log$9.error('Failed to fetch detailed network info:', error);
5828
+ log$8.error('Failed to fetch detailed network info:', error);
5253
5829
  return null;
5254
5830
  }
5255
5831
  }
@@ -5385,7 +5961,7 @@ class CertificateValidator {
5385
5961
  }
5386
5962
  }
5387
5963
 
5388
- const log$8 = createPrefixedLogger('RN-MTLS');
5964
+ const log$7 = createPrefixedLogger('RN-MTLS');
5389
5965
  /**
5390
5966
  * React Native mTLS Adapter using @a-cube-io/expo-mutual-tls
5391
5967
  */
@@ -5407,7 +5983,7 @@ class ReactNativeMTLSAdapter {
5407
5983
  this.expoMTLS = ExpoMutualTls;
5408
5984
  // Set up debug logging with the correct event signature
5409
5985
  const debugListener = ExpoMutualTls.onDebugLog((event) => {
5410
- log$8.debug(`${event.type}: ${event.message}`, {
5986
+ log$7.debug(`${event.type}: ${event.message}`, {
5411
5987
  method: event.method,
5412
5988
  url: event.url,
5413
5989
  statusCode: event.statusCode,
@@ -5417,28 +5993,28 @@ class ReactNativeMTLSAdapter {
5417
5993
  this.eventListeners.push(debugListener);
5418
5994
  // Set up error logging with the correct event signature
5419
5995
  const errorListener = ExpoMutualTls.onError((event) => {
5420
- log$8.error(event.message, {
5996
+ log$7.error(event.message, {
5421
5997
  code: event.code,
5422
5998
  });
5423
5999
  });
5424
6000
  this.eventListeners.push(errorListener);
5425
6001
  // Set up certificate expiry monitoring with the correct event signature
5426
6002
  const expiryListener = ExpoMutualTls.onCertificateExpiry((event) => {
5427
- log$8.warn(`Certificate ${event.subject} expires at ${new Date(event.expiry)}`, {
6003
+ log$7.warn(`Certificate ${event.subject} expires at ${new Date(event.expiry)}`, {
5428
6004
  alias: event.alias,
5429
6005
  warning: event.warning,
5430
6006
  });
5431
6007
  });
5432
6008
  this.eventListeners.push(expiryListener);
5433
- log$8.debug('Expo mTLS module loaded successfully');
6009
+ log$7.debug('Expo mTLS module loaded successfully');
5434
6010
  }
5435
6011
  catch (error) {
5436
- log$8.warn('@a-cube-io/expo-mutual-tls not available:', error);
6012
+ log$7.warn('@a-cube-io/expo-mutual-tls not available:', error);
5437
6013
  }
5438
6014
  }
5439
6015
  async isMTLSSupported() {
5440
6016
  const supported = this.expoMTLS !== null;
5441
- log$8.debug('mTLS support check:', {
6017
+ log$7.debug('mTLS support check:', {
5442
6018
  supported,
5443
6019
  platform: this.getPlatformInfo().platform,
5444
6020
  moduleAvailable: !!this.expoMTLS,
@@ -5450,7 +6026,7 @@ class ReactNativeMTLSAdapter {
5450
6026
  throw new MTLSError(MTLSErrorType$1.NOT_SUPPORTED, 'Expo mTLS module not available');
5451
6027
  }
5452
6028
  this.config = config;
5453
- log$8.debug('Initialized with config:', {
6029
+ log$7.debug('Initialized with config:', {
5454
6030
  baseUrl: config.baseUrl,
5455
6031
  port: config.port,
5456
6032
  timeout: config.timeout,
@@ -5464,7 +6040,7 @@ class ReactNativeMTLSAdapter {
5464
6040
  if (!this.config) {
5465
6041
  throw new MTLSError(MTLSErrorType$1.CONFIGURATION_ERROR, 'Adapter not initialized. Call initialize() first.');
5466
6042
  }
5467
- log$8.debug('Configuring certificate:', {
6043
+ log$7.debug('Configuring certificate:', {
5468
6044
  format: certificateData.format,
5469
6045
  hasPassword: !!certificateData.password,
5470
6046
  certificateLength: certificateData.certificate.length,
@@ -5481,14 +6057,14 @@ class ReactNativeMTLSAdapter {
5481
6057
  'client-key-service', // keyService
5482
6058
  true // enableLogging - let the native module handle its own debug logging
5483
6059
  );
5484
- log$8.debug('PEM services configured:', configResult);
6060
+ log$7.debug('PEM services configured:', configResult);
5485
6061
  if (!configResult.success) {
5486
6062
  throw new MTLSError(MTLSErrorType$1.CONFIGURATION_ERROR, `PEM configuration failed: ${configResult.state}`);
5487
6063
  }
5488
6064
  // Step 2: Store the actual PEM certificate and private key
5489
6065
  const storeResult = await this.expoMTLS.storePEM(certificateData.certificate, certificateData.privateKey, certificateData.password // passphrase (optional)
5490
6066
  );
5491
- log$8.debug('PEM certificate store result:', storeResult);
6067
+ log$7.debug('PEM certificate store result:', storeResult);
5492
6068
  if (!storeResult) {
5493
6069
  throw new MTLSError(MTLSErrorType$1.CERTIFICATE_INVALID, 'Failed to store PEM certificate');
5494
6070
  }
@@ -5501,14 +6077,14 @@ class ReactNativeMTLSAdapter {
5501
6077
  const configResult = await this.expoMTLS.configureP12('client-p12-service', // keychainService
5502
6078
  true // enableLogging - let the native module handle its own debug logging
5503
6079
  );
5504
- log$8.debug('P12 service configured:', configResult);
6080
+ log$7.debug('P12 service configured:', configResult);
5505
6081
  if (!configResult.success) {
5506
6082
  throw new MTLSError(MTLSErrorType$1.CONFIGURATION_ERROR, `P12 configuration failed: ${configResult.state}`);
5507
6083
  }
5508
6084
  // Step 2: Store the P12 certificate data
5509
6085
  const storeResult = await this.expoMTLS.storeP12(certificateData.certificate, // P12 data in certificate field
5510
6086
  certificateData.password);
5511
- log$8.debug('P12 certificate store result:', storeResult);
6087
+ log$7.debug('P12 certificate store result:', storeResult);
5512
6088
  if (!storeResult) {
5513
6089
  throw new MTLSError(MTLSErrorType$1.CERTIFICATE_INVALID, 'Failed to store P12 certificate');
5514
6090
  }
@@ -5522,7 +6098,7 @@ class ReactNativeMTLSAdapter {
5522
6098
  if (error instanceof MTLSError) {
5523
6099
  throw error;
5524
6100
  }
5525
- log$8.error('Certificate configuration failed:', error);
6101
+ log$7.error('Certificate configuration failed:', error);
5526
6102
  throw new MTLSError(MTLSErrorType$1.CONFIGURATION_ERROR, 'Failed to configure certificate', error);
5527
6103
  }
5528
6104
  }
@@ -5533,38 +6109,38 @@ class ReactNativeMTLSAdapter {
5533
6109
  try {
5534
6110
  // Use static method call
5535
6111
  const hasCert = await this.expoMTLS.hasCertificate();
5536
- log$8.debug('Certificate availability check:', hasCert);
6112
+ log$7.debug('Certificate availability check:', hasCert);
5537
6113
  return hasCert;
5538
6114
  }
5539
6115
  catch (error) {
5540
- log$8.error('Certificate check failed:', error);
6116
+ log$7.error('Certificate check failed:', error);
5541
6117
  return false;
5542
6118
  }
5543
6119
  }
5544
6120
  async getCertificateInfo() {
5545
6121
  if (!this.expoMTLS) {
5546
- log$8.debug('Certificate info requested but module not available');
6122
+ log$7.debug('Certificate info requested but module not available');
5547
6123
  return null;
5548
6124
  }
5549
6125
  try {
5550
6126
  const hasCert = await this.hasCertificate();
5551
6127
  if (!hasCert) {
5552
- log$8.debug('No certificate stored');
6128
+ log$7.debug('No certificate stored');
5553
6129
  return null;
5554
6130
  }
5555
6131
  // Use getCertificatesInfo to retrieve information about stored certificates
5556
6132
  const result = await this.expoMTLS.getCertificatesInfo();
5557
6133
  if (!result || !result.certificates || result.certificates.length === 0) {
5558
- log$8.debug('No certificate information available');
6134
+ log$7.debug('No certificate information available');
5559
6135
  return null;
5560
6136
  }
5561
6137
  // Get the first certificate (primary client certificate)
5562
6138
  const cert = result.certificates[0];
5563
6139
  if (!cert) {
5564
- log$8.debug('Certificate data is empty');
6140
+ log$7.debug('Certificate data is empty');
5565
6141
  return null;
5566
6142
  }
5567
- log$8.debug('Retrieved certificate info:', {
6143
+ log$7.debug('Retrieved certificate info:', {
5568
6144
  subject: cert.subject.commonName,
5569
6145
  issuer: cert.issuer.commonName,
5570
6146
  validFrom: new Date(cert.validFrom),
@@ -5583,7 +6159,7 @@ class ReactNativeMTLSAdapter {
5583
6159
  };
5584
6160
  }
5585
6161
  catch (error) {
5586
- log$8.error('Failed to get certificate info:', error);
6162
+ log$7.error('Failed to get certificate info:', error);
5587
6163
  return null;
5588
6164
  }
5589
6165
  }
@@ -5594,7 +6170,7 @@ class ReactNativeMTLSAdapter {
5594
6170
  */
5595
6171
  async parseCertificateData(certificateData) {
5596
6172
  if (!this.expoMTLS) {
5597
- log$8.debug('Parse certificate: Module not available');
6173
+ log$7.debug('Parse certificate: Module not available');
5598
6174
  return null;
5599
6175
  }
5600
6176
  try {
@@ -5611,14 +6187,14 @@ class ReactNativeMTLSAdapter {
5611
6187
  else {
5612
6188
  throw new MTLSError(MTLSErrorType$1.CERTIFICATE_INVALID, `Unsupported certificate format: ${certificateData.format}`);
5613
6189
  }
5614
- log$8.debug('Certificate parsed successfully:', {
6190
+ log$7.debug('Certificate parsed successfully:', {
5615
6191
  certificateCount: result.certificates.length,
5616
6192
  subjects: result.certificates.map((cert) => cert.subject.commonName),
5617
6193
  });
5618
6194
  return result;
5619
6195
  }
5620
6196
  catch (error) {
5621
- log$8.error('Failed to parse certificate:', error);
6197
+ log$7.error('Failed to parse certificate:', error);
5622
6198
  if (error instanceof MTLSError) {
5623
6199
  throw error;
5624
6200
  }
@@ -5633,7 +6209,7 @@ class ReactNativeMTLSAdapter {
5633
6209
  if (!hasCert) {
5634
6210
  throw new MTLSError(MTLSErrorType$1.CERTIFICATE_NOT_FOUND, 'No certificate configured');
5635
6211
  }
5636
- log$8.debug('Making mTLS request:', {
6212
+ log$7.debug('Making mTLS request:', {
5637
6213
  method: requestConfig.method || 'GET',
5638
6214
  url: requestConfig.url,
5639
6215
  headers: requestConfig.headers,
@@ -5641,7 +6217,7 @@ class ReactNativeMTLSAdapter {
5641
6217
  responseType: requestConfig.responseType,
5642
6218
  });
5643
6219
  if (requestConfig.data) {
5644
- log$8.debug('mTLS request body:', requestConfig.data);
6220
+ log$7.debug('mTLS request body:', requestConfig.data);
5645
6221
  }
5646
6222
  try {
5647
6223
  const response = await this.expoMTLS.request(requestConfig.url, {
@@ -5650,7 +6226,7 @@ class ReactNativeMTLSAdapter {
5650
6226
  body: requestConfig.data ? JSON.stringify(requestConfig.data) : undefined,
5651
6227
  responseType: requestConfig.responseType,
5652
6228
  });
5653
- log$8.debug('mTLS request successful:', response);
6229
+ log$7.debug('mTLS request successful:', response);
5654
6230
  if (!response.success) {
5655
6231
  throw new MTLSError(MTLSErrorType$1.CONNECTION_FAILED, `mTLS request failed: ${response.statusMessage} (${response.statusCode})`, undefined, response.statusCode);
5656
6232
  }
@@ -5662,7 +6238,7 @@ class ReactNativeMTLSAdapter {
5662
6238
  data = JSON.parse(response.body);
5663
6239
  }
5664
6240
  catch (parseError) {
5665
- log$8.warn('Failed to parse JSON response:', parseError);
6241
+ log$7.warn('Failed to parse JSON response:', parseError);
5666
6242
  // If parsing fails, keep raw body
5667
6243
  }
5668
6244
  }
@@ -5679,7 +6255,7 @@ class ReactNativeMTLSAdapter {
5679
6255
  };
5680
6256
  }
5681
6257
  catch (error) {
5682
- log$8.error('mTLS request failed:', error);
6258
+ log$7.error('mTLS request failed:', error);
5683
6259
  throw new MTLSError(MTLSErrorType$1.CONNECTION_FAILED, 'mTLS request failed', error);
5684
6260
  }
5685
6261
  }
@@ -5692,18 +6268,18 @@ class ReactNativeMTLSAdapter {
5692
6268
  */
5693
6269
  async testConnection() {
5694
6270
  if (!this.expoMTLS || !this.config) {
5695
- log$8.debug('Diagnostic test: No mTLS module or config available');
6271
+ log$7.debug('Diagnostic test: No mTLS module or config available');
5696
6272
  return false;
5697
6273
  }
5698
6274
  try {
5699
6275
  const hasCert = await this.hasCertificate();
5700
6276
  if (!hasCert) {
5701
- log$8.debug('Diagnostic test: No certificate configured');
6277
+ log$7.debug('Diagnostic test: No certificate configured');
5702
6278
  return false;
5703
6279
  }
5704
- log$8.debug('Running diagnostic test (may fail even if mTLS works):', this.config.baseUrl);
6280
+ log$7.debug('Running diagnostic test (may fail even if mTLS works):', this.config.baseUrl);
5705
6281
  const result = await this.expoMTLS.testConnection(this.config.baseUrl);
5706
- log$8.debug('Diagnostic test result (NOT validation):', {
6282
+ log$7.debug('Diagnostic test result (NOT validation):', {
5707
6283
  success: result.success,
5708
6284
  statusCode: result.statusCode,
5709
6285
  statusMessage: result.statusMessage,
@@ -5714,13 +6290,13 @@ class ReactNativeMTLSAdapter {
5714
6290
  return result.success;
5715
6291
  }
5716
6292
  catch (error) {
5717
- log$8.warn('Diagnostic test failed (this is expected):', error);
6293
+ log$7.warn('Diagnostic test failed (this is expected):', error);
5718
6294
  return false;
5719
6295
  }
5720
6296
  }
5721
6297
  async removeCertificate() {
5722
6298
  if (!this.expoMTLS) {
5723
- log$8.debug('Remove certificate: Module not available');
6299
+ log$7.debug('Remove certificate: Module not available');
5724
6300
  return;
5725
6301
  }
5726
6302
  try {
@@ -5729,10 +6305,10 @@ class ReactNativeMTLSAdapter {
5729
6305
  this.isConfigured = false;
5730
6306
  // Cleanup event listeners
5731
6307
  this.cleanupEventListeners();
5732
- log$8.debug('Certificate removed successfully');
6308
+ log$7.debug('Certificate removed successfully');
5733
6309
  }
5734
6310
  catch (error) {
5735
- log$8.error('Failed to remove certificate:', error);
6311
+ log$7.error('Failed to remove certificate:', error);
5736
6312
  throw new MTLSError(MTLSErrorType$1.CONFIGURATION_ERROR, 'Failed to remove certificate', error);
5737
6313
  }
5738
6314
  }
@@ -5741,7 +6317,7 @@ class ReactNativeMTLSAdapter {
5741
6317
  */
5742
6318
  cleanupEventListeners() {
5743
6319
  if (this.eventListeners.length > 0) {
5744
- log$8.debug(`Cleaning up ${this.eventListeners.length} event listeners`);
6320
+ log$7.debug(`Cleaning up ${this.eventListeners.length} event listeners`);
5745
6321
  }
5746
6322
  // Remove individual listeners if they have remove methods
5747
6323
  this.eventListeners.forEach((listener) => {
@@ -5778,7 +6354,7 @@ class ReactNativeMTLSAdapter {
5778
6354
  }
5779
6355
  }
5780
6356
 
5781
- const log$7 = createPrefixedLogger('WEB-MTLS');
6357
+ const log$6 = createPrefixedLogger('WEB-MTLS');
5782
6358
  /**
5783
6359
  * Web mTLS Adapter - Graceful fallback for web browsers
5784
6360
  *
@@ -5792,13 +6368,13 @@ const log$7 = createPrefixedLogger('WEB-MTLS');
5792
6368
  */
5793
6369
  class WebMTLSAdapter {
5794
6370
  constructor() {
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');
6371
+ log$6.warn('Web browsers do not support programmatic mTLS configuration');
6372
+ log$6.info('Use JWT authentication or configure client certificates in browser settings');
5797
6373
  }
5798
6374
  async isMTLSSupported() {
5799
6375
  // mTLS is not supported programmatically in web browsers
5800
6376
  const supported = false;
5801
- log$7.debug('mTLS support check:', {
6377
+ log$6.debug('mTLS support check:', {
5802
6378
  supported,
5803
6379
  platform: this.getPlatformInfo().platform,
5804
6380
  reason: 'Browser security model prevents programmatic certificate configuration',
@@ -5807,14 +6383,14 @@ class WebMTLSAdapter {
5807
6383
  return supported;
5808
6384
  }
5809
6385
  async initialize(config) {
5810
- log$7.warn('Initialized but mTLS not available in web browsers:', {
6386
+ log$6.warn('Initialized but mTLS not available in web browsers:', {
5811
6387
  baseUrl: config.baseUrl,
5812
6388
  port: config.port,
5813
6389
  recommendation: 'Use standard HTTPS with JWT authentication',
5814
6390
  });
5815
6391
  }
5816
6392
  async configureCertificate(certificateData) {
5817
- log$7.error('Certificate configuration attempted:', {
6393
+ log$6.error('Certificate configuration attempted:', {
5818
6394
  format: certificateData.format,
5819
6395
  reason: 'Not supported in web browsers',
5820
6396
  alternatives: [
@@ -5829,15 +6405,15 @@ class WebMTLSAdapter {
5829
6405
  }
5830
6406
  async hasCertificate() {
5831
6407
  // We cannot detect if the browser has certificates configured
5832
- log$7.debug('Certificate availability check: Cannot detect browser certificates programmatically');
6408
+ log$6.debug('Certificate availability check: Cannot detect browser certificates programmatically');
5833
6409
  return false;
5834
6410
  }
5835
6411
  async getCertificateInfo() {
5836
- log$7.debug('Certificate info requested: Not accessible in web browsers');
6412
+ log$6.debug('Certificate info requested: Not accessible in web browsers');
5837
6413
  return null;
5838
6414
  }
5839
6415
  async request(requestConfig) {
5840
- log$7.error('mTLS request attempted:', {
6416
+ log$6.error('mTLS request attempted:', {
5841
6417
  method: requestConfig.method,
5842
6418
  url: requestConfig.url,
5843
6419
  reason: 'Not supported in web browsers',
@@ -5852,11 +6428,11 @@ class WebMTLSAdapter {
5852
6428
  'are properly configured in the browser certificate store.');
5853
6429
  }
5854
6430
  async testConnection() {
5855
- log$7.debug('Connection test: mTLS not available in web browsers');
6431
+ log$6.debug('Connection test: mTLS not available in web browsers');
5856
6432
  return false;
5857
6433
  }
5858
6434
  async removeCertificate() {
5859
- log$7.debug('Remove certificate: No certificates to remove (not supported in web browsers)');
6435
+ log$6.debug('Remove certificate: No certificates to remove (not supported in web browsers)');
5860
6436
  // No-op - cannot remove certificates programmatically in browsers
5861
6437
  }
5862
6438
  /**
@@ -5864,7 +6440,7 @@ class WebMTLSAdapter {
5864
6440
  * Always returns null for web browsers as mTLS is not supported
5865
6441
  */
5866
6442
  getBaseUrl() {
5867
- log$7.debug('Base URL requested: Not supported in web browsers');
6443
+ log$6.debug('Base URL requested: Not supported in web browsers');
5868
6444
  return null;
5869
6445
  }
5870
6446
  getPlatformInfo() {
@@ -5897,7 +6473,7 @@ class WebMTLSAdapter {
5897
6473
  }
5898
6474
  }
5899
6475
 
5900
- const log$6 = createPrefixedLogger('MTLS-LOADER');
6476
+ const log$5 = createPrefixedLogger('MTLS-LOADER');
5901
6477
  function loadMTLSAdapter(platform, config) {
5902
6478
  try {
5903
6479
  let adapter;
@@ -5931,7 +6507,7 @@ function loadMTLSAdapter(platform, config) {
5931
6507
  return adapter;
5932
6508
  }
5933
6509
  catch (error) {
5934
- log$6.warn(`mTLS adapter not available for platform ${platform}:`, error);
6510
+ log$5.warn(`mTLS adapter not available for platform ${platform}:`, error);
5935
6511
  return null;
5936
6512
  }
5937
6513
  }
@@ -5941,7 +6517,7 @@ async function initializeAdapterAsync(adapter, config) {
5941
6517
  if (isSupported) {
5942
6518
  await adapter.initialize(config);
5943
6519
  const platformInfo = adapter.getPlatformInfo();
5944
- log$6.debug('mTLS adapter initialized:', {
6520
+ log$5.debug('mTLS adapter initialized:', {
5945
6521
  platform: platformInfo.platform,
5946
6522
  mtlsSupported: platformInfo.mtlsSupported,
5947
6523
  certificateStorage: platformInfo.certificateStorage,
@@ -5950,20 +6526,20 @@ async function initializeAdapterAsync(adapter, config) {
5950
6526
  }
5951
6527
  }
5952
6528
  catch (error) {
5953
- log$6.warn('Failed to initialize mTLS adapter:', error);
6529
+ log$5.warn('Failed to initialize mTLS adapter:', error);
5954
6530
  }
5955
6531
  }
5956
6532
 
5957
- const log$5 = createPrefixedLogger('ADAPTER-LOADER');
6533
+ const log$4 = createPrefixedLogger('ADAPTER-LOADER');
5958
6534
  function loadPlatformAdapters(options = {}) {
5959
6535
  const { mtlsConfig } = options;
5960
6536
  const { platform } = detectPlatform();
5961
- log$5.debug('Loading adapters for platform:', platform);
6537
+ log$4.debug('Loading adapters for platform:', platform);
5962
6538
  const storageAdapters = loadStorageAdapters(platform);
5963
6539
  const networkMonitor = loadNetworkMonitor(platform);
5964
6540
  const cache = loadCacheAdapter(platform);
5965
6541
  const mtls = loadMTLSAdapter(platform, mtlsConfig);
5966
- log$5.debug('Adapters loaded:', {
6542
+ log$4.debug('Adapters loaded:', {
5967
6543
  platform,
5968
6544
  hasStorage: !!storageAdapters.storage,
5969
6545
  hasSecureStorage: !!storageAdapters.secureStorage,
@@ -5989,92 +6565,6 @@ function createACubeMTLSConfig(baseUrl, timeout, autoInitialize = true, forcePor
5989
6565
  };
5990
6566
  }
5991
6567
 
5992
- class ConfigManager {
5993
- constructor(userConfig) {
5994
- this.config = this.buildConfig(userConfig);
5995
- }
5996
- buildConfig(userConfig) {
5997
- return {
5998
- environment: userConfig.environment,
5999
- apiUrl: this.getDefaultApiUrl(userConfig.environment),
6000
- authUrl: this.getDefaultAuthUrl(userConfig.environment),
6001
- timeout: 30000,
6002
- retryAttempts: 3,
6003
- debug: userConfig.debug ?? false,
6004
- customHeaders: {},
6005
- };
6006
- }
6007
- getDefaultApiUrl(environment) {
6008
- switch (environment) {
6009
- case 'production':
6010
- return 'https://ereceipts-it.acubeapi.com';
6011
- case 'development':
6012
- return 'https://ereceipts-it.dev.acubeapi.com';
6013
- case 'sandbox':
6014
- default:
6015
- return 'https://ereceipts-it-sandbox.acubeapi.com';
6016
- }
6017
- }
6018
- getDefaultAuthUrl(environment) {
6019
- switch (environment) {
6020
- case 'production':
6021
- return 'https://common.api.acubeapi.com';
6022
- case 'development':
6023
- case 'sandbox':
6024
- default:
6025
- return 'https://common-sandbox.api.acubeapi.com';
6026
- }
6027
- }
6028
- getConfig() {
6029
- return {
6030
- environment: this.config.environment,
6031
- debug: this.config.debug,
6032
- };
6033
- }
6034
- getApiUrl() {
6035
- return this.config.apiUrl;
6036
- }
6037
- getAuthUrl() {
6038
- return this.config.authUrl;
6039
- }
6040
- getEnvironment() {
6041
- return this.config.environment;
6042
- }
6043
- isDebugEnabled() {
6044
- return this.config.debug;
6045
- }
6046
- getTimeout() {
6047
- return this.config.timeout;
6048
- }
6049
- getRetryAttempts() {
6050
- return this.config.retryAttempts;
6051
- }
6052
- getCustomHeaders() {
6053
- return { ...this.config.customHeaders };
6054
- }
6055
- updateConfig(updates) {
6056
- if (updates.environment) {
6057
- this.config.environment = updates.environment;
6058
- this.config.apiUrl = this.getDefaultApiUrl(updates.environment);
6059
- this.config.authUrl = this.getDefaultAuthUrl(updates.environment);
6060
- }
6061
- if (updates.debug !== undefined) {
6062
- this.config.debug = updates.debug;
6063
- }
6064
- }
6065
- }
6066
-
6067
- class ACubeSDKError extends Error {
6068
- constructor(type, message, originalError, statusCode, violations) {
6069
- super(message);
6070
- this.type = type;
6071
- this.originalError = originalError;
6072
- this.statusCode = statusCode;
6073
- this.name = 'ACubeSDKError';
6074
- this.violations = violations;
6075
- }
6076
- }
6077
-
6078
6568
  const DI_TOKENS = {
6079
6569
  HTTP_PORT: Symbol('HTTP_PORT'),
6080
6570
  BASE_HTTP_PORT: Symbol('BASE_HTTP_PORT'),
@@ -7075,7 +7565,7 @@ class TelemetryRepositoryImpl {
7075
7565
  }
7076
7566
  }
7077
7567
 
7078
- const log$4 = createPrefixedLogger('CACHE-KEY');
7568
+ const log$3 = createPrefixedLogger('CACHE-KEY');
7079
7569
  const URL_PATTERNS = [
7080
7570
  // Receipt (mf1) - specific patterns first
7081
7571
  {
@@ -7168,7 +7658,7 @@ const DEFAULT_TTL = 5 * 60 * 1000; // 5 minutes
7168
7658
  class CacheKeyGenerator {
7169
7659
  constructor(customConfig) {
7170
7660
  this.config = { ...DEFAULT_TTL_CONFIG, ...customConfig };
7171
- log$4.info('CacheKeyGenerator initialized with config:', {
7661
+ log$3.info('CacheKeyGenerator initialized with config:', {
7172
7662
  resources: Object.keys(this.config),
7173
7663
  });
7174
7664
  }
@@ -7178,7 +7668,7 @@ class CacheKeyGenerator {
7178
7668
  // Fallback: use URL as key
7179
7669
  const paramStr = params ? this.serializeParams(params) : '';
7180
7670
  const key = paramStr ? `${url}?${paramStr}` : url;
7181
- log$4.debug('URL not matched, using fallback key:', { url, key });
7671
+ log$3.debug('URL not matched, using fallback key:', { url, key });
7182
7672
  return key;
7183
7673
  }
7184
7674
  const { resource, ids, action, isList, parent } = parsed;
@@ -7186,21 +7676,21 @@ class CacheKeyGenerator {
7186
7676
  const paramStr = params ? this.serializeParams(params) : '';
7187
7677
  const parentPart = parent && ids.length > 0 ? `${parent}=${ids[0]}&` : '';
7188
7678
  const key = `${resource}:list:${parentPart}${paramStr}`;
7189
- log$4.debug('Generated list cache key:', { url, key, resource });
7679
+ log$3.debug('Generated list cache key:', { url, key, resource });
7190
7680
  return key;
7191
7681
  }
7192
7682
  // Single item
7193
7683
  if (ids.length === 0 && action) {
7194
7684
  // Special case for endpoints like /cashiers/me
7195
7685
  const key = `${resource}:${action}`;
7196
- log$4.debug('Generated special action cache key:', { url, key, resource, action });
7686
+ log$3.debug('Generated special action cache key:', { url, key, resource, action });
7197
7687
  return key;
7198
7688
  }
7199
7689
  let key = `${resource}:${ids.join(':')}`;
7200
7690
  if (action) {
7201
7691
  key += `:${action}`;
7202
7692
  }
7203
- log$4.debug('Generated item cache key:', { url, key, resource, ids, action });
7693
+ log$3.debug('Generated item cache key:', { url, key, resource, ids, action });
7204
7694
  return key;
7205
7695
  }
7206
7696
  parseResource(url) {
@@ -7210,23 +7700,23 @@ class CacheKeyGenerator {
7210
7700
  getTTL(url) {
7211
7701
  const resource = this.parseResource(url);
7212
7702
  if (!resource) {
7213
- log$4.debug('No resource found for URL, using default TTL:', { url, ttl: DEFAULT_TTL });
7703
+ log$3.debug('No resource found for URL, using default TTL:', { url, ttl: DEFAULT_TTL });
7214
7704
  return DEFAULT_TTL;
7215
7705
  }
7216
7706
  const ttl = this.config[resource].ttlMs;
7217
- log$4.debug('TTL for resource:', { url, resource, ttlMs: ttl, ttlMin: ttl / 60000 });
7707
+ log$3.debug('TTL for resource:', { url, resource, ttlMs: ttl, ttlMin: ttl / 60000 });
7218
7708
  return ttl;
7219
7709
  }
7220
7710
  shouldCache(url) {
7221
7711
  const parsed = this.parseUrl(url);
7222
7712
  if (!parsed) {
7223
- log$4.debug('URL not recognized, should not cache:', { url });
7713
+ log$3.debug('URL not recognized, should not cache:', { url });
7224
7714
  return false;
7225
7715
  }
7226
7716
  const { resource, isList } = parsed;
7227
7717
  const config = this.config[resource];
7228
7718
  if (isList) {
7229
- log$4.debug('List endpoint cache decision:', {
7719
+ log$3.debug('List endpoint cache decision:', {
7230
7720
  url,
7231
7721
  resource,
7232
7722
  isList: true,
@@ -7234,7 +7724,7 @@ class CacheKeyGenerator {
7234
7724
  });
7235
7725
  return config.cacheList;
7236
7726
  }
7237
- log$4.debug('Item endpoint cache decision:', {
7727
+ log$3.debug('Item endpoint cache decision:', {
7238
7728
  url,
7239
7729
  resource,
7240
7730
  isList: false,
@@ -7245,7 +7735,7 @@ class CacheKeyGenerator {
7245
7735
  getInvalidationPatterns(url, method) {
7246
7736
  const parsed = this.parseUrl(url);
7247
7737
  if (!parsed) {
7248
- log$4.debug('No patterns to invalidate for URL:', { url, method });
7738
+ log$3.debug('No patterns to invalidate for URL:', { url, method });
7249
7739
  return [];
7250
7740
  }
7251
7741
  const { resource, ids, parent } = parsed;
@@ -7267,7 +7757,7 @@ class CacheKeyGenerator {
7267
7757
  if (resource === 'cashier' && (method === 'PUT' || method === 'DELETE')) {
7268
7758
  patterns.push('cashier:me');
7269
7759
  }
7270
- log$4.debug('Invalidation patterns:', { url, method, patterns });
7760
+ log$3.debug('Invalidation patterns:', { url, method, patterns });
7271
7761
  return patterns;
7272
7762
  }
7273
7763
  parseUrl(url) {
@@ -7302,7 +7792,7 @@ class CacheKeyGenerator {
7302
7792
  }
7303
7793
  }
7304
7794
 
7305
- const log$3 = createPrefixedLogger('CACHE');
7795
+ const log$2 = createPrefixedLogger('CACHE');
7306
7796
  class CachingHttpDecorator {
7307
7797
  constructor(http, cache, keyGenerator, networkMonitor, config = {}) {
7308
7798
  this.http = http;
@@ -7312,7 +7802,7 @@ class CachingHttpDecorator {
7312
7802
  this.config = config;
7313
7803
  this.currentOnlineState = true;
7314
7804
  this.authToken = null;
7315
- log$3.info('CachingHttpDecorator initialized', {
7805
+ log$2.info('CachingHttpDecorator initialized', {
7316
7806
  enabled: config.enabled !== false,
7317
7807
  hasNetworkMonitor: !!networkMonitor,
7318
7808
  });
@@ -7322,7 +7812,7 @@ class CachingHttpDecorator {
7322
7812
  if (this.networkMonitor) {
7323
7813
  this.networkSubscription = this.networkMonitor.online$.subscribe((online) => {
7324
7814
  if (this.currentOnlineState !== online) {
7325
- log$3.info('Network state changed:', { online });
7815
+ log$2.info('Network state changed:', { online });
7326
7816
  }
7327
7817
  this.currentOnlineState = online;
7328
7818
  });
@@ -7341,19 +7831,19 @@ class CachingHttpDecorator {
7341
7831
  const startTime = Date.now();
7342
7832
  // Check if caching is disabled globally
7343
7833
  if (this.config.enabled === false) {
7344
- log$3.debug('GET (cache disabled globally):', { url });
7834
+ log$2.debug('GET (cache disabled globally):', { url });
7345
7835
  return this.http.get(url, config);
7346
7836
  }
7347
7837
  // Check if this URL should be cached
7348
7838
  const shouldCache = this.keyGenerator.shouldCache(url);
7349
7839
  if (!shouldCache) {
7350
- log$3.debug('GET (not cacheable - likely a list endpoint):', { url });
7840
+ log$2.debug('GET (not cacheable - likely a list endpoint):', { url });
7351
7841
  return this.http.get(url, config);
7352
7842
  }
7353
7843
  const cacheKey = this.keyGenerator.generate(url, config?.params);
7354
7844
  const ttl = this.keyGenerator.getTTL(url);
7355
7845
  const resource = this.keyGenerator.parseResource(url);
7356
- log$3.info('GET request starting:', {
7846
+ log$2.info('GET request starting:', {
7357
7847
  url,
7358
7848
  resource,
7359
7849
  cacheKey,
@@ -7366,18 +7856,18 @@ class CachingHttpDecorator {
7366
7856
  try {
7367
7857
  cached = await this.cache.get(cacheKey);
7368
7858
  if (cached) {
7369
- log$3.debug('Cache entry found:', {
7859
+ log$2.debug('Cache entry found:', {
7370
7860
  cacheKey,
7371
7861
  timestamp: new Date(cached.timestamp).toISOString(),
7372
7862
  ageMs: Date.now() - cached.timestamp,
7373
7863
  });
7374
7864
  }
7375
7865
  else {
7376
- log$3.debug('Cache entry not found:', { cacheKey });
7866
+ log$2.debug('Cache entry not found:', { cacheKey });
7377
7867
  }
7378
7868
  }
7379
7869
  catch (error) {
7380
- log$3.warn('Cache lookup failed:', {
7870
+ log$2.warn('Cache lookup failed:', {
7381
7871
  cacheKey,
7382
7872
  error: error instanceof Error ? error.message : error,
7383
7873
  });
@@ -7385,7 +7875,7 @@ class CachingHttpDecorator {
7385
7875
  if (cached) {
7386
7876
  const age = Date.now() - cached.timestamp;
7387
7877
  const isExpired = age >= ttl;
7388
- log$3.debug('Cache analysis:', {
7878
+ log$2.debug('Cache analysis:', {
7389
7879
  cacheKey,
7390
7880
  ageMs: age,
7391
7881
  ageSec: Math.round(age / 1000),
@@ -7396,7 +7886,7 @@ class CachingHttpDecorator {
7396
7886
  // If within TTL, return cached data
7397
7887
  if (!isExpired) {
7398
7888
  const duration = Date.now() - startTime;
7399
- log$3.info('CACHE HIT:', {
7889
+ log$2.info('CACHE HIT:', {
7400
7890
  url,
7401
7891
  cacheKey,
7402
7892
  ageMs: age,
@@ -7411,7 +7901,7 @@ class CachingHttpDecorator {
7411
7901
  // If offline and cache is stale, return stale data
7412
7902
  if (!this.isOnline()) {
7413
7903
  const duration = Date.now() - startTime;
7414
- log$3.info('CACHE STALE (offline):', {
7904
+ log$2.info('CACHE STALE (offline):', {
7415
7905
  url,
7416
7906
  cacheKey,
7417
7907
  ageMs: age,
@@ -7423,25 +7913,25 @@ class CachingHttpDecorator {
7423
7913
  headers: { 'x-cache': 'STALE' },
7424
7914
  };
7425
7915
  }
7426
- log$3.debug('Cache expired, fetching fresh data:', { cacheKey, ageMs: age, ttlMs: ttl });
7916
+ log$2.debug('Cache expired, fetching fresh data:', { cacheKey, ageMs: age, ttlMs: ttl });
7427
7917
  }
7428
7918
  // Fetch fresh data
7429
7919
  try {
7430
- log$3.debug('Fetching from network:', { url });
7920
+ log$2.debug('Fetching from network:', { url });
7431
7921
  const response = await this.http.get(url, config);
7432
7922
  // Cache the response
7433
7923
  try {
7434
7924
  await this.cache.set(cacheKey, response.data);
7435
- log$3.debug('Response cached successfully:', { cacheKey });
7925
+ log$2.debug('Response cached successfully:', { cacheKey });
7436
7926
  }
7437
7927
  catch (error) {
7438
- log$3.error('Failed to cache response:', {
7928
+ log$2.error('Failed to cache response:', {
7439
7929
  cacheKey,
7440
7930
  error: error instanceof Error ? error.message : error,
7441
7931
  });
7442
7932
  }
7443
7933
  const duration = Date.now() - startTime;
7444
- log$3.info('CACHE MISS (fetched fresh):', {
7934
+ log$2.info('CACHE MISS (fetched fresh):', {
7445
7935
  url,
7446
7936
  cacheKey,
7447
7937
  status: response.status,
@@ -7456,7 +7946,7 @@ class CachingHttpDecorator {
7456
7946
  // On error, return stale cache if available
7457
7947
  if (cached) {
7458
7948
  const duration = Date.now() - startTime;
7459
- log$3.warn('CACHE STALE (network error):', {
7949
+ log$2.warn('CACHE STALE (network error):', {
7460
7950
  url,
7461
7951
  cacheKey,
7462
7952
  error: error instanceof Error ? error.message : 'Unknown error',
@@ -7468,7 +7958,7 @@ class CachingHttpDecorator {
7468
7958
  headers: { 'x-cache': 'STALE' },
7469
7959
  };
7470
7960
  }
7471
- log$3.error('Network error with no cache fallback:', {
7961
+ log$2.error('Network error with no cache fallback:', {
7472
7962
  url,
7473
7963
  error: error instanceof Error ? error.message : error,
7474
7964
  });
@@ -7476,31 +7966,35 @@ class CachingHttpDecorator {
7476
7966
  }
7477
7967
  }
7478
7968
  async post(url, data, config) {
7479
- log$3.info('POST request:', { url });
7969
+ log$2.info('POST request:', { url });
7480
7970
  const response = await this.http.post(url, data, config);
7481
7971
  await this.invalidateRelated(url, 'POST');
7482
7972
  return response;
7483
7973
  }
7484
7974
  async put(url, data, config) {
7485
- log$3.info('PUT request:', { url });
7975
+ log$2.info('PUT request:', { url });
7486
7976
  const response = await this.http.put(url, data, config);
7487
7977
  await this.invalidateRelated(url, 'PUT');
7488
7978
  return response;
7489
7979
  }
7490
7980
  async patch(url, data, config) {
7491
- log$3.info('PATCH request:', { url });
7981
+ log$2.info('PATCH request:', { url });
7492
7982
  const response = await this.http.patch(url, data, config);
7493
7983
  await this.invalidateRelated(url, 'PATCH');
7494
7984
  return response;
7495
7985
  }
7496
7986
  async delete(url, config) {
7497
- log$3.info('DELETE request:', { url });
7987
+ log$2.info('DELETE request:', { url });
7498
7988
  const response = await this.http.delete(url, config);
7499
7989
  await this.invalidateRelated(url, 'DELETE');
7500
7990
  return response;
7501
7991
  }
7502
7992
  setAuthToken(token) {
7503
- log$3.debug('Auth token updated:', { hasToken: !!token });
7993
+ log$2.debug('CachingHttpDecorator.setAuthToken called:', {
7994
+ hasToken: !!token,
7995
+ tokenPrefix: token?.substring(0, 20),
7996
+ underlyingHttpType: this.http.constructor.name,
7997
+ });
7504
7998
  this.authToken = token;
7505
7999
  this.http.setAuthToken(token);
7506
8000
  }
@@ -7510,17 +8004,17 @@ class CachingHttpDecorator {
7510
8004
  async invalidateRelated(url, method) {
7511
8005
  const patterns = this.keyGenerator.getInvalidationPatterns(url, method);
7512
8006
  if (patterns.length === 0) {
7513
- log$3.debug('No cache patterns to invalidate:', { url, method });
8007
+ log$2.debug('No cache patterns to invalidate:', { url, method });
7514
8008
  return;
7515
8009
  }
7516
- log$3.info('Invalidating cache patterns:', { url, method, patterns });
8010
+ log$2.info('Invalidating cache patterns:', { url, method, patterns });
7517
8011
  for (const pattern of patterns) {
7518
8012
  try {
7519
8013
  await this.cache.invalidate(pattern);
7520
- log$3.debug('Cache pattern invalidated:', { pattern });
8014
+ log$2.debug('Cache pattern invalidated:', { pattern });
7521
8015
  }
7522
8016
  catch (error) {
7523
- log$3.error('Failed to invalidate pattern:', {
8017
+ log$2.error('Failed to invalidate pattern:', {
7524
8018
  pattern,
7525
8019
  error: error instanceof Error ? error.message : error,
7526
8020
  });
@@ -7528,12 +8022,13 @@ class CachingHttpDecorator {
7528
8022
  }
7529
8023
  }
7530
8024
  destroy() {
7531
- log$3.debug('CachingHttpDecorator destroyed');
8025
+ log$2.debug('CachingHttpDecorator destroyed');
7532
8026
  this.networkSubscription?.unsubscribe();
7533
8027
  }
7534
8028
  }
7535
8029
 
7536
- const log$2 = createPrefixedLogger('HTTP-MTLS');
8030
+ const logJwt = createPrefixedLogger('HTTP-JWT');
8031
+ const logMtls = createPrefixedLogger('HTTP-MTLS');
7537
8032
  class AxiosHttpAdapter {
7538
8033
  constructor(config) {
7539
8034
  this.authToken = null;
@@ -7551,23 +8046,30 @@ class AxiosHttpAdapter {
7551
8046
  }
7552
8047
  setMTLSAdapter(adapter) {
7553
8048
  this.mtlsAdapter = adapter;
7554
- log$2.debug('mTLS adapter configured:', !!adapter);
8049
+ logMtls.debug('mTLS adapter configured:', !!adapter);
7555
8050
  }
7556
8051
  setAuthStrategy(strategy) {
7557
8052
  this.authStrategy = strategy;
7558
- log$2.debug('Auth strategy configured:', !!strategy);
8053
+ logJwt.debug('Auth strategy configured:', !!strategy);
7559
8054
  }
7560
8055
  async shouldUseMTLS(url, method) {
7561
8056
  if (!this.mtlsAdapter) {
8057
+ logJwt.debug(`No mTLS adapter, using JWT for ${method} ${url}`);
7562
8058
  return false;
7563
8059
  }
7564
8060
  if (this.authStrategy) {
7565
8061
  const config = await this.authStrategy.determineAuthConfig(url, method);
7566
- log$2.debug(`Auth config for ${method} ${url}:`, config);
8062
+ const logger = config.mode === 'mtls' ? logMtls : logJwt;
8063
+ logger.debug(`Auth config for ${method} ${url}:`, config);
7567
8064
  return config.mode === 'mtls';
7568
8065
  }
7569
8066
  // Fallback: use mTLS for mf1/mf2 endpoints if no strategy
7570
- return url.startsWith('/mf1') || url.startsWith('/mf2');
8067
+ // This should rarely happen - only before SDK is fully initialized
8068
+ const useMtls = url.startsWith('/mf1') || url.startsWith('/mf2');
8069
+ if (useMtls) {
8070
+ logMtls.warn(`No auth strategy set, falling back to mTLS for ${method} ${url}`);
8071
+ }
8072
+ return useMtls;
7571
8073
  }
7572
8074
  async makeMTLSRequest(url, method, data, config) {
7573
8075
  if (!this.mtlsAdapter) {
@@ -7580,10 +8082,10 @@ class AxiosHttpAdapter {
7580
8082
  };
7581
8083
  if (this.authToken) {
7582
8084
  headers['Authorization'] = `Bearer ${this.authToken}`;
7583
- log$2.debug('JWT token present for mTLS request');
8085
+ logMtls.debug('JWT token present for mTLS request');
7584
8086
  }
7585
8087
  else {
7586
- log$2.warn('No JWT token for mTLS request');
8088
+ logMtls.warn('No JWT token for mTLS request');
7587
8089
  }
7588
8090
  const mtlsConfig = {
7589
8091
  url: fullUrl,
@@ -7592,15 +8094,15 @@ class AxiosHttpAdapter {
7592
8094
  data,
7593
8095
  timeout: config?.timeout,
7594
8096
  };
7595
- log$2.debug(`mTLS ${method} ${fullUrl}`);
8097
+ logMtls.debug(`mTLS ${method} ${fullUrl}`);
7596
8098
  if (data) {
7597
- log$2.debug('Request body:', data);
8099
+ logMtls.debug('Request body:', data);
7598
8100
  }
7599
8101
  try {
7600
8102
  const response = await this.mtlsAdapter.request(mtlsConfig);
7601
- log$2.debug(`mTLS Response ${response.status} from ${fullUrl}`);
8103
+ logMtls.debug(`mTLS Response ${response.status} from ${fullUrl}`);
7602
8104
  if (response.data) {
7603
- log$2.debug('Response body:', response.data);
8105
+ logMtls.debug('Response body:', response.data);
7604
8106
  }
7605
8107
  return {
7606
8108
  data: response.data,
@@ -7609,11 +8111,11 @@ class AxiosHttpAdapter {
7609
8111
  };
7610
8112
  }
7611
8113
  catch (error) {
7612
- log$2.error(`mTLS Response error from ${fullUrl}:`, error);
8114
+ logMtls.error(`mTLS Response error from ${fullUrl}:`, error);
7613
8115
  if (error && typeof error === 'object' && 'response' in error) {
7614
8116
  const axiosError = error;
7615
8117
  if (axiosError.response?.data) {
7616
- log$2.error('Response body:', axiosError.response.data);
8118
+ logMtls.error('Response body:', axiosError.response.data);
7617
8119
  }
7618
8120
  }
7619
8121
  throw error;
@@ -7628,36 +8130,46 @@ class AxiosHttpAdapter {
7628
8130
  this.client.interceptors.request.use((config) => {
7629
8131
  if (this.authToken) {
7630
8132
  config.headers.Authorization = `Bearer ${this.authToken}`;
7631
- log$2.debug('Adding JWT token to request');
8133
+ logJwt.debug('Adding JWT token to request', {
8134
+ tokenPrefix: this.authToken.substring(0, 30) + '...',
8135
+ tokenLength: this.authToken.length,
8136
+ });
7632
8137
  }
7633
8138
  else {
7634
- log$2.warn('No JWT token available for request:', { url: config.url });
8139
+ logJwt.warn('No JWT token available for request:', { url: config.url });
7635
8140
  }
7636
8141
  const method = config.method?.toUpperCase() ?? 'UNKNOWN';
7637
- log$2.debug(`→ ${method} ${config.url}`);
8142
+ const authHeader = config.headers.Authorization;
8143
+ // Log full request details for debugging
8144
+ logJwt.info(`→ ${method} ${config.url}`, {
8145
+ baseURL: config.baseURL,
8146
+ fullURL: `${config.baseURL}${config.url}`,
8147
+ hasAuthHeader: !!authHeader,
8148
+ authHeaderValue: authHeader ? `${String(authHeader).substring(0, 50)}...` : 'MISSING',
8149
+ });
7638
8150
  if (config.params && Object.keys(config.params).length > 0) {
7639
- log$2.debug('Request params:', config.params);
8151
+ logJwt.debug('Request params:', config.params);
7640
8152
  }
7641
8153
  if (config.data) {
7642
- log$2.debug('Request body:', config.data);
8154
+ logJwt.debug('Request body:', config.data);
7643
8155
  }
7644
8156
  return config;
7645
8157
  }, (error) => {
7646
- log$2.error('Request error:', error);
8158
+ logJwt.error('Request error:', error);
7647
8159
  return Promise.reject(error);
7648
8160
  });
7649
8161
  this.client.interceptors.response.use((response) => {
7650
8162
  const method = response.config.method?.toUpperCase() ?? 'UNKNOWN';
7651
- log$2.debug(`← ${method} ${response.status} ${response.config.url}`);
8163
+ logJwt.debug(`← ${method} ${response.status} ${response.config.url}`);
7652
8164
  if (response.data) {
7653
- log$2.debug('Response body:', response.data);
8165
+ logJwt.debug('Response body:', response.data);
7654
8166
  }
7655
8167
  return response;
7656
8168
  }, (error) => {
7657
8169
  const method = error.config?.method?.toUpperCase() ?? 'UNKNOWN';
7658
- log$2.error(`← ${method} ${error.response?.status ?? 'ERR'} ${error.config?.url ?? 'unknown'}`);
8170
+ logJwt.error(`← ${method} ${error.response?.status ?? 'ERR'} ${error.config?.url ?? 'unknown'}`);
7659
8171
  if (error.response?.data) {
7660
- log$2.error('Response body:', error.response.data);
8172
+ logJwt.error('Response body:', error.response.data);
7661
8173
  }
7662
8174
  return Promise.reject(error);
7663
8175
  });
@@ -7727,7 +8239,10 @@ class AxiosHttpAdapter {
7727
8239
  return this.mapResponse(response);
7728
8240
  }
7729
8241
  setAuthToken(token) {
7730
- log$2.info('setAuthToken called:', { hasToken: !!token, tokenPrefix: token?.substring(0, 20) });
8242
+ logJwt.info('setAuthToken called:', {
8243
+ hasToken: !!token,
8244
+ tokenPrefix: token?.substring(0, 20),
8245
+ });
7731
8246
  this.authToken = token;
7732
8247
  }
7733
8248
  getAuthToken() {
@@ -7943,6 +8458,11 @@ class ACubeSDK {
7943
8458
  const tokenStorage = this.container.get(DI_TOKENS.TOKEN_STORAGE_PORT);
7944
8459
  const httpPort = this.container.get(DI_TOKENS.HTTP_PORT);
7945
8460
  const baseHttpPort = this.container.get(DI_TOKENS.BASE_HTTP_PORT);
8461
+ log$1.debug('HTTP ports initialized', {
8462
+ httpPortType: httpPort.constructor.name,
8463
+ baseHttpPortType: baseHttpPort.constructor.name,
8464
+ areSameInstance: httpPort === baseHttpPort,
8465
+ });
7946
8466
  log$1.debug('Initializing authentication service');
7947
8467
  this.authService = new AuthenticationService(httpPort, tokenStorage, {
7948
8468
  authUrl: this.config.getAuthUrl(),
@@ -7975,12 +8495,22 @@ class ACubeSDK {
7975
8495
  this.offlineManager.sync().catch(() => { });
7976
8496
  }
7977
8497
  });
7978
- if (await this.authService.isAuthenticated()) {
8498
+ const isAuth = await this.authService.isAuthenticated();
8499
+ log$1.debug('Checking authentication status during init', { isAuthenticated: isAuth });
8500
+ if (isAuth) {
7979
8501
  const token = await this.authService.getAccessToken();
8502
+ log$1.debug('Token retrieved during init', {
8503
+ hasToken: !!token,
8504
+ tokenPrefix: token?.substring(0, 20),
8505
+ });
7980
8506
  if (token) {
7981
8507
  httpPort.setAuthToken(token);
8508
+ log$1.info('Auth token set on HTTP port during initialization');
7982
8509
  }
7983
8510
  }
8511
+ else {
8512
+ log$1.warn('User not authenticated during SDK init - token will be set after login');
8513
+ }
7984
8514
  if (this.adapters?.mtls && 'setMTLSAdapter' in baseHttpPort) {
7985
8515
  log$1.debug('Connecting mTLS adapter to HTTP port');
7986
8516
  const httpWithMtls = baseHttpPort;
@@ -8799,842 +9329,401 @@ class SDKManager {
8799
9329
  this.appStateService.state$.subscribe(this.events.onAppStateChanged);
8800
9330
  }
8801
9331
  if (this.events?.onTelemetryStateChanged) {
8802
- this.telemetryService.state$.subscribe(this.events.onTelemetryStateChanged);
8803
- }
8804
- this.isInitialized = true;
8805
- // Only start polling for MERCHANT/CASHIER users (SUPPLIER gets 401 on these endpoints)
8806
- const user = await this.sdk.getCurrentUser();
8807
- const canPoll = user && hasAnyRole(user.roles, ['ROLE_MERCHANT', 'ROLE_CASHIER']);
8808
- if (canPoll) {
8809
- this.notificationService.startPolling();
8810
- await this.startTelemetryPollingAuto();
8811
- this.isPollingActive = true;
8812
- }
8813
- // AppStateService remains active for all users (handles OFFLINE network state)
8814
- }
8815
- /**
8816
- * Observable stream of app state
8817
- * Emits AppState with mode (NORMAL, WARNING, BLOCKED, OFFLINE)
8818
- */
8819
- get appState$() {
8820
- this.ensureInitialized();
8821
- return this.appStateService.state$;
8822
- }
8823
- /**
8824
- * Observable stream of app mode only
8825
- * Emits AppMode with distinctUntilChanged
8826
- */
8827
- get mode$() {
8828
- this.ensureInitialized();
8829
- return this.appStateService.mode$;
8830
- }
8831
- /**
8832
- * Observable stream indicating if app is blocked
8833
- */
8834
- get isBlocked$() {
8835
- this.ensureInitialized();
8836
- return this.appStateService.isBlocked$;
8837
- }
8838
- /**
8839
- * Observable stream of warning state with countdown
8840
- */
8841
- get warning$() {
8842
- this.ensureInitialized();
8843
- return this.appStateService.warning$;
8844
- }
8845
- /**
8846
- * Observable stream of telemetry state (data, isLoading, isCached, error)
8847
- */
8848
- get telemetryState$() {
8849
- this.ensureInitialized();
8850
- return this.telemetryService.state$;
8851
- }
8852
- /**
8853
- * Get the pemId from the installed certificate
8854
- */
8855
- async getPemId() {
8856
- this.ensureInitialized();
8857
- try {
8858
- const certInfo = await this.sdk.getCertificatesInfo();
8859
- return certInfo?.pemId ?? null;
8860
- }
8861
- catch {
8862
- return null;
8863
- }
8864
- }
8865
- /**
8866
- * Start polling telemetry using the pemId from installed certificate
8867
- * Returns the pemId if successful, null if no certificate is installed
8868
- */
8869
- async startTelemetryPollingAuto() {
8870
- this.ensureInitialized();
8871
- const pemId = await this.getPemId();
8872
- if (pemId) {
8873
- this.telemetryService.startPolling(pemId);
8874
- }
8875
- return pemId;
8876
- }
8877
- /**
8878
- * Start polling telemetry for a specific PEM
8879
- */
8880
- startTelemetryPolling(pemId) {
8881
- this.ensureInitialized();
8882
- this.telemetryService.startPolling(pemId);
8883
- }
8884
- /**
8885
- * Stop telemetry polling
8886
- */
8887
- stopTelemetryPolling() {
8888
- this.ensureInitialized();
8889
- this.telemetryService.stopPolling();
8890
- }
8891
- /**
8892
- * Get simplified services for product use
8893
- */
8894
- getServices() {
8895
- this.ensureInitialized();
8896
- const sdk = this.sdk;
8897
- const telemetryService = this.telemetryService;
8898
- return {
8899
- receipts: sdk.receipts,
8900
- merchants: sdk.merchants,
8901
- cashiers: sdk.cashiers,
8902
- cashRegisters: sdk.cashRegisters,
8903
- pointOfSales: sdk.pointOfSales,
8904
- suppliers: sdk.suppliers,
8905
- pems: sdk.pems,
8906
- dailyReports: sdk.dailyReports,
8907
- journals: sdk.journals,
8908
- telemetry: {
8909
- startPollingAuto: () => this.startTelemetryPollingAuto(),
8910
- startPolling: (pemId) => telemetryService.startPolling(pemId),
8911
- stopPolling: () => telemetryService.stopPolling(),
8912
- getTelemetry: (pemId) => telemetryService.getTelemetry(pemId),
8913
- refreshTelemetry: (pemId) => telemetryService.refreshTelemetry(pemId),
8914
- triggerSync: () => telemetryService.triggerSync(),
8915
- clearTelemetry: () => telemetryService.clearTelemetry(),
8916
- getPemId: () => this.getPemId(),
8917
- },
8918
- login: (credentials) => sdk.login(credentials),
8919
- logout: () => sdk.logout(),
8920
- getCurrentUser: () => sdk.getCurrentUser(),
8921
- isAuthenticated: () => sdk.isAuthenticated(),
8922
- storeCertificate: (certificate, privateKey, options) => sdk.storeCertificate(certificate, privateKey, options),
8923
- hasCertificate: () => sdk.hasCertificate(),
8924
- clearCertificate: () => sdk.clearCertificate(),
8925
- isOnline: () => sdk.isOnline(),
8926
- };
9332
+ this.telemetryService.state$.subscribe(this.events.onTelemetryStateChanged);
9333
+ }
9334
+ this.isInitialized = true;
9335
+ // Only start polling for MERCHANT/CASHIER users (SUPPLIER gets 401 on these endpoints)
9336
+ const user = await this.sdk.getCurrentUser();
9337
+ const canPoll = user && hasAnyRole(user.roles, ['ROLE_MERCHANT', 'ROLE_CASHIER']);
9338
+ if (canPoll) {
9339
+ this.notificationService.startPolling();
9340
+ await this.startTelemetryPollingAuto();
9341
+ this.isPollingActive = true;
9342
+ }
9343
+ // AppStateService remains active for all users (handles OFFLINE network state)
8927
9344
  }
8928
9345
  /**
8929
- * Manually trigger a notification sync
9346
+ * Observable stream of app state
9347
+ * Emits AppState with mode (NORMAL, WARNING, BLOCKED, OFFLINE)
8930
9348
  */
8931
- async syncNotifications() {
9349
+ get appState$() {
8932
9350
  this.ensureInitialized();
8933
- await this.notificationService.triggerSync();
9351
+ return this.appStateService.state$;
8934
9352
  }
8935
9353
  /**
8936
- * Manually trigger a telemetry sync
9354
+ * Observable stream of app mode only
9355
+ * Emits AppMode with distinctUntilChanged
8937
9356
  */
8938
- async syncTelemetry() {
9357
+ get mode$() {
8939
9358
  this.ensureInitialized();
8940
- return this.telemetryService.triggerSync();
9359
+ return this.appStateService.mode$;
8941
9360
  }
8942
9361
  /**
8943
- * Check if the manager is initialized
9362
+ * Observable stream indicating if app is blocked
8944
9363
  */
8945
- getIsInitialized() {
8946
- return this.isInitialized;
9364
+ get isBlocked$() {
9365
+ this.ensureInitialized();
9366
+ return this.appStateService.isBlocked$;
8947
9367
  }
8948
9368
  /**
8949
- * Get the underlying SDK instance (for advanced use cases)
9369
+ * Observable stream of warning state with countdown
8950
9370
  */
8951
- getSDK() {
9371
+ get warning$() {
8952
9372
  this.ensureInitialized();
8953
- return this.sdk;
8954
- }
8955
- cleanup() {
8956
- this.notificationService?.destroy();
8957
- this.telemetryService?.destroy();
8958
- this.appStateService?.destroy();
8959
- this.sdk?.destroy();
8960
- this.notificationService = null;
8961
- this.telemetryService = null;
8962
- this.appStateService = null;
8963
- this.sdk = null;
8964
- this.isInitialized = false;
8965
- this.isPollingActive = false;
8966
- }
8967
- ensureInitialized() {
8968
- if (!this.isInitialized) {
8969
- throw new ACubeSDKError('SDK_NOT_INITIALIZED', 'SDKManager not initialized. Call initialize() first.');
8970
- }
8971
- }
8972
- }
8973
- SDKManager.instance = null;
8974
-
8975
- const RECEIPT_READY = 'ready';
8976
- const RECEIPT_SENT = 'sent';
8977
- const RECEIPT_SORT_DESCENDING = 'descending';
8978
- const RECEIPT_SORT_ASCENDING = 'ascending';
8979
-
8980
- const log = createPrefixedLogger('CACHE-HANDLER');
8981
- class CacheHandler {
8982
- constructor(cache, networkMonitor) {
8983
- this.cache = cache;
8984
- this.networkMonitor = networkMonitor;
8985
- this.currentOnlineState = true;
8986
- this.setupNetworkMonitoring();
8987
- }
8988
- setupNetworkMonitoring() {
8989
- if (this.networkMonitor) {
8990
- this.networkSubscription = this.networkMonitor.online$.subscribe((online) => {
8991
- this.currentOnlineState = online;
8992
- });
8993
- }
8994
- }
8995
- isOnline() {
8996
- if (this.networkMonitor) {
8997
- return this.currentOnlineState;
8998
- }
8999
- if (typeof navigator !== 'undefined' && 'onLine' in navigator) {
9000
- return navigator.onLine;
9001
- }
9002
- return false;
9003
- }
9004
- async handleCachedRequest(url, requestFn, config) {
9005
- if (!this.cache || config?.useCache === false) {
9006
- const response = await requestFn();
9007
- return response.data;
9008
- }
9009
- const cacheKey = this.generateCacheKey(url);
9010
- const online = this.isOnline();
9011
- log.debug('Request:', { url, cacheKey, online });
9012
- if (online) {
9013
- try {
9014
- const response = await requestFn();
9015
- if (this.cache) {
9016
- await this.cache.set(cacheKey, response.data).catch((error) => {
9017
- log.error('Failed to cache:', error instanceof Error ? error.message : error);
9018
- });
9019
- }
9020
- return response.data;
9021
- }
9022
- catch (error) {
9023
- const cached = await this.cache.get(cacheKey).catch(() => null);
9024
- if (cached) {
9025
- log.debug('Network failed, using cache fallback');
9026
- return cached.data;
9027
- }
9028
- throw error;
9029
- }
9030
- }
9031
- else {
9032
- const cached = await this.cache.get(cacheKey).catch(() => null);
9033
- if (cached) {
9034
- log.debug('Offline, returning cached data');
9035
- return cached.data;
9036
- }
9037
- throw new Error('Offline: No cached data available');
9038
- }
9373
+ return this.appStateService.warning$;
9039
9374
  }
9040
- generateCacheKey(url) {
9041
- return url;
9375
+ /**
9376
+ * Observable stream of telemetry state (data, isLoading, isCached, error)
9377
+ */
9378
+ get telemetryState$() {
9379
+ this.ensureInitialized();
9380
+ return this.telemetryService.state$;
9042
9381
  }
9043
- async invalidateCache(pattern) {
9044
- if (!this.cache)
9045
- return;
9382
+ /**
9383
+ * Get the pemId from the installed certificate
9384
+ */
9385
+ async getPemId() {
9386
+ this.ensureInitialized();
9046
9387
  try {
9047
- await this.cache.invalidate(pattern);
9388
+ const certInfo = await this.sdk.getCertificatesInfo();
9389
+ return certInfo?.pemId ?? null;
9048
9390
  }
9049
- catch (error) {
9050
- log.error('Invalidation failed:', error instanceof Error ? error.message : error);
9391
+ catch {
9392
+ return null;
9051
9393
  }
9052
9394
  }
9053
- getCacheStatus() {
9054
- return {
9055
- available: !!this.cache,
9056
- networkMonitorAvailable: !!this.networkMonitor,
9057
- isOnline: this.isOnline(),
9058
- };
9059
- }
9060
- destroy() {
9061
- this.networkSubscription?.unsubscribe();
9062
- }
9063
- }
9064
-
9065
- function transformError(error) {
9066
- if (axios.isAxiosError(error)) {
9067
- const response = error.response;
9068
- if (!response) {
9069
- return new ACubeSDKError('NETWORK_ERROR', 'Network error occurred', error);
9070
- }
9071
- const status = response.status;
9072
- const data = response.data;
9073
- const violations = data?.violations;
9074
- let message = 'Unknown error occurred';
9075
- if (data?.detail) {
9076
- message = data.detail;
9077
- }
9078
- else if (data?.title) {
9079
- message = data.title;
9080
- }
9081
- else if (error.message) {
9082
- message = error.message;
9083
- }
9084
- switch (status) {
9085
- case 400:
9086
- return new ACubeSDKError('VALIDATION_ERROR', message, error, status, violations);
9087
- case 401:
9088
- return new ACubeSDKError('AUTH_ERROR', message, error, status, violations);
9089
- case 403:
9090
- return new ACubeSDKError('FORBIDDEN_ERROR', message, error, status, violations);
9091
- case 404:
9092
- return new ACubeSDKError('NOT_FOUND_ERROR', message, error, status, violations);
9093
- case 422:
9094
- return new ACubeSDKError('VALIDATION_ERROR', message, error, status, violations);
9095
- default:
9096
- return new ACubeSDKError('UNKNOWN_ERROR', message, error, status, violations);
9395
+ /**
9396
+ * Start polling telemetry using the pemId from installed certificate
9397
+ * Returns the pemId if successful, null if no certificate is installed
9398
+ */
9399
+ async startTelemetryPollingAuto() {
9400
+ this.ensureInitialized();
9401
+ const pemId = await this.getPemId();
9402
+ if (pemId) {
9403
+ this.telemetryService.startPolling(pemId);
9097
9404
  }
9405
+ return pemId;
9098
9406
  }
9099
- return new ACubeSDKError('UNKNOWN_ERROR', 'Unknown error occurred', error);
9100
- }
9101
-
9102
- var ErrorCategory;
9103
- (function (ErrorCategory) {
9104
- ErrorCategory["SERVER_ERROR"] = "SERVER_ERROR";
9105
- ErrorCategory["CLIENT_ERROR"] = "CLIENT_ERROR";
9106
- ErrorCategory["AUTH_ERROR"] = "AUTH_ERROR";
9107
- ErrorCategory["CERTIFICATE_ERROR"] = "CERTIFICATE_ERROR";
9108
- ErrorCategory["NETWORK_ERROR"] = "NETWORK_ERROR";
9109
- ErrorCategory["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
9110
- })(ErrorCategory || (ErrorCategory = {}));
9111
- function extractStatusCode(error) {
9112
- if (error instanceof MTLSError && error.statusCode) {
9113
- return error.statusCode;
9114
- }
9115
- const errorObj = error;
9116
- if (errorObj?.response?.status) {
9117
- return errorObj.response.status;
9118
- }
9119
- if (typeof errorObj?.statusCode === 'number') {
9120
- return errorObj.statusCode;
9121
- }
9122
- return undefined;
9123
- }
9124
- function classifyError(error) {
9125
- const statusCode = extractStatusCode(error);
9126
- const errorMessage = error instanceof Error ? error.message : String(error);
9127
- if (statusCode && statusCode >= 500 && statusCode < 600) {
9128
- return {
9129
- category: ErrorCategory.SERVER_ERROR,
9130
- statusCode,
9131
- message: errorMessage,
9132
- shouldRetry: false,
9133
- userMessage: `Server error (${statusCode}): The server encountered an error.`,
9134
- };
9135
- }
9136
- if (statusCode === 401 || statusCode === 403) {
9137
- return {
9138
- category: ErrorCategory.AUTH_ERROR,
9139
- statusCode,
9140
- message: errorMessage,
9141
- shouldRetry: false,
9142
- userMessage: `Authentication error (${statusCode}): Invalid credentials or insufficient permissions.`,
9143
- };
9144
- }
9145
- if (statusCode && statusCode >= 400 && statusCode < 500) {
9146
- return {
9147
- category: ErrorCategory.CLIENT_ERROR,
9148
- statusCode,
9149
- message: errorMessage,
9150
- shouldRetry: false,
9151
- userMessage: `Request error (${statusCode}): ${errorMessage}`,
9152
- };
9407
+ /**
9408
+ * Start polling telemetry for a specific PEM
9409
+ */
9410
+ startTelemetryPolling(pemId) {
9411
+ this.ensureInitialized();
9412
+ this.telemetryService.startPolling(pemId);
9153
9413
  }
9154
- if (error instanceof MTLSError) {
9155
- return {
9156
- category: ErrorCategory.CERTIFICATE_ERROR,
9157
- statusCode,
9158
- message: errorMessage,
9159
- shouldRetry: true,
9160
- userMessage: 'Certificate error: Unable to establish secure connection.',
9161
- };
9414
+ /**
9415
+ * Stop telemetry polling
9416
+ */
9417
+ stopTelemetryPolling() {
9418
+ this.ensureInitialized();
9419
+ this.telemetryService.stopPolling();
9162
9420
  }
9163
- if (!statusCode &&
9164
- (errorMessage.toLowerCase().includes('network') ||
9165
- errorMessage.toLowerCase().includes('timeout') ||
9166
- errorMessage.toLowerCase().includes('connection'))) {
9421
+ /**
9422
+ * Get simplified services for product use
9423
+ */
9424
+ getServices() {
9425
+ this.ensureInitialized();
9426
+ const sdk = this.sdk;
9427
+ const telemetryService = this.telemetryService;
9167
9428
  return {
9168
- category: ErrorCategory.NETWORK_ERROR,
9169
- message: errorMessage,
9170
- shouldRetry: true,
9171
- userMessage: 'Network error: Unable to connect to server.',
9429
+ receipts: sdk.receipts,
9430
+ merchants: sdk.merchants,
9431
+ cashiers: sdk.cashiers,
9432
+ cashRegisters: sdk.cashRegisters,
9433
+ pointOfSales: sdk.pointOfSales,
9434
+ suppliers: sdk.suppliers,
9435
+ pems: sdk.pems,
9436
+ dailyReports: sdk.dailyReports,
9437
+ journals: sdk.journals,
9438
+ telemetry: {
9439
+ startPollingAuto: () => this.startTelemetryPollingAuto(),
9440
+ startPolling: (pemId) => telemetryService.startPolling(pemId),
9441
+ stopPolling: () => telemetryService.stopPolling(),
9442
+ getTelemetry: (pemId) => telemetryService.getTelemetry(pemId),
9443
+ refreshTelemetry: (pemId) => telemetryService.refreshTelemetry(pemId),
9444
+ triggerSync: () => telemetryService.triggerSync(),
9445
+ clearTelemetry: () => telemetryService.clearTelemetry(),
9446
+ getPemId: () => this.getPemId(),
9447
+ },
9448
+ login: (credentials) => sdk.login(credentials),
9449
+ logout: () => sdk.logout(),
9450
+ getCurrentUser: () => sdk.getCurrentUser(),
9451
+ isAuthenticated: () => sdk.isAuthenticated(),
9452
+ storeCertificate: (certificate, privateKey, options) => sdk.storeCertificate(certificate, privateKey, options),
9453
+ hasCertificate: () => sdk.hasCertificate(),
9454
+ clearCertificate: () => sdk.clearCertificate(),
9455
+ isOnline: () => sdk.isOnline(),
9172
9456
  };
9173
9457
  }
9174
- return {
9175
- category: ErrorCategory.UNKNOWN_ERROR,
9176
- statusCode,
9177
- message: errorMessage,
9178
- shouldRetry: false,
9179
- userMessage: `Unexpected error: ${errorMessage}`,
9180
- };
9181
- }
9182
- function shouldReconfigureCertificate(error) {
9183
- const classification = classifyError(error);
9184
- return classification.category === ErrorCategory.CERTIFICATE_ERROR;
9185
- }
9186
- function shouldRetryRequest(error, isRetryAttempt) {
9187
- if (isRetryAttempt) {
9188
- return false;
9458
+ /**
9459
+ * Manually trigger a notification sync
9460
+ */
9461
+ async syncNotifications() {
9462
+ this.ensureInitialized();
9463
+ await this.notificationService.triggerSync();
9189
9464
  }
9190
- const classification = classifyError(error);
9191
- return classification.shouldRetry;
9192
- }
9193
- function getUserFriendlyMessage(error) {
9194
- const classification = classifyError(error);
9195
- return classification.userMessage;
9196
- }
9197
-
9198
- // Enum options arrays
9199
- const VAT_RATE_CODE_OPTIONS = [
9200
- '4.00',
9201
- '5.00',
9202
- '10.00',
9203
- '22.00',
9204
- '2.00',
9205
- '6.40',
9206
- '7.00',
9207
- '7.30',
9208
- '7.50',
9209
- '7.65',
9210
- '7.95',
9211
- '8.30',
9212
- '8.50',
9213
- '8.80',
9214
- '9.50',
9215
- '12.30',
9216
- 'N1',
9217
- 'N2',
9218
- 'N3',
9219
- 'N4',
9220
- 'N5',
9221
- 'N6',
9222
- ];
9223
- const GOOD_OR_SERVICE_OPTIONS = ['goods', 'service'];
9224
- const RECEIPT_PROOF_TYPE_OPTIONS = ['POS', 'VR', 'ND'];
9225
- // Enum types for receipt validation
9226
- const VatRateCodeSchema = z.enum(VAT_RATE_CODE_OPTIONS);
9227
- const GoodOrServiceSchema = z.enum(GOOD_OR_SERVICE_OPTIONS);
9228
- const ReceiptProofTypeSchema = z.enum(RECEIPT_PROOF_TYPE_OPTIONS);
9229
- // Receipt Item Schema
9230
- const ReceiptItemSchema = z.object({
9231
- type: GoodOrServiceSchema.optional(),
9232
- quantity: z.string().min(1, { error: 'fieldIsRequired' }),
9233
- description: z.string().min(1, { error: 'fieldIsRequired' }),
9234
- unit_price: z.string().min(1, { error: 'fieldIsRequired' }),
9235
- vat_rate_code: VatRateCodeSchema.optional(),
9236
- simplified_vat_allocation: z.boolean().optional(),
9237
- discount: z.string().nullable().optional(),
9238
- is_down_payment_or_voucher_redemption: z.boolean().optional(),
9239
- complimentary: z.boolean().optional(),
9240
- });
9241
- // Main Receipt Input Schema
9242
- const ReceiptInputSchema = z
9243
- .object({
9244
- items: z.array(ReceiptItemSchema).min(1, { error: 'arrayMin1' }),
9245
- customer_tax_code: z.string().optional(),
9246
- customer_lottery_code: z.string().optional(),
9247
- discount: z.string().nullable().optional(),
9248
- invoice_issuing: z.boolean().optional(),
9249
- uncollected_dcr_to_ssn: z.boolean().optional(),
9250
- services_uncollected_amount: z.string().nullable().optional(),
9251
- goods_uncollected_amount: z.string().nullable().optional(),
9252
- cash_payment_amount: z.string().nullable().optional(),
9253
- electronic_payment_amount: z.string().nullable().optional(),
9254
- ticket_restaurant_payment_amount: z.string().nullable().optional(),
9255
- ticket_restaurant_quantity: z.number().optional(),
9256
- })
9257
- .refine((data) => {
9258
- // At least one payment method should be provided
9259
- const hasCashPayment = data.cash_payment_amount && parseFloat(data.cash_payment_amount) > 0;
9260
- const hasElectronicPayment = data.electronic_payment_amount && parseFloat(data.electronic_payment_amount) > 0;
9261
- const hasTicketPayment = data.ticket_restaurant_payment_amount &&
9262
- parseFloat(data.ticket_restaurant_payment_amount) > 0;
9263
- return hasCashPayment || hasElectronicPayment || hasTicketPayment;
9264
- }, {
9265
- error: 'At least one payment method is required',
9266
- path: ['payment_methods'],
9267
- })
9268
- .refine((data) => {
9269
- // only one between customer_tax_code and customer_lottery_code can be provided
9270
- return !data.customer_tax_code || !data.customer_lottery_code;
9271
- }, {
9272
- error: 'Only one between customer_tax_code and customer_lottery_code can be provided',
9273
- path: ['customer_tax_code', 'customer_lottery_code'],
9274
- });
9275
- // Receipt Return or Void via PEM Schema
9276
- const ReceiptReturnOrVoidViaPEMInputSchema = z.object({
9277
- device_id: z.string().optional(),
9278
- items: z.array(ReceiptItemSchema).min(1, { error: 'arrayMin1' }),
9279
- document_number: z.string().min(1, { error: 'fieldIsRequired' }),
9280
- document_datetime: z.string().optional(),
9281
- lottery_code: z.string().optional(),
9282
- });
9283
- // Receipt Return or Void with Proof Schema
9284
- const ReceiptReturnOrVoidWithProofInputSchema = z.object({
9285
- items: z.array(ReceiptItemSchema).min(1, { error: 'arrayMin1' }),
9286
- proof: ReceiptProofTypeSchema,
9287
- document_datetime: z.string().min(1, { error: 'fieldIsRequired' }),
9288
- });
9289
- // Void Receipt Schema
9290
- const VoidReceiptInputSchema = z.object({
9291
- document_number: z.string().min(1, { error: 'fieldIsRequired' }),
9292
- });
9293
- const ReceiptReturnItemSchema = z
9294
- .array(z.object({
9295
- id: z.number(),
9296
- quantity: z.string().min(1, { error: 'fieldIsRequired' }),
9297
- }))
9298
- .min(1, { error: 'arrayMin1' });
9299
- // Receipt Return Schema
9300
- const ReceiptReturnInputSchema = z.object({
9301
- items: z.array(ReceiptReturnItemSchema).min(1, { error: 'arrayMin1' }),
9302
- document_number: z.string().min(1, { error: 'fieldIsRequired' }),
9303
- });
9304
-
9305
- // Cashier Create Input Schema (MF1)
9306
- const CashierCreateInputSchema = z.object({
9307
- email: z
9308
- .string()
9309
- .min(1, { error: 'fieldIsRequired' })
9310
- .max(255, { error: 'emailMaxLength' })
9311
- .email({ error: 'invalidEmail' }),
9312
- password: z
9313
- .string()
9314
- .min(8, { error: 'passwordMinLength' })
9315
- .max(40, { error: 'passwordMaxLength' }),
9316
- name: z.string().min(1, { error: 'fieldIsRequired' }).max(255, { error: 'nameMaxLength' }),
9317
- display_name: z
9318
- .string()
9319
- .min(1, { error: 'fieldIsRequired' })
9320
- .max(255, { error: 'displayNameMaxLength' }),
9321
- });
9322
-
9323
- // Enum options arrays
9324
- const PEM_STATUS_OPTIONS = [
9325
- 'NEW',
9326
- 'REGISTERED',
9327
- 'ACTIVATED',
9328
- 'ONLINE',
9329
- 'OFFLINE',
9330
- 'DISCARDED',
9331
- ];
9332
- // Address Schema (reusable)
9333
- const AddressSchema = z.object({
9334
- street_address: z.string().min(1, { error: 'fieldIsRequired' }),
9335
- street_number: z.string().min(1, { error: 'fieldIsRequired' }),
9336
- zip_code: z
9337
- .string()
9338
- .min(1, { error: 'fieldIsRequired' })
9339
- .regex(/^\d{5}$/, { error: 'invalidZipCode' }),
9340
- city: z.string().min(1, { error: 'fieldIsRequired' }),
9341
- province: z
9342
- .string()
9343
- .min(2, { error: 'provinceMinLength' })
9344
- .max(2, { error: 'provinceMaxLength' })
9345
- .toUpperCase(),
9346
- });
9347
- // PEM Status Schema
9348
- const PEMStatusSchema = z.enum(PEM_STATUS_OPTIONS);
9349
- // Activation Request Schema
9350
- const ActivationRequestSchema = z.object({
9351
- registration_key: z.string().min(1, { error: 'fieldIsRequired' }),
9352
- });
9353
- // PEM Status Offline Request Schema
9354
- const PEMStatusOfflineRequestSchema = z.object({
9355
- timestamp: z
9356
- .string()
9357
- .min(1, { error: 'fieldIsRequired' })
9358
- .refine((val) => !isNaN(Date.parse(val)), {
9359
- error: 'invalidDateFormat',
9360
- }),
9361
- reason: z.string().min(1, { error: 'fieldIsRequired' }),
9362
- });
9465
+ /**
9466
+ * Manually trigger a telemetry sync
9467
+ */
9468
+ async syncTelemetry() {
9469
+ this.ensureInitialized();
9470
+ return this.telemetryService.triggerSync();
9471
+ }
9472
+ /**
9473
+ * Check if the manager is initialized
9474
+ */
9475
+ getIsInitialized() {
9476
+ return this.isInitialized;
9477
+ }
9478
+ /**
9479
+ * Get the underlying SDK instance (for advanced use cases)
9480
+ */
9481
+ getSDK() {
9482
+ this.ensureInitialized();
9483
+ return this.sdk;
9484
+ }
9485
+ cleanup() {
9486
+ this.notificationService?.destroy();
9487
+ this.telemetryService?.destroy();
9488
+ this.appStateService?.destroy();
9489
+ this.sdk?.destroy();
9490
+ this.notificationService = null;
9491
+ this.telemetryService = null;
9492
+ this.appStateService = null;
9493
+ this.sdk = null;
9494
+ this.isInitialized = false;
9495
+ this.isPollingActive = false;
9496
+ }
9497
+ ensureInitialized() {
9498
+ if (!this.isInitialized) {
9499
+ throw new ACubeSDKError('SDK_NOT_INITIALIZED', 'SDKManager not initialized. Call initialize() first.');
9500
+ }
9501
+ }
9502
+ }
9503
+ SDKManager.instance = null;
9363
9504
 
9364
- // Cash Register Create Schema
9365
- const CashRegisterCreateSchema = z.object({
9366
- pem_serial_number: z.string().min(1, { error: 'fieldIsRequired' }),
9367
- name: z.string().min(1, { error: 'fieldIsRequired' }).max(100, { error: 'nameMaxLength' }),
9368
- });
9505
+ const RECEIPT_READY = 'ready';
9506
+ const RECEIPT_SENT = 'sent';
9507
+ const RECEIPT_SORT_DESCENDING = 'descending';
9508
+ const RECEIPT_SORT_ASCENDING = 'ascending';
9369
9509
 
9370
- // VAT number validation regex (Partita IVA - 11 digits)
9371
- const VAT_NUMBER_REGEX = /^\d{11}$/;
9372
- // Fiscal code validation regex (Codice Fiscale - 11 digits only for merchants)
9373
- const FISCAL_CODE_REGEX = /^\d{11}$/;
9374
- // Password validation regex (from OpenAPI spec)
9375
- const PASSWORD_REGEX = /^((?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{10,}).*)$/;
9376
- // Merchant Create Input Schema
9377
- const MerchantCreateInputSchema = z
9378
- .object({
9379
- vat_number: z
9380
- .string()
9381
- .min(1, { error: 'fieldIsRequired' })
9382
- .regex(VAT_NUMBER_REGEX, { error: 'invalidVatNumber' }),
9383
- fiscal_code: z.string().regex(FISCAL_CODE_REGEX, { error: 'invalidFiscalCode' }).optional(),
9384
- business_name: z.string().max(200, { error: 'businessNameMaxLength' }).optional().nullable(),
9385
- first_name: z.string().max(100, { error: 'firstNameMaxLength' }).optional().nullable(),
9386
- last_name: z.string().max(100, { error: 'lastNameMaxLength' }).optional().nullable(),
9387
- email: z.string().min(1, { error: 'fieldIsRequired' }).email({ error: 'invalidEmail' }),
9388
- password: z
9389
- .string()
9390
- .min(1, { error: 'fieldIsRequired' })
9391
- .regex(PASSWORD_REGEX, { error: 'passwordComplexity' }),
9392
- address: AddressSchema.optional(),
9393
- })
9394
- .refine((data) => {
9395
- const hasBusinessName = data.business_name && data.business_name.trim() !== '';
9396
- const hasPersonalNames = (data.first_name && data.first_name.trim() !== '') ||
9397
- (data.last_name && data.last_name.trim() !== '');
9398
- // If business name is set, first/last name must not be provided
9399
- if (hasBusinessName && hasPersonalNames) {
9400
- return false;
9510
+ const log = createPrefixedLogger('CACHE-HANDLER');
9511
+ class CacheHandler {
9512
+ constructor(cache, networkMonitor) {
9513
+ this.cache = cache;
9514
+ this.networkMonitor = networkMonitor;
9515
+ this.currentOnlineState = true;
9516
+ this.setupNetworkMonitoring();
9401
9517
  }
9402
- // At least one naming method must be provided
9403
- if (!hasBusinessName && !hasPersonalNames) {
9518
+ setupNetworkMonitoring() {
9519
+ if (this.networkMonitor) {
9520
+ this.networkSubscription = this.networkMonitor.online$.subscribe((online) => {
9521
+ this.currentOnlineState = online;
9522
+ });
9523
+ }
9524
+ }
9525
+ isOnline() {
9526
+ if (this.networkMonitor) {
9527
+ return this.currentOnlineState;
9528
+ }
9529
+ if (typeof navigator !== 'undefined' && 'onLine' in navigator) {
9530
+ return navigator.onLine;
9531
+ }
9404
9532
  return false;
9405
9533
  }
9406
- return true;
9407
- }, {
9408
- error: 'businessNameOrPersonalNamesRequired',
9409
- path: ['business_name'],
9410
- });
9411
- // Merchant Update Input Schema
9412
- const MerchantUpdateInputSchema = z.object({
9413
- business_name: z.string().max(200, { error: 'businessNameMaxLength' }).optional().nullable(),
9414
- first_name: z.string().max(100, { error: 'firstNameMaxLength' }).optional().nullable(),
9415
- last_name: z.string().max(100, { error: 'lastNameMaxLength' }).optional().nullable(),
9416
- address: AddressSchema.optional().nullable(),
9417
- });
9418
-
9419
- // Enum options arrays
9420
- const PEM_TYPE_OPTIONS = ['AP', 'SP', 'TM', 'PV'];
9421
- // PEM Data Schema
9422
- const PemDataSchema = z.object({
9423
- version: z.string().min(1, { error: 'fieldIsRequired' }),
9424
- type: z.enum(PEM_TYPE_OPTIONS, {
9425
- error: 'invalidPemType',
9426
- }),
9427
- });
9428
- // PEM Create Input Schema
9429
- const PemCreateInputSchema = z.object({
9430
- merchant_uuid: z.string().min(1, { error: 'fieldIsRequired' }).uuid({ error: 'invalidUuid' }),
9431
- address: AddressSchema.optional(),
9432
- /* external_pem_data: PemDataSchema.optional(), */
9433
- });
9434
-
9435
- // Italian Fiscal ID validation regex (Codice Fiscale for individuals or Partita IVA for companies)
9436
- const FISCAL_ID_REGEX = /^([A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]|[0-9]{11})$/;
9437
- // Supplier Create Input Schema
9438
- const SupplierCreateInputSchema = z.object({
9439
- fiscal_id: z
9440
- .string()
9441
- .min(1, { error: 'fieldIsRequired' })
9442
- .regex(FISCAL_ID_REGEX, { error: 'invalidFiscalId' })
9443
- .toUpperCase(),
9444
- name: z.string().min(1, { error: 'fieldIsRequired' }).max(200, { error: 'nameMaxLength' }),
9445
- address: AddressSchema.optional(),
9446
- });
9447
- // Supplier Update Input Schema
9448
- const SupplierUpdateInputSchema = z.object({
9449
- name: z.string().min(1, { error: 'fieldIsRequired' }).max(200, { error: 'nameMaxLength' }),
9450
- address: AddressSchema.optional(),
9451
- });
9452
-
9453
- // Journal Close Input Schema
9454
- const JournalCloseInputSchema = z.object({
9455
- closing_timestamp: z
9456
- .string()
9457
- .min(1, { error: 'fieldIsRequired' })
9458
- .refine((val) => !isNaN(Date.parse(val)), {
9459
- error: 'invalidDateFormat',
9460
- }),
9461
- reason: z.string().max(255, { error: 'reasonMaxLength' }).optional(),
9462
- });
9463
-
9464
- // Daily Report Status Options
9465
- const DAILY_REPORT_STATUS_OPTIONS = ['pending', 'sent', 'error'];
9466
- // Daily Report Status Schema
9467
- const DailyReportStatusSchema = z.enum(DAILY_REPORT_STATUS_OPTIONS, {
9468
- error: 'invalidDailyReportStatus',
9469
- });
9470
- // Daily Reports List Parameters Schema
9471
- const DailyReportsParamsSchema = z.object({
9472
- pem_serial_number: z.string().min(1, { error: 'fieldIsRequired' }).optional(),
9473
- date_from: z
9474
- .string()
9475
- .refine((val) => !isNaN(Date.parse(val)), {
9476
- error: 'invalidDateFormat',
9477
- })
9478
- .optional(),
9479
- date_to: z
9480
- .string()
9481
- .refine((val) => !isNaN(Date.parse(val)), {
9482
- error: 'invalidDateFormat',
9483
- })
9484
- .optional(),
9485
- status: DailyReportStatusSchema.optional(),
9486
- page: z.number().min(1, { error: 'pageMinValue' }).optional(),
9487
- });
9488
-
9489
- const NotificationScopeSchema = z.object({
9490
- type: z.literal('global'),
9491
- });
9492
- const PemStatusSchema = z.enum(['ONLINE', 'OFFLINE']);
9493
- const NotificationDataBlockAtSchema = z.object({
9494
- block_at: z.string(),
9495
- });
9496
- const NotificationDataPemStatusSchema = z.object({
9497
- from: PemStatusSchema,
9498
- to: PemStatusSchema,
9499
- });
9500
- const NotificationBaseSchema = z.object({
9501
- uuid: z.string().uuid({ error: 'invalidUuid' }),
9502
- scope: NotificationScopeSchema,
9503
- source: z.enum(['system', 'Italian Tax Authority']),
9504
- level: z.enum(['info', 'warning', 'error', 'critical']),
9505
- created_at: z.string(),
9506
- });
9507
- const NotificationMf2UnreachableSchema = NotificationBaseSchema.extend({
9508
- type: z.literal('INTERNAL_COMMUNICATION_FAILURE'),
9509
- code: z.literal('SYS-W-01'),
9510
- data: NotificationDataBlockAtSchema,
9511
- });
9512
- const NotificationPemsBlockedSchema = NotificationBaseSchema.extend({
9513
- type: z.literal('PEM_STATUS_CHANGED'),
9514
- code: z.literal('SYS-C-01'),
9515
- data: NotificationDataPemStatusSchema,
9516
- });
9517
- const NotificationPemBackOnlineSchema = NotificationBaseSchema.extend({
9518
- type: z.literal('PEM_STATUS_CHANGED'),
9519
- code: z.literal('SYS-I-01'),
9520
- data: NotificationDataPemStatusSchema,
9521
- });
9522
- const NotificationSchema = z.discriminatedUnion('code', [
9523
- NotificationMf2UnreachableSchema,
9524
- NotificationPemsBlockedSchema,
9525
- NotificationPemBackOnlineSchema,
9526
- ]);
9527
- const NotificationListResponseSchema = z.object({
9528
- members: z.array(NotificationSchema),
9529
- });
9534
+ async handleCachedRequest(url, requestFn, config) {
9535
+ if (!this.cache || config?.useCache === false) {
9536
+ const response = await requestFn();
9537
+ return response.data;
9538
+ }
9539
+ const cacheKey = this.generateCacheKey(url);
9540
+ const online = this.isOnline();
9541
+ log.debug('Request:', { url, cacheKey, online });
9542
+ if (online) {
9543
+ try {
9544
+ const response = await requestFn();
9545
+ if (this.cache) {
9546
+ await this.cache.set(cacheKey, response.data).catch((error) => {
9547
+ log.error('Failed to cache:', error instanceof Error ? error.message : error);
9548
+ });
9549
+ }
9550
+ return response.data;
9551
+ }
9552
+ catch (error) {
9553
+ const cached = await this.cache.get(cacheKey).catch(() => null);
9554
+ if (cached) {
9555
+ log.debug('Network failed, using cache fallback');
9556
+ return cached.data;
9557
+ }
9558
+ throw error;
9559
+ }
9560
+ }
9561
+ else {
9562
+ const cached = await this.cache.get(cacheKey).catch(() => null);
9563
+ if (cached) {
9564
+ log.debug('Offline, returning cached data');
9565
+ return cached.data;
9566
+ }
9567
+ throw new Error('Offline: No cached data available');
9568
+ }
9569
+ }
9570
+ generateCacheKey(url) {
9571
+ return url;
9572
+ }
9573
+ async invalidateCache(pattern) {
9574
+ if (!this.cache)
9575
+ return;
9576
+ try {
9577
+ await this.cache.invalidate(pattern);
9578
+ }
9579
+ catch (error) {
9580
+ log.error('Invalidation failed:', error instanceof Error ? error.message : error);
9581
+ }
9582
+ }
9583
+ getCacheStatus() {
9584
+ return {
9585
+ available: !!this.cache,
9586
+ networkMonitorAvailable: !!this.networkMonitor,
9587
+ isOnline: this.isOnline(),
9588
+ };
9589
+ }
9590
+ destroy() {
9591
+ this.networkSubscription?.unsubscribe();
9592
+ }
9593
+ }
9530
9594
 
9531
- const TelemetryMerchantSchema = z.object({
9532
- vat_number: z.string(),
9533
- fiscal_code: z.string().nullable(),
9534
- business_name: z.string(),
9535
- });
9536
- const TelemetrySupplierSchema = z.object({
9537
- vat_number: z.string(),
9538
- fiscal_code: z.string().nullable(),
9539
- business_name: z.string(),
9540
- });
9541
- const TelemetrySoftwareVersionSchema = z.object({
9542
- version: z.string(),
9543
- swid: z.string(),
9544
- installed_at: z.string(),
9545
- status: z.enum(['active', 'inactive', 'archived']),
9546
- });
9547
- const TelemetrySoftwareSchema = z.object({
9548
- code: z.string(),
9549
- name: z.string(),
9550
- approval_reference: z.string(),
9551
- version_info: TelemetrySoftwareVersionSchema,
9552
- });
9553
- const PendingReceiptsSchema = z.object({
9554
- count: z.number().int().nonnegative(),
9555
- total_amount: z.string(),
9556
- });
9557
- const TransmissionSchema = z.object({
9558
- attempted_at: z.string(),
9559
- outcome: z.enum(['success', 'failed', 'pending']),
9560
- });
9561
- const MessageSchema = z.object({
9562
- received_at: z.string(),
9563
- content: z.string(),
9564
- });
9565
- const LotterySecretRequestSchema = z.object({
9566
- requested_at: z.string(),
9567
- outcome: z.enum(['success', 'failed', 'pending']),
9568
- });
9569
- const LotterySchema = z.object({
9570
- last_transmission: TransmissionSchema,
9571
- secret_request: LotterySecretRequestSchema,
9572
- });
9573
- const TelemetrySchema = z.object({
9574
- pem_id: z.string(),
9575
- pem_status: z.enum(['ONLINE', 'OFFLINE', 'ERROR']),
9576
- pem_status_changed_at: z.string(),
9577
- merchant: TelemetryMerchantSchema,
9578
- supplier: TelemetrySupplierSchema,
9579
- software: TelemetrySoftwareSchema,
9580
- last_communication_at: z.string(),
9581
- pending_receipts: PendingReceiptsSchema,
9582
- last_receipt_transmission: TransmissionSchema,
9583
- last_message_from_mf2: MessageSchema,
9584
- ade_corrispettivi_transmission: TransmissionSchema,
9585
- last_message_from_ade: MessageSchema,
9586
- lottery: LotterySchema,
9587
- });
9595
+ function transformError(error) {
9596
+ if (axios.isAxiosError(error)) {
9597
+ const response = error.response;
9598
+ if (!response) {
9599
+ return new ACubeSDKError('NETWORK_ERROR', 'Network error occurred', error);
9600
+ }
9601
+ const status = response.status;
9602
+ const data = response.data;
9603
+ const violations = data?.violations;
9604
+ let message = 'Unknown error occurred';
9605
+ if (data?.detail) {
9606
+ message = data.detail;
9607
+ }
9608
+ else if (data?.title) {
9609
+ message = data.title;
9610
+ }
9611
+ else if (error.message) {
9612
+ message = error.message;
9613
+ }
9614
+ switch (status) {
9615
+ case 400:
9616
+ return new ACubeSDKError('VALIDATION_ERROR', message, error, status, violations);
9617
+ case 401:
9618
+ return new ACubeSDKError('AUTH_ERROR', message, error, status, violations);
9619
+ case 403:
9620
+ return new ACubeSDKError('FORBIDDEN_ERROR', message, error, status, violations);
9621
+ case 404:
9622
+ return new ACubeSDKError('NOT_FOUND_ERROR', message, error, status, violations);
9623
+ case 422:
9624
+ return new ACubeSDKError('VALIDATION_ERROR', message, error, status, violations);
9625
+ default:
9626
+ return new ACubeSDKError('UNKNOWN_ERROR', message, error, status, violations);
9627
+ }
9628
+ }
9629
+ return new ACubeSDKError('UNKNOWN_ERROR', 'Unknown error occurred', error);
9630
+ }
9588
9631
 
9589
- // Receipt schemas and types
9590
- // Common validation utilities
9591
- const ValidationMessages = {
9592
- fieldIsRequired: 'This field is required',
9593
- arrayMin1: 'At least one item is required',
9594
- paymentMethodRequired: 'At least one payment method is required',
9595
- invalidEmail: 'Please enter a valid email address',
9596
- passwordMinLength: 'Password must be at least 8 characters long',
9597
- passwordComplexity: 'Password must contain at least one uppercase letter, one lowercase letter, one number, and one special character',
9598
- invalidZipCode: 'Please enter a valid 5-digit zip code',
9599
- provinceMinLength: 'Province code must be 2 characters',
9600
- provinceMaxLength: 'Province code must be 2 characters',
9601
- invalidDateFormat: 'Please enter a valid date',
9602
- nameMaxLength: 'Name is too long',
9603
- invalidFiscalId: 'Please enter a valid Italian fiscal ID (Codice Fiscale or Partita IVA)',
9604
- invalidVatNumber: 'Please enter a valid VAT number (11 digits)',
9605
- invalidFiscalCode: 'Please enter a valid fiscal code (11 digits)',
9606
- businessNameMaxLength: 'Business name is too long (max 200 characters)',
9607
- businessNameOrPersonalNamesRequired: 'Please provide either a business name or first/last name, but not both',
9608
- firstNameMaxLength: 'First name is too long (max 100 characters)',
9609
- lastNameMaxLength: 'Last name is too long (max 100 characters)',
9610
- invalidUuid: 'Please enter a valid UUID',
9611
- invalidPemType: 'PEM type must be one of: AP, SP, TM, PV',
9612
- reasonMaxLength: 'Reason is too long (max 255 characters)',
9613
- pageMinValue: 'Page number must be at least 1',
9614
- invalidDailyReportStatus: 'Daily report status must be one of: pending, sent, error',
9615
- displayNameMaxLength: 'Display name is too long (max 255 characters)',
9616
- };
9617
- // Validation helper functions
9618
- const validateInput = (schema, data) => {
9619
- const result = schema.safeParse(data);
9620
- if (!result.success) {
9621
- const errors = result.error.issues.map((error) => ({
9622
- field: error.path.join('.'),
9623
- message: error.message,
9624
- code: error.code,
9625
- }));
9632
+ var ErrorCategory;
9633
+ (function (ErrorCategory) {
9634
+ ErrorCategory["SERVER_ERROR"] = "SERVER_ERROR";
9635
+ ErrorCategory["CLIENT_ERROR"] = "CLIENT_ERROR";
9636
+ ErrorCategory["AUTH_ERROR"] = "AUTH_ERROR";
9637
+ ErrorCategory["CERTIFICATE_ERROR"] = "CERTIFICATE_ERROR";
9638
+ ErrorCategory["NETWORK_ERROR"] = "NETWORK_ERROR";
9639
+ ErrorCategory["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
9640
+ })(ErrorCategory || (ErrorCategory = {}));
9641
+ function extractStatusCode(error) {
9642
+ if (error instanceof MTLSError && error.statusCode) {
9643
+ return error.statusCode;
9644
+ }
9645
+ const errorObj = error;
9646
+ if (errorObj?.response?.status) {
9647
+ return errorObj.response.status;
9648
+ }
9649
+ if (typeof errorObj?.statusCode === 'number') {
9650
+ return errorObj.statusCode;
9651
+ }
9652
+ return undefined;
9653
+ }
9654
+ function classifyError(error) {
9655
+ const statusCode = extractStatusCode(error);
9656
+ const errorMessage = error instanceof Error ? error.message : String(error);
9657
+ if (statusCode && statusCode >= 500 && statusCode < 600) {
9626
9658
  return {
9627
- success: false,
9628
- errors,
9629
- data: null,
9659
+ category: ErrorCategory.SERVER_ERROR,
9660
+ statusCode,
9661
+ message: errorMessage,
9662
+ shouldRetry: false,
9663
+ userMessage: `Server error (${statusCode}): The server encountered an error.`,
9664
+ };
9665
+ }
9666
+ if (statusCode === 401 || statusCode === 403) {
9667
+ return {
9668
+ category: ErrorCategory.AUTH_ERROR,
9669
+ statusCode,
9670
+ message: errorMessage,
9671
+ shouldRetry: false,
9672
+ userMessage: `Authentication error (${statusCode}): Invalid credentials or insufficient permissions.`,
9673
+ };
9674
+ }
9675
+ if (statusCode && statusCode >= 400 && statusCode < 500) {
9676
+ return {
9677
+ category: ErrorCategory.CLIENT_ERROR,
9678
+ statusCode,
9679
+ message: errorMessage,
9680
+ shouldRetry: false,
9681
+ userMessage: `Request error (${statusCode}): ${errorMessage}`,
9682
+ };
9683
+ }
9684
+ if (error instanceof MTLSError) {
9685
+ return {
9686
+ category: ErrorCategory.CERTIFICATE_ERROR,
9687
+ statusCode,
9688
+ message: errorMessage,
9689
+ shouldRetry: true,
9690
+ userMessage: 'Certificate error: Unable to establish secure connection.',
9691
+ };
9692
+ }
9693
+ if (!statusCode &&
9694
+ (errorMessage.toLowerCase().includes('network') ||
9695
+ errorMessage.toLowerCase().includes('timeout') ||
9696
+ errorMessage.toLowerCase().includes('connection'))) {
9697
+ return {
9698
+ category: ErrorCategory.NETWORK_ERROR,
9699
+ message: errorMessage,
9700
+ shouldRetry: true,
9701
+ userMessage: 'Network error: Unable to connect to server.',
9630
9702
  };
9631
9703
  }
9632
9704
  return {
9633
- success: true,
9634
- errors: [],
9635
- data: result.data,
9705
+ category: ErrorCategory.UNKNOWN_ERROR,
9706
+ statusCode,
9707
+ message: errorMessage,
9708
+ shouldRetry: false,
9709
+ userMessage: `Unexpected error: ${errorMessage}`,
9636
9710
  };
9637
- };
9711
+ }
9712
+ function shouldReconfigureCertificate(error) {
9713
+ const classification = classifyError(error);
9714
+ return classification.category === ErrorCategory.CERTIFICATE_ERROR;
9715
+ }
9716
+ function shouldRetryRequest(error, isRetryAttempt) {
9717
+ if (isRetryAttempt) {
9718
+ return false;
9719
+ }
9720
+ const classification = classifyError(error);
9721
+ return classification.shouldRetry;
9722
+ }
9723
+ function getUserFriendlyMessage(error) {
9724
+ const classification = classifyError(error);
9725
+ return classification.userMessage;
9726
+ }
9638
9727
 
9639
9728
  var MTLSErrorType;
9640
9729
  (function (MTLSErrorType) {