feed-common 1.77.1 → 1.77.2
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/.vscode/settings.json +1 -1
- package/CHANGELOG.md +7 -0
- package/dist/constants/profile.constants.d.ts +12 -0
- package/dist/constants/profile.constants.d.ts.map +1 -1
- package/dist/constants/profile.constants.js +39 -1
- package/dist/constants/profile.constants.js.map +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/sources/country.source.d.ts +5 -0
- package/dist/sources/country.source.d.ts.map +1 -0
- package/dist/sources/country.source.js +78 -0
- package/dist/sources/country.source.js.map +1 -0
- package/dist/sources/currency.source.d.ts.map +1 -1
- package/dist/sources/currency.source.js +0 -1
- package/dist/sources/currency.source.js.map +1 -1
- package/dist/sources/ebay-gallery-type.source.d.ts +5 -0
- package/dist/sources/ebay-gallery-type.source.d.ts.map +1 -0
- package/dist/sources/ebay-gallery-type.source.js +5 -0
- package/dist/sources/ebay-gallery-type.source.js.map +1 -0
- package/dist/sources/ebay-inventory-tracking.source.d.ts +3 -0
- package/dist/sources/ebay-inventory-tracking.source.d.ts.map +1 -0
- package/dist/sources/ebay-inventory-tracking.source.js +11 -0
- package/dist/sources/ebay-inventory-tracking.source.js.map +1 -0
- package/dist/sources/ebay-listing-type.source.d.ts +5 -0
- package/dist/sources/ebay-listing-type.source.d.ts.map +1 -0
- package/dist/sources/ebay-listing-type.source.js +5 -0
- package/dist/sources/ebay-listing-type.source.js.map +1 -0
- package/dist/sources/ebay-yes-no.source.d.ts +5 -0
- package/dist/sources/ebay-yes-no.source.d.ts.map +1 -0
- package/dist/sources/ebay-yes-no.source.js +2 -0
- package/dist/sources/ebay-yes-no.source.js.map +1 -0
- package/dist/sources/google-availability.source.d.ts +5 -0
- package/dist/sources/google-availability.source.d.ts.map +1 -0
- package/dist/sources/google-availability.source.js +7 -0
- package/dist/sources/google-availability.source.js.map +1 -0
- package/dist/sources/language.source.d.ts +5 -0
- package/dist/sources/language.source.d.ts.map +1 -0
- package/dist/sources/language.source.js +31 -0
- package/dist/sources/language.source.js.map +1 -0
- package/dist/utils/feed-templates/{index.d.ts → common-schemas.d.ts} +24 -29
- package/dist/utils/feed-templates/common-schemas.d.ts.map +1 -0
- package/dist/utils/feed-templates/{index.js → common-schemas.js} +668 -176
- package/dist/utils/feed-templates/common-schemas.js.map +1 -0
- package/dist/utils/feed-templates/common.d.ts +20 -0
- package/dist/utils/feed-templates/common.d.ts.map +1 -0
- package/dist/utils/feed-templates/common.js +60 -0
- package/dist/utils/feed-templates/common.js.map +1 -0
- package/dist/utils/feed-templates/ebay.template.d.ts +1 -1
- package/dist/utils/feed-templates/ebay.template.d.ts.map +1 -1
- package/dist/utils/feed-templates/ebay.template.js +189 -2
- package/dist/utils/feed-templates/ebay.template.js.map +1 -1
- package/dist/utils/feed-templates/facebook.template.d.ts.map +1 -1
- package/dist/utils/feed-templates/facebook.template.js +2 -1
- package/dist/utils/feed-templates/facebook.template.js.map +1 -1
- package/dist/utils/feed-templates/google-api.template.d.ts.map +1 -1
- package/dist/utils/feed-templates/google-api.template.js +19 -7
- package/dist/utils/feed-templates/google-api.template.js.map +1 -1
- package/dist/utils/feed-templates/google.template.d.ts.map +1 -1
- package/dist/utils/feed-templates/google.template.js +7 -15
- package/dist/utils/feed-templates/google.template.js.map +1 -1
- package/dist/utils/feed-templates/microsoft.template.d.ts.map +1 -1
- package/dist/utils/feed-templates/microsoft.template.js +11 -7
- package/dist/utils/feed-templates/microsoft.template.js.map +1 -1
- package/dist/utils/feed-templates/template-utils.d.ts +4 -0
- package/dist/utils/feed-templates/template-utils.d.ts.map +1 -0
- package/dist/utils/feed-templates/template-utils.js +29 -0
- package/dist/utils/feed-templates/template-utils.js.map +1 -0
- package/dist/utils/feed-templates/tiktok.template.d.ts.map +1 -1
- package/dist/utils/feed-templates/tiktok.template.js +2 -1
- package/dist/utils/feed-templates/tiktok.template.js.map +1 -1
- package/dist/utils/profile.d.ts +2 -1
- package/dist/utils/profile.d.ts.map +1 -1
- package/dist/utils/profile.js +82 -1
- package/dist/utils/profile.js.map +1 -1
- package/dist/utils/utils.d.ts +2 -0
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +23 -3
- package/dist/utils/utils.js.map +1 -1
- package/package.json +5 -4
- package/src/constants/profile.constants.ts +39 -1
- package/src/index.ts +11 -1
- package/src/sources/country.source.ts +77 -0
- package/src/sources/currency.source.ts +0 -1
- package/src/sources/ebay-gallery-type.source.ts +4 -0
- package/src/sources/ebay-inventory-tracking.source.ts +12 -0
- package/src/sources/ebay-listing-type.source.ts +4 -0
- package/src/sources/ebay-yes-no.source.ts +1 -0
- package/src/sources/google-availability.source.ts +6 -0
- package/src/sources/language.source.ts +30 -0
- package/src/utils/feed-templates/common-schemas.ts +1014 -0
- package/src/utils/feed-templates/common.ts +82 -0
- package/src/utils/feed-templates/ebay.template.ts +215 -4
- package/src/utils/feed-templates/facebook.template.ts +2 -1
- package/src/utils/feed-templates/google-api.template.ts +54 -29
- package/src/utils/feed-templates/google.template.ts +46 -52
- package/src/utils/feed-templates/microsoft.template.ts +26 -21
- package/src/utils/feed-templates/template-utils.ts +30 -0
- package/src/utils/feed-templates/tiktok.template.ts +4 -2
- package/src/utils/profile.ts +116 -2
- package/src/utils/utils.ts +25 -5
- package/tests/company.spec.ts +39 -39
- package/tests/profile-utils.spec.ts +38 -0
- package/tests/validator.spec.ts +1 -5
- package/dist/utils/feed-templates/index.d.ts.map +0 -1
- package/dist/utils/feed-templates/index.js.map +0 -1
- package/src/utils/feed-templates/index.ts +0 -514
@@ -1,514 +0,0 @@
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
2
|
-
import { SafeParseReturnType, z, ZodType } from 'zod';
|
3
|
-
import { SOURCE_FB_CATEGORY, SOURCE_GOOGLE_PRODUCT_HIGHLIGHT, XMLFeedType } from '../../constants/profile.constants.js';
|
4
|
-
import { customFeedTemplate } from './custom.template.js';
|
5
|
-
import { facebookFeedTemplate } from './facebook.template.js';
|
6
|
-
import { XmlFeedTemplateType } from '../../types/profile.types.js';
|
7
|
-
import { googleFeedTemplate } from './google.template.js';
|
8
|
-
import { tiktokFeedTemplate } from './tiktok.template.js';
|
9
|
-
import { microsoftTemplate } from './microsoft.template.js';
|
10
|
-
import { googleApiTemplate } from './google-api.template.js';
|
11
|
-
import { getSourceTagValue } from '../utils.js';
|
12
|
-
import { eBayFeedTemplate } from './ebay.template.js';
|
13
|
-
|
14
|
-
export const hasMacro = (v: string) => /{{[^}]+}}/.test(v.replaceAll(/{{source\..+?}}/g, ''));
|
15
|
-
export const removeMacro = (v: string) => v.replaceAll(/{{.+?}}/g, '');
|
16
|
-
|
17
|
-
export function validate(
|
18
|
-
value: string | number,
|
19
|
-
validator: ZodType<any, any>,
|
20
|
-
skipEmpty = true
|
21
|
-
): SafeParseReturnType<any, any> {
|
22
|
-
let valueToValidate = value;
|
23
|
-
|
24
|
-
if (typeof value === 'string') {
|
25
|
-
valueToValidate = removeMacro(value);
|
26
|
-
}
|
27
|
-
|
28
|
-
if (!value && skipEmpty) {
|
29
|
-
return { success: true, data: value };
|
30
|
-
}
|
31
|
-
|
32
|
-
return validator.safeParse(valueToValidate);
|
33
|
-
}
|
34
|
-
|
35
|
-
export function validateIfNoMacro(value: string | number, validator: ZodType<any, any> | ZodType<any, any>[]): SafeParseReturnType<any, any> {
|
36
|
-
if (typeof value === 'string' && hasMacro(value)) {
|
37
|
-
return { success: true, data: value };
|
38
|
-
}
|
39
|
-
|
40
|
-
if (Array.isArray(validator)) {
|
41
|
-
for (const v of validator) {
|
42
|
-
const result = v.safeParse(resolveSourceMacro(value));
|
43
|
-
if (!result.success) {
|
44
|
-
return result;
|
45
|
-
}
|
46
|
-
}
|
47
|
-
return { success: true, data: value };
|
48
|
-
}
|
49
|
-
|
50
|
-
return validator.safeParse(resolveSourceMacro(value));
|
51
|
-
}
|
52
|
-
|
53
|
-
export function resolveSourceMacro(macro: any): any {
|
54
|
-
if (typeof macro !== 'string') {
|
55
|
-
return macro;
|
56
|
-
}
|
57
|
-
return macro.replace(/{{source\..+?}}/g, (macro) => {
|
58
|
-
const { tag, value } = getSourceTagValue(macro.slice(2, -2));
|
59
|
-
return value?.map(v => v.value)?.join(getSourceValueSeparator(tag)) ?? '';
|
60
|
-
});
|
61
|
-
}
|
62
|
-
|
63
|
-
export const dateRangeSchema = z
|
64
|
-
.string()
|
65
|
-
.refine(v => !v || v.split('/').length === 2, {
|
66
|
-
message: 'The date range start and end should be separated by a "/"',
|
67
|
-
})
|
68
|
-
.refine(v => !v || z.string().datetime({ offset: true }).safeParse(v.split('/')[0]).success, {
|
69
|
-
message: 'Date from should be a valid date',
|
70
|
-
})
|
71
|
-
.refine(v => !v || z.string().datetime({ offset: true }).safeParse(v.split('/')[1]).success, {
|
72
|
-
message: 'Date to should be a valid date',
|
73
|
-
})
|
74
|
-
.refine(v => !v || new Date(v.split('/')[1]) > new Date(v.split('/')[0]), {
|
75
|
-
message: 'Date to should be greater than date from',
|
76
|
-
});
|
77
|
-
|
78
|
-
const unitMeasureRegex = /^(?<quantity>[\d.,]+)\s*(?<units>\w+)$/;
|
79
|
-
|
80
|
-
export const measureUnitsSchema = (units: string[]) =>
|
81
|
-
z.string().superRefine((v, ctx) => {
|
82
|
-
if (!v) {
|
83
|
-
return true;
|
84
|
-
}
|
85
|
-
|
86
|
-
const match = unitMeasureRegex.exec(v);
|
87
|
-
|
88
|
-
if (!match) {
|
89
|
-
ctx.addIssue({
|
90
|
-
code: z.ZodIssueCode.custom,
|
91
|
-
message: 'Invalid format',
|
92
|
-
});
|
93
|
-
} else if (!units.map(u => u.toLowerCase()).includes(match.groups?.units?.toLowerCase() as string)) {
|
94
|
-
ctx.addIssue({
|
95
|
-
code: z.ZodIssueCode.custom,
|
96
|
-
message: `Invalid unit. Valid units are: ${units.join(', ')}`,
|
97
|
-
});
|
98
|
-
}
|
99
|
-
});
|
100
|
-
|
101
|
-
export const sameUnitScheme = (other: string, errorMessage: string) => z.string().superRefine((v, ctx) => {
|
102
|
-
if (!v || !other) {
|
103
|
-
return true;
|
104
|
-
}
|
105
|
-
|
106
|
-
const match = unitMeasureRegex.exec(v);
|
107
|
-
const otherMatch = unitMeasureRegex.exec(other);
|
108
|
-
|
109
|
-
if (!match || !otherMatch) {
|
110
|
-
return true;
|
111
|
-
}
|
112
|
-
|
113
|
-
if (match.groups?.units !== otherMatch.groups?.units) {
|
114
|
-
ctx.addIssue({
|
115
|
-
code: z.ZodIssueCode.custom,
|
116
|
-
message: errorMessage,
|
117
|
-
});
|
118
|
-
}
|
119
|
-
})
|
120
|
-
|
121
|
-
export const optionalUrlSchema = z
|
122
|
-
.string()
|
123
|
-
.refine(v => !v || z.string().url().safeParse(v).success, { message: 'invalid URL' });
|
124
|
-
|
125
|
-
export function getTemplate(type: XMLFeedType): XmlFeedTemplateType {
|
126
|
-
switch (type) {
|
127
|
-
case XMLFeedType.Custom:
|
128
|
-
return customFeedTemplate;
|
129
|
-
case XMLFeedType.Facebook:
|
130
|
-
return facebookFeedTemplate;
|
131
|
-
case XMLFeedType.Google:
|
132
|
-
return googleFeedTemplate;
|
133
|
-
case XMLFeedType.TikTok:
|
134
|
-
return tiktokFeedTemplate;
|
135
|
-
case XMLFeedType.Microsoft:
|
136
|
-
return microsoftTemplate;
|
137
|
-
case XMLFeedType.GMC_API:
|
138
|
-
return googleApiTemplate;
|
139
|
-
case XMLFeedType.eBay:
|
140
|
-
return eBayFeedTemplate;
|
141
|
-
default:
|
142
|
-
throw new Error(`Invalid feed type: ${type}`);
|
143
|
-
}
|
144
|
-
}
|
145
|
-
|
146
|
-
export const currencySchema = z.enum([
|
147
|
-
'AED', 'AFN', 'ALL', 'AMD', 'ANG', 'AOA', 'ARS', 'AUD', 'AWG', 'AZN', 'BAM', 'BBD',
|
148
|
-
'BDT', 'BGN', 'BHD', 'BIF', 'BMD', 'BND', 'BOB', 'BOV', 'BRL', 'BSD', 'BTN', 'BWP',
|
149
|
-
'BYN', 'BZD', 'CAD', 'CDF', 'CHE', 'CHF', 'CHW', 'CLF', 'CLP', 'CNY', 'COP', 'COU',
|
150
|
-
'CRC', 'CUC', 'CUP', 'CVE', 'CZK', 'DJF', 'DKK', 'DOP', 'DZD', 'EGP', 'ERN', 'ETB',
|
151
|
-
'EUR', 'FJD', 'FKP', 'FOK', 'GBP', 'GEL', 'GGP', 'GHS', 'GIP', 'GMD', 'GNF', 'GTQ',
|
152
|
-
'GYD', 'HKD', 'HNL', 'HRK', 'HTG', 'HUF', 'IDR', 'ILS', 'IMP', 'INR', 'IQD', 'IRR',
|
153
|
-
'ISK', 'JMD', 'JOD', 'JPY', 'KES', 'KGS', 'KHR', 'KID', 'KMF', 'KRW', 'KWD', 'KYD',
|
154
|
-
'KZT', 'LAK', 'LBP', 'LKR', 'LRD', 'LSL', 'LYD', 'MAD', 'MDL', 'MGA', 'MKD', 'MMK',
|
155
|
-
'MNT', 'MOP', 'MRU', 'MUR', 'MVR', 'MWK', 'MXN', 'MXV', 'MYR', 'MZN', 'NAD', 'NGN',
|
156
|
-
'NIO', 'NOK', 'NPR', 'NZD', 'OMR', 'PAB', 'PEN', 'PGK', 'PHP', 'PKR', 'PLN', 'PYG',
|
157
|
-
'QAR', 'RON', 'RSD', 'RUB', 'RWF', 'SAR', 'SBD', 'SCR', 'SDG', 'SEK', 'SGD', 'SHP',
|
158
|
-
'SLE', 'SLL', 'SOS', 'SRD', 'SSP', 'STN', 'SYP', 'SZL', 'THB', 'TJS', 'TMT', 'TND',
|
159
|
-
'TOP', 'TRY', 'TTD', 'TVD', 'TWD', 'TZS', 'UAH', 'UGX', 'USD', 'USN', 'UYI', 'UYU',
|
160
|
-
'UYW', 'UZS', 'VED', 'VES', 'VND', 'VUV', 'WST', 'XAF', 'XAG', 'XAU', 'XBA', 'XBB',
|
161
|
-
'XBC', 'XBD', 'XCD', 'XDR', 'XOF', 'XPD', 'XPF', 'XPT', 'XSU', 'XTS', 'XUA', 'XXX',
|
162
|
-
'YER', 'ZAR', 'ZMW', 'ZWL'
|
163
|
-
]);
|
164
|
-
|
165
|
-
export const languageSchema = z.string().refine(v => !v || [
|
166
|
-
'aa', 'ab', 'ae', 'af', 'ak', 'am', 'an', 'ar', 'as', 'av', 'ay', 'az',
|
167
|
-
'ba', 'be', 'bg', 'bh', 'bi', 'bm', 'bn', 'bo', 'br', 'bs', 'ca', 'ce',
|
168
|
-
'ch', 'co', 'cr', 'cs', 'cu', 'cv', 'cy', 'da', 'de', 'dv', 'dz', 'ee',
|
169
|
-
'el', 'en', 'eo', 'es', 'et', 'eu', 'fa', 'ff', 'fi', 'fj', 'fo', 'fr',
|
170
|
-
'fy', 'ga', 'gd', 'gl', 'gn', 'gu', 'gv', 'ha', 'he', 'hi', 'ho', 'hr',
|
171
|
-
'ht', 'hu', 'hy', 'hz', 'ia', 'id', 'ie', 'ig', 'ii', 'ik', 'io', 'is',
|
172
|
-
'it', 'iu', 'ja', 'jv', 'ka', 'kg', 'ki', 'kj', 'kk', 'kl', 'km', 'kn',
|
173
|
-
'ko', 'kr', 'ks', 'ku', 'kv', 'kw', 'ky', 'la', 'lb', 'lg', 'li', 'ln',
|
174
|
-
'lo', 'lt', 'lu', 'lv', 'mg', 'mh', 'mi', 'mk', 'ml', 'mn', 'mr', 'ms',
|
175
|
-
'mt', 'my', 'na', 'nb', 'nd', 'ne', 'ng', 'nl', 'nn', 'no', 'nr', 'nv',
|
176
|
-
'ny', 'oc', 'oj', 'om', 'or', 'os', 'pa', 'pi', 'pl', 'ps', 'pt', 'qu',
|
177
|
-
'rm', 'rn', 'ro', 'ru', 'rw', 'sa', 'sc', 'sd', 'se', 'sg', 'si', 'sk',
|
178
|
-
'sl', 'sm', 'sn', 'so', 'sq', 'sr', 'ss', 'st', 'su', 'sv', 'sw', 'ta',
|
179
|
-
'te', 'tg', 'th', 'ti', 'tk', 'tl', 'tn', 'to', 'tr', 'ts', 'tt', 'tw',
|
180
|
-
'ty', 'ug', 'uk', 'ur', 'uz', 've', 'vi', 'vo', 'wa', 'wo', 'xh', 'yi',
|
181
|
-
'yo', 'za', 'zh', 'zu'
|
182
|
-
].includes(v.toLowerCase()), { message: 'Invalid language code' });
|
183
|
-
|
184
|
-
export const countrySchema = z.string().refine(v => !v || [
|
185
|
-
'AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AO', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AW', 'AX', 'AZ',
|
186
|
-
'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BN', 'BO', 'BQ', 'BR', 'BS',
|
187
|
-
'BT', 'BV', 'BW', 'BY', 'BZ', 'CA', 'CC', 'CD', 'CF', 'CG', 'CH', 'CI', 'CK', 'CL', 'CM', 'CN',
|
188
|
-
'CO', 'CR', 'CU', 'CV', 'CW', 'CX', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DM', 'DO', 'DZ', 'EC', 'EE',
|
189
|
-
'EG', 'EH', 'ER', 'ES', 'ET', 'FI', 'FJ', 'FM', 'FO', 'FR', 'GA', 'GB', 'GD', 'GE', 'GF', 'GG',
|
190
|
-
'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR', 'GT', 'GU', 'GW', 'GY', 'HK', 'HM', 'HN', 'HR',
|
191
|
-
'HT', 'HU', 'ID', 'IE', 'IL', 'IM', 'IN', 'IO', 'IQ', 'IR', 'IS', 'IT', 'JE', 'JM', 'JO', 'JP',
|
192
|
-
'KE', 'KG', 'KH', 'KI', 'KM', 'KN', 'KP', 'KR', 'KW', 'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK',
|
193
|
-
'LR', 'LS', 'LT', 'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'ME', 'MF', 'MG', 'MH', 'MK', 'ML', 'MM',
|
194
|
-
'MN', 'MO', 'MP', 'MQ', 'MR', 'MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ', 'NA', 'NC', 'NE',
|
195
|
-
'NF', 'NG', 'NI', 'NL', 'NO', 'NP', 'NR', 'NU', 'NZ', 'OM', 'PA', 'PE', 'PF', 'PG', 'PH', 'PK',
|
196
|
-
'PL', 'PM', 'PN', 'PR', 'PT', 'PW', 'PY', 'QA', 'RE', 'RO', 'RS', 'RU', 'RW', 'SA', 'SB', 'SC',
|
197
|
-
'SD', 'SE', 'SG', 'SH', 'SI', 'SJ', 'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'SS', 'ST', 'SV', 'SX',
|
198
|
-
'SY', 'SZ', 'TC', 'TD', 'TF', 'TG', 'TH', 'TJ', 'TK', 'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 'TV',
|
199
|
-
'TZ', 'UA', 'UG', 'UM', 'US', 'UY', 'UZ', 'VA', 'VC', 'VE', 'VG', 'VI', 'VN', 'VU', 'WF', 'WS',
|
200
|
-
'YE', 'YT', 'ZA', 'ZM', 'ZW'
|
201
|
-
].includes(v.toUpperCase()), { message: 'Invalid country code' });
|
202
|
-
|
203
|
-
export const priceRegex = /^(?<value>\d+(?:\.\d{1,2})?)\s*(?<currency>\w+)$/;
|
204
|
-
|
205
|
-
export const priceSchema = ({ min = 0, max = 1000000 } = {}) =>
|
206
|
-
z.string().superRefine((v, ctx) => {
|
207
|
-
if (!v) {
|
208
|
-
return true;
|
209
|
-
}
|
210
|
-
|
211
|
-
try {
|
212
|
-
parsePriceString({ price: v, min, max });
|
213
|
-
return true;
|
214
|
-
} catch (e: any) {
|
215
|
-
ctx.addIssue({
|
216
|
-
code: z.ZodIssueCode.custom,
|
217
|
-
message: e.message,
|
218
|
-
});
|
219
|
-
}
|
220
|
-
});
|
221
|
-
|
222
|
-
export const salePriceSchema = ({ min = 0, max = 1000000, price = '' } = {}) =>
|
223
|
-
z.string().superRefine((v, ctx) => {
|
224
|
-
if (!v) {
|
225
|
-
return true;
|
226
|
-
}
|
227
|
-
|
228
|
-
try {
|
229
|
-
const { currency, value } = parsePriceString({ price: v, min, max });
|
230
|
-
|
231
|
-
if (price) {
|
232
|
-
try {
|
233
|
-
const { currency: priceCurrency, value: priceAmount } = parsePriceString({ price, min, max });
|
234
|
-
|
235
|
-
if (currency !== priceCurrency) {
|
236
|
-
ctx.addIssue({
|
237
|
-
code: z.ZodIssueCode.custom,
|
238
|
-
message: 'Sale price currency should be the same as the price currency',
|
239
|
-
});
|
240
|
-
return;
|
241
|
-
}
|
242
|
-
|
243
|
-
if (Number(value) >= Number(priceAmount)) {
|
244
|
-
ctx.addIssue({
|
245
|
-
code: z.ZodIssueCode.custom,
|
246
|
-
message: 'Sale price should be lower than the price',
|
247
|
-
});
|
248
|
-
return;
|
249
|
-
}
|
250
|
-
} catch (e: any) { }
|
251
|
-
}
|
252
|
-
return true;
|
253
|
-
} catch (e: any) {
|
254
|
-
ctx.addIssue({
|
255
|
-
code: z.ZodIssueCode.custom,
|
256
|
-
message: e.message,
|
257
|
-
});
|
258
|
-
}
|
259
|
-
});
|
260
|
-
|
261
|
-
const ee = ['A+++', 'A++', 'A+', 'A', 'B', 'C', 'D', 'E', 'F', 'G',];
|
262
|
-
|
263
|
-
/**
|
264
|
-
* Check if minEfficiency is less or equal to maxEfficiency
|
265
|
-
* @param minEfficiency
|
266
|
-
* @param maxEfficiency
|
267
|
-
* @returns
|
268
|
-
*/
|
269
|
-
const compareEfficiency = (minEfficiency: string, maxEfficiency: string): boolean => {
|
270
|
-
const minIndex = ee.findIndex(e => e === minEfficiency);
|
271
|
-
const maxIndex = ee.findIndex(e => e === maxEfficiency);
|
272
|
-
|
273
|
-
if (minIndex === -1 || maxIndex === -1) {
|
274
|
-
return false;
|
275
|
-
}
|
276
|
-
|
277
|
-
return minIndex >= maxIndex;
|
278
|
-
}
|
279
|
-
|
280
|
-
export const energyEfficiencyClassSchema = ({ minEfficiency = '', maxEfficiency } = {} as { minEfficiency?: string, maxEfficiency?: string }) => {
|
281
|
-
return z.string().superRefine((v, ctx) => {
|
282
|
-
if (!v) {
|
283
|
-
if (maxEfficiency || minEfficiency) {
|
284
|
-
ctx.addIssue({
|
285
|
-
code: z.ZodIssueCode.custom,
|
286
|
-
message: 'Energy efficiency class is required',
|
287
|
-
});
|
288
|
-
return false;
|
289
|
-
}
|
290
|
-
return true;
|
291
|
-
}
|
292
|
-
|
293
|
-
if (!ee.includes(v)) {
|
294
|
-
ctx.addIssue({
|
295
|
-
code: z.ZodIssueCode.custom,
|
296
|
-
message: 'Invalid energy efficiency class',
|
297
|
-
});
|
298
|
-
return false;
|
299
|
-
}
|
300
|
-
|
301
|
-
if (minEfficiency && !compareEfficiency(minEfficiency, v)) {
|
302
|
-
ctx.addIssue({
|
303
|
-
code: z.ZodIssueCode.custom,
|
304
|
-
message: 'Energy efficiency class should be greater or equal to the minimum energy efficiency class',
|
305
|
-
});
|
306
|
-
return false;
|
307
|
-
}
|
308
|
-
|
309
|
-
if (maxEfficiency && !compareEfficiency(v, maxEfficiency)) {
|
310
|
-
ctx.addIssue({
|
311
|
-
code: z.ZodIssueCode.custom,
|
312
|
-
message: 'Energy efficiency class should be lower or equal to the maximum energy efficiency class',
|
313
|
-
});
|
314
|
-
return false;
|
315
|
-
}
|
316
|
-
return true;
|
317
|
-
});
|
318
|
-
}
|
319
|
-
|
320
|
-
export const minEnergyEfficiencyClassSchema = ({ efficiency = '', maxEfficiency } = {} as { efficiency?: string, maxEfficiency?: string }) => {
|
321
|
-
return z.string().superRefine((v, ctx) => {
|
322
|
-
if (!v) {
|
323
|
-
if (maxEfficiency || efficiency) {
|
324
|
-
ctx.addIssue({
|
325
|
-
code: z.ZodIssueCode.custom,
|
326
|
-
message: 'Minimum energy efficiency class is required',
|
327
|
-
});
|
328
|
-
return false;
|
329
|
-
}
|
330
|
-
return true;
|
331
|
-
}
|
332
|
-
|
333
|
-
if (!ee.includes(v)) {
|
334
|
-
ctx.addIssue({
|
335
|
-
code: z.ZodIssueCode.custom,
|
336
|
-
message: 'Invalid energy efficiency class',
|
337
|
-
});
|
338
|
-
return false;
|
339
|
-
}
|
340
|
-
|
341
|
-
if (efficiency && !compareEfficiency(v, efficiency)) {
|
342
|
-
ctx.addIssue({
|
343
|
-
code: z.ZodIssueCode.custom,
|
344
|
-
message: 'Minimum energy efficiency class should be lower or equal to the energy efficiency class',
|
345
|
-
});
|
346
|
-
return false;
|
347
|
-
}
|
348
|
-
|
349
|
-
if (maxEfficiency && !compareEfficiency(v, maxEfficiency)) {
|
350
|
-
ctx.addIssue({
|
351
|
-
code: z.ZodIssueCode.custom,
|
352
|
-
message: 'Minimum energy efficiency class should be lower or equal to the maximum energy efficiency class',
|
353
|
-
});
|
354
|
-
return false;
|
355
|
-
}
|
356
|
-
return true;
|
357
|
-
});
|
358
|
-
}
|
359
|
-
|
360
|
-
export const maxEnergyEfficiencyClassSchema = ({ efficiency = '', minEfficiency } = {} as { efficiency?: string, minEfficiency?: string }) => {
|
361
|
-
return z.string().superRefine((v, ctx) => {
|
362
|
-
if (!v) {
|
363
|
-
if (minEfficiency || efficiency) {
|
364
|
-
ctx.addIssue({
|
365
|
-
code: z.ZodIssueCode.custom,
|
366
|
-
message: 'Maximum energy efficiency class is required',
|
367
|
-
});
|
368
|
-
return false;
|
369
|
-
}
|
370
|
-
return true;
|
371
|
-
}
|
372
|
-
|
373
|
-
if (!ee.includes(v)) {
|
374
|
-
ctx.addIssue({
|
375
|
-
code: z.ZodIssueCode.custom,
|
376
|
-
message: 'Invalid energy efficiency class',
|
377
|
-
});
|
378
|
-
return false;
|
379
|
-
}
|
380
|
-
|
381
|
-
if (efficiency && !compareEfficiency(efficiency, v)) {
|
382
|
-
ctx.addIssue({
|
383
|
-
code: z.ZodIssueCode.custom,
|
384
|
-
message: 'Maximum energy efficiency class should be greater or equal to the energy efficiency class',
|
385
|
-
});
|
386
|
-
return false;
|
387
|
-
}
|
388
|
-
|
389
|
-
if (minEfficiency && !compareEfficiency(minEfficiency, v)) {
|
390
|
-
ctx.addIssue({
|
391
|
-
code: z.ZodIssueCode.custom,
|
392
|
-
message: 'Maximum energy efficiency class should be greater or equal to the minimum energy efficiency class',
|
393
|
-
});
|
394
|
-
return false;
|
395
|
-
}
|
396
|
-
return true;
|
397
|
-
});
|
398
|
-
}
|
399
|
-
|
400
|
-
export const gtinSchema = z.string().refine((gtin) => {
|
401
|
-
if (!gtin) {
|
402
|
-
return true;
|
403
|
-
}
|
404
|
-
|
405
|
-
const length = gtin.length;
|
406
|
-
|
407
|
-
if (![8, 12, 13, 14].includes(length)) {
|
408
|
-
return false;
|
409
|
-
}
|
410
|
-
|
411
|
-
const digits = gtin.split('').map(Number);
|
412
|
-
const checkDigit = digits.pop();
|
413
|
-
const sum = digits.reverse().reduce((acc, digit, idx) => {
|
414
|
-
return acc + digit * (idx % 2 === 0 ? 3 : 1);
|
415
|
-
}, 0);
|
416
|
-
|
417
|
-
const calculatedCheckDigit = (10 - (sum % 10)) % 10;
|
418
|
-
return checkDigit === calculatedCheckDigit;
|
419
|
-
}, {
|
420
|
-
message: 'Invalid GTIN',
|
421
|
-
});
|
422
|
-
|
423
|
-
export const requiredIfOtherPresentSchema = (other: string[], errorMessage: string) => z.string().superRefine((v, ctx) => {
|
424
|
-
if (!v && other.some(o => o)) {
|
425
|
-
ctx.addIssue({
|
426
|
-
code: z.ZodIssueCode.custom,
|
427
|
-
message: errorMessage,
|
428
|
-
});
|
429
|
-
}
|
430
|
-
});
|
431
|
-
|
432
|
-
export function splitByCommaAndTrim(str: string): string[] {
|
433
|
-
return typeof str === 'string'
|
434
|
-
? str
|
435
|
-
.split(',')
|
436
|
-
.map(s => s.trim())
|
437
|
-
.filter(Boolean)
|
438
|
-
: [];
|
439
|
-
}
|
440
|
-
|
441
|
-
export function parsePriceString({ price, min = 0, max = 1000000 }: { price: string; min?: number; max?: number }): {
|
442
|
-
value: string;
|
443
|
-
currency: string;
|
444
|
-
} {
|
445
|
-
const match = priceRegex.exec(price);
|
446
|
-
|
447
|
-
if (!match) {
|
448
|
-
throw new Error('Invalid format');
|
449
|
-
} else if (
|
450
|
-
!Number.isFinite(Number(match.groups?.value)) ||
|
451
|
-
Number(match.groups?.value) < min ||
|
452
|
-
Number(match.groups?.value) > max
|
453
|
-
) {
|
454
|
-
|
455
|
-
throw new Error(`Value should be between ${min} and ${max}`)
|
456
|
-
|
457
|
-
} else if (!currencySchema.safeParse(match.groups?.currency).success) {
|
458
|
-
throw new Error('Invalid currency');
|
459
|
-
}
|
460
|
-
|
461
|
-
return { value: match.groups?.value as string, currency: match.groups?.currency as string };
|
462
|
-
}
|
463
|
-
|
464
|
-
export const dimensionRegex = /^(?<value>[\d.,]+)\s*(?<unit>\w+)$/;
|
465
|
-
|
466
|
-
export function parseDimensionString({ dimension, min = 0, max = 1000000 }: { dimension: string; min?: number; max?: number }): {
|
467
|
-
value: string;
|
468
|
-
unit: string;
|
469
|
-
} {
|
470
|
-
const match = dimensionRegex.exec(dimension);
|
471
|
-
|
472
|
-
if (!match) {
|
473
|
-
throw new Error('Invalid format');
|
474
|
-
} else if (
|
475
|
-
!Number.isFinite(Number(match.groups?.value)) ||
|
476
|
-
Number(match.groups?.value) < min ||
|
477
|
-
Number(match.groups?.value) > max
|
478
|
-
) {
|
479
|
-
throw new Error(`Value should be between ${min} and ${max}`);
|
480
|
-
}
|
481
|
-
|
482
|
-
return { value: match.groups?.value as string, unit: match.groups?.unit as string };
|
483
|
-
}
|
484
|
-
|
485
|
-
export function convertToBoolean(value: string): boolean {
|
486
|
-
if (value === 'true') {
|
487
|
-
return true;
|
488
|
-
}
|
489
|
-
|
490
|
-
if (value === 'false') {
|
491
|
-
return false;
|
492
|
-
}
|
493
|
-
|
494
|
-
throw new Error('Invalid boolean value');
|
495
|
-
}
|
496
|
-
|
497
|
-
export function castToArray(value: string): string[] {
|
498
|
-
return Array.isArray(value) ? value : [value];
|
499
|
-
}
|
500
|
-
|
501
|
-
export function castToInt(value: string): number {
|
502
|
-
return typeof value === 'string' ? parseInt(value, 10) : value;
|
503
|
-
}
|
504
|
-
|
505
|
-
export function getSourceValueSeparator(source = ''): string {
|
506
|
-
switch (source) {
|
507
|
-
case SOURCE_GOOGLE_PRODUCT_HIGHLIGHT:
|
508
|
-
return '|';
|
509
|
-
case SOURCE_FB_CATEGORY:
|
510
|
-
return ':';
|
511
|
-
default:
|
512
|
-
return ',';
|
513
|
-
}
|
514
|
-
}
|