hookwright 2.0.1 → 2.2.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/cli.js +60 -22
- 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: "2.0
|
|
27
|
+
version: "2.2.0",
|
|
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",
|
|
@@ -1792,8 +1792,12 @@ var EVENTS4 = ["return", "exchange"].flatMap(
|
|
|
1792
1792
|
status,
|
|
1793
1793
|
type: `return_prime_${requestType}_${status}`,
|
|
1794
1794
|
label: `${titleCase(requestType)} ${titleCase(status)}`,
|
|
1795
|
-
|
|
1796
|
-
|
|
1795
|
+
// A return is one or more products sent back, so it is a multi pick, not the
|
|
1796
|
+
// single "which product was viewed" a browsing event asks for. An exchange is
|
|
1797
|
+
// the same list, followed by the replacement chosen for each line.
|
|
1798
|
+
selection: requestType === "exchange" ? "exchange" : "cart",
|
|
1799
|
+
subject: requestType === "exchange" ? "the returned products and their replacements" : "the returned products",
|
|
1800
|
+
pickPrompt: requestType === "exchange" ? "Select the products being returned for exchange" : "Select the products being returned"
|
|
1797
1801
|
}))
|
|
1798
1802
|
);
|
|
1799
1803
|
var DEFAULT_EVENT4 = "return_requested";
|
|
@@ -1806,6 +1810,9 @@ function eventFromPayload4(payload) {
|
|
|
1806
1810
|
function selectionFor4(eventName) {
|
|
1807
1811
|
return eventDef3(eventName).selection;
|
|
1808
1812
|
}
|
|
1813
|
+
function pickPromptFor(eventName) {
|
|
1814
|
+
return eventDef3(eventName).pickPrompt;
|
|
1815
|
+
}
|
|
1809
1816
|
var COMMON_FIELDS3 = [
|
|
1810
1817
|
{ source: "request.request_type", target: "\xABgate\xBB + requestType", required: true, note: "return or exchange" },
|
|
1811
1818
|
{ source: "request.status", target: "\xABgate\xBB + status", required: true, note: "requested, approved, received, inspected or rejected" },
|
|
@@ -1868,7 +1875,7 @@ function editableFieldsFor3(eventName) {
|
|
|
1868
1875
|
}
|
|
1869
1876
|
var editableFields6 = editableFieldsFor3(DEFAULT_EVENT4);
|
|
1870
1877
|
function statusBlock(reached, at, comment = null) {
|
|
1871
|
-
return { status: reached, comment
|
|
1878
|
+
return { status: reached, comment: comment ?? "quickreply test", created_at: at };
|
|
1872
1879
|
}
|
|
1873
1880
|
function buildPayload6(ctx) {
|
|
1874
1881
|
const { config, items, phone } = ctx;
|
|
@@ -1891,14 +1898,14 @@ function buildPayload6(ctx) {
|
|
|
1891
1898
|
id: Number(sel?.variant?.id ?? sel?.product?.id ?? 0),
|
|
1892
1899
|
refund: {
|
|
1893
1900
|
requested_mode: "store_credit",
|
|
1894
|
-
actual_mode:
|
|
1895
|
-
meta:
|
|
1896
|
-
status: def.status === "
|
|
1901
|
+
actual_mode: "store_credit",
|
|
1902
|
+
meta: { discount_code: ctx.couponCode ?? `RP${String(now.getTime()).slice(-7)}` },
|
|
1903
|
+
status: def.status === "requested" ? "pending" : "refunded",
|
|
1897
1904
|
refunded_amount: {
|
|
1898
|
-
shop_money: {
|
|
1899
|
-
presentment_money: {
|
|
1905
|
+
shop_money: { amount: originalPrice, currency_code: currency },
|
|
1906
|
+
presentment_money: { amount: originalPrice, currency_code: currency }
|
|
1900
1907
|
},
|
|
1901
|
-
refunded_at:
|
|
1908
|
+
refunded_at: at,
|
|
1902
1909
|
comment: null
|
|
1903
1910
|
},
|
|
1904
1911
|
return_fee: {
|
|
@@ -1910,8 +1917,8 @@ function buildPayload6(ctx) {
|
|
|
1910
1917
|
},
|
|
1911
1918
|
exchange_fee: {
|
|
1912
1919
|
price_set: {
|
|
1913
|
-
shop_money: { amount:
|
|
1914
|
-
presentment_money: { amount:
|
|
1920
|
+
shop_money: { amount: ctx.exchangeFee ?? 0, currency_code: currency },
|
|
1921
|
+
presentment_money: { amount: ctx.exchangeFee ?? 0, currency_code: currency }
|
|
1915
1922
|
}
|
|
1916
1923
|
},
|
|
1917
1924
|
exchange: { order: null },
|
|
@@ -1940,7 +1947,7 @@ function buildPayload6(ctx) {
|
|
|
1940
1947
|
}
|
|
1941
1948
|
} : {},
|
|
1942
1949
|
shipping: [
|
|
1943
|
-
|
|
1950
|
+
{
|
|
1944
1951
|
shipping_company: "bluedartV2",
|
|
1945
1952
|
tracking_available: true,
|
|
1946
1953
|
awb: String(now.getTime()).slice(-11),
|
|
@@ -1973,13 +1980,13 @@ function buildPayload6(ctx) {
|
|
|
1973
1980
|
do_not_carry_forward_discount: true
|
|
1974
1981
|
},
|
|
1975
1982
|
shopify_order_fulfillment_location: null,
|
|
1976
|
-
return_location:
|
|
1983
|
+
return_location: {
|
|
1977
1984
|
id: "rp-location-1",
|
|
1978
1985
|
fullName: config.shopify.shop?.name ?? config.shopify.domain,
|
|
1979
1986
|
mobileNumber: nationalNumber(phone, cust.countryCode),
|
|
1980
1987
|
pinCode: cust.zip,
|
|
1981
1988
|
streetAddress1: cust.address1,
|
|
1982
|
-
streetAddress2: cust.address2
|
|
1989
|
+
streetAddress2: cust.address2 || "Second line",
|
|
1983
1990
|
landmark: "",
|
|
1984
1991
|
city: cust.city,
|
|
1985
1992
|
state: cust.province,
|
|
@@ -2032,7 +2039,7 @@ function buildPayload6(ctx) {
|
|
|
2032
2039
|
country_code: cust.countryCode,
|
|
2033
2040
|
province_code: cust.provinceCode,
|
|
2034
2041
|
address_line_1: cust.address1,
|
|
2035
|
-
address_line_2: cust.address2
|
|
2042
|
+
address_line_2: cust.address2 || "Second line",
|
|
2036
2043
|
country: cust.country,
|
|
2037
2044
|
address_line_3: ""
|
|
2038
2045
|
},
|
|
@@ -2092,6 +2099,7 @@ var return_prime_default = {
|
|
|
2092
2099
|
editableFields: editableFields6,
|
|
2093
2100
|
editableFieldsFor: editableFieldsFor3,
|
|
2094
2101
|
selectionFor: selectionFor4,
|
|
2102
|
+
pickPromptFor,
|
|
2095
2103
|
eventFromPayload: eventFromPayload4,
|
|
2096
2104
|
buildPayload: buildPayload6,
|
|
2097
2105
|
sign: sign6,
|
|
@@ -3571,7 +3579,7 @@ function loadPayload(file) {
|
|
|
3571
3579
|
}
|
|
3572
3580
|
|
|
3573
3581
|
// src/core/build.mjs
|
|
3574
|
-
function draftPayload({ cfg, providerId = "cashfree-occ", items, discount = 0, phone, eventName, collection, envelope, live, delta }) {
|
|
3582
|
+
function draftPayload({ cfg, providerId = "cashfree-occ", items, discount = 0, phone, eventName, collection, envelope, live, delta, exchangeItems }) {
|
|
3575
3583
|
const provider = getProvider(providerId);
|
|
3576
3584
|
const event = eventName ?? provider.defaultEvent;
|
|
3577
3585
|
const resolvedPhone = phone ?? cfg.customer.phone;
|
|
@@ -3585,6 +3593,7 @@ function draftPayload({ cfg, providerId = "cashfree-occ", items, discount = 0, p
|
|
|
3585
3593
|
envelope,
|
|
3586
3594
|
live,
|
|
3587
3595
|
delta,
|
|
3596
|
+
exchangeItems,
|
|
3588
3597
|
phone: parsed.ok ? parsed.value : String(resolvedPhone ?? "")
|
|
3589
3598
|
});
|
|
3590
3599
|
const editable = provider.editableFieldsFor ? provider.editableFieldsFor(event) : provider.editableFields;
|
|
@@ -3600,7 +3609,7 @@ function applyEdits(payload, fields, edits) {
|
|
|
3600
3609
|
}
|
|
3601
3610
|
return payload;
|
|
3602
3611
|
}
|
|
3603
|
-
async function buildPayload10({ cfg, providerId = "cashfree-occ", items = [], discount = 0, phone, checkImageUrls = true, payload: prebuilt, eventName, collection, envelope, live, delta }) {
|
|
3612
|
+
async function buildPayload10({ cfg, providerId = "cashfree-occ", items = [], discount = 0, phone, checkImageUrls = true, payload: prebuilt, eventName, collection, envelope, live, delta, exchangeItems }) {
|
|
3604
3613
|
const provider0 = getProvider(providerId);
|
|
3605
3614
|
const needsItems = !provider0.selectionFor || ["cart", "product"].includes(provider0.selectionFor(eventName ?? provider0.defaultEvent));
|
|
3606
3615
|
if (needsItems && !items.length) throw new ConfigError("no products selected");
|
|
@@ -3609,7 +3618,7 @@ async function buildPayload10({ cfg, providerId = "cashfree-occ", items = [], di
|
|
|
3609
3618
|
const parsed = toE164(resolvedPhone, cfg.customer.countryCode);
|
|
3610
3619
|
if (!parsed.ok) throw new ConfigError(`phone is unusable: ${parsed.reason}`);
|
|
3611
3620
|
const event = eventName ?? provider.defaultEvent;
|
|
3612
|
-
const payload = prebuilt ?? provider.buildPayload({ config: cfg, items, discount, phone: parsed.value, eventName: event, collection, envelope, live, delta });
|
|
3621
|
+
const payload = prebuilt ?? provider.buildPayload({ config: cfg, items, discount, phone: parsed.value, eventName: event, collection, envelope, live, delta, exchangeItems });
|
|
3613
3622
|
const body = JSON.stringify(payload);
|
|
3614
3623
|
const report = await runAll({ payload, body, provider, config: cfg, checkImageUrls, eventName: event });
|
|
3615
3624
|
const summary = provider.summarize ? provider.summarize(payload) : {};
|
|
@@ -3905,6 +3914,7 @@ var STEP = {
|
|
|
3905
3914
|
LOADING: "loading",
|
|
3906
3915
|
COLLECTION: "collection",
|
|
3907
3916
|
PICK: "pick",
|
|
3917
|
+
REPLACEMENT: "replacement",
|
|
3908
3918
|
VARIANT: "variant",
|
|
3909
3919
|
QUANTITY: "quantity",
|
|
3910
3920
|
DELTA: "delta",
|
|
@@ -3932,6 +3942,7 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
|
|
|
3932
3942
|
const [cursor, setCursor] = useState(0);
|
|
3933
3943
|
const [items, setItems] = useState([]);
|
|
3934
3944
|
const [pendingVariant, setPendingVariant] = useState(null);
|
|
3945
|
+
const [exchangeItems, setExchangeItems] = useState([]);
|
|
3935
3946
|
const [delta, setDelta] = useState([]);
|
|
3936
3947
|
const isDeltaEvent = providerId === "nitro" && (eventName === "addtocart" || eventName === "removefromcart");
|
|
3937
3948
|
const [draft, setDraft] = useState(null);
|
|
@@ -4054,10 +4065,18 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
|
|
|
4054
4065
|
alive = false;
|
|
4055
4066
|
};
|
|
4056
4067
|
}, [step === STEP.EVENT, eventName]);
|
|
4068
|
+
const onReplacementsPicked = (ids) => {
|
|
4069
|
+
const picked = ids.map((id) => products.find((p) => p.id === id)).filter(Boolean);
|
|
4070
|
+
if (!picked.length) return;
|
|
4071
|
+
const pairs = picked.map((p) => ({ product: p, variant: p.variants[0], quantity: 1 }));
|
|
4072
|
+
setExchangeItems(pairs);
|
|
4073
|
+
startReview(0, collection, items, delta, pairs);
|
|
4074
|
+
};
|
|
4057
4075
|
const advance = (nextItems, nextCursor) => {
|
|
4058
4076
|
if (nextCursor >= chosen.length) {
|
|
4059
4077
|
setItems(nextItems);
|
|
4060
4078
|
if (isDeltaEvent) setStep(STEP.DELTA);
|
|
4079
|
+
else if (selection === "exchange") setStep(STEP.REPLACEMENT);
|
|
4061
4080
|
else if (selection === "cart") setStep(STEP.DISCOUNT);
|
|
4062
4081
|
else startReview(0, collection, nextItems);
|
|
4063
4082
|
return;
|
|
@@ -4114,7 +4133,7 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
|
|
|
4114
4133
|
const nextItems = [...items, { product, variant: pendingVariant, quantity: qty }];
|
|
4115
4134
|
advance(nextItems, cursor + 1);
|
|
4116
4135
|
};
|
|
4117
|
-
const startReview = async (discount, chosenCollection = collection, chosenItems = items, chosenDelta = delta) => {
|
|
4136
|
+
const startReview = async (discount, chosenCollection = collection, chosenItems = items, chosenDelta = delta, chosenExchange = exchangeItems) => {
|
|
4118
4137
|
try {
|
|
4119
4138
|
let live = null;
|
|
4120
4139
|
if (needsLive(providerId, eventName)) {
|
|
@@ -4129,7 +4148,8 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
|
|
|
4129
4148
|
eventName,
|
|
4130
4149
|
collection: chosenCollection,
|
|
4131
4150
|
live,
|
|
4132
|
-
delta: chosenDelta
|
|
4151
|
+
delta: chosenDelta,
|
|
4152
|
+
exchangeItems: chosenExchange
|
|
4133
4153
|
});
|
|
4134
4154
|
setDraft({ ...next, discount, live, delta: chosenDelta });
|
|
4135
4155
|
setStep(STEP.MODE);
|
|
@@ -4252,7 +4272,7 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
|
|
|
4252
4272
|
] }),
|
|
4253
4273
|
step === STEP.PICK && selection !== "product" && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
4254
4274
|
/* @__PURE__ */ jsxs8(Text8, { children: [
|
|
4255
|
-
|
|
4275
|
+
`${provider.pickPromptFor?.(eventName) ?? "Select the products in the cart"} `,
|
|
4256
4276
|
/* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "(space toggles \xB7 enter confirms)" })
|
|
4257
4277
|
] }),
|
|
4258
4278
|
/* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(
|
|
@@ -4267,6 +4287,24 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
|
|
|
4267
4287
|
}
|
|
4268
4288
|
) })
|
|
4269
4289
|
] }),
|
|
4290
|
+
step === STEP.REPLACEMENT && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
4291
|
+
/* @__PURE__ */ jsxs8(Text8, { children: [
|
|
4292
|
+
"What is each returned line being exchanged for? ",
|
|
4293
|
+
/* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "(space toggles \xB7 enter confirms)" })
|
|
4294
|
+
] }),
|
|
4295
|
+
/* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: `Picked in order, paired with the ${items.length} line${items.length === 1 ? "" : "s"} coming back.` }),
|
|
4296
|
+
/* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(
|
|
4297
|
+
MultiSelect,
|
|
4298
|
+
{
|
|
4299
|
+
visibleOptionCount: 10,
|
|
4300
|
+
options: products.map((p) => ({
|
|
4301
|
+
label: `${truncate(p.title, 44).padEnd(45)} ${money(p.variants[0]?.price, currency)}`,
|
|
4302
|
+
value: p.id
|
|
4303
|
+
})),
|
|
4304
|
+
onSubmit: onReplacementsPicked
|
|
4305
|
+
}
|
|
4306
|
+
) })
|
|
4307
|
+
] }),
|
|
4270
4308
|
step === STEP.DELTA && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
4271
4309
|
/* @__PURE__ */ jsxs8(Text8, { children: [
|
|
4272
4310
|
eventName === "addtocart" ? "Which of those lines is the shopper adding now? " : "Which of those lines is the shopper removing? ",
|