@stripe/link-cli 0.3.0 → 0.3.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 (2) hide show
  1. package/dist/cli.js +443 -445
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -11358,7 +11358,7 @@ var Login = ({
11358
11358
  ] });
11359
11359
  }
11360
11360
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingY: 1, children: [
11361
- /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { bold: true, children: "Link CLI Authentication" }) }),
11361
+ /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { bold: true, children: "Authentication" }) }),
11362
11362
  /* @__PURE__ */ jsxs(
11363
11363
  Box,
11364
11364
  {
@@ -11432,8 +11432,62 @@ var statusOptions = z.object({
11432
11432
  timeout: z.coerce.number().default(300).describe("Polling timeout in seconds.")
11433
11433
  });
11434
11434
 
11435
+ // src/commands/auth/status.tsx
11436
+ import { Box as Box3, Text as Text3 } from "ink";
11437
+ import { useEffect as useEffect3, useState as useState3 } from "react";
11438
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
11439
+ var AuthStatus = ({ onComplete }) => {
11440
+ const [checked, setChecked] = useState3(false);
11441
+ const [authenticated, setAuthenticated] = useState3(false);
11442
+ const [tokenPreview, setTokenPreview] = useState3("");
11443
+ const [tokenType, setTokenType] = useState3("");
11444
+ const [credentialsPath, setCredentialsPath] = useState3("");
11445
+ useEffect3(() => {
11446
+ const auth = storage.getAuth();
11447
+ const credentialsPath2 = storage.getPath();
11448
+ if (auth) {
11449
+ setAuthenticated(true);
11450
+ setTokenPreview(`${auth.access_token.substring(0, 20)}...`);
11451
+ setTokenType(auth.token_type);
11452
+ }
11453
+ setCredentialsPath(credentialsPath2);
11454
+ setChecked(true);
11455
+ setTimeout(onComplete, 1e3);
11456
+ }, [onComplete]);
11457
+ if (!checked) {
11458
+ return null;
11459
+ }
11460
+ if (authenticated) {
11461
+ return /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", children: [
11462
+ /* @__PURE__ */ jsx3(Text3, { color: "green", children: "\u2713 Authenticated" }),
11463
+ /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
11464
+ /* @__PURE__ */ jsxs2(Text3, { children: [
11465
+ "Access token: ",
11466
+ /* @__PURE__ */ jsx3(Text3, { bold: true, children: tokenPreview })
11467
+ ] }),
11468
+ /* @__PURE__ */ jsxs2(Text3, { children: [
11469
+ "Token type: ",
11470
+ /* @__PURE__ */ jsx3(Text3, { bold: true, children: tokenType })
11471
+ ] }),
11472
+ /* @__PURE__ */ jsxs2(Text3, { children: [
11473
+ "Credentials: ",
11474
+ /* @__PURE__ */ jsx3(Text3, { bold: true, children: credentialsPath })
11475
+ ] })
11476
+ ] })
11477
+ ] });
11478
+ }
11479
+ return /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", children: [
11480
+ /* @__PURE__ */ jsx3(Text3, { color: "yellow", children: "\u2717 Not authenticated" }),
11481
+ /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: 'Run "link-cli auth login" to authenticate' }),
11482
+ /* @__PURE__ */ jsx3(Box3, { marginTop: 1, paddingX: 2, children: /* @__PURE__ */ jsxs2(Text3, { children: [
11483
+ "Credentials: ",
11484
+ /* @__PURE__ */ jsx3(Text3, { bold: true, children: credentialsPath })
11485
+ ] }) })
11486
+ ] });
11487
+ };
11488
+
11435
11489
  // src/commands/auth/index.tsx
11436
- import { jsx as jsx3 } from "react/jsx-runtime";
11490
+ import { jsx as jsx4 } from "react/jsx-runtime";
11437
11491
  function createAuthCli(authResource, updateInfo) {
11438
11492
  const cli2 = Cli.create("auth", {
11439
11493
  description: "Authentication commands"
@@ -11453,7 +11507,7 @@ function createAuthCli(authResource, updateInfo) {
11453
11507
  if (!c.agent && !c.formatExplicit) {
11454
11508
  return new Promise((resolve) => {
11455
11509
  const { waitUntilExit } = render(
11456
- /* @__PURE__ */ jsx3(
11510
+ /* @__PURE__ */ jsx4(
11457
11511
  Login,
11458
11512
  {
11459
11513
  authResource,
@@ -11506,7 +11560,7 @@ function createAuthCli(authResource, updateInfo) {
11506
11560
  if (!c.agent && !c.formatExplicit) {
11507
11561
  return new Promise((resolve) => {
11508
11562
  const { waitUntilExit } = render(
11509
- /* @__PURE__ */ jsx3(Logout, { authResource, onComplete: () => {
11563
+ /* @__PURE__ */ jsx4(Logout, { authResource, onComplete: () => {
11510
11564
  } })
11511
11565
  );
11512
11566
  waitUntilExit().then(() => resolve(result));
@@ -11520,6 +11574,25 @@ function createAuthCli(authResource, updateInfo) {
11520
11574
  options: statusOptions,
11521
11575
  outputPolicy: "agent-only",
11522
11576
  async *run(c) {
11577
+ if (!c.agent && !c.formatExplicit) {
11578
+ return new Promise((resolve) => {
11579
+ const { waitUntilExit } = render(
11580
+ /* @__PURE__ */ jsx4(AuthStatus, { onComplete: () => {
11581
+ } })
11582
+ );
11583
+ waitUntilExit().then(() => {
11584
+ const auth = storage.getAuth();
11585
+ resolve({
11586
+ authenticated: !!auth,
11587
+ ...auth ? {
11588
+ access_token: `${auth.access_token.substring(0, 20)}...`,
11589
+ token_type: auth.token_type
11590
+ } : {},
11591
+ credentials_path: storage.getPath()
11592
+ });
11593
+ });
11594
+ });
11595
+ }
11523
11596
  const opts = c.options;
11524
11597
  const interval = opts.interval;
11525
11598
  const maxAttempts = opts.maxAttempts;
@@ -11586,24 +11659,24 @@ import { render as render2 } from "ink";
11586
11659
 
11587
11660
  // src/commands/demo/demo-runner.tsx
11588
11661
  import { Box as Box8, Text as Text9, useInput as useInput4 } from "ink";
11589
- import { useCallback, useState as useState6 } from "react";
11662
+ import { useCallback, useState as useState7 } from "react";
11590
11663
 
11591
11664
  // src/utils/markdown-text.tsx
11592
- import { Text as Text3 } from "ink";
11593
- import { jsx as jsx4 } from "react/jsx-runtime";
11665
+ import { Text as Text4 } from "ink";
11666
+ import { jsx as jsx5 } from "react/jsx-runtime";
11594
11667
  var MarkdownText = ({
11595
11668
  children,
11596
11669
  dimColor
11597
11670
  }) => {
11598
11671
  const parts = tokenize(children);
11599
- return /* @__PURE__ */ jsx4(Text3, { dimColor, children: parts.map((part) => {
11672
+ return /* @__PURE__ */ jsx5(Text4, { dimColor, children: parts.map((part) => {
11600
11673
  if (part.type === "bold") {
11601
- return /* @__PURE__ */ jsx4(Text3, { bold: true, children: part.text }, part.key);
11674
+ return /* @__PURE__ */ jsx5(Text4, { bold: true, children: part.text }, part.key);
11602
11675
  }
11603
11676
  if (part.type === "code") {
11604
- return /* @__PURE__ */ jsx4(Text3, { color: "yellow", children: part.text }, part.key);
11677
+ return /* @__PURE__ */ jsx5(Text4, { color: "yellow", children: part.text }, part.key);
11605
11678
  }
11606
- return /* @__PURE__ */ jsx4(Text3, { children: part.text }, part.key);
11679
+ return /* @__PURE__ */ jsx5(Text4, { children: part.text }, part.key);
11607
11680
  }) });
11608
11681
  };
11609
11682
  function tokenize(input) {
@@ -11638,7 +11711,7 @@ function tokenize(input) {
11638
11711
  }
11639
11712
 
11640
11713
  // src/commands/spend-request/app-download-qr-codes.tsx
11641
- import { Box as Box3, Text as Text4 } from "ink";
11714
+ import { Box as Box4, Text as Text5 } from "ink";
11642
11715
  import { useMemo } from "react";
11643
11716
 
11644
11717
  // src/utils/render-qr-matrix.ts
@@ -11675,25 +11748,25 @@ function renderQrMatrix(url) {
11675
11748
  }
11676
11749
 
11677
11750
  // src/commands/spend-request/app-download-qr-codes.tsx
11678
- import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
11751
+ import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
11679
11752
  var DOWNLOAD_URL = "https://link.com/download";
11680
11753
  var AppDownloadQrCodes = () => {
11681
11754
  const qrLines = useMemo(() => renderQrMatrix(DOWNLOAD_URL), []);
11682
- return /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", marginTop: 1, children: [
11683
- /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: "Get the Link app to approve spend requests from your phone" }),
11684
- /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", alignItems: "flex-start", marginTop: 1, children: [
11755
+ return /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", marginTop: 1, children: [
11756
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: "Get the Link app to approve spend requests from your phone" }),
11757
+ /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", alignItems: "flex-start", marginTop: 1, children: [
11685
11758
  qrLines.map((line, i) => (
11686
11759
  // biome-ignore lint/suspicious/noArrayIndexKey: stable static array
11687
- /* @__PURE__ */ jsx5(Text4, { children: line }, i)
11760
+ /* @__PURE__ */ jsx6(Text5, { children: line }, i)
11688
11761
  )),
11689
- /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: DOWNLOAD_URL })
11762
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: DOWNLOAD_URL })
11690
11763
  ] })
11691
11764
  ] });
11692
11765
  };
11693
11766
 
11694
11767
  // src/commands/demo/card-flow.tsx
11695
11768
  import { Box as Box5, Text as Text6, useInput as useInput2 } from "ink";
11696
- import { useEffect as useEffect3, useRef, useState as useState3 } from "react";
11769
+ import { useEffect as useEffect4, useRef, useState as useState4 } from "react";
11697
11770
 
11698
11771
  // src/utils/poll-until-approved.ts
11699
11772
  function pollUntilApproved(repository, id, options = {}) {
@@ -11721,12 +11794,12 @@ function pollUntilApproved(repository, id, options = {}) {
11721
11794
 
11722
11795
  // src/commands/demo/constants.ts
11723
11796
  var DEMO_MERCHANT_NAME = "Galtee Outdoor";
11724
- var DEMO_MERCHANT_URL = "https://galtee.stripedemos.com/";
11797
+ var DEMO_MERCHANT_URL = "https://galtee.stripedemos.com/en/products/prod_RtAl1kmlzvL8oj";
11725
11798
  var DEMO_MPP_DEV_URL = "https://mpp.dev";
11726
11799
  var DEMO_CLIMATE_API_URL = "https://climate.stripe.dev/api/test/contribute";
11727
11800
  var DEMO_CARD_AMOUNT = 12900;
11728
11801
  var DEMO_SPT_AMOUNT = 100;
11729
- var DEMO_CARD_CONTEXT = "Link CLI onboarding demo: Merino Trail Jacket (size M, Forest) from Galtee Outdoor. Agent completing checkout using a virtual card credential.";
11802
+ var DEMO_CARD_CONTEXT = "Link CLI onboarding demo: Errigal Puffer Jacket from Galtee Outdoor. Agent completing checkout using a virtual card credential.";
11730
11803
  var DEMO_SPT_CONTEXT = "Demo purchase: Testing the Link CLI machine payment flow by making an automated HTTP 402 payment to Stripe Climate. This demonstrates the shared payment token credential and machine payment protocol.";
11731
11804
 
11732
11805
  // src/commands/demo/content.ts
@@ -11735,100 +11808,103 @@ var sptAmount = `$${(DEMO_SPT_AMOUNT / 100).toFixed(2)}`;
11735
11808
  var CARD_FLOW = {
11736
11809
  title: "Flow 1: Virtual Card",
11737
11810
  intro: {
11738
- description: `An agent buys a Merino Trail Jacket (${cardAmount}) from Galtee Outdoor using a **virtual card** \u2014 a one-time card number issued from your Link wallet. Your real payment details are never shared with the agent or the business.`,
11811
+ description: `Agent buys a Errigal Puffer Jacket (${cardAmount}) with a one-time virtual card from your Link wallet. Your real card is never shared.`,
11739
11812
  steps: [
11740
- `The agent calls \`spend-request create\` to request ${cardAmount} at Galtee Outdoor`,
11741
- "You approve in the Link app",
11742
- "Link issues a one-time virtual card",
11743
- "Open the checkout page and enter the card details"
11813
+ "Select payment method",
11814
+ `Create spend request for ${cardAmount}`,
11815
+ "Approve in Link",
11816
+ "Get virtual card and open checkout"
11744
11817
  ],
11745
11818
  prompt: "Press [Enter] to start"
11746
11819
  },
11820
+ explainPm: {
11821
+ prompt: "Press [Enter] to create a spend request"
11822
+ },
11747
11823
  createSpend: {
11748
- description: `\`spend-request create\` sends the business name, URL, amount (${cardAmount}), and purchase description to Link. No credentials are issued until you approve.`,
11824
+ description: `Requests ${cardAmount} from your wallet. No credentials issued until you approve.`,
11749
11825
  loading: "Creating spend request..."
11750
11826
  },
11751
11827
  approval: {
11752
- description: "Open the URL to approve the spend request. The CLI polls and continues once approved.",
11828
+ description: "Open the URL to approve. CLI continues once approved.",
11753
11829
  loading: "Waiting for approval...",
11754
11830
  browserHint: "Press [Enter] to open in browser"
11755
11831
  },
11756
11832
  showCard: {
11757
- description: "Link issued a one-time virtual card. An agent fills these into the checkout form. Single-use \u2014 expires in minutes:",
11758
- openUrl: "Open Galtee Outdoor and enter these details at checkout.",
11833
+ description: "One-time virtual card issued. Enter these at Galtee Outdoor checkout:",
11759
11834
  prompt: "Press [Enter] to open Galtee Outdoor"
11760
11835
  },
11761
11836
  done: {
11762
11837
  success: "Opened Galtee Outdoor in your browser",
11763
- detail: "Enter the card details above at checkout. Galtee Outdoor runs in testmode \u2014 no real charge."
11838
+ detail: "Testmode \u2014 no real charge."
11764
11839
  }
11765
11840
  };
11766
11841
  var SPT_FLOW = {
11767
11842
  title: "Flow 2: Machine Payment (SPT)",
11768
11843
  intro: {
11769
- description: "Some APIs accept payment without a checkout form. When called without credentials, the server responds with **HTTP 402** and a payment challenge. The agent signs that challenge with a **shared payment token** (SPT) and retries \u2014 this is the Machine Payment Protocol (MPP).",
11770
- preamble: `A ${sptAmount} donation to Stripe Climate (climate.stripe.dev) demonstrates:`,
11844
+ description: "No checkout form. The server returns **HTTP 402** with a payment challenge. The link-cli creates and sends a **Shared Payment Token** (SPT) programmaticaly scoped to the business and amount.",
11845
+ preamble: `${sptAmount} donation to Stripe Climate demonstrates:`,
11771
11846
  steps: [
11772
- "Probe the API \u2014 server responds HTTP 402 with a challenge",
11773
- "Decode the challenge to extract the `network_id`",
11774
- "Call `spend-request create` for an SPT credential",
11775
- "Approve the spend request",
11776
- "`mpp pay` signs the challenge and retries with an Authorization header"
11847
+ "Select payment method",
11848
+ "Probe API \u2014 get HTTP 402 challenge and decode `network_id`",
11849
+ "Create SPT spend request",
11850
+ "Approve",
11851
+ "`mpp pay` signs and retries"
11777
11852
  ],
11778
11853
  prompt: "Press [Enter] to start"
11779
11854
  },
11780
11855
  probe: {
11781
- description: `The agent POSTs to ${DEMO_CLIMATE_API_URL}. Without a payment credential, the server returns HTTP 402 with a \`WWW-Authenticate\` challenge header.`,
11856
+ description: `POST to ${DEMO_CLIMATE_API_URL} without credentials \u2014 server returns 402 with a \`WWW-Authenticate\` challenge.`,
11782
11857
  loading: "Probing...",
11783
- detail: "The challenge contains a **network_id** \u2014 the business identifier on the Stripe network. The agent uses it to request the matching SPT credential."
11858
+ detail: "Challenge contains a `network_id` \u2014 the business identifier on Stripe's network.",
11859
+ prompt: "Press [Enter] to create a spend request"
11784
11860
  },
11785
11861
  createSpend: {
11786
- description: `\`spend-request create\` with \`credential_type: "shared_payment_token"\`, the decoded \`network_id\`, and amount (${sptAmount}). The \`network_id\` identifies the business \u2014 no name or URL needed.`,
11862
+ description: `Request an SPT using the decoded \`network_id\` and amount (${sptAmount}).`,
11787
11863
  loading: "Creating spend request..."
11788
11864
  },
11789
11865
  approval: {
11790
- description: "Approve the spend request. Once approved, Link issues an SPT the agent uses to sign the 402 challenge.",
11866
+ description: "Approve to issue the SPT.",
11791
11867
  loading: "Waiting for approval...",
11792
11868
  browserHint: "Press [Enter] to open in browser"
11793
11869
  },
11794
11870
  mppPay: {
11795
- description: "`mpp pay` retrieves the SPT, re-probes the API, signs the 402 challenge, and retries with an `Authorization: Payment` header.",
11871
+ description: "`mpp pay` retrieves the SPT, signs the challenge, retries with `Authorization: Payment`.",
11796
11872
  loading: "Completing payment...",
11797
11873
  prompt: "Press [Enter] to pay"
11798
11874
  },
11799
11875
  done: {
11800
11876
  success: "Payment complete",
11801
- detail: `The ${sptAmount} donation went through entirely via API \u2014 no forms, no browser.`
11877
+ detail: `${sptAmount} donation completed via API \u2014 no forms, no browser.`
11802
11878
  }
11803
11879
  };
11804
11880
  var DEMO_MENU = {
11805
11881
  title: "Link CLI Demo",
11806
- subtitle: "Two flows showing how agents request and use payment credentials with Link.",
11882
+ subtitle: "See how agents use Link to make payments.",
11807
11883
  question: "Which flow would you like to run?",
11808
11884
  hint: "Use \u2191\u2193 to select, [Enter] to confirm",
11809
11885
  options: [
11810
11886
  {
11811
11887
  key: "both",
11812
11888
  label: "Both flows",
11813
- description: "Walk through both flows end-to-end."
11889
+ description: "Run both end-to-end."
11814
11890
  },
11815
11891
  {
11816
11892
  key: "card",
11817
11893
  label: "Virtual card",
11818
- description: "The agent requests a one-time card number and fills it into a checkout form."
11894
+ description: "One-time card number for checkout forms."
11819
11895
  },
11820
11896
  {
11821
11897
  key: "spt",
11822
11898
  label: "Machine payment (SPT)",
11823
- description: "The agent pays via API using the Machine Payment Protocol \u2014 no browser, no forms."
11899
+ description: "Pay via API \u2014 no browser, no forms."
11824
11900
  }
11825
11901
  ],
11826
- transition: "Virtual card flow done. Next: **machine payment** \u2014 the agent pays an API directly, no checkout form needed.",
11902
+ transition: "Card flow done. Next: **machine payment** \u2014 paying an API directly.",
11827
11903
  transitionPrompt: "Press [Enter] to continue to Flow 2"
11828
11904
  };
11829
11905
  var ONBOARD = {
11830
11906
  title: "Welcome to Link CLI",
11831
- subtitle: "Set up Link CLI to let agents make secure payments on your behalf.",
11907
+ subtitle: "Let agents make secure payments on your behalf.",
11832
11908
  auth: {
11833
11909
  alreadyLoggedIn: "Already logged in",
11834
11910
  authenticated: "Authenticated",
@@ -11838,48 +11914,23 @@ var ONBOARD = {
11838
11914
  loading: "Checking payment methods...",
11839
11915
  pickPrompt: "Which payment method should we use for the demo?",
11840
11916
  pickHint: "Use \u2191\u2193 to select, [Enter] to confirm",
11841
- missing: "No payment methods found in your Link wallet.",
11917
+ missing: "No payment methods in your Link wallet.",
11842
11918
  missingSteps: [
11843
11919
  "Open the Link app or visit link.com",
11844
11920
  "Add a payment method",
11845
- "Come back here and press [Enter] to retry"
11921
+ "Press [Enter] to retry"
11846
11922
  ],
11847
11923
  retryPrompt: "Press [Enter] to retry"
11848
11924
  },
11849
11925
  appTip: {
11850
11926
  title: "Get the Link app",
11851
- description: "Approve spend requests from your phone. Push notifications let you approve or deny instantly.",
11927
+ description: "Approve spend requests from your phone with push notifications.",
11852
11928
  url: "https://link.com/download"
11853
11929
  }
11854
11930
  };
11855
11931
 
11856
- // src/commands/demo/step-data.tsx
11857
- import { Box as Box4, Text as Text5 } from "ink";
11858
- import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
11859
- var StepData = ({ data }) => {
11860
- const entries = Object.entries(data).filter(
11861
- ([, v]) => v !== void 0 && v !== null
11862
- );
11863
- const maxKeyLen = Math.max(...entries.map(([k]) => k.length));
11864
- return /* @__PURE__ */ jsx6(
11865
- Box4,
11866
- {
11867
- flexDirection: "column",
11868
- paddingX: 2,
11869
- marginTop: 1,
11870
- borderStyle: "single",
11871
- borderColor: "gray",
11872
- children: entries.map(([key, value]) => /* @__PURE__ */ jsxs3(Text5, { children: [
11873
- /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: key.padEnd(maxKeyLen) }),
11874
- " ",
11875
- /* @__PURE__ */ jsx6(Text5, { children: typeof value === "object" ? JSON.stringify(value) : String(value) })
11876
- ] }, key))
11877
- }
11878
- );
11879
- };
11880
-
11881
11932
  // src/commands/demo/card-flow.tsx
11882
- import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
11933
+ import { Fragment, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
11883
11934
  function formatPmLabel(pm) {
11884
11935
  return `${pm.card_details?.brand ?? pm.type} ****${pm.card_details?.last4 ?? ""}`;
11885
11936
  }
@@ -11895,15 +11946,14 @@ var CardFlow = ({
11895
11946
  paymentMethodId: initialPaymentMethodId,
11896
11947
  onComplete
11897
11948
  }) => {
11898
- const [step, setStep] = useState3("intro");
11899
- const [paymentMethod, setPaymentMethod] = useState3(
11949
+ const [step, setStep] = useState4("intro");
11950
+ const [paymentMethod, setPaymentMethod] = useState4(
11900
11951
  null
11901
11952
  );
11902
- const [paymentMethods, setPaymentMethods] = useState3([]);
11903
- const [selectedPmIndex, setSelectedPmIndex] = useState3(0);
11904
- const [spendRequest, setSpendRequest] = useState3(null);
11905
- const [spendRequestPayload, setSpendRequestPayload] = useState3(null);
11906
- const [error, setError] = useState3("");
11953
+ const [paymentMethods, setPaymentMethods] = useState4([]);
11954
+ const [selectedPmIndex, setSelectedPmIndex] = useState4(0);
11955
+ const [spendRequest, setSpendRequest] = useState4(null);
11956
+ const [error, setError] = useState4("");
11907
11957
  const approvalUrl = spendRequest?.approval_url ?? "";
11908
11958
  const enterResolver = useRef(null);
11909
11959
  const pmResolver = useRef(null);
@@ -11956,7 +12006,7 @@ var CardFlow = ({
11956
12006
  }
11957
12007
  });
11958
12008
  const started = useRef(false);
11959
- useEffect3(() => {
12009
+ useEffect4(() => {
11960
12010
  if (started.current) return;
11961
12011
  started.current = true;
11962
12012
  const run = async () => {
@@ -11992,7 +12042,7 @@ var CardFlow = ({
11992
12042
  await waitForEnter();
11993
12043
  }
11994
12044
  setStep("create-spend");
11995
- const payload = {
12045
+ const result = await spendRequestRepo2.createSpendRequest({
11996
12046
  payment_details: pmId,
11997
12047
  credential_type: "card",
11998
12048
  amount: DEMO_CARD_AMOUNT,
@@ -12001,9 +12051,7 @@ var CardFlow = ({
12001
12051
  merchant_url: DEMO_MERCHANT_URL,
12002
12052
  request_approval: true,
12003
12053
  test: true
12004
- };
12005
- setSpendRequestPayload(payload);
12006
- const result = await spendRequestRepo2.createSpendRequest(payload);
12054
+ });
12007
12055
  setSpendRequest(result);
12008
12056
  setStep("await-approval");
12009
12057
  for (; ; ) {
@@ -12075,177 +12123,160 @@ var CardFlow = ({
12075
12123
  /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: DEMO_MERCHANT_URL })
12076
12124
  ] }),
12077
12125
  /* @__PURE__ */ jsx7(MarkdownText, { children: CARD_FLOW.intro.description }),
12078
- /* @__PURE__ */ jsx7(Box5, { marginTop: 1, children: /* @__PURE__ */ jsxs4(Text6, { children: [
12079
- "What happens:",
12080
- "\n",
12081
- CARD_FLOW.intro.steps.map((s, i) => ` ${i + 1}. ${s}`).join("\n")
12082
- ] }) }),
12126
+ /* @__PURE__ */ jsxs4(Box5, { marginTop: 1, flexDirection: "column", children: [
12127
+ /* @__PURE__ */ jsx7(Text6, { children: "What happens:" }),
12128
+ CARD_FLOW.intro.steps.map((s, i) => {
12129
+ const doneAfter = [
12130
+ "pick-pm",
12131
+ "create-spend",
12132
+ "await-approval",
12133
+ "show-card"
12134
+ ];
12135
+ const activeFrom = [
12136
+ "fetch-pm",
12137
+ "create-spend",
12138
+ "await-approval",
12139
+ "show-card"
12140
+ ];
12141
+ const done = pastStep(doneAfter[i]);
12142
+ const active = !done && (step === activeFrom[i] || pastStep(activeFrom[i]));
12143
+ return done ? /* @__PURE__ */ jsxs4(Text6, { dimColor: true, strikethrough: true, children: [
12144
+ " ",
12145
+ i + 1,
12146
+ ". ",
12147
+ s
12148
+ ] }, s) : active ? /* @__PURE__ */ jsxs4(Text6, { bold: true, color: "cyan", children: [
12149
+ " ",
12150
+ i + 1,
12151
+ ". ",
12152
+ s
12153
+ ] }, s) : /* @__PURE__ */ jsxs4(Text6, { dimColor: true, children: [
12154
+ " ",
12155
+ i + 1,
12156
+ ". ",
12157
+ s
12158
+ ] }, s);
12159
+ })
12160
+ ] }),
12083
12161
  step === "intro" && prompt(CARD_FLOW.intro.prompt)
12084
12162
  ] }),
12085
12163
  step === "fetch-pm" && /* @__PURE__ */ jsx7(Box5, { flexDirection: "column", children: /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Fetching payment methods from your Link wallet..." }) }),
12086
- step === "pick-pm" && paymentMethods.length > 1 && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
12087
- /* @__PURE__ */ jsx7(Text6, { children: "Which payment method should we use for the demo?" }),
12088
- /* @__PURE__ */ jsx7(Box5, { flexDirection: "column", marginTop: 1, children: paymentMethods.map((pm, i) => /* @__PURE__ */ jsx7(Text6, { children: i === selectedPmIndex ? /* @__PURE__ */ jsxs4(Text6, { color: "cyan", bold: true, children: [
12089
- ">",
12090
- " ",
12091
- formatPmLabel(pm),
12092
- pm.is_default ? " (default)" : ""
12093
- ] }) : /* @__PURE__ */ jsxs4(Text6, { dimColor: true, children: [
12094
- " ",
12095
- formatPmLabel(pm),
12096
- pm.is_default ? " (default)" : ""
12097
- ] }) }, pm.id)) }),
12098
- /* @__PURE__ */ jsx7(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Use \u2191\u2193 to select, [Enter] to confirm" }) })
12099
- ] }),
12100
- pastStep("fetch-pm") && paymentMethod && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
12101
- /* @__PURE__ */ jsxs4(Text6, { color: "green", children: [
12102
- "\u2713 Using ",
12103
- /* @__PURE__ */ jsx7(Text6, { bold: true, children: pmLabel }),
12104
- paymentMethod.is_default ? " (default)" : ""
12164
+ (step === "pick-pm" || step === "explain-pm") && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
12165
+ step === "pick-pm" && paymentMethods.length > 1 && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
12166
+ /* @__PURE__ */ jsx7(Text6, { children: "Which payment method should we use for the demo?" }),
12167
+ /* @__PURE__ */ jsx7(Box5, { flexDirection: "column", marginTop: 1, children: paymentMethods.map((pm, i) => /* @__PURE__ */ jsx7(Text6, { children: i === selectedPmIndex ? /* @__PURE__ */ jsxs4(Text6, { color: "cyan", bold: true, children: [
12168
+ ">",
12169
+ " ",
12170
+ formatPmLabel(pm),
12171
+ pm.is_default ? " (default)" : ""
12172
+ ] }) : /* @__PURE__ */ jsxs4(Text6, { dimColor: true, children: [
12173
+ " ",
12174
+ formatPmLabel(pm),
12175
+ pm.is_default ? " (default)" : ""
12176
+ ] }) }, pm.id)) }),
12177
+ /* @__PURE__ */ jsx7(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Use \u2191\u2193 to select, [Enter] to confirm" }) })
12105
12178
  ] }),
12106
- step === "explain-pm" && prompt()
12179
+ paymentMethod && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
12180
+ /* @__PURE__ */ jsxs4(Text6, { color: "green", children: [
12181
+ "\u2713 Using ",
12182
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: pmLabel }),
12183
+ paymentMethod.is_default ? " (default)" : ""
12184
+ ] }),
12185
+ step === "explain-pm" && prompt(CARD_FLOW.explainPm.prompt)
12186
+ ] })
12107
12187
  ] }),
12108
- pastStep("explain-pm") && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
12188
+ step === "create-spend" && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
12109
12189
  /* @__PURE__ */ jsx7(MarkdownText, { children: CARD_FLOW.createSpend.description }),
12110
- spendRequestPayload && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", marginTop: 1, children: [
12111
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "spend-request create" }),
12112
- /* @__PURE__ */ jsx7(
12190
+ /* @__PURE__ */ jsx7(Box5, { marginY: 1, children: /* @__PURE__ */ jsx7(Text6, { color: "cyan", children: CARD_FLOW.createSpend.loading }) })
12191
+ ] }),
12192
+ (step === "await-approval" || step === "approval-timeout") && spendRequest && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
12193
+ /* @__PURE__ */ jsxs4(Text6, { color: "green", children: [
12194
+ "\u2713 Spend request created (",
12195
+ spendRequest.id,
12196
+ ")"
12197
+ ] }),
12198
+ step === "await-approval" && /* @__PURE__ */ jsxs4(Fragment, { children: [
12199
+ /* @__PURE__ */ jsx7(Text6, { children: CARD_FLOW.approval.description }),
12200
+ /* @__PURE__ */ jsxs4(
12113
12201
  Box5,
12114
12202
  {
12115
12203
  flexDirection: "column",
12116
- borderStyle: "single",
12117
- borderColor: "gray",
12204
+ borderStyle: "round",
12205
+ borderColor: "cyan",
12118
12206
  paddingX: 2,
12119
- children: /* @__PURE__ */ jsx7(Text6, { children: JSON.stringify(
12120
- spendRequestPayload,
12121
- null,
12122
- 2
12123
- ) })
12207
+ paddingY: 1,
12208
+ marginTop: 1,
12209
+ children: [
12210
+ /* @__PURE__ */ jsxs4(Text6, { children: [
12211
+ "Approve at:",
12212
+ " ",
12213
+ /* @__PURE__ */ jsx7(Text6, { bold: true, color: "cyan", children: approvalUrl })
12214
+ ] }),
12215
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: CARD_FLOW.approval.browserHint })
12216
+ ]
12124
12217
  }
12125
- )
12126
- ] }),
12127
- step === "create-spend" && /* @__PURE__ */ jsx7(Box5, { marginY: 1, children: /* @__PURE__ */ jsx7(Text6, { color: "cyan", children: CARD_FLOW.createSpend.loading }) })
12128
- ] }),
12129
- (step === "await-approval" || step === "approval-timeout" || pastStep("await-approval")) && spendRequest && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
12130
- /* @__PURE__ */ jsxs4(Text6, { color: "green", children: [
12131
- "\u2713 Spend request created (ID: ",
12132
- /* @__PURE__ */ jsx7(Text6, { bold: true, children: spendRequest.id }),
12133
- ")"
12218
+ ),
12219
+ /* @__PURE__ */ jsx7(Box5, { marginY: 1, children: /* @__PURE__ */ jsx7(Text6, { color: "cyan", children: CARD_FLOW.approval.loading }) })
12134
12220
  ] }),
12135
- /* @__PURE__ */ jsx7(
12136
- StepData,
12137
- {
12138
- data: {
12139
- id: spendRequest.id,
12140
- status: spendRequest.status,
12141
- credential_type: spendRequest.credential_type,
12142
- amount: spendRequest.amount,
12143
- merchant_name: spendRequest.merchant_name,
12144
- merchant_url: spendRequest.merchant_url,
12145
- context: spendRequest.context,
12146
- approval_url: spendRequest.approval_url
12221
+ step === "approval-timeout" && /* @__PURE__ */ jsxs4(Fragment, { children: [
12222
+ /* @__PURE__ */ jsx7(Text6, { color: "yellow", children: "\u26A0 Approval timed out (5 min). Still pending \u2014 you can still approve." }),
12223
+ /* @__PURE__ */ jsxs4(
12224
+ Box5,
12225
+ {
12226
+ flexDirection: "column",
12227
+ borderStyle: "round",
12228
+ borderColor: "yellow",
12229
+ paddingX: 2,
12230
+ paddingY: 1,
12231
+ marginTop: 1,
12232
+ children: [
12233
+ /* @__PURE__ */ jsxs4(Text6, { children: [
12234
+ "Approve at:",
12235
+ " ",
12236
+ /* @__PURE__ */ jsx7(Text6, { bold: true, color: "cyan", children: approvalUrl })
12237
+ ] }),
12238
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Press [Enter] to open in browser" })
12239
+ ]
12147
12240
  }
12148
- }
12149
- )
12150
- ] }),
12151
- step === "await-approval" && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
12152
- /* @__PURE__ */ jsx7(Text6, { children: CARD_FLOW.approval.description }),
12153
- /* @__PURE__ */ jsxs4(
12154
- Box5,
12155
- {
12156
- flexDirection: "column",
12157
- borderStyle: "round",
12158
- borderColor: "cyan",
12159
- paddingX: 2,
12160
- paddingY: 1,
12161
- marginTop: 1,
12162
- children: [
12163
- /* @__PURE__ */ jsxs4(Text6, { children: [
12164
- "Approve at:",
12165
- " ",
12166
- /* @__PURE__ */ jsx7(Text6, { bold: true, color: "cyan", children: approvalUrl })
12167
- ] }),
12168
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: CARD_FLOW.approval.browserHint })
12169
- ]
12170
- }
12171
- ),
12172
- /* @__PURE__ */ jsx7(Box5, { marginY: 1, children: /* @__PURE__ */ jsx7(Text6, { color: "cyan", children: CARD_FLOW.approval.loading }) })
12173
- ] }),
12174
- step === "approval-timeout" && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
12175
- /* @__PURE__ */ jsx7(Text6, { color: "yellow", children: "\u26A0 Approval timed out (5 min). The spend request is still pending \u2014 you can still approve it." }),
12176
- /* @__PURE__ */ jsxs4(
12177
- Box5,
12178
- {
12179
- flexDirection: "column",
12180
- borderStyle: "round",
12181
- borderColor: "yellow",
12182
- paddingX: 2,
12183
- paddingY: 1,
12184
- marginTop: 1,
12185
- children: [
12186
- /* @__PURE__ */ jsxs4(Text6, { children: [
12187
- "Approve at:",
12188
- " ",
12189
- /* @__PURE__ */ jsx7(Text6, { bold: true, color: "cyan", children: approvalUrl })
12190
- ] }),
12191
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Press [Enter] to open in browser" })
12192
- ]
12193
- }
12194
- ),
12195
- /* @__PURE__ */ jsx7(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "r Retry polling q Quit demo" }) })
12241
+ ),
12242
+ /* @__PURE__ */ jsx7(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "r Retry polling q Quit demo" }) })
12243
+ ] })
12196
12244
  ] }),
12197
- pastStep("await-approval") && card && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
12245
+ (step === "show-card" || step === "open-url" || step === "done") && card && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
12198
12246
  /* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u2713 Approved!" }),
12199
12247
  /* @__PURE__ */ jsx7(MarkdownText, { children: CARD_FLOW.showCard.description }),
12200
- /* @__PURE__ */ jsxs4(
12201
- Box5,
12202
- {
12203
- flexDirection: "column",
12204
- borderStyle: "round",
12205
- borderColor: "green",
12206
- paddingX: 2,
12207
- paddingY: 1,
12208
- marginTop: 1,
12209
- children: [
12210
- /* @__PURE__ */ jsx7(Text6, { color: "yellow", dimColor: true, children: "[testmode card]" }),
12211
- /* @__PURE__ */ jsxs4(Text6, { children: [
12212
- "Number: ",
12213
- /* @__PURE__ */ jsx7(Text6, { bold: true, children: formatCardNumber(card.number) })
12214
- ] }),
12215
- /* @__PURE__ */ jsxs4(Text6, { children: [
12216
- "Exp:",
12217
- " ",
12218
- /* @__PURE__ */ jsx7(Text6, { bold: true, children: formatExpiry(card.exp_month, card.exp_year) })
12219
- ] }),
12220
- /* @__PURE__ */ jsxs4(Text6, { children: [
12221
- "CVC: ",
12222
- /* @__PURE__ */ jsx7(Text6, { bold: true, children: card.cvc })
12223
- ] }),
12224
- card.billing_address?.postal_code && /* @__PURE__ */ jsxs4(Text6, { children: [
12225
- "Zip: ",
12226
- /* @__PURE__ */ jsx7(Text6, { bold: true, children: card.billing_address.postal_code })
12227
- ] }),
12228
- card.valid_until && /* @__PURE__ */ jsxs4(Text6, { dimColor: true, children: [
12229
- "Expires:",
12230
- " ",
12231
- new Date(card.valid_until).toLocaleTimeString([], {
12232
- hour: "2-digit",
12233
- minute: "2-digit"
12234
- })
12235
- ] })
12236
- ]
12237
- }
12238
- ),
12239
- /* @__PURE__ */ jsx7(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx7(MarkdownText, { children: CARD_FLOW.showCard.openUrl }) }),
12248
+ /* @__PURE__ */ jsx7(Box5, { flexDirection: "column", paddingX: 2, marginTop: 1, children: /* @__PURE__ */ jsxs4(Text6, { children: [
12249
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Number " }),
12250
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: formatCardNumber(card.number) }),
12251
+ " ",
12252
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Exp " }),
12253
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: formatExpiry(card.exp_month, card.exp_year) }),
12254
+ " ",
12255
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "CVC " }),
12256
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: card.cvc }),
12257
+ card.billing_address?.postal_code && /* @__PURE__ */ jsxs4(Fragment, { children: [
12258
+ " ",
12259
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Zip " }),
12260
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: card.billing_address.postal_code })
12261
+ ] }),
12262
+ card.valid_until && /* @__PURE__ */ jsxs4(Fragment, { children: [
12263
+ " ",
12264
+ /* @__PURE__ */ jsxs4(Text6, { dimColor: true, children: [
12265
+ "expires",
12266
+ " ",
12267
+ new Date(card.valid_until).toLocaleTimeString([], {
12268
+ hour: "2-digit",
12269
+ minute: "2-digit"
12270
+ })
12271
+ ] })
12272
+ ] })
12273
+ ] }) }),
12240
12274
  step === "show-card" && prompt(CARD_FLOW.showCard.prompt)
12241
12275
  ] }),
12242
12276
  step === "done" && /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
12243
- /* @__PURE__ */ jsxs4(Box5, { flexDirection: "row", gap: 1, children: [
12244
- /* @__PURE__ */ jsx7(Text6, { color: "yellow", children: "[testmode]" }),
12245
- /* @__PURE__ */ jsxs4(Text6, { color: "green", children: [
12246
- "\u2713 ",
12247
- CARD_FLOW.done.success
12248
- ] })
12277
+ /* @__PURE__ */ jsxs4(Text6, { color: "green", children: [
12278
+ "\u2713 ",
12279
+ CARD_FLOW.done.success
12249
12280
  ] }),
12250
12281
  /* @__PURE__ */ jsx7(Text6, { children: CARD_FLOW.done.detail })
12251
12282
  ] }),
@@ -12258,7 +12289,7 @@ var CardFlow = ({
12258
12289
 
12259
12290
  // src/commands/demo/spt-flow.tsx
12260
12291
  import { Box as Box7, Text as Text8, useInput as useInput3 } from "ink";
12261
- import { useEffect as useEffect5, useRef as useRef2, useState as useState5 } from "react";
12292
+ import { useEffect as useEffect6, useRef as useRef2, useState as useState6 } from "react";
12262
12293
 
12263
12294
  // src/commands/mpp/decode.ts
12264
12295
  import { Challenge } from "mppx";
@@ -12344,7 +12375,7 @@ import Spinner2 from "ink-spinner";
12344
12375
  import { Credential, Method } from "mppx";
12345
12376
  import { Mppx, Transport } from "mppx/client";
12346
12377
  import { Methods as StripeMethods } from "mppx/stripe";
12347
- import { useEffect as useEffect4, useState as useState4 } from "react";
12378
+ import { useEffect as useEffect5, useState as useState5 } from "react";
12348
12379
  import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
12349
12380
  function buildHeaders(data, headers) {
12350
12381
  const result = {};
@@ -12450,10 +12481,10 @@ function MppPay({
12450
12481
  repository,
12451
12482
  onComplete
12452
12483
  }) {
12453
- const [step, setStep] = useState4("retrieving");
12454
- const [result, setResult] = useState4(null);
12455
- const [error, setError] = useState4(null);
12456
- useEffect4(() => {
12484
+ const [step, setStep] = useState5("retrieving");
12485
+ const [result, setResult] = useState5(null);
12486
+ const [error, setError] = useState5(null);
12487
+ useEffect5(() => {
12457
12488
  (async () => {
12458
12489
  try {
12459
12490
  setStep("retrieving");
@@ -12545,22 +12576,20 @@ function MppPay({
12545
12576
  }
12546
12577
 
12547
12578
  // src/commands/demo/spt-flow.tsx
12548
- import { Fragment, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
12579
+ import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
12549
12580
  var SptFlow = ({
12550
12581
  spendRequestRepo: spendRequestRepo2,
12551
12582
  paymentMethodsResource,
12552
12583
  paymentMethodId: initialPaymentMethodId,
12553
12584
  onComplete
12554
12585
  }) => {
12555
- const [step, setStep] = useState5("intro");
12556
- const [networkId, setNetworkId] = useState5("");
12557
- const [paymentMethods, setPaymentMethods] = useState5([]);
12558
- const [selectedPmIndex, setSelectedPmIndex] = useState5(0);
12559
- const [spendRequest, setSpendRequest] = useState5(null);
12560
- const [spendRequestPayload, setSpendRequestPayload] = useState5(null);
12561
- const [payResult, setPayResult] = useState5(null);
12562
- const [challengeData, setChallengeData] = useState5(null);
12563
- const [error, setError] = useState5("");
12586
+ const [step, setStep] = useState6("intro");
12587
+ const [networkId, setNetworkId] = useState6("");
12588
+ const [paymentMethods, setPaymentMethods] = useState6([]);
12589
+ const [selectedPmIndex, setSelectedPmIndex] = useState6(0);
12590
+ const [spendRequest, setSpendRequest] = useState6(null);
12591
+ const [payResult, setPayResult] = useState6(null);
12592
+ const [error, setError] = useState6("");
12564
12593
  const approvalUrl = spendRequest?.approval_url ?? "";
12565
12594
  const enterResolver = useRef2(null);
12566
12595
  const pmResolver = useRef2(null);
@@ -12613,7 +12642,7 @@ var SptFlow = ({
12613
12642
  }
12614
12643
  });
12615
12644
  const started = useRef2(false);
12616
- useEffect5(() => {
12645
+ useEffect6(() => {
12617
12646
  if (started.current) return;
12618
12647
  started.current = true;
12619
12648
  const run = async () => {
@@ -12652,17 +12681,10 @@ var SptFlow = ({
12652
12681
  const wwwAuth = probeResponse.headers.get("www-authenticate") ?? "";
12653
12682
  const decoded = decodeStripeChallenge(wwwAuth);
12654
12683
  setNetworkId(decoded.network_id);
12655
- setChallengeData({
12656
- status: probeResponse.status,
12657
- method: decoded.method,
12658
- intent: decoded.intent,
12659
- network_id: decoded.network_id,
12660
- realm: decoded.realm
12661
- });
12662
12684
  setStep("explain-402");
12663
12685
  await waitForEnter();
12664
12686
  setStep("create-spend");
12665
- const payload = {
12687
+ const result = await spendRequestRepo2.createSpendRequest({
12666
12688
  payment_details: pmId,
12667
12689
  credential_type: "shared_payment_token",
12668
12690
  network_id: decoded.network_id,
@@ -12670,9 +12692,7 @@ var SptFlow = ({
12670
12692
  context: DEMO_SPT_CONTEXT,
12671
12693
  request_approval: true,
12672
12694
  test: true
12673
- };
12674
- setSpendRequestPayload(payload);
12675
- const result = await spendRequestRepo2.createSpendRequest(payload);
12695
+ });
12676
12696
  setSpendRequest(result);
12677
12697
  setStep("await-approval");
12678
12698
  for (; ; ) {
@@ -12754,7 +12774,41 @@ var SptFlow = ({
12754
12774
  /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.intro.description }),
12755
12775
  /* @__PURE__ */ jsxs6(Box7, { marginTop: 1, flexDirection: "column", children: [
12756
12776
  /* @__PURE__ */ jsx9(Text8, { children: SPT_FLOW.intro.preamble }),
12757
- SPT_FLOW.intro.steps.map((s, i) => /* @__PURE__ */ jsx9(MarkdownText, { children: ` ${i + 1}. ${s}` }, s))
12777
+ SPT_FLOW.intro.steps.map((s, i) => {
12778
+ const doneAfter = [
12779
+ "pick-pm",
12780
+ "probe",
12781
+ "create-spend",
12782
+ "await-approval",
12783
+ "mpp-pay"
12784
+ ];
12785
+ const activeFrom = [
12786
+ "fetch-pm",
12787
+ "probe",
12788
+ "create-spend",
12789
+ "await-approval",
12790
+ "mpp-pay-gate"
12791
+ ];
12792
+ const done = pastStep(doneAfter[i]);
12793
+ const active = !done && (step === activeFrom[i] || pastStep(activeFrom[i]));
12794
+ const label = s.replace(/`/g, "");
12795
+ return done ? /* @__PURE__ */ jsxs6(Text8, { dimColor: true, strikethrough: true, children: [
12796
+ " ",
12797
+ i + 1,
12798
+ ". ",
12799
+ label
12800
+ ] }, s) : active ? /* @__PURE__ */ jsxs6(Text8, { bold: true, color: "cyan", children: [
12801
+ " ",
12802
+ i + 1,
12803
+ ". ",
12804
+ label
12805
+ ] }, s) : /* @__PURE__ */ jsxs6(Text8, { dimColor: true, children: [
12806
+ " ",
12807
+ i + 1,
12808
+ ". ",
12809
+ label
12810
+ ] }, s);
12811
+ })
12758
12812
  ] }),
12759
12813
  step === "intro" && prompt(SPT_FLOW.intro.prompt)
12760
12814
  ] }),
@@ -12773,146 +12827,90 @@ var SptFlow = ({
12773
12827
  ] }) }, pm.id)) }),
12774
12828
  /* @__PURE__ */ jsx9(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Use \u2191\u2193 to select, [Enter] to confirm" }) })
12775
12829
  ] }),
12776
- pastStep("fetch-pm") && /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
12830
+ (step === "probe" || step === "explain-402") && /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
12777
12831
  /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.probe.description }),
12778
- step === "probe" && /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: SPT_FLOW.probe.loading }) })
12832
+ step === "probe" && /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: SPT_FLOW.probe.loading }) }),
12833
+ step === "explain-402" && networkId && /* @__PURE__ */ jsxs6(Fragment2, { children: [
12834
+ /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.probe.detail }),
12835
+ /* @__PURE__ */ jsxs6(Text8, { color: "green", children: [
12836
+ "\u2713 Got HTTP 402 \u2014 network_id: ",
12837
+ /* @__PURE__ */ jsx9(Text8, { bold: true, children: networkId })
12838
+ ] }),
12839
+ prompt(SPT_FLOW.probe.prompt)
12840
+ ] })
12841
+ ] }),
12842
+ step === "create-spend" && /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
12843
+ /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.createSpend.description }),
12844
+ /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: SPT_FLOW.createSpend.loading }) })
12779
12845
  ] }),
12780
- pastStep("probe") && networkId && /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
12846
+ (step === "await-approval" || step === "approval-timeout") && spendRequest && /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
12781
12847
  /* @__PURE__ */ jsxs6(Text8, { color: "green", children: [
12782
- "\u2713 Got HTTP 402 with a ",
12783
- /* @__PURE__ */ jsx9(Text8, { bold: true, children: "WWW-Authenticate" }),
12784
- " challenge"
12848
+ "\u2713 Spend request created (",
12849
+ spendRequest.id,
12850
+ ")"
12785
12851
  ] }),
12786
- challengeData && /* @__PURE__ */ jsx9(StepData, { data: challengeData }),
12787
- /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.probe.detail }),
12788
- step === "explain-402" && prompt()
12789
- ] }),
12790
- pastStep("explain-402") && /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
12791
- /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.createSpend.description }),
12792
- spendRequestPayload && /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", marginTop: 1, children: [
12793
- /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "spend-request create" }),
12794
- /* @__PURE__ */ jsx9(
12852
+ step === "await-approval" && /* @__PURE__ */ jsxs6(Fragment2, { children: [
12853
+ /* @__PURE__ */ jsx9(Text8, { children: SPT_FLOW.approval.description }),
12854
+ /* @__PURE__ */ jsxs6(
12795
12855
  Box7,
12796
12856
  {
12797
12857
  flexDirection: "column",
12798
- borderStyle: "single",
12799
- borderColor: "gray",
12858
+ borderStyle: "round",
12859
+ borderColor: "cyan",
12800
12860
  paddingX: 2,
12801
- children: /* @__PURE__ */ jsx9(Text8, { children: JSON.stringify(
12802
- spendRequestPayload,
12803
- null,
12804
- 2
12805
- ) })
12861
+ paddingY: 1,
12862
+ marginTop: 1,
12863
+ children: [
12864
+ /* @__PURE__ */ jsxs6(Text8, { children: [
12865
+ "Approve at:",
12866
+ " ",
12867
+ /* @__PURE__ */ jsx9(Text8, { bold: true, color: "cyan", children: approvalUrl })
12868
+ ] }),
12869
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: SPT_FLOW.approval.browserHint })
12870
+ ]
12806
12871
  }
12807
- )
12808
- ] }),
12809
- step === "create-spend" && /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: SPT_FLOW.createSpend.loading }) })
12810
- ] }),
12811
- (step === "await-approval" || step === "approval-timeout" || pastStep("await-approval")) && spendRequest && /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
12812
- /* @__PURE__ */ jsxs6(Text8, { color: "green", children: [
12813
- "\u2713 Spend request created (ID: ",
12814
- /* @__PURE__ */ jsx9(Text8, { bold: true, children: spendRequest.id }),
12815
- ")"
12872
+ ),
12873
+ /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: SPT_FLOW.approval.loading }) })
12816
12874
  ] }),
12817
- /* @__PURE__ */ jsx9(
12818
- StepData,
12819
- {
12820
- data: {
12821
- id: spendRequest.id,
12822
- status: spendRequest.status,
12823
- credential_type: spendRequest.credential_type,
12824
- network_id: spendRequest.network_id,
12825
- amount: spendRequest.amount,
12826
- context: spendRequest.context,
12827
- approval_url: spendRequest.approval_url
12875
+ step === "approval-timeout" && /* @__PURE__ */ jsxs6(Fragment2, { children: [
12876
+ /* @__PURE__ */ jsx9(Text8, { color: "yellow", children: "\u26A0 Approval timed out (5 min). Still pending \u2014 you can still approve." }),
12877
+ /* @__PURE__ */ jsxs6(
12878
+ Box7,
12879
+ {
12880
+ flexDirection: "column",
12881
+ borderStyle: "round",
12882
+ borderColor: "yellow",
12883
+ paddingX: 2,
12884
+ paddingY: 1,
12885
+ marginTop: 1,
12886
+ children: [
12887
+ /* @__PURE__ */ jsxs6(Text8, { children: [
12888
+ "Approve at:",
12889
+ " ",
12890
+ /* @__PURE__ */ jsx9(Text8, { bold: true, color: "cyan", children: approvalUrl })
12891
+ ] }),
12892
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Press [Enter] to open in browser" })
12893
+ ]
12828
12894
  }
12829
- }
12830
- )
12831
- ] }),
12832
- step === "await-approval" && /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
12833
- /* @__PURE__ */ jsx9(Text8, { children: SPT_FLOW.approval.description }),
12834
- /* @__PURE__ */ jsxs6(
12835
- Box7,
12836
- {
12837
- flexDirection: "column",
12838
- borderStyle: "round",
12839
- borderColor: "cyan",
12840
- paddingX: 2,
12841
- paddingY: 1,
12842
- marginTop: 1,
12843
- children: [
12844
- /* @__PURE__ */ jsxs6(Text8, { children: [
12845
- "Approve at:",
12846
- " ",
12847
- /* @__PURE__ */ jsx9(Text8, { bold: true, color: "cyan", children: approvalUrl })
12848
- ] }),
12849
- /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: SPT_FLOW.approval.browserHint })
12850
- ]
12851
- }
12852
- ),
12853
- /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: SPT_FLOW.approval.loading }) })
12854
- ] }),
12855
- step === "approval-timeout" && /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
12856
- /* @__PURE__ */ jsx9(Text8, { color: "yellow", children: "\u26A0 Approval timed out (5 min). The spend request is still pending \u2014 you can still approve it." }),
12857
- /* @__PURE__ */ jsxs6(
12858
- Box7,
12859
- {
12860
- flexDirection: "column",
12861
- borderStyle: "round",
12862
- borderColor: "yellow",
12863
- paddingX: 2,
12864
- paddingY: 1,
12865
- marginTop: 1,
12866
- children: [
12867
- /* @__PURE__ */ jsxs6(Text8, { children: [
12868
- "Approve at:",
12869
- " ",
12870
- /* @__PURE__ */ jsx9(Text8, { bold: true, color: "cyan", children: approvalUrl })
12871
- ] }),
12872
- /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Press [Enter] to open in browser" })
12873
- ]
12874
- }
12875
- ),
12876
- /* @__PURE__ */ jsx9(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "r Retry polling q Quit demo" }) })
12895
+ ),
12896
+ /* @__PURE__ */ jsx9(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "r Retry polling q Quit demo" }) })
12897
+ ] })
12877
12898
  ] }),
12878
- pastStep("await-approval") && step !== "error" && /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
12879
- (step === "mpp-pay-gate" || pastStep("mpp-pay-gate")) && /* @__PURE__ */ jsxs6(Fragment, { children: [
12880
- /* @__PURE__ */ jsx9(Text8, { color: "green", children: "\u2713 Approved!" }),
12881
- /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.mppPay.description })
12882
- ] }),
12899
+ (step === "mpp-pay-gate" || step === "mpp-pay") && /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
12900
+ /* @__PURE__ */ jsx9(Text8, { color: "green", children: "\u2713 Approved!" }),
12901
+ /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.mppPay.description }),
12883
12902
  step === "mpp-pay-gate" && prompt(SPT_FLOW.mppPay.prompt),
12884
12903
  step === "mpp-pay" && /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: SPT_FLOW.mppPay.loading }) })
12885
12904
  ] }),
12886
12905
  step === "done" && payResult && /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
12887
- /* @__PURE__ */ jsxs6(
12888
- Box7,
12889
- {
12890
- flexDirection: "column",
12891
- borderStyle: "round",
12892
- borderColor: "green",
12893
- paddingX: 2,
12894
- paddingY: 1,
12895
- children: [
12896
- /* @__PURE__ */ jsx9(Text8, { bold: true, color: "green", children: SPT_FLOW.done.success }),
12897
- /* @__PURE__ */ jsxs6(Text8, { children: [
12898
- "Status: ",
12899
- /* @__PURE__ */ jsxs6(Text8, { bold: true, children: [
12900
- "HTTP ",
12901
- payResult.status
12902
- ] })
12903
- ] }),
12904
- payResult.body && (() => {
12905
- const body = payResult.body;
12906
- try {
12907
- return /* @__PURE__ */ jsx9(Text8, { children: JSON.stringify(JSON.parse(body), null, 2) });
12908
- } catch {
12909
- return /* @__PURE__ */ jsx9(Text8, { children: body });
12910
- }
12911
- })()
12912
- ]
12913
- }
12914
- ),
12915
- /* @__PURE__ */ jsx9(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.done.detail }) })
12906
+ /* @__PURE__ */ jsxs6(Text8, { bold: true, color: "green", children: [
12907
+ "\u2713 ",
12908
+ SPT_FLOW.done.success,
12909
+ " (HTTP ",
12910
+ payResult.status,
12911
+ ")"
12912
+ ] }),
12913
+ /* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.done.detail })
12916
12914
  ] }),
12917
12915
  step === "error" && /* @__PURE__ */ jsxs6(Text8, { color: "red", children: [
12918
12916
  "Error: ",
@@ -12922,7 +12920,7 @@ var SptFlow = ({
12922
12920
  };
12923
12921
 
12924
12922
  // src/commands/demo/demo-runner.tsx
12925
- import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
12923
+ import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
12926
12924
  var DemoRunner = ({
12927
12925
  authRepo: authRepo2,
12928
12926
  spendRequestRepo: spendRequestRepo2,
@@ -12933,17 +12931,17 @@ var DemoRunner = ({
12933
12931
  onComplete
12934
12932
  }) => {
12935
12933
  const preselected = onlyCard ? "card" : onlySpt ? "spt" : null;
12936
- const [choice, setChoice] = useState6(preselected);
12937
- const [menuIndex, setMenuIndex] = useState6(0);
12934
+ const [choice, setChoice] = useState7(preselected);
12935
+ const [menuIndex, setMenuIndex] = useState7(0);
12938
12936
  const postAuthPhase = preselected === "spt" ? "spt-flow" : preselected ? "card-flow" : "menu";
12939
- const [phase, setPhase] = useState6(
12937
+ const [phase, setPhase] = useState7(
12940
12938
  storage.isAuthenticated() ? postAuthPhase : "auth"
12941
12939
  );
12942
- const [paymentMethodId, setPaymentMethodId] = useState6(
12940
+ const [paymentMethodId, setPaymentMethodId] = useState7(
12943
12941
  preselectedPmId ?? ""
12944
12942
  );
12945
- const [cardSuccess, setCardSuccess] = useState6(null);
12946
- const [sptSuccess, setSptSuccess] = useState6(null);
12943
+ const [cardSuccess, setCardSuccess] = useState7(null);
12944
+ const [sptSuccess, setSptSuccess] = useState7(null);
12947
12945
  const runCard = choice === "card" || choice === "both";
12948
12946
  const runSpt = choice === "spt" || choice === "both";
12949
12947
  useInput4((_input, key) => {
@@ -12997,7 +12995,7 @@ var DemoRunner = ({
12997
12995
  ),
12998
12996
  phase === "menu" && /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", children: [
12999
12997
  /* @__PURE__ */ jsx10(Text9, { children: DEMO_MENU.question }),
13000
- /* @__PURE__ */ jsx10(Box8, { flexDirection: "column", marginTop: 1, gap: 1, children: DEMO_MENU.options.map((opt, i) => /* @__PURE__ */ jsx10(Box8, { flexDirection: "column", children: i === menuIndex ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
12998
+ /* @__PURE__ */ jsx10(Box8, { flexDirection: "column", marginTop: 1, gap: 1, children: DEMO_MENU.options.map((opt, i) => /* @__PURE__ */ jsx10(Box8, { flexDirection: "column", children: i === menuIndex ? /* @__PURE__ */ jsxs7(Fragment3, { children: [
13001
12999
  /* @__PURE__ */ jsxs7(Text9, { color: "cyan", bold: true, children: [
13002
13000
  ">",
13003
13001
  " ",
@@ -13244,7 +13242,7 @@ import { render as render4 } from "ink";
13244
13242
 
13245
13243
  // src/commands/onboard/onboard-runner.tsx
13246
13244
  import { Box as Box10, Text as Text11, useInput as useInput5 } from "ink";
13247
- import { useEffect as useEffect6, useRef as useRef3, useState as useState7 } from "react";
13245
+ import { useEffect as useEffect7, useRef as useRef3, useState as useState8 } from "react";
13248
13246
  import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
13249
13247
  var OnboardRunner = ({
13250
13248
  authRepo: authRepo2,
@@ -13252,10 +13250,10 @@ var OnboardRunner = ({
13252
13250
  paymentMethodsResource,
13253
13251
  onComplete
13254
13252
  }) => {
13255
- const [phase, setPhase] = useState7("welcome");
13256
- const [authSkipped, setAuthSkipped] = useState7(false);
13257
- const [pmMissing, setPmMissing] = useState7(false);
13258
- const [error, setError] = useState7("");
13253
+ const [phase, setPhase] = useState8("welcome");
13254
+ const [authSkipped, setAuthSkipped] = useState8(false);
13255
+ const [pmMissing, setPmMissing] = useState8(false);
13256
+ const [error, setError] = useState8("");
13259
13257
  const enterResolver = useRef3(null);
13260
13258
  function waitForEnter() {
13261
13259
  return new Promise((resolve) => {
@@ -13276,7 +13274,7 @@ var OnboardRunner = ({
13276
13274
  }
13277
13275
  });
13278
13276
  const started = useRef3(false);
13279
- useEffect6(() => {
13277
+ useEffect7(() => {
13280
13278
  if (started.current) return;
13281
13279
  started.current = true;
13282
13280
  const run = async () => {
@@ -13437,18 +13435,18 @@ var AddPaymentMethod = () => {
13437
13435
  // src/commands/payment-methods/list.tsx
13438
13436
  import { Box as Box12, Text as Text13 } from "ink";
13439
13437
  import Spinner3 from "ink-spinner";
13440
- import { useEffect as useEffect7, useState as useState8 } from "react";
13438
+ import { useEffect as useEffect8, useState as useState9 } from "react";
13441
13439
  import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
13442
13440
  var PaymentMethodsList = ({
13443
13441
  resource,
13444
13442
  onComplete
13445
13443
  }) => {
13446
- const [status, setStatus] = useState8(
13444
+ const [status, setStatus] = useState9(
13447
13445
  "loading"
13448
13446
  );
13449
- const [methods, setMethods] = useState8([]);
13450
- const [error, setError] = useState8("");
13451
- useEffect7(() => {
13447
+ const [methods, setMethods] = useState9([]);
13448
+ const [error, setError] = useState9("");
13449
+ useEffect8(() => {
13452
13450
  const fetch2 = async () => {
13453
13451
  try {
13454
13452
  const result = await resource.listPaymentMethods();
@@ -13621,7 +13619,7 @@ function parseTotalFlag(raw) {
13621
13619
  // src/commands/spend-request/create.tsx
13622
13620
  import { Box as Box14, Text as Text15 } from "ink";
13623
13621
  import Spinner5 from "ink-spinner";
13624
- import { useCallback as useCallback2, useEffect as useEffect9, useState as useState9 } from "react";
13622
+ import { useCallback as useCallback2, useEffect as useEffect10, useState as useState10 } from "react";
13625
13623
 
13626
13624
  // src/commands/spend-request/approval-waiting-view.tsx
13627
13625
  import { Box as Box13, Text as Text14 } from "ink";
@@ -13658,7 +13656,7 @@ var ApprovalWaitingView = ({
13658
13656
 
13659
13657
  // src/commands/spend-request/use-approval-polling.ts
13660
13658
  import { useInput as useInput7 } from "ink";
13661
- import { useEffect as useEffect8 } from "react";
13659
+ import { useEffect as useEffect9 } from "react";
13662
13660
  function useApprovalPolling({
13663
13661
  status,
13664
13662
  setStatus,
@@ -13676,12 +13674,12 @@ function useApprovalPolling({
13676
13674
  },
13677
13675
  { isActive: isWaiting }
13678
13676
  );
13679
- useEffect8(() => {
13677
+ useEffect9(() => {
13680
13678
  if (status !== "waiting") return;
13681
13679
  const timeout = setTimeout(() => setStatus("polling"), 1e3);
13682
13680
  return () => clearTimeout(timeout);
13683
13681
  }, [status, setStatus]);
13684
- useEffect8(() => {
13682
+ useEffect9(() => {
13685
13683
  if (status !== "polling" || !requestId) return;
13686
13684
  let cancelled = false;
13687
13685
  const poll = async () => {
@@ -13715,16 +13713,16 @@ function useApprovalPolling({
13715
13713
  }
13716
13714
 
13717
13715
  // src/commands/spend-request/create.tsx
13718
- import { Fragment as Fragment3, jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
13716
+ import { Fragment as Fragment4, jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
13719
13717
  var CreateSpendRequest = ({
13720
13718
  repository,
13721
13719
  params,
13722
13720
  requestApproval = false,
13723
13721
  onComplete
13724
13722
  }) => {
13725
- const [status, setStatus] = useState9("creating");
13726
- const [request, setRequest] = useState9(null);
13727
- const [error, setError] = useState9("");
13723
+ const [status, setStatus] = useState10("creating");
13724
+ const [request, setRequest] = useState10(null);
13725
+ const [error, setError] = useState10("");
13728
13726
  const approvalUrl = request?.approval_url ?? "";
13729
13727
  const onSuccess = useCallback2(
13730
13728
  (result) => setRequest(result),
@@ -13741,7 +13739,7 @@ var CreateSpendRequest = ({
13741
13739
  onSuccess,
13742
13740
  onError
13743
13741
  });
13744
- useEffect9(() => {
13742
+ useEffect10(() => {
13745
13743
  const create = async () => {
13746
13744
  try {
13747
13745
  const result = await repository.createSpendRequest(params);
@@ -13805,7 +13803,7 @@ var CreateSpendRequest = ({
13805
13803
  /* @__PURE__ */ jsx20(AppDownloadQrCodes, {})
13806
13804
  ] });
13807
13805
  }
13808
- return /* @__PURE__ */ jsxs13(Fragment3, { children: [
13806
+ return /* @__PURE__ */ jsxs13(Fragment4, { children: [
13809
13807
  /* @__PURE__ */ jsx20(Box14, { children: /* @__PURE__ */ jsxs13(Text15, { color: "green", children: [
13810
13808
  "\u2713 Spend request created (ID: ",
13811
13809
  /* @__PURE__ */ jsx20(Text15, { bold: true, children: request?.id }),
@@ -13824,17 +13822,17 @@ var CreateSpendRequest = ({
13824
13822
  // src/commands/spend-request/request-approval.tsx
13825
13823
  import { Box as Box15, Text as Text16 } from "ink";
13826
13824
  import Spinner6 from "ink-spinner";
13827
- import { useCallback as useCallback3, useEffect as useEffect10, useState as useState10 } from "react";
13825
+ import { useCallback as useCallback3, useEffect as useEffect11, useState as useState11 } from "react";
13828
13826
  import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
13829
13827
  var RequestApproval = ({
13830
13828
  repository,
13831
13829
  id,
13832
13830
  onComplete
13833
13831
  }) => {
13834
- const [status, setStatus] = useState10("requesting");
13835
- const [approvalUrl, setApprovalUrl] = useState10("");
13836
- const [result, setResult] = useState10(null);
13837
- const [error, setError] = useState10("");
13832
+ const [status, setStatus] = useState11("requesting");
13833
+ const [approvalUrl, setApprovalUrl] = useState11("");
13834
+ const [result, setResult] = useState11(null);
13835
+ const [error, setError] = useState11("");
13838
13836
  const onSuccess = useCallback3((r) => setResult(r), []);
13839
13837
  const onError = useCallback3((msg) => setError(msg), []);
13840
13838
  useApprovalPolling({
@@ -13847,7 +13845,7 @@ var RequestApproval = ({
13847
13845
  onSuccess,
13848
13846
  onError
13849
13847
  });
13850
- useEffect10(() => {
13848
+ useEffect11(() => {
13851
13849
  const request = async () => {
13852
13850
  try {
13853
13851
  const res = await repository.requestApproval(id);
@@ -13911,7 +13909,7 @@ var RequestApproval = ({
13911
13909
  // src/commands/spend-request/retrieve.tsx
13912
13910
  import { Box as Box16, Text as Text17 } from "ink";
13913
13911
  import Spinner7 from "ink-spinner";
13914
- import { useEffect as useEffect11, useRef as useRef4, useState as useState11 } from "react";
13912
+ import { useEffect as useEffect12, useRef as useRef4, useState as useState12 } from "react";
13915
13913
  import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
13916
13914
  var RetrieveSpendRequest = ({
13917
13915
  repository,
@@ -13920,20 +13918,20 @@ var RetrieveSpendRequest = ({
13920
13918
  include,
13921
13919
  onComplete
13922
13920
  }) => {
13923
- const [phase, setPhase] = useState11("fetching");
13924
- const [request, setRequest] = useState11(null);
13925
- const [error, setError] = useState11("");
13926
- const [elapsed, setElapsed] = useState11(0);
13921
+ const [phase, setPhase] = useState12("fetching");
13922
+ const [request, setRequest] = useState12(null);
13923
+ const [error, setError] = useState12("");
13924
+ const [elapsed, setElapsed] = useState12(0);
13927
13925
  const startTimeRef = useRef4(Date.now());
13928
13926
  const pollRef = useRef4(null);
13929
13927
  const timerRef = useRef4(null);
13930
- useEffect11(() => {
13928
+ useEffect12(() => {
13931
13929
  return () => {
13932
13930
  if (pollRef.current) clearInterval(pollRef.current);
13933
13931
  if (timerRef.current) clearInterval(timerRef.current);
13934
13932
  };
13935
13933
  }, []);
13936
- useEffect11(() => {
13934
+ useEffect12(() => {
13937
13935
  const fetch2 = async () => {
13938
13936
  try {
13939
13937
  const result = await repository.getSpendRequest(id, { include });
@@ -13962,7 +13960,7 @@ var RetrieveSpendRequest = ({
13962
13960
  };
13963
13961
  fetch2();
13964
13962
  }, [repository, id, include, onComplete]);
13965
- useEffect11(() => {
13963
+ useEffect12(() => {
13966
13964
  if (phase !== "polling") return;
13967
13965
  timerRef.current = setInterval(() => {
13968
13966
  const secs = Math.floor((Date.now() - startTimeRef.current) / 1e3);
@@ -14231,7 +14229,7 @@ var updateOptions = z6.object({
14231
14229
  // src/commands/spend-request/update.tsx
14232
14230
  import { Box as Box17, Text as Text18 } from "ink";
14233
14231
  import Spinner8 from "ink-spinner";
14234
- import { useEffect as useEffect12, useState as useState12 } from "react";
14232
+ import { useEffect as useEffect13, useState as useState13 } from "react";
14235
14233
  import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
14236
14234
  var UpdateSpendRequest = ({
14237
14235
  repository,
@@ -14239,12 +14237,12 @@ var UpdateSpendRequest = ({
14239
14237
  params,
14240
14238
  onComplete
14241
14239
  }) => {
14242
- const [status, setStatus] = useState12(
14240
+ const [status, setStatus] = useState13(
14243
14241
  "loading"
14244
14242
  );
14245
- const [request, setRequest] = useState12(null);
14246
- const [error, setError] = useState12("");
14247
- useEffect12(() => {
14243
+ const [request, setRequest] = useState13(null);
14244
+ const [error, setError] = useState13("");
14245
+ useEffect13(() => {
14248
14246
  const update = async () => {
14249
14247
  try {
14250
14248
  const result = await repository.updateSpendRequest(id, params);
@@ -14915,7 +14913,7 @@ var ResourceFactory = class {
14915
14913
  };
14916
14914
 
14917
14915
  // src/cli.tsx
14918
- var cliVersion = "0.3.0";
14916
+ var cliVersion = "0.3.1";
14919
14917
  var buildNumber = "1";
14920
14918
  var cliName = "@stripe/link-cli";
14921
14919
  var defaultHeaders = {