hookwright 1.13.0 → 2.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.
Files changed (2) hide show
  1. package/dist/cli.js +151 -132
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -24,7 +24,7 @@ var init_package = __esm({
24
24
  "package.json"() {
25
25
  package_default = {
26
26
  name: "hookwright",
27
- version: "1.13.0",
27
+ version: "2.0.1",
28
28
  description: "Build real, signed e-commerce webhooks from a live Shopify catalogue \u2014 interactive terminal UI, no backend",
29
29
  keywords: [
30
30
  "webhook",
@@ -1807,26 +1807,40 @@ function selectionFor4(eventName) {
1807
1807
  return eventDef3(eventName).selection;
1808
1808
  }
1809
1809
  var COMMON_FIELDS3 = [
1810
- { source: "request_type", target: "\xABgate\xBB + requestType", required: true, note: "return or exchange" },
1811
- { source: "status", target: "\xABgate\xBB + status", required: true, note: "requested, approved, received, inspected or rejected" },
1812
- { source: "customer.phone", target: "phone", required: true, note: "missing phone is rejected on every event" },
1813
- { source: "customer.address.country_code", target: "phone region" },
1814
- { source: "request_number", target: "requestNumber" },
1815
- { source: "order.name", target: "order.name" },
1816
- { source: "line_items[].original_product.title", target: "product.name", required: true, note: "the first PAID line wins; freebies rank last" },
1817
- { source: "line_items[].original_product.image.src", target: "product.image" },
1818
- { source: "line_items[].original_product.price", target: "product.price", note: "a zero price marks the line a freebie" },
1819
- { source: "line_items[].reason", target: "reason" },
1820
- { source: "line_items[].presentment_price.actual_amount", target: "pricing.totalPrice" },
1821
- { source: "line_items[].return_fee.price_set\u2026amount", target: "pricing.returnFee" },
1822
- { source: "line_items[].refund.status", target: "refund.status" },
1823
- { source: "line_items[].refund.meta.discount_code", target: "refund.discountCode", note: "only present once store credit is issued" },
1824
- { source: "line_items[].shipping[0].awb", target: "shipping.awb" },
1825
- { source: "approved/received/inspected/rejected.created_at", target: "timeline.*" }
1810
+ { source: "request.request_type", target: "\xABgate\xBB + requestType", required: true, note: "return or exchange" },
1811
+ { source: "request.status", target: "\xABgate\xBB + status", required: true, note: "requested, approved, received, inspected or rejected" },
1812
+ { source: "request.customer.phone", target: "phone", required: true, note: "missing phone is rejected on every event" },
1813
+ { source: "request.customer.address.country_code", target: "phone region" },
1814
+ { source: "request.customer.name", target: "customer.name" },
1815
+ { source: "request.customer.email", target: "customer.email", note: "null on some real requests" },
1816
+ { source: "request.request_number", target: "requestNumber" },
1817
+ { source: "request.id", target: "requestId" },
1818
+ { source: "request.manual_request", target: "manualRequest" },
1819
+ { source: "request.smart_exchange", target: "smartExchange" },
1820
+ { source: "request.order.name", target: "order.name" },
1821
+ { source: "request.order.id", target: "order.id" },
1822
+ { source: "request.line_items[].original_product.title", target: "product.name + product.details", required: true, note: "the first PAID line wins; freebies rank last" },
1823
+ { source: "request.line_items[].original_product.image.src", target: "product.image" },
1824
+ { source: "request.line_items[].original_product.price", target: "product.price", note: "a zero price marks the line a freebie" },
1825
+ { source: "request.line_items[].original_product.sku", target: "product.sku" },
1826
+ { source: "request.line_items[].reason", target: "reason" },
1827
+ { source: "request.line_items[].quantity", target: "product.quantity" },
1828
+ { source: "request.line_items[].presentment_price.actual_amount", target: "pricing.totalPrice" },
1829
+ { source: "request.line_items[].presentment_price.currency", target: "pricing.currency" },
1830
+ { source: "request.line_items[].return_fee.price_set.presentment_money.amount", target: "pricing.returnFee" },
1831
+ { source: "request.line_items[].refund.status", target: "refund.status" },
1832
+ { source: "request.line_items[].refund.requested_mode", target: "refund.requestedMode" },
1833
+ { source: "request.line_items[].refund.meta.discount_code", target: "refund.discountCode", note: "only present once store credit is issued" },
1834
+ { source: "request.line_items[].shipping[0].awb", target: "shipping.awb", note: "absent until a label is raised" },
1835
+ { source: "request.line_items[].shipping[0].tracking_available", target: "shipping.trackingAvailable" },
1836
+ { source: "request.approved.created_at / request.received.created_at / request.inspected.created_at / request.rejected.created_at", target: "timeline.*", note: "whichever steps have happened" },
1837
+ { source: "request.created_at", target: "createdAt" }
1826
1838
  ];
1827
1839
  var EXCHANGE_FIELDS = [
1828
- { source: "line_items[].exchange_product.title", target: "exchangeProduct.name", note: "exchanges only \u2014 returns never carry it" },
1829
- { source: "line_items[].exchange_product.price", target: "exchangeProduct.price + pricing.priceDifference", note: "difference is signed: positive means the shopper owes more" }
1840
+ { source: "request.line_items[].exchange_product.title", target: "exchangeProduct.name", note: "exchanges only \u2014 returns never carry it" },
1841
+ { source: "request.line_items[].exchange_product.price", target: "exchangeProduct.price + pricing.priceDifference", note: "difference is signed: positive means the shopper owes more" },
1842
+ { source: "request.line_items[].exchange_product.image.src", target: "exchangeProduct.image" },
1843
+ { source: "request.line_items[].exchange_product.sku", target: "exchangeProduct.sku" }
1830
1844
  ];
1831
1845
  var fieldMap6 = COMMON_FIELDS3;
1832
1846
  function fieldMapFor2(eventName) {
@@ -1864,124 +1878,129 @@ function buildPayload6(ctx) {
1864
1878
  const currency = ctx.currency || config.defaults.currency;
1865
1879
  const cust = config.customer;
1866
1880
  const at = now.toISOString();
1867
- const first = items?.[0];
1868
- const second = items?.[1] ?? first;
1869
- const originalPrice = money2(first?.variant?.price ?? 0);
1870
- const exchangePrice = money2(second?.variant?.price ?? 0);
1881
+ const selected = (items ?? []).filter(Boolean);
1882
+ const replacements = ctx.exchangeItems ?? (ctx.exchange ? [ctx.exchange] : []);
1883
+ const replacementFor = (sel, idx) => replacements[idx] ?? ctx.exchange ?? sel;
1871
1884
  const reachedIndex = STATUSES.indexOf(def.status);
1872
1885
  const reached = (name) => STATUSES.indexOf(name) <= reachedIndex && def.status !== "requested";
1873
- const lineItem = {
1874
- id: Number(first?.variant?.id ?? first?.product?.id ?? 0),
1875
- refund: {
1876
- requested_mode: "store_credit",
1877
- actual_mode: def.status === "rejected" ? "store_credit" : null,
1878
- meta: def.status === "rejected" && ctx.couponCode ? { discount_code: ctx.couponCode } : null,
1879
- status: def.status === "rejected" ? "refunded" : "pending",
1880
- refunded_amount: {
1881
- shop_money: { ...def.status === "rejected" ? { amount: originalPrice } : {}, currency_code: currency },
1882
- presentment_money: { ...def.status === "rejected" ? { amount: originalPrice } : {}, currency_code: currency }
1886
+ const makeLineItem = (sel, idx) => {
1887
+ const repl = replacementFor(sel, idx);
1888
+ const originalPrice = money2(sel?.variant?.price ?? 0);
1889
+ const exchangePrice = money2(repl?.variant?.price ?? 0);
1890
+ return {
1891
+ id: Number(sel?.variant?.id ?? sel?.product?.id ?? 0),
1892
+ refund: {
1893
+ requested_mode: "store_credit",
1894
+ actual_mode: def.status === "rejected" ? "store_credit" : null,
1895
+ meta: def.status === "rejected" && ctx.couponCode ? { discount_code: ctx.couponCode } : null,
1896
+ status: def.status === "rejected" ? "refunded" : "pending",
1897
+ refunded_amount: {
1898
+ shop_money: { ...def.status === "rejected" ? { amount: originalPrice } : {}, currency_code: currency },
1899
+ presentment_money: { ...def.status === "rejected" ? { amount: originalPrice } : {}, currency_code: currency }
1900
+ },
1901
+ refunded_at: def.status === "rejected" ? at : null,
1902
+ comment: null
1883
1903
  },
1884
- refunded_at: def.status === "rejected" ? at : null,
1885
- comment: null
1886
- },
1887
- return_fee: {
1888
- price_set: {
1889
- shop_money: { amount: ctx.returnFee ?? 0, currency_code: currency },
1890
- presentment_money: { amount: ctx.returnFee ?? 0, currency_code: currency }
1904
+ return_fee: {
1905
+ price_set: {
1906
+ shop_money: { amount: ctx.returnFee ?? 0, currency_code: currency },
1907
+ presentment_money: { amount: ctx.returnFee ?? 0, currency_code: currency }
1908
+ },
1909
+ rule: "order"
1891
1910
  },
1892
- rule: "order"
1893
- },
1894
- exchange_fee: {
1895
- price_set: {
1896
- shop_money: { amount: null, currency_code: null },
1897
- presentment_money: { amount: null, currency_code: null }
1898
- }
1899
- },
1900
- exchange: { order: null },
1901
- original_product: {
1902
- title: first?.product?.title,
1903
- variant_title: first?.variant?.title ?? null,
1904
- product_id: Number(first?.product?.id ?? 0),
1905
- variant_id: Number(first?.variant?.id ?? 0),
1906
- image: { src: imageForVariant(first?.product, first?.variant) },
1907
- price: originalPrice,
1908
- sku: first?.variant?.sku || "",
1909
- variant_deleted: false,
1910
- product_deleted: false
1911
- },
1912
- ...def.requestType === "exchange" ? {
1913
- exchange_product: {
1914
- product_id: Number(second?.product?.id ?? 0),
1915
- title: second?.product?.title,
1916
- variant_title: second?.variant?.title ?? "Default Title",
1917
- variant_id: Number(second?.variant?.id ?? 0),
1918
- image: { src: imageForVariant(second?.product, second?.variant) },
1919
- price: exchangePrice,
1920
- sku: second?.variant?.sku || "",
1911
+ exchange_fee: {
1912
+ price_set: {
1913
+ shop_money: { amount: null, currency_code: null },
1914
+ presentment_money: { amount: null, currency_code: null }
1915
+ }
1916
+ },
1917
+ exchange: { order: null },
1918
+ original_product: {
1919
+ title: sel?.product?.title,
1920
+ variant_title: sel?.variant?.title ?? null,
1921
+ product_id: Number(sel?.product?.id ?? 0),
1922
+ variant_id: Number(sel?.variant?.id ?? 0),
1923
+ image: { src: imageForVariant(sel?.product, sel?.variant) },
1924
+ price: originalPrice,
1925
+ sku: sel?.variant?.sku || "",
1921
1926
  variant_deleted: false,
1922
1927
  product_deleted: false
1923
- }
1924
- } : {},
1925
- shipping: [
1926
- def.status === "requested" ? { tracking_available: false, labels: [] } : {
1927
- shipping_company: "bluedartV2",
1928
- tracking_available: true,
1929
- awb: String(now.getTime()).slice(-11),
1930
- tracking_updated_at: null,
1931
- labels: [],
1932
- shipment_status: "Requested",
1933
- tracking_url: `https://www.bluedart.com/trackdartresultthirdparty?trackFor=0&trackNo=${String(now.getTime()).slice(-11)}`
1934
- }
1935
- ],
1936
- quantity: first?.quantity ?? 1,
1937
- reason: ctx.reason ?? "Size of Fit Issues",
1938
- shop_price: {
1939
- actual_amount: originalPrice,
1940
- total_tax: 0,
1941
- return_quantity: first?.quantity ?? 1,
1942
- total_discount: 0,
1943
- shipping_amount: 0,
1944
- taxes_included: true,
1945
- currency,
1946
- do_not_carry_forward_discount: true
1947
- },
1948
- presentment_price: {
1949
- actual_amount: originalPrice,
1950
- total_tax: 0,
1951
- return_quantity: first?.quantity ?? 1,
1952
- total_discount: 0,
1953
- shipping_amount: 0,
1954
- taxes_included: true,
1955
- currency,
1956
- do_not_carry_forward_discount: true
1957
- },
1958
- shopify_order_fulfillment_location: null,
1959
- return_location: def.status === "requested" ? null : {
1960
- id: "rp-location-1",
1961
- fullName: config.shopify.shop?.name ?? config.shopify.domain,
1962
- mobileNumber: nationalNumber(phone, cust.countryCode),
1963
- pinCode: cust.zip,
1964
- streetAddress1: cust.address1,
1965
- streetAddress2: cust.address2 ?? "",
1966
- landmark: "",
1967
- city: cust.city,
1968
- state: cust.province,
1969
- stateCode: cust.provinceCode,
1970
- countryCode: cust.countryCode,
1971
- country: cust.country,
1972
- store: config.shopify.domain,
1973
- facilityCode: "",
1974
- isDefault: true,
1975
- latitude: "",
1976
- longitude: "",
1977
- inStoreReturnExchange: false,
1978
- external: false,
1979
- createdAt: at,
1980
- updatedAt: at
1981
- },
1982
- notes: null,
1983
- tags: []
1928
+ },
1929
+ ...def.requestType === "exchange" ? {
1930
+ exchange_product: {
1931
+ product_id: Number(repl?.product?.id ?? 0),
1932
+ title: repl?.product?.title,
1933
+ variant_title: repl?.variant?.title ?? "Default Title",
1934
+ variant_id: Number(repl?.variant?.id ?? 0),
1935
+ image: { src: imageForVariant(repl?.product, repl?.variant) },
1936
+ price: exchangePrice,
1937
+ sku: repl?.variant?.sku || "",
1938
+ variant_deleted: false,
1939
+ product_deleted: false
1940
+ }
1941
+ } : {},
1942
+ shipping: [
1943
+ def.status === "requested" ? { tracking_available: false, labels: [] } : {
1944
+ shipping_company: "bluedartV2",
1945
+ tracking_available: true,
1946
+ awb: String(now.getTime()).slice(-11),
1947
+ tracking_updated_at: null,
1948
+ labels: [],
1949
+ shipment_status: "Requested",
1950
+ tracking_url: `https://www.bluedart.com/trackdartresultthirdparty?trackFor=0&trackNo=${String(now.getTime()).slice(-11)}`
1951
+ }
1952
+ ],
1953
+ quantity: sel?.quantity ?? 1,
1954
+ reason: ctx.reason ?? "Size of Fit Issues",
1955
+ shop_price: {
1956
+ actual_amount: originalPrice,
1957
+ total_tax: 0,
1958
+ return_quantity: sel?.quantity ?? 1,
1959
+ total_discount: 0,
1960
+ shipping_amount: 0,
1961
+ taxes_included: true,
1962
+ currency,
1963
+ do_not_carry_forward_discount: true
1964
+ },
1965
+ presentment_price: {
1966
+ actual_amount: originalPrice,
1967
+ total_tax: 0,
1968
+ return_quantity: sel?.quantity ?? 1,
1969
+ total_discount: 0,
1970
+ shipping_amount: 0,
1971
+ taxes_included: true,
1972
+ currency,
1973
+ do_not_carry_forward_discount: true
1974
+ },
1975
+ shopify_order_fulfillment_location: null,
1976
+ return_location: def.status === "requested" ? null : {
1977
+ id: "rp-location-1",
1978
+ fullName: config.shopify.shop?.name ?? config.shopify.domain,
1979
+ mobileNumber: nationalNumber(phone, cust.countryCode),
1980
+ pinCode: cust.zip,
1981
+ streetAddress1: cust.address1,
1982
+ streetAddress2: cust.address2 ?? "",
1983
+ landmark: "",
1984
+ city: cust.city,
1985
+ state: cust.province,
1986
+ stateCode: cust.provinceCode,
1987
+ countryCode: cust.countryCode,
1988
+ country: cust.country,
1989
+ store: config.shopify.domain,
1990
+ facilityCode: "",
1991
+ isDefault: true,
1992
+ latitude: "",
1993
+ longitude: "",
1994
+ inStoreReturnExchange: false,
1995
+ external: false,
1996
+ createdAt: at,
1997
+ updatedAt: at
1998
+ },
1999
+ notes: null,
2000
+ tags: []
2001
+ };
1984
2002
  };
2003
+ const lineItems = selected.map(makeLineItem);
1985
2004
  const request = {
1986
2005
  id: `rp-${now.getTime()}`,
1987
2006
  request_number: ctx.requestNumber ?? `${def.requestType === "exchange" ? "EXC" : "RET"}${String(now.getTime()).slice(-3)}`,
@@ -1996,7 +2015,7 @@ function buildPayload6(ctx) {
1996
2015
  name: ctx.orderName ?? `#${String(now.getTime()).slice(-5)}`,
1997
2016
  order_manual_payment: false,
1998
2017
  payment_gateways: [],
1999
- fulfillments: [{ id: Number(String(now.getTime()).slice(-10)), line_items: [lineItem.id], delivery_status: null, delivery_date: null }],
2018
+ fulfillments: [{ id: Number(String(now.getTime()).slice(-10)), line_items: lineItems.map((li) => li.id), delivery_status: null, delivery_date: null }],
2000
2019
  created_at: at
2001
2020
  },
2002
2021
  customer: {
@@ -2026,7 +2045,7 @@ function buildPayload6(ctx) {
2026
2045
  archived: statusBlock(false, at),
2027
2046
  unarchived: statusBlock(false, at),
2028
2047
  incentive: null,
2029
- line_items: [lineItem],
2048
+ line_items: lineItems,
2030
2049
  created_at: at
2031
2050
  };
2032
2051
  return ctx.envelope === "root" ? request : { request };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hookwright",
3
- "version": "1.13.0",
3
+ "version": "2.0.1",
4
4
  "description": "Build real, signed e-commerce webhooks from a live Shopify catalogue — interactive terminal UI, no backend",
5
5
  "keywords": [
6
6
  "webhook",