@lucaapp/service-utils 2.0.9 → 4.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/dist/index.d.ts CHANGED
@@ -11,4 +11,9 @@ export * from './lib/wsEvent';
11
11
  export * from './lib/lifecycle';
12
12
  export * from './lib/logger';
13
13
  export * from './lib/datetime';
14
+ export * from './lib/proxy';
15
+ export * from './lib/random';
16
+ export * from './lib/crypto';
17
+ export * from './lib/phone';
18
+ export * from './lib/http';
14
19
  export * from './types';
package/dist/index.js CHANGED
@@ -27,4 +27,9 @@ __exportStar(require("./lib/wsEvent"), exports);
27
27
  __exportStar(require("./lib/lifecycle"), exports);
28
28
  __exportStar(require("./lib/logger"), exports);
29
29
  __exportStar(require("./lib/datetime"), exports);
30
+ __exportStar(require("./lib/proxy"), exports);
31
+ __exportStar(require("./lib/random"), exports);
32
+ __exportStar(require("./lib/crypto"), exports);
33
+ __exportStar(require("./lib/phone"), exports);
34
+ __exportStar(require("./lib/http"), exports);
30
35
  __exportStar(require("./types"), exports);
@@ -0,0 +1,46 @@
1
+ import crypto from 'crypto';
2
+ /**
3
+ * Hash a password using scrypt with a salt
4
+ * @param password - The password to hash
5
+ * @param salt - The salt to use for hashing
6
+ * @returns A promise that resolves to the hashed password as a Buffer
7
+ */
8
+ export declare const hashPassword: (password: string, salt: string) => Promise<Buffer>;
9
+ /**
10
+ * Generate a pseudo hash for testing or placeholder purposes
11
+ * @returns A promise that resolves to a pseudo hash as a Buffer
12
+ */
13
+ export declare const pseudoHashPassword: () => Promise<Buffer>;
14
+ /**
15
+ * Create a SHA-256 hash of the input data
16
+ * @param data - The data to hash
17
+ * @returns The SHA-256 hash as a hexadecimal string
18
+ */
19
+ export declare const sha256: (data: string) => string;
20
+ /**
21
+ * Create a SHA-256 hash of multiple data pieces concatenated
22
+ * @param dataArray - Array of strings to concatenate and hash
23
+ * @returns The concatenated SHA-256 hash as a hexadecimal string
24
+ */
25
+ export declare const concatSha256: (dataArray: string[]) => string;
26
+ /**
27
+ * Create an MD5 hash of the input data
28
+ * @param data - The data to hash
29
+ * @returns The MD5 hash as a hexadecimal string
30
+ */
31
+ export declare const md5: (data: string) => string;
32
+ /**
33
+ * Create an HMAC-SHA256 hash
34
+ * @param data - The data to hash
35
+ * @param key - The secret key for HMAC
36
+ * @returns The HMAC-SHA256 hash as a hexadecimal string
37
+ */
38
+ export declare const hmacSha256: (data: string, key: string) => string;
39
+ /**
40
+ * Create a hash with custom algorithm and encoding
41
+ * @param data - The data to hash
42
+ * @param algorithm - The hash algorithm to use (e.g., 'sha256', 'md5', 'sha1')
43
+ * @param encoding - The output encoding ('hex', 'base64', 'binary')
44
+ * @returns The hash in the specified encoding
45
+ */
46
+ export declare const createHash: (data: string, algorithm?: string, encoding?: crypto.BinaryToTextEncoding) => string;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createHash = exports.hmacSha256 = exports.md5 = exports.concatSha256 = exports.sha256 = exports.pseudoHashPassword = exports.hashPassword = void 0;
7
+ const crypto_1 = __importDefault(require("crypto"));
8
+ const util_1 = require("util");
9
+ const scrypt = (0, util_1.promisify)(crypto_1.default.scrypt);
10
+ const KEY_LENGTH = 64;
11
+ /**
12
+ * Hash a password using scrypt with a salt
13
+ * @param password - The password to hash
14
+ * @param salt - The salt to use for hashing
15
+ * @returns A promise that resolves to the hashed password as a Buffer
16
+ */
17
+ const hashPassword = async (password, salt) => {
18
+ const hash = await scrypt(password, salt, KEY_LENGTH);
19
+ return hash;
20
+ };
21
+ exports.hashPassword = hashPassword;
22
+ /**
23
+ * Generate a pseudo hash for testing or placeholder purposes
24
+ * @returns A promise that resolves to a pseudo hash as a Buffer
25
+ */
26
+ const pseudoHashPassword = async () => {
27
+ const hash = await scrypt('pseudo', 'pseudo', KEY_LENGTH);
28
+ return hash;
29
+ };
30
+ exports.pseudoHashPassword = pseudoHashPassword;
31
+ /**
32
+ * Create a SHA-256 hash of the input data
33
+ * @param data - The data to hash
34
+ * @returns The SHA-256 hash as a hexadecimal string
35
+ */
36
+ const sha256 = (data) => {
37
+ const hash = crypto_1.default.createHash('sha256');
38
+ hash.update(data);
39
+ return hash.digest('hex');
40
+ };
41
+ exports.sha256 = sha256;
42
+ /**
43
+ * Create a SHA-256 hash of multiple data pieces concatenated
44
+ * @param dataArray - Array of strings to concatenate and hash
45
+ * @returns The concatenated SHA-256 hash as a hexadecimal string
46
+ */
47
+ const concatSha256 = (dataArray) => {
48
+ let result = '';
49
+ dataArray.forEach(data => {
50
+ const hash = crypto_1.default.createHash('sha256');
51
+ hash.update(data);
52
+ result += hash.digest('hex');
53
+ });
54
+ return result;
55
+ };
56
+ exports.concatSha256 = concatSha256;
57
+ /**
58
+ * Create an MD5 hash of the input data
59
+ * @param data - The data to hash
60
+ * @returns The MD5 hash as a hexadecimal string
61
+ */
62
+ const md5 = (data) => {
63
+ const hash = crypto_1.default.createHash('md5');
64
+ hash.update(data);
65
+ return hash.digest('hex');
66
+ };
67
+ exports.md5 = md5;
68
+ /**
69
+ * Create an HMAC-SHA256 hash
70
+ * @param data - The data to hash
71
+ * @param key - The secret key for HMAC
72
+ * @returns The HMAC-SHA256 hash as a hexadecimal string
73
+ */
74
+ const hmacSha256 = (data, key) => {
75
+ const hmac = crypto_1.default.createHmac('sha256', key);
76
+ hmac.update(data);
77
+ return hmac.digest('hex');
78
+ };
79
+ exports.hmacSha256 = hmacSha256;
80
+ /**
81
+ * Create a hash with custom algorithm and encoding
82
+ * @param data - The data to hash
83
+ * @param algorithm - The hash algorithm to use (e.g., 'sha256', 'md5', 'sha1')
84
+ * @param encoding - The output encoding ('hex', 'base64', 'binary')
85
+ * @returns The hash in the specified encoding
86
+ */
87
+ const createHash = (data, algorithm = 'sha256', encoding = 'hex') => {
88
+ const hash = crypto_1.default.createHash(algorithm);
89
+ hash.update(data);
90
+ return hash.digest(encoding);
91
+ };
92
+ exports.createHash = createHash;
@@ -0,0 +1 @@
1
+ export * from './hash';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./hash"), exports);
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Converts a Date object or string to ISO date format (YYYY-MM-DD)
3
+ * Returns undefined if the input is null, undefined, or invalid
4
+ */
5
+ export declare const toISODateString: (date: Date | string | null | undefined) => string | undefined;
6
+ /**
7
+ * Converts an ISO date string to a Date object
8
+ * Returns undefined if the input is null, undefined, or invalid
9
+ */
10
+ export declare const toDateObject: (date: string | null | undefined) => Date | undefined;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.toDateObject = exports.toISODateString = void 0;
7
+ const moment_1 = __importDefault(require("moment"));
8
+ const DATE_FORMAT_ISO = 'YYYY-MM-DD';
9
+ /**
10
+ * Converts a Date object or string to ISO date format (YYYY-MM-DD)
11
+ * Returns undefined if the input is null, undefined, or invalid
12
+ */
13
+ const toISODateString = (date) => {
14
+ if (!date)
15
+ return undefined;
16
+ const momentDate = (0, moment_1.default)(date);
17
+ if (!momentDate.isValid())
18
+ return undefined;
19
+ return momentDate.format(DATE_FORMAT_ISO);
20
+ };
21
+ exports.toISODateString = toISODateString;
22
+ /**
23
+ * Converts an ISO date string to a Date object
24
+ * Returns undefined if the input is null, undefined, or invalid
25
+ */
26
+ const toDateObject = (date) => {
27
+ if (!date)
28
+ return undefined;
29
+ const momentDate = (0, moment_1.default)(date);
30
+ if (!momentDate.isValid())
31
+ return undefined;
32
+ return momentDate.toDate();
33
+ };
34
+ exports.toDateObject = toDateObject;
@@ -1 +1,2 @@
1
1
  export * from './datetime';
2
+ export * from './dateConversion';
@@ -15,3 +15,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./datetime"), exports);
18
+ __exportStar(require("./dateConversion"), exports);
@@ -0,0 +1,66 @@
1
+ import { AxiosError, AxiosInstance, AxiosInterceptorManager, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
2
+ /**
3
+ * Logger interface for axios utilities
4
+ * Services should provide their own logger implementation
5
+ */
6
+ export interface AxiosLogger {
7
+ trace(obj: unknown, message: string): void;
8
+ error(obj: unknown, message: string): void;
9
+ warn(obj: unknown, message: string): void;
10
+ }
11
+ /**
12
+ * Configuration options for creating axios clients
13
+ */
14
+ export interface AxiosClientConfig {
15
+ proxy?: false;
16
+ timeout?: number;
17
+ baseURL?: string;
18
+ headers?: Record<string, string>;
19
+ }
20
+ /**
21
+ * Handle axios errors with proper logging
22
+ * @param axiosError - The axios error to handle
23
+ * @param logger - Logger instance for error reporting
24
+ */
25
+ export declare const handleAxiosError: (axiosError: AxiosError, logger: AxiosLogger) => void;
26
+ /**
27
+ * Create logging interceptors for axios instances
28
+ * @param name - Name identifier for the client (used in logs)
29
+ * @param logger - Logger instance for request/response logging
30
+ * @returns Object containing request and response interceptors
31
+ */
32
+ export declare const createLoggingInterceptors: (name: string, logger: AxiosLogger) => {
33
+ request: Parameters<AxiosInterceptorManager<InternalAxiosRequestConfig>["use"]>;
34
+ response: Parameters<AxiosInterceptorManager<AxiosResponse>["use"]>;
35
+ };
36
+ /**
37
+ * Create a configured axios client with optional logging
38
+ * @param config - Configuration options for the axios client
39
+ * @param logger - Optional logger for request/response logging
40
+ * @param clientName - Optional name for the client (used in logs)
41
+ * @returns Configured axios instance
42
+ */
43
+ export declare const createAxiosClient: (config?: AxiosClientConfig, logger?: AxiosLogger, clientName?: string) => AxiosInstance;
44
+ /**
45
+ * Create a default axios client with proxy disabled
46
+ * @param logger - Optional logger for request/response logging
47
+ * @param clientName - Optional name for the client (used in logs)
48
+ * @returns Default configured axios instance
49
+ */
50
+ export declare const createDefaultAxiosClient: (logger?: AxiosLogger, clientName?: string) => AxiosInstance;
51
+ /**
52
+ * Create an axios client with timeout configuration
53
+ * @param timeout - Timeout in milliseconds
54
+ * @param logger - Optional logger for request/response logging
55
+ * @param clientName - Optional name for the client (used in logs)
56
+ * @returns Configured axios instance with timeout
57
+ */
58
+ export declare const createAxiosClientWithTimeout: (timeout: number, logger?: AxiosLogger, clientName?: string) => AxiosInstance;
59
+ /**
60
+ * Add logging interceptors to an existing axios instance
61
+ * @param client - Existing axios instance
62
+ * @param logger - Logger instance for request/response logging
63
+ * @param clientName - Name identifier for the client (used in logs)
64
+ * @returns The same axios instance with logging interceptors added
65
+ */
66
+ export declare const addLoggingToAxiosClient: (client: AxiosInstance, logger: AxiosLogger, clientName?: string) => AxiosInstance;
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.addLoggingToAxiosClient = exports.createAxiosClientWithTimeout = exports.createDefaultAxiosClient = exports.createAxiosClient = exports.createLoggingInterceptors = exports.handleAxiosError = void 0;
7
+ const boom_1 = require("@hapi/boom");
8
+ const axios_1 = __importDefault(require("axios"));
9
+ /**
10
+ * Handle axios errors with proper logging
11
+ * @param axiosError - The axios error to handle
12
+ * @param logger - Logger instance for error reporting
13
+ */
14
+ const handleAxiosError = (axiosError, logger) => {
15
+ const { response } = axiosError;
16
+ const message = response?.data
17
+ ? JSON.stringify(response.data)
18
+ : JSON.stringify(axiosError);
19
+ logger.error({ axiosError }, `Axios API Response: ${message}`);
20
+ };
21
+ exports.handleAxiosError = handleAxiosError;
22
+ /**
23
+ * Serialize request for logging purposes
24
+ * @param config - Axios request configuration
25
+ * @returns Serialized request object
26
+ */
27
+ const serializeRequest = ({ headers, method, url, }) => ({ method, url, headers });
28
+ /**
29
+ * Create logging interceptors for axios instances
30
+ * @param name - Name identifier for the client (used in logs)
31
+ * @param logger - Logger instance for request/response logging
32
+ * @returns Object containing request and response interceptors
33
+ */
34
+ const createLoggingInterceptors = (name, logger) => ({
35
+ request: [
36
+ request => {
37
+ logger.trace({ request: serializeRequest(request) }, `[${name}] -> ${request.method?.toUpperCase()} ${request.url}`);
38
+ return request;
39
+ },
40
+ rawError => {
41
+ const error = (0, boom_1.boomify)(rawError);
42
+ logger.error(error, `[${name}] Request error: ${error.message}`);
43
+ return Promise.reject(rawError);
44
+ },
45
+ ],
46
+ response: [
47
+ response => {
48
+ const { status, headers, config: request, data } = response;
49
+ logger.trace({
50
+ response: {
51
+ status,
52
+ headers,
53
+ body: data,
54
+ },
55
+ request: serializeRequest(request),
56
+ }, `[${name}] <- ${status} ${request.method?.toUpperCase()} ${request.url}`);
57
+ return response;
58
+ },
59
+ rawError => {
60
+ const error = (0, boom_1.boomify)(rawError);
61
+ if (error.response) {
62
+ logger.error({ err: error, responseData: error.response.data }, `[${name}] <- ${error.response.status} ${error.config?.method?.toUpperCase()} ${error.config?.url}`);
63
+ }
64
+ else {
65
+ logger.error({ err: error }, `[${name}] Response error: ${error.message}`);
66
+ }
67
+ return Promise.reject(rawError);
68
+ },
69
+ ],
70
+ });
71
+ exports.createLoggingInterceptors = createLoggingInterceptors;
72
+ /**
73
+ * Create a configured axios client with optional logging
74
+ * @param config - Configuration options for the axios client
75
+ * @param logger - Optional logger for request/response logging
76
+ * @param clientName - Optional name for the client (used in logs)
77
+ * @returns Configured axios instance
78
+ */
79
+ const createAxiosClient = (config = {}, logger, clientName = 'Default Client') => {
80
+ const { proxy = false, timeout, baseURL, headers, ...restConfig } = config;
81
+ const client = axios_1.default.create({
82
+ proxy,
83
+ timeout,
84
+ baseURL,
85
+ headers,
86
+ ...restConfig,
87
+ });
88
+ // Add logging interceptors if logger is provided
89
+ if (logger) {
90
+ const loggingInterceptors = (0, exports.createLoggingInterceptors)(clientName, logger);
91
+ client.interceptors.request.use(...loggingInterceptors.request);
92
+ client.interceptors.response.use(...loggingInterceptors.response);
93
+ }
94
+ return client;
95
+ };
96
+ exports.createAxiosClient = createAxiosClient;
97
+ /**
98
+ * Create a default axios client with proxy disabled
99
+ * @param logger - Optional logger for request/response logging
100
+ * @param clientName - Optional name for the client (used in logs)
101
+ * @returns Default configured axios instance
102
+ */
103
+ const createDefaultAxiosClient = (logger, clientName = 'Default Client') => {
104
+ return (0, exports.createAxiosClient)({ proxy: false }, logger, clientName);
105
+ };
106
+ exports.createDefaultAxiosClient = createDefaultAxiosClient;
107
+ /**
108
+ * Create an axios client with timeout configuration
109
+ * @param timeout - Timeout in milliseconds
110
+ * @param logger - Optional logger for request/response logging
111
+ * @param clientName - Optional name for the client (used in logs)
112
+ * @returns Configured axios instance with timeout
113
+ */
114
+ const createAxiosClientWithTimeout = (timeout, logger, clientName = 'Timeout Client') => {
115
+ return (0, exports.createAxiosClient)({ proxy: false, timeout }, logger, clientName);
116
+ };
117
+ exports.createAxiosClientWithTimeout = createAxiosClientWithTimeout;
118
+ /**
119
+ * Add logging interceptors to an existing axios instance
120
+ * @param client - Existing axios instance
121
+ * @param logger - Logger instance for request/response logging
122
+ * @param clientName - Name identifier for the client (used in logs)
123
+ * @returns The same axios instance with logging interceptors added
124
+ */
125
+ const addLoggingToAxiosClient = (client, logger, clientName = 'Client') => {
126
+ const loggingInterceptors = (0, exports.createLoggingInterceptors)(clientName, logger);
127
+ client.interceptors.request.use(...loggingInterceptors.request);
128
+ client.interceptors.response.use(...loggingInterceptors.response);
129
+ return client;
130
+ };
131
+ exports.addLoggingToAxiosClient = addLoggingToAxiosClient;
@@ -0,0 +1 @@
1
+ export * from './axios';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./axios"), exports);
@@ -0,0 +1 @@
1
+ export * from './phone';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./phone"), exports);
@@ -0,0 +1,65 @@
1
+ import { PhoneNumber } from 'libphonenumber-js/max';
2
+ /**
3
+ * Output format options for phone numbers
4
+ */
5
+ export declare enum OutputFormat {
6
+ International = "international",
7
+ E164 = "E.164",
8
+ National = "national"
9
+ }
10
+ /**
11
+ * Validate if a phone number is valid for Germany
12
+ * @param value - The phone number string to validate
13
+ * @returns True if the phone number is valid and from Germany
14
+ */
15
+ export declare const isValidPhoneNumber: (value: string) => boolean;
16
+ /**
17
+ * Validate if a phone number is a valid German mobile number
18
+ * @param value - The phone number string to validate
19
+ * @returns True if the phone number is a valid German mobile number
20
+ */
21
+ export declare const isValidMobilePhoneNumber: (value: string) => boolean;
22
+ /**
23
+ * Format a phone number to E.164 format
24
+ * @param phone - The phone number string to format
25
+ * @returns The formatted phone number in E.164 format or undefined if invalid
26
+ */
27
+ export declare const getFormattedPhoneNumber: (phone: string) => string | undefined;
28
+ /**
29
+ * Try to parse and format a phone number with error handling
30
+ * @param phone - The phone number string to parse
31
+ * @param outputFormat - The desired output format (defaults to E.164)
32
+ * @returns The formatted phone number or undefined if parsing fails
33
+ */
34
+ export declare const tryParsePhoneNumber: (phone?: string, outputFormat?: OutputFormat) => string | undefined;
35
+ /**
36
+ * Format phone number for international display (used in backend/format.ts pattern)
37
+ * @param phone - The phone number string, null, or undefined
38
+ * @returns Formatted international phone number, or the original value if null/undefined
39
+ */
40
+ export declare const formatPhoneNumber: (phone: string | undefined | null) => string | undefined | null;
41
+ /**
42
+ * Parse a phone number and return the PhoneNumber object
43
+ * @param phone - The phone number string to parse
44
+ * @param defaultCountry - The default country code (defaults to 'DE')
45
+ * @returns The parsed PhoneNumber object or undefined if invalid
46
+ */
47
+ export declare const parsePhone: (phone: string, defaultCountry?: string) => PhoneNumber | undefined;
48
+ /**
49
+ * Get the country code from a phone number
50
+ * @param phone - The phone number string
51
+ * @returns The country code or undefined if parsing fails
52
+ */
53
+ export declare const getPhoneCountry: (phone: string) => string | undefined;
54
+ /**
55
+ * Get the phone number type (mobile, landline, etc.)
56
+ * @param phone - The phone number string
57
+ * @returns The phone number type or undefined if parsing fails
58
+ */
59
+ export declare const getPhoneType: (phone: string) => string | undefined;
60
+ /**
61
+ * Normalize a phone number by removing spaces and formatting
62
+ * @param phone - The phone number string
63
+ * @returns The normalized phone number or undefined if invalid
64
+ */
65
+ export declare const normalizePhoneNumber: (phone: string) => string | undefined;
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.normalizePhoneNumber = exports.getPhoneType = exports.getPhoneCountry = exports.parsePhone = exports.formatPhoneNumber = exports.tryParsePhoneNumber = exports.getFormattedPhoneNumber = exports.isValidMobilePhoneNumber = exports.isValidPhoneNumber = exports.OutputFormat = void 0;
27
+ const max_1 = __importStar(require("libphonenumber-js/max"));
28
+ /**
29
+ * Output format options for phone numbers
30
+ */
31
+ var OutputFormat;
32
+ (function (OutputFormat) {
33
+ OutputFormat["International"] = "international";
34
+ OutputFormat["E164"] = "E.164";
35
+ OutputFormat["National"] = "national";
36
+ })(OutputFormat || (exports.OutputFormat = OutputFormat = {}));
37
+ /**
38
+ * Validate if a phone number is valid for Germany
39
+ * @param value - The phone number string to validate
40
+ * @returns True if the phone number is valid and from Germany
41
+ */
42
+ const isValidPhoneNumber = (value) => {
43
+ const parsedNumber = (0, max_1.default)(value, 'DE');
44
+ return !!parsedNumber?.isValid() && parsedNumber?.country === 'DE';
45
+ };
46
+ exports.isValidPhoneNumber = isValidPhoneNumber;
47
+ /**
48
+ * Validate if a phone number is a valid German mobile number
49
+ * @param value - The phone number string to validate
50
+ * @returns True if the phone number is a valid German mobile number
51
+ */
52
+ const isValidMobilePhoneNumber = (value) => {
53
+ const parsedNumber = (0, max_1.default)(value, 'DE');
54
+ return (!!parsedNumber?.isValid() &&
55
+ parsedNumber?.getType() === 'MOBILE' &&
56
+ parsedNumber?.country === 'DE');
57
+ };
58
+ exports.isValidMobilePhoneNumber = isValidMobilePhoneNumber;
59
+ /**
60
+ * Format a phone number to E.164 format
61
+ * @param phone - The phone number string to format
62
+ * @returns The formatted phone number in E.164 format or undefined if invalid
63
+ */
64
+ const getFormattedPhoneNumber = (phone) => (0, max_1.default)(phone, 'DE')?.format('E.164');
65
+ exports.getFormattedPhoneNumber = getFormattedPhoneNumber;
66
+ /**
67
+ * Try to parse and format a phone number with error handling
68
+ * @param phone - The phone number string to parse
69
+ * @param outputFormat - The desired output format (defaults to E.164)
70
+ * @returns The formatted phone number or undefined if parsing fails
71
+ */
72
+ const tryParsePhoneNumber = (phone, outputFormat = OutputFormat.E164) => {
73
+ if (!phone) {
74
+ return undefined;
75
+ }
76
+ try {
77
+ const phoneNumber = (0, max_1.parsePhoneNumberWithError)(phone, 'DE');
78
+ switch (outputFormat) {
79
+ case OutputFormat.International:
80
+ return phoneNumber?.formatInternational();
81
+ case OutputFormat.National:
82
+ return phoneNumber?.formatNational();
83
+ case OutputFormat.E164:
84
+ default:
85
+ return phoneNumber?.format('E.164');
86
+ }
87
+ }
88
+ catch {
89
+ // Silently handle parsing errors
90
+ return undefined;
91
+ }
92
+ };
93
+ exports.tryParsePhoneNumber = tryParsePhoneNumber;
94
+ /**
95
+ * Format phone number for international display (used in backend/format.ts pattern)
96
+ * @param phone - The phone number string, null, or undefined
97
+ * @returns Formatted international phone number, or the original value if null/undefined
98
+ */
99
+ const formatPhoneNumber = (phone) => {
100
+ if (!phone)
101
+ return phone;
102
+ return (0, max_1.default)(phone, 'DE')?.formatInternational();
103
+ };
104
+ exports.formatPhoneNumber = formatPhoneNumber;
105
+ /**
106
+ * Parse a phone number and return the PhoneNumber object
107
+ * @param phone - The phone number string to parse
108
+ * @param defaultCountry - The default country code (defaults to 'DE')
109
+ * @returns The parsed PhoneNumber object or undefined if invalid
110
+ */
111
+ const parsePhone = (phone, defaultCountry = 'DE') => {
112
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
113
+ return (0, max_1.default)(phone, defaultCountry) || undefined;
114
+ };
115
+ exports.parsePhone = parsePhone;
116
+ /**
117
+ * Get the country code from a phone number
118
+ * @param phone - The phone number string
119
+ * @returns The country code or undefined if parsing fails
120
+ */
121
+ const getPhoneCountry = (phone) => {
122
+ // Try parsing without default country first to detect international numbers
123
+ const parsed = (0, max_1.default)(phone);
124
+ return parsed?.country;
125
+ };
126
+ exports.getPhoneCountry = getPhoneCountry;
127
+ /**
128
+ * Get the phone number type (mobile, landline, etc.)
129
+ * @param phone - The phone number string
130
+ * @returns The phone number type or undefined if parsing fails
131
+ */
132
+ const getPhoneType = (phone) => {
133
+ // Try parsing without default country first, then with DE if needed
134
+ let parsed = (0, max_1.default)(phone);
135
+ if (!parsed) {
136
+ parsed = (0, max_1.default)(phone, 'DE');
137
+ }
138
+ return parsed?.getType();
139
+ };
140
+ exports.getPhoneType = getPhoneType;
141
+ /**
142
+ * Normalize a phone number by removing spaces and formatting
143
+ * @param phone - The phone number string
144
+ * @returns The normalized phone number or undefined if invalid
145
+ */
146
+ const normalizePhoneNumber = (phone) => {
147
+ const parsed = (0, max_1.default)(phone, 'DE');
148
+ return parsed?.format('E.164');
149
+ };
150
+ exports.normalizePhoneNumber = normalizePhoneNumber;
@@ -0,0 +1 @@
1
+ export * from './proxy';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./proxy"), exports);
@@ -0,0 +1,37 @@
1
+ import { AxiosError, AxiosInstance, AxiosRequestConfig } from 'axios';
2
+ import { HttpsProxyAgent } from 'https-proxy-agent';
3
+ import https from 'https';
4
+ export interface ProxyConfig {
5
+ https?: string | null;
6
+ http?: string | null;
7
+ retries?: number;
8
+ timeout?: number;
9
+ }
10
+ export interface ProxyClientOptions {
11
+ proxy?: string | null;
12
+ timeout?: number;
13
+ throttleRequestsPerSecond?: number;
14
+ rejectUnauthorized?: boolean;
15
+ retryCondition?: (error: AxiosError) => boolean;
16
+ onRetry?: (retryCount: number, error: AxiosError, requestConfig: AxiosRequestConfig) => void;
17
+ }
18
+ /**
19
+ * Creates an HTTPS proxy agent for the given proxy URL
20
+ */
21
+ export declare const createHttpsProxyAgent: (proxy: string) => HttpsProxyAgent<string>;
22
+ /**
23
+ * Creates a proxy-aware Axios client with configurable options
24
+ */
25
+ export declare const createProxyClient: ({ proxy, timeout, throttleRequestsPerSecond, rejectUnauthorized, retryCondition, onRetry, }?: ProxyClientOptions) => AxiosInstance;
26
+ /**
27
+ * Parses proxy configuration from URL string
28
+ */
29
+ export declare const getProxyConfig: (proxyUrl?: string | null) => {
30
+ host: string;
31
+ port: number;
32
+ } | undefined;
33
+ /**
34
+ * Creates a proxy agent based on configuration
35
+ * Falls back to regular HTTPS agent if no proxy is configured
36
+ */
37
+ export declare const createProxyAgent: (proxyUrl?: string | null, rejectUnauthorized?: boolean) => HttpsProxyAgent<string> | https.Agent;
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createProxyAgent = exports.getProxyConfig = exports.createProxyClient = exports.createHttpsProxyAgent = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const axios_rate_limit_1 = __importDefault(require("axios-rate-limit"));
9
+ const axios_retry_1 = __importDefault(require("axios-retry"));
10
+ const https_proxy_agent_1 = require("https-proxy-agent");
11
+ const https_1 = __importDefault(require("https"));
12
+ /**
13
+ * Creates an HTTPS proxy agent for the given proxy URL
14
+ */
15
+ const createHttpsProxyAgent = (proxy) => new https_proxy_agent_1.HttpsProxyAgent(proxy);
16
+ exports.createHttpsProxyAgent = createHttpsProxyAgent;
17
+ /**
18
+ * Default retry condition that excludes 429 Too Many Requests from retries
19
+ */
20
+ const defaultRetryCondition = (error) => {
21
+ // Do not retry on 429 Too Many Requests
22
+ if (error.response && error.response.status === 429) {
23
+ return false;
24
+ }
25
+ return axios_retry_1.default.isNetworkOrIdempotentRequestError(error);
26
+ };
27
+ /**
28
+ * Creates a proxy-aware Axios client with configurable options
29
+ */
30
+ const createProxyClient = ({ proxy, timeout = 120000, throttleRequestsPerSecond, rejectUnauthorized = true, retryCondition = defaultRetryCondition, onRetry, } = {}) => {
31
+ const retryConfig = {
32
+ retries: 3,
33
+ retryDelay: axios_retry_1.default.exponentialDelay,
34
+ shouldResetTimeout: true,
35
+ retryCondition,
36
+ onRetry,
37
+ };
38
+ let client;
39
+ if (!proxy) {
40
+ // No proxy - create regular client
41
+ client = axios_1.default.create({
42
+ proxy: false,
43
+ timeout,
44
+ httpsAgent: new https_1.default.Agent({
45
+ rejectUnauthorized,
46
+ }),
47
+ });
48
+ }
49
+ else {
50
+ // With proxy - create proxy-aware client
51
+ client = axios_1.default.create({
52
+ httpsAgent: (0, exports.createHttpsProxyAgent)(proxy),
53
+ proxy: false,
54
+ timeout,
55
+ });
56
+ }
57
+ // Apply retry configuration
58
+ (0, axios_retry_1.default)(client, retryConfig);
59
+ // Apply rate limiting if specified
60
+ if (throttleRequestsPerSecond) {
61
+ (0, axios_rate_limit_1.default)(client, { maxRPS: throttleRequestsPerSecond });
62
+ }
63
+ return client;
64
+ };
65
+ exports.createProxyClient = createProxyClient;
66
+ /**
67
+ * Parses proxy configuration from URL string
68
+ */
69
+ const getProxyConfig = (proxyUrl) => {
70
+ if (!proxyUrl) {
71
+ return undefined;
72
+ }
73
+ try {
74
+ const { hostname, port } = new URL(proxyUrl);
75
+ return {
76
+ host: hostname,
77
+ port: Number(port) || 8080,
78
+ };
79
+ }
80
+ catch (error) {
81
+ console.error('Error parsing proxy URL:', error);
82
+ return undefined;
83
+ }
84
+ };
85
+ exports.getProxyConfig = getProxyConfig;
86
+ /**
87
+ * Creates a proxy agent based on configuration
88
+ * Falls back to regular HTTPS agent if no proxy is configured
89
+ */
90
+ const createProxyAgent = (proxyUrl, rejectUnauthorized = true) => {
91
+ if (proxyUrl) {
92
+ return (0, exports.createHttpsProxyAgent)(proxyUrl);
93
+ }
94
+ return new https_1.default.Agent({
95
+ rejectUnauthorized,
96
+ });
97
+ };
98
+ exports.createProxyAgent = createProxyAgent;
@@ -0,0 +1 @@
1
+ export * from './random';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./random"), exports);
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Generates a random string of specified length using the provided alphabet
3
+ * @param length - The length of the string to generate
4
+ * @param alphabet - The alphabet to use for character selection (defaults to alphanumeric uppercase)
5
+ * @returns A random string of the specified length
6
+ */
7
+ export declare const generateRandomString: (length: number, alphabet?: string) => string;
8
+ /**
9
+ * Generates a random numeric string of specified length
10
+ * @param length - The length of the numeric string to generate
11
+ * @returns A random numeric string
12
+ */
13
+ export declare const generateRandomNumericString: (length: number) => string;
14
+ /**
15
+ * Generates a random alphabetic string of specified length (uppercase)
16
+ * @param length - The length of the alphabetic string to generate
17
+ * @returns A random alphabetic string
18
+ */
19
+ export declare const generateRandomAlphabeticString: (length: number) => string;
20
+ /**
21
+ * Generates a random lowercase alphanumeric string of specified length
22
+ * @param length - The length of the string to generate
23
+ * @returns A random lowercase alphanumeric string
24
+ */
25
+ export declare const generateRandomLowercaseString: (length: number) => string;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateRandomLowercaseString = exports.generateRandomAlphabeticString = exports.generateRandomNumericString = exports.generateRandomString = void 0;
4
+ const crypto_1 = require("crypto");
5
+ const DEFAULT_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
6
+ /**
7
+ * Gets a random character from the provided alphabet
8
+ */
9
+ const getRandomCharFromAlphabet = (alphabet) => alphabet.charAt((0, crypto_1.randomInt)(alphabet.length));
10
+ /**
11
+ * Generates a random string of specified length using the provided alphabet
12
+ * @param length - The length of the string to generate
13
+ * @param alphabet - The alphabet to use for character selection (defaults to alphanumeric uppercase)
14
+ * @returns A random string of the specified length
15
+ */
16
+ const generateRandomString = (length, alphabet = DEFAULT_ALPHABET) => Array.from({ length })
17
+ .map(() => getRandomCharFromAlphabet(alphabet))
18
+ .join('');
19
+ exports.generateRandomString = generateRandomString;
20
+ /**
21
+ * Generates a random numeric string of specified length
22
+ * @param length - The length of the numeric string to generate
23
+ * @returns A random numeric string
24
+ */
25
+ const generateRandomNumericString = (length) => (0, exports.generateRandomString)(length, '0123456789');
26
+ exports.generateRandomNumericString = generateRandomNumericString;
27
+ /**
28
+ * Generates a random alphabetic string of specified length (uppercase)
29
+ * @param length - The length of the alphabetic string to generate
30
+ * @returns A random alphabetic string
31
+ */
32
+ const generateRandomAlphabeticString = (length) => (0, exports.generateRandomString)(length, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
33
+ exports.generateRandomAlphabeticString = generateRandomAlphabeticString;
34
+ /**
35
+ * Generates a random lowercase alphanumeric string of specified length
36
+ * @param length - The length of the string to generate
37
+ * @returns A random lowercase alphanumeric string
38
+ */
39
+ const generateRandomLowercaseString = (length) => (0, exports.generateRandomString)(length, 'abcdefghijklmnopqrstuvwxyz0123456789');
40
+ exports.generateRandomLowercaseString = generateRandomLowercaseString;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lucaapp/service-utils",
3
- "version": "2.0.9",
3
+ "version": "4.0.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -29,14 +29,17 @@
29
29
  "@types/response-time": "^2.3.9",
30
30
  "@types/swagger-ui-express": "4.1.3",
31
31
  "axios": "^1.11.0",
32
+ "axios-rate-limit": "^1.4.0",
33
+ "axios-retry": "^4.5.0",
32
34
  "body-parser": "^2.2.0",
33
35
  "busboy": "^1.6.0",
34
36
  "cls-rtracer": "^2.6.3",
35
37
  "express": "4.21.2",
36
38
  "express-async-errors": "3.1.1",
39
+ "https-proxy-agent": "^7.0.6",
37
40
  "jose": "4.15.9",
38
41
  "kafkajs": "2.1.0",
39
- "libphonenumber-js": "1.9.44",
42
+ "libphonenumber-js": "^1.12.10",
40
43
  "lodash": "^4.17.21",
41
44
  "moment-timezone": "^0.5.44",
42
45
  "negotiator": "^0.6.4",