@porulle/adapter-shopify 0.70.2 → 0.72.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/dist/index.d.ts CHANGED
@@ -18,7 +18,7 @@ export interface ShopifyConnectorOptions {
18
18
  export declare const INVENTORY_QUERY = "query PorulleInventoryPage($after: String) {\n productVariants(first: 250, after: $after, sortKey: ID) { pageInfo { hasNextPage endCursor } nodes { legacyResourceId inventoryQuantity } }\n}";
19
19
  export declare const VARIANT_INVENTORY_QUERY = "query PorulleVariantInventory($ids: [ID!]!) {\n nodes(ids: $ids) { ... on ProductVariant { legacyResourceId inventoryQuantity } }\n}";
20
20
  export declare const STORE_PROFILE_QUERY = "query PorulleStoreProfile {\n shop { name currencyCode myshopifyDomain primaryDomain { host } }\n}";
21
- export declare const ORDER_CREATE_MUTATION = "mutation PorulleOrderCreate($order: OrderCreateOrderInput!, $options: OrderCreateOptionsInput) {\n orderCreate(order: $order, options: $options) { order { legacyResourceId } userErrors { field message } }\n}";
21
+ export declare const ORDER_CREATE_MUTATION = "mutation PorulleOrderCreate($order: OrderCreateOrderInput!, $options: OrderCreateOptionsInput) {\n orderCreate(order: $order, options: $options) { order { legacyResourceId } userErrors { code field message } }\n}";
22
22
  /**
23
23
  * Restocks at the store and refunds nothing there, and tells the customer nothing: the marketplace
24
24
  * took the payment, so it refunds and it writes to the shopper.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createHmac, timingSafeEqual } from "node:crypto";
2
- import { CHANNEL_CANCEL_REFUSED, defineChannelConnector, Err, Ok } from "@porulle/core";
2
+ import { CHANNEL_CANCEL_REFUSED, CHANNEL_OUT_OF_STOCK, defineChannelConnector, Err, Ok } from "@porulle/core";
3
3
  import { z } from "zod";
4
4
  import { readCatalogItems, readCatalogPage } from "./catalog.js";
5
5
  import { shopifyGid, shopifyGraphql } from "./graphql.js";
@@ -17,7 +17,7 @@ export const STORE_PROFILE_QUERY = `query PorulleStoreProfile {
17
17
  shop { name currencyCode myshopifyDomain primaryDomain { host } }
18
18
  }`;
19
19
  export const ORDER_CREATE_MUTATION = `mutation PorulleOrderCreate($order: OrderCreateOrderInput!, $options: OrderCreateOptionsInput) {
20
- orderCreate(order: $order, options: $options) { order { legacyResourceId } userErrors { field message } }
20
+ orderCreate(order: $order, options: $options) { order { legacyResourceId } userErrors { code field message } }
21
21
  }`;
22
22
  /**
23
23
  * Restocks at the store and refunds nothing there, and tells the customer nothing: the marketplace
@@ -43,7 +43,7 @@ const storeProfileSchema = z.object({
43
43
  const orderCreateSchema = z.object({
44
44
  orderCreate: z.object({
45
45
  order: z.object({ legacyResourceId: z.string() }).nullable(),
46
- userErrors: z.array(z.object({ field: z.array(z.string()).nullable(), message: z.string() })),
46
+ userErrors: z.array(z.object({ code: z.string().nullish(), field: z.array(z.string()).nullable(), message: z.string() })),
47
47
  }),
48
48
  });
49
49
  const orderCancelSchema = z.object({
@@ -246,6 +246,8 @@ export function shopifyConnector(options) {
246
246
  })),
247
247
  // The delivery the shopper paid this seller, so the order total matches the payment below.
248
248
  ...(slice.shipping ? { shippingLines: [{ title: slice.shipping.title, priceSet: money(slice.shipping.amount, slice.currency) }] } : {}),
249
+ // The shopper's discount as a fixed amount off the items, so the store's total is what was paid.
250
+ ...(slice.discount ? { discountCode: { itemFixedDiscountCode: { code: slice.discount.code, amountSet: money(slice.discount.amount, slice.currency) } } } : {}),
249
251
  transactions: [{ kind: "SALE", status: "SUCCESS", gateway: SOURCE_NAME, amountSet: money(slice.grandTotal, slice.currency) }],
250
252
  },
251
253
  options: { inventoryBehaviour: "DECREMENT_OBEYING_POLICY", sendReceipt: false, sendFulfillmentReceipt: false },
@@ -253,6 +255,9 @@ export function shopifyConnector(options) {
253
255
  if (!created.ok)
254
256
  return created;
255
257
  const { order, userErrors } = created.value.orderCreate;
258
+ if (userErrors.some((error) => error.code === "INVENTORY_CLAIM_FAILED")) {
259
+ return Err({ code: CHANNEL_OUT_OF_STOCK, message: `The store does not have the stock: ${userErrors.map((error) => error.message).join("; ")}.`, retriable: false });
260
+ }
256
261
  if (userErrors.length > 0 || !order) {
257
262
  return Err({ code: "SHOPIFY_ORDER_REJECTED", message: `Shopify refused the order: ${userErrors.map((error) => error.message).join("; ") || "no order returned"}.`, retriable: false });
258
263
  }