@stripe/link-cli 0.4.0 → 0.4.2
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.
- package/README.md +25 -0
- package/dist/cli.js +41 -13
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -71,6 +71,23 @@ The `--request-approval` flag triggers a push notification (or email) to the use
|
|
|
71
71
|
|
|
72
72
|
Users can easily approve requests with the [Link app](https://link.com/download).
|
|
73
73
|
|
|
74
|
+
#### Line items and totals
|
|
75
|
+
|
|
76
|
+
`--line-item` and `--total` use repeatable `key:value` format.
|
|
77
|
+
|
|
78
|
+
**`--line-item` keys:** `name` (required), `quantity`, `unit_amount`, `description`, `sku`, `url`, `image_url`, `product_url`
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
--line-item "name:Running Shoes,unit_amount:12000,quantity:1,description:Trail runners"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**`--total` keys:** `type` (required), `display_text` (required), `amount` (required)
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
--total "type:subtotal,display_text:Subtotal,amount:12000" \
|
|
88
|
+
--total "type:total,display_text:Total,amount:12000"
|
|
89
|
+
```
|
|
90
|
+
|
|
74
91
|
#### Credential types
|
|
75
92
|
|
|
76
93
|
By default, a spend request provisions a virtual card. For merchants that support the [Machine Payments Protocol](https://mpp.dev) (HTTP 402) and the Stripe payment method, you can instead include `--credential-type "shared_payment_token"`.
|
|
@@ -84,6 +101,14 @@ link-cli spend-request retrieve lsrq_001 --format json
|
|
|
84
101
|
```
|
|
85
102
|
By default, retrieving a spend request will not include card details. Use the `--include=card` to see unmasked card details.
|
|
86
103
|
|
|
104
|
+
For agent polling, pass `--interval` and optionally `--max-attempts`:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
link-cli spend-request retrieve lsrq_001 --interval 2 --max-attempts 150 --format json
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Polling exits successfully only after the request reaches a terminal status such as `approved`, `denied`, or `expired`. If polling reaches `--timeout` or exhausts `--max-attempts` while the request is still non-terminal, the command exits non-zero with `code: "POLLING_TIMEOUT"` so callers do not treat a still-pending request as complete.
|
|
111
|
+
|
|
87
112
|
If the merchant supports MPP, use `link-cli mpp pay` instead:
|
|
88
113
|
|
|
89
114
|
```bash
|
package/dist/cli.js
CHANGED
|
@@ -13590,8 +13590,13 @@ function parseKvString(raw) {
|
|
|
13590
13590
|
}
|
|
13591
13591
|
return result;
|
|
13592
13592
|
}
|
|
13593
|
-
function formatZodError(err, prefix) {
|
|
13593
|
+
function formatZodError(err, prefix, schema) {
|
|
13594
|
+
const allowed = Object.keys(schema.shape);
|
|
13594
13595
|
const messages = err.issues.map((issue) => {
|
|
13596
|
+
if (issue.code === "unrecognized_keys") {
|
|
13597
|
+
const keys = issue.keys.map((k) => `"${k}"`).join(", ");
|
|
13598
|
+
return `${prefix}: unrecognized key ${keys}. Allowed keys: ${allowed.join(", ")}`;
|
|
13599
|
+
}
|
|
13595
13600
|
const key = issue.path[0]?.toString();
|
|
13596
13601
|
return key ? `${prefix} ${key}: ${issue.message}` : `${prefix}: ${issue.message}`;
|
|
13597
13602
|
});
|
|
@@ -13602,7 +13607,8 @@ function parseLineItemFlag(raw) {
|
|
|
13602
13607
|
try {
|
|
13603
13608
|
return LineItemSchema.parse(obj);
|
|
13604
13609
|
} catch (err) {
|
|
13605
|
-
if (err instanceof z5.ZodError)
|
|
13610
|
+
if (err instanceof z5.ZodError)
|
|
13611
|
+
throw formatZodError(err, "Line item", LineItemSchema);
|
|
13606
13612
|
throw err;
|
|
13607
13613
|
}
|
|
13608
13614
|
}
|
|
@@ -13611,7 +13617,8 @@ function parseTotalFlag(raw) {
|
|
|
13611
13617
|
try {
|
|
13612
13618
|
return TotalSchema.parse(obj);
|
|
13613
13619
|
} catch (err) {
|
|
13614
|
-
if (err instanceof z5.ZodError)
|
|
13620
|
+
if (err instanceof z5.ZodError)
|
|
13621
|
+
throw formatZodError(err, "Total", TotalSchema);
|
|
13615
13622
|
throw err;
|
|
13616
13623
|
}
|
|
13617
13624
|
}
|
|
@@ -14199,19 +14206,27 @@ var createOptions = z6.object({
|
|
|
14199
14206
|
context: z6.string().min(100).describe(
|
|
14200
14207
|
"Min 100 chars \u2014 describe the purchase and rationale; the user reads this when approving"
|
|
14201
14208
|
),
|
|
14202
|
-
lineItem: z6.array(z6.union([z6.string(), z6.record(z6.string(), z6.unknown())])).default([]).describe(
|
|
14203
|
-
|
|
14209
|
+
lineItem: z6.array(z6.union([z6.string(), z6.record(z6.string(), z6.unknown())])).default([]).describe(
|
|
14210
|
+
'Line item (repeatable, key:value format). Keys: name (required), quantity, unit_amount, description, sku, url, image_url, product_url. Example: "name:Shoes,unit_amount:5000,quantity:2"'
|
|
14211
|
+
),
|
|
14212
|
+
total: z6.array(z6.union([z6.string(), z6.record(z6.string(), z6.unknown())])).default([]).describe(
|
|
14213
|
+
'Total (repeatable, key:value format). Keys: type (required), display_text (required), amount (required). Example: "type:total,display_text:Total,amount:5000"'
|
|
14214
|
+
),
|
|
14204
14215
|
requestApproval: z6.boolean().default(true).describe("Request approval and poll until approved/denied/expired"),
|
|
14205
14216
|
test: z6.boolean().default(false).describe(
|
|
14206
14217
|
"Use test mode (creates testmode credentials from test card data)"
|
|
14207
14218
|
)
|
|
14208
14219
|
});
|
|
14209
14220
|
var retrieveOptions = z6.object({
|
|
14210
|
-
timeout: z6.coerce.number().default(300).describe(
|
|
14221
|
+
timeout: z6.coerce.number().default(300).describe(
|
|
14222
|
+
"Polling timeout in seconds. When reached during active polling, exits non-zero with POLLING_TIMEOUT."
|
|
14223
|
+
),
|
|
14211
14224
|
interval: z6.coerce.number().default(0).describe(
|
|
14212
|
-
"Poll interval in seconds. When > 0, polls until status is terminal
|
|
14225
|
+
"Poll interval in seconds. When > 0, polls until status is terminal, timeout is reached, or max attempts are exhausted."
|
|
14226
|
+
),
|
|
14227
|
+
maxAttempts: z6.coerce.number().default(0).describe(
|
|
14228
|
+
"Max poll attempts. 0 = unlimited. Exhaustion during active polling exits non-zero with POLLING_TIMEOUT."
|
|
14213
14229
|
),
|
|
14214
|
-
maxAttempts: z6.coerce.number().default(0).describe("Max poll attempts. 0 = unlimited (use timeout instead)."),
|
|
14215
14230
|
include: z6.array(z6.string()).default([]).describe("Include extra data (repeatable, e.g. --include card)")
|
|
14216
14231
|
});
|
|
14217
14232
|
var updateOptions = z6.object({
|
|
@@ -14221,8 +14236,12 @@ var updateOptions = z6.object({
|
|
|
14221
14236
|
profileId: z6.string().optional().describe("Profile ID"),
|
|
14222
14237
|
merchantId: z6.string().optional().describe("Merchant ID"),
|
|
14223
14238
|
currency: z6.string().optional().describe("Currency code"),
|
|
14224
|
-
lineItem: z6.array(z6.union([z6.string(), z6.record(z6.string(), z6.unknown())])).default([]).describe(
|
|
14225
|
-
|
|
14239
|
+
lineItem: z6.array(z6.union([z6.string(), z6.record(z6.string(), z6.unknown())])).default([]).describe(
|
|
14240
|
+
'Line item (repeatable, key:value format). Keys: name (required), quantity, unit_amount, description, sku, url, image_url, product_url. Example: "name:Shoes,unit_amount:5000,quantity:2"'
|
|
14241
|
+
),
|
|
14242
|
+
total: z6.array(z6.union([z6.string(), z6.record(z6.string(), z6.unknown())])).default([]).describe(
|
|
14243
|
+
'Total (repeatable, key:value format). Keys: type (required), display_text (required), amount (required). Example: "type:total,display_text:Total,amount:5000"'
|
|
14244
|
+
)
|
|
14226
14245
|
});
|
|
14227
14246
|
|
|
14228
14247
|
// src/commands/spend-request/update.tsx
|
|
@@ -14600,11 +14619,20 @@ function createSpendRequestCli(repository) {
|
|
|
14600
14619
|
return;
|
|
14601
14620
|
}
|
|
14602
14621
|
attempts++;
|
|
14603
|
-
|
|
14604
|
-
if (shouldStop) {
|
|
14622
|
+
if (interval <= 0) {
|
|
14605
14623
|
yield request;
|
|
14606
14624
|
return;
|
|
14607
14625
|
}
|
|
14626
|
+
const maxAttemptsExhausted = maxAttempts > 0 && attempts >= maxAttempts;
|
|
14627
|
+
const timeoutReached = Date.now() >= deadline;
|
|
14628
|
+
if (maxAttemptsExhausted || timeoutReached) {
|
|
14629
|
+
const reason = maxAttemptsExhausted ? `max attempts (${maxAttempts}) exhausted` : `timeout (${timeout}s) reached`;
|
|
14630
|
+
return c.error({
|
|
14631
|
+
code: "POLLING_TIMEOUT",
|
|
14632
|
+
message: `Polling stopped before spend request ${id} reached a terminal status: ${reason}; current status is ${request.status}.`,
|
|
14633
|
+
retryable: true
|
|
14634
|
+
});
|
|
14635
|
+
}
|
|
14608
14636
|
const snapshot = JSON.stringify(request);
|
|
14609
14637
|
if (snapshot !== previousAttemptData) {
|
|
14610
14638
|
previousAttemptData = snapshot;
|
|
@@ -14917,7 +14945,7 @@ var ResourceFactory = class {
|
|
|
14917
14945
|
};
|
|
14918
14946
|
|
|
14919
14947
|
// src/cli.tsx
|
|
14920
|
-
var cliVersion = "0.4.
|
|
14948
|
+
var cliVersion = "0.4.2";
|
|
14921
14949
|
var buildNumber = "1";
|
|
14922
14950
|
var cliName = "@stripe/link-cli";
|
|
14923
14951
|
var defaultHeaders = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stripe/link-cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"link-cli": "./dist/cli.js"
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"ink": "^5.2.1",
|
|
26
26
|
"ink-spinner": "^5.0.0",
|
|
27
27
|
"mppx": "^0.5.7",
|
|
28
|
+
"viem": "^2.47.5",
|
|
28
29
|
"qrcode": "^1.5.4",
|
|
29
30
|
"react": "^18.3.1",
|
|
30
31
|
"update-notifier": "^7.3.1",
|