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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var axios = require('axios');
6
5
  var z = require('zod');
6
+ var axios = require('axios');
7
7
 
8
8
  function _interopNamespaceDefault(e) {
9
9
  var n = Object.create(null);
@@ -1415,6 +1415,15 @@ function from(input, scheduler) {
1415
1415
  return scheduler ? scheduled(input, scheduler) : innerFrom(input);
1416
1416
  }
1417
1417
 
1418
+ function of() {
1419
+ var args = [];
1420
+ for (var _i = 0; _i < arguments.length; _i++) {
1421
+ args[_i] = arguments[_i];
1422
+ }
1423
+ var scheduler = popScheduler(args);
1424
+ return from(args, scheduler);
1425
+ }
1426
+
1418
1427
  function isValidDate(value) {
1419
1428
  return value instanceof Date && !isNaN(value);
1420
1429
  }
@@ -1861,131 +1870,436 @@ function extractRoles(jwtRoles) {
1861
1870
  return allRoles;
1862
1871
  }
1863
1872
 
1864
- class AuthenticationService {
1865
- get user$() {
1866
- return this.userSubject.asObservable();
1867
- }
1868
- get isAuthenticated$() {
1869
- return this.userSubject.pipe(map((user) => user !== null), distinctUntilChanged(), takeUntil(this.destroy$));
1870
- }
1871
- get authState$() {
1872
- return this.authStateSubject.asObservable();
1873
+ function clearObject(input) {
1874
+ if (input === null || input === undefined || input === '') {
1875
+ return undefined;
1873
1876
  }
1874
- constructor(httpPort, tokenStorage, config, events = {}) {
1875
- this.httpPort = httpPort;
1876
- this.tokenStorage = tokenStorage;
1877
- this.config = config;
1878
- this.events = events;
1879
- this.userSubject = new BehaviorSubject(null);
1880
- this.authStateSubject = new BehaviorSubject('idle');
1881
- this.destroy$ = new Subject();
1877
+ if (Array.isArray(input)) {
1878
+ const cleanedArray = input
1879
+ .map((item) => clearObject(item))
1880
+ .filter((item) => item !== undefined);
1881
+ return cleanedArray;
1882
1882
  }
1883
- async login(credentials) {
1884
- this.authStateSubject.next('authenticating');
1885
- try {
1886
- const response = await this.httpPort.post(`${this.config.authUrl}/login`, {
1887
- email: credentials.email,
1888
- password: credentials.password,
1889
- });
1890
- const jwtPayload = parseJwt(response.data.token);
1891
- const expiresAt = jwtPayload.exp * 1000;
1892
- await this.tokenStorage.saveAccessToken(response.data.token, expiresAt);
1893
- const user = this.createUserFromPayload(jwtPayload);
1894
- await this.tokenStorage.saveUser(user);
1895
- this.userSubject.next(user);
1896
- this.authStateSubject.next('authenticated');
1897
- this.events.onUserChanged?.(user);
1898
- return user;
1899
- }
1900
- catch (error) {
1901
- this.authStateSubject.next('error');
1902
- throw error;
1883
+ if (typeof input === 'object' && input.constructor === Object) {
1884
+ const cleaned = {};
1885
+ for (const [key, value] of Object.entries(input)) {
1886
+ const cleanedValue = clearObject(value);
1887
+ if (cleanedValue !== undefined) {
1888
+ cleaned[key] = cleanedValue;
1889
+ }
1903
1890
  }
1891
+ return cleaned;
1904
1892
  }
1905
- async logout() {
1906
- await this.tokenStorage.clearTokens();
1907
- this.userSubject.next(null);
1908
- this.authStateSubject.next('idle');
1909
- this.events.onUserChanged?.(null);
1893
+ return input;
1894
+ }
1895
+ function clearObjectShallow(obj) {
1896
+ if (!obj || typeof obj !== 'object') {
1897
+ return {};
1910
1898
  }
1911
- async getCurrentUser() {
1912
- const currentUser = this.userSubject.value;
1913
- if (currentUser) {
1914
- return currentUser;
1915
- }
1916
- const storedUser = await this.tokenStorage.getUser();
1917
- if (storedUser) {
1918
- this.userSubject.next(storedUser);
1919
- this.authStateSubject.next('authenticated');
1920
- return storedUser;
1921
- }
1922
- const token = await this.tokenStorage.getAccessToken();
1923
- if (!token) {
1924
- return null;
1925
- }
1926
- const jwtPayload = parseJwt(token);
1927
- if (isTokenExpired(jwtPayload)) {
1928
- await this.tokenStorage.clearTokens();
1929
- return null;
1899
+ const cleaned = {};
1900
+ for (const [key, value] of Object.entries(obj)) {
1901
+ if (value !== null && value !== undefined && value !== '') {
1902
+ cleaned[key] = value;
1930
1903
  }
1931
- const user = this.createUserFromPayload(jwtPayload);
1932
- await this.tokenStorage.saveUser(user);
1933
- this.userSubject.next(user);
1934
- this.authStateSubject.next('authenticated');
1935
- return user;
1936
1904
  }
1937
- async isAuthenticated() {
1938
- const token = await this.tokenStorage.getAccessToken();
1939
- if (!token) {
1940
- return false;
1941
- }
1942
- const jwtPayload = parseJwt(token);
1943
- return !isTokenExpired(jwtPayload);
1905
+ return cleaned;
1906
+ }
1907
+ function isEmpty(value) {
1908
+ return value === null || value === undefined || value === '';
1909
+ }
1910
+ function hasNonEmptyValues(obj) {
1911
+ if (!obj || typeof obj !== 'object') {
1912
+ return false;
1944
1913
  }
1945
- async getAccessToken() {
1946
- const token = await this.tokenStorage.getAccessToken();
1947
- if (!token) {
1948
- return null;
1949
- }
1950
- const jwtPayload = parseJwt(token);
1951
- if (isTokenExpired(jwtPayload)) {
1952
- await this.tokenStorage.clearTokens();
1953
- this.userSubject.next(null);
1954
- this.authStateSubject.next('idle');
1955
- this.events.onUserChanged?.(null);
1956
- return null;
1957
- }
1958
- return token;
1914
+ return Object.values(obj).some((value) => !isEmpty(value));
1915
+ }
1916
+
1917
+ /**
1918
+ * Platform detection utilities
1919
+ */
1920
+ /**
1921
+ * Detect the current platform
1922
+ */
1923
+ function detectPlatform() {
1924
+ // Check for React Native
1925
+ if (typeof global !== 'undefined' &&
1926
+ global.__DEV__ !== undefined &&
1927
+ typeof global.navigator !== 'undefined' &&
1928
+ global.navigator.product === 'ReactNative') {
1929
+ return {
1930
+ platform: 'react-native',
1931
+ isReactNative: true,
1932
+ isWeb: false,
1933
+ isNode: false,
1934
+ isExpo: checkExpo(),
1935
+ };
1959
1936
  }
1960
- createUserFromPayload(jwtPayload) {
1937
+ // Check for Web/Browser
1938
+ if (typeof window !== 'undefined' &&
1939
+ typeof window.document !== 'undefined' &&
1940
+ typeof window.navigator !== 'undefined') {
1961
1941
  return {
1962
- id: jwtPayload.uid.toString(),
1963
- email: jwtPayload.username,
1964
- username: jwtPayload.username,
1965
- roles: jwtPayload.roles,
1966
- fid: jwtPayload.fid,
1967
- pid: jwtPayload.pid,
1968
- expiresAt: jwtPayload.exp * 1000,
1942
+ platform: 'web',
1943
+ isReactNative: false,
1944
+ isWeb: true,
1945
+ isNode: false,
1946
+ isExpo: false,
1969
1947
  };
1970
1948
  }
1971
- destroy() {
1972
- this.destroy$.next();
1973
- this.destroy$.complete();
1949
+ // Check for Node.js
1950
+ if (typeof process !== 'undefined' && process.versions && process.versions.node) {
1951
+ return {
1952
+ platform: 'node',
1953
+ isReactNative: false,
1954
+ isWeb: false,
1955
+ isNode: true,
1956
+ isExpo: false,
1957
+ };
1974
1958
  }
1959
+ // Unknown platform
1960
+ return {
1961
+ platform: 'unknown',
1962
+ isReactNative: false,
1963
+ isWeb: false,
1964
+ isNode: false,
1965
+ isExpo: false,
1966
+ };
1975
1967
  }
1976
-
1977
- const CERTIFICATE_KEY = 'acube_certificate';
1978
- class CertificateService {
1979
- get certificate$() {
1980
- return this.certificateSubject.asObservable();
1968
+ /**
1969
+ * Check if running in Expo
1970
+ */
1971
+ function checkExpo() {
1972
+ try {
1973
+ return (typeof global !== 'undefined' &&
1974
+ (typeof global.Expo !== 'undefined' || typeof global.expo !== 'undefined'));
1981
1975
  }
1982
- get hasCertificate$() {
1983
- return this.certificateSubject.pipe(map((cert) => cert !== null), distinctUntilChanged());
1976
+ catch {
1977
+ return false;
1984
1978
  }
1985
- get state$() {
1986
- return this.stateSubject.asObservable();
1979
+ }
1980
+
1981
+ function getDefaultExportFromCjs (x) {
1982
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
1983
+ }
1984
+
1985
+ var picocolors_browser = {exports: {}};
1986
+
1987
+ var x=String;
1988
+ 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}};
1989
+ picocolors_browser.exports=create();
1990
+ picocolors_browser.exports.createColors = create;
1991
+
1992
+ var picocolors_browserExports = picocolors_browser.exports;
1993
+ var pc = /*@__PURE__*/getDefaultExportFromCjs(picocolors_browserExports);
1994
+
1995
+ const levelColors = {
1996
+ debug: {
1997
+ prefix: pc.gray,
1998
+ message: pc.gray,
1999
+ data: pc.dim,
2000
+ },
2001
+ info: {
2002
+ prefix: pc.cyan,
2003
+ message: pc.white,
2004
+ data: pc.dim,
2005
+ },
2006
+ warn: {
2007
+ prefix: pc.yellow,
2008
+ message: pc.yellow,
2009
+ data: pc.dim,
2010
+ },
2011
+ error: {
2012
+ prefix: pc.red,
2013
+ message: pc.red,
2014
+ data: pc.dim,
2015
+ },
2016
+ };
2017
+ const levelIcons = {
2018
+ debug: '🔍',
2019
+ info: 'ℹ️ ',
2020
+ warn: '⚠️ ',
2021
+ error: '❌',
2022
+ };
2023
+ /**
2024
+ * Format data for pretty display in logs
2025
+ */
2026
+ function formatData(data, level) {
2027
+ if (data === undefined || data === null) {
2028
+ return String(data);
1987
2029
  }
1988
- constructor(secureStorage) {
2030
+ // For primitive types, just return as string
2031
+ if (typeof data !== 'object') {
2032
+ return String(data);
2033
+ }
2034
+ // For Error objects, format nicely
2035
+ if (data instanceof Error) {
2036
+ return `${data.name}: ${data.message}${data.stack ? `\n${pc.dim(data.stack)}` : ''}`;
2037
+ }
2038
+ try {
2039
+ // Apply level-specific coloring
2040
+ const colors = levelColors[level];
2041
+ return colors.data(JSON.stringify(data, null, 2));
2042
+ }
2043
+ catch {
2044
+ // Fallback to JSON.stringify if pretty-format fails
2045
+ try {
2046
+ return JSON.stringify(data, null, 2);
2047
+ }
2048
+ catch {
2049
+ return String(data);
2050
+ }
2051
+ }
2052
+ }
2053
+ class Logger {
2054
+ constructor() {
2055
+ this.enabled = false;
2056
+ }
2057
+ setEnabled(enabled) {
2058
+ this.enabled = enabled;
2059
+ }
2060
+ isEnabled() {
2061
+ return this.enabled;
2062
+ }
2063
+ debug(prefix, message, data) {
2064
+ if (!this.enabled)
2065
+ return;
2066
+ this.log('debug', prefix, message, data);
2067
+ }
2068
+ info(prefix, message, data) {
2069
+ if (!this.enabled)
2070
+ return;
2071
+ this.log('info', prefix, message, data);
2072
+ }
2073
+ warn(prefix, message, data) {
2074
+ this.log('warn', prefix, message, data);
2075
+ }
2076
+ error(prefix, message, data) {
2077
+ this.log('error', prefix, message, data);
2078
+ }
2079
+ log(level, prefix, message, data) {
2080
+ const colors = levelColors[level];
2081
+ const icon = levelIcons[level];
2082
+ const isoTime = new Date().toISOString().split('T')[1] ?? '';
2083
+ const timestamp = pc.dim(isoTime.slice(0, 12));
2084
+ const formattedPrefix = colors.prefix(`[${prefix}]`);
2085
+ const formattedMessage = colors.message(message);
2086
+ const consoleMethod = level === 'debug'
2087
+ ? console.debug
2088
+ : level === 'info'
2089
+ ? console.info
2090
+ : level === 'warn'
2091
+ ? console.warn
2092
+ : console.error;
2093
+ const header = `${timestamp} ${icon} ${formattedPrefix} ${formattedMessage}`;
2094
+ if (data !== undefined) {
2095
+ const formattedData = formatData(data, level);
2096
+ // Check if data is an object (multi-line) or primitive (single-line)
2097
+ const isMultiLine = typeof data === 'object' && data !== null;
2098
+ if (isMultiLine) {
2099
+ consoleMethod(`${header}\n${formattedData}`);
2100
+ }
2101
+ else {
2102
+ consoleMethod(`${header}`, formattedData);
2103
+ }
2104
+ }
2105
+ else {
2106
+ consoleMethod(header);
2107
+ }
2108
+ }
2109
+ }
2110
+ const logger = new Logger();
2111
+ function createPrefixedLogger(prefix) {
2112
+ return {
2113
+ debug: (message, data) => logger.debug(prefix, message, data),
2114
+ info: (message, data) => logger.info(prefix, message, data),
2115
+ warn: (message, data) => logger.warn(prefix, message, data),
2116
+ error: (message, data) => logger.error(prefix, message, data),
2117
+ };
2118
+ }
2119
+
2120
+ /**
2121
+ * Formats a numeric string value to have exactly the specified number of decimal places.
2122
+ * E.g., "1" → "1.00", "10" → "10.00", "1.5" → "1.50"
2123
+ * Returns undefined for undefined input (preserves optional fields).
2124
+ *
2125
+ * @param value - The string value to format
2126
+ * @param decimals - Number of decimal places (default: 2)
2127
+ * @returns Formatted string or undefined if input is undefined
2128
+ */
2129
+ function formatDecimal(value, decimals = 2) {
2130
+ if (value === undefined)
2131
+ return undefined;
2132
+ const num = parseFloat(value);
2133
+ if (isNaN(num))
2134
+ return value;
2135
+ return num.toFixed(decimals);
2136
+ }
2137
+
2138
+ const log$h = createPrefixedLogger('AUTH-SERVICE');
2139
+ class AuthenticationService {
2140
+ get user$() {
2141
+ return this.userSubject.asObservable();
2142
+ }
2143
+ get isAuthenticated$() {
2144
+ return this.userSubject.pipe(map((user) => user !== null), distinctUntilChanged(), takeUntil(this.destroy$));
2145
+ }
2146
+ get authState$() {
2147
+ return this.authStateSubject.asObservable();
2148
+ }
2149
+ constructor(httpPort, tokenStorage, config, events = {}) {
2150
+ this.httpPort = httpPort;
2151
+ this.tokenStorage = tokenStorage;
2152
+ this.config = config;
2153
+ this.events = events;
2154
+ this.userSubject = new BehaviorSubject(null);
2155
+ this.authStateSubject = new BehaviorSubject('idle');
2156
+ this.destroy$ = new Subject();
2157
+ }
2158
+ async login(credentials) {
2159
+ this.authStateSubject.next('authenticating');
2160
+ log$h.info('Login attempt', {
2161
+ authUrl: this.config.authUrl,
2162
+ email: credentials.email,
2163
+ });
2164
+ try {
2165
+ const response = await this.httpPort.post(`${this.config.authUrl}/login`, {
2166
+ email: credentials.email,
2167
+ password: credentials.password,
2168
+ });
2169
+ const jwtPayload = parseJwt(response.data.token);
2170
+ const expiresAt = jwtPayload.exp * 1000;
2171
+ log$h.info('Login successful', {
2172
+ authUrl: this.config.authUrl,
2173
+ tokenPrefix: response.data.token.substring(0, 30) + '...',
2174
+ expiresAt: new Date(expiresAt).toISOString(),
2175
+ });
2176
+ await this.tokenStorage.saveAccessToken(response.data.token, expiresAt);
2177
+ const user = this.createUserFromPayload(jwtPayload);
2178
+ await this.tokenStorage.saveUser(user);
2179
+ this.userSubject.next(user);
2180
+ this.authStateSubject.next('authenticated');
2181
+ this.events.onUserChanged?.(user);
2182
+ return user;
2183
+ }
2184
+ catch (error) {
2185
+ this.authStateSubject.next('error');
2186
+ throw error;
2187
+ }
2188
+ }
2189
+ async logout() {
2190
+ await this.tokenStorage.clearTokens();
2191
+ this.userSubject.next(null);
2192
+ this.authStateSubject.next('idle');
2193
+ this.events.onUserChanged?.(null);
2194
+ }
2195
+ async getCurrentUser() {
2196
+ // Always verify token is valid before returning user
2197
+ const token = await this.tokenStorage.getAccessToken();
2198
+ if (!token) {
2199
+ // No token - clear any stale user state
2200
+ log$h.debug('getCurrentUser: No token in storage');
2201
+ if (this.userSubject.value) {
2202
+ this.userSubject.next(null);
2203
+ this.authStateSubject.next('idle');
2204
+ }
2205
+ return null;
2206
+ }
2207
+ log$h.debug('getCurrentUser: Token found', {
2208
+ tokenPrefix: token.substring(0, 30) + '...',
2209
+ tokenLength: token.length,
2210
+ });
2211
+ const jwtPayload = parseJwt(token);
2212
+ if (isTokenExpired(jwtPayload)) {
2213
+ // Token expired - clear everything
2214
+ log$h.warn('getCurrentUser: Token expired');
2215
+ await this.tokenStorage.clearTokens();
2216
+ this.userSubject.next(null);
2217
+ this.authStateSubject.next('idle');
2218
+ this.events.onUserChanged?.(null);
2219
+ return null;
2220
+ }
2221
+ // Token is valid - return cached user if available
2222
+ const currentUser = this.userSubject.value;
2223
+ if (currentUser) {
2224
+ log$h.debug('getCurrentUser: Returning cached user', {
2225
+ email: currentUser.email,
2226
+ roles: currentUser.roles,
2227
+ });
2228
+ return currentUser;
2229
+ }
2230
+ // Check stored user
2231
+ const storedUser = await this.tokenStorage.getUser();
2232
+ if (storedUser) {
2233
+ this.userSubject.next(storedUser);
2234
+ this.authStateSubject.next('authenticated');
2235
+ return storedUser;
2236
+ }
2237
+ // Create user from token
2238
+ const user = this.createUserFromPayload(jwtPayload);
2239
+ await this.tokenStorage.saveUser(user);
2240
+ this.userSubject.next(user);
2241
+ this.authStateSubject.next('authenticated');
2242
+ return user;
2243
+ }
2244
+ async isAuthenticated() {
2245
+ const token = await this.tokenStorage.getAccessToken();
2246
+ if (!token) {
2247
+ log$h.debug('isAuthenticated: No token in storage');
2248
+ return false;
2249
+ }
2250
+ const jwtPayload = parseJwt(token);
2251
+ const expired = isTokenExpired(jwtPayload);
2252
+ log$h.debug('isAuthenticated: Token check', {
2253
+ hasToken: true,
2254
+ expired,
2255
+ expiresAt: new Date(jwtPayload.exp * 1000).toISOString(),
2256
+ });
2257
+ return !expired;
2258
+ }
2259
+ async getAccessToken() {
2260
+ const token = await this.tokenStorage.getAccessToken();
2261
+ if (!token) {
2262
+ return null;
2263
+ }
2264
+ const jwtPayload = parseJwt(token);
2265
+ if (isTokenExpired(jwtPayload)) {
2266
+ await this.tokenStorage.clearTokens();
2267
+ this.userSubject.next(null);
2268
+ this.authStateSubject.next('idle');
2269
+ this.events.onUserChanged?.(null);
2270
+ return null;
2271
+ }
2272
+ return token;
2273
+ }
2274
+ createUserFromPayload(jwtPayload) {
2275
+ return {
2276
+ id: jwtPayload.uid.toString(),
2277
+ email: jwtPayload.username,
2278
+ username: jwtPayload.username,
2279
+ roles: jwtPayload.roles,
2280
+ fid: jwtPayload.fid,
2281
+ pid: jwtPayload.pid,
2282
+ expiresAt: jwtPayload.exp * 1000,
2283
+ };
2284
+ }
2285
+ destroy() {
2286
+ this.destroy$.next();
2287
+ this.destroy$.complete();
2288
+ }
2289
+ }
2290
+
2291
+ const CERTIFICATE_KEY = 'acube_certificate';
2292
+ class CertificateService {
2293
+ get certificate$() {
2294
+ return this.certificateSubject.asObservable();
2295
+ }
2296
+ get hasCertificate$() {
2297
+ return this.certificateSubject.pipe(map((cert) => cert !== null), distinctUntilChanged());
2298
+ }
2299
+ get state$() {
2300
+ return this.stateSubject.asObservable();
2301
+ }
2302
+ constructor(secureStorage) {
1989
2303
  this.secureStorage = secureStorage;
1990
2304
  this.certificateSubject = new BehaviorSubject(null);
1991
2305
  this.stateSubject = new BehaviorSubject('idle');
@@ -2080,406 +2394,677 @@ function hasAnyRole(userRoles, required) {
2080
2394
  return Object.values(userRoles).some((roles) => required.some((role) => roles.includes(role)));
2081
2395
  }
2082
2396
 
2083
- class AuthStrategy {
2084
- constructor(jwtHandler, mtlsHandler, userProvider, mtlsAdapter) {
2085
- this.jwtHandler = jwtHandler;
2086
- this.mtlsHandler = mtlsHandler;
2087
- this.userProvider = userProvider;
2088
- this.mtlsAdapter = mtlsAdapter;
2397
+ class ConfigManager {
2398
+ constructor(userConfig) {
2399
+ this.config = this.buildConfig(userConfig);
2089
2400
  }
2090
- async determineAuthConfig(url, method, explicitMode) {
2091
- if (this.isNotificationEndpoint(url) || this.isTelemetryEndpoint(url)) {
2092
- return { mode: 'mtls', usePort444: true };
2093
- }
2094
- const platform = this.detectPlatform();
2095
- const userRole = await this.getUserRole();
2096
- const isReceiptEndpoint = this.isReceiptEndpoint(url);
2097
- if (userRole === 'SUPPLIER') {
2098
- return { mode: 'jwt', usePort444: false };
2099
- }
2100
- if (userRole === 'CASHIER') {
2101
- if (!isReceiptEndpoint) {
2102
- return { mode: 'jwt', usePort444: false };
2103
- }
2104
- if (platform === 'mobile') {
2105
- return { mode: 'mtls', usePort444: true };
2106
- }
2107
- return { mode: 'jwt', usePort444: true };
2108
- }
2109
- if (userRole === 'MERCHANT') {
2110
- if (!isReceiptEndpoint) {
2111
- return { mode: 'jwt', usePort444: false };
2112
- }
2113
- if (this.isReturnableItemsEndpoint(url)) {
2114
- return { mode: 'mtls', usePort444: true };
2115
- }
2116
- if (method === 'GET') {
2117
- if (this.isDetailedReceiptEndpoint(url)) {
2118
- if (platform === 'mobile') {
2119
- return { mode: 'mtls', usePort444: true };
2120
- }
2121
- return { mode: 'jwt', usePort444: true };
2122
- }
2123
- return { mode: 'jwt', usePort444: false };
2124
- }
2125
- if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) {
2126
- if (platform === 'mobile') {
2127
- return { mode: 'mtls', usePort444: true };
2128
- }
2129
- return { mode: 'jwt', usePort444: true };
2130
- }
2131
- return { mode: 'jwt', usePort444: false };
2132
- }
2133
- if (explicitMode) {
2134
- if (userRole === 'SUPPLIER' && explicitMode === 'mtls') {
2135
- return { mode: 'jwt', usePort444: false };
2136
- }
2137
- return {
2138
- mode: explicitMode,
2139
- usePort444: explicitMode === 'mtls' || (platform === 'web' && isReceiptEndpoint),
2140
- };
2141
- }
2142
- if (platform === 'web') {
2143
- return { mode: 'jwt', usePort444: isReceiptEndpoint };
2144
- }
2145
- if (isReceiptEndpoint && platform === 'mobile') {
2146
- return { mode: 'mtls', usePort444: true };
2147
- }
2148
- return { mode: 'jwt', usePort444: false };
2149
- }
2150
- async getAuthHeaders() {
2151
- return this.jwtHandler.getAuthHeaders();
2152
- }
2153
- getMtlsHandler() {
2154
- return this.mtlsHandler;
2155
- }
2156
- getJwtHandler() {
2157
- return this.jwtHandler;
2401
+ buildConfig(userConfig) {
2402
+ return {
2403
+ environment: userConfig.environment,
2404
+ apiUrl: this.getDefaultApiUrl(userConfig.environment),
2405
+ authUrl: this.getDefaultAuthUrl(userConfig.environment),
2406
+ timeout: 30000,
2407
+ retryAttempts: 3,
2408
+ debug: userConfig.debug ?? false,
2409
+ customHeaders: {},
2410
+ };
2158
2411
  }
2159
- detectPlatform() {
2160
- if (!this.mtlsAdapter) {
2161
- return 'web';
2412
+ getDefaultApiUrl(environment) {
2413
+ switch (environment) {
2414
+ case 'production':
2415
+ return 'https://ereceipts-it.acubeapi.com';
2416
+ case 'development':
2417
+ return 'https://ereceipts-it.dev.acubeapi.com';
2418
+ case 'sandbox':
2419
+ default:
2420
+ return 'https://ereceipts-it-sandbox.acubeapi.com';
2162
2421
  }
2163
- const platformInfo = this.mtlsAdapter.getPlatformInfo();
2164
- return platformInfo.platform === 'web' ? 'web' : 'mobile';
2165
2422
  }
2166
- async getUserRole() {
2167
- if (!this.userProvider) {
2168
- return null;
2169
- }
2170
- const user = await this.userProvider.getCurrentUser();
2171
- if (!user || !user.roles) {
2172
- return null;
2173
- }
2174
- if (hasRole(user.roles, 'ROLE_SUPPLIER')) {
2175
- return 'SUPPLIER';
2176
- }
2177
- if (hasRole(user.roles, 'ROLE_MERCHANT')) {
2178
- return 'MERCHANT';
2179
- }
2180
- if (hasRole(user.roles, 'ROLE_CASHIER')) {
2181
- return 'CASHIER';
2423
+ getDefaultAuthUrl(environment) {
2424
+ switch (environment) {
2425
+ case 'production':
2426
+ return 'https://common.api.acubeapi.com';
2427
+ case 'development':
2428
+ case 'sandbox':
2429
+ default:
2430
+ return 'https://common-sandbox.api.acubeapi.com';
2182
2431
  }
2183
- return null;
2184
- }
2185
- isReceiptEndpoint(url) {
2186
- return url.includes('/receipts') || url.includes('/mf1/receipts');
2187
- }
2188
- isReturnableItemsEndpoint(url) {
2189
- return !!(url.match(/\/receipts\/[a-f0-9-]+\/returnable-items$/) ||
2190
- url.match(/\/mf1\/receipts\/[a-f0-9-]+\/returnable-items$/));
2191
2432
  }
2192
- isDetailedReceiptEndpoint(url) {
2193
- return !!(url.match(/\/receipts\/[a-f0-9-]+\/details$/) ||
2194
- url.match(/\/mf1\/receipts\/[a-f0-9-]+\/details$/));
2433
+ getConfig() {
2434
+ return {
2435
+ environment: this.config.environment,
2436
+ debug: this.config.debug,
2437
+ };
2195
2438
  }
2196
- isNotificationEndpoint(url) {
2197
- return url.includes('/mf1/notifications');
2439
+ getApiUrl() {
2440
+ return this.config.apiUrl;
2198
2441
  }
2199
- isTelemetryEndpoint(url) {
2200
- return !!url.match(/\/mf1\/pems\/[^/]+\/telemetry/);
2442
+ getAuthUrl() {
2443
+ return this.config.authUrl;
2201
2444
  }
2202
- }
2203
-
2204
- class JwtAuthHandler {
2205
- constructor(tokenStorage) {
2206
- this.tokenStorage = tokenStorage;
2445
+ getEnvironment() {
2446
+ return this.config.environment;
2207
2447
  }
2208
- async getAuthConfig(_url, _method) {
2209
- return { mode: 'jwt', usePort444: false };
2448
+ isDebugEnabled() {
2449
+ return this.config.debug;
2210
2450
  }
2211
- async getAuthHeaders() {
2212
- const token = await this.tokenStorage.getAccessToken();
2213
- if (!token) {
2214
- return {};
2215
- }
2216
- return { Authorization: `Bearer ${token}` };
2451
+ getTimeout() {
2452
+ return this.config.timeout;
2217
2453
  }
2218
- }
2219
-
2220
- function clearObject(input) {
2221
- if (input === null || input === undefined || input === '') {
2222
- return undefined;
2454
+ getRetryAttempts() {
2455
+ return this.config.retryAttempts;
2223
2456
  }
2224
- if (Array.isArray(input)) {
2225
- const cleanedArray = input
2226
- .map((item) => clearObject(item))
2227
- .filter((item) => item !== undefined);
2228
- return cleanedArray;
2457
+ getCustomHeaders() {
2458
+ return { ...this.config.customHeaders };
2229
2459
  }
2230
- if (typeof input === 'object' && input.constructor === Object) {
2231
- const cleaned = {};
2232
- for (const [key, value] of Object.entries(input)) {
2233
- const cleanedValue = clearObject(value);
2234
- if (cleanedValue !== undefined) {
2235
- cleaned[key] = cleanedValue;
2236
- }
2460
+ updateConfig(updates) {
2461
+ if (updates.environment) {
2462
+ this.config.environment = updates.environment;
2463
+ this.config.apiUrl = this.getDefaultApiUrl(updates.environment);
2464
+ this.config.authUrl = this.getDefaultAuthUrl(updates.environment);
2237
2465
  }
2238
- return cleaned;
2239
- }
2240
- return input;
2241
- }
2242
- function clearObjectShallow(obj) {
2243
- if (!obj || typeof obj !== 'object') {
2244
- return {};
2245
- }
2246
- const cleaned = {};
2247
- for (const [key, value] of Object.entries(obj)) {
2248
- if (value !== null && value !== undefined && value !== '') {
2249
- cleaned[key] = value;
2466
+ if (updates.debug !== undefined) {
2467
+ this.config.debug = updates.debug;
2250
2468
  }
2251
2469
  }
2252
- return cleaned;
2253
- }
2254
- function isEmpty(value) {
2255
- return value === null || value === undefined || value === '';
2256
- }
2257
- function hasNonEmptyValues(obj) {
2258
- if (!obj || typeof obj !== 'object') {
2259
- return false;
2260
- }
2261
- return Object.values(obj).some((value) => !isEmpty(value));
2262
2470
  }
2263
2471
 
2264
- /**
2265
- * Platform detection utilities
2266
- */
2267
- /**
2268
- * Detect the current platform
2269
- */
2270
- function detectPlatform() {
2271
- // Check for React Native
2272
- if (typeof global !== 'undefined' &&
2273
- global.__DEV__ !== undefined &&
2274
- typeof global.navigator !== 'undefined' &&
2275
- global.navigator.product === 'ReactNative') {
2276
- return {
2277
- platform: 'react-native',
2278
- isReactNative: true,
2279
- isWeb: false,
2280
- isNode: false,
2281
- isExpo: checkExpo(),
2282
- };
2283
- }
2284
- // Check for Web/Browser
2285
- if (typeof window !== 'undefined' &&
2286
- typeof window.document !== 'undefined' &&
2287
- typeof window.navigator !== 'undefined') {
2288
- return {
2289
- platform: 'web',
2290
- isReactNative: false,
2291
- isWeb: true,
2292
- isNode: false,
2293
- isExpo: false,
2294
- };
2295
- }
2296
- // Check for Node.js
2297
- if (typeof process !== 'undefined' && process.versions && process.versions.node) {
2298
- return {
2299
- platform: 'node',
2300
- isReactNative: false,
2301
- isWeb: false,
2302
- isNode: true,
2303
- isExpo: false,
2304
- };
2305
- }
2306
- // Unknown platform
2307
- return {
2308
- platform: 'unknown',
2309
- isReactNative: false,
2310
- isWeb: false,
2311
- isNode: false,
2312
- isExpo: false,
2313
- };
2314
- }
2315
- /**
2316
- * Check if running in Expo
2317
- */
2318
- function checkExpo() {
2319
- try {
2320
- return (typeof global !== 'undefined' &&
2321
- (typeof global.Expo !== 'undefined' || typeof global.expo !== 'undefined'));
2472
+ // Enum options arrays
2473
+ const VAT_RATE_CODE_OPTIONS = [
2474
+ '4.00',
2475
+ '5.00',
2476
+ '10.00',
2477
+ '22.00',
2478
+ '2.00',
2479
+ '6.40',
2480
+ '7.00',
2481
+ '7.30',
2482
+ '7.50',
2483
+ '7.65',
2484
+ '7.95',
2485
+ '8.30',
2486
+ '8.50',
2487
+ '8.80',
2488
+ '9.50',
2489
+ '12.30',
2490
+ 'N1',
2491
+ 'N2',
2492
+ 'N3',
2493
+ 'N4',
2494
+ 'N5',
2495
+ 'N6',
2496
+ ];
2497
+ const GOOD_OR_SERVICE_OPTIONS = ['goods', 'service'];
2498
+ const RECEIPT_PROOF_TYPE_OPTIONS = ['POS', 'VR', 'ND'];
2499
+ // Enum types for receipt validation
2500
+ const VatRateCodeSchema = z__namespace.enum(VAT_RATE_CODE_OPTIONS);
2501
+ const GoodOrServiceSchema = z__namespace.enum(GOOD_OR_SERVICE_OPTIONS);
2502
+ const ReceiptProofTypeSchema = z__namespace.enum(RECEIPT_PROOF_TYPE_OPTIONS);
2503
+ // Receipt Item Schema
2504
+ const ReceiptItemSchema = z__namespace.object({
2505
+ type: GoodOrServiceSchema.optional(),
2506
+ quantity: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
2507
+ description: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
2508
+ unit_price: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
2509
+ vat_rate_code: VatRateCodeSchema.optional(),
2510
+ simplified_vat_allocation: z__namespace.boolean().optional(),
2511
+ discount: z__namespace.string().nullable().optional(),
2512
+ is_down_payment_or_voucher_redemption: z__namespace.boolean().optional(),
2513
+ complimentary: z__namespace.boolean().optional(),
2514
+ });
2515
+ // Main Receipt Input Schema
2516
+ const ReceiptInputSchema = z__namespace
2517
+ .object({
2518
+ items: z__namespace.array(ReceiptItemSchema).min(1, { error: 'arrayMin1' }),
2519
+ customer_tax_code: z__namespace.string().optional(),
2520
+ customer_lottery_code: z__namespace.string().optional(),
2521
+ discount: z__namespace.string().nullable().optional(),
2522
+ invoice_issuing: z__namespace.boolean().optional(),
2523
+ uncollected_dcr_to_ssn: z__namespace.boolean().optional(),
2524
+ services_uncollected_amount: z__namespace.string().nullable().optional(),
2525
+ goods_uncollected_amount: z__namespace.string().nullable().optional(),
2526
+ cash_payment_amount: z__namespace.string().nullable().optional(),
2527
+ electronic_payment_amount: z__namespace.string().nullable().optional(),
2528
+ ticket_restaurant_payment_amount: z__namespace.string().nullable().optional(),
2529
+ ticket_restaurant_quantity: z__namespace.number().optional(),
2530
+ })
2531
+ .refine((data) => {
2532
+ // At least one payment method should be provided
2533
+ const hasCashPayment = data.cash_payment_amount && parseFloat(data.cash_payment_amount) > 0;
2534
+ const hasElectronicPayment = data.electronic_payment_amount && parseFloat(data.electronic_payment_amount) > 0;
2535
+ const hasTicketPayment = data.ticket_restaurant_payment_amount &&
2536
+ parseFloat(data.ticket_restaurant_payment_amount) > 0;
2537
+ return hasCashPayment || hasElectronicPayment || hasTicketPayment;
2538
+ }, {
2539
+ error: 'At least one payment method is required',
2540
+ path: ['payment_methods'],
2541
+ })
2542
+ .refine((data) => {
2543
+ // only one between customer_tax_code and customer_lottery_code can be provided
2544
+ return !data.customer_tax_code || !data.customer_lottery_code;
2545
+ }, {
2546
+ error: 'Only one between customer_tax_code and customer_lottery_code can be provided',
2547
+ path: ['customer_tax_code', 'customer_lottery_code'],
2548
+ });
2549
+ // Receipt Return or Void via PEM Schema
2550
+ const ReceiptReturnOrVoidViaPEMInputSchema = z__namespace.object({
2551
+ device_id: z__namespace.string().optional(),
2552
+ items: z__namespace.array(ReceiptItemSchema).min(1, { error: 'arrayMin1' }),
2553
+ document_number: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
2554
+ document_datetime: z__namespace.string().optional(),
2555
+ lottery_code: z__namespace.string().optional(),
2556
+ });
2557
+ // Receipt Return or Void with Proof Schema
2558
+ const ReceiptReturnOrVoidWithProofInputSchema = z__namespace.object({
2559
+ items: z__namespace.array(ReceiptItemSchema).min(1, { error: 'arrayMin1' }),
2560
+ proof: ReceiptProofTypeSchema,
2561
+ document_datetime: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
2562
+ });
2563
+ // Void Receipt Schema
2564
+ const VoidReceiptInputSchema = z__namespace.object({
2565
+ document_number: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
2566
+ });
2567
+ const ReceiptReturnItemSchema = z__namespace
2568
+ .array(z__namespace.object({
2569
+ id: z__namespace.number(),
2570
+ quantity: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
2571
+ }))
2572
+ .min(1, { error: 'arrayMin1' });
2573
+ // Receipt Return Schema
2574
+ const ReceiptReturnInputSchema = z__namespace.object({
2575
+ items: z__namespace.array(ReceiptReturnItemSchema).min(1, { error: 'arrayMin1' }),
2576
+ document_number: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
2577
+ });
2578
+
2579
+ // Cashier Create Input Schema (MF1)
2580
+ const CashierCreateInputSchema = z__namespace.object({
2581
+ email: z__namespace
2582
+ .string()
2583
+ .min(1, { error: 'fieldIsRequired' })
2584
+ .max(255, { error: 'emailMaxLength' })
2585
+ .email({ error: 'invalidEmail' }),
2586
+ password: z__namespace
2587
+ .string()
2588
+ .min(8, { error: 'passwordMinLength' })
2589
+ .max(40, { error: 'passwordMaxLength' }),
2590
+ name: z__namespace.string().min(1, { error: 'fieldIsRequired' }).max(255, { error: 'nameMaxLength' }),
2591
+ display_name: z__namespace
2592
+ .string()
2593
+ .min(1, { error: 'fieldIsRequired' })
2594
+ .max(255, { error: 'displayNameMaxLength' }),
2595
+ });
2596
+
2597
+ // Enum options arrays
2598
+ const PEM_STATUS_OPTIONS = [
2599
+ 'NEW',
2600
+ 'REGISTERED',
2601
+ 'ACTIVATED',
2602
+ 'ONLINE',
2603
+ 'OFFLINE',
2604
+ 'DISCARDED',
2605
+ ];
2606
+ // Address Schema (reusable)
2607
+ const AddressSchema = z__namespace.object({
2608
+ street_address: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
2609
+ street_number: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
2610
+ zip_code: z__namespace
2611
+ .string()
2612
+ .min(1, { error: 'fieldIsRequired' })
2613
+ .regex(/^\d{5}$/, { error: 'invalidZipCode' }),
2614
+ city: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
2615
+ province: z__namespace
2616
+ .string()
2617
+ .min(2, { error: 'provinceMinLength' })
2618
+ .max(2, { error: 'provinceMaxLength' })
2619
+ .toUpperCase(),
2620
+ });
2621
+ // PEM Status Schema
2622
+ const PEMStatusSchema = z__namespace.enum(PEM_STATUS_OPTIONS);
2623
+ // Activation Request Schema
2624
+ const ActivationRequestSchema = z__namespace.object({
2625
+ registration_key: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
2626
+ });
2627
+ // PEM Status Offline Request Schema
2628
+ const PEMStatusOfflineRequestSchema = z__namespace.object({
2629
+ timestamp: z__namespace
2630
+ .string()
2631
+ .min(1, { error: 'fieldIsRequired' })
2632
+ .refine((val) => !isNaN(Date.parse(val)), {
2633
+ error: 'invalidDateFormat',
2634
+ }),
2635
+ reason: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
2636
+ });
2637
+
2638
+ // Cash Register Create Schema
2639
+ const CashRegisterCreateSchema = z__namespace.object({
2640
+ pem_serial_number: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
2641
+ name: z__namespace.string().min(1, { error: 'fieldIsRequired' }).max(100, { error: 'nameMaxLength' }),
2642
+ });
2643
+
2644
+ // VAT number validation regex (Partita IVA - 11 digits)
2645
+ const VAT_NUMBER_REGEX = /^\d{11}$/;
2646
+ // Fiscal code validation regex (Codice Fiscale - 11 digits only for merchants)
2647
+ const FISCAL_CODE_REGEX = /^\d{11}$/;
2648
+ // Password validation regex (from OpenAPI spec)
2649
+ const PASSWORD_REGEX = /^((?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{10,}).*)$/;
2650
+ // Merchant Create Input Schema
2651
+ const MerchantCreateInputSchema = z__namespace
2652
+ .object({
2653
+ vat_number: z__namespace
2654
+ .string()
2655
+ .min(1, { error: 'fieldIsRequired' })
2656
+ .regex(VAT_NUMBER_REGEX, { error: 'invalidVatNumber' }),
2657
+ fiscal_code: z__namespace.string().regex(FISCAL_CODE_REGEX, { error: 'invalidFiscalCode' }).optional(),
2658
+ business_name: z__namespace.string().max(200, { error: 'businessNameMaxLength' }).optional().nullable(),
2659
+ first_name: z__namespace.string().max(100, { error: 'firstNameMaxLength' }).optional().nullable(),
2660
+ last_name: z__namespace.string().max(100, { error: 'lastNameMaxLength' }).optional().nullable(),
2661
+ email: z__namespace.string().min(1, { error: 'fieldIsRequired' }).email({ error: 'invalidEmail' }),
2662
+ password: z__namespace
2663
+ .string()
2664
+ .min(1, { error: 'fieldIsRequired' })
2665
+ .regex(PASSWORD_REGEX, { error: 'passwordComplexity' }),
2666
+ address: AddressSchema.optional(),
2667
+ })
2668
+ .refine((data) => {
2669
+ const hasBusinessName = data.business_name && data.business_name.trim() !== '';
2670
+ const hasPersonalNames = (data.first_name && data.first_name.trim() !== '') ||
2671
+ (data.last_name && data.last_name.trim() !== '');
2672
+ // If business name is set, first/last name must not be provided
2673
+ if (hasBusinessName && hasPersonalNames) {
2674
+ return false;
2322
2675
  }
2323
- catch {
2676
+ // At least one naming method must be provided
2677
+ if (!hasBusinessName && !hasPersonalNames) {
2324
2678
  return false;
2325
2679
  }
2326
- }
2680
+ return true;
2681
+ }, {
2682
+ error: 'businessNameOrPersonalNamesRequired',
2683
+ path: ['business_name'],
2684
+ });
2685
+ // Merchant Update Input Schema
2686
+ const MerchantUpdateInputSchema = z__namespace.object({
2687
+ business_name: z__namespace.string().max(200, { error: 'businessNameMaxLength' }).optional().nullable(),
2688
+ first_name: z__namespace.string().max(100, { error: 'firstNameMaxLength' }).optional().nullable(),
2689
+ last_name: z__namespace.string().max(100, { error: 'lastNameMaxLength' }).optional().nullable(),
2690
+ address: AddressSchema.optional().nullable(),
2691
+ });
2327
2692
 
2328
- function getDefaultExportFromCjs (x) {
2329
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
2330
- }
2693
+ // Enum options arrays
2694
+ const PEM_TYPE_OPTIONS = ['AP', 'SP', 'TM', 'PV'];
2695
+ // PEM Data Schema
2696
+ const PemDataSchema = z__namespace.object({
2697
+ version: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
2698
+ type: z__namespace.enum(PEM_TYPE_OPTIONS, {
2699
+ error: 'invalidPemType',
2700
+ }),
2701
+ });
2702
+ // PEM Create Input Schema
2703
+ const PemCreateInputSchema = z__namespace.object({
2704
+ merchant_uuid: z__namespace.string().min(1, { error: 'fieldIsRequired' }).uuid({ error: 'invalidUuid' }),
2705
+ address: AddressSchema.optional(),
2706
+ /* external_pem_data: PemDataSchema.optional(), */
2707
+ });
2331
2708
 
2332
- var picocolors_browser = {exports: {}};
2709
+ // Italian Fiscal ID validation regex (Codice Fiscale for individuals or Partita IVA for companies)
2710
+ const FISCAL_ID_REGEX = /^([A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]|[0-9]{11})$/;
2711
+ // Supplier Create Input Schema
2712
+ const SupplierCreateInputSchema = z__namespace.object({
2713
+ fiscal_id: z__namespace
2714
+ .string()
2715
+ .min(1, { error: 'fieldIsRequired' })
2716
+ .regex(FISCAL_ID_REGEX, { error: 'invalidFiscalId' })
2717
+ .toUpperCase(),
2718
+ name: z__namespace.string().min(1, { error: 'fieldIsRequired' }).max(200, { error: 'nameMaxLength' }),
2719
+ address: AddressSchema.optional(),
2720
+ });
2721
+ // Supplier Update Input Schema
2722
+ const SupplierUpdateInputSchema = z__namespace.object({
2723
+ name: z__namespace.string().min(1, { error: 'fieldIsRequired' }).max(200, { error: 'nameMaxLength' }),
2724
+ address: AddressSchema.optional(),
2725
+ });
2333
2726
 
2334
- var x=String;
2335
- 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}};
2336
- picocolors_browser.exports=create();
2337
- picocolors_browser.exports.createColors = create;
2727
+ // Journal Close Input Schema
2728
+ const JournalCloseInputSchema = z__namespace.object({
2729
+ closing_timestamp: z__namespace
2730
+ .string()
2731
+ .min(1, { error: 'fieldIsRequired' })
2732
+ .refine((val) => !isNaN(Date.parse(val)), {
2733
+ error: 'invalidDateFormat',
2734
+ }),
2735
+ reason: z__namespace.string().max(255, { error: 'reasonMaxLength' }).optional(),
2736
+ });
2338
2737
 
2339
- var picocolors_browserExports = picocolors_browser.exports;
2340
- var pc = /*@__PURE__*/getDefaultExportFromCjs(picocolors_browserExports);
2738
+ // Daily Report Status Options
2739
+ const DAILY_REPORT_STATUS_OPTIONS = ['pending', 'sent', 'error'];
2740
+ // Daily Report Status Schema
2741
+ const DailyReportStatusSchema = z__namespace.enum(DAILY_REPORT_STATUS_OPTIONS, {
2742
+ error: 'invalidDailyReportStatus',
2743
+ });
2744
+ // Daily Reports List Parameters Schema
2745
+ const DailyReportsParamsSchema = z__namespace.object({
2746
+ pem_serial_number: z__namespace.string().min(1, { error: 'fieldIsRequired' }).optional(),
2747
+ date_from: z__namespace
2748
+ .string()
2749
+ .refine((val) => !isNaN(Date.parse(val)), {
2750
+ error: 'invalidDateFormat',
2751
+ })
2752
+ .optional(),
2753
+ date_to: z__namespace
2754
+ .string()
2755
+ .refine((val) => !isNaN(Date.parse(val)), {
2756
+ error: 'invalidDateFormat',
2757
+ })
2758
+ .optional(),
2759
+ status: DailyReportStatusSchema.optional(),
2760
+ page: z__namespace.number().min(1, { error: 'pageMinValue' }).optional(),
2761
+ });
2762
+
2763
+ const NotificationScopeSchema = z__namespace.object({
2764
+ type: z__namespace.literal('global'),
2765
+ });
2766
+ const PemStatusSchema = z__namespace.enum(['ONLINE', 'OFFLINE']);
2767
+ const NotificationDataBlockAtSchema = z__namespace.object({
2768
+ block_at: z__namespace.string(),
2769
+ });
2770
+ const NotificationDataPemStatusSchema = z__namespace.object({
2771
+ from: PemStatusSchema,
2772
+ to: PemStatusSchema,
2773
+ });
2774
+ const NotificationBaseSchema = z__namespace.object({
2775
+ uuid: z__namespace.string().uuid({ error: 'invalidUuid' }),
2776
+ scope: NotificationScopeSchema,
2777
+ source: z__namespace.enum(['system', 'Italian Tax Authority']),
2778
+ level: z__namespace.enum(['info', 'warning', 'error', 'critical']),
2779
+ created_at: z__namespace.string(),
2780
+ });
2781
+ const NotificationMf2UnreachableSchema = NotificationBaseSchema.extend({
2782
+ type: z__namespace.literal('INTERNAL_COMMUNICATION_FAILURE'),
2783
+ code: z__namespace.literal('SYS-W-01'),
2784
+ data: NotificationDataBlockAtSchema,
2785
+ });
2786
+ const NotificationPemsBlockedSchema = NotificationBaseSchema.extend({
2787
+ type: z__namespace.literal('PEM_STATUS_CHANGED'),
2788
+ code: z__namespace.literal('SYS-C-01'),
2789
+ data: NotificationDataPemStatusSchema,
2790
+ });
2791
+ const NotificationPemBackOnlineSchema = NotificationBaseSchema.extend({
2792
+ type: z__namespace.literal('PEM_STATUS_CHANGED'),
2793
+ code: z__namespace.literal('SYS-I-01'),
2794
+ data: NotificationDataPemStatusSchema,
2795
+ });
2796
+ const NotificationSchema = z__namespace.discriminatedUnion('code', [
2797
+ NotificationMf2UnreachableSchema,
2798
+ NotificationPemsBlockedSchema,
2799
+ NotificationPemBackOnlineSchema,
2800
+ ]);
2801
+ const NotificationListResponseSchema = z__namespace.object({
2802
+ members: z__namespace.array(NotificationSchema),
2803
+ });
2804
+
2805
+ const TelemetryMerchantSchema = z__namespace.object({
2806
+ vat_number: z__namespace.string(),
2807
+ fiscal_code: z__namespace.string().nullable(),
2808
+ business_name: z__namespace.string(),
2809
+ });
2810
+ const TelemetrySupplierSchema = z__namespace.object({
2811
+ vat_number: z__namespace.string(),
2812
+ fiscal_code: z__namespace.string().nullable(),
2813
+ business_name: z__namespace.string(),
2814
+ });
2815
+ const TelemetrySoftwareVersionSchema = z__namespace.object({
2816
+ version: z__namespace.string(),
2817
+ swid: z__namespace.string(),
2818
+ installed_at: z__namespace.string(),
2819
+ status: z__namespace.enum(['active', 'inactive', 'archived']),
2820
+ });
2821
+ const TelemetrySoftwareSchema = z__namespace.object({
2822
+ code: z__namespace.string(),
2823
+ name: z__namespace.string(),
2824
+ approval_reference: z__namespace.string(),
2825
+ version_info: TelemetrySoftwareVersionSchema,
2826
+ });
2827
+ const PendingReceiptsSchema = z__namespace.object({
2828
+ count: z__namespace.number().int().nonnegative(),
2829
+ total_amount: z__namespace.string(),
2830
+ });
2831
+ const TransmissionSchema = z__namespace.object({
2832
+ attempted_at: z__namespace.string(),
2833
+ outcome: z__namespace.enum(['success', 'failed', 'pending']),
2834
+ });
2835
+ const MessageSchema = z__namespace.object({
2836
+ received_at: z__namespace.string(),
2837
+ content: z__namespace.string(),
2838
+ });
2839
+ const LotterySecretRequestSchema = z__namespace.object({
2840
+ requested_at: z__namespace.string(),
2841
+ outcome: z__namespace.enum(['success', 'failed', 'pending']),
2842
+ });
2843
+ const LotterySchema = z__namespace.object({
2844
+ last_transmission: TransmissionSchema,
2845
+ secret_request: LotterySecretRequestSchema,
2846
+ });
2847
+ const TelemetrySchema = z__namespace.object({
2848
+ pem_id: z__namespace.string(),
2849
+ pem_status: z__namespace.enum(['ONLINE', 'OFFLINE', 'ERROR']),
2850
+ pem_status_changed_at: z__namespace.string(),
2851
+ merchant: TelemetryMerchantSchema,
2852
+ supplier: TelemetrySupplierSchema,
2853
+ software: TelemetrySoftwareSchema,
2854
+ last_communication_at: z__namespace.string(),
2855
+ pending_receipts: PendingReceiptsSchema,
2856
+ last_receipt_transmission: TransmissionSchema,
2857
+ last_message_from_mf2: MessageSchema,
2858
+ ade_corrispettivi_transmission: TransmissionSchema,
2859
+ last_message_from_ade: MessageSchema,
2860
+ lottery: LotterySchema,
2861
+ });
2341
2862
 
2342
- const levelColors = {
2343
- debug: {
2344
- prefix: pc.gray,
2345
- message: pc.gray,
2346
- data: pc.dim,
2347
- },
2348
- info: {
2349
- prefix: pc.cyan,
2350
- message: pc.white,
2351
- data: pc.dim,
2352
- },
2353
- warn: {
2354
- prefix: pc.yellow,
2355
- message: pc.yellow,
2356
- data: pc.dim,
2357
- },
2358
- error: {
2359
- prefix: pc.red,
2360
- message: pc.red,
2361
- data: pc.dim,
2362
- },
2363
- };
2364
- const levelIcons = {
2365
- debug: '🔍',
2366
- info: 'ℹ️ ',
2367
- warn: '⚠️ ',
2368
- error: '',
2863
+ // Receipt schemas and types
2864
+ // Common validation utilities
2865
+ const ValidationMessages = {
2866
+ fieldIsRequired: 'This field is required',
2867
+ arrayMin1: 'At least one item is required',
2868
+ paymentMethodRequired: 'At least one payment method is required',
2869
+ invalidEmail: 'Please enter a valid email address',
2870
+ passwordMinLength: 'Password must be at least 8 characters long',
2871
+ passwordComplexity: 'Password must contain at least one uppercase letter, one lowercase letter, one number, and one special character',
2872
+ invalidZipCode: 'Please enter a valid 5-digit zip code',
2873
+ provinceMinLength: 'Province code must be 2 characters',
2874
+ provinceMaxLength: 'Province code must be 2 characters',
2875
+ invalidDateFormat: 'Please enter a valid date',
2876
+ nameMaxLength: 'Name is too long',
2877
+ invalidFiscalId: 'Please enter a valid Italian fiscal ID (Codice Fiscale or Partita IVA)',
2878
+ invalidVatNumber: 'Please enter a valid VAT number (11 digits)',
2879
+ invalidFiscalCode: 'Please enter a valid fiscal code (11 digits)',
2880
+ businessNameMaxLength: 'Business name is too long (max 200 characters)',
2881
+ businessNameOrPersonalNamesRequired: 'Please provide either a business name or first/last name, but not both',
2882
+ firstNameMaxLength: 'First name is too long (max 100 characters)',
2883
+ lastNameMaxLength: 'Last name is too long (max 100 characters)',
2884
+ invalidUuid: 'Please enter a valid UUID',
2885
+ invalidPemType: 'PEM type must be one of: AP, SP, TM, PV',
2886
+ reasonMaxLength: 'Reason is too long (max 255 characters)',
2887
+ pageMinValue: 'Page number must be at least 1',
2888
+ invalidDailyReportStatus: 'Daily report status must be one of: pending, sent, error',
2889
+ displayNameMaxLength: 'Display name is too long (max 255 characters)',
2369
2890
  };
2370
- /**
2371
- * Format data for pretty display in logs
2372
- */
2373
- function formatData(data, level) {
2374
- if (data === undefined || data === null) {
2375
- return String(data);
2376
- }
2377
- // For primitive types, just return as string
2378
- if (typeof data !== 'object') {
2379
- return String(data);
2891
+ // Validation helper functions
2892
+ const validateInput = (schema, data) => {
2893
+ const result = schema.safeParse(data);
2894
+ if (!result.success) {
2895
+ const errors = result.error.issues.map((error) => ({
2896
+ field: error.path.join('.'),
2897
+ message: error.message,
2898
+ code: error.code,
2899
+ }));
2900
+ return {
2901
+ success: false,
2902
+ errors,
2903
+ data: null,
2904
+ };
2380
2905
  }
2381
- // For Error objects, format nicely
2382
- if (data instanceof Error) {
2383
- return `${data.name}: ${data.message}${data.stack ? `\n${pc.dim(data.stack)}` : ''}`;
2906
+ return {
2907
+ success: true,
2908
+ errors: [],
2909
+ data: result.data,
2910
+ };
2911
+ };
2912
+
2913
+ class ACubeSDKError extends Error {
2914
+ constructor(type, message, originalError, statusCode, violations) {
2915
+ super(message);
2916
+ this.type = type;
2917
+ this.originalError = originalError;
2918
+ this.statusCode = statusCode;
2919
+ this.name = 'ACubeSDKError';
2920
+ this.violations = violations;
2384
2921
  }
2385
- try {
2386
- // Apply level-specific coloring
2387
- const colors = levelColors[level];
2388
- return colors.data(JSON.stringify(data, null, 2));
2922
+ }
2923
+
2924
+ const log$g = createPrefixedLogger('AUTH-STRATEGY');
2925
+ class AuthStrategy {
2926
+ constructor(jwtHandler, mtlsHandler, userProvider, mtlsAdapter) {
2927
+ this.jwtHandler = jwtHandler;
2928
+ this.mtlsHandler = mtlsHandler;
2929
+ this.userProvider = userProvider;
2930
+ this.mtlsAdapter = mtlsAdapter;
2389
2931
  }
2390
- catch {
2391
- // Fallback to JSON.stringify if pretty-format fails
2392
- try {
2393
- return JSON.stringify(data, null, 2);
2932
+ async determineAuthConfig(url, method, explicitMode) {
2933
+ if (this.isNotificationEndpoint(url) || this.isTelemetryEndpoint(url)) {
2934
+ return { mode: 'mtls', usePort444: true };
2394
2935
  }
2395
- catch {
2396
- return String(data);
2936
+ const platform = this.detectPlatform();
2937
+ const userRole = await this.getUserRole();
2938
+ const isReceiptEndpoint = this.isReceiptEndpoint(url);
2939
+ log$g.debug('Determining auth config', {
2940
+ url,
2941
+ method,
2942
+ platform,
2943
+ userRole,
2944
+ isReceiptEndpoint,
2945
+ explicitMode,
2946
+ });
2947
+ if (userRole === 'SUPPLIER') {
2948
+ return { mode: 'jwt', usePort444: false };
2397
2949
  }
2950
+ if (userRole === 'CASHIER') {
2951
+ if (!isReceiptEndpoint) {
2952
+ return { mode: 'jwt', usePort444: false };
2953
+ }
2954
+ if (platform === 'mobile') {
2955
+ return { mode: 'mtls', usePort444: true };
2956
+ }
2957
+ return { mode: 'jwt', usePort444: true };
2958
+ }
2959
+ if (userRole === 'MERCHANT') {
2960
+ if (!isReceiptEndpoint) {
2961
+ return { mode: 'jwt', usePort444: false };
2962
+ }
2963
+ if (this.isReturnableItemsEndpoint(url)) {
2964
+ return { mode: 'mtls', usePort444: true };
2965
+ }
2966
+ if (method === 'GET') {
2967
+ if (this.isDetailedReceiptEndpoint(url)) {
2968
+ if (platform === 'mobile') {
2969
+ return { mode: 'mtls', usePort444: true };
2970
+ }
2971
+ return { mode: 'jwt', usePort444: true };
2972
+ }
2973
+ return { mode: 'jwt', usePort444: false };
2974
+ }
2975
+ if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) {
2976
+ if (platform === 'mobile') {
2977
+ return { mode: 'mtls', usePort444: true };
2978
+ }
2979
+ return { mode: 'jwt', usePort444: true };
2980
+ }
2981
+ return { mode: 'jwt', usePort444: false };
2982
+ }
2983
+ if (explicitMode) {
2984
+ if (userRole === 'SUPPLIER' && explicitMode === 'mtls') {
2985
+ return { mode: 'jwt', usePort444: false };
2986
+ }
2987
+ return {
2988
+ mode: explicitMode,
2989
+ usePort444: explicitMode === 'mtls' || (platform === 'web' && isReceiptEndpoint),
2990
+ };
2991
+ }
2992
+ if (platform === 'web') {
2993
+ return { mode: 'jwt', usePort444: isReceiptEndpoint };
2994
+ }
2995
+ if (isReceiptEndpoint && platform === 'mobile') {
2996
+ return { mode: 'mtls', usePort444: true };
2997
+ }
2998
+ return { mode: 'jwt', usePort444: false };
2398
2999
  }
2399
- }
2400
- class Logger {
2401
- constructor() {
2402
- this.enabled = false;
2403
- }
2404
- setEnabled(enabled) {
2405
- this.enabled = enabled;
2406
- }
2407
- isEnabled() {
2408
- return this.enabled;
2409
- }
2410
- debug(prefix, message, data) {
2411
- if (!this.enabled)
2412
- return;
2413
- this.log('debug', prefix, message, data);
3000
+ async getAuthHeaders() {
3001
+ return this.jwtHandler.getAuthHeaders();
2414
3002
  }
2415
- info(prefix, message, data) {
2416
- if (!this.enabled)
2417
- return;
2418
- this.log('info', prefix, message, data);
3003
+ getMtlsHandler() {
3004
+ return this.mtlsHandler;
2419
3005
  }
2420
- warn(prefix, message, data) {
2421
- this.log('warn', prefix, message, data);
3006
+ getJwtHandler() {
3007
+ return this.jwtHandler;
2422
3008
  }
2423
- error(prefix, message, data) {
2424
- this.log('error', prefix, message, data);
3009
+ detectPlatform() {
3010
+ if (!this.mtlsAdapter) {
3011
+ return 'web';
3012
+ }
3013
+ const platformInfo = this.mtlsAdapter.getPlatformInfo();
3014
+ return platformInfo.platform === 'web' ? 'web' : 'mobile';
2425
3015
  }
2426
- log(level, prefix, message, data) {
2427
- const colors = levelColors[level];
2428
- const icon = levelIcons[level];
2429
- const isoTime = new Date().toISOString().split('T')[1] ?? '';
2430
- const timestamp = pc.dim(isoTime.slice(0, 12));
2431
- const formattedPrefix = colors.prefix(`[${prefix}]`);
2432
- const formattedMessage = colors.message(message);
2433
- const consoleMethod = level === 'debug'
2434
- ? console.debug
2435
- : level === 'info'
2436
- ? console.info
2437
- : level === 'warn'
2438
- ? console.warn
2439
- : console.error;
2440
- const header = `${timestamp} ${icon} ${formattedPrefix} ${formattedMessage}`;
2441
- if (data !== undefined) {
2442
- const formattedData = formatData(data, level);
2443
- // Check if data is an object (multi-line) or primitive (single-line)
2444
- const isMultiLine = typeof data === 'object' && data !== null;
2445
- if (isMultiLine) {
2446
- consoleMethod(`${header}\n${formattedData}`);
2447
- }
2448
- else {
2449
- consoleMethod(`${header}`, formattedData);
2450
- }
3016
+ async getUserRole() {
3017
+ if (!this.userProvider) {
3018
+ return null;
2451
3019
  }
2452
- else {
2453
- consoleMethod(header);
3020
+ const user = await this.userProvider.getCurrentUser();
3021
+ if (!user || !user.roles) {
3022
+ return null;
3023
+ }
3024
+ if (hasRole(user.roles, 'ROLE_SUPPLIER')) {
3025
+ return 'SUPPLIER';
3026
+ }
3027
+ if (hasRole(user.roles, 'ROLE_MERCHANT')) {
3028
+ return 'MERCHANT';
3029
+ }
3030
+ if (hasRole(user.roles, 'ROLE_CASHIER')) {
3031
+ return 'CASHIER';
2454
3032
  }
3033
+ return null;
3034
+ }
3035
+ isReceiptEndpoint(url) {
3036
+ return url.includes('/receipts') || url.includes('/mf1/receipts');
3037
+ }
3038
+ isReturnableItemsEndpoint(url) {
3039
+ return !!(url.match(/\/receipts\/[a-f0-9-]+\/returnable-items$/) ||
3040
+ url.match(/\/mf1\/receipts\/[a-f0-9-]+\/returnable-items$/));
3041
+ }
3042
+ isDetailedReceiptEndpoint(url) {
3043
+ return !!(url.match(/\/receipts\/[a-f0-9-]+\/details$/) ||
3044
+ url.match(/\/mf1\/receipts\/[a-f0-9-]+\/details$/));
3045
+ }
3046
+ isNotificationEndpoint(url) {
3047
+ return url.includes('/mf1/notifications');
3048
+ }
3049
+ isTelemetryEndpoint(url) {
3050
+ return !!url.match(/\/mf1\/pems\/[^/]+\/telemetry/);
2455
3051
  }
2456
- }
2457
- const logger = new Logger();
2458
- function createPrefixedLogger(prefix) {
2459
- return {
2460
- debug: (message, data) => logger.debug(prefix, message, data),
2461
- info: (message, data) => logger.info(prefix, message, data),
2462
- warn: (message, data) => logger.warn(prefix, message, data),
2463
- error: (message, data) => logger.error(prefix, message, data),
2464
- };
2465
3052
  }
2466
3053
 
2467
- /**
2468
- * Formats a numeric string value to have exactly the specified number of decimal places.
2469
- * E.g., "1" → "1.00", "10" → "10.00", "1.5" → "1.50"
2470
- * Returns undefined for undefined input (preserves optional fields).
2471
- *
2472
- * @param value - The string value to format
2473
- * @param decimals - Number of decimal places (default: 2)
2474
- * @returns Formatted string or undefined if input is undefined
2475
- */
2476
- function formatDecimal(value, decimals = 2) {
2477
- if (value === undefined)
2478
- return undefined;
2479
- const num = parseFloat(value);
2480
- if (isNaN(num))
2481
- return value;
2482
- return num.toFixed(decimals);
3054
+ class JwtAuthHandler {
3055
+ constructor(tokenStorage) {
3056
+ this.tokenStorage = tokenStorage;
3057
+ }
3058
+ async getAuthConfig(_url, _method) {
3059
+ return { mode: 'jwt', usePort444: false };
3060
+ }
3061
+ async getAuthHeaders() {
3062
+ const token = await this.tokenStorage.getAccessToken();
3063
+ if (!token) {
3064
+ return {};
3065
+ }
3066
+ return { Authorization: `Bearer ${token}` };
3067
+ }
2483
3068
  }
2484
3069
 
2485
3070
  const log$f = createPrefixedLogger('MTLS-HANDLER');
@@ -6012,92 +6597,6 @@ function createACubeMTLSConfig(baseUrl, timeout, autoInitialize = true, forcePor
6012
6597
  };
6013
6598
  }
6014
6599
 
6015
- class ConfigManager {
6016
- constructor(userConfig) {
6017
- this.config = this.buildConfig(userConfig);
6018
- }
6019
- buildConfig(userConfig) {
6020
- return {
6021
- environment: userConfig.environment,
6022
- apiUrl: this.getDefaultApiUrl(userConfig.environment),
6023
- authUrl: this.getDefaultAuthUrl(userConfig.environment),
6024
- timeout: 30000,
6025
- retryAttempts: 3,
6026
- debug: userConfig.debug ?? false,
6027
- customHeaders: {},
6028
- };
6029
- }
6030
- getDefaultApiUrl(environment) {
6031
- switch (environment) {
6032
- case 'production':
6033
- return 'https://ereceipts-it.acubeapi.com';
6034
- case 'development':
6035
- return 'https://ereceipts-it.dev.acubeapi.com';
6036
- case 'sandbox':
6037
- default:
6038
- return 'https://ereceipts-it-sandbox.acubeapi.com';
6039
- }
6040
- }
6041
- getDefaultAuthUrl(environment) {
6042
- switch (environment) {
6043
- case 'production':
6044
- return 'https://common.api.acubeapi.com';
6045
- case 'development':
6046
- case 'sandbox':
6047
- default:
6048
- return 'https://common-sandbox.api.acubeapi.com';
6049
- }
6050
- }
6051
- getConfig() {
6052
- return {
6053
- environment: this.config.environment,
6054
- debug: this.config.debug,
6055
- };
6056
- }
6057
- getApiUrl() {
6058
- return this.config.apiUrl;
6059
- }
6060
- getAuthUrl() {
6061
- return this.config.authUrl;
6062
- }
6063
- getEnvironment() {
6064
- return this.config.environment;
6065
- }
6066
- isDebugEnabled() {
6067
- return this.config.debug;
6068
- }
6069
- getTimeout() {
6070
- return this.config.timeout;
6071
- }
6072
- getRetryAttempts() {
6073
- return this.config.retryAttempts;
6074
- }
6075
- getCustomHeaders() {
6076
- return { ...this.config.customHeaders };
6077
- }
6078
- updateConfig(updates) {
6079
- if (updates.environment) {
6080
- this.config.environment = updates.environment;
6081
- this.config.apiUrl = this.getDefaultApiUrl(updates.environment);
6082
- this.config.authUrl = this.getDefaultAuthUrl(updates.environment);
6083
- }
6084
- if (updates.debug !== undefined) {
6085
- this.config.debug = updates.debug;
6086
- }
6087
- }
6088
- }
6089
-
6090
- class ACubeSDKError extends Error {
6091
- constructor(type, message, originalError, statusCode, violations) {
6092
- super(message);
6093
- this.type = type;
6094
- this.originalError = originalError;
6095
- this.statusCode = statusCode;
6096
- this.name = 'ACubeSDKError';
6097
- this.violations = violations;
6098
- }
6099
- }
6100
-
6101
6600
  const DI_TOKENS = {
6102
6601
  HTTP_PORT: Symbol('HTTP_PORT'),
6103
6602
  BASE_HTTP_PORT: Symbol('BASE_HTTP_PORT'),
@@ -7523,7 +8022,11 @@ class CachingHttpDecorator {
7523
8022
  return response;
7524
8023
  }
7525
8024
  setAuthToken(token) {
7526
- log$3.debug('Auth token updated:', { hasToken: !!token });
8025
+ log$3.debug('CachingHttpDecorator.setAuthToken called:', {
8026
+ hasToken: !!token,
8027
+ tokenPrefix: token?.substring(0, 20),
8028
+ underlyingHttpType: this.http.constructor.name,
8029
+ });
7527
8030
  this.authToken = token;
7528
8031
  this.http.setAuthToken(token);
7529
8032
  }
@@ -7556,7 +8059,8 @@ class CachingHttpDecorator {
7556
8059
  }
7557
8060
  }
7558
8061
 
7559
- const log$2 = createPrefixedLogger('HTTP-MTLS');
8062
+ const logJwt = createPrefixedLogger('HTTP-JWT');
8063
+ const logMtls = createPrefixedLogger('HTTP-MTLS');
7560
8064
  class AxiosHttpAdapter {
7561
8065
  constructor(config) {
7562
8066
  this.authToken = null;
@@ -7574,23 +8078,30 @@ class AxiosHttpAdapter {
7574
8078
  }
7575
8079
  setMTLSAdapter(adapter) {
7576
8080
  this.mtlsAdapter = adapter;
7577
- log$2.debug('mTLS adapter configured:', !!adapter);
8081
+ logMtls.debug('mTLS adapter configured:', !!adapter);
7578
8082
  }
7579
8083
  setAuthStrategy(strategy) {
7580
8084
  this.authStrategy = strategy;
7581
- log$2.debug('Auth strategy configured:', !!strategy);
8085
+ logJwt.debug('Auth strategy configured:', !!strategy);
7582
8086
  }
7583
8087
  async shouldUseMTLS(url, method) {
7584
8088
  if (!this.mtlsAdapter) {
8089
+ logJwt.debug(`No mTLS adapter, using JWT for ${method} ${url}`);
7585
8090
  return false;
7586
8091
  }
7587
8092
  if (this.authStrategy) {
7588
8093
  const config = await this.authStrategy.determineAuthConfig(url, method);
7589
- log$2.debug(`Auth config for ${method} ${url}:`, config);
8094
+ const logger = config.mode === 'mtls' ? logMtls : logJwt;
8095
+ logger.debug(`Auth config for ${method} ${url}:`, config);
7590
8096
  return config.mode === 'mtls';
7591
8097
  }
7592
8098
  // Fallback: use mTLS for mf1/mf2 endpoints if no strategy
7593
- return url.startsWith('/mf1') || url.startsWith('/mf2');
8099
+ // This should rarely happen - only before SDK is fully initialized
8100
+ const useMtls = url.startsWith('/mf1') || url.startsWith('/mf2');
8101
+ if (useMtls) {
8102
+ logMtls.warn(`No auth strategy set, falling back to mTLS for ${method} ${url}`);
8103
+ }
8104
+ return useMtls;
7594
8105
  }
7595
8106
  async makeMTLSRequest(url, method, data, config) {
7596
8107
  if (!this.mtlsAdapter) {
@@ -7603,10 +8114,10 @@ class AxiosHttpAdapter {
7603
8114
  };
7604
8115
  if (this.authToken) {
7605
8116
  headers['Authorization'] = `Bearer ${this.authToken}`;
7606
- log$2.debug('JWT token present for mTLS request');
8117
+ logMtls.debug('JWT token present for mTLS request');
7607
8118
  }
7608
8119
  else {
7609
- log$2.warn('No JWT token for mTLS request');
8120
+ logMtls.warn('No JWT token for mTLS request');
7610
8121
  }
7611
8122
  const mtlsConfig = {
7612
8123
  url: fullUrl,
@@ -7615,15 +8126,15 @@ class AxiosHttpAdapter {
7615
8126
  data,
7616
8127
  timeout: config?.timeout,
7617
8128
  };
7618
- log$2.debug(`mTLS ${method} ${fullUrl}`);
8129
+ logMtls.debug(`mTLS ${method} ${fullUrl}`);
7619
8130
  if (data) {
7620
- log$2.debug('Request body:', data);
8131
+ logMtls.debug('Request body:', data);
7621
8132
  }
7622
8133
  try {
7623
8134
  const response = await this.mtlsAdapter.request(mtlsConfig);
7624
- log$2.debug(`mTLS Response ${response.status} from ${fullUrl}`);
8135
+ logMtls.debug(`mTLS Response ${response.status} from ${fullUrl}`);
7625
8136
  if (response.data) {
7626
- log$2.debug('Response body:', response.data);
8137
+ logMtls.debug('Response body:', response.data);
7627
8138
  }
7628
8139
  return {
7629
8140
  data: response.data,
@@ -7632,11 +8143,11 @@ class AxiosHttpAdapter {
7632
8143
  };
7633
8144
  }
7634
8145
  catch (error) {
7635
- log$2.error(`mTLS Response error from ${fullUrl}:`, error);
8146
+ logMtls.error(`mTLS Response error from ${fullUrl}:`, error);
7636
8147
  if (error && typeof error === 'object' && 'response' in error) {
7637
8148
  const axiosError = error;
7638
8149
  if (axiosError.response?.data) {
7639
- log$2.error('Response body:', axiosError.response.data);
8150
+ logMtls.error('Response body:', axiosError.response.data);
7640
8151
  }
7641
8152
  }
7642
8153
  throw error;
@@ -7651,36 +8162,46 @@ class AxiosHttpAdapter {
7651
8162
  this.client.interceptors.request.use((config) => {
7652
8163
  if (this.authToken) {
7653
8164
  config.headers.Authorization = `Bearer ${this.authToken}`;
7654
- log$2.debug('Adding JWT token to request');
8165
+ logJwt.debug('Adding JWT token to request', {
8166
+ tokenPrefix: this.authToken.substring(0, 30) + '...',
8167
+ tokenLength: this.authToken.length,
8168
+ });
7655
8169
  }
7656
8170
  else {
7657
- log$2.warn('No JWT token available for request:', { url: config.url });
8171
+ logJwt.warn('No JWT token available for request:', { url: config.url });
7658
8172
  }
7659
8173
  const method = config.method?.toUpperCase() ?? 'UNKNOWN';
7660
- log$2.debug(`→ ${method} ${config.url}`);
8174
+ const authHeader = config.headers.Authorization;
8175
+ // Log full request details for debugging
8176
+ logJwt.info(`→ ${method} ${config.url}`, {
8177
+ baseURL: config.baseURL,
8178
+ fullURL: `${config.baseURL}${config.url}`,
8179
+ hasAuthHeader: !!authHeader,
8180
+ authHeaderValue: authHeader ? `${String(authHeader).substring(0, 50)}...` : 'MISSING',
8181
+ });
7661
8182
  if (config.params && Object.keys(config.params).length > 0) {
7662
- log$2.debug('Request params:', config.params);
8183
+ logJwt.debug('Request params:', config.params);
7663
8184
  }
7664
8185
  if (config.data) {
7665
- log$2.debug('Request body:', config.data);
8186
+ logJwt.debug('Request body:', config.data);
7666
8187
  }
7667
8188
  return config;
7668
8189
  }, (error) => {
7669
- log$2.error('Request error:', error);
8190
+ logJwt.error('Request error:', error);
7670
8191
  return Promise.reject(error);
7671
8192
  });
7672
8193
  this.client.interceptors.response.use((response) => {
7673
8194
  const method = response.config.method?.toUpperCase() ?? 'UNKNOWN';
7674
- log$2.debug(`← ${method} ${response.status} ${response.config.url}`);
8195
+ logJwt.debug(`← ${method} ${response.status} ${response.config.url}`);
7675
8196
  if (response.data) {
7676
- log$2.debug('Response body:', response.data);
8197
+ logJwt.debug('Response body:', response.data);
7677
8198
  }
7678
8199
  return response;
7679
8200
  }, (error) => {
7680
8201
  const method = error.config?.method?.toUpperCase() ?? 'UNKNOWN';
7681
- log$2.error(`← ${method} ${error.response?.status ?? 'ERR'} ${error.config?.url ?? 'unknown'}`);
8202
+ logJwt.error(`← ${method} ${error.response?.status ?? 'ERR'} ${error.config?.url ?? 'unknown'}`);
7682
8203
  if (error.response?.data) {
7683
- log$2.error('Response body:', error.response.data);
8204
+ logJwt.error('Response body:', error.response.data);
7684
8205
  }
7685
8206
  return Promise.reject(error);
7686
8207
  });
@@ -7750,7 +8271,10 @@ class AxiosHttpAdapter {
7750
8271
  return this.mapResponse(response);
7751
8272
  }
7752
8273
  setAuthToken(token) {
7753
- log$2.info('setAuthToken called:', { hasToken: !!token, tokenPrefix: token?.substring(0, 20) });
8274
+ logJwt.info('setAuthToken called:', {
8275
+ hasToken: !!token,
8276
+ tokenPrefix: token?.substring(0, 20),
8277
+ });
7754
8278
  this.authToken = token;
7755
8279
  }
7756
8280
  getAuthToken() {
@@ -7906,7 +8430,7 @@ class SDKFactory {
7906
8430
  }
7907
8431
  }
7908
8432
 
7909
- const log$1 = createPrefixedLogger('SDK');
8433
+ const log$2 = createPrefixedLogger('SDK');
7910
8434
  class ACubeSDK {
7911
8435
  constructor(config, customAdapters, events = {}) {
7912
8436
  this.events = events;
@@ -7920,22 +8444,22 @@ class ACubeSDK {
7920
8444
  }
7921
8445
  async initialize() {
7922
8446
  if (this.isInitialized) {
7923
- log$1.debug('SDK already initialized, skipping');
8447
+ log$2.debug('SDK already initialized, skipping');
7924
8448
  return;
7925
8449
  }
7926
- log$1.info('Initializing SDK', {
8450
+ log$2.info('Initializing SDK', {
7927
8451
  apiUrl: this.config.getApiUrl(),
7928
8452
  authUrl: this.config.getAuthUrl(),
7929
8453
  debugEnabled: this.config.isDebugEnabled(),
7930
8454
  });
7931
8455
  try {
7932
8456
  if (!this.adapters) {
7933
- log$1.debug('Loading platform adapters');
8457
+ log$2.debug('Loading platform adapters');
7934
8458
  const mtlsConfig = createACubeMTLSConfig(this.config.getApiUrl(), this.config.getTimeout(), true);
7935
8459
  this.adapters = loadPlatformAdapters({
7936
8460
  mtlsConfig,
7937
8461
  });
7938
- log$1.info('Platform adapters loaded', {
8462
+ log$2.info('Platform adapters loaded', {
7939
8463
  hasCache: !!this.adapters.cache,
7940
8464
  hasNetworkMonitor: !!this.adapters.networkMonitor,
7941
8465
  hasMtls: !!this.adapters.mtls,
@@ -7948,25 +8472,30 @@ class ACubeSDK {
7948
8472
  timeout: this.config.getTimeout(),
7949
8473
  debugEnabled: this.config.isDebugEnabled(),
7950
8474
  };
7951
- log$1.debug('Creating DI container');
8475
+ log$2.debug('Creating DI container');
7952
8476
  this.container = SDKFactory.createContainer(factoryConfig);
7953
- log$1.debug('Registering auth services');
8477
+ log$2.debug('Registering auth services');
7954
8478
  SDKFactory.registerAuthServices(this.container, this.adapters.secureStorage, factoryConfig);
7955
8479
  if (this.adapters.cache) {
7956
- log$1.info('Registering cache services', {
8480
+ log$2.info('Registering cache services', {
7957
8481
  hasNetworkMonitor: !!this.adapters.networkMonitor,
7958
8482
  });
7959
8483
  SDKFactory.registerCacheServices(this.container, this.adapters.cache, this.adapters.networkMonitor);
7960
8484
  }
7961
8485
  else {
7962
- log$1.debug('No cache adapter available, caching disabled');
8486
+ log$2.debug('No cache adapter available, caching disabled');
7963
8487
  }
7964
- log$1.debug('Initializing certificate service');
8488
+ log$2.debug('Initializing certificate service');
7965
8489
  this.certificateService = new CertificateService(this.adapters.secureStorage);
7966
8490
  const tokenStorage = this.container.get(DI_TOKENS.TOKEN_STORAGE_PORT);
7967
8491
  const httpPort = this.container.get(DI_TOKENS.HTTP_PORT);
7968
8492
  const baseHttpPort = this.container.get(DI_TOKENS.BASE_HTTP_PORT);
7969
- log$1.debug('Initializing authentication service');
8493
+ log$2.debug('HTTP ports initialized', {
8494
+ httpPortType: httpPort.constructor.name,
8495
+ baseHttpPortType: baseHttpPort.constructor.name,
8496
+ areSameInstance: httpPort === baseHttpPort,
8497
+ });
8498
+ log$2.debug('Initializing authentication service');
7970
8499
  this.authService = new AuthenticationService(httpPort, tokenStorage, {
7971
8500
  authUrl: this.config.getAuthUrl(),
7972
8501
  timeout: this.config.getTimeout(),
@@ -7976,7 +8505,7 @@ class ACubeSDK {
7976
8505
  this.events.onAuthError?.(new ACubeSDKError('AUTH_ERROR', error.message, error));
7977
8506
  },
7978
8507
  });
7979
- log$1.debug('Initializing offline manager');
8508
+ log$2.debug('Initializing offline manager');
7980
8509
  const queueEvents = {
7981
8510
  onOperationAdded: (operation) => {
7982
8511
  this.events.onOfflineOperationAdded?.(operation.id);
@@ -7998,19 +8527,29 @@ class ACubeSDK {
7998
8527
  this.offlineManager.sync().catch(() => { });
7999
8528
  }
8000
8529
  });
8001
- if (await this.authService.isAuthenticated()) {
8530
+ const isAuth = await this.authService.isAuthenticated();
8531
+ log$2.debug('Checking authentication status during init', { isAuthenticated: isAuth });
8532
+ if (isAuth) {
8002
8533
  const token = await this.authService.getAccessToken();
8534
+ log$2.debug('Token retrieved during init', {
8535
+ hasToken: !!token,
8536
+ tokenPrefix: token?.substring(0, 20),
8537
+ });
8003
8538
  if (token) {
8004
8539
  httpPort.setAuthToken(token);
8540
+ log$2.info('Auth token set on HTTP port during initialization');
8005
8541
  }
8006
8542
  }
8543
+ else {
8544
+ log$2.warn('User not authenticated during SDK init - token will be set after login');
8545
+ }
8007
8546
  if (this.adapters?.mtls && 'setMTLSAdapter' in baseHttpPort) {
8008
- log$1.debug('Connecting mTLS adapter to HTTP port');
8547
+ log$2.debug('Connecting mTLS adapter to HTTP port');
8009
8548
  const httpWithMtls = baseHttpPort;
8010
8549
  httpWithMtls.setMTLSAdapter(this.adapters.mtls);
8011
8550
  }
8012
8551
  if ('setAuthStrategy' in baseHttpPort) {
8013
- log$1.debug('Configuring auth strategy');
8552
+ log$2.debug('Configuring auth strategy');
8014
8553
  const jwtHandler = new JwtAuthHandler(tokenStorage);
8015
8554
  const certificatePort = this.certificateService
8016
8555
  ? {
@@ -8059,19 +8598,19 @@ class ACubeSDK {
8059
8598
  }
8060
8599
  }
8061
8600
  catch (certError) {
8062
- log$1.warn('Certificate auto-configuration failed, will retry on demand', {
8601
+ log$2.warn('Certificate auto-configuration failed, will retry on demand', {
8063
8602
  error: certError instanceof Error ? certError.message : certError,
8064
8603
  });
8065
8604
  }
8066
8605
  }
8067
8606
  this.isInitialized = true;
8068
- log$1.info('SDK initialized successfully', {
8607
+ log$2.info('SDK initialized successfully', {
8069
8608
  hasCache: !!this.adapters.cache,
8070
8609
  hasMtls: !!this.adapters.mtls,
8071
8610
  });
8072
8611
  }
8073
8612
  catch (error) {
8074
- log$1.error('SDK initialization failed', {
8613
+ log$2.error('SDK initialization failed', {
8075
8614
  error: error instanceof Error ? error.message : error,
8076
8615
  });
8077
8616
  throw new ACubeSDKError('SDK_INITIALIZATION_ERROR', `Failed to initialize SDK: ${error instanceof Error ? error.message : 'Unknown error'}`, error);
@@ -8127,19 +8666,19 @@ class ACubeSDK {
8127
8666
  }
8128
8667
  async login(credentials) {
8129
8668
  this.ensureInitialized();
8130
- log$1.info('Login attempt', { email: credentials.email });
8669
+ log$2.info('Login attempt', { email: credentials.email });
8131
8670
  const user = await this.authService.login(credentials);
8132
- log$1.info('Login successful', { roles: user.roles });
8671
+ log$2.info('Login successful', { roles: user.roles });
8133
8672
  const token = await this.authService.getAccessToken();
8134
8673
  if (token) {
8135
8674
  this.httpPort.setAuthToken(token);
8136
- log$1.debug('Auth token set on HTTP port');
8675
+ log$2.debug('Auth token set on HTTP port');
8137
8676
  }
8138
8677
  return user;
8139
8678
  }
8140
8679
  async logout() {
8141
8680
  this.ensureInitialized();
8142
- log$1.info('Logout');
8681
+ log$2.info('Logout');
8143
8682
  await this.authService.logout();
8144
8683
  this.httpPort.setAuthToken(null);
8145
8684
  }
@@ -8313,6 +8852,7 @@ const INITIAL_STATE = {
8313
8852
  remainingMs: 0,
8314
8853
  },
8315
8854
  lastNotification: null,
8855
+ certificateMissing: false,
8316
8856
  };
8317
8857
  class AppStateService {
8318
8858
  get state$() {
@@ -8327,28 +8867,33 @@ class AppStateService {
8327
8867
  get warning$() {
8328
8868
  return this.state$.pipe(map((s) => s.warning), distinctUntilChanged((a, b) => a.active === b.active && a.remainingMs === b.remainingMs));
8329
8869
  }
8330
- constructor(notifications$, networkPort) {
8870
+ get certificateMissing$() {
8871
+ return this.state$.pipe(map((s) => s.certificateMissing), distinctUntilChanged());
8872
+ }
8873
+ constructor(notifications$, networkPort, certificateMissingInput$ = of(false)) {
8331
8874
  this.notifications$ = notifications$;
8332
8875
  this.networkPort = networkPort;
8876
+ this.certificateMissingInput$ = certificateMissingInput$;
8333
8877
  this.stateSubject = new BehaviorSubject(INITIAL_STATE);
8334
8878
  this.destroy$ = new Subject();
8335
8879
  this.warningTimerId = null;
8336
8880
  this.setupSubscriptions();
8337
8881
  }
8338
8882
  setupSubscriptions() {
8339
- combineLatest([this.notifications$, this.networkPort.online$])
8883
+ combineLatest([this.notifications$, this.networkPort.online$, this.certificateMissingInput$])
8340
8884
  .pipe(takeUntil(this.destroy$))
8341
- .subscribe(([notifications, isOnline]) => {
8342
- this.processState(notifications, isOnline);
8885
+ .subscribe(([notifications, isOnline, certificateMissing]) => {
8886
+ this.processState(notifications, isOnline, certificateMissing);
8343
8887
  });
8344
8888
  }
8345
- processState(notifications, isOnline) {
8889
+ processState(notifications, isOnline, certificateMissing) {
8346
8890
  if (!isOnline) {
8347
8891
  this.updateState({
8348
8892
  mode: 'OFFLINE',
8349
8893
  isOnline: false,
8350
8894
  warning: { active: false, blockAt: null, remainingMs: 0 },
8351
8895
  lastNotification: null,
8896
+ certificateMissing,
8352
8897
  });
8353
8898
  this.stopWarningTimer();
8354
8899
  return;
@@ -8410,6 +8955,7 @@ class AppStateService {
8410
8955
  isOnline: true,
8411
8956
  warning: warningState,
8412
8957
  lastNotification,
8958
+ certificateMissing,
8413
8959
  });
8414
8960
  }
8415
8961
  getLatestNotificationByCode(notifications) {
@@ -8675,6 +9221,7 @@ class TelemetryService {
8675
9221
  }
8676
9222
  }
8677
9223
 
9224
+ const log$1 = createPrefixedLogger('SDK-MANAGER');
8678
9225
  /**
8679
9226
  * SDKManager - Singleton wrapper for ACubeSDK with simplified API
8680
9227
  *
@@ -8725,6 +9272,7 @@ class SDKManager {
8725
9272
  this.appStateService = null;
8726
9273
  this.isInitialized = false;
8727
9274
  this.isPollingActive = false;
9275
+ this.certificateMissingSubject = new BehaviorSubject(false);
8728
9276
  /**
8729
9277
  * Handle user state changes (login/logout/token expiration)
8730
9278
  * Manages polling lifecycle based on user role
@@ -8735,9 +9283,14 @@ class SDKManager {
8735
9283
  if (!this.isInitialized)
8736
9284
  return;
8737
9285
  if (user) {
8738
- // User logged in - check role and start polling if allowed
9286
+ // User logged in - check role and certificate before starting polling
8739
9287
  const canPoll = hasAnyRole(user.roles, ['ROLE_MERCHANT', 'ROLE_CASHIER']);
8740
9288
  if (canPoll && !this.isPollingActive) {
9289
+ const hasCert = await this.checkCertificate();
9290
+ if (!hasCert) {
9291
+ log$1.warn('Certificate missing — polling blocked until certificate is installed');
9292
+ return;
9293
+ }
8741
9294
  this.notificationService?.startPolling();
8742
9295
  await this.startTelemetryPollingAuto();
8743
9296
  this.isPollingActive = true;
@@ -8751,6 +9304,7 @@ class SDKManager {
8751
9304
  this.telemetryService?.clearTelemetry();
8752
9305
  this.isPollingActive = false;
8753
9306
  }
9307
+ this.certificateMissingSubject.next(false);
8754
9308
  }
8755
9309
  };
8756
9310
  }
@@ -8817,7 +9371,7 @@ class SDKManager {
8817
9371
  this.telemetryService = new TelemetryService(telemetryRepo, networkPort, {
8818
9372
  pollIntervalMs: this.config.telemetryPollIntervalMs ?? 60000,
8819
9373
  });
8820
- this.appStateService = new AppStateService(this.notificationService.notifications$, networkPort);
9374
+ this.appStateService = new AppStateService(this.notificationService.notifications$, networkPort, this.certificateMissingSubject.asObservable());
8821
9375
  if (this.events?.onAppStateChanged) {
8822
9376
  this.appStateService.state$.subscribe(this.events.onAppStateChanged);
8823
9377
  }
@@ -8829,9 +9383,15 @@ class SDKManager {
8829
9383
  const user = await this.sdk.getCurrentUser();
8830
9384
  const canPoll = user && hasAnyRole(user.roles, ['ROLE_MERCHANT', 'ROLE_CASHIER']);
8831
9385
  if (canPoll) {
8832
- this.notificationService.startPolling();
8833
- await this.startTelemetryPollingAuto();
8834
- this.isPollingActive = true;
9386
+ const hasCert = await this.checkCertificate();
9387
+ if (hasCert) {
9388
+ this.notificationService.startPolling();
9389
+ await this.startTelemetryPollingAuto();
9390
+ this.isPollingActive = true;
9391
+ }
9392
+ else {
9393
+ log$1.warn('Certificate missing at init — polling blocked until certificate is installed');
9394
+ }
8835
9395
  }
8836
9396
  // AppStateService remains active for all users (handles OFFLINE network state)
8837
9397
  }
@@ -8844,820 +9404,429 @@ class SDKManager {
8844
9404
  return this.appStateService.state$;
8845
9405
  }
8846
9406
  /**
8847
- * Observable stream of app mode only
8848
- * Emits AppMode with distinctUntilChanged
8849
- */
8850
- get mode$() {
8851
- this.ensureInitialized();
8852
- return this.appStateService.mode$;
8853
- }
8854
- /**
8855
- * Observable stream indicating if app is blocked
8856
- */
8857
- get isBlocked$() {
8858
- this.ensureInitialized();
8859
- return this.appStateService.isBlocked$;
8860
- }
8861
- /**
8862
- * Observable stream of warning state with countdown
8863
- */
8864
- get warning$() {
8865
- this.ensureInitialized();
8866
- return this.appStateService.warning$;
8867
- }
8868
- /**
8869
- * Observable stream of telemetry state (data, isLoading, isCached, error)
8870
- */
8871
- get telemetryState$() {
8872
- this.ensureInitialized();
8873
- return this.telemetryService.state$;
8874
- }
8875
- /**
8876
- * Get the pemId from the installed certificate
8877
- */
8878
- async getPemId() {
8879
- this.ensureInitialized();
8880
- try {
8881
- const certInfo = await this.sdk.getCertificatesInfo();
8882
- return certInfo?.pemId ?? null;
8883
- }
8884
- catch {
8885
- return null;
8886
- }
8887
- }
8888
- /**
8889
- * Start polling telemetry using the pemId from installed certificate
8890
- * Returns the pemId if successful, null if no certificate is installed
8891
- */
8892
- async startTelemetryPollingAuto() {
8893
- this.ensureInitialized();
8894
- const pemId = await this.getPemId();
8895
- if (pemId) {
8896
- this.telemetryService.startPolling(pemId);
8897
- }
8898
- return pemId;
8899
- }
8900
- /**
8901
- * Start polling telemetry for a specific PEM
8902
- */
8903
- startTelemetryPolling(pemId) {
8904
- this.ensureInitialized();
8905
- this.telemetryService.startPolling(pemId);
8906
- }
8907
- /**
8908
- * Stop telemetry polling
8909
- */
8910
- stopTelemetryPolling() {
8911
- this.ensureInitialized();
8912
- this.telemetryService.stopPolling();
8913
- }
8914
- /**
8915
- * Get simplified services for product use
8916
- */
8917
- getServices() {
8918
- this.ensureInitialized();
8919
- const sdk = this.sdk;
8920
- const telemetryService = this.telemetryService;
8921
- return {
8922
- receipts: sdk.receipts,
8923
- merchants: sdk.merchants,
8924
- cashiers: sdk.cashiers,
8925
- cashRegisters: sdk.cashRegisters,
8926
- pointOfSales: sdk.pointOfSales,
8927
- suppliers: sdk.suppliers,
8928
- pems: sdk.pems,
8929
- dailyReports: sdk.dailyReports,
8930
- journals: sdk.journals,
8931
- telemetry: {
8932
- startPollingAuto: () => this.startTelemetryPollingAuto(),
8933
- startPolling: (pemId) => telemetryService.startPolling(pemId),
8934
- stopPolling: () => telemetryService.stopPolling(),
8935
- getTelemetry: (pemId) => telemetryService.getTelemetry(pemId),
8936
- refreshTelemetry: (pemId) => telemetryService.refreshTelemetry(pemId),
8937
- triggerSync: () => telemetryService.triggerSync(),
8938
- clearTelemetry: () => telemetryService.clearTelemetry(),
8939
- getPemId: () => this.getPemId(),
8940
- },
8941
- login: (credentials) => sdk.login(credentials),
8942
- logout: () => sdk.logout(),
8943
- getCurrentUser: () => sdk.getCurrentUser(),
8944
- isAuthenticated: () => sdk.isAuthenticated(),
8945
- storeCertificate: (certificate, privateKey, options) => sdk.storeCertificate(certificate, privateKey, options),
8946
- hasCertificate: () => sdk.hasCertificate(),
8947
- clearCertificate: () => sdk.clearCertificate(),
8948
- isOnline: () => sdk.isOnline(),
8949
- };
9407
+ * Observable stream of app mode only
9408
+ * Emits AppMode with distinctUntilChanged
9409
+ */
9410
+ get mode$() {
9411
+ this.ensureInitialized();
9412
+ return this.appStateService.mode$;
8950
9413
  }
8951
9414
  /**
8952
- * Manually trigger a notification sync
9415
+ * Observable stream indicating if app is blocked
8953
9416
  */
8954
- async syncNotifications() {
9417
+ get isBlocked$() {
8955
9418
  this.ensureInitialized();
8956
- await this.notificationService.triggerSync();
9419
+ return this.appStateService.isBlocked$;
8957
9420
  }
8958
9421
  /**
8959
- * Manually trigger a telemetry sync
9422
+ * Observable stream of warning state with countdown
8960
9423
  */
8961
- async syncTelemetry() {
9424
+ get warning$() {
8962
9425
  this.ensureInitialized();
8963
- return this.telemetryService.triggerSync();
9426
+ return this.appStateService.warning$;
8964
9427
  }
8965
9428
  /**
8966
- * Check if the manager is initialized
9429
+ * Observable stream indicating if certificate is missing
9430
+ * When true, polling is blocked and the user should install a certificate
8967
9431
  */
8968
- getIsInitialized() {
8969
- return this.isInitialized;
9432
+ get certificateMissing$() {
9433
+ return this.certificateMissingSubject.asObservable();
8970
9434
  }
8971
9435
  /**
8972
- * Get the underlying SDK instance (for advanced use cases)
9436
+ * Observable stream of telemetry state (data, isLoading, isCached, error)
8973
9437
  */
8974
- getSDK() {
9438
+ get telemetryState$() {
8975
9439
  this.ensureInitialized();
8976
- return this.sdk;
8977
- }
8978
- cleanup() {
8979
- this.notificationService?.destroy();
8980
- this.telemetryService?.destroy();
8981
- this.appStateService?.destroy();
8982
- this.sdk?.destroy();
8983
- this.notificationService = null;
8984
- this.telemetryService = null;
8985
- this.appStateService = null;
8986
- this.sdk = null;
8987
- this.isInitialized = false;
8988
- this.isPollingActive = false;
8989
- }
8990
- ensureInitialized() {
8991
- if (!this.isInitialized) {
8992
- throw new ACubeSDKError('SDK_NOT_INITIALIZED', 'SDKManager not initialized. Call initialize() first.');
8993
- }
8994
- }
8995
- }
8996
- SDKManager.instance = null;
8997
-
8998
- const RECEIPT_READY = 'ready';
8999
- const RECEIPT_SENT = 'sent';
9000
- const RECEIPT_SORT_DESCENDING = 'descending';
9001
- const RECEIPT_SORT_ASCENDING = 'ascending';
9002
-
9003
- const log = createPrefixedLogger('CACHE-HANDLER');
9004
- class CacheHandler {
9005
- constructor(cache, networkMonitor) {
9006
- this.cache = cache;
9007
- this.networkMonitor = networkMonitor;
9008
- this.currentOnlineState = true;
9009
- this.setupNetworkMonitoring();
9010
- }
9011
- setupNetworkMonitoring() {
9012
- if (this.networkMonitor) {
9013
- this.networkSubscription = this.networkMonitor.online$.subscribe((online) => {
9014
- this.currentOnlineState = online;
9015
- });
9016
- }
9017
- }
9018
- isOnline() {
9019
- if (this.networkMonitor) {
9020
- return this.currentOnlineState;
9021
- }
9022
- if (typeof navigator !== 'undefined' && 'onLine' in navigator) {
9023
- return navigator.onLine;
9024
- }
9025
- return false;
9026
- }
9027
- async handleCachedRequest(url, requestFn, config) {
9028
- if (!this.cache || config?.useCache === false) {
9029
- const response = await requestFn();
9030
- return response.data;
9031
- }
9032
- const cacheKey = this.generateCacheKey(url);
9033
- const online = this.isOnline();
9034
- log.debug('Request:', { url, cacheKey, online });
9035
- if (online) {
9036
- try {
9037
- const response = await requestFn();
9038
- if (this.cache) {
9039
- await this.cache.set(cacheKey, response.data).catch((error) => {
9040
- log.error('Failed to cache:', error instanceof Error ? error.message : error);
9041
- });
9042
- }
9043
- return response.data;
9044
- }
9045
- catch (error) {
9046
- const cached = await this.cache.get(cacheKey).catch(() => null);
9047
- if (cached) {
9048
- log.debug('Network failed, using cache fallback');
9049
- return cached.data;
9050
- }
9051
- throw error;
9052
- }
9053
- }
9054
- else {
9055
- const cached = await this.cache.get(cacheKey).catch(() => null);
9056
- if (cached) {
9057
- log.debug('Offline, returning cached data');
9058
- return cached.data;
9059
- }
9060
- throw new Error('Offline: No cached data available');
9061
- }
9062
- }
9063
- generateCacheKey(url) {
9064
- return url;
9440
+ return this.telemetryService.state$;
9065
9441
  }
9066
- async invalidateCache(pattern) {
9067
- if (!this.cache)
9068
- return;
9442
+ /**
9443
+ * Get the pemId from the installed certificate
9444
+ */
9445
+ async getPemId() {
9446
+ this.ensureInitialized();
9069
9447
  try {
9070
- await this.cache.invalidate(pattern);
9448
+ const certInfo = await this.sdk.getCertificatesInfo();
9449
+ return certInfo?.pemId ?? null;
9071
9450
  }
9072
- catch (error) {
9073
- log.error('Invalidation failed:', error instanceof Error ? error.message : error);
9451
+ catch {
9452
+ return null;
9074
9453
  }
9075
9454
  }
9076
- getCacheStatus() {
9077
- return {
9078
- available: !!this.cache,
9079
- networkMonitorAvailable: !!this.networkMonitor,
9080
- isOnline: this.isOnline(),
9081
- };
9082
- }
9083
- destroy() {
9084
- this.networkSubscription?.unsubscribe();
9085
- }
9086
- }
9087
-
9088
- function transformError(error) {
9089
- if (axios.isAxiosError(error)) {
9090
- const response = error.response;
9091
- if (!response) {
9092
- return new ACubeSDKError('NETWORK_ERROR', 'Network error occurred', error);
9093
- }
9094
- const status = response.status;
9095
- const data = response.data;
9096
- const violations = data?.violations;
9097
- let message = 'Unknown error occurred';
9098
- if (data?.detail) {
9099
- message = data.detail;
9100
- }
9101
- else if (data?.title) {
9102
- message = data.title;
9103
- }
9104
- else if (error.message) {
9105
- message = error.message;
9106
- }
9107
- switch (status) {
9108
- case 400:
9109
- return new ACubeSDKError('VALIDATION_ERROR', message, error, status, violations);
9110
- case 401:
9111
- return new ACubeSDKError('AUTH_ERROR', message, error, status, violations);
9112
- case 403:
9113
- return new ACubeSDKError('FORBIDDEN_ERROR', message, error, status, violations);
9114
- case 404:
9115
- return new ACubeSDKError('NOT_FOUND_ERROR', message, error, status, violations);
9116
- case 422:
9117
- return new ACubeSDKError('VALIDATION_ERROR', message, error, status, violations);
9118
- default:
9119
- return new ACubeSDKError('UNKNOWN_ERROR', message, error, status, violations);
9455
+ /**
9456
+ * Start polling telemetry using the pemId from installed certificate
9457
+ * Returns the pemId if successful, null if no certificate is installed
9458
+ */
9459
+ async startTelemetryPollingAuto() {
9460
+ this.ensureInitialized();
9461
+ const pemId = await this.getPemId();
9462
+ if (pemId) {
9463
+ this.telemetryService.startPolling(pemId);
9120
9464
  }
9465
+ return pemId;
9121
9466
  }
9122
- return new ACubeSDKError('UNKNOWN_ERROR', 'Unknown error occurred', error);
9123
- }
9124
-
9125
- exports.ErrorCategory = void 0;
9126
- (function (ErrorCategory) {
9127
- ErrorCategory["SERVER_ERROR"] = "SERVER_ERROR";
9128
- ErrorCategory["CLIENT_ERROR"] = "CLIENT_ERROR";
9129
- ErrorCategory["AUTH_ERROR"] = "AUTH_ERROR";
9130
- ErrorCategory["CERTIFICATE_ERROR"] = "CERTIFICATE_ERROR";
9131
- ErrorCategory["NETWORK_ERROR"] = "NETWORK_ERROR";
9132
- ErrorCategory["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
9133
- })(exports.ErrorCategory || (exports.ErrorCategory = {}));
9134
- function extractStatusCode(error) {
9135
- if (error instanceof MTLSError && error.statusCode) {
9136
- return error.statusCode;
9137
- }
9138
- const errorObj = error;
9139
- if (errorObj?.response?.status) {
9140
- return errorObj.response.status;
9141
- }
9142
- if (typeof errorObj?.statusCode === 'number') {
9143
- return errorObj.statusCode;
9144
- }
9145
- return undefined;
9146
- }
9147
- function classifyError(error) {
9148
- const statusCode = extractStatusCode(error);
9149
- const errorMessage = error instanceof Error ? error.message : String(error);
9150
- if (statusCode && statusCode >= 500 && statusCode < 600) {
9151
- return {
9152
- category: exports.ErrorCategory.SERVER_ERROR,
9153
- statusCode,
9154
- message: errorMessage,
9155
- shouldRetry: false,
9156
- userMessage: `Server error (${statusCode}): The server encountered an error.`,
9157
- };
9158
- }
9159
- if (statusCode === 401 || statusCode === 403) {
9160
- return {
9161
- category: exports.ErrorCategory.AUTH_ERROR,
9162
- statusCode,
9163
- message: errorMessage,
9164
- shouldRetry: false,
9165
- userMessage: `Authentication error (${statusCode}): Invalid credentials or insufficient permissions.`,
9166
- };
9167
- }
9168
- if (statusCode && statusCode >= 400 && statusCode < 500) {
9169
- return {
9170
- category: exports.ErrorCategory.CLIENT_ERROR,
9171
- statusCode,
9172
- message: errorMessage,
9173
- shouldRetry: false,
9174
- userMessage: `Request error (${statusCode}): ${errorMessage}`,
9175
- };
9467
+ /**
9468
+ * Start polling telemetry for a specific PEM
9469
+ */
9470
+ startTelemetryPolling(pemId) {
9471
+ this.ensureInitialized();
9472
+ this.telemetryService.startPolling(pemId);
9176
9473
  }
9177
- if (error instanceof MTLSError) {
9178
- return {
9179
- category: exports.ErrorCategory.CERTIFICATE_ERROR,
9180
- statusCode,
9181
- message: errorMessage,
9182
- shouldRetry: true,
9183
- userMessage: 'Certificate error: Unable to establish secure connection.',
9184
- };
9474
+ /**
9475
+ * Stop telemetry polling
9476
+ */
9477
+ stopTelemetryPolling() {
9478
+ this.ensureInitialized();
9479
+ this.telemetryService.stopPolling();
9185
9480
  }
9186
- if (!statusCode &&
9187
- (errorMessage.toLowerCase().includes('network') ||
9188
- errorMessage.toLowerCase().includes('timeout') ||
9189
- errorMessage.toLowerCase().includes('connection'))) {
9481
+ /**
9482
+ * Get simplified services for product use
9483
+ */
9484
+ getServices() {
9485
+ this.ensureInitialized();
9486
+ const sdk = this.sdk;
9487
+ const telemetryService = this.telemetryService;
9190
9488
  return {
9191
- category: exports.ErrorCategory.NETWORK_ERROR,
9192
- message: errorMessage,
9193
- shouldRetry: true,
9194
- userMessage: 'Network error: Unable to connect to server.',
9489
+ receipts: sdk.receipts,
9490
+ merchants: sdk.merchants,
9491
+ cashiers: sdk.cashiers,
9492
+ cashRegisters: sdk.cashRegisters,
9493
+ pointOfSales: sdk.pointOfSales,
9494
+ suppliers: sdk.suppliers,
9495
+ pems: sdk.pems,
9496
+ dailyReports: sdk.dailyReports,
9497
+ journals: sdk.journals,
9498
+ telemetry: {
9499
+ startPollingAuto: () => this.startTelemetryPollingAuto(),
9500
+ startPolling: (pemId) => telemetryService.startPolling(pemId),
9501
+ stopPolling: () => telemetryService.stopPolling(),
9502
+ getTelemetry: (pemId) => telemetryService.getTelemetry(pemId),
9503
+ refreshTelemetry: (pemId) => telemetryService.refreshTelemetry(pemId),
9504
+ triggerSync: () => telemetryService.triggerSync(),
9505
+ clearTelemetry: () => telemetryService.clearTelemetry(),
9506
+ getPemId: () => this.getPemId(),
9507
+ },
9508
+ login: (credentials) => sdk.login(credentials),
9509
+ logout: () => sdk.logout(),
9510
+ getCurrentUser: () => sdk.getCurrentUser(),
9511
+ isAuthenticated: () => sdk.isAuthenticated(),
9512
+ storeCertificate: async (certificate, privateKey, options) => {
9513
+ await sdk.storeCertificate(certificate, privateKey, options);
9514
+ this.certificateMissingSubject.next(false);
9515
+ // Start polling if user can poll and polling is not active
9516
+ if (!this.isPollingActive) {
9517
+ const user = await sdk.getCurrentUser();
9518
+ const canPoll = user && hasAnyRole(user.roles, ['ROLE_MERCHANT', 'ROLE_CASHIER']);
9519
+ if (canPoll) {
9520
+ log$1.info('Certificate installed — starting polling');
9521
+ this.notificationService?.startPolling();
9522
+ await this.startTelemetryPollingAuto();
9523
+ this.isPollingActive = true;
9524
+ }
9525
+ }
9526
+ },
9527
+ hasCertificate: () => sdk.hasCertificate(),
9528
+ clearCertificate: async () => {
9529
+ await sdk.clearCertificate();
9530
+ this.certificateMissingSubject.next(true);
9531
+ // Stop polling since certificate is required
9532
+ if (this.isPollingActive) {
9533
+ log$1.info('Certificate removed — stopping polling');
9534
+ this.notificationService?.stopPolling();
9535
+ this.telemetryService?.stopPolling();
9536
+ this.telemetryService?.clearTelemetry();
9537
+ this.isPollingActive = false;
9538
+ }
9539
+ },
9540
+ getCertificate: () => sdk.getCertificate(),
9541
+ getCertificatesInfo: () => sdk.getCertificatesInfo(),
9542
+ notifications: sdk.notifications,
9543
+ isOnline: () => sdk.isOnline(),
9195
9544
  };
9196
9545
  }
9197
- return {
9198
- category: exports.ErrorCategory.UNKNOWN_ERROR,
9199
- statusCode,
9200
- message: errorMessage,
9201
- shouldRetry: false,
9202
- userMessage: `Unexpected error: ${errorMessage}`,
9203
- };
9204
- }
9205
- function shouldReconfigureCertificate(error) {
9206
- const classification = classifyError(error);
9207
- return classification.category === exports.ErrorCategory.CERTIFICATE_ERROR;
9208
- }
9209
- function shouldRetryRequest(error, isRetryAttempt) {
9210
- if (isRetryAttempt) {
9211
- return false;
9546
+ /**
9547
+ * Manually trigger a notification sync
9548
+ */
9549
+ async syncNotifications() {
9550
+ this.ensureInitialized();
9551
+ await this.notificationService.triggerSync();
9212
9552
  }
9213
- const classification = classifyError(error);
9214
- return classification.shouldRetry;
9215
- }
9216
- function getUserFriendlyMessage(error) {
9217
- const classification = classifyError(error);
9218
- return classification.userMessage;
9219
- }
9220
-
9221
- // Enum options arrays
9222
- const VAT_RATE_CODE_OPTIONS = [
9223
- '4.00',
9224
- '5.00',
9225
- '10.00',
9226
- '22.00',
9227
- '2.00',
9228
- '6.40',
9229
- '7.00',
9230
- '7.30',
9231
- '7.50',
9232
- '7.65',
9233
- '7.95',
9234
- '8.30',
9235
- '8.50',
9236
- '8.80',
9237
- '9.50',
9238
- '12.30',
9239
- 'N1',
9240
- 'N2',
9241
- 'N3',
9242
- 'N4',
9243
- 'N5',
9244
- 'N6',
9245
- ];
9246
- const GOOD_OR_SERVICE_OPTIONS = ['goods', 'service'];
9247
- const RECEIPT_PROOF_TYPE_OPTIONS = ['POS', 'VR', 'ND'];
9248
- // Enum types for receipt validation
9249
- const VatRateCodeSchema = z__namespace.enum(VAT_RATE_CODE_OPTIONS);
9250
- const GoodOrServiceSchema = z__namespace.enum(GOOD_OR_SERVICE_OPTIONS);
9251
- const ReceiptProofTypeSchema = z__namespace.enum(RECEIPT_PROOF_TYPE_OPTIONS);
9252
- // Receipt Item Schema
9253
- const ReceiptItemSchema = z__namespace.object({
9254
- type: GoodOrServiceSchema.optional(),
9255
- quantity: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
9256
- description: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
9257
- unit_price: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
9258
- vat_rate_code: VatRateCodeSchema.optional(),
9259
- simplified_vat_allocation: z__namespace.boolean().optional(),
9260
- discount: z__namespace.string().nullable().optional(),
9261
- is_down_payment_or_voucher_redemption: z__namespace.boolean().optional(),
9262
- complimentary: z__namespace.boolean().optional(),
9263
- });
9264
- // Main Receipt Input Schema
9265
- const ReceiptInputSchema = z__namespace
9266
- .object({
9267
- items: z__namespace.array(ReceiptItemSchema).min(1, { error: 'arrayMin1' }),
9268
- customer_tax_code: z__namespace.string().optional(),
9269
- customer_lottery_code: z__namespace.string().optional(),
9270
- discount: z__namespace.string().nullable().optional(),
9271
- invoice_issuing: z__namespace.boolean().optional(),
9272
- uncollected_dcr_to_ssn: z__namespace.boolean().optional(),
9273
- services_uncollected_amount: z__namespace.string().nullable().optional(),
9274
- goods_uncollected_amount: z__namespace.string().nullable().optional(),
9275
- cash_payment_amount: z__namespace.string().nullable().optional(),
9276
- electronic_payment_amount: z__namespace.string().nullable().optional(),
9277
- ticket_restaurant_payment_amount: z__namespace.string().nullable().optional(),
9278
- ticket_restaurant_quantity: z__namespace.number().optional(),
9279
- })
9280
- .refine((data) => {
9281
- // At least one payment method should be provided
9282
- const hasCashPayment = data.cash_payment_amount && parseFloat(data.cash_payment_amount) > 0;
9283
- const hasElectronicPayment = data.electronic_payment_amount && parseFloat(data.electronic_payment_amount) > 0;
9284
- const hasTicketPayment = data.ticket_restaurant_payment_amount &&
9285
- parseFloat(data.ticket_restaurant_payment_amount) > 0;
9286
- return hasCashPayment || hasElectronicPayment || hasTicketPayment;
9287
- }, {
9288
- error: 'At least one payment method is required',
9289
- path: ['payment_methods'],
9290
- })
9291
- .refine((data) => {
9292
- // only one between customer_tax_code and customer_lottery_code can be provided
9293
- return !data.customer_tax_code || !data.customer_lottery_code;
9294
- }, {
9295
- error: 'Only one between customer_tax_code and customer_lottery_code can be provided',
9296
- path: ['customer_tax_code', 'customer_lottery_code'],
9297
- });
9298
- // Receipt Return or Void via PEM Schema
9299
- const ReceiptReturnOrVoidViaPEMInputSchema = z__namespace.object({
9300
- device_id: z__namespace.string().optional(),
9301
- items: z__namespace.array(ReceiptItemSchema).min(1, { error: 'arrayMin1' }),
9302
- document_number: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
9303
- document_datetime: z__namespace.string().optional(),
9304
- lottery_code: z__namespace.string().optional(),
9305
- });
9306
- // Receipt Return or Void with Proof Schema
9307
- const ReceiptReturnOrVoidWithProofInputSchema = z__namespace.object({
9308
- items: z__namespace.array(ReceiptItemSchema).min(1, { error: 'arrayMin1' }),
9309
- proof: ReceiptProofTypeSchema,
9310
- document_datetime: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
9311
- });
9312
- // Void Receipt Schema
9313
- const VoidReceiptInputSchema = z__namespace.object({
9314
- document_number: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
9315
- });
9316
- const ReceiptReturnItemSchema = z__namespace
9317
- .array(z__namespace.object({
9318
- id: z__namespace.number(),
9319
- quantity: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
9320
- }))
9321
- .min(1, { error: 'arrayMin1' });
9322
- // Receipt Return Schema
9323
- const ReceiptReturnInputSchema = z__namespace.object({
9324
- items: z__namespace.array(ReceiptReturnItemSchema).min(1, { error: 'arrayMin1' }),
9325
- document_number: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
9326
- });
9327
-
9328
- // Cashier Create Input Schema (MF1)
9329
- const CashierCreateInputSchema = z__namespace.object({
9330
- email: z__namespace
9331
- .string()
9332
- .min(1, { error: 'fieldIsRequired' })
9333
- .max(255, { error: 'emailMaxLength' })
9334
- .email({ error: 'invalidEmail' }),
9335
- password: z__namespace
9336
- .string()
9337
- .min(8, { error: 'passwordMinLength' })
9338
- .max(40, { error: 'passwordMaxLength' }),
9339
- name: z__namespace.string().min(1, { error: 'fieldIsRequired' }).max(255, { error: 'nameMaxLength' }),
9340
- display_name: z__namespace
9341
- .string()
9342
- .min(1, { error: 'fieldIsRequired' })
9343
- .max(255, { error: 'displayNameMaxLength' }),
9344
- });
9345
-
9346
- // Enum options arrays
9347
- const PEM_STATUS_OPTIONS = [
9348
- 'NEW',
9349
- 'REGISTERED',
9350
- 'ACTIVATED',
9351
- 'ONLINE',
9352
- 'OFFLINE',
9353
- 'DISCARDED',
9354
- ];
9355
- // Address Schema (reusable)
9356
- const AddressSchema = z__namespace.object({
9357
- street_address: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
9358
- street_number: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
9359
- zip_code: z__namespace
9360
- .string()
9361
- .min(1, { error: 'fieldIsRequired' })
9362
- .regex(/^\d{5}$/, { error: 'invalidZipCode' }),
9363
- city: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
9364
- province: z__namespace
9365
- .string()
9366
- .min(2, { error: 'provinceMinLength' })
9367
- .max(2, { error: 'provinceMaxLength' })
9368
- .toUpperCase(),
9369
- });
9370
- // PEM Status Schema
9371
- const PEMStatusSchema = z__namespace.enum(PEM_STATUS_OPTIONS);
9372
- // Activation Request Schema
9373
- const ActivationRequestSchema = z__namespace.object({
9374
- registration_key: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
9375
- });
9376
- // PEM Status Offline Request Schema
9377
- const PEMStatusOfflineRequestSchema = z__namespace.object({
9378
- timestamp: z__namespace
9379
- .string()
9380
- .min(1, { error: 'fieldIsRequired' })
9381
- .refine((val) => !isNaN(Date.parse(val)), {
9382
- error: 'invalidDateFormat',
9383
- }),
9384
- reason: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
9385
- });
9553
+ /**
9554
+ * Manually trigger a telemetry sync
9555
+ */
9556
+ async syncTelemetry() {
9557
+ this.ensureInitialized();
9558
+ return this.telemetryService.triggerSync();
9559
+ }
9560
+ /**
9561
+ * Check if the manager is initialized
9562
+ */
9563
+ getIsInitialized() {
9564
+ return this.isInitialized;
9565
+ }
9566
+ /**
9567
+ * Get the underlying SDK instance (for advanced use cases)
9568
+ */
9569
+ getSDK() {
9570
+ this.ensureInitialized();
9571
+ return this.sdk;
9572
+ }
9573
+ /**
9574
+ * Check certificate availability and update certificateMissing state.
9575
+ * Returns true if certificate is available, false otherwise.
9576
+ */
9577
+ async checkCertificate() {
9578
+ try {
9579
+ const hasCert = await this.sdk.hasCertificate();
9580
+ this.certificateMissingSubject.next(!hasCert);
9581
+ return hasCert;
9582
+ }
9583
+ catch {
9584
+ this.certificateMissingSubject.next(true);
9585
+ return false;
9586
+ }
9587
+ }
9588
+ cleanup() {
9589
+ this.notificationService?.destroy();
9590
+ this.telemetryService?.destroy();
9591
+ this.appStateService?.destroy();
9592
+ this.sdk?.destroy();
9593
+ this.notificationService = null;
9594
+ this.telemetryService = null;
9595
+ this.appStateService = null;
9596
+ this.sdk = null;
9597
+ this.isInitialized = false;
9598
+ this.isPollingActive = false;
9599
+ }
9600
+ ensureInitialized() {
9601
+ if (!this.isInitialized) {
9602
+ throw new ACubeSDKError('SDK_NOT_INITIALIZED', 'SDKManager not initialized. Call initialize() first.');
9603
+ }
9604
+ }
9605
+ }
9606
+ SDKManager.instance = null;
9386
9607
 
9387
- // Cash Register Create Schema
9388
- const CashRegisterCreateSchema = z__namespace.object({
9389
- pem_serial_number: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
9390
- name: z__namespace.string().min(1, { error: 'fieldIsRequired' }).max(100, { error: 'nameMaxLength' }),
9391
- });
9608
+ const RECEIPT_READY = 'ready';
9609
+ const RECEIPT_SENT = 'sent';
9610
+ const RECEIPT_SORT_DESCENDING = 'descending';
9611
+ const RECEIPT_SORT_ASCENDING = 'ascending';
9392
9612
 
9393
- // VAT number validation regex (Partita IVA - 11 digits)
9394
- const VAT_NUMBER_REGEX = /^\d{11}$/;
9395
- // Fiscal code validation regex (Codice Fiscale - 11 digits only for merchants)
9396
- const FISCAL_CODE_REGEX = /^\d{11}$/;
9397
- // Password validation regex (from OpenAPI spec)
9398
- const PASSWORD_REGEX = /^((?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{10,}).*)$/;
9399
- // Merchant Create Input Schema
9400
- const MerchantCreateInputSchema = z__namespace
9401
- .object({
9402
- vat_number: z__namespace
9403
- .string()
9404
- .min(1, { error: 'fieldIsRequired' })
9405
- .regex(VAT_NUMBER_REGEX, { error: 'invalidVatNumber' }),
9406
- fiscal_code: z__namespace.string().regex(FISCAL_CODE_REGEX, { error: 'invalidFiscalCode' }).optional(),
9407
- business_name: z__namespace.string().max(200, { error: 'businessNameMaxLength' }).optional().nullable(),
9408
- first_name: z__namespace.string().max(100, { error: 'firstNameMaxLength' }).optional().nullable(),
9409
- last_name: z__namespace.string().max(100, { error: 'lastNameMaxLength' }).optional().nullable(),
9410
- email: z__namespace.string().min(1, { error: 'fieldIsRequired' }).email({ error: 'invalidEmail' }),
9411
- password: z__namespace
9412
- .string()
9413
- .min(1, { error: 'fieldIsRequired' })
9414
- .regex(PASSWORD_REGEX, { error: 'passwordComplexity' }),
9415
- address: AddressSchema.optional(),
9416
- })
9417
- .refine((data) => {
9418
- const hasBusinessName = data.business_name && data.business_name.trim() !== '';
9419
- const hasPersonalNames = (data.first_name && data.first_name.trim() !== '') ||
9420
- (data.last_name && data.last_name.trim() !== '');
9421
- // If business name is set, first/last name must not be provided
9422
- if (hasBusinessName && hasPersonalNames) {
9423
- return false;
9613
+ const log = createPrefixedLogger('CACHE-HANDLER');
9614
+ class CacheHandler {
9615
+ constructor(cache, networkMonitor) {
9616
+ this.cache = cache;
9617
+ this.networkMonitor = networkMonitor;
9618
+ this.currentOnlineState = true;
9619
+ this.setupNetworkMonitoring();
9424
9620
  }
9425
- // At least one naming method must be provided
9426
- if (!hasBusinessName && !hasPersonalNames) {
9621
+ setupNetworkMonitoring() {
9622
+ if (this.networkMonitor) {
9623
+ this.networkSubscription = this.networkMonitor.online$.subscribe((online) => {
9624
+ this.currentOnlineState = online;
9625
+ });
9626
+ }
9627
+ }
9628
+ isOnline() {
9629
+ if (this.networkMonitor) {
9630
+ return this.currentOnlineState;
9631
+ }
9632
+ if (typeof navigator !== 'undefined' && 'onLine' in navigator) {
9633
+ return navigator.onLine;
9634
+ }
9427
9635
  return false;
9428
9636
  }
9429
- return true;
9430
- }, {
9431
- error: 'businessNameOrPersonalNamesRequired',
9432
- path: ['business_name'],
9433
- });
9434
- // Merchant Update Input Schema
9435
- const MerchantUpdateInputSchema = z__namespace.object({
9436
- business_name: z__namespace.string().max(200, { error: 'businessNameMaxLength' }).optional().nullable(),
9437
- first_name: z__namespace.string().max(100, { error: 'firstNameMaxLength' }).optional().nullable(),
9438
- last_name: z__namespace.string().max(100, { error: 'lastNameMaxLength' }).optional().nullable(),
9439
- address: AddressSchema.optional().nullable(),
9440
- });
9441
-
9442
- // Enum options arrays
9443
- const PEM_TYPE_OPTIONS = ['AP', 'SP', 'TM', 'PV'];
9444
- // PEM Data Schema
9445
- const PemDataSchema = z__namespace.object({
9446
- version: z__namespace.string().min(1, { error: 'fieldIsRequired' }),
9447
- type: z__namespace.enum(PEM_TYPE_OPTIONS, {
9448
- error: 'invalidPemType',
9449
- }),
9450
- });
9451
- // PEM Create Input Schema
9452
- const PemCreateInputSchema = z__namespace.object({
9453
- merchant_uuid: z__namespace.string().min(1, { error: 'fieldIsRequired' }).uuid({ error: 'invalidUuid' }),
9454
- address: AddressSchema.optional(),
9455
- /* external_pem_data: PemDataSchema.optional(), */
9456
- });
9457
-
9458
- // Italian Fiscal ID validation regex (Codice Fiscale for individuals or Partita IVA for companies)
9459
- const FISCAL_ID_REGEX = /^([A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]|[0-9]{11})$/;
9460
- // Supplier Create Input Schema
9461
- const SupplierCreateInputSchema = z__namespace.object({
9462
- fiscal_id: z__namespace
9463
- .string()
9464
- .min(1, { error: 'fieldIsRequired' })
9465
- .regex(FISCAL_ID_REGEX, { error: 'invalidFiscalId' })
9466
- .toUpperCase(),
9467
- name: z__namespace.string().min(1, { error: 'fieldIsRequired' }).max(200, { error: 'nameMaxLength' }),
9468
- address: AddressSchema.optional(),
9469
- });
9470
- // Supplier Update Input Schema
9471
- const SupplierUpdateInputSchema = z__namespace.object({
9472
- name: z__namespace.string().min(1, { error: 'fieldIsRequired' }).max(200, { error: 'nameMaxLength' }),
9473
- address: AddressSchema.optional(),
9474
- });
9475
-
9476
- // Journal Close Input Schema
9477
- const JournalCloseInputSchema = z__namespace.object({
9478
- closing_timestamp: z__namespace
9479
- .string()
9480
- .min(1, { error: 'fieldIsRequired' })
9481
- .refine((val) => !isNaN(Date.parse(val)), {
9482
- error: 'invalidDateFormat',
9483
- }),
9484
- reason: z__namespace.string().max(255, { error: 'reasonMaxLength' }).optional(),
9485
- });
9486
-
9487
- // Daily Report Status Options
9488
- const DAILY_REPORT_STATUS_OPTIONS = ['pending', 'sent', 'error'];
9489
- // Daily Report Status Schema
9490
- const DailyReportStatusSchema = z__namespace.enum(DAILY_REPORT_STATUS_OPTIONS, {
9491
- error: 'invalidDailyReportStatus',
9492
- });
9493
- // Daily Reports List Parameters Schema
9494
- const DailyReportsParamsSchema = z__namespace.object({
9495
- pem_serial_number: z__namespace.string().min(1, { error: 'fieldIsRequired' }).optional(),
9496
- date_from: z__namespace
9497
- .string()
9498
- .refine((val) => !isNaN(Date.parse(val)), {
9499
- error: 'invalidDateFormat',
9500
- })
9501
- .optional(),
9502
- date_to: z__namespace
9503
- .string()
9504
- .refine((val) => !isNaN(Date.parse(val)), {
9505
- error: 'invalidDateFormat',
9506
- })
9507
- .optional(),
9508
- status: DailyReportStatusSchema.optional(),
9509
- page: z__namespace.number().min(1, { error: 'pageMinValue' }).optional(),
9510
- });
9511
-
9512
- const NotificationScopeSchema = z__namespace.object({
9513
- type: z__namespace.literal('global'),
9514
- });
9515
- const PemStatusSchema = z__namespace.enum(['ONLINE', 'OFFLINE']);
9516
- const NotificationDataBlockAtSchema = z__namespace.object({
9517
- block_at: z__namespace.string(),
9518
- });
9519
- const NotificationDataPemStatusSchema = z__namespace.object({
9520
- from: PemStatusSchema,
9521
- to: PemStatusSchema,
9522
- });
9523
- const NotificationBaseSchema = z__namespace.object({
9524
- uuid: z__namespace.string().uuid({ error: 'invalidUuid' }),
9525
- scope: NotificationScopeSchema,
9526
- source: z__namespace.enum(['system', 'Italian Tax Authority']),
9527
- level: z__namespace.enum(['info', 'warning', 'error', 'critical']),
9528
- created_at: z__namespace.string(),
9529
- });
9530
- const NotificationMf2UnreachableSchema = NotificationBaseSchema.extend({
9531
- type: z__namespace.literal('INTERNAL_COMMUNICATION_FAILURE'),
9532
- code: z__namespace.literal('SYS-W-01'),
9533
- data: NotificationDataBlockAtSchema,
9534
- });
9535
- const NotificationPemsBlockedSchema = NotificationBaseSchema.extend({
9536
- type: z__namespace.literal('PEM_STATUS_CHANGED'),
9537
- code: z__namespace.literal('SYS-C-01'),
9538
- data: NotificationDataPemStatusSchema,
9539
- });
9540
- const NotificationPemBackOnlineSchema = NotificationBaseSchema.extend({
9541
- type: z__namespace.literal('PEM_STATUS_CHANGED'),
9542
- code: z__namespace.literal('SYS-I-01'),
9543
- data: NotificationDataPemStatusSchema,
9544
- });
9545
- const NotificationSchema = z__namespace.discriminatedUnion('code', [
9546
- NotificationMf2UnreachableSchema,
9547
- NotificationPemsBlockedSchema,
9548
- NotificationPemBackOnlineSchema,
9549
- ]);
9550
- const NotificationListResponseSchema = z__namespace.object({
9551
- members: z__namespace.array(NotificationSchema),
9552
- });
9637
+ async handleCachedRequest(url, requestFn, config) {
9638
+ if (!this.cache || config?.useCache === false) {
9639
+ const response = await requestFn();
9640
+ return response.data;
9641
+ }
9642
+ const cacheKey = this.generateCacheKey(url);
9643
+ const online = this.isOnline();
9644
+ log.debug('Request:', { url, cacheKey, online });
9645
+ if (online) {
9646
+ try {
9647
+ const response = await requestFn();
9648
+ if (this.cache) {
9649
+ await this.cache.set(cacheKey, response.data).catch((error) => {
9650
+ log.error('Failed to cache:', error instanceof Error ? error.message : error);
9651
+ });
9652
+ }
9653
+ return response.data;
9654
+ }
9655
+ catch (error) {
9656
+ const cached = await this.cache.get(cacheKey).catch(() => null);
9657
+ if (cached) {
9658
+ log.debug('Network failed, using cache fallback');
9659
+ return cached.data;
9660
+ }
9661
+ throw error;
9662
+ }
9663
+ }
9664
+ else {
9665
+ const cached = await this.cache.get(cacheKey).catch(() => null);
9666
+ if (cached) {
9667
+ log.debug('Offline, returning cached data');
9668
+ return cached.data;
9669
+ }
9670
+ throw new Error('Offline: No cached data available');
9671
+ }
9672
+ }
9673
+ generateCacheKey(url) {
9674
+ return url;
9675
+ }
9676
+ async invalidateCache(pattern) {
9677
+ if (!this.cache)
9678
+ return;
9679
+ try {
9680
+ await this.cache.invalidate(pattern);
9681
+ }
9682
+ catch (error) {
9683
+ log.error('Invalidation failed:', error instanceof Error ? error.message : error);
9684
+ }
9685
+ }
9686
+ getCacheStatus() {
9687
+ return {
9688
+ available: !!this.cache,
9689
+ networkMonitorAvailable: !!this.networkMonitor,
9690
+ isOnline: this.isOnline(),
9691
+ };
9692
+ }
9693
+ destroy() {
9694
+ this.networkSubscription?.unsubscribe();
9695
+ }
9696
+ }
9553
9697
 
9554
- const TelemetryMerchantSchema = z__namespace.object({
9555
- vat_number: z__namespace.string(),
9556
- fiscal_code: z__namespace.string().nullable(),
9557
- business_name: z__namespace.string(),
9558
- });
9559
- const TelemetrySupplierSchema = z__namespace.object({
9560
- vat_number: z__namespace.string(),
9561
- fiscal_code: z__namespace.string().nullable(),
9562
- business_name: z__namespace.string(),
9563
- });
9564
- const TelemetrySoftwareVersionSchema = z__namespace.object({
9565
- version: z__namespace.string(),
9566
- swid: z__namespace.string(),
9567
- installed_at: z__namespace.string(),
9568
- status: z__namespace.enum(['active', 'inactive', 'archived']),
9569
- });
9570
- const TelemetrySoftwareSchema = z__namespace.object({
9571
- code: z__namespace.string(),
9572
- name: z__namespace.string(),
9573
- approval_reference: z__namespace.string(),
9574
- version_info: TelemetrySoftwareVersionSchema,
9575
- });
9576
- const PendingReceiptsSchema = z__namespace.object({
9577
- count: z__namespace.number().int().nonnegative(),
9578
- total_amount: z__namespace.string(),
9579
- });
9580
- const TransmissionSchema = z__namespace.object({
9581
- attempted_at: z__namespace.string(),
9582
- outcome: z__namespace.enum(['success', 'failed', 'pending']),
9583
- });
9584
- const MessageSchema = z__namespace.object({
9585
- received_at: z__namespace.string(),
9586
- content: z__namespace.string(),
9587
- });
9588
- const LotterySecretRequestSchema = z__namespace.object({
9589
- requested_at: z__namespace.string(),
9590
- outcome: z__namespace.enum(['success', 'failed', 'pending']),
9591
- });
9592
- const LotterySchema = z__namespace.object({
9593
- last_transmission: TransmissionSchema,
9594
- secret_request: LotterySecretRequestSchema,
9595
- });
9596
- const TelemetrySchema = z__namespace.object({
9597
- pem_id: z__namespace.string(),
9598
- pem_status: z__namespace.enum(['ONLINE', 'OFFLINE', 'ERROR']),
9599
- pem_status_changed_at: z__namespace.string(),
9600
- merchant: TelemetryMerchantSchema,
9601
- supplier: TelemetrySupplierSchema,
9602
- software: TelemetrySoftwareSchema,
9603
- last_communication_at: z__namespace.string(),
9604
- pending_receipts: PendingReceiptsSchema,
9605
- last_receipt_transmission: TransmissionSchema,
9606
- last_message_from_mf2: MessageSchema,
9607
- ade_corrispettivi_transmission: TransmissionSchema,
9608
- last_message_from_ade: MessageSchema,
9609
- lottery: LotterySchema,
9610
- });
9698
+ function transformError(error) {
9699
+ if (axios.isAxiosError(error)) {
9700
+ const response = error.response;
9701
+ if (!response) {
9702
+ return new ACubeSDKError('NETWORK_ERROR', 'Network error occurred', error);
9703
+ }
9704
+ const status = response.status;
9705
+ const data = response.data;
9706
+ const violations = data?.violations;
9707
+ let message = 'Unknown error occurred';
9708
+ if (data?.detail) {
9709
+ message = data.detail;
9710
+ }
9711
+ else if (data?.title) {
9712
+ message = data.title;
9713
+ }
9714
+ else if (error.message) {
9715
+ message = error.message;
9716
+ }
9717
+ switch (status) {
9718
+ case 400:
9719
+ return new ACubeSDKError('VALIDATION_ERROR', message, error, status, violations);
9720
+ case 401:
9721
+ return new ACubeSDKError('AUTH_ERROR', message, error, status, violations);
9722
+ case 403:
9723
+ return new ACubeSDKError('FORBIDDEN_ERROR', message, error, status, violations);
9724
+ case 404:
9725
+ return new ACubeSDKError('NOT_FOUND_ERROR', message, error, status, violations);
9726
+ case 422:
9727
+ return new ACubeSDKError('VALIDATION_ERROR', message, error, status, violations);
9728
+ default:
9729
+ return new ACubeSDKError('UNKNOWN_ERROR', message, error, status, violations);
9730
+ }
9731
+ }
9732
+ return new ACubeSDKError('UNKNOWN_ERROR', 'Unknown error occurred', error);
9733
+ }
9611
9734
 
9612
- // Receipt schemas and types
9613
- // Common validation utilities
9614
- const ValidationMessages = {
9615
- fieldIsRequired: 'This field is required',
9616
- arrayMin1: 'At least one item is required',
9617
- paymentMethodRequired: 'At least one payment method is required',
9618
- invalidEmail: 'Please enter a valid email address',
9619
- passwordMinLength: 'Password must be at least 8 characters long',
9620
- passwordComplexity: 'Password must contain at least one uppercase letter, one lowercase letter, one number, and one special character',
9621
- invalidZipCode: 'Please enter a valid 5-digit zip code',
9622
- provinceMinLength: 'Province code must be 2 characters',
9623
- provinceMaxLength: 'Province code must be 2 characters',
9624
- invalidDateFormat: 'Please enter a valid date',
9625
- nameMaxLength: 'Name is too long',
9626
- invalidFiscalId: 'Please enter a valid Italian fiscal ID (Codice Fiscale or Partita IVA)',
9627
- invalidVatNumber: 'Please enter a valid VAT number (11 digits)',
9628
- invalidFiscalCode: 'Please enter a valid fiscal code (11 digits)',
9629
- businessNameMaxLength: 'Business name is too long (max 200 characters)',
9630
- businessNameOrPersonalNamesRequired: 'Please provide either a business name or first/last name, but not both',
9631
- firstNameMaxLength: 'First name is too long (max 100 characters)',
9632
- lastNameMaxLength: 'Last name is too long (max 100 characters)',
9633
- invalidUuid: 'Please enter a valid UUID',
9634
- invalidPemType: 'PEM type must be one of: AP, SP, TM, PV',
9635
- reasonMaxLength: 'Reason is too long (max 255 characters)',
9636
- pageMinValue: 'Page number must be at least 1',
9637
- invalidDailyReportStatus: 'Daily report status must be one of: pending, sent, error',
9638
- displayNameMaxLength: 'Display name is too long (max 255 characters)',
9639
- };
9640
- // Validation helper functions
9641
- const validateInput = (schema, data) => {
9642
- const result = schema.safeParse(data);
9643
- if (!result.success) {
9644
- const errors = result.error.issues.map((error) => ({
9645
- field: error.path.join('.'),
9646
- message: error.message,
9647
- code: error.code,
9648
- }));
9735
+ exports.ErrorCategory = void 0;
9736
+ (function (ErrorCategory) {
9737
+ ErrorCategory["SERVER_ERROR"] = "SERVER_ERROR";
9738
+ ErrorCategory["CLIENT_ERROR"] = "CLIENT_ERROR";
9739
+ ErrorCategory["AUTH_ERROR"] = "AUTH_ERROR";
9740
+ ErrorCategory["CERTIFICATE_ERROR"] = "CERTIFICATE_ERROR";
9741
+ ErrorCategory["NETWORK_ERROR"] = "NETWORK_ERROR";
9742
+ ErrorCategory["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
9743
+ })(exports.ErrorCategory || (exports.ErrorCategory = {}));
9744
+ function extractStatusCode(error) {
9745
+ if (error instanceof MTLSError && error.statusCode) {
9746
+ return error.statusCode;
9747
+ }
9748
+ const errorObj = error;
9749
+ if (errorObj?.response?.status) {
9750
+ return errorObj.response.status;
9751
+ }
9752
+ if (typeof errorObj?.statusCode === 'number') {
9753
+ return errorObj.statusCode;
9754
+ }
9755
+ return undefined;
9756
+ }
9757
+ function classifyError(error) {
9758
+ const statusCode = extractStatusCode(error);
9759
+ const errorMessage = error instanceof Error ? error.message : String(error);
9760
+ if (statusCode && statusCode >= 500 && statusCode < 600) {
9649
9761
  return {
9650
- success: false,
9651
- errors,
9652
- data: null,
9762
+ category: exports.ErrorCategory.SERVER_ERROR,
9763
+ statusCode,
9764
+ message: errorMessage,
9765
+ shouldRetry: false,
9766
+ userMessage: `Server error (${statusCode}): The server encountered an error.`,
9767
+ };
9768
+ }
9769
+ if (statusCode === 401 || statusCode === 403) {
9770
+ return {
9771
+ category: exports.ErrorCategory.AUTH_ERROR,
9772
+ statusCode,
9773
+ message: errorMessage,
9774
+ shouldRetry: false,
9775
+ userMessage: `Authentication error (${statusCode}): Invalid credentials or insufficient permissions.`,
9776
+ };
9777
+ }
9778
+ if (statusCode && statusCode >= 400 && statusCode < 500) {
9779
+ return {
9780
+ category: exports.ErrorCategory.CLIENT_ERROR,
9781
+ statusCode,
9782
+ message: errorMessage,
9783
+ shouldRetry: false,
9784
+ userMessage: `Request error (${statusCode}): ${errorMessage}`,
9785
+ };
9786
+ }
9787
+ if (error instanceof MTLSError) {
9788
+ return {
9789
+ category: exports.ErrorCategory.CERTIFICATE_ERROR,
9790
+ statusCode,
9791
+ message: errorMessage,
9792
+ shouldRetry: true,
9793
+ userMessage: 'Certificate error: Unable to establish secure connection.',
9794
+ };
9795
+ }
9796
+ if (!statusCode &&
9797
+ (errorMessage.toLowerCase().includes('network') ||
9798
+ errorMessage.toLowerCase().includes('timeout') ||
9799
+ errorMessage.toLowerCase().includes('connection'))) {
9800
+ return {
9801
+ category: exports.ErrorCategory.NETWORK_ERROR,
9802
+ message: errorMessage,
9803
+ shouldRetry: true,
9804
+ userMessage: 'Network error: Unable to connect to server.',
9653
9805
  };
9654
9806
  }
9655
9807
  return {
9656
- success: true,
9657
- errors: [],
9658
- data: result.data,
9808
+ category: exports.ErrorCategory.UNKNOWN_ERROR,
9809
+ statusCode,
9810
+ message: errorMessage,
9811
+ shouldRetry: false,
9812
+ userMessage: `Unexpected error: ${errorMessage}`,
9659
9813
  };
9660
- };
9814
+ }
9815
+ function shouldReconfigureCertificate(error) {
9816
+ const classification = classifyError(error);
9817
+ return classification.category === exports.ErrorCategory.CERTIFICATE_ERROR;
9818
+ }
9819
+ function shouldRetryRequest(error, isRetryAttempt) {
9820
+ if (isRetryAttempt) {
9821
+ return false;
9822
+ }
9823
+ const classification = classifyError(error);
9824
+ return classification.shouldRetry;
9825
+ }
9826
+ function getUserFriendlyMessage(error) {
9827
+ const classification = classifyError(error);
9828
+ return classification.userMessage;
9829
+ }
9661
9830
 
9662
9831
  var MTLSErrorType;
9663
9832
  (function (MTLSErrorType) {