hookwright 1.12.2 → 1.13.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 +443 -8
  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.12.2",
27
+ version: "1.13.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",
@@ -178,7 +178,9 @@ var DEFAULT_CONFIG = {
178
178
  shopflo: { webhookUrl: "", webhookSecret: "" },
179
179
  flexype: { webhookUrl: "", webhookSecret: "" },
180
180
  "return-prime": { webhookUrl: "", webhookSecret: "" },
181
- fastrr: { webhookUrl: "", webhookSecret: "" }
181
+ fastrr: { webhookUrl: "", webhookSecret: "" },
182
+ gokwik: { webhookUrl: "", webhookSecret: "" },
183
+ ecom360: { webhookUrl: "", webhookSecret: "" }
182
184
  },
183
185
  customer: {
184
186
  firstName: "",
@@ -2258,6 +2260,423 @@ var fastrr_default = {
2258
2260
  summarize: summarize7
2259
2261
  };
2260
2262
 
2263
+ // src/providers/gokwik.mjs
2264
+ var GATE_PATH5 = "abc_url";
2265
+ var GATE_VALUE4 = "";
2266
+ var fieldMap8 = [
2267
+ { source: "abc_url", target: "\xABgate\xBB + checkout_link", required: true, note: "absent and the event is dropped; its origin builds every other link" },
2268
+ { source: "customer.phone / address.phone", target: "customer.phone", required: true },
2269
+ { source: "sa_localization", target: "phone region", required: true, note: 'address.country says "India", which the parser cannot use' },
2270
+ { source: "customer.firstname", target: "customer.firstName" },
2271
+ { source: "customer.lastname", target: "customer.lastName" },
2272
+ { source: "customer.email / address.email", target: "customer.email" },
2273
+ { source: "items[].title", target: "product_details", required: true, note: "the first PAID line wins; freebies rank last" },
2274
+ { source: "items[].product_title", target: "product_name" },
2275
+ { source: "items[].image", target: "product_image_url", note: "read off the featured line only" },
2276
+ { source: "items[].url", target: "product_url", note: "relative \u2014 resolved against the abc_url origin" },
2277
+ { source: "items[].final_price", target: "product_price", note: "PAISE \u2014 the consumer divides by 100" },
2278
+ { source: "items[].sku", target: "product_sku" },
2279
+ { source: "items[].product_type", target: "product_type" },
2280
+ { source: "items[].variant_id", target: "cart_link", note: "joined as variant:quantity" },
2281
+ { source: "items[].quantity", target: "total_quantity", note: "summed across the cart" },
2282
+ { source: "item_count", target: "item_count", note: "gokwik's own count is kept over the line count" },
2283
+ { source: "total_price", target: "total_price", note: "RUPEE string, unlike the line prices" },
2284
+ { source: "original_total_price", target: "original_total_price" },
2285
+ { source: "items_subtotal_price", target: "subtotal_price" },
2286
+ { source: "total_discount", target: "total_discount" },
2287
+ { source: "currency", target: "currency" },
2288
+ { source: "request_id", target: "request_id" },
2289
+ { source: "token", target: "token" },
2290
+ { source: "drop_stage", target: "drop_stage" },
2291
+ { source: "rto_risk_flag", target: "rto_risk_flag" },
2292
+ { source: "brand_order_count", target: "brand_order_count" },
2293
+ { source: "mkt_source", target: "mkt_source" },
2294
+ { source: "mkt_medium", target: "mkt_medium" },
2295
+ { source: "mkt_campaign", target: "mkt_campaign" },
2296
+ { source: "mkt_content", target: "mkt_content" },
2297
+ { source: "mkt_term", target: "mkt_term" },
2298
+ { source: "mkt_fbclid", target: "mkt_fbclid" },
2299
+ { source: "landing_page", target: "landing_page" },
2300
+ { source: "orig_referrer", target: "orig_referrer" },
2301
+ { source: "address.city", target: "address.city" },
2302
+ { source: "address.state", target: "address.state" },
2303
+ { source: "address.pincode", target: "address.pincode" },
2304
+ { source: "address.country", target: "address.country" },
2305
+ { source: "address.address", target: "address.address" },
2306
+ { source: "shipping.price", target: "shipping.price" },
2307
+ { source: "city", target: "city", note: "the ip city, not the delivery city" },
2308
+ { source: "isp", target: "isp" },
2309
+ { source: "user_agent", target: "user_agent" },
2310
+ { source: "updated_at", target: "eventTime" }
2311
+ ];
2312
+ var editableFields8 = [
2313
+ { group: "Checkout", path: "request_id", label: "Request id" },
2314
+ { group: "Checkout", path: "token", label: "Token" },
2315
+ { group: "Checkout", path: "abc_url", label: "Recovery URL", hint: "gates the event; its origin builds the product and cart links" },
2316
+ { group: "Checkout", path: "drop_stage", label: "Drop stage" },
2317
+ { group: "Checkout", path: "rto_risk_flag", label: "RTO risk flag" },
2318
+ { group: "Checkout", path: "gokwik_source_channel", label: "Source channel" },
2319
+ { group: "Pricing", path: "total_price", label: "Total price", hint: "rupee string, unlike the line prices" },
2320
+ { group: "Pricing", path: "total_discount", label: "Discount" },
2321
+ { group: "Pricing", path: "currency", label: "Currency" },
2322
+ { group: "Customer", path: "customer.firstname", label: "First name" },
2323
+ { group: "Customer", path: "customer.lastname", label: "Last name" },
2324
+ { group: "Customer", path: "customer.email", label: "Email" },
2325
+ { group: "Customer", path: "customer.phone", label: "Phone" },
2326
+ { group: "Customer", path: "brand_order_count", label: "Brand order count", type: "number" },
2327
+ { group: "Customer", path: "sa_localization", label: "Localization", hint: "two letter region used to parse the phone" },
2328
+ { group: "Shipping", path: "address.address", label: "Address line" },
2329
+ { group: "Shipping", path: "address.city", label: "City" },
2330
+ { group: "Shipping", path: "address.state", label: "State" },
2331
+ { group: "Shipping", path: "address.pincode", label: "Pincode", type: "number" },
2332
+ { group: "Attribution", path: "mkt_source", label: "UTM source" },
2333
+ { group: "Attribution", path: "mkt_medium", label: "UTM medium" },
2334
+ { group: "Attribution", path: "mkt_campaign", label: "UTM campaign" },
2335
+ { group: "Attribution", path: "landing_page", label: "Landing page" },
2336
+ { group: "Attribution", path: "orig_referrer", label: "Referrer" }
2337
+ ];
2338
+ function paise(rupees) {
2339
+ return Math.round(money2(rupees) * 100);
2340
+ }
2341
+ function buildPayload8(ctx) {
2342
+ const { config, items, phone } = ctx;
2343
+ const now = ctx.now ?? /* @__PURE__ */ new Date();
2344
+ const currency = ctx.currency || config.defaults.currency;
2345
+ const domain = config.shopify.domain;
2346
+ const cust = config.customer;
2347
+ const utm = config.defaults.utm ?? {};
2348
+ const lineItems = (items ?? []).map(({ product, variant, quantity }) => {
2349
+ const unit = money2(variant?.price ?? 0);
2350
+ return {
2351
+ id: Number(variant?.id ?? 0),
2352
+ sku: variant?.sku || "",
2353
+ url: `/products/${product.handle}?variant=${variant?.id ?? ""}`,
2354
+ grams: 500,
2355
+ image: imageForVariant(product, variant),
2356
+ price: paise(unit),
2357
+ title: `${product.title}${variant?.title ? ` - ${variant.title}` : ""}`,
2358
+ vendor: product.vendor ?? "",
2359
+ taxable: true,
2360
+ quantity,
2361
+ gift_card: false,
2362
+ line_price: paise(unit * quantity),
2363
+ product_id: Number(product.id),
2364
+ variant_id: Number(variant?.id ?? 0),
2365
+ final_price: paise(unit),
2366
+ product_type: product.productType ?? "",
2367
+ product_title: product.title,
2368
+ original_price: paise(unit),
2369
+ total_discount: 0,
2370
+ final_line_price: paise(unit * quantity),
2371
+ requires_shipping: true
2372
+ };
2373
+ });
2374
+ const subtotal = money2(lineItems.reduce((sum, li) => sum + li.final_line_price / 100, 0));
2375
+ const discount = money2(Math.min(ctx.discount ?? 0, subtotal));
2376
+ const total = money2(subtotal - discount);
2377
+ const requestId = ctx.requestId ?? `gk-${now.getTime()}`;
2378
+ const abcUrl = `https://${domain}?mrid=${requestId}`;
2379
+ return {
2380
+ request_id: requestId,
2381
+ token: `${requestId}?key=${now.getTime().toString(36)}`,
2382
+ note: null,
2383
+ attributes: "{}",
2384
+ original_total_price: subtotal.toFixed(4),
2385
+ total_price: total.toFixed(4),
2386
+ total_discount: discount.toFixed(4),
2387
+ total_weight: "500.0000",
2388
+ is_abandoned: true,
2389
+ item_count: lineItems.length,
2390
+ items: lineItems,
2391
+ requires_shipping: true,
2392
+ currency,
2393
+ items_subtotal_price: String(subtotal),
2394
+ cart_level_discount_applications: [],
2395
+ discount: null,
2396
+ shipping: {
2397
+ id: 1,
2398
+ name: "Shipping",
2399
+ price: ctx.shippingPrice ?? 0,
2400
+ title: "Shipping",
2401
+ base_price: 0,
2402
+ cod_charges: 0,
2403
+ prepaid_price: 0,
2404
+ payment_options: "all",
2405
+ discounted_price: 0
2406
+ },
2407
+ abc_url: abcUrl,
2408
+ created_at: now.toISOString(),
2409
+ updated_at: now.toISOString(),
2410
+ city: cust.city,
2411
+ isp: "Test ISP",
2412
+ ip: "203.0.113.10",
2413
+ mkt_source: utm.utm_source ?? "direct",
2414
+ mkt_medium: utm.utm_medium ?? null,
2415
+ mkt_campaign: utm.utm_campaign ?? null,
2416
+ mkt_content: utm.utm_content ?? null,
2417
+ mkt_term: utm.utm_term ?? null,
2418
+ mkt_fbclid: utm.fbclid ?? null,
2419
+ gift_card_total: "0",
2420
+ payment_methods: ["upi", "cc", "dc", "netbanking"],
2421
+ drop_stage: "Payment Page",
2422
+ checkout_url: null,
2423
+ note_text: "",
2424
+ landing_page: "/",
2425
+ orig_referrer: `https://${domain}/`,
2426
+ gokwik_source_channel: "shopify_checkout",
2427
+ store_source: "web",
2428
+ store_platform: null,
2429
+ rto_risk_flag: "Control",
2430
+ sa_localization: cust.countryCode,
2431
+ shopifysessionid: `gk-session-${now.getTime()}`,
2432
+ user_agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/151.0.0.0 Safari/537.36",
2433
+ notify_customer: false,
2434
+ brand_order_count: 2,
2435
+ address: {
2436
+ firstname: cust.firstName,
2437
+ lastname: cust.lastName,
2438
+ city: cust.city,
2439
+ pincode: Number(cust.zip) || 0,
2440
+ state: cust.province,
2441
+ country: cust.country,
2442
+ email: cust.email,
2443
+ phone,
2444
+ default_address: 0,
2445
+ addresstype: "home",
2446
+ partial_address: false,
2447
+ total_order_count: 1,
2448
+ deliver_order_count: 0,
2449
+ address: cust.address1
2450
+ },
2451
+ customer: {
2452
+ firstname: cust.firstName,
2453
+ lastname: cust.lastName,
2454
+ email: cust.email,
2455
+ phone
2456
+ }
2457
+ };
2458
+ }
2459
+ function sign8() {
2460
+ return { signature: null, timestamp: null, headers: { "content-type": "application/json" } };
2461
+ }
2462
+ function webhookUrl8(config) {
2463
+ return String(targetFor(config, "gokwik").webhookUrl ?? "").trim();
2464
+ }
2465
+ function webhookSecret8(config) {
2466
+ return String(targetFor(config, "gokwik").webhookSecret ?? "");
2467
+ }
2468
+ function summarize8(payload) {
2469
+ const items = Array.isArray(payload?.items) ? payload.items : [];
2470
+ let store;
2471
+ try {
2472
+ store = payload?.abc_url ? new URL(payload.abc_url).host : void 0;
2473
+ } catch {
2474
+ store = payload?.abc_url;
2475
+ }
2476
+ return {
2477
+ event: "abandoned checkout",
2478
+ store,
2479
+ customer: `${payload?.customer?.firstname ?? ""} ${payload?.customer?.lastname ?? ""} \xB7 ${payload?.customer?.phone ?? ""}`.trim(),
2480
+ items: items.map((i) => `${i.title} x${i.quantity}`).join(", "),
2481
+ total: payload?.total_price,
2482
+ currency: payload?.currency,
2483
+ extra: `stage ${payload?.drop_stage}, rto ${payload?.rto_risk_flag}`,
2484
+ link: payload?.abc_url
2485
+ };
2486
+ }
2487
+ var gokwik_default = {
2488
+ id: "gokwik",
2489
+ urlKey: "gokwik",
2490
+ label: "GoKwik",
2491
+ eventType: "gokwik_abandoned_checkout",
2492
+ gate: { path: GATE_PATH5, value: GATE_VALUE4 },
2493
+ signatureScheme: "none documented \u2014 every request is accepted",
2494
+ signatureHeader: null,
2495
+ fieldMap: fieldMap8,
2496
+ editableFields: editableFields8,
2497
+ buildPayload: buildPayload8,
2498
+ sign: sign8,
2499
+ webhookUrl: webhookUrl8,
2500
+ webhookSecret: webhookSecret8,
2501
+ summarize: summarize8
2502
+ };
2503
+
2504
+ // src/providers/ecom360.mjs
2505
+ import crypto4 from "crypto";
2506
+ var GATE_PATH6 = "event";
2507
+ var GATE_VALUE5 = "ABANDONED_CHECKOUT";
2508
+ var fieldMap9 = [
2509
+ { source: "event", target: "\xABgate\xBB", required: true, note: "must be ABANDONED_CHECKOUT or the event is dropped" },
2510
+ { source: "data.phone / data.customer.shipping_address.phone", target: "customer.phone", required: true },
2511
+ { source: "data.customer.shipping_address.country_code", target: "phone region" },
2512
+ { source: "data.customer.first_name", target: "customer.firstName" },
2513
+ { source: "data.customer.last_name", target: "customer.lastName" },
2514
+ { source: "data.email / data.customer.email", target: "customer.email" },
2515
+ { source: "data.abandoned_checkout_url", target: "checkout_link", required: true },
2516
+ { source: "data.store_url", target: "store_url + cart_link", required: true, note: "the cart link is built from it; no lookup needed" },
2517
+ { source: "data.line_items[].title", target: "product_details", required: true, note: "the first PAID line wins; freebies rank last" },
2518
+ { source: "data.line_items[].sku", target: "product_sku" },
2519
+ { source: "data.line_items[].price", target: "product_price", note: "also ranks the lines; a zero marks a freebie" },
2520
+ { source: "data.line_items[].variant_id", target: "cart_link", note: "joined as variant:quantity" },
2521
+ { source: "data.line_items[].quantity", target: "total_quantity", note: "summed across the cart" },
2522
+ { source: "data.line_items[]", target: "item_count", note: "the line count" },
2523
+ { source: "\u2014 (no handle is sent)", target: "product_url", note: "the consumer builds none, by design" },
2524
+ { source: "data.total_price", target: "total_price" },
2525
+ { source: "data.original_total_price", target: "original_total_price" },
2526
+ { source: "data.total_discount", target: "total_discount" },
2527
+ { source: "data.promotions[0].code", target: "coupon_code" },
2528
+ { source: "data.promotions[0].value", target: "coupon_value" },
2529
+ { source: "data.cart_id", target: "cart_id" },
2530
+ { source: "data.cart_token", target: "cart_token" },
2531
+ { source: "data.platform", target: "platform" },
2532
+ { source: "data.utm_parameters.utm_source", target: "utm_parameters.utm_source" },
2533
+ { source: "data.utm_parameters.utm_medium", target: "utm_parameters.utm_medium" },
2534
+ { source: "data.utm_parameters.utm_campaign", target: "utm_parameters.utm_campaign" },
2535
+ { source: "data.utm_parameters.fbclid", target: "utm_parameters.fbclid" },
2536
+ { source: "data.customer.shipping_address.city", target: "shipping_address.city" },
2537
+ { source: "data.customer.shipping_address.province", target: "shipping_address.province" },
2538
+ { source: "data.customer.shipping_address.zip", target: "shipping_address.zip" },
2539
+ { source: "data.customer.shipping_address.country", target: "shipping_address.country" }
2540
+ ];
2541
+ var editableFields9 = [
2542
+ { group: "Checkout", path: "data.cart_id", label: "Cart id" },
2543
+ { group: "Checkout", path: "data.cart_token", label: "Cart token" },
2544
+ { group: "Checkout", path: "data.abandoned_checkout_url", label: "Checkout URL", hint: "the link the shopper is sent back to" },
2545
+ { group: "Checkout", path: "data.store_url", label: "Store domain", hint: "the cart link is built from this" },
2546
+ { group: "Checkout", path: "data.platform", label: "Platform" },
2547
+ { group: "Pricing", path: "data.total_price", label: "Total price", type: "number" },
2548
+ { group: "Pricing", path: "data.original_total_price", label: "Original total", type: "number" },
2549
+ { group: "Pricing", path: "data.total_discount", label: "Discount", type: "number" },
2550
+ { group: "Customer", path: "data.customer.first_name", label: "First name" },
2551
+ { group: "Customer", path: "data.customer.last_name", label: "Last name" },
2552
+ { group: "Customer", path: "data.email", label: "Email" },
2553
+ { group: "Customer", path: "data.phone", label: "Phone" },
2554
+ { group: "Shipping", path: "data.customer.shipping_address.address1", label: "Address line 1" },
2555
+ { group: "Shipping", path: "data.customer.shipping_address.city", label: "City" },
2556
+ { group: "Shipping", path: "data.customer.shipping_address.province", label: "State" },
2557
+ { group: "Shipping", path: "data.customer.shipping_address.zip", label: "Zip / postcode" },
2558
+ { group: "Shipping", path: "data.customer.shipping_address.country_code", label: "Country code", hint: "region used to parse the phone" },
2559
+ { group: "Attribution", path: "data.utm_parameters.utm_source", label: "UTM source" },
2560
+ { group: "Attribution", path: "data.utm_parameters.utm_campaign", label: "UTM campaign" },
2561
+ { group: "Attribution", path: "data.utm_parameters.fbclid", label: "FBCLID" }
2562
+ ];
2563
+ function buildPayload9(ctx) {
2564
+ const { config, items, phone } = ctx;
2565
+ const now = ctx.now ?? /* @__PURE__ */ new Date();
2566
+ const domain = config.shopify.domain;
2567
+ const cust = config.customer;
2568
+ const utm = config.defaults.utm ?? {};
2569
+ const lineItems = (items ?? []).map(({ product, variant, quantity }) => ({
2570
+ product_id: String(product.id),
2571
+ variant_id: String(variant?.id ?? ""),
2572
+ sku: variant?.sku || "",
2573
+ price: money2(variant?.price ?? 0),
2574
+ quantity,
2575
+ gram: 200,
2576
+ title: `${product.title}${variant?.title ? ` - ${variant.title}` : ""}`
2577
+ }));
2578
+ const subtotal = money2(lineItems.reduce((sum, li) => sum + li.price * li.quantity, 0));
2579
+ const discount = money2(Math.min(ctx.discount ?? 0, subtotal));
2580
+ const total = money2(subtotal - discount);
2581
+ const cartToken = ctx.cartToken ?? `ec-${now.getTime()}`;
2582
+ const shippingAddress = {
2583
+ first_name: cust.firstName,
2584
+ last_name: cust.lastName,
2585
+ address1: cust.address1,
2586
+ address2: "",
2587
+ city: cust.city,
2588
+ province: cust.province,
2589
+ country: cust.country,
2590
+ zip: cust.zip,
2591
+ phone,
2592
+ name: `${cust.firstName} ${cust.lastName}`.trim(),
2593
+ province_code: cust.provinceCode ?? "",
2594
+ country_code: cust.countryCode
2595
+ };
2596
+ return {
2597
+ event: GATE_VALUE5,
2598
+ data: {
2599
+ cart_id: `cart_${now.getTime()}`,
2600
+ store_url: domain,
2601
+ platform: "SHOPIFY",
2602
+ cart_token: cartToken,
2603
+ email: cust.email,
2604
+ phone,
2605
+ abandoned_checkout_url: `https://${domain}/checkouts/${cartToken}`,
2606
+ original_total_price: subtotal,
2607
+ total_price: total,
2608
+ total_discount: discount,
2609
+ utm_parameters: {
2610
+ fbclid: utm.fbclid ?? void 0,
2611
+ utm_source: utm.utm_source ?? void 0,
2612
+ utm_medium: utm.utm_medium ?? void 0,
2613
+ utm_campaign: utm.utm_campaign ?? void 0,
2614
+ utm_content: utm.utm_content ?? void 0,
2615
+ utm_term: utm.utm_term ?? void 0
2616
+ },
2617
+ line_items: lineItems,
2618
+ promotions: ctx.couponCode ? [{ code: ctx.couponCode, value: discount }] : [],
2619
+ customer: {
2620
+ email: cust.email,
2621
+ first_name: cust.firstName,
2622
+ last_name: cust.lastName,
2623
+ shipping_address: shippingAddress
2624
+ }
2625
+ }
2626
+ };
2627
+ }
2628
+ function sign9({ body, secret }) {
2629
+ const signature = crypto4.createHmac("sha256", String(secret)).update(body).digest("base64");
2630
+ return {
2631
+ timestamp: null,
2632
+ signature,
2633
+ headers: {
2634
+ "content-type": "application/json",
2635
+ "x-webhook-signature": signature,
2636
+ "x-webhook-topic": "abandonedCheckout",
2637
+ "x-webhook-version": "v1",
2638
+ "user-agent": "Ecom360-v1"
2639
+ }
2640
+ };
2641
+ }
2642
+ function webhookUrl9(config) {
2643
+ return String(targetFor(config, "ecom360").webhookUrl ?? "").trim();
2644
+ }
2645
+ function webhookSecret9(config) {
2646
+ return String(targetFor(config, "ecom360").webhookSecret ?? "");
2647
+ }
2648
+ function summarize9(payload) {
2649
+ const d = payload?.data ?? {};
2650
+ const items = Array.isArray(d.line_items) ? d.line_items : [];
2651
+ const c2 = d.customer ?? {};
2652
+ return {
2653
+ event: "abandoned checkout",
2654
+ store: d.store_url,
2655
+ customer: `${c2.first_name ?? ""} ${c2.last_name ?? ""} \xB7 ${d.phone ?? ""}`.trim(),
2656
+ items: items.map((i) => `${i.title} x${i.quantity}`).join(", "),
2657
+ total: d.total_price,
2658
+ currency: void 0,
2659
+ extra: `platform ${d.platform}`,
2660
+ link: d.abandoned_checkout_url
2661
+ };
2662
+ }
2663
+ var ecom360_default = {
2664
+ id: "ecom360",
2665
+ urlKey: "ecom360",
2666
+ label: "Ecom 360",
2667
+ eventType: "ecom360_abandoned_checkout",
2668
+ gate: { path: GATE_PATH6, value: GATE_VALUE5 },
2669
+ signatureScheme: "base64 HMAC-SHA256 over the body",
2670
+ signatureHeader: "x-webhook-signature",
2671
+ fieldMap: fieldMap9,
2672
+ editableFields: editableFields9,
2673
+ buildPayload: buildPayload9,
2674
+ sign: sign9,
2675
+ webhookUrl: webhookUrl9,
2676
+ webhookSecret: webhookSecret9,
2677
+ summarize: summarize9
2678
+ };
2679
+
2261
2680
  // src/providers/index.mjs
2262
2681
  var PROVIDER_META = [
2263
2682
  {
@@ -2311,6 +2730,20 @@ var PROVIDER_META = [
2311
2730
  signature: "none documented \u2014 every request is accepted",
2312
2731
  header: null,
2313
2732
  available: true
2733
+ },
2734
+ {
2735
+ id: "gokwik",
2736
+ label: "GoKwik",
2737
+ signature: "none documented \u2014 every request is accepted",
2738
+ header: null,
2739
+ available: true
2740
+ },
2741
+ {
2742
+ id: "ecom360",
2743
+ label: "Ecom 360",
2744
+ signature: "base64 HMAC-SHA256 over the body",
2745
+ header: "x-webhook-signature",
2746
+ available: true
2314
2747
  }
2315
2748
  ];
2316
2749
  var providers = {
@@ -2320,7 +2753,9 @@ var providers = {
2320
2753
  [shopflo_default.id]: shopflo_default,
2321
2754
  [flexype_default.id]: flexype_default,
2322
2755
  [return_prime_default.id]: return_prime_default,
2323
- [fastrr_default.id]: fastrr_default
2756
+ [fastrr_default.id]: fastrr_default,
2757
+ [gokwik_default.id]: gokwik_default,
2758
+ [ecom360_default.id]: ecom360_default
2324
2759
  };
2325
2760
  function getProvider(id) {
2326
2761
  const provider = providers[id];
@@ -2980,8 +3415,8 @@ function resolveSource(payload, source) {
2980
3415
  }
2981
3416
  return void 0;
2982
3417
  }
2983
- function coverage(payload, fieldMap8) {
2984
- return fieldMap8.map((f) => {
3418
+ function coverage(payload, fieldMap10) {
3419
+ return fieldMap10.map((f) => {
2985
3420
  const value = resolveSource(payload, f.source);
2986
3421
  const present = value !== void 0 && value !== null && value !== "";
2987
3422
  return {
@@ -3146,7 +3581,7 @@ function applyEdits(payload, fields, edits) {
3146
3581
  }
3147
3582
  return payload;
3148
3583
  }
3149
- async function buildPayload8({ cfg, providerId = "cashfree-occ", items = [], discount = 0, phone, checkImageUrls = true, payload: prebuilt, eventName, collection, envelope, live, delta }) {
3584
+ async function buildPayload10({ cfg, providerId = "cashfree-occ", items = [], discount = 0, phone, checkImageUrls = true, payload: prebuilt, eventName, collection, envelope, live, delta }) {
3150
3585
  const provider0 = getProvider(providerId);
3151
3586
  const needsItems = !provider0.selectionFor || ["cart", "product"].includes(provider0.selectionFor(eventName ?? provider0.defaultEvent));
3152
3587
  if (needsItems && !items.length) throw new ConfigError("no products selected");
@@ -3693,7 +4128,7 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
3693
4128
  const onDiscount = (raw) => startReview(Math.max(0, Number.parseFloat(raw) || 0));
3694
4129
  const finalise = (payload) => {
3695
4130
  setStep(STEP.BUILDING);
3696
- buildPayload8({ cfg: config, providerId, items, discount: draft.discount, payload, eventName, collection, live: draft.live, delta: draft.delta }).then(async (result) => {
4131
+ buildPayload10({ cfg: config, providerId, items, discount: draft.discount, payload, eventName, collection, live: draft.live, delta: draft.delta }).then(async (result) => {
3697
4132
  setBuilt(result);
3698
4133
  let req = null;
3699
4134
  let command = "";
@@ -4964,7 +5399,7 @@ async function cmdBuild(args, config) {
4964
5399
  else if (live?.kind === "order") log.ok(`order ${live.name} (${live.id})`);
4965
5400
  else log.warn("no live record available \u2014 falling back to a generated one");
4966
5401
  }
4967
- const built = await buildPayload8({
5402
+ const built = await buildPayload10({
4968
5403
  cfg: config,
4969
5404
  providerId,
4970
5405
  eventName,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hookwright",
3
- "version": "1.12.2",
3
+ "version": "1.13.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",