@lucaapp/service-utils 4.9.1 → 4.11.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 +2 -0
- package/dist/index.js +2 -0
- package/dist/lib/jobs/index.d.ts +1 -0
- package/dist/lib/jobs/index.js +17 -0
- package/dist/lib/jobs/jobTracker.d.ts +30 -0
- package/dist/lib/jobs/jobTracker.js +113 -0
- package/dist/lib/money/supportedCurrencies.d.ts +3 -1
- package/dist/lib/money/supportedCurrencies.js +4 -0
- package/dist/lib/serviceIdentity/serviceIdentity.js +12 -0
- package/dist/lib/validation.d.ts +430 -0
- package/dist/lib/validation.js +431 -0
- package/package.json +3 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -32,4 +32,6 @@ __exportStar(require("./lib/random"), exports);
|
|
|
32
32
|
__exportStar(require("./lib/crypto"), exports);
|
|
33
33
|
__exportStar(require("./lib/phone"), exports);
|
|
34
34
|
__exportStar(require("./lib/http"), exports);
|
|
35
|
+
__exportStar(require("./lib/jobs"), exports);
|
|
36
|
+
__exportStar(require("./lib/validation"), exports);
|
|
35
37
|
__exportStar(require("./types"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './jobTracker';
|
|
@@ -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("./jobTracker"), exports);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Logger } from 'pino';
|
|
2
|
+
export type JsonSchema = Record<string, unknown>;
|
|
3
|
+
export interface JobStatus {
|
|
4
|
+
jobId: string;
|
|
5
|
+
jobName: string;
|
|
6
|
+
method: string;
|
|
7
|
+
status: 'running' | 'completed' | 'failed';
|
|
8
|
+
result?: JsonSchema;
|
|
9
|
+
error?: string;
|
|
10
|
+
startedAt: string;
|
|
11
|
+
completedAt?: string;
|
|
12
|
+
duration?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface RedisClient {
|
|
15
|
+
setex(key: string | Buffer, seconds: number, value: string | Buffer): Promise<string | void>;
|
|
16
|
+
get(key: string | Buffer): Promise<string | null>;
|
|
17
|
+
scan(cursor: number, command: string, pattern: string, countCommand: string, count: number): Promise<[string, string[]]>;
|
|
18
|
+
}
|
|
19
|
+
export declare const createJobTracker: (logger: Logger, redis: RedisClient) => {
|
|
20
|
+
createJobExecution: (jobName: string, method: string) => Promise<string>;
|
|
21
|
+
updateJobStatus: (jobId: string, result: JsonSchema, error?: Error) => Promise<void>;
|
|
22
|
+
getJobStatus: (jobId: string) => Promise<JobStatus | null>;
|
|
23
|
+
getAllRunningJobs: () => Promise<JobStatus[]>;
|
|
24
|
+
getLatestCompletions: () => Promise<Record<string, {
|
|
25
|
+
completedAt: string;
|
|
26
|
+
status: "completed" | "failed";
|
|
27
|
+
error?: string;
|
|
28
|
+
}>>;
|
|
29
|
+
};
|
|
30
|
+
export type JobTracker = ReturnType<typeof createJobTracker>;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createJobTracker = void 0;
|
|
4
|
+
const uuid_1 = require("uuid");
|
|
5
|
+
const JOB_STATUS_PREFIX = 'job:status:';
|
|
6
|
+
const JOB_TTL = 24 * 60 * 60;
|
|
7
|
+
const createJobTracker = (logger, redis) => {
|
|
8
|
+
const createJobExecution = async (jobName, method) => {
|
|
9
|
+
const jobId = (0, uuid_1.v4)();
|
|
10
|
+
const jobStatus = {
|
|
11
|
+
jobId,
|
|
12
|
+
jobName,
|
|
13
|
+
method,
|
|
14
|
+
status: 'running',
|
|
15
|
+
startedAt: new Date().toISOString(),
|
|
16
|
+
};
|
|
17
|
+
const key = `${JOB_STATUS_PREFIX}${jobId}`;
|
|
18
|
+
await redis.setex(key, JOB_TTL, JSON.stringify(jobStatus));
|
|
19
|
+
logger.info(`Created job execution: ${jobId} for job: ${jobName}, method: ${method}`);
|
|
20
|
+
return jobId;
|
|
21
|
+
};
|
|
22
|
+
const updateJobStatus = async (jobId, result, error) => {
|
|
23
|
+
const key = `${JOB_STATUS_PREFIX}${jobId}`;
|
|
24
|
+
const data = await redis.get(key);
|
|
25
|
+
if (!data) {
|
|
26
|
+
logger.warn(`Job status not found for jobId: ${jobId}`);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const jobStatus = JSON.parse(data);
|
|
30
|
+
const completedAt = new Date();
|
|
31
|
+
const startedAt = new Date(jobStatus.startedAt);
|
|
32
|
+
const duration = completedAt.getTime() - startedAt.getTime();
|
|
33
|
+
if (error) {
|
|
34
|
+
jobStatus.status = 'failed';
|
|
35
|
+
jobStatus.error = error.message;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
jobStatus.status = 'completed';
|
|
39
|
+
jobStatus.result = result;
|
|
40
|
+
}
|
|
41
|
+
jobStatus.completedAt = completedAt.toISOString();
|
|
42
|
+
jobStatus.duration = duration;
|
|
43
|
+
await redis.setex(key, JOB_TTL, JSON.stringify(jobStatus));
|
|
44
|
+
logger.info(`Updated job status: ${jobId} - status: ${jobStatus.status}, duration: ${duration}ms`);
|
|
45
|
+
};
|
|
46
|
+
const getJobStatus = async (jobId) => {
|
|
47
|
+
const key = `${JOB_STATUS_PREFIX}${jobId}`;
|
|
48
|
+
const data = await redis.get(key);
|
|
49
|
+
if (!data) {
|
|
50
|
+
logger.warn(`Job status not found for jobId: ${jobId}`);
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
return JSON.parse(data);
|
|
54
|
+
};
|
|
55
|
+
const getAllRunningJobs = async () => {
|
|
56
|
+
const pattern = `${JOB_STATUS_PREFIX}*`;
|
|
57
|
+
const allJobs = [];
|
|
58
|
+
let cursor = 0;
|
|
59
|
+
do {
|
|
60
|
+
const [nextCursor, keys] = await redis.scan(cursor, 'MATCH', pattern, 'COUNT', 100);
|
|
61
|
+
cursor = Number.parseInt(nextCursor, 10);
|
|
62
|
+
for (const key of keys) {
|
|
63
|
+
const data = await redis.get(key);
|
|
64
|
+
if (data) {
|
|
65
|
+
const jobStatus = JSON.parse(data);
|
|
66
|
+
if (jobStatus.status === 'running') {
|
|
67
|
+
allJobs.push(jobStatus);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
} while (cursor !== 0);
|
|
72
|
+
logger.info(`Found ${allJobs.length} running jobs`);
|
|
73
|
+
return allJobs;
|
|
74
|
+
};
|
|
75
|
+
const getLatestCompletions = async () => {
|
|
76
|
+
const pattern = `${JOB_STATUS_PREFIX}*`;
|
|
77
|
+
const completions = new Map();
|
|
78
|
+
let cursor = 0;
|
|
79
|
+
do {
|
|
80
|
+
const [nextCursor, keys] = await redis.scan(cursor, 'MATCH', pattern, 'COUNT', 100);
|
|
81
|
+
cursor = Number.parseInt(nextCursor, 10);
|
|
82
|
+
for (const key of keys) {
|
|
83
|
+
const data = await redis.get(key);
|
|
84
|
+
if (data) {
|
|
85
|
+
const jobStatus = JSON.parse(data);
|
|
86
|
+
if (jobStatus.completedAt &&
|
|
87
|
+
(jobStatus.status === 'completed' || jobStatus.status === 'failed')) {
|
|
88
|
+
const jobKey = `${jobStatus.jobName}/${jobStatus.method}`;
|
|
89
|
+
const existing = completions.get(jobKey);
|
|
90
|
+
if (!existing ||
|
|
91
|
+
new Date(jobStatus.completedAt) > new Date(existing.completedAt)) {
|
|
92
|
+
completions.set(jobKey, {
|
|
93
|
+
completedAt: jobStatus.completedAt,
|
|
94
|
+
status: jobStatus.status,
|
|
95
|
+
error: jobStatus.error,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
} while (cursor !== 0);
|
|
102
|
+
logger.info(`Found ${completions.size} job completions`);
|
|
103
|
+
return Object.fromEntries(completions);
|
|
104
|
+
};
|
|
105
|
+
return {
|
|
106
|
+
createJobExecution,
|
|
107
|
+
updateJobStatus,
|
|
108
|
+
getJobStatus,
|
|
109
|
+
getAllRunningJobs,
|
|
110
|
+
getLatestCompletions,
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
exports.createJobTracker = createJobTracker;
|
|
@@ -9,6 +9,8 @@ var SupportedCurrencies;
|
|
|
9
9
|
SupportedCurrencies["USD"] = "USD";
|
|
10
10
|
SupportedCurrencies["HUF"] = "HUF";
|
|
11
11
|
SupportedCurrencies["CZK"] = "CZK";
|
|
12
|
+
SupportedCurrencies["PLN"] = "PLN";
|
|
13
|
+
SupportedCurrencies["RON"] = "RON";
|
|
12
14
|
})(SupportedCurrencies || (exports.SupportedCurrencies = SupportedCurrencies = {}));
|
|
13
15
|
exports.currencySymbols = {
|
|
14
16
|
[SupportedCurrencies.CHF]: 'CHF',
|
|
@@ -17,4 +19,6 @@ exports.currencySymbols = {
|
|
|
17
19
|
[SupportedCurrencies.USD]: '$',
|
|
18
20
|
[SupportedCurrencies.HUF]: 'Ft',
|
|
19
21
|
[SupportedCurrencies.CZK]: 'Kč',
|
|
22
|
+
[SupportedCurrencies.PLN]: 'zł',
|
|
23
|
+
[SupportedCurrencies.RON]: 'lei',
|
|
20
24
|
};
|
|
@@ -34,6 +34,7 @@ const api_1 = require("../api");
|
|
|
34
34
|
const moment_1 = __importDefault(require("moment"));
|
|
35
35
|
const requestTracer_1 = require("../requestTracer");
|
|
36
36
|
const axios_1 = __importDefault(require("axios"));
|
|
37
|
+
const axios_retry_1 = __importDefault(require("axios-retry"));
|
|
37
38
|
const zod_1 = require("zod");
|
|
38
39
|
const validator_1 = __importDefault(require("validator"));
|
|
39
40
|
const JWT_ALGORITHM = 'ES256';
|
|
@@ -188,6 +189,17 @@ class ServiceIdentity {
|
|
|
188
189
|
this.identityPrivateKey = identityPrivateKey;
|
|
189
190
|
this.identityPublicKey = identityPublicKey;
|
|
190
191
|
this.axiosClient = axios_1.default.create({ proxy: false });
|
|
192
|
+
// Configure axios-retry to handle 429 and respect Retry-After header
|
|
193
|
+
(0, axios_retry_1.default)(this.axiosClient, {
|
|
194
|
+
retries: 3,
|
|
195
|
+
retryDelay: axios_retry_1.default.exponentialDelay,
|
|
196
|
+
shouldResetTimeout: true,
|
|
197
|
+
retryCondition: (error) => {
|
|
198
|
+
// Retry on network errors, 5xx errors, and 429 (rate limit)
|
|
199
|
+
return (axios_retry_1.default.isNetworkOrIdempotentRequestError(error) ||
|
|
200
|
+
error.response?.status === 429);
|
|
201
|
+
},
|
|
202
|
+
});
|
|
191
203
|
if (!debug) {
|
|
192
204
|
this.axiosClient.interceptors.response.use(response => response, error => {
|
|
193
205
|
if (Array.isArray(error?.config?.headers) &&
|
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
import { z as zod, ZodEffects, ZodNumber, ZodObject, ZodString, ZodType, ZodTypeAny } from 'zod';
|
|
2
|
+
import validator from 'validator';
|
|
3
|
+
import { Money } from '../lib/money/money';
|
|
4
|
+
export declare const preprocessArrayFromQueryString: (input: unknown) => string[] | unknown;
|
|
5
|
+
export declare const preprocessNumberFromQueryString: (input: unknown) => number | unknown;
|
|
6
|
+
export declare const preprocessBooleanFromQueryString: (input: unknown) => boolean | unknown;
|
|
7
|
+
export declare const preprocessBooleanFromString: (input: unknown) => boolean | unknown;
|
|
8
|
+
declare const z: {
|
|
9
|
+
string: () => ZodString;
|
|
10
|
+
safeString: () => ZodString;
|
|
11
|
+
safeText: () => ZodString;
|
|
12
|
+
safeBusinessStringForOnboarding: () => zod.ZodEffects<zod.ZodString, string, string>;
|
|
13
|
+
safeNameForOnboarding: () => zod.ZodEffects<zod.ZodString, string, string>;
|
|
14
|
+
nonemptyString: () => zod.ZodString;
|
|
15
|
+
alphaNumericString: () => zod.ZodString;
|
|
16
|
+
tableId: () => zod.ZodString;
|
|
17
|
+
uuid: () => ZodString;
|
|
18
|
+
uuidv4: () => zod.ZodEffects<zod.ZodString, string, string>;
|
|
19
|
+
email: () => ZodEffects<ZodString>;
|
|
20
|
+
phoneNumber: () => ZodEffects<ZodEffects<ZodString>>;
|
|
21
|
+
nullablePhoneNumber: () => zod.ZodEffects<zod.ZodEffects<zod.ZodString, string, string>, string | null, string>;
|
|
22
|
+
strongPassword: () => zod.ZodEffects<zod.ZodString, string, string>;
|
|
23
|
+
zipCode: (locale?: validator.PostalCodeLocale) => ZodEffects<ZodString, string>;
|
|
24
|
+
countryCode: () => zod.ZodString;
|
|
25
|
+
moneyDecimalString: (locale?: string) => zod.ZodEffects<zod.ZodString, string, string>;
|
|
26
|
+
moneyFromFloat: () => ZodEffects<ZodEffects<ZodNumber>, Money>;
|
|
27
|
+
moneyFromInt: () => ZodEffects<ZodNumber, Money>;
|
|
28
|
+
convertMoneyFieldsToCurrency: <T extends ZodObject<Record<string, ZodTypeAny>>>(schema: T) => ZodEffects<T>;
|
|
29
|
+
unixTimestamp: () => zod.ZodNumber;
|
|
30
|
+
integerString: (options?: {
|
|
31
|
+
maxLength?: number;
|
|
32
|
+
lt?: number;
|
|
33
|
+
gt?: number;
|
|
34
|
+
transform?: boolean;
|
|
35
|
+
}) => zod.ZodEffects<zod.ZodEffects<zod.ZodType<string, zod.ZodTypeDef, string>, string, string>, number, string>;
|
|
36
|
+
integerStringRaw: (options?: {
|
|
37
|
+
maxLength?: number;
|
|
38
|
+
lt?: number;
|
|
39
|
+
gt?: number;
|
|
40
|
+
transform?: boolean;
|
|
41
|
+
}) => typeof options.transform extends true ? ZodEffects<ZodType<number>> : ZodEffects<ZodType<string>>;
|
|
42
|
+
bigIntegerString: () => zod.ZodEffects<zod.ZodString, string, string>;
|
|
43
|
+
floatString: (options?: {
|
|
44
|
+
maxLength?: number;
|
|
45
|
+
lt: number;
|
|
46
|
+
gt: number;
|
|
47
|
+
}) => zod.ZodEffects<zod.ZodEffects<zod.ZodString, string, string>, number, string>;
|
|
48
|
+
hex: ({ min, max, length, rawLength, }?: {
|
|
49
|
+
min?: number;
|
|
50
|
+
max?: number;
|
|
51
|
+
length?: number;
|
|
52
|
+
rawLength?: number;
|
|
53
|
+
}) => zod.ZodEffects<zod.ZodString, string, string>;
|
|
54
|
+
sha256: () => zod.ZodEffects<zod.ZodString, string, string>;
|
|
55
|
+
base64: ({ min, max, length, rawLength, isBase64Url, }?: {
|
|
56
|
+
min?: number;
|
|
57
|
+
max?: number;
|
|
58
|
+
length?: number;
|
|
59
|
+
rawLength?: number;
|
|
60
|
+
isBase64Url?: boolean;
|
|
61
|
+
}) => ZodEffects<ZodString>;
|
|
62
|
+
bearerToken: () => ZodEffects<ZodEffects<ZodString>>;
|
|
63
|
+
jwt: ({ max }: {
|
|
64
|
+
max: number;
|
|
65
|
+
}) => ZodEffects<ZodString>;
|
|
66
|
+
ecPublicKey: () => zod.ZodEffects<zod.ZodString, string, string>;
|
|
67
|
+
ecCompressedPublicKey: () => zod.ZodEffects<zod.ZodString, string, string>;
|
|
68
|
+
uncompressedECPublicKey: () => zod.ZodEffects<zod.ZodString, string, string>;
|
|
69
|
+
ecSignature: () => zod.ZodEffects<zod.ZodString, string, string>;
|
|
70
|
+
iv: () => zod.ZodEffects<zod.ZodString, string, string>;
|
|
71
|
+
mac: () => zod.ZodEffects<zod.ZodString, string, string>;
|
|
72
|
+
traceId: () => zod.ZodEffects<zod.ZodString, string, string>;
|
|
73
|
+
isoDateString: () => ZodEffects<ZodString, string>;
|
|
74
|
+
rfc3339String: () => ZodEffects<ZodString, string>;
|
|
75
|
+
iso8601Date: () => zod.ZodEffects<zod.ZodString, string, string>;
|
|
76
|
+
urlHttpsString: () => zod.ZodEffects<zod.ZodString, string, string>;
|
|
77
|
+
urlHttpOrHttpsString: () => zod.ZodEffects<zod.ZodString, string, string>;
|
|
78
|
+
language: () => ZodTypeAny;
|
|
79
|
+
dsgcPayload: () => zod.ZodObject<{
|
|
80
|
+
certificates: zod.ZodArray<zod.ZodObject<{
|
|
81
|
+
certificateType: zod.ZodString;
|
|
82
|
+
country: zod.ZodString;
|
|
83
|
+
kid: zod.ZodString;
|
|
84
|
+
rawData: zod.ZodString;
|
|
85
|
+
signature: zod.ZodString;
|
|
86
|
+
thumbprint: zod.ZodString;
|
|
87
|
+
timestamp: zod.ZodString;
|
|
88
|
+
}, "strip", zod.ZodTypeAny, {
|
|
89
|
+
kid: string;
|
|
90
|
+
timestamp: string;
|
|
91
|
+
signature: string;
|
|
92
|
+
certificateType: string;
|
|
93
|
+
country: string;
|
|
94
|
+
rawData: string;
|
|
95
|
+
thumbprint: string;
|
|
96
|
+
}, {
|
|
97
|
+
kid: string;
|
|
98
|
+
timestamp: string;
|
|
99
|
+
signature: string;
|
|
100
|
+
certificateType: string;
|
|
101
|
+
country: string;
|
|
102
|
+
rawData: string;
|
|
103
|
+
thumbprint: string;
|
|
104
|
+
}>, "many">;
|
|
105
|
+
}, "strip", zod.ZodTypeAny, {
|
|
106
|
+
certificates: {
|
|
107
|
+
kid: string;
|
|
108
|
+
timestamp: string;
|
|
109
|
+
signature: string;
|
|
110
|
+
certificateType: string;
|
|
111
|
+
country: string;
|
|
112
|
+
rawData: string;
|
|
113
|
+
thumbprint: string;
|
|
114
|
+
}[];
|
|
115
|
+
}, {
|
|
116
|
+
certificates: {
|
|
117
|
+
kid: string;
|
|
118
|
+
timestamp: string;
|
|
119
|
+
signature: string;
|
|
120
|
+
certificateType: string;
|
|
121
|
+
country: string;
|
|
122
|
+
rawData: string;
|
|
123
|
+
thumbprint: string;
|
|
124
|
+
}[];
|
|
125
|
+
}>;
|
|
126
|
+
dccListPayload: () => zod.ZodArray<zod.ZodObject<{
|
|
127
|
+
identifier: zod.ZodString;
|
|
128
|
+
version: zod.ZodString;
|
|
129
|
+
country: zod.ZodString;
|
|
130
|
+
hash: zod.ZodString;
|
|
131
|
+
}, "strip", zod.ZodTypeAny, {
|
|
132
|
+
version: string;
|
|
133
|
+
country: string;
|
|
134
|
+
identifier: string;
|
|
135
|
+
hash: string;
|
|
136
|
+
}, {
|
|
137
|
+
version: string;
|
|
138
|
+
country: string;
|
|
139
|
+
identifier: string;
|
|
140
|
+
hash: string;
|
|
141
|
+
}>, "many">;
|
|
142
|
+
dccRulePayload: () => zod.ZodObject<{
|
|
143
|
+
Identifier: zod.ZodString;
|
|
144
|
+
Type: zod.ZodString;
|
|
145
|
+
Country: zod.ZodString;
|
|
146
|
+
Version: zod.ZodString;
|
|
147
|
+
SchemaVersion: zod.ZodString;
|
|
148
|
+
Engine: zod.ZodString;
|
|
149
|
+
EngineVersion: zod.ZodString;
|
|
150
|
+
CertificateType: zod.ZodString;
|
|
151
|
+
Description: zod.ZodArray<zod.ZodObject<{
|
|
152
|
+
lang: zod.ZodString;
|
|
153
|
+
desc: zod.ZodString;
|
|
154
|
+
}, "strip", zod.ZodTypeAny, {
|
|
155
|
+
lang: string;
|
|
156
|
+
desc: string;
|
|
157
|
+
}, {
|
|
158
|
+
lang: string;
|
|
159
|
+
desc: string;
|
|
160
|
+
}>, "many">;
|
|
161
|
+
ValidFrom: zod.ZodString;
|
|
162
|
+
ValidTo: zod.ZodString;
|
|
163
|
+
AffectedFields: zod.ZodArray<zod.ZodString, "many">;
|
|
164
|
+
Logic: zod.ZodAny;
|
|
165
|
+
}, "strip", zod.ZodTypeAny, {
|
|
166
|
+
Identifier: string;
|
|
167
|
+
Type: string;
|
|
168
|
+
Country: string;
|
|
169
|
+
Version: string;
|
|
170
|
+
SchemaVersion: string;
|
|
171
|
+
Engine: string;
|
|
172
|
+
EngineVersion: string;
|
|
173
|
+
CertificateType: string;
|
|
174
|
+
Description: {
|
|
175
|
+
lang: string;
|
|
176
|
+
desc: string;
|
|
177
|
+
}[];
|
|
178
|
+
ValidFrom: string;
|
|
179
|
+
ValidTo: string;
|
|
180
|
+
AffectedFields: string[];
|
|
181
|
+
Logic?: any;
|
|
182
|
+
}, {
|
|
183
|
+
Identifier: string;
|
|
184
|
+
Type: string;
|
|
185
|
+
Country: string;
|
|
186
|
+
Version: string;
|
|
187
|
+
SchemaVersion: string;
|
|
188
|
+
Engine: string;
|
|
189
|
+
EngineVersion: string;
|
|
190
|
+
CertificateType: string;
|
|
191
|
+
Description: {
|
|
192
|
+
lang: string;
|
|
193
|
+
desc: string;
|
|
194
|
+
}[];
|
|
195
|
+
ValidFrom: string;
|
|
196
|
+
ValidTo: string;
|
|
197
|
+
AffectedFields: string[];
|
|
198
|
+
Logic?: any;
|
|
199
|
+
}>;
|
|
200
|
+
setErrorMap(map: zod.ZodErrorMap): void;
|
|
201
|
+
getErrorMap(): zod.ZodErrorMap;
|
|
202
|
+
defaultErrorMap: zod.ZodErrorMap;
|
|
203
|
+
addIssueToContext(ctx: zod.ParseContext, issueData: zod.IssueData): void;
|
|
204
|
+
makeIssue: (params: {
|
|
205
|
+
data: any;
|
|
206
|
+
path: (string | number)[];
|
|
207
|
+
errorMaps: zod.ZodErrorMap[];
|
|
208
|
+
issueData: zod.IssueData;
|
|
209
|
+
}) => zod.ZodIssue;
|
|
210
|
+
EMPTY_PATH: zod.ParsePath;
|
|
211
|
+
ParseStatus: typeof zod.ParseStatus;
|
|
212
|
+
INVALID: zod.INVALID;
|
|
213
|
+
DIRTY: <T>(value: T) => zod.DIRTY<T>;
|
|
214
|
+
OK: <T>(value: T) => zod.OK<T>;
|
|
215
|
+
isAborted: (x: zod.ParseReturnType<any>) => x is zod.INVALID;
|
|
216
|
+
isDirty: <T>(x: zod.ParseReturnType<T>) => x is zod.OK<T> | zod.DIRTY<T>;
|
|
217
|
+
isValid: <T>(x: zod.ParseReturnType<T>) => x is zod.OK<T> | zod.DIRTY<T>;
|
|
218
|
+
isAsync: <T>(x: zod.ParseReturnType<T>) => x is zod.AsyncParseReturnType<T>;
|
|
219
|
+
util: typeof zod.util;
|
|
220
|
+
objectUtil: typeof zod.objectUtil;
|
|
221
|
+
ZodParsedType: {
|
|
222
|
+
function: "function";
|
|
223
|
+
number: "number";
|
|
224
|
+
string: "string";
|
|
225
|
+
nan: "nan";
|
|
226
|
+
integer: "integer";
|
|
227
|
+
float: "float";
|
|
228
|
+
boolean: "boolean";
|
|
229
|
+
date: "date";
|
|
230
|
+
bigint: "bigint";
|
|
231
|
+
symbol: "symbol";
|
|
232
|
+
undefined: "undefined";
|
|
233
|
+
null: "null";
|
|
234
|
+
array: "array";
|
|
235
|
+
object: "object";
|
|
236
|
+
unknown: "unknown";
|
|
237
|
+
promise: "promise";
|
|
238
|
+
void: "void";
|
|
239
|
+
never: "never";
|
|
240
|
+
map: "map";
|
|
241
|
+
set: "set";
|
|
242
|
+
};
|
|
243
|
+
getParsedType: (data: any) => zod.ZodParsedType;
|
|
244
|
+
ZodType: typeof zod.ZodType;
|
|
245
|
+
ZodString: typeof zod.ZodString;
|
|
246
|
+
ZodNumber: typeof zod.ZodNumber;
|
|
247
|
+
ZodBigInt: typeof zod.ZodBigInt;
|
|
248
|
+
ZodBoolean: typeof zod.ZodBoolean;
|
|
249
|
+
ZodDate: typeof zod.ZodDate;
|
|
250
|
+
ZodSymbol: typeof zod.ZodSymbol;
|
|
251
|
+
ZodUndefined: typeof zod.ZodUndefined;
|
|
252
|
+
ZodNull: typeof zod.ZodNull;
|
|
253
|
+
ZodAny: typeof zod.ZodAny;
|
|
254
|
+
ZodUnknown: typeof zod.ZodUnknown;
|
|
255
|
+
ZodNever: typeof zod.ZodNever;
|
|
256
|
+
ZodVoid: typeof zod.ZodVoid;
|
|
257
|
+
ZodArray: typeof zod.ZodArray;
|
|
258
|
+
ZodObject: typeof zod.ZodObject;
|
|
259
|
+
ZodUnion: typeof zod.ZodUnion;
|
|
260
|
+
ZodDiscriminatedUnion: typeof zod.ZodDiscriminatedUnion;
|
|
261
|
+
ZodIntersection: typeof zod.ZodIntersection;
|
|
262
|
+
ZodTuple: typeof zod.ZodTuple;
|
|
263
|
+
ZodRecord: typeof zod.ZodRecord;
|
|
264
|
+
ZodMap: typeof zod.ZodMap;
|
|
265
|
+
ZodSet: typeof zod.ZodSet;
|
|
266
|
+
ZodFunction: typeof zod.ZodFunction;
|
|
267
|
+
ZodLazy: typeof zod.ZodLazy;
|
|
268
|
+
ZodLiteral: typeof zod.ZodLiteral;
|
|
269
|
+
ZodEnum: typeof zod.ZodEnum;
|
|
270
|
+
ZodNativeEnum: typeof zod.ZodNativeEnum;
|
|
271
|
+
ZodPromise: typeof zod.ZodPromise;
|
|
272
|
+
ZodEffects: typeof zod.ZodEffects;
|
|
273
|
+
ZodTransformer: typeof zod.ZodEffects;
|
|
274
|
+
ZodOptional: typeof zod.ZodOptional;
|
|
275
|
+
ZodNullable: typeof zod.ZodNullable;
|
|
276
|
+
ZodDefault: typeof zod.ZodDefault;
|
|
277
|
+
ZodCatch: typeof zod.ZodCatch;
|
|
278
|
+
ZodNaN: typeof zod.ZodNaN;
|
|
279
|
+
BRAND: typeof zod.BRAND;
|
|
280
|
+
ZodBranded: typeof zod.ZodBranded;
|
|
281
|
+
ZodPipeline: typeof zod.ZodPipeline;
|
|
282
|
+
ZodReadonly: typeof zod.ZodReadonly;
|
|
283
|
+
custom: <T>(check?: ((data: unknown) => any) | undefined, params?: string | (Partial<zod.util.Omit<zod.ZodCustomIssue, "code">> & {
|
|
284
|
+
fatal?: boolean;
|
|
285
|
+
}) | ((input: any) => Partial<zod.util.Omit<zod.ZodCustomIssue, "code">> & {
|
|
286
|
+
fatal?: boolean;
|
|
287
|
+
}), fatal?: boolean | undefined) => ZodType<T, zod.ZodTypeDef, T>;
|
|
288
|
+
Schema: typeof zod.ZodType;
|
|
289
|
+
ZodSchema: typeof zod.ZodType;
|
|
290
|
+
late: {
|
|
291
|
+
object: <T extends zod.ZodRawShape>(shape: () => T, params?: zod.RawCreateParams) => ZodObject<T, "strip", ZodTypeAny, { [k_1 in keyof zod.objectUtil.addQuestionMarks<zod.baseObjectOutputType<T>, { [k in keyof zod.baseObjectOutputType<T>]: undefined extends zod.baseObjectOutputType<T>[k] ? never : k; }[keyof T]>]: zod.objectUtil.addQuestionMarks<zod.baseObjectOutputType<T>, { [k in keyof zod.baseObjectOutputType<T>]: undefined extends zod.baseObjectOutputType<T>[k] ? never : k; }[keyof T]>[k_1]; }, { [k_2 in keyof zod.baseObjectInputType<T>]: zod.baseObjectInputType<T>[k_2]; }>;
|
|
292
|
+
};
|
|
293
|
+
ZodFirstPartyTypeKind: typeof zod.ZodFirstPartyTypeKind;
|
|
294
|
+
coerce: {
|
|
295
|
+
string: (params?: ({
|
|
296
|
+
errorMap?: zod.ZodErrorMap | undefined;
|
|
297
|
+
invalid_type_error?: string | undefined;
|
|
298
|
+
required_error?: string | undefined;
|
|
299
|
+
description?: string | undefined;
|
|
300
|
+
} & {
|
|
301
|
+
coerce?: true | undefined;
|
|
302
|
+
}) | undefined) => ZodString;
|
|
303
|
+
number: (params?: ({
|
|
304
|
+
errorMap?: zod.ZodErrorMap | undefined;
|
|
305
|
+
invalid_type_error?: string | undefined;
|
|
306
|
+
required_error?: string | undefined;
|
|
307
|
+
description?: string | undefined;
|
|
308
|
+
} & {
|
|
309
|
+
coerce?: boolean | undefined;
|
|
310
|
+
}) | undefined) => ZodNumber;
|
|
311
|
+
boolean: (params?: ({
|
|
312
|
+
errorMap?: zod.ZodErrorMap | undefined;
|
|
313
|
+
invalid_type_error?: string | undefined;
|
|
314
|
+
required_error?: string | undefined;
|
|
315
|
+
description?: string | undefined;
|
|
316
|
+
} & {
|
|
317
|
+
coerce?: boolean | undefined;
|
|
318
|
+
}) | undefined) => zod.ZodBoolean;
|
|
319
|
+
bigint: (params?: ({
|
|
320
|
+
errorMap?: zod.ZodErrorMap | undefined;
|
|
321
|
+
invalid_type_error?: string | undefined;
|
|
322
|
+
required_error?: string | undefined;
|
|
323
|
+
description?: string | undefined;
|
|
324
|
+
} & {
|
|
325
|
+
coerce?: boolean | undefined;
|
|
326
|
+
}) | undefined) => zod.ZodBigInt;
|
|
327
|
+
date: (params?: ({
|
|
328
|
+
errorMap?: zod.ZodErrorMap | undefined;
|
|
329
|
+
invalid_type_error?: string | undefined;
|
|
330
|
+
required_error?: string | undefined;
|
|
331
|
+
description?: string | undefined;
|
|
332
|
+
} & {
|
|
333
|
+
coerce?: boolean | undefined;
|
|
334
|
+
}) | undefined) => zod.ZodDate;
|
|
335
|
+
};
|
|
336
|
+
any: (params?: zod.RawCreateParams) => zod.ZodAny;
|
|
337
|
+
array: <T extends ZodTypeAny>(schema: T, params?: zod.RawCreateParams) => zod.ZodArray<T, "many">;
|
|
338
|
+
bigint: (params?: ({
|
|
339
|
+
errorMap?: zod.ZodErrorMap | undefined;
|
|
340
|
+
invalid_type_error?: string | undefined;
|
|
341
|
+
required_error?: string | undefined;
|
|
342
|
+
description?: string | undefined;
|
|
343
|
+
} & {
|
|
344
|
+
coerce?: boolean | undefined;
|
|
345
|
+
}) | undefined) => zod.ZodBigInt;
|
|
346
|
+
boolean: (params?: ({
|
|
347
|
+
errorMap?: zod.ZodErrorMap | undefined;
|
|
348
|
+
invalid_type_error?: string | undefined;
|
|
349
|
+
required_error?: string | undefined;
|
|
350
|
+
description?: string | undefined;
|
|
351
|
+
} & {
|
|
352
|
+
coerce?: boolean | undefined;
|
|
353
|
+
}) | undefined) => zod.ZodBoolean;
|
|
354
|
+
date: (params?: ({
|
|
355
|
+
errorMap?: zod.ZodErrorMap | undefined;
|
|
356
|
+
invalid_type_error?: string | undefined;
|
|
357
|
+
required_error?: string | undefined;
|
|
358
|
+
description?: string | undefined;
|
|
359
|
+
} & {
|
|
360
|
+
coerce?: boolean | undefined;
|
|
361
|
+
}) | undefined) => zod.ZodDate;
|
|
362
|
+
discriminatedUnion: typeof zod.ZodDiscriminatedUnion.create;
|
|
363
|
+
effect: <I extends ZodTypeAny>(schema: I, effect: zod.Effect<I["_output"]>, params?: zod.RawCreateParams) => ZodEffects<I, I["_output"], zod.input<I>>;
|
|
364
|
+
enum: {
|
|
365
|
+
<U extends string, T extends Readonly<[U, ...U[]]>>(values: T, params?: zod.RawCreateParams): zod.ZodEnum<zod.Writeable<T>>;
|
|
366
|
+
<U extends string, T extends [U, ...U[]]>(values: T, params?: zod.RawCreateParams): zod.ZodEnum<T>;
|
|
367
|
+
};
|
|
368
|
+
function: typeof zod.ZodFunction.create;
|
|
369
|
+
instanceof: <T extends abstract new (..._: any[]) => {}>(cls: T, params?: Partial<zod.util.Omit<zod.ZodCustomIssue, "code">> & {
|
|
370
|
+
fatal?: boolean;
|
|
371
|
+
}) => ZodType<InstanceType<T>, zod.ZodTypeDef, InstanceType<T>>;
|
|
372
|
+
intersection: <T extends ZodTypeAny, U extends ZodTypeAny>(left: T, right: U, params?: zod.RawCreateParams) => zod.ZodIntersection<T, U>;
|
|
373
|
+
lazy: <T extends ZodTypeAny>(getter: () => T, params?: zod.RawCreateParams) => zod.ZodLazy<T>;
|
|
374
|
+
literal: <T extends zod.Primitive>(value: T, params?: zod.RawCreateParams) => zod.ZodLiteral<T>;
|
|
375
|
+
map: <Key extends ZodTypeAny = zod.ZodTypeAny, Value extends ZodTypeAny = zod.ZodTypeAny>(keyType: Key, valueType: Value, params?: zod.RawCreateParams) => zod.ZodMap<Key, Value>;
|
|
376
|
+
nan: (params?: zod.RawCreateParams) => zod.ZodNaN;
|
|
377
|
+
nativeEnum: <T extends zod.EnumLike>(values: T, params?: zod.RawCreateParams) => zod.ZodNativeEnum<T>;
|
|
378
|
+
never: (params?: zod.RawCreateParams) => zod.ZodNever;
|
|
379
|
+
null: (params?: zod.RawCreateParams) => zod.ZodNull;
|
|
380
|
+
nullable: <T extends ZodTypeAny>(type: T, params?: zod.RawCreateParams) => zod.ZodNullable<T>;
|
|
381
|
+
number: (params?: ({
|
|
382
|
+
errorMap?: zod.ZodErrorMap | undefined;
|
|
383
|
+
invalid_type_error?: string | undefined;
|
|
384
|
+
required_error?: string | undefined;
|
|
385
|
+
description?: string | undefined;
|
|
386
|
+
} & {
|
|
387
|
+
coerce?: boolean | undefined;
|
|
388
|
+
}) | undefined) => ZodNumber;
|
|
389
|
+
object: <T extends zod.ZodRawShape>(shape: T, params?: zod.RawCreateParams) => ZodObject<T, "strip", ZodTypeAny, { [k_1 in keyof zod.objectUtil.addQuestionMarks<zod.baseObjectOutputType<T>, { [k in keyof zod.baseObjectOutputType<T>]: undefined extends zod.baseObjectOutputType<T>[k] ? never : k; }[keyof T]>]: zod.objectUtil.addQuestionMarks<zod.baseObjectOutputType<T>, { [k in keyof zod.baseObjectOutputType<T>]: undefined extends zod.baseObjectOutputType<T>[k] ? never : k; }[keyof T]>[k_1]; }, { [k_2 in keyof zod.baseObjectInputType<T>]: zod.baseObjectInputType<T>[k_2]; }>;
|
|
390
|
+
oboolean: () => zod.ZodOptional<zod.ZodBoolean>;
|
|
391
|
+
onumber: () => zod.ZodOptional<ZodNumber>;
|
|
392
|
+
optional: <T extends ZodTypeAny>(type: T, params?: zod.RawCreateParams) => zod.ZodOptional<T>;
|
|
393
|
+
ostring: () => zod.ZodOptional<ZodString>;
|
|
394
|
+
pipeline: typeof zod.ZodPipeline.create;
|
|
395
|
+
preprocess: <I extends ZodTypeAny>(preprocess: (arg: unknown, ctx: zod.RefinementCtx) => unknown, schema: I, params?: zod.RawCreateParams) => ZodEffects<I, I["_output"], unknown>;
|
|
396
|
+
promise: <T extends ZodTypeAny>(schema: T, params?: zod.RawCreateParams) => zod.ZodPromise<T>;
|
|
397
|
+
record: typeof zod.ZodRecord.create;
|
|
398
|
+
set: <Value extends ZodTypeAny = zod.ZodTypeAny>(valueType: Value, params?: zod.RawCreateParams) => zod.ZodSet<Value>;
|
|
399
|
+
strictObject: <T extends zod.ZodRawShape>(shape: T, params?: zod.RawCreateParams) => ZodObject<T, "strict", ZodTypeAny, { [k_1 in keyof zod.objectUtil.addQuestionMarks<zod.baseObjectOutputType<T>, { [k in keyof zod.baseObjectOutputType<T>]: undefined extends zod.baseObjectOutputType<T>[k] ? never : k; }[keyof T]>]: zod.objectUtil.addQuestionMarks<zod.baseObjectOutputType<T>, { [k in keyof zod.baseObjectOutputType<T>]: undefined extends zod.baseObjectOutputType<T>[k] ? never : k; }[keyof T]>[k_1]; }, { [k_2 in keyof zod.baseObjectInputType<T>]: zod.baseObjectInputType<T>[k_2]; }>;
|
|
400
|
+
symbol: (params?: zod.RawCreateParams) => zod.ZodSymbol;
|
|
401
|
+
transformer: <I extends ZodTypeAny>(schema: I, effect: zod.Effect<I["_output"]>, params?: zod.RawCreateParams) => ZodEffects<I, I["_output"], zod.input<I>>;
|
|
402
|
+
tuple: <T extends [] | [ZodTypeAny, ...ZodTypeAny[]]>(schemas: T, params?: zod.RawCreateParams) => zod.ZodTuple<T, null>;
|
|
403
|
+
undefined: (params?: zod.RawCreateParams) => zod.ZodUndefined;
|
|
404
|
+
union: <T extends readonly [ZodTypeAny, ZodTypeAny, ...ZodTypeAny[]]>(types: T, params?: zod.RawCreateParams) => zod.ZodUnion<T>;
|
|
405
|
+
unknown: (params?: zod.RawCreateParams) => zod.ZodUnknown;
|
|
406
|
+
void: (params?: zod.RawCreateParams) => zod.ZodVoid;
|
|
407
|
+
NEVER: never;
|
|
408
|
+
ZodIssueCode: {
|
|
409
|
+
invalid_type: "invalid_type";
|
|
410
|
+
invalid_literal: "invalid_literal";
|
|
411
|
+
custom: "custom";
|
|
412
|
+
invalid_union: "invalid_union";
|
|
413
|
+
invalid_union_discriminator: "invalid_union_discriminator";
|
|
414
|
+
invalid_enum_value: "invalid_enum_value";
|
|
415
|
+
unrecognized_keys: "unrecognized_keys";
|
|
416
|
+
invalid_arguments: "invalid_arguments";
|
|
417
|
+
invalid_return_type: "invalid_return_type";
|
|
418
|
+
invalid_date: "invalid_date";
|
|
419
|
+
invalid_string: "invalid_string";
|
|
420
|
+
too_small: "too_small";
|
|
421
|
+
too_big: "too_big";
|
|
422
|
+
invalid_intersection_types: "invalid_intersection_types";
|
|
423
|
+
not_multiple_of: "not_multiple_of";
|
|
424
|
+
not_finite: "not_finite";
|
|
425
|
+
};
|
|
426
|
+
quotelessJson: (obj: any) => string;
|
|
427
|
+
ZodError: typeof zod.ZodError;
|
|
428
|
+
};
|
|
429
|
+
export * from 'zod';
|
|
430
|
+
export { z };
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint-disable @typescript-eslint/explicit-module-boundary-types, max-lines */
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
15
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
16
|
+
};
|
|
17
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
18
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.z = exports.preprocessBooleanFromString = exports.preprocessBooleanFromQueryString = exports.preprocessNumberFromQueryString = exports.preprocessArrayFromQueryString = void 0;
|
|
22
|
+
const url_1 = require("url");
|
|
23
|
+
const zod_1 = require("zod");
|
|
24
|
+
const validator_1 = __importDefault(require("validator"));
|
|
25
|
+
const min_1 = require("libphonenumber-js/min");
|
|
26
|
+
const api_1 = require("../lib/api");
|
|
27
|
+
const money_1 = require("../lib/money/money");
|
|
28
|
+
const supportedCurrencies_1 = require("../lib/money/supportedCurrencies");
|
|
29
|
+
const language_1 = require("../lib/negotiator/language");
|
|
30
|
+
(0, api_1.extendZodWithOpenApi)(zod_1.z);
|
|
31
|
+
// Regular expressions
|
|
32
|
+
const SAFE_CHARACTERS_REGEX = /^[\w !&()+,./:@`|£À-ÿāăąćĉċčđēėęěĝğģĥħĩīįİıĵķĸĺļłńņōőœŗřśŝşšţŦũūŭůűųŵŷźżžơưếệ–-]*$/i;
|
|
33
|
+
const NO_HTTP_REGEX = /^((?!http).)*$/i;
|
|
34
|
+
const NO_FTP_REGEX = /^((?!ftp).)*$/i;
|
|
35
|
+
const ALPHANUMERIC_REGEX = /^[\da-z]+$/i;
|
|
36
|
+
const ONBOARDING_BUSINESS_ENTITY_REGEX = /^[\w !&'()*+,./£À-ÿāăąćĉċčđēėęěĝğģĥħĩīįİıĵķĸĺļłńņōőœŗřśŝşšţŦũūŭůűųŵŷźżžơưếệ''-]+$/i;
|
|
37
|
+
const ONBOARDING_NAME_REGEX = /^[\s'.A-Za-z£À-žơưếệ''-]+$/;
|
|
38
|
+
const COUNTRY_CODE_REGEX = /^[A-Z]{2}$/;
|
|
39
|
+
const PASSWORD_REQUIREMENTS = {
|
|
40
|
+
minLength: 9,
|
|
41
|
+
minNumbers: 1,
|
|
42
|
+
minLowercase: 1,
|
|
43
|
+
minUppercase: 1,
|
|
44
|
+
minSymbols: 1,
|
|
45
|
+
};
|
|
46
|
+
// Helper functions for query string preprocessing
|
|
47
|
+
const preprocessArrayFromQueryString = (input) => {
|
|
48
|
+
if (typeof input !== 'string')
|
|
49
|
+
return undefined;
|
|
50
|
+
return input.split(',');
|
|
51
|
+
};
|
|
52
|
+
exports.preprocessArrayFromQueryString = preprocessArrayFromQueryString;
|
|
53
|
+
const preprocessNumberFromQueryString = (input) => {
|
|
54
|
+
if (input === '')
|
|
55
|
+
return undefined;
|
|
56
|
+
return input ? Number(input) : input;
|
|
57
|
+
};
|
|
58
|
+
exports.preprocessNumberFromQueryString = preprocessNumberFromQueryString;
|
|
59
|
+
const preprocessBooleanFromQueryString = (input) => {
|
|
60
|
+
if (input === '')
|
|
61
|
+
return undefined;
|
|
62
|
+
if (typeof input !== 'string')
|
|
63
|
+
return undefined;
|
|
64
|
+
return input.toLowerCase() !== 'false';
|
|
65
|
+
};
|
|
66
|
+
exports.preprocessBooleanFromQueryString = preprocessBooleanFromQueryString;
|
|
67
|
+
// Alias for backward compatibility
|
|
68
|
+
exports.preprocessBooleanFromString = exports.preprocessBooleanFromQueryString;
|
|
69
|
+
// Helper function for money validation
|
|
70
|
+
const isValidMoneyAmount = (number) => validator_1.default.isCurrency(number.toString(10), {
|
|
71
|
+
require_decimal: false,
|
|
72
|
+
allow_decimal: true,
|
|
73
|
+
negative_sign_after_digits: false,
|
|
74
|
+
allow_negatives: true,
|
|
75
|
+
digits_after_decimal: [1, 2],
|
|
76
|
+
});
|
|
77
|
+
// Helper function for updating money fields with currency
|
|
78
|
+
const updateMoneyFieldsWithCurrency = (object) => {
|
|
79
|
+
const currency = object.currency;
|
|
80
|
+
Object.keys(object).forEach(key => {
|
|
81
|
+
const value = object[key];
|
|
82
|
+
if (value instanceof money_1.Money) {
|
|
83
|
+
if (!currency) {
|
|
84
|
+
throw new Error('currency is required to convert money fields');
|
|
85
|
+
}
|
|
86
|
+
// eslint-disable-next-line no-param-reassign
|
|
87
|
+
object[key] = money_1.Money.fromAmount(value.getAmount(), currency);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
// Extended zod with custom validators
|
|
92
|
+
const z = {
|
|
93
|
+
...zod_1.z,
|
|
94
|
+
// Override string to always trim
|
|
95
|
+
string: () => zod_1.z.string().trim(),
|
|
96
|
+
// String validators
|
|
97
|
+
safeString: () => z
|
|
98
|
+
.string()
|
|
99
|
+
.trim()
|
|
100
|
+
.regex(SAFE_CHARACTERS_REGEX)
|
|
101
|
+
.regex(NO_HTTP_REGEX)
|
|
102
|
+
.regex(NO_FTP_REGEX),
|
|
103
|
+
safeText: () => z.string().trim().regex(NO_HTTP_REGEX).regex(NO_FTP_REGEX),
|
|
104
|
+
safeBusinessStringForOnboarding: () => zod_1.z
|
|
105
|
+
.string()
|
|
106
|
+
.regex(ONBOARDING_BUSINESS_ENTITY_REGEX)
|
|
107
|
+
.max(255)
|
|
108
|
+
.trim()
|
|
109
|
+
.min(1)
|
|
110
|
+
.transform(value => value.trimEnd())
|
|
111
|
+
.openapi({
|
|
112
|
+
type: 'string',
|
|
113
|
+
example: 'My Business',
|
|
114
|
+
}),
|
|
115
|
+
safeNameForOnboarding: () => zod_1.z
|
|
116
|
+
.string()
|
|
117
|
+
.regex(ONBOARDING_NAME_REGEX)
|
|
118
|
+
.max(255)
|
|
119
|
+
.trim()
|
|
120
|
+
.min(1)
|
|
121
|
+
.transform(value => value.trimEnd())
|
|
122
|
+
.openapi({
|
|
123
|
+
type: 'string',
|
|
124
|
+
example: 'Alex',
|
|
125
|
+
}),
|
|
126
|
+
nonemptyString: () => z.string().trim().min(1),
|
|
127
|
+
alphaNumericString: () => zod_1.z.string().regex(ALPHANUMERIC_REGEX),
|
|
128
|
+
tableId: () => z.string(),
|
|
129
|
+
// UUID validators
|
|
130
|
+
uuid: () => zod_1.z.string().trim().uuid(),
|
|
131
|
+
uuidv4: () => zod_1.z
|
|
132
|
+
.string()
|
|
133
|
+
.length(36)
|
|
134
|
+
.refine(value => validator_1.default.isUUID(value, '4')),
|
|
135
|
+
// Email validator
|
|
136
|
+
email: () => zod_1.z
|
|
137
|
+
.string()
|
|
138
|
+
.trim()
|
|
139
|
+
.email()
|
|
140
|
+
.max(255)
|
|
141
|
+
.refine(value => validator_1.default.isEmail(value, {
|
|
142
|
+
allow_display_name: false,
|
|
143
|
+
require_display_name: false,
|
|
144
|
+
allow_utf8_local_part: true,
|
|
145
|
+
require_tld: true,
|
|
146
|
+
allow_ip_domain: false,
|
|
147
|
+
// @ts-expect-error: double escape as this is passed into new RegExp("[${blacklisted_chars}]")
|
|
148
|
+
blacklisted_chars: "=',\\\\",
|
|
149
|
+
}))
|
|
150
|
+
.openapi({
|
|
151
|
+
type: 'string',
|
|
152
|
+
example: 'test@nexenio.com',
|
|
153
|
+
}),
|
|
154
|
+
// Phone number validators
|
|
155
|
+
phoneNumber: () => zod_1.z
|
|
156
|
+
.string()
|
|
157
|
+
.trim()
|
|
158
|
+
.max(32)
|
|
159
|
+
.refine(value => {
|
|
160
|
+
return (0, min_1.parsePhoneNumber)(value, 'DE').isValid();
|
|
161
|
+
}, {
|
|
162
|
+
message: 'invalid phone number',
|
|
163
|
+
})
|
|
164
|
+
.transform(value => {
|
|
165
|
+
return (0, min_1.parsePhoneNumber)(value, 'DE').formatInternational();
|
|
166
|
+
})
|
|
167
|
+
.openapi({
|
|
168
|
+
type: 'string',
|
|
169
|
+
example: '+4917712345678',
|
|
170
|
+
}),
|
|
171
|
+
nullablePhoneNumber: () => zod_1.z
|
|
172
|
+
.string()
|
|
173
|
+
.trim()
|
|
174
|
+
.max(32)
|
|
175
|
+
.refine(value => {
|
|
176
|
+
if (value === '')
|
|
177
|
+
return true;
|
|
178
|
+
return (0, min_1.parsePhoneNumber)(value, 'DE').isValid();
|
|
179
|
+
}, {
|
|
180
|
+
message: 'invalid phone number',
|
|
181
|
+
})
|
|
182
|
+
.transform(value => {
|
|
183
|
+
if (value === '')
|
|
184
|
+
return null;
|
|
185
|
+
return (0, min_1.parsePhoneNumber)(value, 'DE').formatInternational();
|
|
186
|
+
})
|
|
187
|
+
.openapi({
|
|
188
|
+
type: 'string',
|
|
189
|
+
example: '+4917712345678',
|
|
190
|
+
}),
|
|
191
|
+
// Password validator
|
|
192
|
+
strongPassword: () => zod_1.z
|
|
193
|
+
.string()
|
|
194
|
+
.refine(value => validator_1.default.isStrongPassword(value, PASSWORD_REQUIREMENTS)),
|
|
195
|
+
// Postal code validators
|
|
196
|
+
zipCode: (locale) => z
|
|
197
|
+
.string()
|
|
198
|
+
.trim()
|
|
199
|
+
.max(255)
|
|
200
|
+
.refine(value => validator_1.default.isPostalCode(value, locale || 'any')),
|
|
201
|
+
countryCode: () => zod_1.z.string().regex(COUNTRY_CODE_REGEX),
|
|
202
|
+
// Money validators
|
|
203
|
+
moneyDecimalString: (locale) => zod_1.z
|
|
204
|
+
.string()
|
|
205
|
+
.max(255)
|
|
206
|
+
.refine(value => validator_1.default.isCurrency(value, {
|
|
207
|
+
require_decimal: true,
|
|
208
|
+
negative_sign_after_digits: false,
|
|
209
|
+
allow_negatives: true,
|
|
210
|
+
digits_after_decimal: [2],
|
|
211
|
+
symbol: '€',
|
|
212
|
+
symbol_after_digits: true,
|
|
213
|
+
allow_space_after_digits: true,
|
|
214
|
+
decimal_separator: locale === 'de' ? ',' : '.',
|
|
215
|
+
thousands_separator: locale === 'de' ? '.' : ',',
|
|
216
|
+
})),
|
|
217
|
+
moneyFromFloat: () => z
|
|
218
|
+
.number()
|
|
219
|
+
.refine(isValidMoneyAmount)
|
|
220
|
+
.transform(value => money_1.Money.fromFloat(value, supportedCurrencies_1.SupportedCurrencies.EUR))
|
|
221
|
+
.openapi({
|
|
222
|
+
type: 'number',
|
|
223
|
+
}),
|
|
224
|
+
moneyFromInt: () => z
|
|
225
|
+
.number()
|
|
226
|
+
.int()
|
|
227
|
+
.nonnegative()
|
|
228
|
+
.transform(value => money_1.Money.fromAmount(value, supportedCurrencies_1.SupportedCurrencies.EUR))
|
|
229
|
+
.openapi({
|
|
230
|
+
type: 'integer',
|
|
231
|
+
}),
|
|
232
|
+
convertMoneyFieldsToCurrency: (schema) => {
|
|
233
|
+
return schema.refine((object) => {
|
|
234
|
+
try {
|
|
235
|
+
updateMoneyFieldsWithCurrency(object);
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
}, {
|
|
242
|
+
message: 'Currency is required to convert money fields.',
|
|
243
|
+
path: ['currency'],
|
|
244
|
+
});
|
|
245
|
+
},
|
|
246
|
+
// Number validators
|
|
247
|
+
unixTimestamp: () => zod_1.z.number().int().positive(),
|
|
248
|
+
integerString: (options = {}) => z
|
|
249
|
+
.integerStringRaw(options)
|
|
250
|
+
.transform(value => Number.parseInt(value, 10))
|
|
251
|
+
.openapi({
|
|
252
|
+
type: 'string',
|
|
253
|
+
}),
|
|
254
|
+
integerStringRaw: (options = {}) => zod_1.z
|
|
255
|
+
.string()
|
|
256
|
+
.max(options.maxLength || 17)
|
|
257
|
+
.refine(value => validator_1.default.isInt(value, {
|
|
258
|
+
lt: options.lt || Number.MAX_SAFE_INTEGER,
|
|
259
|
+
gt: options.gt || Number.MIN_SAFE_INTEGER,
|
|
260
|
+
allow_leading_zeroes: false,
|
|
261
|
+
})),
|
|
262
|
+
bigIntegerString: () => zod_1.z
|
|
263
|
+
.string()
|
|
264
|
+
.max(2048)
|
|
265
|
+
.refine(value => validator_1.default.isInt(value, {
|
|
266
|
+
allow_leading_zeroes: false,
|
|
267
|
+
})),
|
|
268
|
+
floatString: (options) => zod_1.z
|
|
269
|
+
.string()
|
|
270
|
+
.max(options?.maxLength || 17)
|
|
271
|
+
.refine(value => validator_1.default.isFloat(value, {
|
|
272
|
+
lt: options?.lt || Number.MAX_SAFE_INTEGER,
|
|
273
|
+
gt: options?.gt || Number.MIN_SAFE_INTEGER,
|
|
274
|
+
}))
|
|
275
|
+
.transform(value => Number.parseFloat(value))
|
|
276
|
+
.openapi({
|
|
277
|
+
type: 'string',
|
|
278
|
+
}),
|
|
279
|
+
// Encoding validators
|
|
280
|
+
hex: ({ min, max, length, rawLength, } = {}) => zod_1.z
|
|
281
|
+
.string()
|
|
282
|
+
.min(min)
|
|
283
|
+
.max(max)
|
|
284
|
+
.length(length)
|
|
285
|
+
.refine(value => {
|
|
286
|
+
if (!validator_1.default.isHexadecimal(value))
|
|
287
|
+
return false;
|
|
288
|
+
if (!rawLength)
|
|
289
|
+
return true;
|
|
290
|
+
return Buffer.from(value, 'hex').length === rawLength;
|
|
291
|
+
}),
|
|
292
|
+
sha256: () => z.hex({ length: 64, rawLength: 32 }),
|
|
293
|
+
base64: ({ min, max, length, rawLength, isBase64Url = false, } = {}) => {
|
|
294
|
+
let schema = zod_1.z.string();
|
|
295
|
+
if (min !== undefined)
|
|
296
|
+
schema = schema.min(min);
|
|
297
|
+
if (max !== undefined)
|
|
298
|
+
schema = schema.max(max);
|
|
299
|
+
if (length !== undefined)
|
|
300
|
+
schema = schema.length(length);
|
|
301
|
+
return schema.refine(value => {
|
|
302
|
+
if (!validator_1.default.isBase64(value, { urlSafe: isBase64Url }))
|
|
303
|
+
return false;
|
|
304
|
+
if (!rawLength)
|
|
305
|
+
return true;
|
|
306
|
+
return (Buffer.from(value, isBase64Url ? 'base64url' : 'base64').length ===
|
|
307
|
+
rawLength);
|
|
308
|
+
});
|
|
309
|
+
},
|
|
310
|
+
bearerToken: () => zod_1.z
|
|
311
|
+
.string()
|
|
312
|
+
.trim()
|
|
313
|
+
.min(28)
|
|
314
|
+
.max(255)
|
|
315
|
+
.refine(value => {
|
|
316
|
+
return validator_1.default.isBase64(value.replace('Bearer ', ''));
|
|
317
|
+
})
|
|
318
|
+
.transform(value => value.replace('Bearer ', ''))
|
|
319
|
+
.openapi({
|
|
320
|
+
type: 'string',
|
|
321
|
+
}),
|
|
322
|
+
jwt: ({ max }) => z
|
|
323
|
+
.string()
|
|
324
|
+
.trim()
|
|
325
|
+
.max(max)
|
|
326
|
+
.refine(value => validator_1.default.isJWT(value)),
|
|
327
|
+
// Cryptographic validators
|
|
328
|
+
ecPublicKey: () => z.base64({ length: 88, rawLength: 65 }),
|
|
329
|
+
ecCompressedPublicKey: () => z.base64({ length: 44, rawLength: 33 }),
|
|
330
|
+
uncompressedECPublicKey: () => {
|
|
331
|
+
let schema = zod_1.z.string();
|
|
332
|
+
schema = schema.length(88);
|
|
333
|
+
return schema.refine(value => {
|
|
334
|
+
if (!validator_1.default.isBase64(value))
|
|
335
|
+
return false;
|
|
336
|
+
return Buffer.from(value, 'base64').length === 65;
|
|
337
|
+
});
|
|
338
|
+
},
|
|
339
|
+
ecSignature: () => z.base64({ max: 120 }),
|
|
340
|
+
iv: () => z.base64({ length: 24, rawLength: 16 }),
|
|
341
|
+
mac: () => z.base64({ length: 44, rawLength: 32 }),
|
|
342
|
+
traceId: () => z.base64({ length: 24, rawLength: 16 }),
|
|
343
|
+
// Date validators
|
|
344
|
+
isoDateString: () => z
|
|
345
|
+
.string()
|
|
346
|
+
.trim()
|
|
347
|
+
.refine(value => {
|
|
348
|
+
return validator_1.default.isISO8601(value, {
|
|
349
|
+
strict: true,
|
|
350
|
+
});
|
|
351
|
+
})
|
|
352
|
+
.openapi({
|
|
353
|
+
type: 'string',
|
|
354
|
+
format: 'date-time',
|
|
355
|
+
example: '2021-01-30T08:30:00Z',
|
|
356
|
+
}),
|
|
357
|
+
rfc3339String: () => z
|
|
358
|
+
.string()
|
|
359
|
+
.trim()
|
|
360
|
+
.refine(value => {
|
|
361
|
+
return validator_1.default.isRFC3339(value);
|
|
362
|
+
})
|
|
363
|
+
.openapi({
|
|
364
|
+
type: 'string',
|
|
365
|
+
format: 'date-time',
|
|
366
|
+
example: '2021-01-30T08:30:00Z',
|
|
367
|
+
}),
|
|
368
|
+
iso8601Date: () => zod_1.z.string().refine(value => validator_1.default.isISO8601(value)),
|
|
369
|
+
// URL validators
|
|
370
|
+
urlHttpsString: () => zod_1.z
|
|
371
|
+
.string()
|
|
372
|
+
.max(255)
|
|
373
|
+
.refine(value => validator_1.default.isURL(value, {
|
|
374
|
+
require_protocol: true,
|
|
375
|
+
protocols: ['https'],
|
|
376
|
+
allow_protocol_relative_urls: false,
|
|
377
|
+
disallow_auth: true,
|
|
378
|
+
require_host: true,
|
|
379
|
+
}) && validator_1.default.isFQDN(new url_1.URL(value).hostname), {
|
|
380
|
+
message: 'invalid url',
|
|
381
|
+
}),
|
|
382
|
+
urlHttpOrHttpsString: () => zod_1.z
|
|
383
|
+
.string()
|
|
384
|
+
.max(255)
|
|
385
|
+
.refine(value => validator_1.default.isURL(value, {
|
|
386
|
+
require_protocol: true,
|
|
387
|
+
protocols: ['http', 'https'],
|
|
388
|
+
allow_protocol_relative_urls: false,
|
|
389
|
+
disallow_auth: true,
|
|
390
|
+
require_host: true,
|
|
391
|
+
}) && validator_1.default.isFQDN(new url_1.URL(value).hostname), {
|
|
392
|
+
message: 'invalid url',
|
|
393
|
+
}),
|
|
394
|
+
// Language validator
|
|
395
|
+
language: () => z.enum(language_1.AVAILABLE_LANGUAGES),
|
|
396
|
+
// DCC/DSGC validators (for COVID certificate validation)
|
|
397
|
+
dsgcPayload: () => zod_1.z.object({
|
|
398
|
+
certificates: zod_1.z.array(zod_1.z.object({
|
|
399
|
+
certificateType: zod_1.z.string(),
|
|
400
|
+
country: zod_1.z.string(),
|
|
401
|
+
kid: zod_1.z.string(),
|
|
402
|
+
rawData: zod_1.z.string(),
|
|
403
|
+
signature: zod_1.z.string(),
|
|
404
|
+
thumbprint: zod_1.z.string(),
|
|
405
|
+
timestamp: zod_1.z.string(),
|
|
406
|
+
})),
|
|
407
|
+
}),
|
|
408
|
+
dccListPayload: () => zod_1.z.array(zod_1.z.object({
|
|
409
|
+
identifier: zod_1.z.string(),
|
|
410
|
+
version: zod_1.z.string(),
|
|
411
|
+
country: zod_1.z.string().length(2),
|
|
412
|
+
hash: zod_1.z.string(),
|
|
413
|
+
})),
|
|
414
|
+
dccRulePayload: () => zod_1.z.object({
|
|
415
|
+
Identifier: zod_1.z.string(),
|
|
416
|
+
Type: zod_1.z.string(),
|
|
417
|
+
Country: zod_1.z.string().length(2),
|
|
418
|
+
Version: zod_1.z.string(),
|
|
419
|
+
SchemaVersion: zod_1.z.string(),
|
|
420
|
+
Engine: zod_1.z.string(),
|
|
421
|
+
EngineVersion: zod_1.z.string(),
|
|
422
|
+
CertificateType: zod_1.z.string(),
|
|
423
|
+
Description: zod_1.z.array(zod_1.z.object({ lang: zod_1.z.string().length(2), desc: zod_1.z.string() })),
|
|
424
|
+
ValidFrom: zod_1.z.string(),
|
|
425
|
+
ValidTo: zod_1.z.string(),
|
|
426
|
+
AffectedFields: zod_1.z.array(zod_1.z.string()),
|
|
427
|
+
Logic: zod_1.z.any(),
|
|
428
|
+
}),
|
|
429
|
+
};
|
|
430
|
+
exports.z = z;
|
|
431
|
+
__exportStar(require("zod"), exports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lucaapp/service-utils",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.11.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"@types/node": "22.13.11",
|
|
29
29
|
"@types/response-time": "^2.3.9",
|
|
30
30
|
"@types/swagger-ui-express": "4.1.8",
|
|
31
|
+
"@types/validator": "13.7.1",
|
|
31
32
|
"axios": "^1.12.2",
|
|
32
33
|
"axios-rate-limit": "^1.4.0",
|
|
33
34
|
"axios-retry": "^4.5.0",
|
|
@@ -52,6 +53,7 @@
|
|
|
52
53
|
"swagger-ui-express": "5.0.1",
|
|
53
54
|
"url-value-parser": "^2.2.0",
|
|
54
55
|
"uuid": "^9.0.0",
|
|
56
|
+
"validator": "13.7.0",
|
|
55
57
|
"zod": "3.22.3"
|
|
56
58
|
},
|
|
57
59
|
"devDependencies": {
|