hookwright 1.1.0 → 1.1.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 (3) hide show
  1. package/README.md +5 -1
  2. package/dist/cli.js +400 -278
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -53,6 +53,10 @@ Then **Integrations → Cashfree One Click Checkout** builds the payload:
53
53
  5. Pre-flight report — every check, the full field coverage table, the signed request and the complete payload
54
54
  6. A **ready-to-paste `curl` is copied to your clipboard** automatically, then send
55
55
 
56
+ The report page is a compact status board with a command bar — `s` send · `c` copy curl · `j` copy json · `u` curl · `p` payload · `f` fields · `v` checks · `r` request. Panels are collapsed by default, so you see the verdict first and the detail only when you ask for it.
57
+
58
+ `esc` walks back one step at a time through the whole flow (report → mode → discount → quantity → variant → products → event), and only leaves the integration from the first step.
59
+
56
60
  ### The curl is built for pasting
57
61
 
58
62
  The command is emitted in the exact shape Postman itself exports — `curl --location --request POST` with unindented `--header` / `--data` lines — and the body is inlined, never `@file`. Drop it straight into **Postman → Import → Raw text**, a colleague's terminal, or a bug report.
@@ -127,7 +131,7 @@ Adding one is a single file in `src/providers/` exporting `buildPayload`, `sign`
127
131
  ```bash
128
132
  npm install
129
133
  npm run dev # esbuild watch
130
- npm test # 138 tests, no network required
134
+ npm test # 179 tests, no network required
131
135
  npm start # build + run
132
136
  ```
133
137
 
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.1.0",
27
+ version: "1.1.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",
@@ -71,11 +71,11 @@ var init_package = __esm({
71
71
  });
72
72
 
73
73
  // src/cli.jsx
74
- import React15 from "react";
74
+ import React16 from "react";
75
75
  import { render } from "ink";
76
76
 
77
77
  // src/ui/App.jsx
78
- import React14, { useState as useState8 } from "react";
78
+ import React15, { useState as useState8 } from "react";
79
79
  import { useApp as useApp2 } from "ink";
80
80
 
81
81
  // src/ui/screens/Home.jsx
@@ -331,8 +331,8 @@ function Home({ config, onPick, onQuit }) {
331
331
  const ready = canSend(config);
332
332
  const shop = config.shopify.shop;
333
333
  const options = [
334
- { label: "Setup".padEnd(18) + (ready ? "Shopify and webhook destination" : "connect Shopify and set the webhook URL"), value: "setup" },
335
334
  { label: "Integrations".padEnd(18) + "build and send a provider webhook", value: "integrations" },
335
+ { label: "Setup".padEnd(18) + (ready ? "Shopify and webhook destination" : "connect Shopify and set the webhook URL"), value: "setup" },
336
336
  { label: "History".padEnd(18) + "review or re-send a saved payload", value: "history" },
337
337
  { label: "Doctor".padEnd(18) + "check credentials and connectivity", value: "doctor" },
338
338
  { label: "Clear".padEnd(18) + "remove cached data", value: "clear" },
@@ -1143,8 +1143,8 @@ function Integrations({ config, onPick, onBack, onSetup }) {
1143
1143
  }
1144
1144
 
1145
1145
  // src/ui/screens/Build.jsx
1146
- import React7, { useEffect, useState } from "react";
1147
- import { Box as Box7, Text as Text7, useApp, useInput as useInput3 } from "ink";
1146
+ import React8, { useEffect, useState } from "react";
1147
+ import { Box as Box8, Text as Text8, useApp, useInput as useInput3 } from "ink";
1148
1148
  import { Spinner, Select as Select4, MultiSelect, TextInput, ConfirmInput, Alert, Badge } from "@inkjs/ui";
1149
1149
 
1150
1150
  // src/ui/components/CheckList.jsx
@@ -1195,6 +1195,40 @@ function FieldTable({ coverage: coverage2, limit }) {
1195
1195
  ] });
1196
1196
  }
1197
1197
 
1198
+ // src/ui/components/CommandBar.jsx
1199
+ import React7 from "react";
1200
+ import { Box as Box7, Text as Text7 } from "ink";
1201
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1202
+ function CommandBar({ commands, width: width2 = 78 }) {
1203
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginTop: 1, children: [
1204
+ /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: "\u2500".repeat(width2) }),
1205
+ /* @__PURE__ */ jsx7(Box7, { flexWrap: "wrap", children: commands.map((c2, i) => /* @__PURE__ */ jsxs7(Box7, { marginRight: 2, children: [
1206
+ /* @__PURE__ */ jsx7(Text7, { bold: true, color: c2.disabled ? palette.dim : c2.active ? palette.ok : palette.accent, children: c2.key }),
1207
+ /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: ` ${c2.label}` }),
1208
+ i < commands.length - 1 ? /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: " \xB7" }) : null
1209
+ ] }, c2.key)) })
1210
+ ] });
1211
+ }
1212
+ function StatusRow({ label, ok, warn, value, detail, labelWidth = 12 }) {
1213
+ const colour = ok === void 0 ? palette.dim : ok ? palette.ok : warn ? palette.warn : palette.bad;
1214
+ const mark = ok === void 0 ? " " : ok ? "\u2714" : warn ? "\u25B2" : "\u2716";
1215
+ return /* @__PURE__ */ jsxs7(Box7, { children: [
1216
+ /* @__PURE__ */ jsx7(Text7, { color: colour, children: ` ${mark} ` }),
1217
+ /* @__PURE__ */ jsx7(Text7, { bold: true, children: String(label).padEnd(labelWidth) }),
1218
+ /* @__PURE__ */ jsx7(Text7, { color: colour, children: value }),
1219
+ detail ? /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: ` ${detail}` }) : null
1220
+ ] });
1221
+ }
1222
+ function Panel({ title, hint, children }) {
1223
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginTop: 1, children: [
1224
+ /* @__PURE__ */ jsxs7(Box7, { children: [
1225
+ /* @__PURE__ */ jsx7(Text7, { bold: true, color: palette.heading, children: title }),
1226
+ hint ? /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: ` ${hint}` }) : null
1227
+ ] }),
1228
+ /* @__PURE__ */ jsx7(Box7, { flexDirection: "column", borderStyle: "round", borderColor: palette.dim, paddingX: 1, children })
1229
+ ] });
1230
+ }
1231
+
1198
1232
  // src/errors.mjs
1199
1233
  var ForgeError = class extends Error {
1200
1234
  constructor(message, { hint, cause } = {}) {
@@ -2002,7 +2036,7 @@ async function copy(text, { allowOsc52 = true } = {}) {
2002
2036
  }
2003
2037
 
2004
2038
  // src/ui/screens/Build.jsx
2005
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
2039
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
2006
2040
  var STEP = {
2007
2041
  EVENT: "event",
2008
2042
  LOADING: "loading",
@@ -2037,15 +2071,64 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
2037
2071
  const [copied, setCopied] = useState(null);
2038
2072
  const [request, setRequest] = useState(null);
2039
2073
  const [curl, setCurl] = useState("");
2040
- const [showPayload, setShowPayload] = useState(false);
2074
+ const [panel, setPanel] = useState(null);
2041
2075
  const [sendResult, setSendResult] = useState(null);
2042
2076
  const [error, setError] = useState(null);
2077
+ const goBack = () => {
2078
+ switch (step) {
2079
+ case STEP.EVENT:
2080
+ return onDone();
2081
+ case STEP.PICK:
2082
+ return multiEvent ? setStep(STEP.EVENT) : onDone();
2083
+ case STEP.VARIANT:
2084
+ if (cursor === 0) return setStep(STEP.PICK);
2085
+ setItems(items.slice(0, -1));
2086
+ return stepInto(cursor - 1);
2087
+ case STEP.QUANTITY:
2088
+ if (chosen[cursor]?.variants.length > 1) return setStep(STEP.VARIANT);
2089
+ if (cursor === 0) return setStep(STEP.PICK);
2090
+ setItems(items.slice(0, -1));
2091
+ return stepInto(cursor - 1);
2092
+ case STEP.DISCOUNT: {
2093
+ const last = chosen.length - 1;
2094
+ setItems(items.slice(0, -1));
2095
+ return stepInto(last);
2096
+ }
2097
+ case STEP.MODE:
2098
+ return setStep(STEP.DISCOUNT);
2099
+ case STEP.FIELDS:
2100
+ if (fieldIndex === 0) return setStep(STEP.MODE);
2101
+ return setFieldIndex(fieldIndex - 1);
2102
+ case STEP.REPORT:
2103
+ return setStep(STEP.MODE);
2104
+ case STEP.RESULT:
2105
+ case STEP.ERROR:
2106
+ return onDone();
2107
+ default:
2108
+ return onDone();
2109
+ }
2110
+ };
2111
+ const stepInto = (index) => {
2112
+ setCursor(index);
2113
+ const product = chosen[index];
2114
+ if (!product) return setStep(STEP.PICK);
2115
+ if (product.variants.length > 1) return setStep(STEP.VARIANT);
2116
+ setPendingVariant(product.variants[0]);
2117
+ setStep(STEP.QUANTITY);
2118
+ };
2043
2119
  useInput3((input, key) => {
2044
- if (key.escape) onDone();
2120
+ if (key.escape) return goBack();
2045
2121
  if ((step === STEP.RESULT || step === STEP.ERROR) && (key.return || input === "q")) onDone();
2046
- if (step === STEP.REPORT && input === "p") setShowPayload((v) => !v);
2047
- if (step === STEP.REPORT && input === "c" && curl) copy(curl).then((r) => setCopied({ ...r, what: "curl" }));
2048
- if (step === STEP.REPORT && input === "j" && built) copy(built.body).then((r) => setCopied({ ...r, what: "payload JSON" }));
2122
+ if (step !== STEP.REPORT) return;
2123
+ const toggle = (name) => setPanel((v) => v === name ? null : name);
2124
+ if (input === "p") toggle("payload");
2125
+ if (input === "f") toggle("fields");
2126
+ if (input === "v") toggle("checks");
2127
+ if (input === "r") toggle("request");
2128
+ if (input === "u") toggle("curl");
2129
+ if (input === "c" && curl) copy(curl).then((r) => setCopied({ ...r, what: "curl" }));
2130
+ if (input === "j" && built) copy(built.body).then((r) => setCopied({ ...r, what: "payload JSON" }));
2131
+ if ((input === "s" || key.return) && built?.report.ok) doSend();
2049
2132
  });
2050
2133
  useEffect(() => {
2051
2134
  if (step === STEP.EVENT) return;
@@ -2170,8 +2253,9 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
2170
2253
  };
2171
2254
  const store = config.shopify.domain;
2172
2255
  const currency = config.defaults.currency;
2173
- return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2174
- /* @__PURE__ */ jsx7(
2256
+ const coverageMissing = built ? built.report.coverage.filter((c2) => c2.status === "MISSING").length : 0;
2257
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2258
+ /* @__PURE__ */ jsx8(
2175
2259
  Header,
2176
2260
  {
2177
2261
  title: "Build payload",
@@ -2179,9 +2263,9 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
2179
2263
  right: store
2180
2264
  }
2181
2265
  ),
2182
- step === STEP.EVENT && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2183
- /* @__PURE__ */ jsx7(Text7, { children: "Which event do you want to send?" }),
2184
- /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(
2266
+ step === STEP.EVENT && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2267
+ /* @__PURE__ */ jsx8(Text8, { children: "Which event do you want to send?" }),
2268
+ /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(
2185
2269
  Select4,
2186
2270
  {
2187
2271
  visibleOptionCount: provider.events.length,
@@ -2193,13 +2277,13 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
2193
2277
  }
2194
2278
  ) })
2195
2279
  ] }),
2196
- step === STEP.LOADING && /* @__PURE__ */ jsx7(Spinner, { label: `fetching live products from ${store}\u2026` }),
2197
- step === STEP.PICK && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2198
- /* @__PURE__ */ jsxs7(Text7, { children: [
2280
+ step === STEP.LOADING && /* @__PURE__ */ jsx8(Spinner, { label: `fetching live products from ${store}\u2026` }),
2281
+ step === STEP.PICK && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2282
+ /* @__PURE__ */ jsxs8(Text8, { children: [
2199
2283
  `Select the products in the abandoned cart `,
2200
- /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: "(space toggles \xB7 enter confirms)" })
2284
+ /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "(space toggles \xB7 enter confirms)" })
2201
2285
  ] }),
2202
- /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(
2286
+ /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(
2203
2287
  MultiSelect,
2204
2288
  {
2205
2289
  visibleOptionCount: 10,
@@ -2211,12 +2295,12 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
2211
2295
  }
2212
2296
  ) })
2213
2297
  ] }),
2214
- step === STEP.VARIANT && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2215
- /* @__PURE__ */ jsxs7(Text7, { children: [
2298
+ step === STEP.VARIANT && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2299
+ /* @__PURE__ */ jsxs8(Text8, { children: [
2216
2300
  `Variant for `,
2217
- /* @__PURE__ */ jsx7(Text7, { bold: true, color: palette.accent, children: chosen[cursor]?.title })
2301
+ /* @__PURE__ */ jsx8(Text8, { bold: true, color: palette.accent, children: chosen[cursor]?.title })
2218
2302
  ] }),
2219
- /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(
2303
+ /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(
2220
2304
  Select4,
2221
2305
  {
2222
2306
  visibleOptionCount: 8,
@@ -2229,33 +2313,33 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
2229
2313
  `variant-${cursor}`
2230
2314
  ) })
2231
2315
  ] }),
2232
- step === STEP.QUANTITY && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2233
- /* @__PURE__ */ jsxs7(Text7, { children: [
2316
+ step === STEP.QUANTITY && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2317
+ /* @__PURE__ */ jsxs8(Text8, { children: [
2234
2318
  `Quantity for `,
2235
- /* @__PURE__ */ jsx7(Text7, { bold: true, color: palette.accent, children: chosen[cursor]?.title }),
2236
- /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: pendingVariant?.title ? ` \xB7 ${pendingVariant.title}` : "" })
2319
+ /* @__PURE__ */ jsx8(Text8, { bold: true, color: palette.accent, children: chosen[cursor]?.title }),
2320
+ /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: pendingVariant?.title ? ` \xB7 ${pendingVariant.title}` : "" })
2237
2321
  ] }),
2238
- /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, children: [
2239
- /* @__PURE__ */ jsx7(Text7, { color: palette.accent, children: "\u276F " }),
2240
- /* @__PURE__ */ jsx7(TextInput, { defaultValue: "1", placeholder: "1", onSubmit: onQuantity }, `qty-${cursor}`)
2322
+ /* @__PURE__ */ jsxs8(Box8, { marginTop: 1, children: [
2323
+ /* @__PURE__ */ jsx8(Text8, { color: palette.accent, children: "\u276F " }),
2324
+ /* @__PURE__ */ jsx8(TextInput, { defaultValue: "1", placeholder: "1", onSubmit: onQuantity }, `qty-${cursor}`)
2241
2325
  ] })
2242
2326
  ] }),
2243
- step === STEP.DISCOUNT && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2244
- /* @__PURE__ */ jsxs7(Text7, { children: [
2327
+ step === STEP.DISCOUNT && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2328
+ /* @__PURE__ */ jsxs8(Text8, { children: [
2245
2329
  `Cart discount in ${currency} `,
2246
- /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: "(0 for none)" })
2330
+ /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "(0 for none)" })
2247
2331
  ] }),
2248
- /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, children: [
2249
- /* @__PURE__ */ jsx7(Text7, { color: palette.accent, children: "\u276F " }),
2250
- /* @__PURE__ */ jsx7(TextInput, { defaultValue: "0", placeholder: "0", onSubmit: onDiscount })
2332
+ /* @__PURE__ */ jsxs8(Box8, { marginTop: 1, children: [
2333
+ /* @__PURE__ */ jsx8(Text8, { color: palette.accent, children: "\u276F " }),
2334
+ /* @__PURE__ */ jsx8(TextInput, { defaultValue: "0", placeholder: "0", onSubmit: onDiscount })
2251
2335
  ] })
2252
2336
  ] }),
2253
- step === STEP.MODE && draft && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2254
- /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", borderStyle: "round", borderColor: palette.accent, paddingX: 1, marginBottom: 1, children: [
2255
- /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: `${draft.fields.length} fields have been filled in from Shopify and your profile.` }),
2256
- /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: "Review them one by one, or accept the suggestions as they are." })
2337
+ step === STEP.MODE && draft && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2338
+ /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", borderStyle: "round", borderColor: palette.accent, paddingX: 1, marginBottom: 1, children: [
2339
+ /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: `${draft.fields.length} fields have been filled in from Shopify and your profile.` }),
2340
+ /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "Review them one by one, or accept the suggestions as they are." })
2257
2341
  ] }),
2258
- /* @__PURE__ */ jsx7(
2342
+ /* @__PURE__ */ jsx8(
2259
2343
  Select4,
2260
2344
  {
2261
2345
  options: [
@@ -2266,7 +2350,7 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
2266
2350
  }
2267
2351
  )
2268
2352
  ] }),
2269
- step === STEP.FIELDS && draft && /* @__PURE__ */ jsx7(
2353
+ step === STEP.FIELDS && draft && /* @__PURE__ */ jsx8(
2270
2354
  FieldPrompt,
2271
2355
  {
2272
2356
  field: draft.fields[fieldIndex],
@@ -2276,38 +2360,79 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
2276
2360
  onSubmit: onFieldSubmit
2277
2361
  }
2278
2362
  ),
2279
- step === STEP.BUILDING && /* @__PURE__ */ jsx7(Spinner, { label: "assembling payload, verifying images and signature fidelity\u2026" }),
2280
- (step === STEP.REPORT || step === STEP.CONFIRM) && built && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2281
- /* @__PURE__ */ jsx7(Summary, { built, currency }),
2282
- /* @__PURE__ */ jsx7(Section, { title: "Pre-flight", children: /* @__PURE__ */ jsx7(CheckList, { checks: built.report.checks }) }),
2283
- /* @__PURE__ */ jsx7(Section, { title: "Field coverage", children: /* @__PURE__ */ jsx7(FieldTable, { coverage: built.report.coverage }) }),
2284
- /* @__PURE__ */ jsx7(Section, { title: "Request", children: /* @__PURE__ */ jsx7(RequestPreview, { request, bytes: built.body.length }) }),
2285
- curl ? /* @__PURE__ */ jsx7(Section, { title: "curl \u2014 paste straight into Postman (Import \u2192 Raw text)", children: /* @__PURE__ */ jsx7(Box7, { borderStyle: "round", borderColor: palette.accent, paddingX: 1, flexDirection: "column", children: /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: curl }) }) }) : null,
2286
- showPayload ? /* @__PURE__ */ jsx7(Section, { title: "Payload", children: /* @__PURE__ */ jsx7(Box7, { borderStyle: "round", borderColor: palette.dim, paddingX: 1, flexDirection: "column", children: /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: JSON.stringify(built.payload, null, 2) }) }) }) : null,
2287
- /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: copied?.ok ? /* @__PURE__ */ jsx7(Text7, { color: palette.ok, children: `\u2714 ${copied.what} copied to clipboard via ${copied.via}` }) : /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: `saved to ${built.file} \xB7 press c to copy the curl` }) }),
2288
- /* @__PURE__ */ jsx7(Box7, { children: /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: "c copies the curl \xB7 j copies the payload JSON \xB7 p toggles the full payload" }) }),
2289
- /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: built.report.ok ? /* @__PURE__ */ jsx7(Alert, { variant: "success", children: "payload is valid \u2014 the event will pass the schema gate and signature check" }) : /* @__PURE__ */ jsx7(Alert, { variant: "error", children: `blocking: ${built.report.blocking.map((b) => b.name).join(", ")}` }) }),
2290
- /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, children: [
2291
- /* @__PURE__ */ jsx7(Text7, { children: "Send it to the endpoint now? " }),
2292
- /* @__PURE__ */ jsx7(
2293
- ConfirmInput,
2363
+ step === STEP.BUILDING && /* @__PURE__ */ jsx8(Spinner, { label: "assembling payload, verifying images and signature fidelity\u2026" }),
2364
+ (step === STEP.REPORT || step === STEP.CONFIRM) && built && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2365
+ /* @__PURE__ */ jsx8(Summary, { built, currency }),
2366
+ /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginTop: 1, children: [
2367
+ /* @__PURE__ */ jsx8(
2368
+ StatusRow,
2369
+ {
2370
+ label: "Pre-flight",
2371
+ ok: built.report.ok,
2372
+ value: built.report.ok ? `${built.report.checks.length} checks passed` : `${built.report.blocking.length} blocking`,
2373
+ detail: built.report.ok ? "" : built.report.blocking.map((b) => b.name).join(", ")
2374
+ }
2375
+ ),
2376
+ /* @__PURE__ */ jsx8(
2377
+ StatusRow,
2378
+ {
2379
+ label: "Coverage",
2380
+ ok: coverageMissing === 0,
2381
+ value: `${built.report.coverage.length - coverageMissing} of ${built.report.coverage.length} fields resolved`,
2382
+ detail: coverageMissing ? "missing fields render blank in templates" : ""
2383
+ }
2384
+ ),
2385
+ /* @__PURE__ */ jsx8(
2386
+ StatusRow,
2387
+ {
2388
+ label: "Request",
2389
+ ok: Boolean(request),
2390
+ value: request ? `POST \xB7 ${built.body.length} bytes` : "no destination configured",
2391
+ detail: request ? truncate(request.url, 44) : "Setup \u2192 Webhook"
2392
+ }
2393
+ ),
2394
+ /* @__PURE__ */ jsx8(
2395
+ StatusRow,
2294
2396
  {
2295
- isDisabled: !built.report.ok,
2296
- onConfirm: doSend,
2297
- onCancel: () => onDone()
2397
+ label: "Clipboard",
2398
+ ok: copied?.ok,
2399
+ warn: !copied?.ok,
2400
+ value: copied?.ok ? `${copied.what} copied` : "not copied",
2401
+ detail: copied?.ok ? `via ${copied.via}` : "press c"
2298
2402
  }
2299
2403
  )
2300
2404
  ] }),
2301
- !built.report.ok && /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: " sending is disabled while pre-flight fails \u2014 fix the payload, or use the CLI with --force" })
2405
+ panel === "checks" && /* @__PURE__ */ jsx8(Panel, { title: "Pre-flight checks", children: /* @__PURE__ */ jsx8(CheckList, { checks: built.report.checks }) }),
2406
+ panel === "fields" && /* @__PURE__ */ jsx8(Panel, { title: "Field coverage", hint: "what the receiver will read", children: /* @__PURE__ */ jsx8(FieldTable, { coverage: built.report.coverage }) }),
2407
+ panel === "request" && /* @__PURE__ */ jsx8(Panel, { title: "Request", children: /* @__PURE__ */ jsx8(RequestPreview, { request, bytes: built.body.length }) }),
2408
+ panel === "curl" && curl && /* @__PURE__ */ jsx8(Panel, { title: "curl", hint: "Postman \u2192 Import \u2192 Raw text", children: /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: curl }) }),
2409
+ panel === "payload" && /* @__PURE__ */ jsx8(Panel, { title: "Payload", hint: `${built.body.length} bytes`, children: /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: JSON.stringify(built.payload, null, 2) }) }),
2410
+ !built.report.ok && /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Alert, { variant: "error", children: `cannot send \u2014 ${built.report.blocking.map((b) => b.detail).join("; ")}` }) }),
2411
+ /* @__PURE__ */ jsx8(
2412
+ CommandBar,
2413
+ {
2414
+ commands: [
2415
+ { key: "s", label: "send", disabled: !built.report.ok },
2416
+ { key: "c", label: "copy curl" },
2417
+ { key: "j", label: "copy json" },
2418
+ { key: "u", label: "curl", active: panel === "curl" },
2419
+ { key: "p", label: "payload", active: panel === "payload" },
2420
+ { key: "f", label: "fields", active: panel === "fields" },
2421
+ { key: "v", label: "checks", active: panel === "checks" },
2422
+ { key: "r", label: "request", active: panel === "request" },
2423
+ { key: "esc", label: "back" }
2424
+ ]
2425
+ }
2426
+ )
2302
2427
  ] }),
2303
- step === STEP.SENDING && /* @__PURE__ */ jsx7(Spinner, { label: "signing and POSTing the webhook\u2026" }),
2304
- step === STEP.RESULT && sendResult && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2305
- /* @__PURE__ */ jsxs7(Box7, { marginBottom: 1, children: [
2306
- sendResult.ok ? /* @__PURE__ */ jsx7(Badge, { color: "green", children: `HTTP ${sendResult.status}` }) : /* @__PURE__ */ jsx7(Badge, { color: "red", children: sendResult.error ? "FAILED" : `HTTP ${sendResult.status}` }),
2307
- /* @__PURE__ */ jsx7(Text7, { children: " " }),
2308
- /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: sendResult.error ?? explainStatus(sendResult.status) })
2428
+ step === STEP.SENDING && /* @__PURE__ */ jsx8(Spinner, { label: "signing and POSTing the webhook\u2026" }),
2429
+ step === STEP.RESULT && sendResult && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2430
+ /* @__PURE__ */ jsxs8(Box8, { marginBottom: 1, children: [
2431
+ sendResult.ok ? /* @__PURE__ */ jsx8(Badge, { color: "green", children: `HTTP ${sendResult.status}` }) : /* @__PURE__ */ jsx8(Badge, { color: "red", children: sendResult.error ? "FAILED" : `HTTP ${sendResult.status}` }),
2432
+ /* @__PURE__ */ jsx8(Text8, { children: " " }),
2433
+ /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: sendResult.error ?? explainStatus(sendResult.status) })
2309
2434
  ] }),
2310
- /* @__PURE__ */ jsx7(
2435
+ /* @__PURE__ */ jsx8(
2311
2436
  KeyValue,
2312
2437
  {
2313
2438
  rows: [
@@ -2320,22 +2445,22 @@ function Build({ config, providerId = "cashfree-occ", onDone }) {
2320
2445
  ]
2321
2446
  }
2322
2447
  ),
2323
- /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
2324
- /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: "reproduce:" }),
2325
- /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: sendResult.curl })
2448
+ /* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexDirection: "column", children: [
2449
+ /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "reproduce:" }),
2450
+ /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: sendResult.curl })
2326
2451
  ] }),
2327
- /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: "press enter to return to the menu" }) })
2452
+ /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "press enter to return to the menu" }) })
2328
2453
  ] }),
2329
- step === STEP.ERROR && error && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2330
- /* @__PURE__ */ jsx7(Alert, { variant: "error", children: error.message }),
2331
- error.hint ? /* @__PURE__ */ jsx7(Text7, { color: palette.warn, children: ` ${error.hint}` }) : null,
2332
- /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: "press enter to return to the menu" }) })
2454
+ step === STEP.ERROR && error && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2455
+ /* @__PURE__ */ jsx8(Alert, { variant: "error", children: error.message }),
2456
+ error.hint ? /* @__PURE__ */ jsx8(Text8, { color: palette.warn, children: ` ${error.hint}` }) : null,
2457
+ /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "press enter to return to the menu" }) })
2333
2458
  ] })
2334
2459
  ] });
2335
2460
  }
2336
2461
  function RequestPreview({ request, bytes: bytes2 }) {
2337
- if (!request) return /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: " destination not configured" });
2338
- return /* @__PURE__ */ jsx7(
2462
+ if (!request) return /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: " destination not configured" });
2463
+ return /* @__PURE__ */ jsx8(
2339
2464
  KeyValue,
2340
2465
  {
2341
2466
  keyWidth: 22,
@@ -2350,20 +2475,20 @@ function RequestPreview({ request, bytes: bytes2 }) {
2350
2475
  }
2351
2476
  function FieldPrompt({ field, index, total, value, onSubmit }) {
2352
2477
  const filled = Math.round(index / total * 30);
2353
- return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2354
- /* @__PURE__ */ jsxs7(Box7, { children: [
2355
- /* @__PURE__ */ jsx7(Text7, { color: palette.accent, children: "\u2588".repeat(filled) }),
2356
- /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: "\u2591".repeat(30 - filled) }),
2357
- /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: ` ${index + 1}/${total} ${field.group}` })
2478
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2479
+ /* @__PURE__ */ jsxs8(Box8, { children: [
2480
+ /* @__PURE__ */ jsx8(Text8, { color: palette.accent, children: "\u2588".repeat(filled) }),
2481
+ /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "\u2591".repeat(30 - filled) }),
2482
+ /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: ` ${index + 1}/${total} ${field.group}` })
2358
2483
  ] }),
2359
- /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
2360
- /* @__PURE__ */ jsx7(Text7, { bold: true, color: palette.heading, children: field.label }),
2361
- field.hint ? /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: ` ${field.hint}` }) : null,
2362
- field.optional ? /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: " optional" }) : null
2484
+ /* @__PURE__ */ jsxs8(Box8, { marginTop: 1, flexDirection: "column", children: [
2485
+ /* @__PURE__ */ jsx8(Text8, { bold: true, color: palette.heading, children: field.label }),
2486
+ field.hint ? /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: ` ${field.hint}` }) : null,
2487
+ field.optional ? /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: " optional" }) : null
2363
2488
  ] }),
2364
- /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, children: [
2365
- /* @__PURE__ */ jsx7(Text7, { color: palette.accent, children: "\u276F " }),
2366
- /* @__PURE__ */ jsx7(
2489
+ /* @__PURE__ */ jsxs8(Box8, { marginTop: 1, children: [
2490
+ /* @__PURE__ */ jsx8(Text8, { color: palette.accent, children: "\u276F " }),
2491
+ /* @__PURE__ */ jsx8(
2367
2492
  TextInput,
2368
2493
  {
2369
2494
  defaultValue: value == null ? "" : String(value),
@@ -2373,32 +2498,29 @@ function FieldPrompt({ field, index, total, value, onSubmit }) {
2373
2498
  field.path
2374
2499
  )
2375
2500
  ] }),
2376
- /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text7, { color: palette.dim, children: "enter accepts the suggestion \xB7 edit the text to change it" }) })
2501
+ /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "enter accepts the suggestion \xB7 edit the text to change it \xB7 esc goes back a field" }) })
2377
2502
  ] });
2378
2503
  }
2379
2504
  function Summary({ built, currency }) {
2380
- const d = built.payload.data;
2381
- return /* @__PURE__ */ jsx7(Box7, { flexDirection: "column", borderStyle: "round", borderColor: palette.ok, paddingX: 1, children: /* @__PURE__ */ jsx7(
2382
- KeyValue,
2383
- {
2384
- rows: [
2385
- ["type", built.payload.type],
2386
- ["store", d.store_url],
2387
- ["customer", `${d.customer.shipping_address.customer_name} \xB7 ${d.phone}`],
2388
- ["items", d.line_items.map((i) => `${truncate(i.name, 28)} \xD7${i.quantity}`).join(", ")],
2389
- ["total", `${money(d.total_price, d.line_items[0]?.currency ?? currency)} (was ${money(d.original_total_price)} \xB7 discount ${money(d.total_discount)})`],
2390
- ["checkout", truncate(d.abandoned_checkout_url, 58)],
2391
- ["saved", built.file]
2392
- ]
2393
- }
2394
- ) });
2505
+ const s = built.summary ?? (built.provider.summarize ? built.provider.summarize(built.payload) : {});
2506
+ const rows = [
2507
+ ["provider", built.provider.label],
2508
+ ["event", s.event ?? "\u2014"],
2509
+ ["store", s.store ?? "\u2014"],
2510
+ ["customer", s.customer || "\u2014"],
2511
+ ["items", s.items || "\u2014"],
2512
+ ["total", s.total == null ? "\u2014" : `${money(s.total, s.currency ?? currency)}${s.extra ? ` (${s.extra})` : ""}`]
2513
+ ];
2514
+ if (s.link) rows.push(["link", truncate(s.link, 58)]);
2515
+ rows.push(["saved", built.file]);
2516
+ return /* @__PURE__ */ jsx8(Box8, { flexDirection: "column", borderStyle: "round", borderColor: palette.ok, paddingX: 1, children: /* @__PURE__ */ jsx8(KeyValue, { rows }) });
2395
2517
  }
2396
2518
 
2397
2519
  // src/ui/screens/Configure.jsx
2398
- import React8, { useState as useState2 } from "react";
2399
- import { Box as Box8, Text as Text8, useInput as useInput4 } from "ink";
2520
+ import React9, { useState as useState2 } from "react";
2521
+ import { Box as Box9, Text as Text9, useInput as useInput4 } from "ink";
2400
2522
  import { Spinner as Spinner2, TextInput as TextInput2, PasswordInput, Select as Select5, Alert as Alert2 } from "@inkjs/ui";
2401
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
2523
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
2402
2524
  var FIELDS = [
2403
2525
  { group: "Customer", key: "customer.firstName", label: "First name", placeholder: "Test" },
2404
2526
  { group: "Customer", key: "customer.lastName", label: "Last name", placeholder: "Shopper" },
@@ -2473,9 +2595,9 @@ function Configure({ config, section: initialSection, onDone }) {
2473
2595
  });
2474
2596
  };
2475
2597
  if (!section) {
2476
- return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2477
- /* @__PURE__ */ jsx8(Header, { title: "Configure", subtitle: "pick what you want to change", right: "esc to go back" }),
2478
- /* @__PURE__ */ jsx8(
2598
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2599
+ /* @__PURE__ */ jsx9(Header, { title: "Configure", subtitle: "pick what you want to change", right: "esc to go back" }),
2600
+ /* @__PURE__ */ jsx9(
2479
2601
  Select5,
2480
2602
  {
2481
2603
  visibleOptionCount: 8,
@@ -2492,29 +2614,29 @@ function Configure({ config, section: initialSection, onDone }) {
2492
2614
  ] });
2493
2615
  }
2494
2616
  if (phase === "verifying") {
2495
- return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2496
- /* @__PURE__ */ jsx8(Header, { title: "Configure", subtitle: "verifying credentials" }),
2497
- /* @__PURE__ */ jsx8(Spinner2, { label: "contacting Shopify\u2026" })
2617
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2618
+ /* @__PURE__ */ jsx9(Header, { title: "Configure", subtitle: "verifying credentials" }),
2619
+ /* @__PURE__ */ jsx9(Spinner2, { label: "contacting Shopify\u2026" })
2498
2620
  ] });
2499
2621
  }
2500
2622
  if (phase === "done") {
2501
- return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2502
- /* @__PURE__ */ jsx8(Header, { title: "Configure", subtitle: "saved" }),
2503
- /* @__PURE__ */ jsx8(Alert2, { variant: verifyMsg?.ok ? "success" : "warning", children: verifyMsg?.text ?? "saved" }),
2504
- verifyMsg?.hint ? /* @__PURE__ */ jsx8(Text8, { color: palette.warn, children: ` ${verifyMsg.hint}` }) : null,
2505
- /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: `config written to ${verifyMsg?.file} (chmod 600)` }) }),
2506
- /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "press enter to return to the menu" }) })
2623
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2624
+ /* @__PURE__ */ jsx9(Header, { title: "Configure", subtitle: "saved" }),
2625
+ /* @__PURE__ */ jsx9(Alert2, { variant: verifyMsg?.ok ? "success" : "warning", children: verifyMsg?.text ?? "saved" }),
2626
+ verifyMsg?.hint ? /* @__PURE__ */ jsx9(Text9, { color: palette.warn, children: ` ${verifyMsg.hint}` }) : null,
2627
+ /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text9, { color: palette.dim, children: `config written to ${verifyMsg?.file} (chmod 600)` }) }),
2628
+ /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text9, { color: palette.dim, children: "press enter to return to the menu" }) })
2507
2629
  ] });
2508
2630
  }
2509
2631
  const current = get(draft, field.key) ?? "";
2510
- return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2511
- /* @__PURE__ */ jsx8(Header, { title: "Configure", subtitle: `${field.group} \xB7 step ${index + 1} of ${fields.length}`, right: "esc to cancel" }),
2512
- /* @__PURE__ */ jsx8(Progress, { index, total: fields.length }),
2513
- /* @__PURE__ */ jsxs8(Section, { title: field.label, children: [
2514
- field.hint ? /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: ` ${field.hint}` }) : null,
2515
- /* @__PURE__ */ jsxs8(Box8, { marginTop: 1, children: [
2516
- /* @__PURE__ */ jsx8(Text8, { color: palette.accent, children: `${glyph.pointer} ` }),
2517
- field.type === "select" ? /* @__PURE__ */ jsx8(
2632
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2633
+ /* @__PURE__ */ jsx9(Header, { title: "Configure", subtitle: `${field.group} \xB7 step ${index + 1} of ${fields.length}`, right: "esc to cancel" }),
2634
+ /* @__PURE__ */ jsx9(Progress, { index, total: fields.length }),
2635
+ /* @__PURE__ */ jsxs9(Section, { title: field.label, children: [
2636
+ field.hint ? /* @__PURE__ */ jsx9(Text9, { color: palette.dim, children: ` ${field.hint}` }) : null,
2637
+ /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
2638
+ /* @__PURE__ */ jsx9(Text9, { color: palette.accent, children: `${glyph.pointer} ` }),
2639
+ field.type === "select" ? /* @__PURE__ */ jsx9(
2518
2640
  Select5,
2519
2641
  {
2520
2642
  options: field.options,
@@ -2522,7 +2644,7 @@ function Configure({ config, section: initialSection, onDone }) {
2522
2644
  onChange: commit
2523
2645
  },
2524
2646
  field.key
2525
- ) : field.secret ? /* @__PURE__ */ jsx8(PasswordInput, { placeholder: current ? mask(current) : "\u2022\u2022\u2022\u2022\u2022\u2022", onSubmit: (v) => commit(v || current) }, field.key) : /* @__PURE__ */ jsx8(
2647
+ ) : field.secret ? /* @__PURE__ */ jsx9(PasswordInput, { placeholder: current ? mask(current) : "\u2022\u2022\u2022\u2022\u2022\u2022", onSubmit: (v) => commit(v || current) }, field.key) : /* @__PURE__ */ jsx9(
2526
2648
  TextInput2,
2527
2649
  {
2528
2650
  defaultValue: current,
@@ -2537,18 +2659,18 @@ function Configure({ config, section: initialSection, onDone }) {
2537
2659
  }
2538
2660
  function Progress({ index, total }) {
2539
2661
  const filled = Math.round(index / total * 30);
2540
- return /* @__PURE__ */ jsxs8(Box8, { children: [
2541
- /* @__PURE__ */ jsx8(Text8, { color: palette.accent, children: "\u2588".repeat(filled) }),
2542
- /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: "\u2591".repeat(30 - filled) }),
2543
- /* @__PURE__ */ jsx8(Text8, { color: palette.dim, children: ` ${index}/${total}` })
2662
+ return /* @__PURE__ */ jsxs9(Box9, { children: [
2663
+ /* @__PURE__ */ jsx9(Text9, { color: palette.accent, children: "\u2588".repeat(filled) }),
2664
+ /* @__PURE__ */ jsx9(Text9, { color: palette.dim, children: "\u2591".repeat(30 - filled) }),
2665
+ /* @__PURE__ */ jsx9(Text9, { color: palette.dim, children: ` ${index}/${total}` })
2544
2666
  ] });
2545
2667
  }
2546
2668
 
2547
2669
  // src/ui/screens/ConnectShopify.jsx
2548
- import React9, { useState as useState3 } from "react";
2549
- import { Box as Box9, Text as Text9, useInput as useInput5 } from "ink";
2670
+ import React10, { useState as useState3 } from "react";
2671
+ import { Box as Box10, Text as Text10, useInput as useInput5 } from "ink";
2550
2672
  import { Spinner as Spinner3, TextInput as TextInput3, PasswordInput as PasswordInput2, Alert as Alert3, Badge as Badge2 } from "@inkjs/ui";
2551
- import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
2673
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
2552
2674
  var STEP2 = { DOMAIN: "domain", TOKEN: "token", VERIFY: "verify", DONE: "done", FAILED: "failed" };
2553
2675
  function ConnectShopify({ config, onDone }) {
2554
2676
  const [draft] = useState3(() => structuredClone(config));
@@ -2579,13 +2701,13 @@ function ConnectShopify({ config, onDone }) {
2579
2701
  setStep(STEP2.FAILED);
2580
2702
  });
2581
2703
  };
2582
- return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2583
- /* @__PURE__ */ jsx9(Header, { title: "Connect Shopify", subtitle: "the catalogue every payload is built from", right: "esc to cancel" }),
2584
- step === STEP2.DOMAIN && /* @__PURE__ */ jsxs9(Section, { title: "Store domain", children: [
2585
- /* @__PURE__ */ jsx9(Text9, { color: palette.dim, children: " the myshopify.com domain, not your custom domain" }),
2586
- /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
2587
- /* @__PURE__ */ jsx9(Text9, { color: palette.accent, children: `${glyph.pointer} ` }),
2588
- /* @__PURE__ */ jsx9(
2704
+ return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
2705
+ /* @__PURE__ */ jsx10(Header, { title: "Connect Shopify", subtitle: "the catalogue every payload is built from", right: "esc to cancel" }),
2706
+ step === STEP2.DOMAIN && /* @__PURE__ */ jsxs10(Section, { title: "Store domain", children: [
2707
+ /* @__PURE__ */ jsx10(Text10, { color: palette.dim, children: " the myshopify.com domain, not your custom domain" }),
2708
+ /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
2709
+ /* @__PURE__ */ jsx10(Text10, { color: palette.accent, children: `${glyph.pointer} ` }),
2710
+ /* @__PURE__ */ jsx10(
2589
2711
  TextInput3,
2590
2712
  {
2591
2713
  defaultValue: draft.shopify.domain,
@@ -2595,12 +2717,12 @@ function ConnectShopify({ config, onDone }) {
2595
2717
  )
2596
2718
  ] })
2597
2719
  ] }),
2598
- step === STEP2.TOKEN && /* @__PURE__ */ jsxs9(Section, { title: "Admin API access token", children: [
2599
- /* @__PURE__ */ jsx9(Text9, { color: palette.dim, children: " Shopify admin \u2192 Settings \u2192 Apps and sales channels \u2192 Develop apps" }),
2600
- /* @__PURE__ */ jsx9(Text9, { color: palette.dim, children: " the token needs the read_products scope" }),
2601
- /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, children: [
2602
- /* @__PURE__ */ jsx9(Text9, { color: palette.accent, children: `${glyph.pointer} ` }),
2603
- /* @__PURE__ */ jsx9(
2720
+ step === STEP2.TOKEN && /* @__PURE__ */ jsxs10(Section, { title: "Admin API access token", children: [
2721
+ /* @__PURE__ */ jsx10(Text10, { color: palette.dim, children: " Shopify admin \u2192 Settings \u2192 Apps and sales channels \u2192 Develop apps" }),
2722
+ /* @__PURE__ */ jsx10(Text10, { color: palette.dim, children: " the token needs the read_products scope" }),
2723
+ /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
2724
+ /* @__PURE__ */ jsx10(Text10, { color: palette.accent, children: `${glyph.pointer} ` }),
2725
+ /* @__PURE__ */ jsx10(
2604
2726
  PasswordInput2,
2605
2727
  {
2606
2728
  placeholder: draft.shopify.accessToken ? mask(draft.shopify.accessToken) : "shpat_\u2026",
@@ -2609,14 +2731,14 @@ function ConnectShopify({ config, onDone }) {
2609
2731
  )
2610
2732
  ] })
2611
2733
  ] }),
2612
- step === STEP2.VERIFY && /* @__PURE__ */ jsx9(Spinner3, { label: `connecting to ${draft.shopify.domain}\u2026` }),
2613
- step === STEP2.DONE && result && /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2614
- /* @__PURE__ */ jsxs9(Box9, { marginBottom: 1, children: [
2615
- /* @__PURE__ */ jsx9(Badge2, { color: "green", children: "CONNECTED" }),
2616
- /* @__PURE__ */ jsx9(Text9, { children: " " }),
2617
- /* @__PURE__ */ jsx9(Text9, { bold: true, children: result.shop?.name })
2734
+ step === STEP2.VERIFY && /* @__PURE__ */ jsx10(Spinner3, { label: `connecting to ${draft.shopify.domain}\u2026` }),
2735
+ step === STEP2.DONE && result && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
2736
+ /* @__PURE__ */ jsxs10(Box10, { marginBottom: 1, children: [
2737
+ /* @__PURE__ */ jsx10(Badge2, { color: "green", children: "CONNECTED" }),
2738
+ /* @__PURE__ */ jsx10(Text10, { children: " " }),
2739
+ /* @__PURE__ */ jsx10(Text10, { bold: true, children: result.shop?.name })
2618
2740
  ] }),
2619
- /* @__PURE__ */ jsx9(Box9, { flexDirection: "column", borderStyle: "round", borderColor: palette.ok, paddingX: 1, children: /* @__PURE__ */ jsx9(
2741
+ /* @__PURE__ */ jsx10(Box10, { flexDirection: "column", borderStyle: "round", borderColor: palette.ok, paddingX: 1, children: /* @__PURE__ */ jsx10(
2620
2742
  KeyValue,
2621
2743
  {
2622
2744
  keyWidth: 16,
@@ -2632,29 +2754,29 @@ function ConnectShopify({ config, onDone }) {
2632
2754
  ]
2633
2755
  }
2634
2756
  ) }),
2635
- result.applied.length ? /* @__PURE__ */ jsx9(Section, { title: "Picked up from the store", children: result.applied.map((line, i) => /* @__PURE__ */ jsx9(Text9, { color: palette.dim, children: ` ${glyph.tick} ${line}` }, i)) }) : null,
2636
- /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx9(Alert3, { variant: "success", children: "Shopify connected \u2014 you can browse the real catalogue now" }) }),
2637
- /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text9, { color: palette.dim, children: "press enter to continue" }) })
2757
+ result.applied.length ? /* @__PURE__ */ jsx10(Section, { title: "Picked up from the store", children: result.applied.map((line, i) => /* @__PURE__ */ jsx10(Text10, { color: palette.dim, children: ` ${glyph.tick} ${line}` }, i)) }) : null,
2758
+ /* @__PURE__ */ jsx10(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx10(Alert3, { variant: "success", children: "Shopify connected \u2014 you can browse the real catalogue now" }) }),
2759
+ /* @__PURE__ */ jsx10(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text10, { color: palette.dim, children: "press enter to continue" }) })
2638
2760
  ] }),
2639
- step === STEP2.FAILED && error && /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2640
- /* @__PURE__ */ jsx9(Alert3, { variant: "error", children: error.message }),
2641
- error.hint ? /* @__PURE__ */ jsx9(Text9, { color: palette.warn, children: ` ${error.hint}` }) : null,
2642
- /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, flexDirection: "column", children: [
2643
- /* @__PURE__ */ jsx9(Text9, { color: palette.dim, children: " common causes:" }),
2644
- /* @__PURE__ */ jsx9(Text9, { color: palette.dim, children: " \xB7 the token is missing the read_products scope" }),
2645
- /* @__PURE__ */ jsx9(Text9, { color: palette.dim, children: " \xB7 the token belongs to a different store" }),
2646
- /* @__PURE__ */ jsx9(Text9, { color: palette.dim, children: " \xB7 the domain is the custom domain, not the .myshopify.com one" })
2761
+ step === STEP2.FAILED && error && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
2762
+ /* @__PURE__ */ jsx10(Alert3, { variant: "error", children: error.message }),
2763
+ error.hint ? /* @__PURE__ */ jsx10(Text10, { color: palette.warn, children: ` ${error.hint}` }) : null,
2764
+ /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, flexDirection: "column", children: [
2765
+ /* @__PURE__ */ jsx10(Text10, { color: palette.dim, children: " common causes:" }),
2766
+ /* @__PURE__ */ jsx10(Text10, { color: palette.dim, children: " \xB7 the token is missing the read_products scope" }),
2767
+ /* @__PURE__ */ jsx10(Text10, { color: palette.dim, children: " \xB7 the token belongs to a different store" }),
2768
+ /* @__PURE__ */ jsx10(Text10, { color: palette.dim, children: " \xB7 the domain is the custom domain, not the .myshopify.com one" })
2647
2769
  ] }),
2648
- /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text9, { color: palette.dim, children: "press enter to try again" }) })
2770
+ /* @__PURE__ */ jsx10(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text10, { color: palette.dim, children: "press enter to try again" }) })
2649
2771
  ] })
2650
2772
  ] });
2651
2773
  }
2652
2774
 
2653
2775
  // src/ui/screens/Webhook.jsx
2654
- import React10, { useState as useState4 } from "react";
2655
- import { Box as Box10, Text as Text10, useInput as useInput6 } from "ink";
2776
+ import React11, { useState as useState4 } from "react";
2777
+ import { Box as Box11, Text as Text11, useInput as useInput6 } from "ink";
2656
2778
  import { Select as Select6, TextInput as TextInput4, PasswordInput as PasswordInput3, Alert as Alert4, Badge as Badge3, Spinner as Spinner4 } from "@inkjs/ui";
2657
- import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
2779
+ import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
2658
2780
  var STEP3 = { PICK: "pick", URL: "url", SECRET: "secret", PROBE: "probe", DONE: "done" };
2659
2781
  function Webhook({ config, onDone }) {
2660
2782
  const [draft] = useState4(() => structuredClone(config));
@@ -2704,9 +2826,9 @@ function Webhook({ config, onDone }) {
2704
2826
  }),
2705
2827
  { label: "Back".padEnd(30), value: "__back" }
2706
2828
  ];
2707
- return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
2708
- /* @__PURE__ */ jsx10(Header, { title: "Webhook destinations", subtitle: "one endpoint and secret per integration", right: "esc to go back" }),
2709
- /* @__PURE__ */ jsx10(
2829
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
2830
+ /* @__PURE__ */ jsx11(Header, { title: "Webhook destinations", subtitle: "one endpoint and secret per integration", right: "esc to go back" }),
2831
+ /* @__PURE__ */ jsx11(
2710
2832
  Select6,
2711
2833
  {
2712
2834
  visibleOptionCount: options.length,
@@ -2719,17 +2841,17 @@ function Webhook({ config, onDone }) {
2719
2841
  }
2720
2842
  }
2721
2843
  ),
2722
- /* @__PURE__ */ jsx10(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text10, { color: palette.dim, children: `${glyph.dot} set globally \u2014 every build for that provider uses it` }) })
2844
+ /* @__PURE__ */ jsx11(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text11, { color: palette.dim, children: `${glyph.dot} set globally \u2014 every build for that provider uses it` }) })
2723
2845
  ] });
2724
2846
  }
2725
- return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
2726
- /* @__PURE__ */ jsx10(Header, { title: meta.label, subtitle: `signature: ${meta.signature}`, right: "esc to cancel" }),
2727
- step === STEP3.URL && /* @__PURE__ */ jsxs10(Section, { title: "Webhook URL", children: [
2728
- /* @__PURE__ */ jsx10(Text10, { color: palette.dim, children: " the full endpoint the provider would call \u2014 paste it as-is" }),
2729
- urlError ? /* @__PURE__ */ jsx10(Text10, { color: palette.bad, children: ` ${glyph.cross} ${urlError}` }) : null,
2730
- /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
2731
- /* @__PURE__ */ jsx10(Text10, { color: palette.accent, children: `${glyph.pointer} ` }),
2732
- /* @__PURE__ */ jsx10(
2847
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
2848
+ /* @__PURE__ */ jsx11(Header, { title: meta.label, subtitle: `signature: ${meta.signature}`, right: "esc to cancel" }),
2849
+ step === STEP3.URL && /* @__PURE__ */ jsxs11(Section, { title: "Webhook URL", children: [
2850
+ /* @__PURE__ */ jsx11(Text11, { color: palette.dim, children: " the full endpoint the provider would call \u2014 paste it as-is" }),
2851
+ urlError ? /* @__PURE__ */ jsx11(Text11, { color: palette.bad, children: ` ${glyph.cross} ${urlError}` }) : null,
2852
+ /* @__PURE__ */ jsxs11(Box11, { marginTop: 1, children: [
2853
+ /* @__PURE__ */ jsx11(Text11, { color: palette.accent, children: `${glyph.pointer} ` }),
2854
+ /* @__PURE__ */ jsx11(
2733
2855
  TextInput4,
2734
2856
  {
2735
2857
  defaultValue: target.webhookUrl,
@@ -2739,12 +2861,12 @@ function Webhook({ config, onDone }) {
2739
2861
  )
2740
2862
  ] })
2741
2863
  ] }),
2742
- step === STEP3.SECRET && /* @__PURE__ */ jsxs10(Section, { title: meta.id === "nitro" ? "Bearer token" : "Signing secret", children: [
2743
- /* @__PURE__ */ jsx10(Text10, { color: palette.dim, children: ` sent as ${meta.header}` }),
2744
- /* @__PURE__ */ jsx10(Text10, { color: palette.dim, children: " must match what the receiver has stored" }),
2745
- /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
2746
- /* @__PURE__ */ jsx10(Text10, { color: palette.accent, children: `${glyph.pointer} ` }),
2747
- /* @__PURE__ */ jsx10(
2864
+ step === STEP3.SECRET && /* @__PURE__ */ jsxs11(Section, { title: meta.id === "nitro" ? "Bearer token" : "Signing secret", children: [
2865
+ /* @__PURE__ */ jsx11(Text11, { color: palette.dim, children: ` sent as ${meta.header}` }),
2866
+ /* @__PURE__ */ jsx11(Text11, { color: palette.dim, children: " must match what the receiver has stored" }),
2867
+ /* @__PURE__ */ jsxs11(Box11, { marginTop: 1, children: [
2868
+ /* @__PURE__ */ jsx11(Text11, { color: palette.accent, children: `${glyph.pointer} ` }),
2869
+ /* @__PURE__ */ jsx11(
2748
2870
  PasswordInput3,
2749
2871
  {
2750
2872
  placeholder: target.webhookSecret ? mask(target.webhookSecret) : "the signing secret\u2026",
@@ -2753,14 +2875,14 @@ function Webhook({ config, onDone }) {
2753
2875
  )
2754
2876
  ] })
2755
2877
  ] }),
2756
- step === STEP3.PROBE && /* @__PURE__ */ jsx10(Spinner4, { label: "checking the endpoint is reachable\u2026" }),
2757
- step === STEP3.DONE && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
2758
- /* @__PURE__ */ jsxs10(Box10, { marginBottom: 1, children: [
2759
- /* @__PURE__ */ jsx10(Badge3, { color: probe?.reachable ? "green" : "yellow", children: probe?.reachable ? "REACHABLE" : "UNVERIFIED" }),
2760
- /* @__PURE__ */ jsx10(Text10, { children: " " }),
2761
- /* @__PURE__ */ jsx10(Text10, { color: palette.dim, children: probe?.reachable ? `responded HTTP ${probe.status} to an unsigned probe` : probe?.error ?? "could not reach it \u2014 saved anyway" })
2878
+ step === STEP3.PROBE && /* @__PURE__ */ jsx11(Spinner4, { label: "checking the endpoint is reachable\u2026" }),
2879
+ step === STEP3.DONE && /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
2880
+ /* @__PURE__ */ jsxs11(Box11, { marginBottom: 1, children: [
2881
+ /* @__PURE__ */ jsx11(Badge3, { color: probe?.reachable ? "green" : "yellow", children: probe?.reachable ? "REACHABLE" : "UNVERIFIED" }),
2882
+ /* @__PURE__ */ jsx11(Text11, { children: " " }),
2883
+ /* @__PURE__ */ jsx11(Text11, { color: palette.dim, children: probe?.reachable ? `responded HTTP ${probe.status} to an unsigned probe` : probe?.error ?? "could not reach it \u2014 saved anyway" })
2762
2884
  ] }),
2763
- /* @__PURE__ */ jsx10(Box10, { flexDirection: "column", borderStyle: "round", borderColor: palette.ok, paddingX: 1, children: /* @__PURE__ */ jsx10(
2885
+ /* @__PURE__ */ jsx11(Box11, { flexDirection: "column", borderStyle: "round", borderColor: palette.ok, paddingX: 1, children: /* @__PURE__ */ jsx11(
2764
2886
  KeyValue,
2765
2887
  {
2766
2888
  keyWidth: 10,
@@ -2771,8 +2893,8 @@ function Webhook({ config, onDone }) {
2771
2893
  ]
2772
2894
  }
2773
2895
  ) }),
2774
- !meta.available ? /* @__PURE__ */ jsx10(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx10(Alert4, { variant: "info", children: `saved \u2014 ${meta.label} payload generation is not implemented yet` }) }) : null,
2775
- /* @__PURE__ */ jsx10(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text10, { color: palette.dim, children: "press enter to configure another" }) })
2896
+ !meta.available ? /* @__PURE__ */ jsx11(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx11(Alert4, { variant: "info", children: `saved \u2014 ${meta.label} payload generation is not implemented yet` }) }) : null,
2897
+ /* @__PURE__ */ jsx11(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text11, { color: palette.dim, children: "press enter to configure another" }) })
2776
2898
  ] })
2777
2899
  ] });
2778
2900
  }
@@ -2795,10 +2917,10 @@ async function probeEndpoint(url) {
2795
2917
  }
2796
2918
 
2797
2919
  // src/ui/screens/Doctor.jsx
2798
- import React11, { useEffect as useEffect2, useState as useState5 } from "react";
2799
- import { Box as Box11, Text as Text11, useInput as useInput7 } from "ink";
2920
+ import React12, { useEffect as useEffect2, useState as useState5 } from "react";
2921
+ import { Box as Box12, Text as Text12, useInput as useInput7 } from "ink";
2800
2922
  import { Spinner as Spinner5 } from "@inkjs/ui";
2801
- import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
2923
+ import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
2802
2924
  function Doctor({ config, onDone }) {
2803
2925
  const [checks, setChecks] = useState5(null);
2804
2926
  useInput7((input, key) => {
@@ -2811,13 +2933,13 @@ function Doctor({ config, onDone }) {
2811
2933
  alive = false;
2812
2934
  };
2813
2935
  }, []);
2814
- return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
2815
- /* @__PURE__ */ jsx11(Header, { title: "Doctor", subtitle: "everything the generator depends on" }),
2816
- !checks ? /* @__PURE__ */ jsx11(Spinner5, { label: "running checks\u2026" }) : /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
2817
- /* @__PURE__ */ jsx11(Section, { title: "Configuration", children: /* @__PURE__ */ jsx11(CheckList, { checks: checks.config }) }),
2818
- /* @__PURE__ */ jsx11(Section, { title: "Connectivity", children: /* @__PURE__ */ jsx11(CheckList, { checks: checks.connectivity }) }),
2819
- /* @__PURE__ */ jsx11(Section, { title: "Runtime", children: /* @__PURE__ */ jsx11(CheckList, { checks: checks.runtime }) }),
2820
- /* @__PURE__ */ jsx11(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text11, { color: palette.dim, children: "press enter to return to the menu" }) })
2936
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
2937
+ /* @__PURE__ */ jsx12(Header, { title: "Doctor", subtitle: "everything the generator depends on" }),
2938
+ !checks ? /* @__PURE__ */ jsx12(Spinner5, { label: "running checks\u2026" }) : /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
2939
+ /* @__PURE__ */ jsx12(Section, { title: "Configuration", children: /* @__PURE__ */ jsx12(CheckList, { checks: checks.config }) }),
2940
+ /* @__PURE__ */ jsx12(Section, { title: "Connectivity", children: /* @__PURE__ */ jsx12(CheckList, { checks: checks.connectivity }) }),
2941
+ /* @__PURE__ */ jsx12(Section, { title: "Runtime", children: /* @__PURE__ */ jsx12(CheckList, { checks: checks.runtime }) }),
2942
+ /* @__PURE__ */ jsx12(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx12(Text12, { color: palette.dim, children: "press enter to return to the menu" }) })
2821
2943
  ] })
2822
2944
  ] });
2823
2945
  }
@@ -2865,10 +2987,10 @@ async function run(config) {
2865
2987
  }
2866
2988
 
2867
2989
  // src/ui/screens/History.jsx
2868
- import React12, { useState as useState6 } from "react";
2869
- import { Box as Box12, Text as Text12, useInput as useInput8 } from "ink";
2990
+ import React13, { useState as useState6 } from "react";
2991
+ import { Box as Box13, Text as Text13, useInput as useInput8 } from "ink";
2870
2992
  import { Select as Select7, Spinner as Spinner6, Badge as Badge4, Alert as Alert5, ConfirmInput as ConfirmInput2 } from "@inkjs/ui";
2871
- import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
2993
+ import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
2872
2994
  function History({ config, onDone }) {
2873
2995
  const [items] = useState6(() => listPayloads(20));
2874
2996
  const [selected, setSelected] = useState6(null);
@@ -2894,14 +3016,14 @@ function History({ config, onDone }) {
2894
3016
  });
2895
3017
  };
2896
3018
  if (!items.length) {
2897
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
2898
- /* @__PURE__ */ jsx12(Header, { title: "History", subtitle: "saved payloads" }),
2899
- /* @__PURE__ */ jsx12(Text12, { color: palette.dim, children: "nothing built yet \u2014 press esc to go back" })
3019
+ return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
3020
+ /* @__PURE__ */ jsx13(Header, { title: "History", subtitle: "saved payloads" }),
3021
+ /* @__PURE__ */ jsx13(Text13, { color: palette.dim, children: "nothing built yet \u2014 press esc to go back" })
2900
3022
  ] });
2901
3023
  }
2902
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
2903
- /* @__PURE__ */ jsx12(Header, { title: "History", subtitle: `${items.length} saved payload${items.length === 1 ? "" : "s"}`, right: "esc to go back" }),
2904
- phase === "list" && /* @__PURE__ */ jsx12(
3024
+ return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
3025
+ /* @__PURE__ */ jsx13(Header, { title: "History", subtitle: `${items.length} saved payload${items.length === 1 ? "" : "s"}`, right: "esc to go back" }),
3026
+ phase === "list" && /* @__PURE__ */ jsx13(
2905
3027
  Select7,
2906
3028
  {
2907
3029
  visibleOptionCount: 10,
@@ -2912,8 +3034,8 @@ function History({ config, onDone }) {
2912
3034
  onChange: onPick
2913
3035
  }
2914
3036
  ),
2915
- phase === "detail" && selected && /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
2916
- /* @__PURE__ */ jsx12(Section, { title: "Payload", children: /* @__PURE__ */ jsx12(
3037
+ phase === "detail" && selected && /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
3038
+ /* @__PURE__ */ jsx13(Section, { title: "Payload", children: /* @__PURE__ */ jsx13(
2917
3039
  KeyValue,
2918
3040
  {
2919
3041
  rows: [
@@ -2927,31 +3049,31 @@ function History({ config, onDone }) {
2927
3049
  ]
2928
3050
  }
2929
3051
  ) }),
2930
- /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, children: [
2931
- /* @__PURE__ */ jsx12(Text12, { children: "Re-send this payload (it will be re-signed with a fresh timestamp)? " }),
2932
- /* @__PURE__ */ jsx12(ConfirmInput2, { onConfirm: resend, onCancel: () => setPhase("list") })
3052
+ /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, children: [
3053
+ /* @__PURE__ */ jsx13(Text13, { children: "Re-send this payload (it will be re-signed with a fresh timestamp)? " }),
3054
+ /* @__PURE__ */ jsx13(ConfirmInput2, { onConfirm: resend, onCancel: () => setPhase("list") })
2933
3055
  ] })
2934
3056
  ] }),
2935
- phase === "sending" && /* @__PURE__ */ jsx12(Spinner6, { label: "re-signing and sending\u2026" }),
2936
- phase === "result" && result && /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
2937
- /* @__PURE__ */ jsxs12(Box12, { marginBottom: 1, children: [
2938
- /* @__PURE__ */ jsx12(Badge4, { color: result.ok ? "green" : "red", children: result.error ? "FAILED" : `HTTP ${result.status}` }),
2939
- /* @__PURE__ */ jsx12(Text12, { children: " " }),
2940
- /* @__PURE__ */ jsx12(Text12, { color: palette.dim, children: result.error ?? explainStatus(result.status) })
3057
+ phase === "sending" && /* @__PURE__ */ jsx13(Spinner6, { label: "re-signing and sending\u2026" }),
3058
+ phase === "result" && result && /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
3059
+ /* @__PURE__ */ jsxs13(Box13, { marginBottom: 1, children: [
3060
+ /* @__PURE__ */ jsx13(Badge4, { color: result.ok ? "green" : "red", children: result.error ? "FAILED" : `HTTP ${result.status}` }),
3061
+ /* @__PURE__ */ jsx13(Text13, { children: " " }),
3062
+ /* @__PURE__ */ jsx13(Text13, { color: palette.dim, children: result.error ?? explainStatus(result.status) })
2941
3063
  ] }),
2942
- /* @__PURE__ */ jsx12(Text12, { color: palette.dim, children: "press enter to return" })
3064
+ /* @__PURE__ */ jsx13(Text13, { color: palette.dim, children: "press enter to return" })
2943
3065
  ] }),
2944
- phase === "error" && error && /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
2945
- /* @__PURE__ */ jsx12(Alert5, { variant: "error", children: error.message }),
2946
- error.hint ? /* @__PURE__ */ jsx12(Text12, { color: palette.warn, children: ` ${error.hint}` }) : null,
2947
- /* @__PURE__ */ jsx12(Text12, { color: palette.dim, children: "press enter to return" })
3066
+ phase === "error" && error && /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
3067
+ /* @__PURE__ */ jsx13(Alert5, { variant: "error", children: error.message }),
3068
+ error.hint ? /* @__PURE__ */ jsx13(Text13, { color: palette.warn, children: ` ${error.hint}` }) : null,
3069
+ /* @__PURE__ */ jsx13(Text13, { color: palette.dim, children: "press enter to return" })
2948
3070
  ] })
2949
3071
  ] });
2950
3072
  }
2951
3073
 
2952
3074
  // src/ui/screens/Clear.jsx
2953
- import React13, { useState as useState7 } from "react";
2954
- import { Box as Box13, Text as Text13, useInput as useInput9 } from "ink";
3075
+ import React14, { useState as useState7 } from "react";
3076
+ import { Box as Box14, Text as Text14, useInput as useInput9 } from "ink";
2955
3077
  import { Select as Select8, ConfirmInput as ConfirmInput3, Alert as Alert6, Badge as Badge5 } from "@inkjs/ui";
2956
3078
 
2957
3079
  // src/core/cleanup.mjs
@@ -3027,7 +3149,7 @@ var TARGETS = {
3027
3149
  };
3028
3150
 
3029
3151
  // src/ui/screens/Clear.jsx
3030
- import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
3152
+ import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
3031
3153
  function Clear({ config, onDone }) {
3032
3154
  const [state] = useState7(() => inspect());
3033
3155
  const [choice, setChoice] = useState7(null);
@@ -3041,23 +3163,23 @@ function Clear({ config, onDone }) {
3041
3163
  setResult(outcome);
3042
3164
  };
3043
3165
  if (result) {
3044
- return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
3045
- /* @__PURE__ */ jsx13(Header, { title: "Clear", subtitle: "done" }),
3046
- /* @__PURE__ */ jsxs13(Box13, { marginBottom: 1, children: [
3047
- /* @__PURE__ */ jsx13(Badge5, { color: "green", children: "CLEARED" }),
3048
- /* @__PURE__ */ jsx13(Text13, { children: " " }),
3049
- /* @__PURE__ */ jsx13(Text13, { color: palette.dim, children: choice === "all" ? `${result.payloads} payload(s), ${result.logs} log, ${result.config} config file removed` : `${result.removed} item(s) removed` })
3166
+ return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
3167
+ /* @__PURE__ */ jsx14(Header, { title: "Clear", subtitle: "done" }),
3168
+ /* @__PURE__ */ jsxs14(Box14, { marginBottom: 1, children: [
3169
+ /* @__PURE__ */ jsx14(Badge5, { color: "green", children: "CLEARED" }),
3170
+ /* @__PURE__ */ jsx14(Text14, { children: " " }),
3171
+ /* @__PURE__ */ jsx14(Text14, { color: palette.dim, children: choice === "all" ? `${result.payloads} payload(s), ${result.logs} log, ${result.config} config file removed` : `${result.removed} item(s) removed` })
3050
3172
  ] }),
3051
- choice === "all" ? /* @__PURE__ */ jsx13(Alert6, { variant: "info", children: "back to first-run state \u2014 reconnect Shopify to continue" }) : null,
3052
- /* @__PURE__ */ jsx13(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text13, { color: palette.dim, children: "press enter to return" }) })
3173
+ choice === "all" ? /* @__PURE__ */ jsx14(Alert6, { variant: "info", children: "back to first-run state \u2014 reconnect Shopify to continue" }) : null,
3174
+ /* @__PURE__ */ jsx14(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text14, { color: palette.dim, children: "press enter to return" }) })
3053
3175
  ] });
3054
3176
  }
3055
3177
  if (choice) {
3056
3178
  const target = TARGETS[choice];
3057
- return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
3058
- /* @__PURE__ */ jsx13(Header, { title: "Clear", subtitle: target.label, right: "esc to cancel" }),
3059
- /* @__PURE__ */ jsx13(Alert6, { variant: "warning", children: `This permanently deletes ${target.description}.` }),
3060
- /* @__PURE__ */ jsx13(Section, { title: "Will be removed", children: choice === "all" ? /* @__PURE__ */ jsx13(
3179
+ return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
3180
+ /* @__PURE__ */ jsx14(Header, { title: "Clear", subtitle: target.label, right: "esc to cancel" }),
3181
+ /* @__PURE__ */ jsx14(Alert6, { variant: "warning", children: `This permanently deletes ${target.description}.` }),
3182
+ /* @__PURE__ */ jsx14(Section, { title: "Will be removed", children: choice === "all" ? /* @__PURE__ */ jsx14(
3061
3183
  KeyValue,
3062
3184
  {
3063
3185
  keyWidth: 10,
@@ -3067,22 +3189,22 @@ function Clear({ config, onDone }) {
3067
3189
  ["config", state.config.label]
3068
3190
  ]
3069
3191
  }
3070
- ) : /* @__PURE__ */ jsx13(Text13, { color: palette.dim, children: ` ${glyph.dot} ${choice === "payloads" ? state.payloads.label : choice === "logs" ? state.logs.label : target.description}` }) }),
3071
- choice === "all" || choice === "disconnect" ? /* @__PURE__ */ jsx13(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text13, { color: palette.warn, children: " your Shopify access token will have to be entered again" }) }) : null,
3072
- /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, children: [
3073
- /* @__PURE__ */ jsx13(Text13, { children: "Are you sure? " }),
3074
- /* @__PURE__ */ jsx13(ConfirmInput3, { defaultChoice: "cancel", onConfirm: run2, onCancel: () => setChoice(null) })
3192
+ ) : /* @__PURE__ */ jsx14(Text14, { color: palette.dim, children: ` ${glyph.dot} ${choice === "payloads" ? state.payloads.label : choice === "logs" ? state.logs.label : target.description}` }) }),
3193
+ choice === "all" || choice === "disconnect" ? /* @__PURE__ */ jsx14(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text14, { color: palette.warn, children: " your Shopify access token will have to be entered again" }) }) : null,
3194
+ /* @__PURE__ */ jsxs14(Box14, { marginTop: 1, children: [
3195
+ /* @__PURE__ */ jsx14(Text14, { children: "Are you sure? " }),
3196
+ /* @__PURE__ */ jsx14(ConfirmInput3, { defaultChoice: "cancel", onConfirm: run2, onCancel: () => setChoice(null) })
3075
3197
  ] })
3076
3198
  ] });
3077
3199
  }
3078
- return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
3079
- /* @__PURE__ */ jsx13(Header, { title: "Clear", subtitle: "remove locally cached data", right: "esc to go back" }),
3080
- /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", marginBottom: 1, paddingX: 1, children: [
3081
- /* @__PURE__ */ jsx13(Text13, { color: palette.dim, children: `${glyph.dot} ${state.payloads.label}` }),
3082
- /* @__PURE__ */ jsx13(Text13, { color: palette.dim, children: `${glyph.dot} ${state.logs.label}` }),
3083
- /* @__PURE__ */ jsx13(Text13, { color: palette.dim, children: `${glyph.dot} ${state.config.label}` })
3200
+ return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
3201
+ /* @__PURE__ */ jsx14(Header, { title: "Clear", subtitle: "remove locally cached data", right: "esc to go back" }),
3202
+ /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", marginBottom: 1, paddingX: 1, children: [
3203
+ /* @__PURE__ */ jsx14(Text14, { color: palette.dim, children: `${glyph.dot} ${state.payloads.label}` }),
3204
+ /* @__PURE__ */ jsx14(Text14, { color: palette.dim, children: `${glyph.dot} ${state.logs.label}` }),
3205
+ /* @__PURE__ */ jsx14(Text14, { color: palette.dim, children: `${glyph.dot} ${state.config.label}` })
3084
3206
  ] }),
3085
- /* @__PURE__ */ jsx13(
3207
+ /* @__PURE__ */ jsx14(
3086
3208
  Select8,
3087
3209
  {
3088
3210
  visibleOptionCount: 8,
@@ -3097,7 +3219,7 @@ function Clear({ config, onDone }) {
3097
3219
  }
3098
3220
 
3099
3221
  // src/ui/App.jsx
3100
- import { jsx as jsx14 } from "react/jsx-runtime";
3222
+ import { jsx as jsx15 } from "react/jsx-runtime";
3101
3223
  function App({ config: initialConfig, initialScreen = "home" }) {
3102
3224
  const { exit } = useApp2();
3103
3225
  const [config, setConfig] = useState8(initialConfig);
@@ -3114,7 +3236,7 @@ function App({ config: initialConfig, initialScreen = "home" }) {
3114
3236
  const toIntegrations = go("integrations");
3115
3237
  switch (screen) {
3116
3238
  case "setup":
3117
- return /* @__PURE__ */ jsx14(
3239
+ return /* @__PURE__ */ jsx15(
3118
3240
  Setup,
3119
3241
  {
3120
3242
  config,
@@ -3131,7 +3253,7 @@ function App({ config: initialConfig, initialScreen = "home" }) {
3131
3253
  }
3132
3254
  );
3133
3255
  case "integrations":
3134
- return /* @__PURE__ */ jsx14(
3256
+ return /* @__PURE__ */ jsx15(
3135
3257
  Integrations,
3136
3258
  {
3137
3259
  config,
@@ -3144,21 +3266,21 @@ function App({ config: initialConfig, initialScreen = "home" }) {
3144
3266
  }
3145
3267
  );
3146
3268
  case "connect":
3147
- return /* @__PURE__ */ jsx14(ConnectShopify, { config, onDone: toSetup });
3269
+ return /* @__PURE__ */ jsx15(ConnectShopify, { config, onDone: toSetup });
3148
3270
  case "webhook":
3149
- return /* @__PURE__ */ jsx14(Webhook, { config, onDone: toSetup });
3271
+ return /* @__PURE__ */ jsx15(Webhook, { config, onDone: toSetup });
3150
3272
  case "configure":
3151
- return /* @__PURE__ */ jsx14(Configure, { config, section, onDone: toSetup });
3273
+ return /* @__PURE__ */ jsx15(Configure, { config, section, onDone: toSetup });
3152
3274
  case "build":
3153
- return /* @__PURE__ */ jsx14(Build, { config, providerId: provider, onDone: toIntegrations });
3275
+ return /* @__PURE__ */ jsx15(Build, { config, providerId: provider, onDone: toIntegrations });
3154
3276
  case "history":
3155
- return /* @__PURE__ */ jsx14(History, { config, onDone: toHome });
3277
+ return /* @__PURE__ */ jsx15(History, { config, onDone: toHome });
3156
3278
  case "doctor":
3157
- return /* @__PURE__ */ jsx14(Doctor, { config, onDone: toHome });
3279
+ return /* @__PURE__ */ jsx15(Doctor, { config, onDone: toHome });
3158
3280
  case "clear":
3159
- return /* @__PURE__ */ jsx14(Clear, { config, onDone: toHome });
3281
+ return /* @__PURE__ */ jsx15(Clear, { config, onDone: toHome });
3160
3282
  default:
3161
- return /* @__PURE__ */ jsx14(Home, { config, onPick: setScreen, onQuit: exit });
3283
+ return /* @__PURE__ */ jsx15(Home, { config, onPick: setScreen, onQuit: exit });
3162
3284
  }
3163
3285
  }
3164
3286
 
@@ -3458,7 +3580,7 @@ function printReport(built) {
3458
3580
  }
3459
3581
 
3460
3582
  // src/cli.jsx
3461
- import { jsx as jsx15 } from "react/jsx-runtime";
3583
+ import { jsx as jsx16 } from "react/jsx-runtime";
3462
3584
  var HELP = `
3463
3585
  ${c.bold("hookwright")} \u2014 generate real, signed provider webhooks from a live Shopify catalogue
3464
3586
 
@@ -3548,7 +3670,7 @@ async function main() {
3548
3670
  const config = loadConfig(args.flags.config);
3549
3671
  if (command && command !== "ui") {
3550
3672
  if (command === "configure" && process.stdin.isTTY) {
3551
- render(/* @__PURE__ */ jsx15(App, { config, initialScreen: "connect" }));
3673
+ render(/* @__PURE__ */ jsx16(App, { config, initialScreen: "connect" }));
3552
3674
  return;
3553
3675
  }
3554
3676
  const code = await headless(command, args, config);
@@ -3561,7 +3683,7 @@ async function main() {
3561
3683
  process.exitCode = 1;
3562
3684
  return;
3563
3685
  }
3564
- render(/* @__PURE__ */ jsx15(App, { config, initialScreen: "home" }));
3686
+ render(/* @__PURE__ */ jsx16(App, { config, initialScreen: "home" }));
3565
3687
  }
3566
3688
  main().catch((err) => {
3567
3689
  console.error(c.red(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hookwright",
3
- "version": "1.1.0",
3
+ "version": "1.1.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",