hookwright 1.2.1 → 1.2.3

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 (3) hide show
  1. package/README.md +3 -1
  2. package/dist/cli.js +45 -14
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -75,6 +75,8 @@ Every command works without a TTY, for CI or scripting:
75
75
  hookwright build --items 2 # cashfree-occ by default
76
76
  hookwright build --provider razorpay-magic --items 2
77
77
  hookwright build --provider nitro --event orders/create
78
+ hookwright build --provider nitro --event category_view --collection summer-sale
79
+ hookwright build --provider nitro --event view # no product needed
78
80
  hookwright build --search "cold brew" # only products matching a title
79
81
  hookwright build --items 3 --discount 250 --send
80
82
  hookwright send --dry-run # print the request + curl, send nothing
@@ -142,7 +144,7 @@ Adding one is a single file in `src/providers/` exporting `buildPayload`, `sign`
142
144
  ```bash
143
145
  npm install
144
146
  npm run dev # esbuild watch
145
- npm test # 187 tests, no network required
147
+ npm test # 190 tests, no network required
146
148
  npm start # build + run
147
149
  ```
148
150
 
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.2.1",
27
+ version: "1.2.3",
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",
@@ -776,6 +776,9 @@ var EVENTS = [
776
776
  { eventName: "orders/create", type: "nitro_orders_create", label: "Order Created", selection: "cart", subject: "ordered items" },
777
777
  { eventName: "orders/updated", type: "nitro_orders_updated", label: "Order Updated", selection: "cart", subject: "ordered items" }
778
778
  ];
779
+ function eventFromPayload(payload) {
780
+ return payload?.eventName;
781
+ }
779
782
  function selectionFor(eventName) {
780
783
  return EVENTS.find((e) => e.eventName === eventName)?.selection ?? "cart";
781
784
  }
@@ -1061,6 +1064,7 @@ var nitro_default = {
1061
1064
  editableFields: editableFields3,
1062
1065
  editableFieldsFor,
1063
1066
  selectionFor,
1067
+ eventFromPayload,
1064
1068
  buildPayload: buildPayload3,
1065
1069
  sign: sign3,
1066
1070
  webhookUrl: webhookUrl3,
@@ -1773,10 +1777,11 @@ async function checkImages(payload, { timeoutMs = 1e4 } = {}) {
1773
1777
  }));
1774
1778
  }
1775
1779
  async function runAll({ payload, body, provider, config, checkImageUrls = true, checkEndpoint = true, eventName }) {
1776
- const checks = [checkGate(payload, provider, eventName), checkRoundTrip(body), checkPhone(payload), checkAllowedPhone(payload, config)];
1780
+ const event = eventName ?? (provider.eventFromPayload ? provider.eventFromPayload(payload) : void 0);
1781
+ const checks = [checkGate(payload, provider, event), checkRoundTrip(body), checkPhone(payload), checkAllowedPhone(payload, config)];
1777
1782
  if (checkImageUrls) checks.push(...await checkImages(payload));
1778
1783
  if (checkEndpoint) checks.push(await checkEndpointExists(provider.webhookUrl(config)));
1779
- const fields = eventName && provider.fieldMapFor ? provider.fieldMapFor(eventName) : provider.fieldMap;
1784
+ const fields = event && provider.fieldMapFor ? provider.fieldMapFor(event) : provider.fieldMap;
1780
1785
  const cov = coverage(payload, fields);
1781
1786
  const missing = cov.filter((c2) => c2.status === "MISSING");
1782
1787
  checks.push({
@@ -1918,7 +1923,8 @@ async function buildPayload4({ cfg, providerId = "cashfree-occ", items = [], dis
1918
1923
  };
1919
1924
  const file = savePayload({ provider: provider.id, payload, body, meta });
1920
1925
  audit("payload.built", { provider: provider.id, valid: report.ok, file });
1921
- return { provider, payload, body, report, file, meta, summary };
1926
+ const record = { provider: provider.id, payload, body, meta };
1927
+ return { provider, payload, body, report, file, meta, summary, record };
1922
1928
  }
1923
1929
 
1924
1930
  // src/core/send.mjs
@@ -2356,7 +2362,7 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
2356
2362
  };
2357
2363
  const doSend = () => {
2358
2364
  setStep(STEP.SENDING);
2359
- dispatch({ cfg: config, record: { provider: built.provider.id, payload: built.payload, body: built.body } }).then((result) => {
2365
+ dispatch({ cfg: config, record: built.record }).then((result) => {
2360
2366
  setSendResult(result);
2361
2367
  setStep(STEP.RESULT);
2362
2368
  }).catch((err) => {
@@ -3530,18 +3536,42 @@ async function cmdBuild(args, config) {
3530
3536
  const discount = Number.parseFloat(args.flags.discount ?? "0") || 0;
3531
3537
  const search = typeof args.flags.search === "string" ? args.flags.search : void 0;
3532
3538
  const checkImageUrls = args.flags.image !== false && args.flags["image-check"] !== false;
3533
- log.step(`fetching products from ${config.shopify.domain}\u2026`);
3534
- const products = await fetchCatalogue(config, { search });
3535
- if (!products.length) {
3536
- log.fail("Shopify returned no products");
3537
- return 1;
3539
+ const provider = getProvider(providerId);
3540
+ const eventName = typeof args.flags.event === "string" ? args.flags.event : provider.defaultEvent;
3541
+ const selection = provider.selectionFor ? provider.selectionFor(eventName) : "cart";
3542
+ let items = [];
3543
+ let collection;
3544
+ if (selection === "collection") {
3545
+ log.step(`fetching collections from ${config.shopify.domain}\u2026`);
3546
+ const collections = await fetchCollections(config, { search });
3547
+ if (!collections.length) {
3548
+ log.fail("Shopify returned no collections");
3549
+ log.dim("create one in Shopify, or pick a different event");
3550
+ return 1;
3551
+ }
3552
+ const wanted = typeof args.flags.collection === "string" ? args.flags.collection.toLowerCase() : null;
3553
+ collection = collections.find((c2) => wanted && (c2.id === wanted || c2.handle === wanted || c2.title.toLowerCase() === wanted)) ?? collections[0];
3554
+ if (wanted && collection.title.toLowerCase() !== wanted && collection.id !== wanted && collection.handle !== wanted) {
3555
+ log.warn(`no collection matched "${args.flags.collection}", using ${collection.title}`);
3556
+ }
3557
+ log.ok(`collection: ${collection.title}`);
3558
+ } else if (selection !== "none") {
3559
+ log.step(`fetching products from ${config.shopify.domain}\u2026`);
3560
+ const products = await fetchCatalogue(config, { search });
3561
+ if (!products.length) {
3562
+ log.fail("Shopify returned no products");
3563
+ return 1;
3564
+ }
3565
+ items = autoSelect(products, selection === "product" ? 1 : count);
3566
+ log.ok(`${items.length} product(s): ${items.map((i) => i.product.title).join(", ")}`);
3567
+ } else {
3568
+ log.ok(`${eventName} needs no product or collection`);
3538
3569
  }
3539
- const items = autoSelect(products, count);
3540
- log.ok(`${items.length} product(s): ${items.map((i) => i.product.title).join(", ")}`);
3541
3570
  const built = await buildPayload4({
3542
3571
  cfg: config,
3543
3572
  providerId,
3544
- eventName: typeof args.flags.event === "string" ? args.flags.event : void 0,
3573
+ eventName,
3574
+ collection,
3545
3575
  items,
3546
3576
  discount,
3547
3577
  phone: typeof args.flags.phone === "string" ? args.flags.phone : void 0,
@@ -3586,7 +3616,7 @@ async function cmdBuild(args, config) {
3586
3616
  async function cmdSend(args, config, built) {
3587
3617
  const bad = requireConfig(config);
3588
3618
  if (bad) return bad;
3589
- let record = built ? { provider: built.provider.id, payload: built.payload, body: built.body } : null;
3619
+ let record = built?.record ?? null;
3590
3620
  if (!record && typeof args.flags.file === "string") record = loadPayload(args.flags.file);
3591
3621
  if (!record) record = loadLast();
3592
3622
  if (!record) {
@@ -3747,6 +3777,7 @@ ${c.bold("BUILD OPTIONS")}
3747
3777
  --provider <id> cashfree-occ | razorpay-magic | nitro (default cashfree-occ)
3748
3778
  --event <name> nitro only: view \xB7 category_view \xB7 product_view \xB7 addtocart
3749
3779
  removefromcart \xB7 checkout \xB7 orders/create \xB7 orders/updated
3780
+ --collection <x> nitro category_view: collection id, handle or title
3750
3781
  --items <n> how many products to put in the cart (default 1)
3751
3782
  --search <text> only consider products matching a title
3752
3783
  --discount <n> cart discount in major currency units (default 0)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hookwright",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
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",