@a-cube-io/ereceipts-js-sdk 1.0.0
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/LICENSE +41 -0
- package/README.md +444 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/auth-D6UEILKY.cjs +56 -0
- package/dist/auth-D6UEILKY.cjs.map +1 -0
- package/dist/auth-RZRIC4PK.js +7 -0
- package/dist/auth-RZRIC4PK.js.map +1 -0
- package/dist/chunk-24ZJ6SNG.cjs +624 -0
- package/dist/chunk-24ZJ6SNG.cjs.map +1 -0
- package/dist/chunk-C3YEL4ED.js +511 -0
- package/dist/chunk-C3YEL4ED.js.map +1 -0
- package/dist/chunk-K65HAAAO.js +44 -0
- package/dist/chunk-K65HAAAO.js.map +1 -0
- package/dist/chunk-NARXAXFL.cjs +215 -0
- package/dist/chunk-NARXAXFL.cjs.map +1 -0
- package/dist/chunk-UBEIMFLN.js +209 -0
- package/dist/chunk-UBEIMFLN.js.map +1 -0
- package/dist/chunk-UVUWF5FV.cjs +3964 -0
- package/dist/chunk-UVUWF5FV.cjs.map +1 -0
- package/dist/chunk-UXVFQRZK.cjs +533 -0
- package/dist/chunk-UXVFQRZK.cjs.map +1 -0
- package/dist/chunk-VDHN3FKS.js +3929 -0
- package/dist/chunk-VDHN3FKS.js.map +1 -0
- package/dist/chunk-XQKCXG4I.cjs +52 -0
- package/dist/chunk-XQKCXG4I.cjs.map +1 -0
- package/dist/chunk-YX3PJ4FC.js +590 -0
- package/dist/chunk-YX3PJ4FC.js.map +1 -0
- package/dist/client-WPBRHPKX.cjs +31 -0
- package/dist/client-WPBRHPKX.cjs.map +1 -0
- package/dist/client-Z2LXQJMF.js +6 -0
- package/dist/client-Z2LXQJMF.js.map +1 -0
- package/dist/index.cjs +1326 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +960 -0
- package/dist/index.d.ts +960 -0
- package/dist/index.js +1065 -0
- package/dist/index.js.map +1 -0
- package/dist/metafile-cjs.json +1 -0
- package/dist/metafile-esm.json +1 -0
- package/dist/queue-D7PJ536B.js +4 -0
- package/dist/queue-D7PJ536B.js.map +1 -0
- package/dist/queue-JHWXWX2B.cjs +13 -0
- package/dist/queue-JHWXWX2B.cjs.map +1 -0
- package/dist/token-3CIX4E64.cjs +13 -0
- package/dist/token-3CIX4E64.cjs.map +1 -0
- package/dist/token-4OAGWTVG.js +4 -0
- package/dist/token-4OAGWTVG.js.map +1 -0
- package/openapi.yaml +2732 -0
- package/package.json +115 -0
|
@@ -0,0 +1,533 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkUVUWF5FV_cjs = require('./chunk-UVUWF5FV.cjs');
|
|
4
|
+
var chunk24ZJ6SNG_cjs = require('./chunk-24ZJ6SNG.cjs');
|
|
5
|
+
var chunkXQKCXG4I_cjs = require('./chunk-XQKCXG4I.cjs');
|
|
6
|
+
|
|
7
|
+
/* A-Cube SDK - Professional TypeScript SDK for Italian e-receipt system */
|
|
8
|
+
|
|
9
|
+
// src/utils/validation.ts
|
|
10
|
+
var validateEmail = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name((email) => {
|
|
11
|
+
const errors = [];
|
|
12
|
+
if (!email || email.trim() === "") {
|
|
13
|
+
errors.push({
|
|
14
|
+
field: "email",
|
|
15
|
+
message: "Email is required",
|
|
16
|
+
code: "EMAIL_REQUIRED"
|
|
17
|
+
});
|
|
18
|
+
} else {
|
|
19
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
20
|
+
if (!emailRegex.test(email)) {
|
|
21
|
+
errors.push({
|
|
22
|
+
field: "email",
|
|
23
|
+
message: "Invalid email format",
|
|
24
|
+
code: "EMAIL_INVALID"
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
isValid: errors.length === 0,
|
|
30
|
+
errors
|
|
31
|
+
};
|
|
32
|
+
}, "validateEmail");
|
|
33
|
+
var validatePassword = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name((password) => {
|
|
34
|
+
const errors = [];
|
|
35
|
+
if (!password) {
|
|
36
|
+
errors.push({
|
|
37
|
+
field: "password",
|
|
38
|
+
message: "Password is required",
|
|
39
|
+
code: "PASSWORD_REQUIRED"
|
|
40
|
+
});
|
|
41
|
+
return {
|
|
42
|
+
isValid: false,
|
|
43
|
+
errors
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (password.length < 8) {
|
|
47
|
+
errors.push({
|
|
48
|
+
field: "password",
|
|
49
|
+
message: "Password must be at least 8 characters long",
|
|
50
|
+
code: "PASSWORD_TOO_SHORT"
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (password.length > 40) {
|
|
54
|
+
errors.push({
|
|
55
|
+
field: "password",
|
|
56
|
+
message: "Password must not exceed 40 characters",
|
|
57
|
+
code: "PASSWORD_TOO_LONG"
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (!/[A-Z]/.test(password)) {
|
|
61
|
+
errors.push({
|
|
62
|
+
field: "password",
|
|
63
|
+
message: "Password must contain at least one uppercase letter",
|
|
64
|
+
code: "PASSWORD_NO_UPPERCASE"
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
if (!/[a-z]/.test(password)) {
|
|
68
|
+
errors.push({
|
|
69
|
+
field: "password",
|
|
70
|
+
message: "Password must contain at least one lowercase letter",
|
|
71
|
+
code: "PASSWORD_NO_LOWERCASE"
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
if (!/[0-9]/.test(password)) {
|
|
75
|
+
errors.push({
|
|
76
|
+
field: "password",
|
|
77
|
+
message: "Password must contain at least one digit",
|
|
78
|
+
code: "PASSWORD_NO_DIGIT"
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
if (!/[!@#$%^&*]/.test(password)) {
|
|
82
|
+
errors.push({
|
|
83
|
+
field: "password",
|
|
84
|
+
message: "Password must contain at least one special character (!@#$%^&*)",
|
|
85
|
+
code: "PASSWORD_NO_SPECIAL"
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
isValid: errors.length === 0,
|
|
90
|
+
errors
|
|
91
|
+
};
|
|
92
|
+
}, "validatePassword");
|
|
93
|
+
var validateFiscalId = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name((fiscalId) => {
|
|
94
|
+
const errors = [];
|
|
95
|
+
if (!fiscalId || fiscalId.trim() === "") {
|
|
96
|
+
errors.push({
|
|
97
|
+
field: "fiscal_id",
|
|
98
|
+
message: "Fiscal ID is required",
|
|
99
|
+
code: "FISCAL_ID_REQUIRED"
|
|
100
|
+
});
|
|
101
|
+
} else {
|
|
102
|
+
const fiscalIdRegex = /^\d{11}$/;
|
|
103
|
+
if (!fiscalIdRegex.test(fiscalId)) {
|
|
104
|
+
errors.push({
|
|
105
|
+
field: "fiscal_id",
|
|
106
|
+
message: "Fiscal ID must be exactly 11 digits",
|
|
107
|
+
code: "FISCAL_ID_INVALID"
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
isValid: errors.length === 0,
|
|
113
|
+
errors
|
|
114
|
+
};
|
|
115
|
+
}, "validateFiscalId");
|
|
116
|
+
var validateZipCode = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name((zipCode) => {
|
|
117
|
+
const errors = [];
|
|
118
|
+
if (!zipCode || zipCode.trim() === "") {
|
|
119
|
+
errors.push({
|
|
120
|
+
field: "zip_code",
|
|
121
|
+
message: "ZIP code is required",
|
|
122
|
+
code: "ZIP_CODE_REQUIRED"
|
|
123
|
+
});
|
|
124
|
+
} else {
|
|
125
|
+
const zipCodeRegex = /^\d{5}$/;
|
|
126
|
+
if (!zipCodeRegex.test(zipCode)) {
|
|
127
|
+
errors.push({
|
|
128
|
+
field: "zip_code",
|
|
129
|
+
message: "ZIP code must be exactly 5 digits",
|
|
130
|
+
code: "ZIP_CODE_INVALID"
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
isValid: errors.length === 0,
|
|
136
|
+
errors
|
|
137
|
+
};
|
|
138
|
+
}, "validateZipCode");
|
|
139
|
+
var validateProvinceCode = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name((province) => {
|
|
140
|
+
const errors = [];
|
|
141
|
+
if (!province || province.trim() === "") {
|
|
142
|
+
errors.push({
|
|
143
|
+
field: "province",
|
|
144
|
+
message: "Province code is required",
|
|
145
|
+
code: "PROVINCE_REQUIRED"
|
|
146
|
+
});
|
|
147
|
+
} else {
|
|
148
|
+
const provinceRegex = /^[A-Z]{2}$/;
|
|
149
|
+
if (!provinceRegex.test(province.toUpperCase())) {
|
|
150
|
+
errors.push({
|
|
151
|
+
field: "province",
|
|
152
|
+
message: "Province code must be exactly 2 letters",
|
|
153
|
+
code: "PROVINCE_INVALID"
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
isValid: errors.length === 0,
|
|
159
|
+
errors
|
|
160
|
+
};
|
|
161
|
+
}, "validateProvinceCode");
|
|
162
|
+
var validateAddress = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name((address) => {
|
|
163
|
+
const errors = [];
|
|
164
|
+
if (!address.street_address || address.street_address.trim() === "") {
|
|
165
|
+
errors.push({
|
|
166
|
+
field: "street_address",
|
|
167
|
+
message: "Street address is required",
|
|
168
|
+
code: "STREET_ADDRESS_REQUIRED"
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
if (!address.city || address.city.trim() === "") {
|
|
172
|
+
errors.push({
|
|
173
|
+
field: "city",
|
|
174
|
+
message: "City is required",
|
|
175
|
+
code: "CITY_REQUIRED"
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
const zipValidation = validateZipCode(address.zip_code);
|
|
179
|
+
errors.push(...zipValidation.errors);
|
|
180
|
+
const provinceValidation = validateProvinceCode(address.province);
|
|
181
|
+
errors.push(...provinceValidation.errors);
|
|
182
|
+
return {
|
|
183
|
+
isValid: errors.length === 0,
|
|
184
|
+
errors
|
|
185
|
+
};
|
|
186
|
+
}, "validateAddress");
|
|
187
|
+
var validateReceiptItem = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name((item) => {
|
|
188
|
+
const errors = [];
|
|
189
|
+
if (!item.quantity) {
|
|
190
|
+
errors.push({
|
|
191
|
+
field: "quantity",
|
|
192
|
+
message: "Quantity is required",
|
|
193
|
+
code: "QUANTITY_REQUIRED"
|
|
194
|
+
});
|
|
195
|
+
} else {
|
|
196
|
+
const quantityRegex = /^\d+\.\d{2}$/;
|
|
197
|
+
if (!quantityRegex.test(item.quantity)) {
|
|
198
|
+
errors.push({
|
|
199
|
+
field: "quantity",
|
|
200
|
+
message: "Quantity must be in format X.XX (e.g., 1.00, 2.50)",
|
|
201
|
+
code: "QUANTITY_INVALID_FORMAT"
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (!item.description || item.description.trim() === "") {
|
|
206
|
+
errors.push({
|
|
207
|
+
field: "description",
|
|
208
|
+
message: "Description is required",
|
|
209
|
+
code: "DESCRIPTION_REQUIRED"
|
|
210
|
+
});
|
|
211
|
+
} else if (item.description.length > 1e3) {
|
|
212
|
+
errors.push({
|
|
213
|
+
field: "description",
|
|
214
|
+
message: "Description must not exceed 1000 characters",
|
|
215
|
+
code: "DESCRIPTION_TOO_LONG"
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
if (!item.unit_price) {
|
|
219
|
+
errors.push({
|
|
220
|
+
field: "unit_price",
|
|
221
|
+
message: "Unit price is required",
|
|
222
|
+
code: "UNIT_PRICE_REQUIRED"
|
|
223
|
+
});
|
|
224
|
+
} else {
|
|
225
|
+
const priceRegex = /^\d+(\.\d{1,8})?$/;
|
|
226
|
+
if (!priceRegex.test(item.unit_price)) {
|
|
227
|
+
errors.push({
|
|
228
|
+
field: "unit_price",
|
|
229
|
+
message: "Unit price must be a valid decimal number with up to 8 decimal places",
|
|
230
|
+
code: "UNIT_PRICE_INVALID_FORMAT"
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
isValid: errors.length === 0,
|
|
236
|
+
errors
|
|
237
|
+
};
|
|
238
|
+
}, "validateReceiptItem");
|
|
239
|
+
var validateMoneyAmount = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name((amount, fieldName, required = false) => {
|
|
240
|
+
const errors = [];
|
|
241
|
+
if (!amount || amount.trim() === "") {
|
|
242
|
+
if (required) {
|
|
243
|
+
errors.push({
|
|
244
|
+
field: fieldName,
|
|
245
|
+
message: `${fieldName} is required`,
|
|
246
|
+
code: `${fieldName.toUpperCase()}_REQUIRED`
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
} else {
|
|
250
|
+
const amountRegex = /^\d+(\.\d{2,8})?$/;
|
|
251
|
+
if (!amountRegex.test(amount)) {
|
|
252
|
+
errors.push({
|
|
253
|
+
field: fieldName,
|
|
254
|
+
message: `${fieldName} must be a valid decimal number with 2-8 decimal places`,
|
|
255
|
+
code: `${fieldName.toUpperCase()}_INVALID_FORMAT`
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return {
|
|
260
|
+
isValid: errors.length === 0,
|
|
261
|
+
errors
|
|
262
|
+
};
|
|
263
|
+
}, "validateMoneyAmount");
|
|
264
|
+
var combineValidationResults = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name((...results) => {
|
|
265
|
+
const allErrors = results.flatMap((result) => result.errors);
|
|
266
|
+
return {
|
|
267
|
+
isValid: allErrors.length === 0,
|
|
268
|
+
errors: allErrors
|
|
269
|
+
};
|
|
270
|
+
}, "combineValidationResults");
|
|
271
|
+
var validateRequired = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name((value, fieldName) => {
|
|
272
|
+
if (value === null || value === void 0 || value === "") {
|
|
273
|
+
return {
|
|
274
|
+
isValid: false,
|
|
275
|
+
errors: [
|
|
276
|
+
{
|
|
277
|
+
field: fieldName,
|
|
278
|
+
message: `${fieldName} is required`,
|
|
279
|
+
code: `${fieldName.toUpperCase()}_REQUIRED`
|
|
280
|
+
}
|
|
281
|
+
]
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
return {
|
|
285
|
+
isValid: true,
|
|
286
|
+
errors: []
|
|
287
|
+
};
|
|
288
|
+
}, "validateRequired");
|
|
289
|
+
|
|
290
|
+
// src/api/auth.ts
|
|
291
|
+
var _AuthenticationError = class _AuthenticationError extends Error {
|
|
292
|
+
constructor(message, code, status) {
|
|
293
|
+
super(message);
|
|
294
|
+
chunkXQKCXG4I_cjs.__publicField(this, "code");
|
|
295
|
+
chunkXQKCXG4I_cjs.__publicField(this, "status");
|
|
296
|
+
this.code = code, this.status = status;
|
|
297
|
+
this.name = "AuthenticationError";
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
chunkXQKCXG4I_cjs.__name(_AuthenticationError, "AuthenticationError");
|
|
301
|
+
var AuthenticationError = _AuthenticationError;
|
|
302
|
+
var validateLoginCredentials = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name((email, password) => {
|
|
303
|
+
const emailValidation = validateEmail(email);
|
|
304
|
+
const passwordValidation = validatePassword(password);
|
|
305
|
+
return {
|
|
306
|
+
isValid: emailValidation.isValid && passwordValidation.isValid,
|
|
307
|
+
errors: [
|
|
308
|
+
...emailValidation.errors,
|
|
309
|
+
...passwordValidation.errors
|
|
310
|
+
]
|
|
311
|
+
};
|
|
312
|
+
}, "validateLoginCredentials");
|
|
313
|
+
var loginProvider = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name(async (email, password) => {
|
|
314
|
+
chunk24ZJ6SNG_cjs.authLogger.info("Attempting provider login", {
|
|
315
|
+
email
|
|
316
|
+
});
|
|
317
|
+
const validation = validateLoginCredentials(email, password);
|
|
318
|
+
if (!validation.isValid) {
|
|
319
|
+
const error = new AuthenticationError("Invalid credentials format", "INVALID_CREDENTIALS_FORMAT");
|
|
320
|
+
chunk24ZJ6SNG_cjs.authLogger.authFailure("provider", error);
|
|
321
|
+
throw error;
|
|
322
|
+
}
|
|
323
|
+
try {
|
|
324
|
+
const client = chunkUVUWF5FV_cjs.getAPIClient();
|
|
325
|
+
const response = await client.post(chunkUVUWF5FV_cjs.MF1_PATHS.LOGIN, {
|
|
326
|
+
username: email,
|
|
327
|
+
password,
|
|
328
|
+
grant_type: "password"
|
|
329
|
+
}, {
|
|
330
|
+
headers: {
|
|
331
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
const tokenData = {
|
|
335
|
+
access_token: response.data.access_token,
|
|
336
|
+
token_type: response.data.token_type,
|
|
337
|
+
expires_in: response.data.expires_in
|
|
338
|
+
};
|
|
339
|
+
await chunk24ZJ6SNG_cjs.SecureTokenStorage.storeToken(tokenData);
|
|
340
|
+
await chunk24ZJ6SNG_cjs.SecureTokenStorage.storeUserInfo(tokenData.access_token);
|
|
341
|
+
chunk24ZJ6SNG_cjs.authLogger.authSuccess("provider", {
|
|
342
|
+
email
|
|
343
|
+
});
|
|
344
|
+
return tokenData;
|
|
345
|
+
} catch (error) {
|
|
346
|
+
const authError = new AuthenticationError(error.response?.data?.detail || "Login failed", "LOGIN_FAILED", error.response?.status);
|
|
347
|
+
chunk24ZJ6SNG_cjs.authLogger.authFailure("provider", authError);
|
|
348
|
+
throw authError;
|
|
349
|
+
}
|
|
350
|
+
}, "loginProvider");
|
|
351
|
+
var loginMerchant = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name(async (email, password) => {
|
|
352
|
+
chunk24ZJ6SNG_cjs.authLogger.info("Attempting merchant login", {
|
|
353
|
+
email
|
|
354
|
+
});
|
|
355
|
+
const validation = validateLoginCredentials(email, password);
|
|
356
|
+
if (!validation.isValid) {
|
|
357
|
+
const error = new AuthenticationError("Invalid credentials format", "INVALID_CREDENTIALS_FORMAT");
|
|
358
|
+
chunk24ZJ6SNG_cjs.authLogger.authFailure("merchant", error);
|
|
359
|
+
throw error;
|
|
360
|
+
}
|
|
361
|
+
try {
|
|
362
|
+
const client = chunkUVUWF5FV_cjs.getAPIClient();
|
|
363
|
+
const response = await client.post(chunkUVUWF5FV_cjs.MF1_PATHS.LOGIN, {
|
|
364
|
+
username: email,
|
|
365
|
+
password,
|
|
366
|
+
grant_type: "password"
|
|
367
|
+
}, {
|
|
368
|
+
headers: {
|
|
369
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
const tokenData = {
|
|
373
|
+
access_token: response.data.access_token,
|
|
374
|
+
token_type: response.data.token_type,
|
|
375
|
+
expires_in: response.data.expires_in
|
|
376
|
+
};
|
|
377
|
+
await chunk24ZJ6SNG_cjs.SecureTokenStorage.storeToken(tokenData);
|
|
378
|
+
await chunk24ZJ6SNG_cjs.SecureTokenStorage.storeUserInfo(tokenData.access_token);
|
|
379
|
+
chunk24ZJ6SNG_cjs.authLogger.authSuccess("merchant", {
|
|
380
|
+
email
|
|
381
|
+
});
|
|
382
|
+
return tokenData;
|
|
383
|
+
} catch (error) {
|
|
384
|
+
const authError = new AuthenticationError(error.response?.data?.detail || "Login failed", "LOGIN_FAILED", error.response?.status);
|
|
385
|
+
chunk24ZJ6SNG_cjs.authLogger.authFailure("merchant", authError);
|
|
386
|
+
throw authError;
|
|
387
|
+
}
|
|
388
|
+
}, "loginMerchant");
|
|
389
|
+
var loginCashier = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name(async (email, password) => {
|
|
390
|
+
chunk24ZJ6SNG_cjs.authLogger.info("Attempting cashier login", {
|
|
391
|
+
email
|
|
392
|
+
});
|
|
393
|
+
const validation = validateLoginCredentials(email, password);
|
|
394
|
+
if (!validation.isValid) {
|
|
395
|
+
const error = new AuthenticationError("Invalid credentials format", "INVALID_CREDENTIALS_FORMAT");
|
|
396
|
+
chunk24ZJ6SNG_cjs.authLogger.authFailure("cashier", error);
|
|
397
|
+
throw error;
|
|
398
|
+
}
|
|
399
|
+
try {
|
|
400
|
+
const client = chunkUVUWF5FV_cjs.getAPIClient();
|
|
401
|
+
const response = await client.post(chunkUVUWF5FV_cjs.MF1_PATHS.LOGIN, {
|
|
402
|
+
username: email,
|
|
403
|
+
password,
|
|
404
|
+
grant_type: "password"
|
|
405
|
+
}, {
|
|
406
|
+
headers: {
|
|
407
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
const tokenData = {
|
|
411
|
+
access_token: response.data.access_token,
|
|
412
|
+
token_type: response.data.token_type,
|
|
413
|
+
expires_in: response.data.expires_in
|
|
414
|
+
};
|
|
415
|
+
await chunk24ZJ6SNG_cjs.SecureTokenStorage.storeToken(tokenData);
|
|
416
|
+
await chunk24ZJ6SNG_cjs.SecureTokenStorage.storeUserInfo(tokenData.access_token);
|
|
417
|
+
chunk24ZJ6SNG_cjs.authLogger.authSuccess("cashier", {
|
|
418
|
+
email
|
|
419
|
+
});
|
|
420
|
+
return tokenData;
|
|
421
|
+
} catch (error) {
|
|
422
|
+
const authError = new AuthenticationError(error.response?.data?.detail || "Login failed", "LOGIN_FAILED", error.response?.status);
|
|
423
|
+
chunk24ZJ6SNG_cjs.authLogger.authFailure("cashier", authError);
|
|
424
|
+
throw authError;
|
|
425
|
+
}
|
|
426
|
+
}, "loginCashier");
|
|
427
|
+
var logout = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name(async () => {
|
|
428
|
+
chunk24ZJ6SNG_cjs.authLogger.info("Logging out user");
|
|
429
|
+
try {
|
|
430
|
+
await chunk24ZJ6SNG_cjs.SecureTokenStorage.removeToken();
|
|
431
|
+
const client = chunkUVUWF5FV_cjs.getAPIClient();
|
|
432
|
+
await client.processOfflineQueue();
|
|
433
|
+
chunk24ZJ6SNG_cjs.authLogger.info("Logout successful");
|
|
434
|
+
} catch (error) {
|
|
435
|
+
chunk24ZJ6SNG_cjs.authLogger.error("Error during logout", error);
|
|
436
|
+
await chunk24ZJ6SNG_cjs.SecureTokenStorage.removeToken();
|
|
437
|
+
}
|
|
438
|
+
}, "logout");
|
|
439
|
+
var isAuthenticated = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name(async () => {
|
|
440
|
+
try {
|
|
441
|
+
const token = await chunk24ZJ6SNG_cjs.SecureTokenStorage.getToken();
|
|
442
|
+
if (!token) {
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
const isValid = await chunk24ZJ6SNG_cjs.SecureTokenStorage.isTokenValid();
|
|
446
|
+
if (!isValid) {
|
|
447
|
+
await chunk24ZJ6SNG_cjs.SecureTokenStorage.removeToken();
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
return true;
|
|
451
|
+
} catch (error) {
|
|
452
|
+
chunk24ZJ6SNG_cjs.authLogger.error("Error checking authentication status", error);
|
|
453
|
+
return false;
|
|
454
|
+
}
|
|
455
|
+
}, "isAuthenticated");
|
|
456
|
+
var getCurrentUser = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name(async () => {
|
|
457
|
+
try {
|
|
458
|
+
const email = await chunk24ZJ6SNG_cjs.SecureTokenStorage.getUserEmail();
|
|
459
|
+
const role = await chunk24ZJ6SNG_cjs.SecureTokenStorage.getUserRole();
|
|
460
|
+
if (!email || !role) {
|
|
461
|
+
return null;
|
|
462
|
+
}
|
|
463
|
+
return {
|
|
464
|
+
email,
|
|
465
|
+
role
|
|
466
|
+
};
|
|
467
|
+
} catch (error) {
|
|
468
|
+
chunk24ZJ6SNG_cjs.authLogger.error("Error getting current user", error);
|
|
469
|
+
return null;
|
|
470
|
+
}
|
|
471
|
+
}, "getCurrentUser");
|
|
472
|
+
var refreshToken = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name(async () => {
|
|
473
|
+
chunk24ZJ6SNG_cjs.authLogger.info("Attempting to refresh token");
|
|
474
|
+
try {
|
|
475
|
+
const isValid = await chunk24ZJ6SNG_cjs.SecureTokenStorage.isTokenValid();
|
|
476
|
+
if (isValid) {
|
|
477
|
+
const token = await chunk24ZJ6SNG_cjs.SecureTokenStorage.getToken();
|
|
478
|
+
if (token) {
|
|
479
|
+
return {
|
|
480
|
+
access_token: token,
|
|
481
|
+
token_type: "Bearer"
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
chunk24ZJ6SNG_cjs.authLogger.warn("Token refresh not available, user needs to re-login");
|
|
486
|
+
return null;
|
|
487
|
+
} catch (error) {
|
|
488
|
+
chunk24ZJ6SNG_cjs.authLogger.error("Token refresh failed", error);
|
|
489
|
+
return null;
|
|
490
|
+
}
|
|
491
|
+
}, "refreshToken");
|
|
492
|
+
var getAuthHeaders = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name(async () => {
|
|
493
|
+
const token = await chunk24ZJ6SNG_cjs.SecureTokenStorage.getToken();
|
|
494
|
+
if (!token || !await chunk24ZJ6SNG_cjs.SecureTokenStorage.isTokenValid()) {
|
|
495
|
+
return {};
|
|
496
|
+
}
|
|
497
|
+
return {
|
|
498
|
+
Authorization: `Bearer ${token}`
|
|
499
|
+
};
|
|
500
|
+
}, "getAuthHeaders");
|
|
501
|
+
var hasRole = /* @__PURE__ */ chunkXQKCXG4I_cjs.__name(async (role) => {
|
|
502
|
+
try {
|
|
503
|
+
const userRole = await chunk24ZJ6SNG_cjs.SecureTokenStorage.getUserRole();
|
|
504
|
+
return userRole === role;
|
|
505
|
+
} catch (error) {
|
|
506
|
+
chunk24ZJ6SNG_cjs.authLogger.error("Error checking user role", error);
|
|
507
|
+
return false;
|
|
508
|
+
}
|
|
509
|
+
}, "hasRole");
|
|
510
|
+
|
|
511
|
+
exports.AuthenticationError = AuthenticationError;
|
|
512
|
+
exports.combineValidationResults = combineValidationResults;
|
|
513
|
+
exports.getAuthHeaders = getAuthHeaders;
|
|
514
|
+
exports.getCurrentUser = getCurrentUser;
|
|
515
|
+
exports.hasRole = hasRole;
|
|
516
|
+
exports.isAuthenticated = isAuthenticated;
|
|
517
|
+
exports.loginCashier = loginCashier;
|
|
518
|
+
exports.loginMerchant = loginMerchant;
|
|
519
|
+
exports.loginProvider = loginProvider;
|
|
520
|
+
exports.logout = logout;
|
|
521
|
+
exports.refreshToken = refreshToken;
|
|
522
|
+
exports.validateAddress = validateAddress;
|
|
523
|
+
exports.validateEmail = validateEmail;
|
|
524
|
+
exports.validateFiscalId = validateFiscalId;
|
|
525
|
+
exports.validateLoginCredentials = validateLoginCredentials;
|
|
526
|
+
exports.validateMoneyAmount = validateMoneyAmount;
|
|
527
|
+
exports.validatePassword = validatePassword;
|
|
528
|
+
exports.validateProvinceCode = validateProvinceCode;
|
|
529
|
+
exports.validateReceiptItem = validateReceiptItem;
|
|
530
|
+
exports.validateRequired = validateRequired;
|
|
531
|
+
exports.validateZipCode = validateZipCode;
|
|
532
|
+
//# sourceMappingURL=chunk-UXVFQRZK.cjs.map
|
|
533
|
+
//# sourceMappingURL=chunk-UXVFQRZK.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/validation.ts","../src/api/auth.ts"],"names":["validateEmail","email","errors","trim","push","field","message","code","emailRegex","test","isValid","length","validatePassword","password","validateFiscalId","fiscalId","fiscalIdRegex","validateZipCode","zipCode","zipCodeRegex","validateProvinceCode","province","provinceRegex","toUpperCase","validateAddress","address","street_address","city","zipValidation","zip_code","provinceValidation","validateReceiptItem","item","quantity","quantityRegex","description","unit_price","priceRegex","validateMoneyAmount","__name","amount","fieldName","required","amountRegex","combineValidationResults","results","allErrors","flatMap","result","validateRequired","value","undefined","AuthenticationError","Error","status","name","validateLoginCredentials","emailValidation","passwordValidation","loginProvider","authLogger","info","validation","error","authFailure","client","getAPIClient","response","post","MF1_PATHS","LOGIN","username","grant_type","headers","tokenData","access_token","data","token_type","expires_in","SecureTokenStorage","storeToken","storeUserInfo","authSuccess","authError","detail","loginMerchant","loginCashier","logout","removeToken","processOfflineQueue","isAuthenticated","token","getToken","isTokenValid","getCurrentUser","getUserEmail","role","getUserRole","refreshToken","warn","getAuthHeaders","Authorization","hasRole","userRole"],"mappings":"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","file":"chunk-UXVFQRZK.cjs","sourcesContent":["// Input validation utilities for A-Cube SDK\n\nexport interface ValidationError {\n field: string;\n message: string;\n code: string;\n}\n\nexport interface ValidationResult {\n isValid: boolean;\n errors: ValidationError[];\n}\n\n/**\n * Email validation\n */\nexport const validateEmail = (email: string): ValidationResult => {\n const errors: ValidationError[] = [];\n \n if (!email || email.trim() === '') {\n errors.push({\n field: 'email',\n message: 'Email is required',\n code: 'EMAIL_REQUIRED'\n });\n } else {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(email)) {\n errors.push({\n field: 'email',\n message: 'Invalid email format',\n code: 'EMAIL_INVALID'\n });\n }\n }\n \n return {\n isValid: errors.length === 0,\n errors\n };\n};\n\n/**\n * Password validation (A-Cube requirements)\n */\nexport const validatePassword = (password: string): ValidationResult => {\n const errors: ValidationError[] = [];\n \n if (!password) {\n errors.push({\n field: 'password',\n message: 'Password is required',\n code: 'PASSWORD_REQUIRED'\n });\n return { isValid: false, errors };\n }\n \n // Minimum length\n if (password.length < 8) {\n errors.push({\n field: 'password',\n message: 'Password must be at least 8 characters long',\n code: 'PASSWORD_TOO_SHORT'\n });\n }\n \n // Maximum length\n if (password.length > 40) {\n errors.push({\n field: 'password',\n message: 'Password must not exceed 40 characters',\n code: 'PASSWORD_TOO_LONG'\n });\n }\n \n // Must contain uppercase letter\n if (!/[A-Z]/.test(password)) {\n errors.push({\n field: 'password',\n message: 'Password must contain at least one uppercase letter',\n code: 'PASSWORD_NO_UPPERCASE'\n });\n }\n \n // Must contain lowercase letter\n if (!/[a-z]/.test(password)) {\n errors.push({\n field: 'password',\n message: 'Password must contain at least one lowercase letter',\n code: 'PASSWORD_NO_LOWERCASE'\n });\n }\n \n // Must contain digit\n if (!/[0-9]/.test(password)) {\n errors.push({\n field: 'password',\n message: 'Password must contain at least one digit',\n code: 'PASSWORD_NO_DIGIT'\n });\n }\n \n // Must contain special character\n if (!/[!@#$%^&*]/.test(password)) {\n errors.push({\n field: 'password',\n message: 'Password must contain at least one special character (!@#$%^&*)',\n code: 'PASSWORD_NO_SPECIAL'\n });\n }\n \n return {\n isValid: errors.length === 0,\n errors\n };\n};\n\n/**\n * Italian fiscal ID validation (Partita IVA)\n */\nexport const validateFiscalId = (fiscalId: string): ValidationResult => {\n const errors: ValidationError[] = [];\n \n if (!fiscalId || fiscalId.trim() === '') {\n errors.push({\n field: 'fiscal_id',\n message: 'Fiscal ID is required',\n code: 'FISCAL_ID_REQUIRED'\n });\n } else {\n // Must be exactly 11 digits\n const fiscalIdRegex = /^\\d{11}$/;\n if (!fiscalIdRegex.test(fiscalId)) {\n errors.push({\n field: 'fiscal_id',\n message: 'Fiscal ID must be exactly 11 digits',\n code: 'FISCAL_ID_INVALID'\n });\n }\n }\n \n return {\n isValid: errors.length === 0,\n errors\n };\n};\n\n/**\n * Italian postal code validation\n */\nexport const validateZipCode = (zipCode: string): ValidationResult => {\n const errors: ValidationError[] = [];\n \n if (!zipCode || zipCode.trim() === '') {\n errors.push({\n field: 'zip_code',\n message: 'ZIP code is required',\n code: 'ZIP_CODE_REQUIRED'\n });\n } else {\n // Must be exactly 5 digits\n const zipCodeRegex = /^\\d{5}$/;\n if (!zipCodeRegex.test(zipCode)) {\n errors.push({\n field: 'zip_code',\n message: 'ZIP code must be exactly 5 digits',\n code: 'ZIP_CODE_INVALID'\n });\n }\n }\n \n return {\n isValid: errors.length === 0,\n errors\n };\n};\n\n/**\n * Italian province code validation\n */\nexport const validateProvinceCode = (province: string): ValidationResult => {\n const errors: ValidationError[] = [];\n \n if (!province || province.trim() === '') {\n errors.push({\n field: 'province',\n message: 'Province code is required',\n code: 'PROVINCE_REQUIRED'\n });\n } else {\n // Must be exactly 2 letters\n const provinceRegex = /^[A-Z]{2}$/;\n if (!provinceRegex.test(province.toUpperCase())) {\n errors.push({\n field: 'province',\n message: 'Province code must be exactly 2 letters',\n code: 'PROVINCE_INVALID'\n });\n }\n }\n \n return {\n isValid: errors.length === 0,\n errors\n };\n};\n\n/**\n * Address validation\n */\nexport const validateAddress = (address: {\n street_address: string;\n zip_code: string;\n city: string;\n province: string;\n}): ValidationResult => {\n const errors: ValidationError[] = [];\n \n // Street address\n if (!address.street_address || address.street_address.trim() === '') {\n errors.push({\n field: 'street_address',\n message: 'Street address is required',\n code: 'STREET_ADDRESS_REQUIRED'\n });\n }\n \n // City\n if (!address.city || address.city.trim() === '') {\n errors.push({\n field: 'city',\n message: 'City is required',\n code: 'CITY_REQUIRED'\n });\n }\n \n // ZIP code\n const zipValidation = validateZipCode(address.zip_code);\n errors.push(...zipValidation.errors);\n \n // Province\n const provinceValidation = validateProvinceCode(address.province);\n errors.push(...provinceValidation.errors);\n \n return {\n isValid: errors.length === 0,\n errors\n };\n};\n\n/**\n * Receipt item validation\n */\nexport const validateReceiptItem = (item: {\n quantity: string;\n description: string;\n unit_price: string;\n}): ValidationResult => {\n const errors: ValidationError[] = [];\n \n // Quantity validation\n if (!item.quantity) {\n errors.push({\n field: 'quantity',\n message: 'Quantity is required',\n code: 'QUANTITY_REQUIRED'\n });\n } else {\n const quantityRegex = /^\\d+\\.\\d{2}$/;\n if (!quantityRegex.test(item.quantity)) {\n errors.push({\n field: 'quantity',\n message: 'Quantity must be in format X.XX (e.g., 1.00, 2.50)',\n code: 'QUANTITY_INVALID_FORMAT'\n });\n }\n }\n \n // Description validation\n if (!item.description || item.description.trim() === '') {\n errors.push({\n field: 'description',\n message: 'Description is required',\n code: 'DESCRIPTION_REQUIRED'\n });\n } else if (item.description.length > 1000) {\n errors.push({\n field: 'description',\n message: 'Description must not exceed 1000 characters',\n code: 'DESCRIPTION_TOO_LONG'\n });\n }\n \n // Unit price validation\n if (!item.unit_price) {\n errors.push({\n field: 'unit_price',\n message: 'Unit price is required',\n code: 'UNIT_PRICE_REQUIRED'\n });\n } else {\n const priceRegex = /^\\d+(\\.\\d{1,8})?$/;\n if (!priceRegex.test(item.unit_price)) {\n errors.push({\n field: 'unit_price',\n message: 'Unit price must be a valid decimal number with up to 8 decimal places',\n code: 'UNIT_PRICE_INVALID_FORMAT'\n });\n }\n }\n \n return {\n isValid: errors.length === 0,\n errors\n };\n};\n\n/**\n * Money amount validation (for payments, discounts, etc.)\n */\nexport const validateMoneyAmount = (\n amount: string,\n fieldName: string,\n required: boolean = false\n): ValidationResult => {\n const errors: ValidationError[] = [];\n \n if (!amount || amount.trim() === '') {\n if (required) {\n errors.push({\n field: fieldName,\n message: `${fieldName} is required`,\n code: `${fieldName.toUpperCase()}_REQUIRED`\n });\n }\n } else {\n const amountRegex = /^\\d+(\\.\\d{2,8})?$/;\n if (!amountRegex.test(amount)) {\n errors.push({\n field: fieldName,\n message: `${fieldName} must be a valid decimal number with 2-8 decimal places`,\n code: `${fieldName.toUpperCase()}_INVALID_FORMAT`\n });\n }\n }\n \n return {\n isValid: errors.length === 0,\n errors\n };\n};\n\n/**\n * Combine multiple validation results\n */\nexport const combineValidationResults = (...results: ValidationResult[]): ValidationResult => {\n const allErrors = results.flatMap(result => result.errors);\n \n return {\n isValid: allErrors.length === 0,\n errors: allErrors\n };\n};\n\n/**\n * Generic field validation\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const validateRequired = (value: any, fieldName: string): ValidationResult => {\n if (value === null || value === undefined || value === '') {\n return {\n isValid: false,\n errors: [{\n field: fieldName,\n message: `${fieldName} is required`,\n code: `${fieldName.toUpperCase()}_REQUIRED`\n }]\n };\n }\n \n return { isValid: true, errors: [] };\n};","import { getAPIClient } from './client';\nimport { SecureTokenStorage } from '../storage/token';\nimport { MF1_PATHS } from '../constants/endpoints';\nimport { AuthToken } from './types.generated';\nimport { ValidationResult, validateEmail, validatePassword } from '../utils/validation';\nimport { authLogger } from '../utils/logger';\n\nexport interface LoginResponse {\n access_token: string;\n token_type: string;\n expires_in?: number;\n}\n\nexport class AuthenticationError extends Error {\n constructor(\n message: string,\n public code: string,\n public status?: number\n ) {\n super(message);\n this.name = 'AuthenticationError';\n }\n}\n\n/**\n * Validate login credentials\n */\nexport const validateLoginCredentials = (email: string, password: string): ValidationResult => {\n const emailValidation = validateEmail(email);\n const passwordValidation = validatePassword(password);\n \n return {\n isValid: emailValidation.isValid && passwordValidation.isValid,\n errors: [...emailValidation.errors, ...passwordValidation.errors],\n };\n};\n\n/**\n * Login as Provider (MF2 system)\n */\nexport const loginProvider = async (email: string, password: string): Promise<AuthToken> => {\n authLogger.info('Attempting provider login', { email });\n \n // Validate credentials\n const validation = validateLoginCredentials(email, password);\n if (!validation.isValid) {\n const error = new AuthenticationError(\n 'Invalid credentials format',\n 'INVALID_CREDENTIALS_FORMAT'\n );\n authLogger.authFailure('provider', error);\n throw error;\n }\n\n try {\n const client = getAPIClient();\n const response = await client.post<LoginResponse>(MF1_PATHS.LOGIN, {\n username: email, // OAuth2 password flow uses 'username' field\n password,\n grant_type: 'password',\n }, {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n });\n\n const tokenData: AuthToken = {\n access_token: response.data.access_token,\n token_type: response.data.token_type,\n expires_in: response.data.expires_in,\n };\n\n // Store token securely\n await SecureTokenStorage.storeToken(tokenData);\n await SecureTokenStorage.storeUserInfo(tokenData.access_token);\n\n authLogger.authSuccess('provider', { email });\n return tokenData;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n const authError = new AuthenticationError(\n error.response?.data?.detail || 'Login failed',\n 'LOGIN_FAILED',\n error.response?.status\n );\n \n authLogger.authFailure('provider', authError);\n throw authError;\n }\n};\n\n/**\n * Login as Merchant (MF1 system)\n */\nexport const loginMerchant = async (email: string, password: string): Promise<AuthToken> => {\n authLogger.info('Attempting merchant login', { email });\n \n // Validate credentials\n const validation = validateLoginCredentials(email, password);\n if (!validation.isValid) {\n const error = new AuthenticationError(\n 'Invalid credentials format',\n 'INVALID_CREDENTIALS_FORMAT'\n );\n authLogger.authFailure('merchant', error);\n throw error;\n }\n\n try {\n const client = getAPIClient();\n const response = await client.post<LoginResponse>(MF1_PATHS.LOGIN, {\n username: email, // OAuth2 password flow uses 'username' field\n password,\n grant_type: 'password',\n }, {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n });\n\n const tokenData: AuthToken = {\n access_token: response.data.access_token,\n token_type: response.data.token_type,\n expires_in: response.data.expires_in,\n };\n\n // Store token securely\n await SecureTokenStorage.storeToken(tokenData);\n await SecureTokenStorage.storeUserInfo(tokenData.access_token);\n\n authLogger.authSuccess('merchant', { email });\n return tokenData;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n const authError = new AuthenticationError(\n error.response?.data?.detail || 'Login failed',\n 'LOGIN_FAILED',\n error.response?.status\n );\n \n authLogger.authFailure('merchant', authError);\n throw authError;\n }\n};\n\n/**\n * Login as Cashier (MF1 system)\n */\nexport const loginCashier = async (email: string, password: string): Promise<AuthToken> => {\n authLogger.info('Attempting cashier login', { email });\n \n // Validate credentials\n const validation = validateLoginCredentials(email, password);\n if (!validation.isValid) {\n const error = new AuthenticationError(\n 'Invalid credentials format',\n 'INVALID_CREDENTIALS_FORMAT'\n );\n authLogger.authFailure('cashier', error);\n throw error;\n }\n\n try {\n const client = getAPIClient();\n const response = await client.post<LoginResponse>(MF1_PATHS.LOGIN, {\n username: email, // OAuth2 password flow uses 'username' field\n password,\n grant_type: 'password',\n }, {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n });\n\n const tokenData: AuthToken = {\n access_token: response.data.access_token,\n token_type: response.data.token_type,\n expires_in: response.data.expires_in,\n };\n\n // Store token securely\n await SecureTokenStorage.storeToken(tokenData);\n await SecureTokenStorage.storeUserInfo(tokenData.access_token);\n\n authLogger.authSuccess('cashier', { email });\n return tokenData;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n const authError = new AuthenticationError(\n error.response?.data?.detail || 'Login failed',\n 'LOGIN_FAILED',\n error.response?.status\n );\n \n authLogger.authFailure('cashier', authError);\n throw authError;\n }\n};\n\n/**\n * Logout user and clear all authentication data\n */\nexport const logout = async (): Promise<void> => {\n authLogger.info('Logging out user');\n \n try {\n // Clear all stored authentication data\n await SecureTokenStorage.removeToken();\n \n // Process any pending offline requests before logout\n const client = getAPIClient();\n await client.processOfflineQueue();\n \n authLogger.info('Logout successful');\n } catch (error) {\n authLogger.error('Error during logout', error);\n // Still clear token even if other operations fail\n await SecureTokenStorage.removeToken();\n }\n};\n\n/**\n * Check if user is currently authenticated\n */\nexport const isAuthenticated = async (): Promise<boolean> => {\n try {\n const token = await SecureTokenStorage.getToken();\n if (!token) {\n return false;\n }\n\n const isValid = await SecureTokenStorage.isTokenValid();\n if (!isValid) {\n // Clean up expired token\n await SecureTokenStorage.removeToken();\n return false;\n }\n\n return true;\n } catch (error) {\n authLogger.error('Error checking authentication status', error);\n return false;\n }\n};\n\n/**\n * Get current user information from stored token\n */\nexport const getCurrentUser = async (): Promise<{\n email: string;\n role: string;\n} | null> => {\n try {\n const email = await SecureTokenStorage.getUserEmail();\n const role = await SecureTokenStorage.getUserRole();\n \n if (!email || !role) {\n return null;\n }\n\n return { email, role };\n } catch (error) {\n authLogger.error('Error getting current user', error);\n return null;\n }\n};\n\n/**\n * Refresh authentication token (if refresh token is available)\n */\nexport const refreshToken = async (): Promise<AuthToken | null> => {\n authLogger.info('Attempting to refresh token');\n \n try {\n // Note: The current API spec doesn't show refresh token endpoint\n // This is a placeholder for future implementation\n \n // For now, we'll check if current token is still valid\n const isValid = await SecureTokenStorage.isTokenValid();\n if (isValid) {\n const token = await SecureTokenStorage.getToken();\n if (token) {\n return {\n access_token: token,\n token_type: 'Bearer',\n };\n }\n }\n\n authLogger.warn('Token refresh not available, user needs to re-login');\n return null;\n } catch (error) {\n authLogger.error('Token refresh failed', error);\n return null;\n }\n};\n\n/**\n * Get authentication headers for API requests\n */\nexport const getAuthHeaders = async (): Promise<Record<string, string>> => {\n const token = await SecureTokenStorage.getToken();\n \n if (!token || !await SecureTokenStorage.isTokenValid()) {\n return {};\n }\n\n return {\n Authorization: `Bearer ${token}`,\n };\n};\n\n/**\n * Check if current user has specific role\n */\nexport const hasRole = async (role: string): Promise<boolean> => {\n try {\n const userRole = await SecureTokenStorage.getUserRole();\n return userRole === role;\n } catch (error) {\n authLogger.error('Error checking user role', error);\n return false;\n }\n};"]}
|