hookwright 1.6.0 → 1.7.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.
Files changed (2) hide show
  1. package/dist/cli.js +52 -18
  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.6.0",
27
+ version: "1.7.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",
@@ -911,7 +911,7 @@ function editableFieldsFor(eventName) {
911
911
  }
912
912
  var editableFields3 = editableFieldsFor(DEFAULT_EVENT);
913
913
  function buildPayload3(ctx) {
914
- const { config, items, phone, live } = ctx;
914
+ const { config, items, phone, live, delta } = ctx;
915
915
  const eventName = ctx.eventName ?? DEFAULT_EVENT;
916
916
  const now = ctx.now ?? /* @__PURE__ */ new Date();
917
917
  const currency = ctx.currency || config.defaults.currency;
@@ -1022,16 +1022,18 @@ function buildPayload3(ctx) {
1022
1022
  case "addtocart":
1023
1023
  case "removefromcart": {
1024
1024
  const added = eventName === "addtocart";
1025
- const removed = added ? [] : items.slice(-1);
1026
- const remaining = added ? items : items.slice(0, -1);
1025
+ const fallback = added ? items : items.slice(-1);
1026
+ const moved = delta?.length ? items.filter((item) => delta.includes(item)) : fallback;
1027
+ const untouched = items.filter((item) => !moved.includes(item));
1028
+ const cart = added ? items : untouched;
1027
1029
  eventVal = {
1028
- line_items: added ? lineItems : remaining.map(cartLine),
1029
- cart_value: added ? cartValue : valueOf(remaining),
1030
- recent_product_image: added ? lineItems[0]?.image_url ?? null : null,
1030
+ line_items: cart.map(cartLine),
1031
+ cart_value: valueOf(cart),
1032
+ recent_product_image: added ? moved.map(cartLine)[0]?.image_url ?? null : null,
1031
1033
  init_cart: false,
1032
- empty_cart: !added && remaining.length === 0,
1033
- items_added: added ? lineItems : [],
1034
- items_removed: removed.map(removedLine),
1034
+ empty_cart: !added && cart.length === 0,
1035
+ items_added: added ? moved.map(cartLine) : [],
1036
+ items_removed: added ? [] : moved.map(removedLine),
1035
1037
  customer,
1036
1038
  bik_customer_id: null
1037
1039
  };
@@ -2908,7 +2910,7 @@ function loadPayload(file) {
2908
2910
  }
2909
2911
 
2910
2912
  // src/core/build.mjs
2911
- function draftPayload({ cfg, providerId = "cashfree-occ", items, discount = 0, phone, eventName, collection, envelope, live }) {
2913
+ function draftPayload({ cfg, providerId = "cashfree-occ", items, discount = 0, phone, eventName, collection, envelope, live, delta }) {
2912
2914
  const provider = getProvider(providerId);
2913
2915
  const event = eventName ?? provider.defaultEvent;
2914
2916
  const resolvedPhone = phone ?? cfg.customer.phone;
@@ -2921,6 +2923,7 @@ function draftPayload({ cfg, providerId = "cashfree-occ", items, discount = 0, p
2921
2923
  collection,
2922
2924
  envelope,
2923
2925
  live,
2926
+ delta,
2924
2927
  phone: parsed.ok ? parsed.value : String(resolvedPhone ?? "")
2925
2928
  });
2926
2929
  const editable = provider.editableFieldsFor ? provider.editableFieldsFor(event) : provider.editableFields;
@@ -2936,7 +2939,7 @@ function applyEdits(payload, fields, edits) {
2936
2939
  }
2937
2940
  return payload;
2938
2941
  }
2939
- async function buildPayload8({ cfg, providerId = "cashfree-occ", items = [], discount = 0, phone, checkImageUrls = true, payload: prebuilt, eventName, collection, envelope, live }) {
2942
+ async function buildPayload8({ cfg, providerId = "cashfree-occ", items = [], discount = 0, phone, checkImageUrls = true, payload: prebuilt, eventName, collection, envelope, live, delta }) {
2940
2943
  const provider0 = getProvider(providerId);
2941
2944
  const needsItems = !provider0.selectionFor || ["cart", "product"].includes(provider0.selectionFor(eventName ?? provider0.defaultEvent));
2942
2945
  if (needsItems && !items.length) throw new ConfigError("no products selected");
@@ -2945,7 +2948,7 @@ async function buildPayload8({ cfg, providerId = "cashfree-occ", items = [], dis
2945
2948
  const parsed = toE164(resolvedPhone, cfg.customer.countryCode);
2946
2949
  if (!parsed.ok) throw new ConfigError(`phone is unusable: ${parsed.reason}`);
2947
2950
  const event = eventName ?? provider.defaultEvent;
2948
- const payload = prebuilt ?? provider.buildPayload({ config: cfg, items, discount, phone: parsed.value, eventName: event, collection, envelope, live });
2951
+ const payload = prebuilt ?? provider.buildPayload({ config: cfg, items, discount, phone: parsed.value, eventName: event, collection, envelope, live, delta });
2949
2952
  const body = JSON.stringify(payload);
2950
2953
  const report = await runAll({ payload, body, provider, config: cfg, checkImageUrls, eventName: event });
2951
2954
  const summary = provider.summarize ? provider.summarize(payload) : {};
@@ -3224,6 +3227,7 @@ var STEP = {
3224
3227
  PICK: "pick",
3225
3228
  VARIANT: "variant",
3226
3229
  QUANTITY: "quantity",
3230
+ DELTA: "delta",
3227
3231
  DISCOUNT: "discount",
3228
3232
  LIVE: "live",
3229
3233
  MODE: "mode",
@@ -3248,6 +3252,8 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
3248
3252
  const [cursor, setCursor] = useState(0);
3249
3253
  const [items, setItems] = useState([]);
3250
3254
  const [pendingVariant, setPendingVariant] = useState(null);
3255
+ const [delta, setDelta] = useState([]);
3256
+ const isDeltaEvent = providerId === "nitro" && (eventName === "addtocart" || eventName === "removefromcart");
3251
3257
  const [draft, setDraft] = useState(null);
3252
3258
  const [fieldIndex, setFieldIndex] = useState(0);
3253
3259
  const [edits, setEdits] = useState({});
@@ -3281,6 +3287,8 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
3281
3287
  setItems(items.slice(0, -1));
3282
3288
  return stepInto(last);
3283
3289
  }
3290
+ case STEP.DELTA:
3291
+ return setStep(STEP.PICK);
3284
3292
  case STEP.LIVE:
3285
3293
  case STEP.MODE:
3286
3294
  return setStep(STEP.DISCOUNT);
@@ -3369,7 +3377,8 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
3369
3377
  const advance = (nextItems, nextCursor) => {
3370
3378
  if (nextCursor >= chosen.length) {
3371
3379
  setItems(nextItems);
3372
- if (selection === "cart") setStep(STEP.DISCOUNT);
3380
+ if (isDeltaEvent) setStep(STEP.DELTA);
3381
+ else if (selection === "cart") setStep(STEP.DISCOUNT);
3373
3382
  else startReview(0, collection, nextItems);
3374
3383
  return;
3375
3384
  }
@@ -3425,7 +3434,7 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
3425
3434
  const nextItems = [...items, { product, variant: pendingVariant, quantity: qty }];
3426
3435
  advance(nextItems, cursor + 1);
3427
3436
  };
3428
- const startReview = async (discount, chosenCollection = collection, chosenItems = items) => {
3437
+ const startReview = async (discount, chosenCollection = collection, chosenItems = items, chosenDelta = delta) => {
3429
3438
  try {
3430
3439
  let live = null;
3431
3440
  if (needsLive(providerId, eventName)) {
@@ -3439,19 +3448,26 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
3439
3448
  discount,
3440
3449
  eventName,
3441
3450
  collection: chosenCollection,
3442
- live
3451
+ live,
3452
+ delta: chosenDelta
3443
3453
  });
3444
- setDraft({ ...next, discount, live });
3454
+ setDraft({ ...next, discount, live, delta: chosenDelta });
3445
3455
  setStep(STEP.MODE);
3446
3456
  } catch (err) {
3447
3457
  setError({ message: err.message, hint: err.hint, failures: err.failures });
3448
3458
  setStep(STEP.ERROR);
3449
3459
  }
3450
3460
  };
3461
+ const onDelta = (ids) => {
3462
+ const picked = items.filter((i) => ids.includes(String(i.variant?.id ?? i.product?.id)));
3463
+ if (!picked.length) return;
3464
+ setDelta(picked);
3465
+ startReview(0, collection, items, picked);
3466
+ };
3451
3467
  const onDiscount = (raw) => startReview(Math.max(0, Number.parseFloat(raw) || 0));
3452
3468
  const finalise = (payload) => {
3453
3469
  setStep(STEP.BUILDING);
3454
- buildPayload8({ cfg: config, providerId, items, discount: draft.discount, payload, eventName, collection, live: draft.live }).then(async (result) => {
3470
+ buildPayload8({ cfg: config, providerId, items, discount: draft.discount, payload, eventName, collection, live: draft.live, delta: draft.delta }).then(async (result) => {
3455
3471
  setBuilt(result);
3456
3472
  let req = null;
3457
3473
  let command = "";
@@ -3571,6 +3587,24 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
3571
3587
  }
3572
3588
  ) })
3573
3589
  ] }),
3590
+ step === STEP.DELTA && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
3591
+ /* @__PURE__ */ jsxs8(Text8, { children: [
3592
+ eventName === "addtocart" ? "Which of those lines is the shopper adding now? " : "Which of those lines is the shopper removing? ",
3593
+ /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "(space toggles \xB7 enter confirms)" })
3594
+ ] }),
3595
+ /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: eventName === "addtocart" ? "The rest were already in the cart." : "The rest stay in the cart." }),
3596
+ /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(
3597
+ MultiSelect,
3598
+ {
3599
+ visibleOptionCount: 10,
3600
+ options: items.map((i) => ({
3601
+ label: `${truncate(i.product.title, 40).padEnd(41)} x${String(i.quantity).padEnd(3)} ${money(i.variant?.price, currency)}`,
3602
+ value: String(i.variant?.id ?? i.product?.id)
3603
+ })),
3604
+ onSubmit: onDelta
3605
+ }
3606
+ ) })
3607
+ ] }),
3574
3608
  step === STEP.VARIANT && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
3575
3609
  /* @__PURE__ */ jsxs8(Text8, { children: [
3576
3610
  `Variant for `,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hookwright",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
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",