@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,73 @@
|
|
|
1
|
+
import { Logger } from '../Logger';
|
|
2
|
+
import { AxiosInstance } from 'axios';
|
|
3
|
+
import ErrorHelper from './base/ErrorHelper';
|
|
4
|
+
import InspiraShopifyError from './errors/InspiraShopifyError';
|
|
5
|
+
|
|
6
|
+
export class ShopifyBillingService {
|
|
7
|
+
|
|
8
|
+
constructor(private axiosInstance: AxiosInstance) { }
|
|
9
|
+
|
|
10
|
+
public requestBilling = async (billing: IRecurringBillingRequest): Promise<IRecurringBillingResponse> => {
|
|
11
|
+
return new Promise<IRecurringBillingResponse>(async (resolve, reject) => {
|
|
12
|
+
try {
|
|
13
|
+
const response = await this.axiosInstance.post('/recurring_application_charges.json', { recurring_application_charge: billing });
|
|
14
|
+
resolve(response.data.recurring_application_charge);
|
|
15
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
public cancelBilling = async (charge_id: number): Promise<void> => {
|
|
20
|
+
return new Promise<void>(async (resolve, reject) => {
|
|
21
|
+
try {
|
|
22
|
+
await this.axiosInstance.delete(`/recurring_application_charges/${charge_id}.json`);
|
|
23
|
+
resolve();
|
|
24
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
public getRecurringApplicationCharge = async (activationId: string): Promise<IRecurringBillingResponse> => {
|
|
29
|
+
return new Promise<IRecurringBillingResponse>(async (resolve, reject) => {
|
|
30
|
+
try {
|
|
31
|
+
const response = await this.axiosInstance.get(`/recurring_application_charges/${activationId}.json`);
|
|
32
|
+
resolve(response.data.recurring_application_charge);
|
|
33
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
public getActiveRecurringApplicationCharge = async (): Promise<IRecurringBillingResponse> => {
|
|
38
|
+
return new Promise<IRecurringBillingResponse>(async (resolve, reject) => {
|
|
39
|
+
try {
|
|
40
|
+
const response = await this.axiosInstance.get('/recurring_application_charges.json');
|
|
41
|
+
resolve(response.data.recurring_application_charges.find((r: IRecurringBillingResponse) => r.status === 'active'));
|
|
42
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
public getApplicationCharge = async (activationId: string): Promise<IBillingResponse> => {
|
|
47
|
+
return new Promise<IBillingResponse>(async (resolve, reject) => {
|
|
48
|
+
try {
|
|
49
|
+
const response = await this.axiosInstance.get(`/application_charges/${activationId}.json`);
|
|
50
|
+
resolve(response.data.application_charge);
|
|
51
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
public singlePayment = async (singlePayment: IShopifySinglePayment): Promise<IShopifySinglePaymentResponse> => {
|
|
56
|
+
return new Promise<IShopifySinglePaymentResponse>(async (resolve, reject) => {
|
|
57
|
+
try {
|
|
58
|
+
const response = await this.axiosInstance.post('/application_charges.json', { application_charge: singlePayment });
|
|
59
|
+
resolve(response.data.application_charge);
|
|
60
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
public addUsage = async (activationId: string, amount: string, description: string): Promise<IUsageCharge> => {
|
|
65
|
+
return new Promise<IUsageCharge>(async (resolve, reject) => {
|
|
66
|
+
try {
|
|
67
|
+
const response = await this.axiosInstance.post(`/recurring_application_charges/${activationId}/usage_charges.json`, { usage_charge: { description: description, price: parseFloat(amount) } });
|
|
68
|
+
resolve(response.data.usage_charge);
|
|
69
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { AxiosInstance } from 'axios';
|
|
2
|
+
import { print } from 'graphql';
|
|
3
|
+
import gql from 'graphql-tag';
|
|
4
|
+
import { Logger } from '../Logger';
|
|
5
|
+
import ErrorHelper from './base/ErrorHelper';
|
|
6
|
+
import InspiraShopifyError from './errors/InspiraShopifyError';
|
|
7
|
+
import { AbstractService } from './base/AbstractService';
|
|
8
|
+
|
|
9
|
+
export class ShopifyCartTrasnformationService extends AbstractService {
|
|
10
|
+
|
|
11
|
+
constructor(private axiosInstance: AxiosInstance) {
|
|
12
|
+
super();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates Cart Customization
|
|
17
|
+
*
|
|
18
|
+
* @param {string} functionId
|
|
19
|
+
* @param {string} metafieldVal
|
|
20
|
+
* @returns Promise
|
|
21
|
+
*/
|
|
22
|
+
public create = async (functionId: string, metafieldVal: string): Promise<{id: number;}> => {
|
|
23
|
+
return new Promise<{id: number;}>(async (resolve, reject) => {
|
|
24
|
+
try {
|
|
25
|
+
Logger.info(`Creating cart transformation: ${functionId} and metafield val ${metafieldVal}`);
|
|
26
|
+
const query = gql `mutation cartTransformCreate($input: String!) {
|
|
27
|
+
cartTransformCreate(functionId: $input) {
|
|
28
|
+
cartTransform {
|
|
29
|
+
id
|
|
30
|
+
}
|
|
31
|
+
userErrors {
|
|
32
|
+
field
|
|
33
|
+
message
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}`;
|
|
37
|
+
const response = await this.axiosInstance.post('/graphql.json', { query: print(query),
|
|
38
|
+
variables: { input: functionId }}, { query_cost: 803 });
|
|
39
|
+
|
|
40
|
+
if(response && response.data && response.data.data && response.data.data.cartTransformCreate && response.data.data.cartTransformCreate.cartTransform ){
|
|
41
|
+
const cartTransfromGraphQL = response.data.data.cartTransformCreate.cartTransform;
|
|
42
|
+
Logger.info(`Cart transform created with ${JSON.stringify(cartTransfromGraphQL)}`);
|
|
43
|
+
const customizationId = cartTransfromGraphQL.id;
|
|
44
|
+
Logger.info(`Cart Tansfrom created with id ${customizationId}`);
|
|
45
|
+
const metafieldQuery = gql `mutation MetafieldsSet($customizationId: ID!, $configurationValue: String!) {
|
|
46
|
+
metafieldsSet(metafields: [
|
|
47
|
+
{
|
|
48
|
+
ownerId: $customizationId
|
|
49
|
+
namespace: "$app:cart-transform"
|
|
50
|
+
key: "function-configuration"
|
|
51
|
+
value: $configurationValue
|
|
52
|
+
type: "json"
|
|
53
|
+
}
|
|
54
|
+
]) {
|
|
55
|
+
metafields {
|
|
56
|
+
id
|
|
57
|
+
}
|
|
58
|
+
userErrors {
|
|
59
|
+
message
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}`;
|
|
63
|
+
|
|
64
|
+
const metafieldResponse = await this.axiosInstance.post('/graphql.json', { query: print(metafieldQuery),
|
|
65
|
+
variables: { customizationId: customizationId, configurationValue: metafieldVal }}, { query_cost: 803 });
|
|
66
|
+
|
|
67
|
+
Logger.info(`Meta response ${JSON.stringify(metafieldResponse.data)}`);
|
|
68
|
+
resolve({ id: this.getIdFromGraphId(customizationId) });
|
|
69
|
+
} else {
|
|
70
|
+
Logger.error(`Create cart transform. Error is ${JSON.stringify(response.data.errors)}. All data is ${JSON.stringify(response.data)}` );
|
|
71
|
+
resolve(null);
|
|
72
|
+
}
|
|
73
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Updates in Cart Transform
|
|
79
|
+
*
|
|
80
|
+
* @param {number} customisationId
|
|
81
|
+
* @param {string} metafieldVal
|
|
82
|
+
* @returns Promise
|
|
83
|
+
*/
|
|
84
|
+
public update = async (customisationId: number, metafieldVal: string): Promise<{id: number;}> => {
|
|
85
|
+
return new Promise<{id: number;}>(async (resolve, reject) => {
|
|
86
|
+
try {
|
|
87
|
+
|
|
88
|
+
Logger.info(`Cart transform updated with ${customisationId}`);
|
|
89
|
+
const metafieldQuery = gql `mutation MetafieldsSet($customizationId: ID!, $configurationValue: String!) {
|
|
90
|
+
metafieldsSet(metafields: [
|
|
91
|
+
{
|
|
92
|
+
ownerId: $customizationId
|
|
93
|
+
namespace: "$app:cart-transform"
|
|
94
|
+
key: "function-configuration"
|
|
95
|
+
value: $configurationValue
|
|
96
|
+
type: "json"
|
|
97
|
+
}
|
|
98
|
+
]) {
|
|
99
|
+
metafields {
|
|
100
|
+
id
|
|
101
|
+
}
|
|
102
|
+
userErrors {
|
|
103
|
+
message
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}`;
|
|
107
|
+
|
|
108
|
+
const metafieldResponse = await this.axiosInstance.post('/graphql.json', { query: print(metafieldQuery),
|
|
109
|
+
variables: { customizationId: this.getGraphCartTransformIdFromId(customisationId), configurationValue: metafieldVal }}, { query_cost: 803 });
|
|
110
|
+
|
|
111
|
+
Logger.info(`Meta response ${JSON.stringify(metafieldResponse.data)}`);
|
|
112
|
+
resolve({ id: customisationId });
|
|
113
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* setMetafield in Cart Transform
|
|
119
|
+
*
|
|
120
|
+
* @param {number} customisationId
|
|
121
|
+
* @param {string} metafieldVal
|
|
122
|
+
* @param {string} key
|
|
123
|
+
* @returns Promise
|
|
124
|
+
*/
|
|
125
|
+
public setMetafield = async (customisationId: number, metafieldVal: string, key: string): Promise<{id: number;}> => {
|
|
126
|
+
return new Promise<{id: number;}>(async (resolve, reject) => {
|
|
127
|
+
try {
|
|
128
|
+
|
|
129
|
+
Logger.info(`Cart transform updated with ${customisationId}`);
|
|
130
|
+
const metafieldQuery = gql `mutation MetafieldsSet($customizationId: ID!, $configurationValue: String!) {
|
|
131
|
+
metafieldsSet(metafields: [
|
|
132
|
+
{
|
|
133
|
+
ownerId: $customizationId
|
|
134
|
+
namespace: "$app:cart-transform"
|
|
135
|
+
key: "${key}"
|
|
136
|
+
value: $configurationValue
|
|
137
|
+
type: "json"
|
|
138
|
+
}
|
|
139
|
+
]) {
|
|
140
|
+
metafields {
|
|
141
|
+
id
|
|
142
|
+
}
|
|
143
|
+
userErrors {
|
|
144
|
+
message
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}`;
|
|
148
|
+
|
|
149
|
+
const metafieldResponse = await this.axiosInstance.post('/graphql.json', { query: print(metafieldQuery),
|
|
150
|
+
variables: { customizationId: this.getGraphCartTransformIdFromId(customisationId), configurationValue: metafieldVal }}, { query_cost: 803 });
|
|
151
|
+
|
|
152
|
+
Logger.info(`Meta response ${JSON.stringify(metafieldResponse.data)}`);
|
|
153
|
+
resolve({ id: customisationId });
|
|
154
|
+
} catch (error) { Logger.error(error, ErrorHelper.getErrorFromResponse(error)); reject(new InspiraShopifyError(error)); }
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
public getCartTransforms = async (namespace: string, key: string): Promise<ICartTransforms> => {
|
|
159
|
+
const query = gql `query cartTransforms {
|
|
160
|
+
cartTransforms(first: 1) {
|
|
161
|
+
edges {
|
|
162
|
+
node {
|
|
163
|
+
functionId
|
|
164
|
+
id
|
|
165
|
+
metafield(namespace: "${namespace}", key: "${key}") {
|
|
166
|
+
value
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}`;
|
|
172
|
+
|
|
173
|
+
const customisationResponse = await this.axiosInstance.post('/graphql.json', { query: print(query) }, { query_cost: 10 });
|
|
174
|
+
if(customisationResponse && customisationResponse.data && customisationResponse.data.data && customisationResponse.data.data.cartTransforms && customisationResponse.data.data.cartTransforms.edges[0]) {
|
|
175
|
+
Logger.info('getCartTransforms got', customisationResponse.data.data.cartTransforms.edges[0].node);
|
|
176
|
+
const cartTransform: ICartTransforms = customisationResponse.data.data.cartTransforms.edges[0].node;
|
|
177
|
+
cartTransform.id = this.getIdFromGraphId(cartTransform.id as any);
|
|
178
|
+
return cartTransform;
|
|
179
|
+
} else if (customisationResponse && customisationResponse.data && customisationResponse.data.errors ) {
|
|
180
|
+
Logger.error(`getCartTransforms ${JSON.stringify(customisationResponse.data.errors)}`);
|
|
181
|
+
return null;
|
|
182
|
+
} else {
|
|
183
|
+
Logger.error(`getCartTransforms with no error ${JSON.stringify(customisationResponse.data)}`);
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
public deleteCartTransforms = async (customisationId: number): Promise<void> => {
|
|
190
|
+
const query = gql `mutation cartTransformDelete($id: ID!) {
|
|
191
|
+
cartTransformDelete(id: $id) {
|
|
192
|
+
deletedId
|
|
193
|
+
userErrors {
|
|
194
|
+
field
|
|
195
|
+
message
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}`;
|
|
199
|
+
|
|
200
|
+
const customisationResponse = await this.axiosInstance.post('/graphql.json', { query: print(query), variables: { id: this.getGraphCartTransformIdFromId(customisationId) } }, { query_cost: 10 });
|
|
201
|
+
if (customisationResponse && customisationResponse.data && customisationResponse.data.errors ) {
|
|
202
|
+
Logger.error(`deleteCartTransforms ${JSON.stringify(customisationResponse.data.errors)}`);
|
|
203
|
+
} else {
|
|
204
|
+
Logger.error(`deleteCartTransforms with no error ${JSON.stringify(customisationResponse.data)}`);
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
}
|