feed-common 1.0.0 → 1.0.1
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/CHANGELOG.md +9 -0
- package/dist/constants/google.constants.d.ts +11 -0
- package/dist/constants/product.constants.d.ts +4 -0
- package/dist/constants/profile.constants.d.ts +69 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/types/company.types.d.ts +9 -0
- package/dist/types/company.types.js +2 -0
- package/dist/types/company.types.js.map +1 -0
- package/dist/types/product.types.d.ts +86 -0
- package/dist/types/profile.types.d.ts +68 -0
- package/dist/utils/gmc.d.ts +16 -0
- package/dist/utils/profile.d.ts +28 -0
- package/dist/utils/utils.d.ts +1 -0
- package/package.json +3 -2
- package/scripts/install.sh +9 -0
- package/src/constants/google.constants.ts +12 -0
- package/src/constants/product.constants.ts +4 -0
- package/src/constants/profile.constants.ts +369 -0
- package/src/index.ts +11 -0
- package/src/types/company.types.ts +10 -0
- package/src/types/product.types.ts +97 -0
- package/src/types/profile.types.ts +73 -0
- package/src/utils/gmc.ts +69 -0
- package/src/utils/profile.ts +348 -0
- package/src/utils/utils.ts +3 -0
- package/.github/workflows/release.yml +0 -38
@@ -0,0 +1,369 @@
|
|
1
|
+
import { ProductUploadMapSource } from '../types/profile.types.js';
|
2
|
+
import { ProductUploadRuleFilterType } from '../types/profile.types.js';
|
3
|
+
|
4
|
+
export const SOURCE_VENDORS = 'source.vendor';
|
5
|
+
export const SOURCE_TAGS = 'source.tag';
|
6
|
+
export const SOURCE_PORODUCT_TYPE = 'source.product_type';
|
7
|
+
export const SOURCE_COLLECTIONS = 'source.collection';
|
8
|
+
export const SOURCE_LANGUAGE = 'source.language';
|
9
|
+
export const SOURCE_GOOGLE_CATEGORY = 'source.google_category';
|
10
|
+
export const SOURCE_COUNTRY = 'source.country';
|
11
|
+
|
12
|
+
export const SOURCE_SHOPIFY_VENDORS = 'shopify.vendor';
|
13
|
+
export const SOURCE_SHOPIFY_BARCODE = 'shopify.barcode';
|
14
|
+
export const SOURCE_SHOPIFY_SKU = 'shopify.sku';
|
15
|
+
|
16
|
+
export const SOURCE_CUSTOM = 'custom_input';
|
17
|
+
|
18
|
+
export const RuleOperators = {
|
19
|
+
contains: {
|
20
|
+
label: 'Contains',
|
21
|
+
value: 'contains',
|
22
|
+
},
|
23
|
+
notContains: {
|
24
|
+
label: 'Not Contains',
|
25
|
+
value: 'notContains',
|
26
|
+
},
|
27
|
+
equals: {
|
28
|
+
label: 'Equals',
|
29
|
+
value: 'equals',
|
30
|
+
},
|
31
|
+
notEquals: {
|
32
|
+
label: 'Not Equals',
|
33
|
+
value: 'notEquals',
|
34
|
+
},
|
35
|
+
startsWith: {
|
36
|
+
label: 'Starts With',
|
37
|
+
value: 'startsWith',
|
38
|
+
},
|
39
|
+
notStartsWith: {
|
40
|
+
label: 'Not Starts With',
|
41
|
+
value: 'notStartsWith',
|
42
|
+
},
|
43
|
+
endsWith: {
|
44
|
+
label: 'Ends With',
|
45
|
+
value: 'endsWith',
|
46
|
+
},
|
47
|
+
notEndsWith: {
|
48
|
+
label: 'Not Ends With',
|
49
|
+
value: 'notEndsWith',
|
50
|
+
},
|
51
|
+
in: {
|
52
|
+
label: 'In',
|
53
|
+
value: 'in',
|
54
|
+
},
|
55
|
+
notIn: {
|
56
|
+
label: 'Not In',
|
57
|
+
value: 'notIn',
|
58
|
+
},
|
59
|
+
};
|
60
|
+
|
61
|
+
export const PruoductUploadRulesOperators = {
|
62
|
+
string: [
|
63
|
+
RuleOperators.contains,
|
64
|
+
RuleOperators.notContains,
|
65
|
+
RuleOperators.equals,
|
66
|
+
RuleOperators.notEquals,
|
67
|
+
RuleOperators.startsWith,
|
68
|
+
RuleOperators.endsWith,
|
69
|
+
RuleOperators.notStartsWith,
|
70
|
+
RuleOperators.notEndsWith,
|
71
|
+
],
|
72
|
+
list: [RuleOperators.in, RuleOperators.notIn],
|
73
|
+
};
|
74
|
+
|
75
|
+
export const ProductUploadRuleFilters: ProductUploadRuleFilterType[] = [
|
76
|
+
{
|
77
|
+
label: 'Title',
|
78
|
+
operators: PruoductUploadRulesOperators.string,
|
79
|
+
value: 'title',
|
80
|
+
},
|
81
|
+
{
|
82
|
+
label: 'Collection',
|
83
|
+
operators: PruoductUploadRulesOperators.list,
|
84
|
+
value: 'collection',
|
85
|
+
},
|
86
|
+
{
|
87
|
+
label: 'Product Type',
|
88
|
+
operators: PruoductUploadRulesOperators.list,
|
89
|
+
value: 'product_type',
|
90
|
+
},
|
91
|
+
{
|
92
|
+
label: 'Vendor',
|
93
|
+
operators: PruoductUploadRulesOperators.list,
|
94
|
+
value: 'vendor',
|
95
|
+
},
|
96
|
+
{
|
97
|
+
label: 'Tag',
|
98
|
+
operators: PruoductUploadRulesOperators.list,
|
99
|
+
value: 'tag',
|
100
|
+
},
|
101
|
+
];
|
102
|
+
|
103
|
+
const ShopifyProductSource = {
|
104
|
+
vendor: { label: 'Shopify Product Vendor', value: SOURCE_SHOPIFY_VENDORS },
|
105
|
+
barcode: { label: 'Shopify Product Barcode', value: SOURCE_SHOPIFY_BARCODE },
|
106
|
+
sku: { label: 'Shopify Product SKU', value: SOURCE_SHOPIFY_SKU },
|
107
|
+
custom: { label: 'Custom input', value: SOURCE_CUSTOM },
|
108
|
+
};
|
109
|
+
|
110
|
+
export const ProductUploadMappings: ProductUploadMapSource[] = [
|
111
|
+
{
|
112
|
+
required: true,
|
113
|
+
label: 'Content Language',
|
114
|
+
attribute: 'contentLanguage',
|
115
|
+
type: 'select',
|
116
|
+
choises: [SOURCE_LANGUAGE],
|
117
|
+
rules: ['title', 'collection', 'product_type', 'vendor', 'tag'],
|
118
|
+
description: 'Language for the item',
|
119
|
+
},
|
120
|
+
{
|
121
|
+
required: true,
|
122
|
+
label: 'Target Country',
|
123
|
+
attribute: 'targetCountry',
|
124
|
+
type: 'select',
|
125
|
+
choises: [SOURCE_COUNTRY],
|
126
|
+
rules: ['title', 'collection', 'product_type', 'vendor', 'tag'],
|
127
|
+
description: 'The item\'s country of sale',
|
128
|
+
},
|
129
|
+
{
|
130
|
+
required: false,
|
131
|
+
label: 'Adult',
|
132
|
+
attribute: 'adult',
|
133
|
+
type: 'select',
|
134
|
+
choises: [
|
135
|
+
{ label: 'Yes', value: true },
|
136
|
+
{ label: 'No', value: false },
|
137
|
+
],
|
138
|
+
rules: ['title', 'collection', 'product_type', 'vendor', 'tag'],
|
139
|
+
description:
|
140
|
+
'Should be set to "Yes" if the item is targeted towards adults',
|
141
|
+
},
|
142
|
+
{
|
143
|
+
required: false,
|
144
|
+
label: 'Age Group',
|
145
|
+
attribute: 'ageGroup',
|
146
|
+
type: 'select',
|
147
|
+
choises: [
|
148
|
+
{ label: '0-3 months old', value: 'newborn' },
|
149
|
+
{ label: '3-12 months old', value: 'infant' },
|
150
|
+
{ label: '1-5 years old', value: 'toddler' },
|
151
|
+
{ label: '5-13 years old', value: 'kids' },
|
152
|
+
{ label: '13 years old or more', value: 'adult' },
|
153
|
+
],
|
154
|
+
rules: ['title', 'collection', 'product_type', 'vendor', 'tag'],
|
155
|
+
description: 'Target age group of the item',
|
156
|
+
},
|
157
|
+
{
|
158
|
+
required: false,
|
159
|
+
label: 'Availability',
|
160
|
+
attribute: 'availability',
|
161
|
+
type: 'select',
|
162
|
+
choises: [
|
163
|
+
{ label: 'In Stock', value: 'in_stock' },
|
164
|
+
{ label: 'Out Of Stock', value: 'out_of_stock' },
|
165
|
+
{ label: 'Preorder', value: 'preorder' },
|
166
|
+
{ label: 'Backorder', value: 'backorder' },
|
167
|
+
],
|
168
|
+
rules: ['title', 'collection', 'product_type', 'vendor', 'tag'],
|
169
|
+
description: 'Availability status of the item',
|
170
|
+
},
|
171
|
+
{
|
172
|
+
required: false,
|
173
|
+
label: 'Brand',
|
174
|
+
attribute: 'brand',
|
175
|
+
type: 'select',
|
176
|
+
defaultValue: 'shopify.vendor',
|
177
|
+
rules: ['title', 'collection', 'product_type', 'vendor', 'tag'],
|
178
|
+
description: 'Brand of the item',
|
179
|
+
choises: [
|
180
|
+
ShopifyProductSource.vendor,
|
181
|
+
SOURCE_VENDORS,
|
182
|
+
ShopifyProductSource.custom,
|
183
|
+
],
|
184
|
+
},
|
185
|
+
{
|
186
|
+
required: false,
|
187
|
+
label: 'Gender',
|
188
|
+
attribute: 'gender',
|
189
|
+
type: 'select',
|
190
|
+
choises: [
|
191
|
+
{ label: 'Male', value: 'male' },
|
192
|
+
{ label: 'Female', value: 'female' },
|
193
|
+
{ label: 'Unisex', value: 'unisex' },
|
194
|
+
],
|
195
|
+
rules: ['title', 'collection', 'product_type', 'vendor', 'tag'],
|
196
|
+
description: 'Target gender of the item',
|
197
|
+
},
|
198
|
+
{
|
199
|
+
required: false,
|
200
|
+
label: 'Google category',
|
201
|
+
attribute: 'googleProductCategory',
|
202
|
+
type: 'select',
|
203
|
+
choises: [SOURCE_GOOGLE_CATEGORY],
|
204
|
+
rules: ['title', 'collection', 'product_type', 'vendor', 'tag'],
|
205
|
+
description: 'Google\'s category of the item',
|
206
|
+
},
|
207
|
+
{
|
208
|
+
required: false,
|
209
|
+
label: 'GTIN',
|
210
|
+
attribute: 'gtin',
|
211
|
+
type: 'select',
|
212
|
+
defaultValue: 'shopify.vendor',
|
213
|
+
rules: ['title', 'collection', 'product_type', 'vendor', 'tag'],
|
214
|
+
description: 'Global Trade Item Number (GTIN) of the item',
|
215
|
+
choises: [
|
216
|
+
ShopifyProductSource.barcode,
|
217
|
+
ShopifyProductSource.sku,
|
218
|
+
{ label: 'Custom input', value: SOURCE_CUSTOM },
|
219
|
+
],
|
220
|
+
},
|
221
|
+
{
|
222
|
+
required: false,
|
223
|
+
label: 'MPN',
|
224
|
+
attribute: 'mpn',
|
225
|
+
type: 'select',
|
226
|
+
defaultValue: 'shopify.vendor',
|
227
|
+
rules: ['title', 'collection', 'product_type', 'vendor', 'tag'],
|
228
|
+
description: 'Manufacturer Part Number (MPN) of the item',
|
229
|
+
choises: [
|
230
|
+
ShopifyProductSource.barcode,
|
231
|
+
ShopifyProductSource.sku,
|
232
|
+
{ label: 'Custom input', value: SOURCE_CUSTOM },
|
233
|
+
],
|
234
|
+
},
|
235
|
+
{
|
236
|
+
required: false,
|
237
|
+
label: 'Included Destinations',
|
238
|
+
attribute: 'includedDestinations',
|
239
|
+
type: 'multiselect',
|
240
|
+
choises: [
|
241
|
+
{ label: 'Shopping ads', value: 'Shopping_ads' },
|
242
|
+
{ label: 'Dynamic remarketing ads', value: 'Display_ads' },
|
243
|
+
{ label: 'Free listings', value: 'Free_listings' },
|
244
|
+
],
|
245
|
+
rules: ['title', 'collection', 'product_type', 'vendor', 'tag'],
|
246
|
+
description:
|
247
|
+
'The list of destinations to include for this target (corresponds to checked check boxes in Merchant Center)',
|
248
|
+
},
|
249
|
+
{
|
250
|
+
required: false,
|
251
|
+
label: 'Shipping label',
|
252
|
+
attribute: 'shippingLabel',
|
253
|
+
type: 'text',
|
254
|
+
rules: ['title', 'collection', 'product_type', 'vendor', 'tag'],
|
255
|
+
description:
|
256
|
+
'The shipping label of the product, used to group product in account-level shipping rules',
|
257
|
+
},
|
258
|
+
|
259
|
+
// /**
|
260
|
+
// * The day a pre-ordered product becomes available for delivery, in ISO 8601 format.
|
261
|
+
// */
|
262
|
+
// availabilityDate?: string | null;
|
263
|
+
// /**
|
264
|
+
// * Color of the item.
|
265
|
+
// */
|
266
|
+
// color?: string | null;
|
267
|
+
// /**
|
268
|
+
// * Condition or state of the item.
|
269
|
+
// */
|
270
|
+
// condition?: string | null;
|
271
|
+
// /**
|
272
|
+
// * Custom label 0 for custom grouping of items in a Shopping campaign.
|
273
|
+
// */
|
274
|
+
// customLabel0?: string | null;
|
275
|
+
// /**
|
276
|
+
// * Custom label 1 for custom grouping of items in a Shopping campaign.
|
277
|
+
// */
|
278
|
+
// customLabel1?: string | null;
|
279
|
+
// /**
|
280
|
+
// * Custom label 2 for custom grouping of items in a Shopping campaign.
|
281
|
+
// */
|
282
|
+
// customLabel2?: string | null;
|
283
|
+
// /**
|
284
|
+
// * Custom label 3 for custom grouping of items in a Shopping campaign.
|
285
|
+
// */
|
286
|
+
// customLabel3?: string | null;
|
287
|
+
// /**
|
288
|
+
// * Custom label 4 for custom grouping of items in a Shopping campaign.
|
289
|
+
// */
|
290
|
+
// customLabel4?: string | null;
|
291
|
+
// /**
|
292
|
+
// * The date time when an offer becomes visible in search results across Google’s YouTube surfaces, in [ISO 8601](http://en.wikipedia.org/wiki/ISO_8601) format. See [Disclosure date](https://support.google.com/merchants/answer/13034208) for more information.
|
293
|
+
// */
|
294
|
+
// disclosureDate?: string | null;
|
295
|
+
// /**
|
296
|
+
// * Date on which the item should expire, as specified upon insertion, in ISO 8601 format. The actual expiration date in Google Shopping is exposed in `productstatuses` as `googleExpirationDate` and might be earlier if `expirationDate` is too far in the future.
|
297
|
+
// */
|
298
|
+
// expirationDate?: string | null;
|
299
|
+
// /**
|
300
|
+
// * The material of which the item is made.
|
301
|
+
// */
|
302
|
+
// material?: string | null;
|
303
|
+
// /**
|
304
|
+
// * Maximal product handling time (in business days).
|
305
|
+
// */
|
306
|
+
// maxHandlingTime?: string | null;
|
307
|
+
// /**
|
308
|
+
// * Minimal product handling time (in business days).
|
309
|
+
// */
|
310
|
+
// minHandlingTime?: string | null;
|
311
|
+
// /**
|
312
|
+
// * The pick up option for the item. Acceptable values are: - "`buy`" - "`reserve`" - "`ship to store`" - "`not supported`"
|
313
|
+
// */
|
314
|
+
// pickupMethod?: string | null;
|
315
|
+
// /**
|
316
|
+
// * Item store pickup timeline. Acceptable values are: - "`same day`" - "`next day`" - "`2-day`" - "`3-day`" - "`4-day`" - "`5-day`" - "`6-day`" - "`7-day`" - "`multi-week`"
|
317
|
+
// */
|
318
|
+
// pickupSla?: string | null;
|
319
|
+
// /**
|
320
|
+
// * The height of the product in the units provided. The value must be between 0 (exclusive) and 3000 (inclusive).
|
321
|
+
// */
|
322
|
+
// productHeight?: Schema$ProductDimension;
|
323
|
+
// /**
|
324
|
+
// * The length of the product in the units provided. The value must be between 0 (exclusive) and 3000 (inclusive).
|
325
|
+
// */
|
326
|
+
// productLength?: Schema$ProductDimension;
|
327
|
+
// /**
|
328
|
+
// * The width of the product in the units provided. The value must be between 0 (exclusive) and 3000 (inclusive).
|
329
|
+
// */
|
330
|
+
// productWidth?: Schema$ProductDimension;
|
331
|
+
// /**
|
332
|
+
// * Shipping rules.
|
333
|
+
// */
|
334
|
+
// shipping?: Schema$ProductShipping[];
|
335
|
+
// /**
|
336
|
+
// * Height of the item for shipping.
|
337
|
+
// */
|
338
|
+
// shippingHeight?: Schema$ProductShippingDimension;
|
339
|
+
// /**
|
340
|
+
// * Length of the item for shipping.
|
341
|
+
// */
|
342
|
+
// shippingLength?: Schema$ProductShippingDimension;
|
343
|
+
// /**
|
344
|
+
// * Weight of the item for shipping.
|
345
|
+
// */
|
346
|
+
// shippingWeight?: Schema$ProductShippingWeight;
|
347
|
+
// /**
|
348
|
+
// * Width of the item for shipping.
|
349
|
+
// */
|
350
|
+
// shippingWidth?: Schema$ProductShippingDimension;
|
351
|
+
// /**
|
352
|
+
// * List of country codes (ISO 3166-1 alpha-2) to exclude the offer from Shopping Ads destination. Countries from this list are removed from countries configured in MC feed settings.
|
353
|
+
// */
|
354
|
+
// shoppingAdsExcludedCountries?: string[] | null;
|
355
|
+
// /**
|
356
|
+
// * Size of the item. Only one value is allowed. For variants with different sizes, insert a separate product for each size with the same `itemGroupId` value (see size definition).
|
357
|
+
// */
|
358
|
+
// sizes?: string[] | null;
|
359
|
+
// /**
|
360
|
+
// * System in which the size is specified. Recommended for apparel items.
|
361
|
+
// */
|
362
|
+
// sizeSystem?: string | null;
|
363
|
+
// /**
|
364
|
+
// * The cut of the item. Recommended for apparel items.
|
365
|
+
// */
|
366
|
+
// sizeType?: string | null;
|
367
|
+
];
|
368
|
+
export const CHANNEL = 'online';
|
369
|
+
export const GMC_PRODUCT_ID_TEMPLATE = '{PRODUCT_ID}_{VARIANT_ID}';
|
package/src/index.ts
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
export * from './constants/google.constants.js';
|
2
|
+
export * from './constants/product.constants.js';
|
3
|
+
export * from './constants/profile.constants.js';
|
4
|
+
|
5
|
+
export * from './types/product.types.js';
|
6
|
+
export * from './types/profile.types.js';
|
7
|
+
export * from './types/company.types.js';
|
8
|
+
|
9
|
+
export * from './utils/gmc.js';
|
10
|
+
export * from './utils/profile.js';
|
11
|
+
export * from './utils/utils.js';
|
@@ -0,0 +1,97 @@
|
|
1
|
+
import { GmcProductSyncStatus } from '../constants/google.constants.js';
|
2
|
+
import { ProductSyncStatus } from '../constants/product.constants.js';
|
3
|
+
|
4
|
+
export type AppProductStatus = 'active' | 'draft' | 'archived';
|
5
|
+
|
6
|
+
export type AppProductVariant = {
|
7
|
+
id: number;
|
8
|
+
title: string;
|
9
|
+
price: string;
|
10
|
+
sku: string | null;
|
11
|
+
image_id: number | null;
|
12
|
+
};
|
13
|
+
|
14
|
+
export type GmcProductId = {
|
15
|
+
id: string;
|
16
|
+
profileId: string;
|
17
|
+
gmcAccount: string;
|
18
|
+
uploaded_at: string;
|
19
|
+
status?: GmcProductSyncStatus;
|
20
|
+
};
|
21
|
+
|
22
|
+
export type GoogleProductIssue = {
|
23
|
+
servability?: 'demoted' | 'disapproved' | 'unaffected' | string;
|
24
|
+
description?: string;
|
25
|
+
documentation?: string;
|
26
|
+
};
|
27
|
+
|
28
|
+
export type gmcIssue = {
|
29
|
+
gmcProductId: string;
|
30
|
+
gmcAccount: string;
|
31
|
+
updated_at: string;
|
32
|
+
issue: GoogleProductIssue[];
|
33
|
+
};
|
34
|
+
|
35
|
+
export type ShopifyCollection = {
|
36
|
+
id: number;
|
37
|
+
handle: string;
|
38
|
+
title: string;
|
39
|
+
};
|
40
|
+
|
41
|
+
export type AppProduct = {
|
42
|
+
status: AppProductStatus;
|
43
|
+
handle: string;
|
44
|
+
title: string;
|
45
|
+
category?: string;
|
46
|
+
id: number;
|
47
|
+
googleCategory?: number;
|
48
|
+
image?: string;
|
49
|
+
_id: string;
|
50
|
+
gmcIssues?: gmcIssue[];
|
51
|
+
gmcProductId?: GmcProductId[];
|
52
|
+
updated_at: string;
|
53
|
+
variants: AppProductVariant[];
|
54
|
+
images: {
|
55
|
+
src: string;
|
56
|
+
id: string;
|
57
|
+
}[];
|
58
|
+
collections: ShopifyCollection[];
|
59
|
+
tags: string[];
|
60
|
+
vendor: string;
|
61
|
+
product_type: string;
|
62
|
+
syncStatus: ProductSyncStatus;
|
63
|
+
};
|
64
|
+
|
65
|
+
export type GetProductsQuery = {
|
66
|
+
before?: string;
|
67
|
+
after?: string;
|
68
|
+
limit?: number;
|
69
|
+
handle?: string;
|
70
|
+
title?: string;
|
71
|
+
id?: number[];
|
72
|
+
sortField?: 'title' | 'id';
|
73
|
+
sort?: 'asc' | 'desc';
|
74
|
+
fields?: string[];
|
75
|
+
gmcProductId?: string[] | boolean;
|
76
|
+
};
|
77
|
+
|
78
|
+
export type GetProductsResponse = {
|
79
|
+
products: AppProduct[];
|
80
|
+
pagination: {
|
81
|
+
firstId: string;
|
82
|
+
lastId: string;
|
83
|
+
hasMore: boolean;
|
84
|
+
hasLess: boolean;
|
85
|
+
};
|
86
|
+
};
|
87
|
+
|
88
|
+
export type ProductsList = {
|
89
|
+
ids: string[];
|
90
|
+
};
|
91
|
+
|
92
|
+
export type UploadProductBulkPayload = {
|
93
|
+
collections: string[];
|
94
|
+
vendors: string[];
|
95
|
+
types: string[];
|
96
|
+
tags: string[];
|
97
|
+
};
|
@@ -0,0 +1,73 @@
|
|
1
|
+
import {
|
2
|
+
ProductUploadRuleFilters,
|
3
|
+
ProductUploadMappings,
|
4
|
+
} from '../constants/profile.constants.js';
|
5
|
+
import { RuleOperators } from '../constants/profile.constants.js';
|
6
|
+
|
7
|
+
export type ProductUploadRuleOpratorType = {
|
8
|
+
label: string;
|
9
|
+
value: string;
|
10
|
+
};
|
11
|
+
|
12
|
+
export type ProductUploadRuleFilterType = {
|
13
|
+
label: string;
|
14
|
+
operators: ProductUploadRuleOpratorType[];
|
15
|
+
value: string;
|
16
|
+
disabled?: boolean;
|
17
|
+
};
|
18
|
+
|
19
|
+
export type RuleOperatorsType = typeof RuleOperators;
|
20
|
+
export type ValueType = string | string[] | number[] | number | boolean;
|
21
|
+
export type OptionTypeItem = { label: string; value: ValueType };
|
22
|
+
export type OptionTypeGroup = { title: string; options: OptionTypeItem[] };
|
23
|
+
export type OptionType = OptionTypeItem | OptionTypeGroup | string;
|
24
|
+
export type ProductUploadMapSource = {
|
25
|
+
required: boolean;
|
26
|
+
label: string;
|
27
|
+
attribute: string;
|
28
|
+
type: 'select' | 'multiselect' | 'text' | 'number';
|
29
|
+
choises?: OptionType[];
|
30
|
+
rules: ProductUploadRuleFilterType['value'][];
|
31
|
+
description?: string;
|
32
|
+
defaultValue?: ValueType;
|
33
|
+
};
|
34
|
+
|
35
|
+
export type ProductUploadMapping = {
|
36
|
+
attribute: MappingFields;
|
37
|
+
value: ValueType;
|
38
|
+
rules: {
|
39
|
+
sections: {
|
40
|
+
ruleItems: {
|
41
|
+
attribute: (typeof ProductUploadRuleFilters)[number]['value'];
|
42
|
+
operator: ProductUploadRuleOpratorType['value'];
|
43
|
+
value: string | string[] | number[] | number | boolean;
|
44
|
+
id: string;
|
45
|
+
}[];
|
46
|
+
}[];
|
47
|
+
};
|
48
|
+
};
|
49
|
+
|
50
|
+
type MappingFields = (typeof ProductUploadMappings)[number]['attribute'];
|
51
|
+
|
52
|
+
export type ProductUploadProfile = {
|
53
|
+
id: string;
|
54
|
+
name: string;
|
55
|
+
active?: boolean;
|
56
|
+
rules: ProductUploadRules;
|
57
|
+
mappings: ProductUploadMapping[];
|
58
|
+
};
|
59
|
+
|
60
|
+
export type ProductUploadRules = {
|
61
|
+
sections: ProductUploadRuleSection[];
|
62
|
+
};
|
63
|
+
|
64
|
+
export type ProductUploadRuleSection = {
|
65
|
+
ruleItems: ProductUploadRuleItem[];
|
66
|
+
};
|
67
|
+
|
68
|
+
export type ProductUploadRuleItem = {
|
69
|
+
id: string;
|
70
|
+
attribute: string;
|
71
|
+
operator: string;
|
72
|
+
value: string | number | string[] | number[] | boolean;
|
73
|
+
};
|
package/src/utils/gmc.ts
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
import { GMC_PRODUCT_ID_TEMPLATE } from '../constants/profile.constants.js';
|
2
|
+
|
3
|
+
export function isGmcProductId (productId: string): boolean {
|
4
|
+
return new RegExp(
|
5
|
+
GMC_PRODUCT_ID_TEMPLATE.replace('{PRODUCT_ID}', '\\d+').replace(
|
6
|
+
'{VARIANT_ID}',
|
7
|
+
'\\d+'
|
8
|
+
)
|
9
|
+
).test(productId);
|
10
|
+
}
|
11
|
+
|
12
|
+
export function GMCProductIdToShopify (productId: string): number {
|
13
|
+
const [, , , id] = productId.split(':');
|
14
|
+
return Number(getProductIdFromGmcId(id));
|
15
|
+
}
|
16
|
+
|
17
|
+
export function GmcIdParts (gmcProductId: string): {
|
18
|
+
channel: string;
|
19
|
+
locale: string;
|
20
|
+
country: string;
|
21
|
+
idPart: string;
|
22
|
+
shopifyId: number;
|
23
|
+
shopifyVariantId: number;
|
24
|
+
} {
|
25
|
+
const [channel, locale, country, idPart] = gmcProductId.split(':');
|
26
|
+
|
27
|
+
if (!channel || !locale || !country || !idPart) {
|
28
|
+
throw new Error(`${gmcProductId} is not a valid GMC product id`);
|
29
|
+
}
|
30
|
+
|
31
|
+
return {
|
32
|
+
channel,
|
33
|
+
locale,
|
34
|
+
country,
|
35
|
+
idPart,
|
36
|
+
...getShopifyIdsFromGmcIdPart(idPart),
|
37
|
+
};
|
38
|
+
}
|
39
|
+
|
40
|
+
export function makeGmcIdPart (
|
41
|
+
productId: number | null,
|
42
|
+
variantId: number | null
|
43
|
+
): string {
|
44
|
+
return GMC_PRODUCT_ID_TEMPLATE.replace(
|
45
|
+
'{PRODUCT_ID}',
|
46
|
+
String(productId)
|
47
|
+
).replace('{VARIANT_ID}', String(variantId));
|
48
|
+
}
|
49
|
+
|
50
|
+
export function getShopifyIdsFromGmcIdPart (gmcId: string): {
|
51
|
+
shopifyId: number;
|
52
|
+
shopifyVariantId: number;
|
53
|
+
} {
|
54
|
+
if (!isGmcProductId(gmcId)) {
|
55
|
+
throw new Error(`${gmcId} is not a valid GMC product id part`);
|
56
|
+
}
|
57
|
+
|
58
|
+
const [productId, variantId] = gmcId.split('_');
|
59
|
+
return { shopifyId: Number(productId), shopifyVariantId: Number(variantId) };
|
60
|
+
}
|
61
|
+
|
62
|
+
export function getProductIdFromGmcId (gmcId: string): number {
|
63
|
+
if (!isGmcProductId(gmcId)) {
|
64
|
+
throw new Error(`${gmcId} is not a valid GMC product id part`);
|
65
|
+
}
|
66
|
+
|
67
|
+
const [productId] = gmcId.split('_');
|
68
|
+
return Number(productId);
|
69
|
+
}
|