@thorprovider/adapters 4.2.1 → 5.0.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/PROVIDER_IMPLEMENTATION_ANALYSIS.md +659 -0
- package/dist/index.d.mts +225 -387
- package/dist/index.d.ts +225 -387
- package/dist/index.js +613 -3062
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +609 -3052
- package/dist/index.mjs.map +1 -1
- package/docs/RETRY_SOLUTION_SUMMARY.md +26 -11
- package/docs/authentication.md +115 -62
- package/docs/capabilities-system.md +4 -2
- package/docs/category-customization.md +37 -29
- package/docs/fetch-reliability-solution.md +127 -278
- package/docs/getting-started.md +43 -29
- package/docs/profile-management.md +68 -38
- package/docs/services-overview.md +4 -2
- package/package.json +1 -1
- package/quick-reference.md +33 -0
- package/src/backend/factory.ts +1 -11
- package/src/factory/index.ts +74 -52
- package/src/index.ts +5 -15
- package/src/providers/index.ts +1 -16
- package/src/providers/medusa/admin.test.ts +404 -0
- package/src/providers/medusa/admin.ts +442 -0
- package/src/providers/medusa/auth.test.ts +137 -0
- package/src/providers/medusa/auth.ts +96 -1
- package/src/providers/medusa/index.ts +21 -1
- package/src/resilience/README.md +70 -48
- package/src/types/capabilities.types.ts +0 -250
- package/src/core/errors.js +0 -161
- package/src/core/fetch-utils.js +0 -240
- package/src/core/logger.js +0 -63
- package/src/metadata/channel-scope-validation.js +0 -136
- package/src/metadata/channel-scope.js +0 -174
- package/src/metadata/index.js +0 -31
- package/src/providers/bigcommerce/bigcommerce.ts +0 -6
- package/src/providers/bigcommerce/index.ts +0 -315
- package/src/providers/bigcommerce/transforms.ts +0 -227
- package/src/providers/magento/index.ts +0 -387
- package/src/providers/magento/magento.ts +0 -5
- package/src/providers/magento/queries.ts +0 -267
- package/src/providers/magento/transforms.ts +0 -249
- package/src/providers/medusa/auth.js +0 -601
- package/src/providers/medusa/index.js +0 -2485
- package/src/providers/medusa/payment.js +0 -265
- package/src/providers/medusa/transforms.js +0 -505
- package/src/providers/shopify/auth.ts +0 -402
- package/src/providers/shopify/index.ts +0 -444
- package/src/providers/shopify/mutations.ts +0 -247
- package/src/providers/shopify/queries.ts +0 -324
- package/src/providers/shopify/shopify.ts +0 -7
- package/src/providers/shopify/transforms.ts +0 -275
- package/src/providers/spree/index.ts +0 -344
- package/src/providers/spree/spree.ts +0 -5
- package/src/providers/spree/transforms.ts +0 -254
- package/src/providers/woocommerce/index.ts +0 -310
- package/src/providers/woocommerce/transforms.ts +0 -254
- package/src/providers/woocommerce/woocommerce.ts +0 -5
- package/src/types/capabilities.types.js +0 -141
- package/src/types/provider.js +0 -9
- package/src/utils/payment-utils.js +0 -152
|
@@ -1,444 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @thorprovider/adapters — Shopify Provider
|
|
3
|
-
* Implements CommerceProvider for Shopify Storefront API (GraphQL)
|
|
4
|
-
*
|
|
5
|
-
* Uses @shopify/storefront-api-client for type-safe GraphQL operations.
|
|
6
|
-
* Authentication via public/private access tokens (legacy Storefront tokens).
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type {
|
|
10
|
-
Product,
|
|
11
|
-
GetProductsOptions,
|
|
12
|
-
Cart,
|
|
13
|
-
CartLineInput,
|
|
14
|
-
CartLineUpdate,
|
|
15
|
-
Collection,
|
|
16
|
-
CollectionProductsOptions,
|
|
17
|
-
GetCollectionsOptions,
|
|
18
|
-
ProductCategory,
|
|
19
|
-
GetCategoriesOptions,
|
|
20
|
-
Order,
|
|
21
|
-
GetOrdersOptions,
|
|
22
|
-
Customer,
|
|
23
|
-
Address,
|
|
24
|
-
PaymentMethod,
|
|
25
|
-
PaymentMethodsOptions,
|
|
26
|
-
ShippingMethod,
|
|
27
|
-
StockLocation,
|
|
28
|
-
InventoryLevel,
|
|
29
|
-
StockValidation,
|
|
30
|
-
FulfillmentOption,
|
|
31
|
-
StorefrontContext,
|
|
32
|
-
BackendCapabilities,
|
|
33
|
-
} from '@thorprovider/types';
|
|
34
|
-
import type { CommerceProvider, ProviderConfig } from '../../types/provider';
|
|
35
|
-
import { SHOPIFY_CAPABILITIES } from '../../types/capabilities.types';
|
|
36
|
-
import { createLogger } from '../../core/logger';
|
|
37
|
-
import { ProviderAPIError, ResourceNotFoundError } from '../../core/errors';
|
|
38
|
-
import { transformProduct, transformCart, transformCollection, transformCustomer, transformOrder } from './transforms';
|
|
39
|
-
import {
|
|
40
|
-
GET_PRODUCT_BY_HANDLE,
|
|
41
|
-
GET_PRODUCTS,
|
|
42
|
-
GET_PRODUCT_RECOMMENDATIONS,
|
|
43
|
-
GET_COLLECTION_BY_HANDLE,
|
|
44
|
-
GET_COLLECTIONS,
|
|
45
|
-
GET_COLLECTION_PRODUCTS,
|
|
46
|
-
GET_CART,
|
|
47
|
-
GET_CUSTOMER,
|
|
48
|
-
} from './queries';
|
|
49
|
-
import {
|
|
50
|
-
CART_CREATE,
|
|
51
|
-
CART_LINES_ADD,
|
|
52
|
-
CART_LINES_UPDATE,
|
|
53
|
-
CART_LINES_REMOVE,
|
|
54
|
-
CART_DISCOUNT_CODES_UPDATE,
|
|
55
|
-
} from './mutations';
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Shopify provider configuration
|
|
59
|
-
*/
|
|
60
|
-
export interface ShopifyProviderConfig extends ProviderConfig {
|
|
61
|
-
/** Store domain (e.g., 'your-store.myshopify.com') */
|
|
62
|
-
storeDomain: string;
|
|
63
|
-
/** Public Storefront API access token */
|
|
64
|
-
publicAccessToken: string;
|
|
65
|
-
/** Private Storefront API access token (server-side only) */
|
|
66
|
-
privateAccessToken?: string;
|
|
67
|
-
/** API version (default: '2026-04') */
|
|
68
|
-
apiVersion?: string;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Shopify commerce provider
|
|
73
|
-
*
|
|
74
|
-
* Implements CommerceProvider for Shopify Storefront API.
|
|
75
|
-
* Uses raw fetch + GraphQL queries (no SDK dependency to stay L2-pure).
|
|
76
|
-
*/
|
|
77
|
-
export class ShopifyProvider implements CommerceProvider {
|
|
78
|
-
readonly name = 'shopify';
|
|
79
|
-
readonly version = '1.0.0';
|
|
80
|
-
readonly capabilities: BackendCapabilities = SHOPIFY_CAPABILITIES;
|
|
81
|
-
|
|
82
|
-
private logger: ReturnType<typeof createLogger>;
|
|
83
|
-
private storeDomain: string;
|
|
84
|
-
private apiVersion: string;
|
|
85
|
-
private endpoint: string;
|
|
86
|
-
private headers: Record<string, string>;
|
|
87
|
-
|
|
88
|
-
constructor(config: ShopifyProviderConfig) {
|
|
89
|
-
this.logger = createLogger('ShopifyProvider', config.debug);
|
|
90
|
-
this.storeDomain = config.storeDomain.replace(/^https?:\/\//, '').replace(/\/$/, '');
|
|
91
|
-
this.apiVersion = config.apiVersion ?? '2026-04';
|
|
92
|
-
this.endpoint = `https://${this.storeDomain}/api/${this.apiVersion}/graphql.json`;
|
|
93
|
-
|
|
94
|
-
this.headers = {
|
|
95
|
-
'Content-Type': 'application/json',
|
|
96
|
-
...(config.privateAccessToken
|
|
97
|
-
? { 'Shopify-Storefront-Private-Token': config.privateAccessToken }
|
|
98
|
-
: { 'X-Shopify-Storefront-Access-Token': config.publicAccessToken }),
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
this.logger.info('Initializing Shopify Provider', {
|
|
102
|
-
storeDomain: this.storeDomain,
|
|
103
|
-
apiVersion: this.apiVersion,
|
|
104
|
-
authType: config.privateAccessToken ? 'private' : 'public',
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// ============================================
|
|
109
|
-
// GraphQL Client
|
|
110
|
-
// ============================================
|
|
111
|
-
|
|
112
|
-
private async query<T = any>(gql: string, variables?: Record<string, any>): Promise<T> {
|
|
113
|
-
const response = await fetch(this.endpoint, {
|
|
114
|
-
method: 'POST',
|
|
115
|
-
headers: this.headers,
|
|
116
|
-
body: JSON.stringify({ query: gql, variables }),
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
if (!response.ok) {
|
|
120
|
-
throw new ProviderAPIError(
|
|
121
|
-
`Shopify API error: ${response.status} ${response.statusText}`,
|
|
122
|
-
'SHOPIFY_API_ERROR',
|
|
123
|
-
response.status,
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const json = await response.json() as { data?: T; errors?: Array<{ message: string }> };
|
|
128
|
-
|
|
129
|
-
if (json.errors?.length) {
|
|
130
|
-
const message = json.errors.map((e) => e.message).join('; ');
|
|
131
|
-
throw new ProviderAPIError(`Shopify GraphQL error: ${message}`, 'SHOPIFY_GRAPHQL_ERROR');
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return json.data as T;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// ============================================
|
|
138
|
-
// Product Operations
|
|
139
|
-
// ============================================
|
|
140
|
-
|
|
141
|
-
async getProduct(handle: string): Promise<Product | undefined> {
|
|
142
|
-
const data = await this.query<{ product: any }>(GET_PRODUCT_BY_HANDLE, { handle });
|
|
143
|
-
return data.product ? transformProduct(data.product) : undefined;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
async getProducts(options?: GetProductsOptions): Promise<Product[]> {
|
|
147
|
-
const first = options?.first ?? 20;
|
|
148
|
-
const sortKeyMap: Record<string, string> = {
|
|
149
|
-
'title-asc': 'TITLE',
|
|
150
|
-
'title-desc': 'TITLE',
|
|
151
|
-
'price-asc': 'PRICE',
|
|
152
|
-
'price-desc': 'PRICE',
|
|
153
|
-
'best-selling': 'BEST_SELLING',
|
|
154
|
-
'created-desc': 'CREATED_AT',
|
|
155
|
-
'relevance': 'RELEVANCE',
|
|
156
|
-
};
|
|
157
|
-
const sortKey = options?.sortKey ? (sortKeyMap[options.sortKey] ?? 'RELEVANCE') : 'RELEVANCE';
|
|
158
|
-
const reverse = options?.sortKey?.endsWith('-desc') ?? false;
|
|
159
|
-
|
|
160
|
-
const data = await this.query<{ products: { edges: Array<{ node: any }> } }>(GET_PRODUCTS, {
|
|
161
|
-
first,
|
|
162
|
-
query: options?.query,
|
|
163
|
-
sortKey,
|
|
164
|
-
reverse,
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
return data.products.edges.map((edge) => transformProduct(edge.node));
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
async getProductRecommendations(productId: string): Promise<Product[]> {
|
|
171
|
-
const data = await this.query<{ productRecommendations: any[] }>(GET_PRODUCT_RECOMMENDATIONS, {
|
|
172
|
-
productId,
|
|
173
|
-
});
|
|
174
|
-
return (data.productRecommendations ?? []).map(transformProduct);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// ============================================
|
|
178
|
-
// Collection Operations
|
|
179
|
-
// ============================================
|
|
180
|
-
|
|
181
|
-
async getCollection(handle: string): Promise<Collection | undefined> {
|
|
182
|
-
const data = await this.query<{ collection: any }>(GET_COLLECTION_BY_HANDLE, { handle });
|
|
183
|
-
return data.collection ? transformCollection(data.collection) : undefined;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
async getCollections(options?: GetCollectionsOptions): Promise<Collection[]> {
|
|
187
|
-
const data = await this.query<{ collections: { edges: Array<{ node: any }> } }>(GET_COLLECTIONS, {
|
|
188
|
-
first: options?.limit ?? 50,
|
|
189
|
-
});
|
|
190
|
-
return data.collections.edges.map((edge) => transformCollection(edge.node));
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
async getCollectionProducts(handle: string, options?: CollectionProductsOptions): Promise<Product[]> {
|
|
194
|
-
const data = await this.query<{ collection: { products: { edges: Array<{ node: any }> } } }>(
|
|
195
|
-
GET_COLLECTION_PRODUCTS,
|
|
196
|
-
{
|
|
197
|
-
handle,
|
|
198
|
-
first: options?.first ?? 20,
|
|
199
|
-
sortKey: options?.sortKey === 'price-asc' || options?.sortKey === 'price-desc' ? 'PRICE' : 'BEST_SELLING',
|
|
200
|
-
reverse: options?.sortKey?.endsWith('-desc') ?? false,
|
|
201
|
-
},
|
|
202
|
-
);
|
|
203
|
-
return (data.collection?.products?.edges ?? []).map((edge) => transformProduct(edge.node));
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// ============================================
|
|
207
|
-
// Category Operations (Shopify does not have native categories)
|
|
208
|
-
// ============================================
|
|
209
|
-
|
|
210
|
-
async getCategory(): Promise<ProductCategory | undefined> {
|
|
211
|
-
this.logger.warn('Shopify does not support native categories. Use collections instead.');
|
|
212
|
-
return undefined;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
async getCategories(): Promise<ProductCategory[]> {
|
|
216
|
-
return [];
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
async getCategoryProducts(): Promise<Product[]> {
|
|
220
|
-
return [];
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// ============================================
|
|
224
|
-
// Cart Operations
|
|
225
|
-
// ============================================
|
|
226
|
-
|
|
227
|
-
async createCart(): Promise<Cart> {
|
|
228
|
-
const data = await this.query<{ cartCreate: { cart: any; userErrors: any[] } }>(CART_CREATE, {
|
|
229
|
-
input: {},
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
if (data.cartCreate.userErrors?.length) {
|
|
233
|
-
throw new ProviderAPIError(
|
|
234
|
-
`Cart creation failed: ${data.cartCreate.userErrors.map((e: any) => e.message).join('; ')}`,
|
|
235
|
-
'SHOPIFY_CART_ERROR',
|
|
236
|
-
);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
return transformCart(data.cartCreate.cart);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
async getCart(cartId: string): Promise<Cart | undefined> {
|
|
243
|
-
const data = await this.query<{ cart: any }>(GET_CART, { cartId });
|
|
244
|
-
return data.cart ? transformCart(data.cart) : undefined;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
async addToCart(cartId: string, lines: CartLineInput[]): Promise<Cart> {
|
|
248
|
-
const data = await this.query<{ cartLinesAdd: { cart: any; userErrors: any[] } }>(CART_LINES_ADD, {
|
|
249
|
-
cartId,
|
|
250
|
-
lines: lines.map((l) => ({ merchandiseId: l.merchandiseId, quantity: l.quantity })),
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
if (data.cartLinesAdd.userErrors?.length) {
|
|
254
|
-
throw new ProviderAPIError(
|
|
255
|
-
`Add to cart failed: ${data.cartLinesAdd.userErrors.map((e: any) => e.message).join('; ')}`,
|
|
256
|
-
'SHOPIFY_CART_ERROR',
|
|
257
|
-
);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
return transformCart(data.cartLinesAdd.cart);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
async removeFromCart(cartId: string, lineIds: string[]): Promise<Cart> {
|
|
264
|
-
const data = await this.query<{ cartLinesRemove: { cart: any; userErrors: any[] } }>(CART_LINES_REMOVE, {
|
|
265
|
-
cartId,
|
|
266
|
-
lineIds,
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
if (data.cartLinesRemove.userErrors?.length) {
|
|
270
|
-
throw new ProviderAPIError(
|
|
271
|
-
`Remove from cart failed: ${data.cartLinesRemove.userErrors.map((e: any) => e.message).join('; ')}`,
|
|
272
|
-
'SHOPIFY_CART_ERROR',
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
return transformCart(data.cartLinesRemove.cart);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
async updateCart(cartId: string, lines: CartLineUpdate[]): Promise<Cart> {
|
|
280
|
-
const data = await this.query<{ cartLinesUpdate: { cart: any; userErrors: any[] } }>(CART_LINES_UPDATE, {
|
|
281
|
-
cartId,
|
|
282
|
-
lines: lines.map((l) => ({ id: l.id, quantity: l.quantity })),
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
if (data.cartLinesUpdate.userErrors?.length) {
|
|
286
|
-
throw new ProviderAPIError(
|
|
287
|
-
`Update cart failed: ${data.cartLinesUpdate.userErrors.map((e: any) => e.message).join('; ')}`,
|
|
288
|
-
'SHOPIFY_CART_ERROR',
|
|
289
|
-
);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
return transformCart(data.cartLinesUpdate.cart);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// ============================================
|
|
296
|
-
// Checkout Operations
|
|
297
|
-
// ============================================
|
|
298
|
-
|
|
299
|
-
async completeCheckout(_cartId: string): Promise<Order> {
|
|
300
|
-
// Shopify checkout is hosted — redirect to cart.checkoutUrl
|
|
301
|
-
// This method cannot programmatically complete checkout
|
|
302
|
-
throw new ProviderAPIError(
|
|
303
|
-
'Shopify uses hosted checkout. Redirect the buyer to cart.checkoutUrl instead of calling completeCheckout().',
|
|
304
|
-
'SHOPIFY_HOSTED_CHECKOUT',
|
|
305
|
-
);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
async getShippingMethods(_cartId: string): Promise<ShippingMethod[]> {
|
|
309
|
-
// Shopify handles shipping selection in hosted checkout
|
|
310
|
-
return [];
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
async getRegionCountries(): Promise<import('@thorprovider/types').Country[]> {
|
|
314
|
-
return [];
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
async addShippingMethod(_cartId: string, _methodId: string): Promise<Cart> {
|
|
318
|
-
throw new ProviderAPIError(
|
|
319
|
-
'Shopify handles shipping selection in hosted checkout.',
|
|
320
|
-
'SHOPIFY_HOSTED_CHECKOUT',
|
|
321
|
-
);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
async initiatePaymentSession(_cartId: string, _providerId: string): Promise<void> {
|
|
325
|
-
throw new ProviderAPIError(
|
|
326
|
-
'Shopify handles payment in hosted checkout.',
|
|
327
|
-
'SHOPIFY_HOSTED_CHECKOUT',
|
|
328
|
-
);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
async applyDiscountCode(cartId: string, code: string): Promise<Cart> {
|
|
332
|
-
const currentCart = await this.getCart(cartId);
|
|
333
|
-
const existingCodes: string[] = []; // Shopify replaces all codes
|
|
334
|
-
existingCodes.push(code);
|
|
335
|
-
|
|
336
|
-
const data = await this.query<{ cartDiscountCodesUpdate: { cart: any; userErrors: any[] } }>(
|
|
337
|
-
CART_DISCOUNT_CODES_UPDATE,
|
|
338
|
-
{ cartId, discountCodes: existingCodes },
|
|
339
|
-
);
|
|
340
|
-
|
|
341
|
-
if (data.cartDiscountCodesUpdate.userErrors?.length) {
|
|
342
|
-
throw new ProviderAPIError(
|
|
343
|
-
`Discount code failed: ${data.cartDiscountCodesUpdate.userErrors.map((e: any) => e.message).join('; ')}`,
|
|
344
|
-
'SHOPIFY_DISCOUNT_ERROR',
|
|
345
|
-
);
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
return transformCart(data.cartDiscountCodesUpdate.cart);
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
async removeDiscountCode(cartId: string, _code: string): Promise<Cart> {
|
|
352
|
-
const data = await this.query<{ cartDiscountCodesUpdate: { cart: any; userErrors: any[] } }>(
|
|
353
|
-
CART_DISCOUNT_CODES_UPDATE,
|
|
354
|
-
{ cartId, discountCodes: [] },
|
|
355
|
-
);
|
|
356
|
-
|
|
357
|
-
return transformCart(data.cartDiscountCodesUpdate.cart);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// ============================================
|
|
361
|
-
// Customer Operations
|
|
362
|
-
// ============================================
|
|
363
|
-
|
|
364
|
-
async getOrders(options: GetOrdersOptions): Promise<Order[]> {
|
|
365
|
-
this.logger.warn('Shopify orders require Customer Account API (planned upgrade path).');
|
|
366
|
-
return [];
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
// ============================================
|
|
370
|
-
// Payment Operations
|
|
371
|
-
// ============================================
|
|
372
|
-
|
|
373
|
-
async getPaymentMethods(_options: PaymentMethodsOptions): Promise<PaymentMethod[]> {
|
|
374
|
-
// Shopify payment selection happens in hosted checkout
|
|
375
|
-
return [];
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// ============================================
|
|
379
|
-
// Inventory Operations (not available via Storefront API)
|
|
380
|
-
// ============================================
|
|
381
|
-
|
|
382
|
-
async getStockLocations(): Promise<StockLocation[]> {
|
|
383
|
-
return [];
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
async checkInventoryLevels(): Promise<InventoryLevel[]> {
|
|
387
|
-
return [];
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
async validateCartStock(): Promise<StockValidation> {
|
|
391
|
-
return { allAvailable: true, unavailableItems: [] };
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
async getFulfillmentOptions(): Promise<FulfillmentOption[]> {
|
|
395
|
-
return [];
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// ============================================
|
|
399
|
-
// Admin Operations (not available via Storefront API)
|
|
400
|
-
// ============================================
|
|
401
|
-
|
|
402
|
-
async cancelOrder(_orderId: string): Promise<Order> {
|
|
403
|
-
throw new ProviderAPIError(
|
|
404
|
-
'Order cancellation requires Shopify Admin API (not available in Storefront API).',
|
|
405
|
-
'SHOPIFY_ADMIN_REQUIRED',
|
|
406
|
-
);
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
async createFulfillment(_orderId: string): Promise<void> {
|
|
410
|
-
throw new ProviderAPIError(
|
|
411
|
-
'Fulfillment requires Shopify Admin API.',
|
|
412
|
-
'SHOPIFY_ADMIN_REQUIRED',
|
|
413
|
-
);
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
async createRefund(_orderId: string): Promise<void> {
|
|
417
|
-
throw new ProviderAPIError(
|
|
418
|
-
'Refunds require Shopify Admin API.',
|
|
419
|
-
'SHOPIFY_ADMIN_REQUIRED',
|
|
420
|
-
);
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
async getAdminOrders(): Promise<{ orders: Order[]; count: number }> {
|
|
424
|
-
return { orders: [], count: 0 };
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
// ============================================
|
|
428
|
-
// Storefront / Multi-Tenant
|
|
429
|
-
// ============================================
|
|
430
|
-
|
|
431
|
-
async getStorefrontContext(): Promise<StorefrontContext> {
|
|
432
|
-
return {
|
|
433
|
-
id: this.storeDomain,
|
|
434
|
-
name: this.storeDomain,
|
|
435
|
-
platformType: 'shopify',
|
|
436
|
-
requiresProductScoping: false,
|
|
437
|
-
currencyCode: 'USD',
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
isStorefrontRequired(): boolean {
|
|
442
|
-
return false;
|
|
443
|
-
}
|
|
444
|
-
}
|
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @thorprovider/adapters — Shopify Provider
|
|
3
|
-
* GraphQL mutation definitions for Storefront API
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { CART_FRAGMENT } from './queries';
|
|
7
|
-
|
|
8
|
-
export const CART_CREATE = `
|
|
9
|
-
mutation CartCreate($input: CartInput!) {
|
|
10
|
-
cartCreate(input: $input) {
|
|
11
|
-
cart {
|
|
12
|
-
...CartFields
|
|
13
|
-
}
|
|
14
|
-
userErrors {
|
|
15
|
-
field
|
|
16
|
-
message
|
|
17
|
-
code
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
${CART_FRAGMENT}
|
|
22
|
-
`;
|
|
23
|
-
|
|
24
|
-
export const CART_LINES_ADD = `
|
|
25
|
-
mutation CartLinesAdd($cartId: ID!, $lines: [CartLineInput!]!) {
|
|
26
|
-
cartLinesAdd(cartId: $cartId, lines: $lines) {
|
|
27
|
-
cart {
|
|
28
|
-
...CartFields
|
|
29
|
-
}
|
|
30
|
-
userErrors {
|
|
31
|
-
field
|
|
32
|
-
message
|
|
33
|
-
code
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
${CART_FRAGMENT}
|
|
38
|
-
`;
|
|
39
|
-
|
|
40
|
-
export const CART_LINES_UPDATE = `
|
|
41
|
-
mutation CartLinesUpdate($cartId: ID!, $lines: [CartLineUpdateInput!]!) {
|
|
42
|
-
cartLinesUpdate(cartId: $cartId, lines: $lines) {
|
|
43
|
-
cart {
|
|
44
|
-
...CartFields
|
|
45
|
-
}
|
|
46
|
-
userErrors {
|
|
47
|
-
field
|
|
48
|
-
message
|
|
49
|
-
code
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
${CART_FRAGMENT}
|
|
54
|
-
`;
|
|
55
|
-
|
|
56
|
-
export const CART_LINES_REMOVE = `
|
|
57
|
-
mutation CartLinesRemove($cartId: ID!, $lineIds: [ID!]!) {
|
|
58
|
-
cartLinesRemove(cartId: $cartId, lineIds: $lineIds) {
|
|
59
|
-
cart {
|
|
60
|
-
...CartFields
|
|
61
|
-
}
|
|
62
|
-
userErrors {
|
|
63
|
-
field
|
|
64
|
-
message
|
|
65
|
-
code
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
${CART_FRAGMENT}
|
|
70
|
-
`;
|
|
71
|
-
|
|
72
|
-
export const CART_DISCOUNT_CODES_UPDATE = `
|
|
73
|
-
mutation CartDiscountCodesUpdate($cartId: ID!, $discountCodes: [String!]!) {
|
|
74
|
-
cartDiscountCodesUpdate(cartId: $cartId, discountCodes: $discountCodes) {
|
|
75
|
-
cart {
|
|
76
|
-
...CartFields
|
|
77
|
-
}
|
|
78
|
-
userErrors {
|
|
79
|
-
field
|
|
80
|
-
message
|
|
81
|
-
code
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
${CART_FRAGMENT}
|
|
86
|
-
`;
|
|
87
|
-
|
|
88
|
-
export const CUSTOMER_ACCESS_TOKEN_CREATE = `
|
|
89
|
-
mutation CustomerAccessTokenCreate($input: CustomerAccessTokenCreateInput!) {
|
|
90
|
-
customerAccessTokenCreate(input: $input) {
|
|
91
|
-
customerAccessToken {
|
|
92
|
-
accessToken
|
|
93
|
-
expiresAt
|
|
94
|
-
}
|
|
95
|
-
customerUserErrors {
|
|
96
|
-
field
|
|
97
|
-
message
|
|
98
|
-
code
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
`;
|
|
103
|
-
|
|
104
|
-
export const CUSTOMER_ACCESS_TOKEN_DELETE = `
|
|
105
|
-
mutation CustomerAccessTokenDelete($customerAccessToken: String!) {
|
|
106
|
-
customerAccessTokenDelete(customerAccessToken: $customerAccessToken) {
|
|
107
|
-
deletedAccessToken
|
|
108
|
-
deletedCustomerAccessTokenId
|
|
109
|
-
userErrors {
|
|
110
|
-
field
|
|
111
|
-
message
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
`;
|
|
116
|
-
|
|
117
|
-
export const CUSTOMER_CREATE = `
|
|
118
|
-
mutation CustomerCreate($input: CustomerCreateInput!) {
|
|
119
|
-
customerCreate(input: $input) {
|
|
120
|
-
customer {
|
|
121
|
-
id
|
|
122
|
-
email
|
|
123
|
-
firstName
|
|
124
|
-
lastName
|
|
125
|
-
}
|
|
126
|
-
customerUserErrors {
|
|
127
|
-
field
|
|
128
|
-
message
|
|
129
|
-
code
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
`;
|
|
134
|
-
|
|
135
|
-
export const CUSTOMER_UPDATE = `
|
|
136
|
-
mutation CustomerUpdate($customerAccessToken: String!, $customer: CustomerUpdateInput!) {
|
|
137
|
-
customerUpdate(customerAccessToken: $customerAccessToken, customer: $customer) {
|
|
138
|
-
customer {
|
|
139
|
-
id
|
|
140
|
-
email
|
|
141
|
-
firstName
|
|
142
|
-
lastName
|
|
143
|
-
phone
|
|
144
|
-
}
|
|
145
|
-
customerAccessToken {
|
|
146
|
-
accessToken
|
|
147
|
-
expiresAt
|
|
148
|
-
}
|
|
149
|
-
customerUserErrors {
|
|
150
|
-
field
|
|
151
|
-
message
|
|
152
|
-
code
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
`;
|
|
157
|
-
|
|
158
|
-
export const CUSTOMER_RECOVER = `
|
|
159
|
-
mutation CustomerRecover($email: String!) {
|
|
160
|
-
customerRecover(email: $email) {
|
|
161
|
-
customerUserErrors {
|
|
162
|
-
field
|
|
163
|
-
message
|
|
164
|
-
code
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
`;
|
|
169
|
-
|
|
170
|
-
export const CUSTOMER_RESET = `
|
|
171
|
-
mutation CustomerReset($id: ID!, $input: CustomerResetInput!) {
|
|
172
|
-
customerReset(id: $id, input: $input) {
|
|
173
|
-
customerAccessToken {
|
|
174
|
-
accessToken
|
|
175
|
-
expiresAt
|
|
176
|
-
}
|
|
177
|
-
customerUserErrors {
|
|
178
|
-
field
|
|
179
|
-
message
|
|
180
|
-
code
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
`;
|
|
185
|
-
|
|
186
|
-
export const CUSTOMER_ADDRESS_CREATE = `
|
|
187
|
-
mutation CustomerAddressCreate($customerAccessToken: String!, $address: MailingAddressInput!) {
|
|
188
|
-
customerAddressCreate(customerAccessToken: $customerAccessToken, address: $address) {
|
|
189
|
-
customerAddress {
|
|
190
|
-
id
|
|
191
|
-
firstName
|
|
192
|
-
lastName
|
|
193
|
-
address1
|
|
194
|
-
address2
|
|
195
|
-
city
|
|
196
|
-
province
|
|
197
|
-
country
|
|
198
|
-
zip
|
|
199
|
-
phone
|
|
200
|
-
company
|
|
201
|
-
}
|
|
202
|
-
customerUserErrors {
|
|
203
|
-
field
|
|
204
|
-
message
|
|
205
|
-
code
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
`;
|
|
210
|
-
|
|
211
|
-
export const CUSTOMER_ADDRESS_UPDATE = `
|
|
212
|
-
mutation CustomerAddressUpdate($customerAccessToken: String!, $id: ID!, $address: MailingAddressInput!) {
|
|
213
|
-
customerAddressUpdate(customerAccessToken: $customerAccessToken, id: $id, address: $address) {
|
|
214
|
-
customerAddress {
|
|
215
|
-
id
|
|
216
|
-
firstName
|
|
217
|
-
lastName
|
|
218
|
-
address1
|
|
219
|
-
address2
|
|
220
|
-
city
|
|
221
|
-
province
|
|
222
|
-
country
|
|
223
|
-
zip
|
|
224
|
-
phone
|
|
225
|
-
company
|
|
226
|
-
}
|
|
227
|
-
customerUserErrors {
|
|
228
|
-
field
|
|
229
|
-
message
|
|
230
|
-
code
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
`;
|
|
235
|
-
|
|
236
|
-
export const CUSTOMER_ADDRESS_DELETE = `
|
|
237
|
-
mutation CustomerAddressDelete($customerAccessToken: String!, $id: ID!) {
|
|
238
|
-
customerAddressDelete(customerAccessToken: $customerAccessToken, id: $id) {
|
|
239
|
-
deletedCustomerAddressId
|
|
240
|
-
customerUserErrors {
|
|
241
|
-
field
|
|
242
|
-
message
|
|
243
|
-
code
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
`;
|