@sommpicks/sommpicks-shopify 24.12.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/Logger.ts +18 -0
- package/README.md +258 -0
- package/addTypings.sh +2 -0
- package/bitbucket-pipelines.yml +38 -0
- package/index.ts +132 -0
- package/package.json +57 -0
- package/publish.sh +20 -0
- package/services/CacheWrapper.ts +30 -0
- package/services/CountryCodeService.ts +507 -0
- package/shopify/ShopifyAppService.ts +109 -0
- package/shopify/ShopifyAssetService.ts +20 -0
- package/shopify/ShopifyBillingService.ts +73 -0
- package/shopify/ShopifyCartTrasnformationService.ts +207 -0
- package/shopify/ShopifyCollectionService.ts +523 -0
- package/shopify/ShopifyCustomerService.ts +472 -0
- package/shopify/ShopifyDeliveryCustomisationService.ts +220 -0
- package/shopify/ShopifyDiscountService.ts +131 -0
- package/shopify/ShopifyDraftOrderService.ts +125 -0
- package/shopify/ShopifyFulfillmentService.ts +41 -0
- package/shopify/ShopifyFunctionsProductDiscountsService.ts +166 -0
- package/shopify/ShopifyInventoryService.ts +415 -0
- package/shopify/ShopifyLocationService.ts +29 -0
- package/shopify/ShopifyOrderRefundsService.ts +138 -0
- package/shopify/ShopifyOrderRiskService.ts +19 -0
- package/shopify/ShopifyOrderService.ts +1143 -0
- package/shopify/ShopifyPageService.ts +62 -0
- package/shopify/ShopifyProductService.ts +772 -0
- package/shopify/ShopifyShippingZonesService.ts +37 -0
- package/shopify/ShopifyShopService.ts +101 -0
- package/shopify/ShopifyTemplateService.ts +30 -0
- package/shopify/ShopifyThemeService.ts +33 -0
- package/shopify/ShopifyUtils.ts +56 -0
- package/shopify/ShopifyWebhookService.ts +110 -0
- package/shopify/base/APIVersion.ts +4 -0
- package/shopify/base/AbstractService.ts +152 -0
- package/shopify/base/ErrorHelper.ts +24 -0
- package/shopify/errors/InspiraShopifyCustomError.ts +7 -0
- package/shopify/errors/InspiraShopifyError.ts +15 -0
- package/shopify/errors/InspiraShopifyUnableToReserveInventoryError.ts +7 -0
- package/shopify/helpers/ShopifyProductServiceHelper.ts +450 -0
- package/shopify/product/ShopifyProductCountService.ts +110 -0
- package/shopify/product/ShopifyProductListService.ts +333 -0
- package/shopify/product/ShopifyProductMetafieldsService.ts +405 -0
- package/shopify/product/ShopifyProductPublicationsService.ts +112 -0
- package/shopify/product/ShopifyVariantService.ts +584 -0
- package/shopify/router/ShopifyMandatoryRouter.ts +37 -0
- package/shopify/router/ShopifyRouter.ts +85 -0
- package/shopify/router/ShopifyRouterBis.ts +85 -0
- package/shopify/router/ShopifyRouterBisBis.ts +85 -0
- package/shopify/router/ShopifyRouterBisBisBis.ts +85 -0
- package/shopify/router/ShopifyRouterBisBisBisBis.ts +85 -0
- package/shopify/router/WebhookSkipMiddleware.ts +73 -0
- package/shopify/router/services/CryptoService.ts +26 -0
- package/shopify/router/services/HmacValidator.ts +36 -0
- package/shopify/router/services/OauthService.ts +17 -0
- package/shopify/router/services/RestUtils.ts +13 -0
- package/shopify/router/services/rateLimiter/MemoryStores.ts +46 -0
- package/shopify/router/services/rateLimiter/StoreRateLimiter.ts +46 -0
- package/test/README.md +223 -0
- package/test/router/ShopifyRouter.test.ts +71 -0
- package/test/router/WebhookSkipMiddleware.test.ts +86 -0
- package/test/router/services/HmacValidator.test.ts +24 -0
- package/test/router/services/RestUtils.test.ts +13 -0
- package/test/router/services/rateLimiter/StoreRateLimiter.test.ts +62 -0
- package/test/services/CacheWrapper.test.ts +30 -0
- package/test/shopify/ShopifyOrderService.test.ts +29 -0
- package/test/shopify/ShopifyProductService.test.ts +118 -0
- package/test/shopify/ShopifyWebhookService.test.ts +105 -0
- package/tsconfig.json +10 -0
- package/typings/axios.d.ts +8 -0
- package/typings/index.d.ts +1682 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import { AxiosInstance } from 'axios';
|
|
2
|
+
import { print } from 'graphql';
|
|
3
|
+
import gql from 'graphql-tag';
|
|
4
|
+
import { Logger } from '../../Logger';
|
|
5
|
+
import InspiraShopifyError from '../errors/InspiraShopifyError';
|
|
6
|
+
import * as moment from 'moment';
|
|
7
|
+
import { ShopifyProductServiceHelper } from '../helpers/ShopifyProductServiceHelper';
|
|
8
|
+
import { AbstractService } from '../base/AbstractService';
|
|
9
|
+
|
|
10
|
+
export class ShopifyProductListService extends AbstractService {
|
|
11
|
+
|
|
12
|
+
private shopifyProductServiceHelper: ShopifyProductServiceHelper;
|
|
13
|
+
|
|
14
|
+
constructor(private axiosInstance: AxiosInstance) {
|
|
15
|
+
super();
|
|
16
|
+
this.shopifyProductServiceHelper = new ShopifyProductServiceHelper();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @param numOfProducts number or all if you want them all
|
|
22
|
+
* @param filter by title, handle published Status and createdDaysAgo
|
|
23
|
+
* @param daysAgo number or all if no filter
|
|
24
|
+
* @param options by default it loads all data
|
|
25
|
+
* @returns {IProduct} List of products
|
|
26
|
+
*/
|
|
27
|
+
public get = async ( numOfProducts: number | 'all',
|
|
28
|
+
filter: { title?: string; handle?: string; publishedStatus: 'any' | 'published' | 'unpublished'; createdDaysAgo: number | 'all', productType?: string; vendor?: string; },
|
|
29
|
+
options: { add_variants?: boolean; add_weight?: boolean; add_body_html?: boolean; add_title?: boolean; add_images?: boolean; add_tags?: boolean; add_options?: boolean; }): Promise<IProduct[]> => {
|
|
30
|
+
try {
|
|
31
|
+
Logger.info(`ShopifyProductListService - get -> Get products with criteria filter: ${JSON.stringify(filter)} and numOfProducts ${numOfProducts}`);
|
|
32
|
+
const products: IProduct[] = [];
|
|
33
|
+
const queryParams = this.buildProductsQuery(filter.publishedStatus, filter.createdDaysAgo, 'all', filter.handle, filter.title, filter.vendor, filter.productType, null);
|
|
34
|
+
let nextCursor = '';
|
|
35
|
+
Logger.info(`ShopifyProductListService - get -> First products query going in ... Query: ${queryParams}`);
|
|
36
|
+
while (nextCursor !== null) {
|
|
37
|
+
if (numOfProducts !== 'all' && products.length >= numOfProducts) {
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
const productsQuery = this.buildProductsGraphQL(numOfProducts, queryParams, nextCursor, options);
|
|
41
|
+
Logger.info(`ShopifyProductListService - get -> Products graphQL query going in ${productsQuery}`);
|
|
42
|
+
const response = await this.axiosInstance.post('/graphql.json', { query: print(gql`${productsQuery}`) }, { query_cost: 800 });
|
|
43
|
+
if (response && response.data && response.data.data && response.data.data.products) {
|
|
44
|
+
const responseData: ShopifygraphQl.IProductResponseFrame = response.data.data;
|
|
45
|
+
Logger.info(`ShopifyProductListService -> Products graphQL pageInfo ${JSON.stringify(responseData?.products?.pageInfo)}`);
|
|
46
|
+
if (responseData.products.pageInfo.hasNextPage) {
|
|
47
|
+
nextCursor = responseData.products.pageInfo.endCursor;
|
|
48
|
+
} else {
|
|
49
|
+
nextCursor = null;
|
|
50
|
+
}
|
|
51
|
+
for (const product of responseData.products.edges) {
|
|
52
|
+
this.shopifyProductServiceHelper.addProduct(products, product.node);
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
throw new InspiraShopifyError({ message: JSON.stringify(response.data.errors) });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
}
|
|
59
|
+
Logger.info(`ShopifyProductListService - get -> ${products.length} Products returning`);
|
|
60
|
+
return products;
|
|
61
|
+
} catch (error) { this.logErrorAndThrow(error); }
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
*
|
|
67
|
+
* @param {number[]} ids product ids to look (Max of 100)
|
|
68
|
+
* @param options by default it loads all data
|
|
69
|
+
* @returns {IProduct} List of products
|
|
70
|
+
*/
|
|
71
|
+
public getByIds = async (ids: number[],
|
|
72
|
+
options: { add_variants?: boolean; add_weight?: boolean; add_body_html?: boolean; add_title?: boolean; add_images?: boolean; add_tags?: boolean; add_options?: boolean; }): Promise<IProduct[]> => {
|
|
73
|
+
try {
|
|
74
|
+
Logger.info(`ShopifyProductListService - getByIds -> Get products ids: ${JSON.stringify(ids)}`);
|
|
75
|
+
const products: IProduct[] = [];
|
|
76
|
+
const productsQuery = this.buildProductsGraphQL(ids.length, `${ids.map(id => `(id:${id})`).join(' OR ')}`, null, options);
|
|
77
|
+
Logger.info(`ShopifyProductListService - getByIds -> Products graphQL query going in ${productsQuery}`);
|
|
78
|
+
const response = await this.axiosInstance.post('/graphql.json', { query: print(gql`${productsQuery}`) }, { query_cost: 800 });
|
|
79
|
+
if (response && response.data && response.data.data && response.data.data.products) {
|
|
80
|
+
const responseData: ShopifygraphQl.IProductResponseFrame = response.data.data;
|
|
81
|
+
for (const product of responseData.products.edges) {
|
|
82
|
+
this.shopifyProductServiceHelper.addProduct(products, product.node);
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
throw new InspiraShopifyError({ message: JSON.stringify(response.data.errors) });
|
|
86
|
+
}
|
|
87
|
+
Logger.info(`ShopifyProductListService - getByIds -> ${products.length} Products returning`);
|
|
88
|
+
return products;
|
|
89
|
+
} catch (error) { this.logErrorAndThrow(error); }
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
*
|
|
95
|
+
* @param {string } cursor sent null to start from begining
|
|
96
|
+
* @param daysAgo number or all if no filter
|
|
97
|
+
* @param options by default it loads all data
|
|
98
|
+
* @returns {IProduct} List of products
|
|
99
|
+
*/
|
|
100
|
+
public getInBatch = async (cursor: string,
|
|
101
|
+
filter: { title?: string; handle?: string; publishedStatus: 'any' | 'published' | 'unpublished'; createdDaysAgo: number | 'all', updatedDaysAgo: number | 'all', productType?: string; vendor?: string; collectionID: number | null },
|
|
102
|
+
options: { add_variants?: boolean; add_weight?: boolean; add_body_html?: boolean; add_title?: boolean; add_images?: boolean; add_tags?: boolean; add_options?: boolean; }): Promise<IProductBatch> => {
|
|
103
|
+
try {
|
|
104
|
+
Logger.info(`ShopifyProductListService - getInBatch -> Get products with criteria : ${JSON.stringify(filter)}`);
|
|
105
|
+
const productsInBatch: IProductBatch = { products: [], nextCursor: null };
|
|
106
|
+
const queryParams = this.buildProductsQuery(filter.publishedStatus, filter.createdDaysAgo, filter.updatedDaysAgo, filter.handle, filter.title, filter.vendor, filter.productType, filter.collectionID);
|
|
107
|
+
|
|
108
|
+
Logger.info(`ShopifyProductListService - getInBatch -> First products query going in ... Query: ${queryParams}`);
|
|
109
|
+
|
|
110
|
+
const productsQuery = this.buildProductsGraphQL('all', queryParams, cursor, options);
|
|
111
|
+
|
|
112
|
+
Logger.info(`ShopifyProductListService - getInBatch -> Products graphQL query going in ${productsQuery}`);
|
|
113
|
+
const response = await this.axiosInstance.post('/graphql.json', { query: print(gql`${productsQuery}`) }, { query_cost: 800 });
|
|
114
|
+
if (response && response.data && response.data.data && response.data.data.products) {
|
|
115
|
+
const responseData: ShopifygraphQl.IProductResponseFrame = response.data.data;
|
|
116
|
+
Logger.info(`ShopifyProductListService -> Products graphQL pageInfo ${JSON.stringify(responseData?.products?.pageInfo)}`);
|
|
117
|
+
if (responseData.products.pageInfo.hasNextPage) {
|
|
118
|
+
productsInBatch.nextCursor = responseData.products.pageInfo.endCursor;
|
|
119
|
+
} else {
|
|
120
|
+
productsInBatch.nextCursor = null;
|
|
121
|
+
}
|
|
122
|
+
for (const product of responseData.products.edges) {
|
|
123
|
+
this.shopifyProductServiceHelper.addProduct(productsInBatch.products, product.node);
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
throw new InspiraShopifyError({ message: JSON.stringify(response.data.errors) });
|
|
127
|
+
}
|
|
128
|
+
Logger.info(`ShopifyProductListService - getInBatch -> ${productsInBatch.products.length} Products returning`);
|
|
129
|
+
return productsInBatch;
|
|
130
|
+
} catch (error) { this.logErrorAndThrow(error); }
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
*
|
|
135
|
+
* @param id of the product
|
|
136
|
+
* @param options by default it loads all data
|
|
137
|
+
* @returns {IProduct} product
|
|
138
|
+
*/
|
|
139
|
+
public getById = async (id: number,
|
|
140
|
+
options: { add_variants?: boolean; add_weight?: boolean; add_body_html?: boolean; add_title?: boolean; add_images?: boolean; add_tags?: boolean; add_options?: boolean; }): Promise<IProduct> => {
|
|
141
|
+
try {
|
|
142
|
+
Logger.info(`ShopifyProductListService - getById -> Get product with id ${id}`);
|
|
143
|
+
let productToReturn: IProduct = null;
|
|
144
|
+
|
|
145
|
+
const productQuery = `{ product(id: "${this.getGraphProductIdFromId(id)}") {
|
|
146
|
+
id
|
|
147
|
+
${options.add_body_html === false ? '' : 'descriptionHtml'}
|
|
148
|
+
${options.add_title === false ? '' : 'title'}
|
|
149
|
+
vendor
|
|
150
|
+
productType
|
|
151
|
+
createdAt
|
|
152
|
+
updatedAt
|
|
153
|
+
publishedAt
|
|
154
|
+
handle
|
|
155
|
+
status
|
|
156
|
+
${options.add_images === false ? '' : 'images(first: 20) { edges { node { id url } } }'}
|
|
157
|
+
${options.add_tags === false ? '' : 'tags'}
|
|
158
|
+
${options.add_options === false ? '' : 'options { name position optionValues { name } }'}
|
|
159
|
+
${options.add_variants === false ? '' : `variants(first: 150) {
|
|
160
|
+
edges {
|
|
161
|
+
node {
|
|
162
|
+
id
|
|
163
|
+
price
|
|
164
|
+
sku
|
|
165
|
+
availableForSale
|
|
166
|
+
inventoryQuantity
|
|
167
|
+
inventoryPolicy
|
|
168
|
+
taxable
|
|
169
|
+
${options.add_images === false ? '' : 'media(first:1) { nodes { id } }'}
|
|
170
|
+
${options.add_options === false ? '' : 'selectedOptions { name value }'}
|
|
171
|
+
inventoryItem {
|
|
172
|
+
id
|
|
173
|
+
${options.add_weight === false ? '' : 'measurement { weight { unit value } }'}
|
|
174
|
+
tracked
|
|
175
|
+
unitCost {
|
|
176
|
+
amount
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}` }
|
|
182
|
+
}
|
|
183
|
+
}`;
|
|
184
|
+
Logger.info(`ShopifyProductListService - getById -> Product graphQL query going in ${productQuery}`);
|
|
185
|
+
const response = await this.axiosInstance.post('/graphql.json', { query: print(gql`${productQuery}`) }, { query_cost: 80 });
|
|
186
|
+
if (response && response.data && response.data.data && response.data.data.product) {
|
|
187
|
+
const responseProduct: ShopifygraphQl.IGenericProductResponse = response.data.data.product;
|
|
188
|
+
productToReturn = {
|
|
189
|
+
id: this.getIdFromGraphId(responseProduct.id),
|
|
190
|
+
body_html: responseProduct.descriptionHtml ? responseProduct.descriptionHtml : null,
|
|
191
|
+
published: responseProduct.publishedAt ? true : false,
|
|
192
|
+
title: responseProduct.title ? responseProduct.title : null,
|
|
193
|
+
created_at: responseProduct.createdAt,
|
|
194
|
+
images: responseProduct.images && responseProduct.images.edges && responseProduct.images.edges.length > 0 ? responseProduct.images.edges.map(im => ({ id: this.getIdFromGraphId(im.node.id), src: im.node.url })) : null,
|
|
195
|
+
product_type: responseProduct.productType,
|
|
196
|
+
published_at: responseProduct.publishedAt,
|
|
197
|
+
updated_at: responseProduct.updatedAt,
|
|
198
|
+
handle: responseProduct.handle,
|
|
199
|
+
status: responseProduct.status,
|
|
200
|
+
vendor: responseProduct.vendor,
|
|
201
|
+
options: responseProduct.options && responseProduct.options.length > 0 ? responseProduct.options.map(op => ({ name: op.name, values: op.optionValues ? op.optionValues.map(v => v.name) : [] })) : [],
|
|
202
|
+
tags: responseProduct.tags ? responseProduct.tags : [],
|
|
203
|
+
variants: responseProduct.variants ? responseProduct.variants.edges.map(variant => ({
|
|
204
|
+
id: this.getIdFromGraphId(variant.node.id),
|
|
205
|
+
barcode: variant.node.barcode ? variant.node.barcode : null,
|
|
206
|
+
price: variant.node.price,
|
|
207
|
+
sku: variant.node.sku,
|
|
208
|
+
inventory_quantity: variant.node.inventoryQuantity,
|
|
209
|
+
inventory_policy: variant.node.inventoryPolicy,
|
|
210
|
+
compare_at_price: variant.node.compareAtPrice,
|
|
211
|
+
taxable: variant.node.taxable,
|
|
212
|
+
weight: variant.node.inventoryItem?.measurement?.weight ? variant.node.inventoryItem?.measurement.weight.value : null,
|
|
213
|
+
weight_unit: variant.node.inventoryItem?.measurement?.weight ? variant.node.inventoryItem?.measurement.weight.unit : null,
|
|
214
|
+
image_id: variant.node.media?.nodes?.length > 0 ? this.getIdFromGraphId(variant.node.media.nodes[0].id) : null,
|
|
215
|
+
inventory_item_id: this.getIdFromGraphId(variant.node.inventoryItem.id),
|
|
216
|
+
option1: variant.node.selectedOptions?.length > 0 ? variant.node.selectedOptions[0].value : null,
|
|
217
|
+
option2: variant.node.selectedOptions?.length > 1 ? variant.node.selectedOptions[1].value : null,
|
|
218
|
+
option3: variant.node.selectedOptions?.length > 2 ? variant.node.selectedOptions[2].value : null,
|
|
219
|
+
} as IVariant)) : []
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
Logger.info(`ShopifyProductListService - getById -> ${productToReturn?.id} Products returning`);
|
|
223
|
+
return productToReturn;
|
|
224
|
+
} catch (error) { this.logErrorAndThrow(error); }
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
private buildProductsQuery = (publishedStatus: 'any' | 'published' | 'unpublished', daysAgoCreated: number | 'all', daysAgoUpdated: number | 'all', handle: string, title: string, vendor: string, productType: string, collectionId: number): string => {
|
|
228
|
+
let queryParams = '';
|
|
229
|
+
if (publishedStatus === 'published' || publishedStatus === 'unpublished') {
|
|
230
|
+
queryParams = `published_status:'${publishedStatus}'`;
|
|
231
|
+
}
|
|
232
|
+
if (daysAgoCreated && daysAgoCreated !== 'all') {
|
|
233
|
+
const dayAgoString = moment().add(-daysAgoCreated, 'days').format('YYYY-MM-DDTHH:mm:ss');
|
|
234
|
+
if (queryParams.length > 0) {
|
|
235
|
+
queryParams = `${queryParams} AND created_at:>'${dayAgoString}'`;
|
|
236
|
+
} else {
|
|
237
|
+
queryParams = `created_at:>'${dayAgoString}'`;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (daysAgoUpdated && daysAgoUpdated !== 'all') {
|
|
241
|
+
const dayAgoUpdatedString = moment().add(-daysAgoUpdated, 'days').format('YYYY-MM-DDTHH:mm:ss');
|
|
242
|
+
if (queryParams.length > 0) {
|
|
243
|
+
queryParams = `${queryParams} AND updated_at:>'${dayAgoUpdatedString}'`;
|
|
244
|
+
} else {
|
|
245
|
+
queryParams = `updated_at:>'${dayAgoUpdatedString}'`;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
if (handle) {
|
|
249
|
+
if (queryParams.length > 0) {
|
|
250
|
+
queryParams = `${queryParams} AND handle:'${handle}'`;
|
|
251
|
+
} else {
|
|
252
|
+
queryParams = `handle:'${handle}'`;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (title) {
|
|
256
|
+
if (queryParams.length > 0) {
|
|
257
|
+
queryParams = `${queryParams} AND title:'${title}'`;
|
|
258
|
+
} else {
|
|
259
|
+
queryParams = `title:'${title}'`;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (vendor) {
|
|
263
|
+
if (queryParams.length > 0) {
|
|
264
|
+
queryParams = `${queryParams} AND vendor:'${vendor}'`;
|
|
265
|
+
} else {
|
|
266
|
+
queryParams = `vendor:'${vendor}'`;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (productType) {
|
|
270
|
+
if (queryParams.length > 0) {
|
|
271
|
+
queryParams = `${queryParams} AND product_type:'${productType}'`;
|
|
272
|
+
} else {
|
|
273
|
+
queryParams = `product_type:'${productType}'`;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (collectionId) {
|
|
277
|
+
if (queryParams.length > 0) {
|
|
278
|
+
queryParams = `${queryParams} AND collection_id:'${collectionId}'`;
|
|
279
|
+
} else {
|
|
280
|
+
queryParams = `collection_id:'${collectionId}'`;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return queryParams;
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
private buildProductsGraphQL = (numOfProducts: number | 'all', queryParams: string, nextCursor: string, options: { add_variants?: boolean; add_weight?: boolean; add_body_html?: boolean; add_title?: boolean; add_images?: boolean; add_tags?: boolean; add_options?: boolean; }): string => {
|
|
287
|
+
const productsQuery = `{ products(first: ${numOfProducts !== 'all' && numOfProducts < 100 ? numOfProducts : 100} ${queryParams !== '' ? `, query: "${queryParams}"` : ''} ${nextCursor !== '' && nextCursor !== null ? `, after: "${nextCursor}"` : ''}) {
|
|
288
|
+
pageInfo { endCursor hasNextPage }
|
|
289
|
+
edges {
|
|
290
|
+
node {
|
|
291
|
+
id
|
|
292
|
+
${options.add_body_html === false ? '' : 'descriptionHtml'}
|
|
293
|
+
${options.add_title === false ? '' : 'title'}
|
|
294
|
+
vendor
|
|
295
|
+
productType
|
|
296
|
+
createdAt
|
|
297
|
+
updatedAt
|
|
298
|
+
publishedAt
|
|
299
|
+
handle
|
|
300
|
+
status
|
|
301
|
+
${options.add_images === false ? '' : 'images(first: 20) { edges { node { id url } } }'}
|
|
302
|
+
${options.add_tags === false ? '' : 'tags'}
|
|
303
|
+
${options.add_options === false ? '' : 'options { name position optionValues { name } }'}
|
|
304
|
+
${options.add_variants === false ? '' : `variants(first: 150) {
|
|
305
|
+
edges {
|
|
306
|
+
node {
|
|
307
|
+
id
|
|
308
|
+
price
|
|
309
|
+
sku
|
|
310
|
+
availableForSale
|
|
311
|
+
inventoryQuantity
|
|
312
|
+
inventoryPolicy
|
|
313
|
+
taxable
|
|
314
|
+
compareAtPrice
|
|
315
|
+
${options.add_images === false ? '' : 'image { id url }'}
|
|
316
|
+
${options.add_options === false ? '' : 'selectedOptions { name value }'}
|
|
317
|
+
inventoryItem {
|
|
318
|
+
id
|
|
319
|
+
${options.add_weight === false ? '' : 'measurement { weight { unit value } }'}
|
|
320
|
+
tracked
|
|
321
|
+
unitCost {
|
|
322
|
+
amount
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}` }
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
} }`;
|
|
331
|
+
return productsQuery;
|
|
332
|
+
};
|
|
333
|
+
}
|