@agenzo/merchant-cli 0.9.4 → 0.9.6
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 +343 -343
- package/dist/index.js +557 -113
- package/dist/index.js.map +1 -1
- package/package.json +28 -28
package/dist/index.js
CHANGED
|
@@ -850,6 +850,12 @@ function render(result, opts) {
|
|
|
850
850
|
process.stdout.write(`${result.text()}
|
|
851
851
|
`);
|
|
852
852
|
}
|
|
853
|
+
function notify(format, type, message) {
|
|
854
|
+
if (format === "json") {
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
console.error(Formatter.status(type, message));
|
|
858
|
+
}
|
|
853
859
|
async function renderWithContext(result, opts, configManager) {
|
|
854
860
|
if (opts.format !== "json") {
|
|
855
861
|
render(result, opts);
|
|
@@ -904,6 +910,42 @@ function memberIdOf(opts) {
|
|
|
904
910
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
905
911
|
}
|
|
906
912
|
|
|
913
|
+
// src/price-annotation.ts
|
|
914
|
+
var ORIGINAL_DESCRIPTION = "Original (pre-discount) price in integer cents. Optional, RECORD-ONLY: stored on our own order / charge record and echoed back in the order detail, never sent to the acquiring gateway and never used to derive or validate the amount charged (that always comes from the order's locked authoritative price).";
|
|
915
|
+
var DISCOUNT_DESCRIPTION = "Discount amount in integer cents. Optional, RECORD-ONLY: same semantics as --original-amount-cents.";
|
|
916
|
+
var PRICE_ANNOTATION_FLAGS = {
|
|
917
|
+
"original-amount-cents": {
|
|
918
|
+
type: "int",
|
|
919
|
+
required: false,
|
|
920
|
+
description: ORIGINAL_DESCRIPTION,
|
|
921
|
+
constraints: "non-negative integer cents"
|
|
922
|
+
},
|
|
923
|
+
"discount-amount-cents": {
|
|
924
|
+
type: "int",
|
|
925
|
+
required: false,
|
|
926
|
+
description: DISCOUNT_DESCRIPTION,
|
|
927
|
+
constraints: "non-negative integer cents"
|
|
928
|
+
}
|
|
929
|
+
};
|
|
930
|
+
function applyPriceAnnotation(body, opts) {
|
|
931
|
+
const mappings = [
|
|
932
|
+
["--original-amount-cents", "originalAmountCents", "original_amount_cents"],
|
|
933
|
+
["--discount-amount-cents", "discountAmountCents", "discount_amount_cents"]
|
|
934
|
+
];
|
|
935
|
+
for (const [flag, optKey, bodyKey] of mappings) {
|
|
936
|
+
const raw = opts[optKey];
|
|
937
|
+
if (raw === void 0) continue;
|
|
938
|
+
const cents = Number(raw);
|
|
939
|
+
if (!Number.isInteger(cents) || cents < 0) {
|
|
940
|
+
throw new CliError(
|
|
941
|
+
"PARAM_INVALID",
|
|
942
|
+
`Invalid ${flag} "${raw}". Expected a non-negative integer number of cents (e.g. 10000 for 100.00).`
|
|
943
|
+
);
|
|
944
|
+
}
|
|
945
|
+
body[bodyKey] = cents;
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
|
|
907
949
|
// src/ride-elife/watch.ts
|
|
908
950
|
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
909
951
|
"At destination",
|
|
@@ -1244,7 +1286,8 @@ var ridePayOrderSchema = {
|
|
|
1244
1286
|
type: "string",
|
|
1245
1287
|
required: true,
|
|
1246
1288
|
description: "Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated"
|
|
1247
|
-
}
|
|
1289
|
+
},
|
|
1290
|
+
...PRICE_ANNOTATION_FLAGS
|
|
1248
1291
|
},
|
|
1249
1292
|
response: {
|
|
1250
1293
|
order_id: { type: "string", description: "Authoritative order_ref (rio_\u2026, = order document _id) that was settled" },
|
|
@@ -1434,6 +1477,123 @@ var rideTripStatusSchema = {
|
|
|
1434
1477
|
BOOKING_FAILED: "Transient upstream error. Retry once after 5s, or fall back to `ride-elife get` for whole-ride status."
|
|
1435
1478
|
}
|
|
1436
1479
|
};
|
|
1480
|
+
var RIDE_ORDER_ID_FLAG = {
|
|
1481
|
+
type: "string",
|
|
1482
|
+
required: true,
|
|
1483
|
+
description: "The numeric ride_id returned by book (NOT the rio_... order_id)"
|
|
1484
|
+
};
|
|
1485
|
+
var CALLBACK_IDEMPOTENCY_FLAG = {
|
|
1486
|
+
type: "string",
|
|
1487
|
+
required: true,
|
|
1488
|
+
description: "Unique key (1-128 chars [A-Za-z0-9_-]) forwarded verbatim as the Idempotency-Key header; never auto-generated"
|
|
1489
|
+
};
|
|
1490
|
+
var CALLBACK_SUBSCRIPTION_FLAGS = {
|
|
1491
|
+
"callback-url": { type: "string", required: true, description: "https URL that receives status events; internal addresses are rejected by the platform" },
|
|
1492
|
+
adapter: { type: "string", required: false, default: "techtanium_v1", description: "Outbound event shape" },
|
|
1493
|
+
"signature-mode": { type: "string", required: false, default: "off", description: "off / optional / required" },
|
|
1494
|
+
"callback-api-key": { type: "string", required: false, description: "API key sent to your endpoint; omit to keep the stored one (never echoed back)" },
|
|
1495
|
+
"rotate-secret": { type: "bool", required: false, default: false, description: "Issue a new signing secret; the old one stops verifying" },
|
|
1496
|
+
"idempotency-key": CALLBACK_IDEMPOTENCY_FLAG
|
|
1497
|
+
};
|
|
1498
|
+
var CALLBACK_SUBSCRIPTION_RESPONSE = {
|
|
1499
|
+
callback_url: { type: "string", description: "Registered destination" },
|
|
1500
|
+
adapter: { type: "string", description: "Outbound event shape" },
|
|
1501
|
+
signature_mode: { type: "string", description: "off / optional / required" },
|
|
1502
|
+
status: { type: "string", description: "Registration status" },
|
|
1503
|
+
callback_secret: { type: "string", description: "Signing secret \u2014 present ONLY in the set response that issued it; store it, it cannot be read back" }
|
|
1504
|
+
};
|
|
1505
|
+
var CALLBACK_ERRORS = {
|
|
1506
|
+
RIDE_NOT_FOUND: "The ride is not yours or does not exist; check the ride_id from book/list-orders.",
|
|
1507
|
+
PARAM_INVALID: "Fix the flag named in the message (https URL, signature-mode, ranges) and retry.",
|
|
1508
|
+
PARAM_IDEMPOTENCY_KEY_REQUIRED: "Supply --idempotency-key (1-128 chars [A-Za-z0-9_-]); the CLI never generates one under --yes."
|
|
1509
|
+
};
|
|
1510
|
+
var rideCallbackSetSchema = {
|
|
1511
|
+
cli: CLI_NAME,
|
|
1512
|
+
noun: NOUN,
|
|
1513
|
+
verb: "callback-set",
|
|
1514
|
+
description: "Register (or update) where one ride's status events are forwarded; takes priority over the default",
|
|
1515
|
+
flags: { "order-id": RIDE_ORDER_ID_FLAG, ...CALLBACK_SUBSCRIPTION_FLAGS },
|
|
1516
|
+
response: { ride_id: { type: "string|int", description: "Ride id" }, order_id: { type: "string", description: "rio_... order id" }, ...CALLBACK_SUBSCRIPTION_RESPONSE },
|
|
1517
|
+
example: {
|
|
1518
|
+
command: "agenzo-merchant-cli ride-elife callback-set --order-id 4112961 --callback-url https://example.com/ride-events --idempotency-key cb-1",
|
|
1519
|
+
output_summary: "Returns the registration; the first registration also returns callback_secret once."
|
|
1520
|
+
},
|
|
1521
|
+
error_recovery: CALLBACK_ERRORS
|
|
1522
|
+
};
|
|
1523
|
+
var rideCallbackGetSchema = {
|
|
1524
|
+
cli: CLI_NAME,
|
|
1525
|
+
noun: NOUN,
|
|
1526
|
+
verb: "callback-get",
|
|
1527
|
+
description: "Show one ride's callback registration (the signing secret is never returned)",
|
|
1528
|
+
flags: { "order-id": RIDE_ORDER_ID_FLAG },
|
|
1529
|
+
response: { ride_id: { type: "string|int", description: "Ride id" }, order_id: { type: "string", description: "rio_... order id" }, ...CALLBACK_SUBSCRIPTION_RESPONSE },
|
|
1530
|
+
example: { command: "agenzo-merchant-cli ride-elife callback-get --order-id 4112961", output_summary: "Returns the registration without the secret." },
|
|
1531
|
+
error_recovery: { RIDE_NOT_FOUND: CALLBACK_ERRORS.RIDE_NOT_FOUND }
|
|
1532
|
+
};
|
|
1533
|
+
var rideCallbackDefaultSetSchema = {
|
|
1534
|
+
cli: CLI_NAME,
|
|
1535
|
+
noun: NOUN,
|
|
1536
|
+
verb: "callback-default-set",
|
|
1537
|
+
description: "Register (or update) the developer-wide fallback used by rides that have no callback of their own",
|
|
1538
|
+
flags: CALLBACK_SUBSCRIPTION_FLAGS,
|
|
1539
|
+
response: { developer_id: { type: "string", description: "Owner of the default" }, ...CALLBACK_SUBSCRIPTION_RESPONSE },
|
|
1540
|
+
example: {
|
|
1541
|
+
command: "agenzo-merchant-cli ride-elife callback-default-set --callback-url https://example.com/ride-events --idempotency-key cbd-1",
|
|
1542
|
+
output_summary: "Configure once so events for rides booked later are never dropped."
|
|
1543
|
+
},
|
|
1544
|
+
error_recovery: { PARAM_INVALID: CALLBACK_ERRORS.PARAM_INVALID, PARAM_IDEMPOTENCY_KEY_REQUIRED: CALLBACK_ERRORS.PARAM_IDEMPOTENCY_KEY_REQUIRED }
|
|
1545
|
+
};
|
|
1546
|
+
var rideCallbackDefaultGetSchema = {
|
|
1547
|
+
cli: CLI_NAME,
|
|
1548
|
+
noun: NOUN,
|
|
1549
|
+
verb: "callback-default-get",
|
|
1550
|
+
description: "Show the developer-wide fallback callback (the signing secret is never returned)",
|
|
1551
|
+
flags: {},
|
|
1552
|
+
response: { developer_id: { type: "string", description: "Owner of the default" }, ...CALLBACK_SUBSCRIPTION_RESPONSE },
|
|
1553
|
+
example: { command: "agenzo-merchant-cli ride-elife callback-default-get", output_summary: "Returns the default without the secret." }
|
|
1554
|
+
};
|
|
1555
|
+
var rideCallbackDeliveriesSchema = {
|
|
1556
|
+
cli: CLI_NAME,
|
|
1557
|
+
noun: NOUN,
|
|
1558
|
+
verb: "callback-deliveries",
|
|
1559
|
+
description: "List one ride's callback forwarding records (pending / delivered / dead)",
|
|
1560
|
+
flags: {
|
|
1561
|
+
"order-id": RIDE_ORDER_ID_FLAG,
|
|
1562
|
+
limit: { type: "int", required: false, default: 50, description: "Page size 1-100" },
|
|
1563
|
+
offset: { type: "int", required: false, default: 0, description: "Records to skip" }
|
|
1564
|
+
},
|
|
1565
|
+
response: {
|
|
1566
|
+
ride_id: { type: "string|int", description: "Ride id" },
|
|
1567
|
+
limit: { type: "int", description: "Page size used" },
|
|
1568
|
+
offset: { type: "int", description: "Offset used" },
|
|
1569
|
+
count: { type: "int", description: "Records in this page" },
|
|
1570
|
+
deliveries: { type: "array", description: "Forwarding records: event_id, status, attempts, last_error, timestamps" }
|
|
1571
|
+
},
|
|
1572
|
+
example: { command: "agenzo-merchant-cli ride-elife callback-deliveries --order-id 4112961", output_summary: "Shows what was forwarded and where it stalled." },
|
|
1573
|
+
error_recovery: { RIDE_NOT_FOUND: CALLBACK_ERRORS.RIDE_NOT_FOUND, PARAM_INVALID: CALLBACK_ERRORS.PARAM_INVALID }
|
|
1574
|
+
};
|
|
1575
|
+
var rideCallbackReplaySchema = {
|
|
1576
|
+
cli: CLI_NAME,
|
|
1577
|
+
noun: NOUN,
|
|
1578
|
+
verb: "callback-replay",
|
|
1579
|
+
description: "Requeue one ride's dead (or failed) callback records; delivered records are never re-sent",
|
|
1580
|
+
flags: {
|
|
1581
|
+
"order-id": RIDE_ORDER_ID_FLAG,
|
|
1582
|
+
"event-id": { type: "string", required: false, description: "Requeue only this record (default: all dead records)" },
|
|
1583
|
+
"include-failed": { type: "bool", required: false, default: false, description: "Also requeue pending records that already failed" },
|
|
1584
|
+
"reset-attempts": { type: "bool", required: false, default: false, description: "Reset the retry counter of requeued records" },
|
|
1585
|
+
"idempotency-key": CALLBACK_IDEMPOTENCY_FLAG
|
|
1586
|
+
},
|
|
1587
|
+
response: {
|
|
1588
|
+
ride_id: { type: "string", description: "Ride id" },
|
|
1589
|
+
requeued: { type: "int", description: "Number of records set back to pending" }
|
|
1590
|
+
},
|
|
1591
|
+
example: {
|
|
1592
|
+
command: "agenzo-merchant-cli ride-elife callback-replay --order-id 4112961 --idempotency-key rp-1",
|
|
1593
|
+
output_summary: "Requeues dead records; the delivery worker re-sends them on its next pass."
|
|
1594
|
+
},
|
|
1595
|
+
error_recovery: CALLBACK_ERRORS
|
|
1596
|
+
};
|
|
1437
1597
|
var listOrdersSchema = {
|
|
1438
1598
|
cli: CLI_NAME,
|
|
1439
1599
|
noun: NOUN,
|
|
@@ -1728,6 +1888,7 @@ var hotelPayOrderSchema = {
|
|
|
1728
1888
|
description: "Unique key forwarded verbatim as the Idempotency-Key header; never auto-generated. Derive from business intent (e.g. hash(order_id + attempt)) and reuse the SAME key when retrying the same payment",
|
|
1729
1889
|
constraints: "1-128 chars [A-Za-z0-9_-]"
|
|
1730
1890
|
},
|
|
1891
|
+
...PRICE_ANNOTATION_FLAGS,
|
|
1731
1892
|
watch: { type: "bool", required: false, default: false, description: "Poll automatically on PAYMENT_NOT_COMPLETED until PAID or timeout. Each iteration emits one NDJSON line" },
|
|
1732
1893
|
"watch-interval": { type: "int", required: false, default: 5, description: "Seconds between poll attempts in --watch mode" },
|
|
1733
1894
|
"watch-timeout": { type: "int", required: false, default: 300, description: "Total seconds before giving up in --watch mode" }
|
|
@@ -2382,6 +2543,39 @@ var ordersPayBatchSchema = {
|
|
|
2382
2543
|
AUTHENTICATION_REQUIRED: "EVO requires cardholder 3DS: open three_ds_url, finish authentication, then replay pay-batch with the SAME idempotency-key (or use --watch to poll automatically)."
|
|
2383
2544
|
}
|
|
2384
2545
|
};
|
|
2546
|
+
var ordersGetPaymentGroupSchema = {
|
|
2547
|
+
cli: CLI_NAME,
|
|
2548
|
+
noun: ORDERS_NOUN,
|
|
2549
|
+
verb: "get-payment-group",
|
|
2550
|
+
description: "Get the status of an aggregate settlement created by `orders pay-batch` (read-only; never re-sends the payment)",
|
|
2551
|
+
flags: {
|
|
2552
|
+
"payment-group-id": { type: "string", required: true, description: "payment_group_id returned by `orders pay-batch` (1-64 chars)" }
|
|
2553
|
+
},
|
|
2554
|
+
response: {
|
|
2555
|
+
payment_group_id: { type: "string", description: "The payment group" },
|
|
2556
|
+
status: { type: "string", description: "settled | partially_settled | failed | uncertain" },
|
|
2557
|
+
currency: { type: "string", description: "ISO 4217 currency of the aggregate settlement" },
|
|
2558
|
+
total_amount: { type: "float", description: "Aggregate total in DECIMAL units" },
|
|
2559
|
+
per_order: {
|
|
2560
|
+
type: "array",
|
|
2561
|
+
description: "Per-order outcome, same shape as pay-batch",
|
|
2562
|
+
items: {
|
|
2563
|
+
order_id: { type: "string", description: "Order id" },
|
|
2564
|
+
domain: { type: "string", description: "hotel | flight | ride" },
|
|
2565
|
+
status: { type: "string", description: "confirmed | refunded | failed" },
|
|
2566
|
+
amount: { type: "float", description: "Authoritative order amount (decimal)" },
|
|
2567
|
+
refunded_amount: { type: "float", description: "Amount refunded when upstream confirmation failed" }
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
},
|
|
2571
|
+
example: {
|
|
2572
|
+
command: "agenzo-merchant-cli orders get-payment-group --payment-group-id pg_...",
|
|
2573
|
+
output_summary: "Returns the batch status and per-order results; use it instead of replaying pay-batch to check progress."
|
|
2574
|
+
},
|
|
2575
|
+
error_recovery: {
|
|
2576
|
+
PARAM_INVALID: "Pass the payment_group_id exactly as pay-batch returned it (1-64 chars)."
|
|
2577
|
+
}
|
|
2578
|
+
};
|
|
2385
2579
|
function flightSchema(verb, description, flags, response, example, extra = {}) {
|
|
2386
2580
|
return { cli: CLI_NAME, noun: FLIGHT_NOUN, verb, description, flags, response, example, ...extra };
|
|
2387
2581
|
}
|
|
@@ -2490,7 +2684,8 @@ var flightCreateOrderSchema = flightSchema(
|
|
|
2490
2684
|
"contact-region": { type: "string", required: true, description: "Contact phone country code (no +)." },
|
|
2491
2685
|
"contact-phone": { type: "string", required: true, description: "Contact phone." },
|
|
2492
2686
|
"contact-email": { type: "string", required: true, description: "Contact email." },
|
|
2493
|
-
passengers: { type: "json", required: true, description: 'JSON array of passengers. gender/id_type are STRINGS ("1"/"2"). child/infant require adult_passenger_name.' },
|
|
2687
|
+
passengers: { type: "json", required: true, description: 'JSON array of passengers. gender/id_type are STRINGS ("1"/"2"). child/infant require adult_passenger_name. A saved traveller can be passed as just {"traveller_token":"tvp_...","type":"adult"} (from token-cli travellers list); the server fills in the ID details.' },
|
|
2688
|
+
"save-travellers": { type: "bool", required: false, description: "Save the fully filled passengers of this order as frequent travellers. Set only when the user explicitly asked to save them." },
|
|
2494
2689
|
member: MEMBER_FLAG_SCHEMA,
|
|
2495
2690
|
"idempotency-key": { type: "string", required: true, description: "Forwarded verbatim as the Idempotency-Key header." }
|
|
2496
2691
|
},
|
|
@@ -2522,7 +2717,8 @@ var flightPayOrderSchema = flightSchema(
|
|
|
2522
2717
|
"return-url": { type: "string", required: false, description: "Optional 3DS/passkey return URL for the network-token authenticate path; falls back to the platform EVO_3DS_RETURN_URL." },
|
|
2523
2718
|
"authorized-charge-no": { type: "string", required: false, description: "Resume a network-token 3DS challenge: charge_no from a prior AUTHENTICATION_REQUIRED response (settled via resume_token), then triggers ticketing on success." },
|
|
2524
2719
|
"evo-explicit": { type: "bool", required: false, default: false, description: "[\u65B9\u6848 B/R16] Explicit opt-in to settle this pay_per_call order via the EVO bound-card fallback rail. Set true ONLY when the user explicitly chose EVO; forwarded to the pay body as evo_explicit=true. Without it, a pay_per_call settlement lacking --payment-token-id is hard-gated server-side." },
|
|
2525
|
-
"idempotency-key": { type: "string", required: true, description: "Forwarded verbatim as the Idempotency-Key header." }
|
|
2720
|
+
"idempotency-key": { type: "string", required: true, description: "Forwarded verbatim as the Idempotency-Key header." },
|
|
2721
|
+
...PRICE_ANNOTATION_FLAGS
|
|
2526
2722
|
},
|
|
2527
2723
|
{ order_no: { type: "string", description: "Our order reference." }, status: { type: "string", description: "PAID on success; AUTHENTICATION_REQUIRED when the card needs 3DS." } },
|
|
2528
2724
|
{ command: "agenzo-merchant-cli flight-flink pay-order --order-no ffo_... --idempotency-key k2", output_summary: "Order becomes PAID; poll get-order until TICKETED." }
|
|
@@ -2631,7 +2827,8 @@ var flightChangePaySchema = flightSchema(
|
|
|
2631
2827
|
"payment-method-id": { type: "string", required: false, description: "Optional bound-card id (EVO path)." },
|
|
2632
2828
|
"payment-token-id": { type: "string", required: false, description: "Optional UPI network-token id (unionpay charge path)." },
|
|
2633
2829
|
"authorized-merchant-trans-id": { type: "string", required: false, description: "Resume a 3DS challenge with the merchant trans id of the already-authorised preauth; the platform reuses and captures it instead of authorizing again." },
|
|
2634
|
-
"idempotency-key": { type: "string", required: true, description: "Idempotency-Key header." }
|
|
2830
|
+
"idempotency-key": { type: "string", required: true, description: "Idempotency-Key header." },
|
|
2831
|
+
...PRICE_ANNOTATION_FLAGS
|
|
2635
2832
|
},
|
|
2636
2833
|
{
|
|
2637
2834
|
change_order_no: { type: "string", description: "Change order number." },
|
|
@@ -3227,6 +3424,12 @@ function registerRidePayOrderCommand(parent, deps) {
|
|
|
3227
3424
|
).option(
|
|
3228
3425
|
"--idempotency-key <key>",
|
|
3229
3426
|
"Idempotency key forwarded verbatim as the Idempotency-Key header"
|
|
3427
|
+
).option(
|
|
3428
|
+
"--original-amount-cents <cents>",
|
|
3429
|
+
PRICE_ANNOTATION_FLAGS["original-amount-cents"].description
|
|
3430
|
+
).option(
|
|
3431
|
+
"--discount-amount-cents <cents>",
|
|
3432
|
+
PRICE_ANNOTATION_FLAGS["discount-amount-cents"].description
|
|
3230
3433
|
);
|
|
3231
3434
|
attachSchemaHelp(cmd, ridePayOrderSchema);
|
|
3232
3435
|
cmd.action(async () => {
|
|
@@ -3254,6 +3457,7 @@ function registerRidePayOrderCommand(parent, deps) {
|
|
|
3254
3457
|
if (opts.returnUrl !== void 0) body.return_url = opts.returnUrl;
|
|
3255
3458
|
if (authorizedChargeNo !== void 0) body.authorized_charge_no = authorizedChargeNo;
|
|
3256
3459
|
if (opts.evoExplicit) body.evo_explicit = true;
|
|
3460
|
+
applyPriceAnnotation(body, opts);
|
|
3257
3461
|
if (!isYes) {
|
|
3258
3462
|
const confirmed = await confirm3({
|
|
3259
3463
|
message: `Settle ride order ${orderId}? This charges the card and creates the ride (AWAITING_PAYMENT \u2192 PAID).`,
|
|
@@ -3744,6 +3948,185 @@ function registerListOrdersCommand(parent, deps) {
|
|
|
3744
3948
|
});
|
|
3745
3949
|
}
|
|
3746
3950
|
|
|
3951
|
+
// src/ride-elife/callback.ts
|
|
3952
|
+
var SIGNATURE_MODES = ["off", "optional", "required"];
|
|
3953
|
+
var DELIVERIES_LIMIT_MAX = 100;
|
|
3954
|
+
function need9(value, flag) {
|
|
3955
|
+
if (value === void 0 || String(value).trim() === "") {
|
|
3956
|
+
throw new CliError("PARAM_INVALID", `Missing required --${flag}.`);
|
|
3957
|
+
}
|
|
3958
|
+
return String(value);
|
|
3959
|
+
}
|
|
3960
|
+
function intFlag(value, flag, min, max) {
|
|
3961
|
+
if (value === void 0) return void 0;
|
|
3962
|
+
const parsed = Number(value);
|
|
3963
|
+
if (!Number.isInteger(parsed) || parsed < min || max !== void 0 && parsed > max) {
|
|
3964
|
+
const range = max === void 0 ? `>= ${min}` : `${min}-${max}`;
|
|
3965
|
+
throw new CliError("PARAM_INVALID", `--${flag} must be an integer ${range}.`);
|
|
3966
|
+
}
|
|
3967
|
+
return parsed;
|
|
3968
|
+
}
|
|
3969
|
+
async function apiKeyOf(opts) {
|
|
3970
|
+
return PromptEngine.resolveInput(opts.apiKey, {
|
|
3971
|
+
message: "API Key:",
|
|
3972
|
+
type: "password"
|
|
3973
|
+
});
|
|
3974
|
+
}
|
|
3975
|
+
function subscriptionBody(opts) {
|
|
3976
|
+
const body = { callback_url: need9(opts.callbackUrl, "callback-url") };
|
|
3977
|
+
if (opts.adapter !== void 0) body.adapter = need9(opts.adapter, "adapter");
|
|
3978
|
+
if (opts.signatureMode !== void 0) {
|
|
3979
|
+
const mode = String(opts.signatureMode);
|
|
3980
|
+
if (!SIGNATURE_MODES.includes(mode)) {
|
|
3981
|
+
throw new CliError("PARAM_INVALID", `--signature-mode must be one of ${SIGNATURE_MODES.join(" / ")}.`);
|
|
3982
|
+
}
|
|
3983
|
+
body.signature_mode = mode;
|
|
3984
|
+
}
|
|
3985
|
+
if (opts.callbackApiKey !== void 0) body.callback_api_key = String(opts.callbackApiKey);
|
|
3986
|
+
if (opts.rotateSecret) body.rotate_secret = true;
|
|
3987
|
+
return body;
|
|
3988
|
+
}
|
|
3989
|
+
function formatSubscription(data) {
|
|
3990
|
+
const lines = [];
|
|
3991
|
+
for (const key of ["ride_id", "order_id", "developer_id", "callback_url", "adapter", "signature_mode", "status"]) {
|
|
3992
|
+
if (data[key] !== void 0 && data[key] !== null) lines.push([key, String(data[key])]);
|
|
3993
|
+
}
|
|
3994
|
+
const out = [Formatter.keyValue(lines)];
|
|
3995
|
+
if (typeof data.callback_secret === "string" && data.callback_secret) {
|
|
3996
|
+
out.push("", Formatter.keyValue([["callback_secret", data.callback_secret]]));
|
|
3997
|
+
out.push("Save this signing secret now \u2014 it is shown only once and cannot be read back.");
|
|
3998
|
+
}
|
|
3999
|
+
return out.join("\n");
|
|
4000
|
+
}
|
|
4001
|
+
async function render2(data, text, format) {
|
|
4002
|
+
const commandResult = { data, text };
|
|
4003
|
+
await renderWithContext(commandResult, { format }, new ConfigManager());
|
|
4004
|
+
}
|
|
4005
|
+
function withSubscriptionFlags(cmd) {
|
|
4006
|
+
return cmd.option("--callback-url <url>", "https URL that receives ride status events (must not be an internal address)").option("--adapter <name>", "Outbound event shape (default techtanium_v1)").option("--signature-mode <mode>", "off / optional / required (default off)").option("--callback-api-key <key>", "API key the platform sends to your endpoint; omit to keep the stored one").option("--rotate-secret", "Issue a new HMAC signing secret (breaks verification with the old one)").option("--idempotency-key <key>", "Idempotency key forwarded verbatim as the Idempotency-Key header");
|
|
4007
|
+
}
|
|
4008
|
+
async function postSubscription(deps, cmd, path, commandPath, doneMessage) {
|
|
4009
|
+
const opts = cmd.optsWithGlobals();
|
|
4010
|
+
const format = resolveFormat(opts.format);
|
|
4011
|
+
const target = path(opts);
|
|
4012
|
+
const body = subscriptionBody(opts);
|
|
4013
|
+
const apiKey = await apiKeyOf(opts);
|
|
4014
|
+
const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey, {
|
|
4015
|
+
yes: Boolean(opts.yes),
|
|
4016
|
+
commandPath
|
|
4017
|
+
});
|
|
4018
|
+
const result = await deps.apiClient.post(
|
|
4019
|
+
target,
|
|
4020
|
+
{ type: "api-key", key: apiKey },
|
|
4021
|
+
body,
|
|
4022
|
+
{ "Idempotency-Key": idempotencyKey }
|
|
4023
|
+
);
|
|
4024
|
+
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
4025
|
+
notify(format, "success", doneMessage);
|
|
4026
|
+
await render2(result.data, () => formatSubscription(result.data), format);
|
|
4027
|
+
}
|
|
4028
|
+
async function getJson(deps, cmd, path, text, params) {
|
|
4029
|
+
const opts = cmd.optsWithGlobals();
|
|
4030
|
+
const format = resolveFormat(opts.format);
|
|
4031
|
+
const target = path(opts);
|
|
4032
|
+
const query = params?.(opts);
|
|
4033
|
+
const apiKey = await apiKeyOf(opts);
|
|
4034
|
+
const result = await deps.apiClient.get(target, { type: "api-key", key: apiKey }, query);
|
|
4035
|
+
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
4036
|
+
await render2(result.data, () => text(result.data), format);
|
|
4037
|
+
}
|
|
4038
|
+
var ridePath = (opts, suffix) => `/ride/${encodeURIComponent(need9(opts.orderId, "order-id"))}/callback${suffix}`;
|
|
4039
|
+
function registerRideCallbackCommands(parent, deps) {
|
|
4040
|
+
const set = withSubscriptionFlags(
|
|
4041
|
+
parent.command("callback-set").description("Register (or update) where one ride's status events are forwarded").option("--api-key <key>", "API Key for authentication (X-Api-Key)").option("--order-id <id>", "The numeric ride_id returned by book")
|
|
4042
|
+
);
|
|
4043
|
+
attachSchemaHelp(set, rideCallbackSetSchema);
|
|
4044
|
+
set.action(
|
|
4045
|
+
() => postSubscription(deps, set, (o) => ridePath(o, ""), "ride-elife callback-set", "Ride callback registered")
|
|
4046
|
+
);
|
|
4047
|
+
const get = parent.command("callback-get").description("Show one ride's callback registration (the signing secret is never returned)").option("--api-key <key>", "API Key for authentication (X-Api-Key)").option("--order-id <id>", "The numeric ride_id returned by book");
|
|
4048
|
+
attachSchemaHelp(get, rideCallbackGetSchema);
|
|
4049
|
+
get.action(() => getJson(deps, get, (o) => ridePath(o, ""), formatSubscription));
|
|
4050
|
+
const defSet = withSubscriptionFlags(
|
|
4051
|
+
parent.command("callback-default-set").description("Register (or update) the developer-wide fallback for rides without their own callback").option("--api-key <key>", "API Key for authentication (X-Api-Key)")
|
|
4052
|
+
);
|
|
4053
|
+
attachSchemaHelp(defSet, rideCallbackDefaultSetSchema);
|
|
4054
|
+
defSet.action(
|
|
4055
|
+
() => postSubscription(
|
|
4056
|
+
deps,
|
|
4057
|
+
defSet,
|
|
4058
|
+
() => "/ride/callback/default",
|
|
4059
|
+
"ride-elife callback-default-set",
|
|
4060
|
+
"Default ride callback registered"
|
|
4061
|
+
)
|
|
4062
|
+
);
|
|
4063
|
+
const defGet = parent.command("callback-default-get").description("Show the developer-wide fallback callback (the signing secret is never returned)").option("--api-key <key>", "API Key for authentication (X-Api-Key)");
|
|
4064
|
+
attachSchemaHelp(defGet, rideCallbackDefaultGetSchema);
|
|
4065
|
+
defGet.action(() => getJson(deps, defGet, () => "/ride/callback/default", formatSubscription));
|
|
4066
|
+
const deliveries = parent.command("callback-deliveries").description("List one ride's callback forwarding records (pending / delivered / dead)").option("--api-key <key>", "API Key for authentication (X-Api-Key)").option("--order-id <id>", "The numeric ride_id returned by book").option("--limit <n>", `Page size 1-${DELIVERIES_LIMIT_MAX} (default 50)`).option("--offset <n>", "Records to skip (default 0)");
|
|
4067
|
+
attachSchemaHelp(deliveries, rideCallbackDeliveriesSchema);
|
|
4068
|
+
deliveries.action(
|
|
4069
|
+
() => getJson(
|
|
4070
|
+
deps,
|
|
4071
|
+
deliveries,
|
|
4072
|
+
(o) => ridePath(o, "/deliveries"),
|
|
4073
|
+
(data) => {
|
|
4074
|
+
const rows = data.deliveries ?? [];
|
|
4075
|
+
if (rows.length === 0) return Formatter.status("info", "No callback deliveries");
|
|
4076
|
+
return Formatter.table(
|
|
4077
|
+
["Event", "Status", "Attempts", "Last error"],
|
|
4078
|
+
rows.map((r) => [
|
|
4079
|
+
String(r.event_id ?? "-"),
|
|
4080
|
+
String(r.status ?? "-"),
|
|
4081
|
+
String(r.attempts ?? "-"),
|
|
4082
|
+
String(r.last_error ?? "-")
|
|
4083
|
+
])
|
|
4084
|
+
);
|
|
4085
|
+
},
|
|
4086
|
+
(o) => {
|
|
4087
|
+
const limit = intFlag(o.limit, "limit", 1, DELIVERIES_LIMIT_MAX);
|
|
4088
|
+
const offset = intFlag(o.offset, "offset", 0);
|
|
4089
|
+
const params = {};
|
|
4090
|
+
if (limit !== void 0) params.limit = String(limit);
|
|
4091
|
+
if (offset !== void 0) params.offset = String(offset);
|
|
4092
|
+
return Object.keys(params).length > 0 ? params : void 0;
|
|
4093
|
+
}
|
|
4094
|
+
)
|
|
4095
|
+
);
|
|
4096
|
+
const replay = parent.command("callback-replay").description("Requeue one ride's dead (or failed) callback records; delivered records are never re-sent").option("--api-key <key>", "API Key for authentication (X-Api-Key)").option("--order-id <id>", "The numeric ride_id returned by book").option("--event-id <id>", "Requeue only this record (default: all dead records of the ride)").option("--include-failed", "Also requeue pending records that already failed at least once").option("--reset-attempts", "Reset the retry counter of requeued records").option("--idempotency-key <key>", "Idempotency key forwarded verbatim as the Idempotency-Key header");
|
|
4097
|
+
attachSchemaHelp(replay, rideCallbackReplaySchema);
|
|
4098
|
+
replay.action(async () => {
|
|
4099
|
+
const opts = replay.optsWithGlobals();
|
|
4100
|
+
const format = resolveFormat(opts.format);
|
|
4101
|
+
const target = ridePath(opts, "/replay");
|
|
4102
|
+
const body = {};
|
|
4103
|
+
if (opts.eventId !== void 0) body.event_id = need9(opts.eventId, "event-id");
|
|
4104
|
+
if (opts.includeFailed) body.include_failed = true;
|
|
4105
|
+
if (opts.resetAttempts) body.reset_attempts = true;
|
|
4106
|
+
const apiKey = await apiKeyOf(opts);
|
|
4107
|
+
const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey, {
|
|
4108
|
+
yes: Boolean(opts.yes),
|
|
4109
|
+
commandPath: "ride-elife callback-replay"
|
|
4110
|
+
});
|
|
4111
|
+
const result = await deps.apiClient.post(
|
|
4112
|
+
target,
|
|
4113
|
+
{ type: "api-key", key: apiKey },
|
|
4114
|
+
body,
|
|
4115
|
+
{ "Idempotency-Key": idempotencyKey }
|
|
4116
|
+
);
|
|
4117
|
+
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
4118
|
+
notify(format, "success", `Requeued ${String(result.data.requeued ?? 0)} callback record(s)`);
|
|
4119
|
+
await render2(
|
|
4120
|
+
result.data,
|
|
4121
|
+
() => Formatter.keyValue([
|
|
4122
|
+
["Ride ID", String(result.data.ride_id ?? "-")],
|
|
4123
|
+
["Requeued", String(result.data.requeued ?? 0)]
|
|
4124
|
+
]),
|
|
4125
|
+
format
|
|
4126
|
+
);
|
|
4127
|
+
});
|
|
4128
|
+
}
|
|
4129
|
+
|
|
3747
4130
|
// src/services/registry.ts
|
|
3748
4131
|
var SERVICE_REGISTRY = [
|
|
3749
4132
|
{
|
|
@@ -4308,7 +4691,7 @@ function registerOrdersPayBatchCommand(parent, deps) {
|
|
|
4308
4691
|
message: "API Key:",
|
|
4309
4692
|
type: "password"
|
|
4310
4693
|
});
|
|
4311
|
-
const orderIds = parseOrderIds(
|
|
4694
|
+
const orderIds = parseOrderIds(need10(opts.orderIds, "order-ids"));
|
|
4312
4695
|
const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey, {
|
|
4313
4696
|
yes: isYes,
|
|
4314
4697
|
commandPath: "orders pay-batch"
|
|
@@ -4378,22 +4761,59 @@ function registerOrdersPayBatchCommand(parent, deps) {
|
|
|
4378
4761
|
}
|
|
4379
4762
|
});
|
|
4380
4763
|
}
|
|
4381
|
-
function
|
|
4764
|
+
function need10(value, flag) {
|
|
4382
4765
|
if (value === void 0) {
|
|
4383
4766
|
throw new CliError("PARAM_INVALID", `Missing required --${flag}.`);
|
|
4384
4767
|
}
|
|
4385
4768
|
return value;
|
|
4386
4769
|
}
|
|
4387
4770
|
|
|
4771
|
+
// src/orders/get-payment-group.ts
|
|
4772
|
+
var PAYMENT_GROUP_ID_MAX = 64;
|
|
4773
|
+
function registerOrdersGetPaymentGroupCommand(parent, deps) {
|
|
4774
|
+
const cmd = parent.command("get-payment-group").description("Get the status of an aggregate settlement created by `orders pay-batch` (read-only)").option("--api-key <key>", "API Key for authentication (X-Api-Key)").requiredOption("--payment-group-id <id>", "payment_group_id returned by `orders pay-batch`");
|
|
4775
|
+
attachSchemaHelp(cmd, ordersGetPaymentGroupSchema);
|
|
4776
|
+
cmd.action(async () => {
|
|
4777
|
+
const opts = cmd.optsWithGlobals();
|
|
4778
|
+
const format = resolveFormat(opts.format);
|
|
4779
|
+
const groupId = String(opts.paymentGroupId ?? "").trim();
|
|
4780
|
+
if (!groupId || groupId.length > PAYMENT_GROUP_ID_MAX) {
|
|
4781
|
+
throw new CliError(
|
|
4782
|
+
"PARAM_INVALID",
|
|
4783
|
+
`--payment-group-id must be 1-${PAYMENT_GROUP_ID_MAX} characters.`
|
|
4784
|
+
);
|
|
4785
|
+
}
|
|
4786
|
+
const apiKey = await PromptEngine.resolveInput(opts.apiKey, {
|
|
4787
|
+
message: "API Key:",
|
|
4788
|
+
type: "password"
|
|
4789
|
+
});
|
|
4790
|
+
const spinner = format === "json" ? null : createSpinner("Fetching payment group...");
|
|
4791
|
+
const result = await deps.apiClient.get(
|
|
4792
|
+
`/orders/payment-groups/${encodeURIComponent(groupId)}`,
|
|
4793
|
+
{ type: "api-key", key: apiKey }
|
|
4794
|
+
);
|
|
4795
|
+
spinner?.stop();
|
|
4796
|
+
if (!result.success) {
|
|
4797
|
+
throw CliError.fromApi(result, { auth: "api-key" });
|
|
4798
|
+
}
|
|
4799
|
+
const data = result.data;
|
|
4800
|
+
const commandResult = {
|
|
4801
|
+
data,
|
|
4802
|
+
text: () => formatPayBatch(data)
|
|
4803
|
+
};
|
|
4804
|
+
await renderWithContext(commandResult, { format }, new ConfigManager());
|
|
4805
|
+
});
|
|
4806
|
+
}
|
|
4807
|
+
|
|
4388
4808
|
// src/hotel-redaug/search.ts
|
|
4389
|
-
function
|
|
4809
|
+
function need11(value, flag) {
|
|
4390
4810
|
if (value === void 0) {
|
|
4391
4811
|
throw new CliError("PARAM_INVALID", `Missing required --${flag}.`);
|
|
4392
4812
|
}
|
|
4393
4813
|
return value;
|
|
4394
4814
|
}
|
|
4395
4815
|
function num5(value, flag) {
|
|
4396
|
-
const n = Number(
|
|
4816
|
+
const n = Number(need11(value, flag));
|
|
4397
4817
|
if (!Number.isFinite(n)) {
|
|
4398
4818
|
throw new CliError("PARAM_INVALID", `--${flag} must be a number.`);
|
|
4399
4819
|
}
|
|
@@ -4415,7 +4835,7 @@ function positiveInt3(value, flag) {
|
|
|
4415
4835
|
}
|
|
4416
4836
|
var YMD_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
4417
4837
|
function stayDate(value, flag) {
|
|
4418
|
-
const raw =
|
|
4838
|
+
const raw = need11(value, flag);
|
|
4419
4839
|
if (!YMD_RE.test(raw)) {
|
|
4420
4840
|
throw new CliError("PARAM_INVALID", `--${flag} must be a YYYY-MM-DD date.`);
|
|
4421
4841
|
}
|
|
@@ -4487,7 +4907,7 @@ function registerHotelSearchCommand(parent, deps) {
|
|
|
4487
4907
|
const pageSize = positiveInt3(opts.pageSize, "page-size");
|
|
4488
4908
|
const body = {};
|
|
4489
4909
|
if (hasDestination) {
|
|
4490
|
-
body.destination_id =
|
|
4910
|
+
body.destination_id = need11(opts.destinationId, "destination-id");
|
|
4491
4911
|
} else {
|
|
4492
4912
|
body.lat = coord(opts.lat, "lat", -90, 90);
|
|
4493
4913
|
body.lng = coord(opts.lng, "lng", -180, 180);
|
|
@@ -4530,14 +4950,14 @@ function registerHotelSearchCommand(parent, deps) {
|
|
|
4530
4950
|
}
|
|
4531
4951
|
|
|
4532
4952
|
// src/hotel-redaug/quote.ts
|
|
4533
|
-
function
|
|
4953
|
+
function need12(value, flag) {
|
|
4534
4954
|
if (value === void 0) {
|
|
4535
4955
|
throw new CliError("PARAM_INVALID", `Missing required --${flag}.`);
|
|
4536
4956
|
}
|
|
4537
4957
|
return value;
|
|
4538
4958
|
}
|
|
4539
4959
|
function num6(value, flag) {
|
|
4540
|
-
const n = Number(
|
|
4960
|
+
const n = Number(need12(value, flag));
|
|
4541
4961
|
if (!Number.isFinite(n)) {
|
|
4542
4962
|
throw new CliError("PARAM_INVALID", `--${flag} must be a number.`);
|
|
4543
4963
|
}
|
|
@@ -4545,7 +4965,7 @@ function num6(value, flag) {
|
|
|
4545
4965
|
}
|
|
4546
4966
|
var YMD_RE2 = /^\d{4}-\d{2}-\d{2}$/;
|
|
4547
4967
|
function stayDate2(value, flag) {
|
|
4548
|
-
const raw =
|
|
4968
|
+
const raw = need12(value, flag);
|
|
4549
4969
|
if (!YMD_RE2.test(raw)) {
|
|
4550
4970
|
throw new CliError("PARAM_INVALID", `--${flag} must be a YYYY-MM-DD date.`);
|
|
4551
4971
|
}
|
|
@@ -4585,7 +5005,7 @@ function registerHotelQuoteCommand(parent, deps) {
|
|
|
4585
5005
|
message: "API Key:",
|
|
4586
5006
|
type: "password"
|
|
4587
5007
|
});
|
|
4588
|
-
const hotelId =
|
|
5008
|
+
const hotelId = need12(opts.hotelId, "hotel-id");
|
|
4589
5009
|
const checkIn = stayDate2(opts.checkIn, "check-in");
|
|
4590
5010
|
const checkOut = stayDate2(opts.checkOut, "check-out");
|
|
4591
5011
|
if (!(checkOut > checkIn)) {
|
|
@@ -4705,14 +5125,14 @@ function parseCancellation(raw) {
|
|
|
4705
5125
|
}
|
|
4706
5126
|
return parsed;
|
|
4707
5127
|
}
|
|
4708
|
-
function
|
|
5128
|
+
function need13(value, flag) {
|
|
4709
5129
|
if (value === void 0) {
|
|
4710
5130
|
throw new CliError("PARAM_INVALID", `Missing required --${flag}.`);
|
|
4711
5131
|
}
|
|
4712
5132
|
return value;
|
|
4713
5133
|
}
|
|
4714
5134
|
function num7(value, flag) {
|
|
4715
|
-
const n = Number(
|
|
5135
|
+
const n = Number(need13(value, flag));
|
|
4716
5136
|
if (!Number.isFinite(n)) {
|
|
4717
5137
|
throw new CliError("PARAM_INVALID", `--${flag} must be a number.`);
|
|
4718
5138
|
}
|
|
@@ -4720,7 +5140,7 @@ function num7(value, flag) {
|
|
|
4720
5140
|
}
|
|
4721
5141
|
var YMD_RE3 = /^\d{4}-\d{2}-\d{2}$/;
|
|
4722
5142
|
function stayDate3(value, flag) {
|
|
4723
|
-
const raw =
|
|
5143
|
+
const raw = need13(value, flag);
|
|
4724
5144
|
if (!YMD_RE3.test(raw)) {
|
|
4725
5145
|
throw new CliError("PARAM_INVALID", `--${flag} must be a YYYY-MM-DD date.`);
|
|
4726
5146
|
}
|
|
@@ -4792,18 +5212,18 @@ function registerHotelCreateOrderCommand(parent, deps) {
|
|
|
4792
5212
|
message: "API Key:",
|
|
4793
5213
|
type: "password"
|
|
4794
5214
|
});
|
|
4795
|
-
const productToken =
|
|
5215
|
+
const productToken = need13(opts.productToken, "product-token");
|
|
4796
5216
|
const totalAmount = num7(opts.totalAmount, "total-amount");
|
|
4797
|
-
const currency =
|
|
4798
|
-
const priceItems = parsePriceItems(
|
|
5217
|
+
const currency = need13(opts.currency, "currency");
|
|
5218
|
+
const priceItems = parsePriceItems(need13(opts.priceItems, "price-items"));
|
|
4799
5219
|
const checkIn = stayDate3(opts.checkIn, "check-in");
|
|
4800
5220
|
const checkOut = stayDate3(opts.checkOut, "check-out");
|
|
4801
5221
|
if (!(checkOut > checkIn)) {
|
|
4802
5222
|
throw new CliError("PARAM_INVALID", "--check-out must be strictly after --check-in.");
|
|
4803
5223
|
}
|
|
4804
|
-
const guestName =
|
|
4805
|
-
const contactName =
|
|
4806
|
-
const contactPhone =
|
|
5224
|
+
const guestName = need13(opts.guestName, "guest-name");
|
|
5225
|
+
const contactName = need13(opts.contactName, "contact-name");
|
|
5226
|
+
const contactPhone = need13(opts.contactPhone, "contact-phone");
|
|
4807
5227
|
const body = {
|
|
4808
5228
|
product_token: productToken,
|
|
4809
5229
|
total_amount: totalAmount,
|
|
@@ -5035,7 +5455,7 @@ function registerHotelPayOrderCommand(parent, deps) {
|
|
|
5035
5455
|
).option(
|
|
5036
5456
|
"--idempotency-key <key>",
|
|
5037
5457
|
"Idempotency key forwarded verbatim as the Idempotency-Key header"
|
|
5038
|
-
).option("--watch", "Poll until PAID or timeout (NDJSON output)", false).option(
|
|
5458
|
+
).option("--original-amount-cents <cents>", PRICE_ANNOTATION_FLAGS["original-amount-cents"].description).option("--discount-amount-cents <cents>", PRICE_ANNOTATION_FLAGS["discount-amount-cents"].description).option("--watch", "Poll until PAID or timeout (NDJSON output)", false).option(
|
|
5039
5459
|
"--watch-interval <seconds>",
|
|
5040
5460
|
"Seconds between polls when --watch is set",
|
|
5041
5461
|
String(DEFAULT_PAY_WATCH_INTERVAL_SECONDS)
|
|
@@ -5076,6 +5496,7 @@ function registerHotelPayOrderCommand(parent, deps) {
|
|
|
5076
5496
|
body.authorized_charge_no = opts.authorizedChargeNo;
|
|
5077
5497
|
}
|
|
5078
5498
|
if (opts.evoExplicit) body.evo_explicit = true;
|
|
5499
|
+
applyPriceAnnotation(body, opts);
|
|
5079
5500
|
if (!isYes) {
|
|
5080
5501
|
const confirmed = await confirm8({
|
|
5081
5502
|
message: `Settle hotel order ${orderId}? This moves money via the order's configured billing mode (monthly_settlement or pay_per_call).`,
|
|
@@ -5155,7 +5576,7 @@ function registerHotelPayOrderCommand(parent, deps) {
|
|
|
5155
5576
|
}
|
|
5156
5577
|
|
|
5157
5578
|
// src/hotel-redaug/get.ts
|
|
5158
|
-
function
|
|
5579
|
+
function need14(value, flag) {
|
|
5159
5580
|
if (value === void 0) {
|
|
5160
5581
|
throw new CliError("PARAM_INVALID", `Missing required --${flag}.`);
|
|
5161
5582
|
}
|
|
@@ -5219,7 +5640,7 @@ function registerHotelGetCommand(parent, deps) {
|
|
|
5219
5640
|
message: "API Key:",
|
|
5220
5641
|
type: "password"
|
|
5221
5642
|
});
|
|
5222
|
-
const orderId =
|
|
5643
|
+
const orderId = need14(opts.orderId, "order-id");
|
|
5223
5644
|
if (opts.watch) {
|
|
5224
5645
|
await watchOrderStatus(deps.apiClient, apiKey, orderId, {
|
|
5225
5646
|
intervalSeconds: resolveSeconds(
|
|
@@ -5253,7 +5674,7 @@ function registerHotelGetCommand(parent, deps) {
|
|
|
5253
5674
|
}
|
|
5254
5675
|
|
|
5255
5676
|
// src/hotel-redaug/cancel.ts
|
|
5256
|
-
function
|
|
5677
|
+
function need15(value, flag) {
|
|
5257
5678
|
if (value === void 0) {
|
|
5258
5679
|
throw new CliError("PARAM_INVALID", `Missing required --${flag}.`);
|
|
5259
5680
|
}
|
|
@@ -5306,8 +5727,8 @@ function registerHotelCancelCommand(parent, deps) {
|
|
|
5306
5727
|
message: "API Key:",
|
|
5307
5728
|
type: "password"
|
|
5308
5729
|
});
|
|
5309
|
-
const orderId =
|
|
5310
|
-
const fcOrderCode =
|
|
5730
|
+
const orderId = need15(opts.orderId, "order-id");
|
|
5731
|
+
const fcOrderCode = need15(opts.fcOrderCode, "fc-order-code");
|
|
5311
5732
|
const body = { fc_order_code: fcOrderCode };
|
|
5312
5733
|
if (opts.reason !== void 0) body.reason = opts.reason;
|
|
5313
5734
|
const idempotencyKey = await resolveIdempotencyKey(opts.idempotencyKey, {
|
|
@@ -5337,14 +5758,14 @@ function registerHotelCancelCommand(parent, deps) {
|
|
|
5337
5758
|
|
|
5338
5759
|
// src/hotel-redaug/checkout.ts
|
|
5339
5760
|
import { confirm as confirm9 } from "@inquirer/prompts";
|
|
5340
|
-
function
|
|
5761
|
+
function need16(value, flag) {
|
|
5341
5762
|
if (value === void 0) {
|
|
5342
5763
|
throw new CliError("PARAM_INVALID", `Missing required --${flag}.`);
|
|
5343
5764
|
}
|
|
5344
5765
|
return value;
|
|
5345
5766
|
}
|
|
5346
5767
|
function num8(value, flag) {
|
|
5347
|
-
const n = Number(
|
|
5768
|
+
const n = Number(need16(value, flag));
|
|
5348
5769
|
if (!Number.isFinite(n)) {
|
|
5349
5770
|
throw new CliError("PARAM_INVALID", `--${flag} must be a number.`);
|
|
5350
5771
|
}
|
|
@@ -5410,10 +5831,10 @@ function registerHotelCheckoutCommand(parent, deps) {
|
|
|
5410
5831
|
message: "API Key:",
|
|
5411
5832
|
type: "password"
|
|
5412
5833
|
});
|
|
5413
|
-
const orderId =
|
|
5414
|
-
const fcOrderCode =
|
|
5415
|
-
const reason =
|
|
5416
|
-
const checkoutRooms = parseCheckoutRooms(
|
|
5834
|
+
const orderId = need16(opts.orderId, "order-id");
|
|
5835
|
+
const fcOrderCode = need16(opts.fcOrderCode, "fc-order-code");
|
|
5836
|
+
const reason = need16(opts.reason, "reason");
|
|
5837
|
+
const checkoutRooms = parseCheckoutRooms(need16(opts.checkoutRooms, "checkout-rooms"));
|
|
5417
5838
|
const refundType = num8(opts.refundType, "refund-type");
|
|
5418
5839
|
const body = {
|
|
5419
5840
|
fc_order_code: fcOrderCode,
|
|
@@ -5456,7 +5877,7 @@ function registerHotelCheckoutCommand(parent, deps) {
|
|
|
5456
5877
|
}
|
|
5457
5878
|
|
|
5458
5879
|
// src/hotel-redaug/get-checkout.ts
|
|
5459
|
-
function
|
|
5880
|
+
function need17(value, flag) {
|
|
5460
5881
|
if (value === void 0) {
|
|
5461
5882
|
throw new CliError("PARAM_INVALID", `Missing required --${flag}.`);
|
|
5462
5883
|
}
|
|
@@ -5492,7 +5913,7 @@ function registerHotelGetCheckoutCommand(parent, deps) {
|
|
|
5492
5913
|
message: "API Key:",
|
|
5493
5914
|
type: "password"
|
|
5494
5915
|
});
|
|
5495
|
-
const taskOrderCode =
|
|
5916
|
+
const taskOrderCode = need17(opts.taskOrderCode, "task-order-code");
|
|
5496
5917
|
if (opts.watch) {
|
|
5497
5918
|
await watchCheckoutStatus(deps.apiClient, apiKey, taskOrderCode, {
|
|
5498
5919
|
intervalSeconds: resolveSeconds(
|
|
@@ -5596,7 +6017,7 @@ function registerHotelListOrdersCommand(parent, deps) {
|
|
|
5596
6017
|
}
|
|
5597
6018
|
|
|
5598
6019
|
// src/hotel-redaug/find-destination.ts
|
|
5599
|
-
function
|
|
6020
|
+
function need18(value, flag) {
|
|
5600
6021
|
if (value === void 0 || value.trim() === "") {
|
|
5601
6022
|
throw new CliError("PARAM_INVALID", `Missing required --${flag}.`);
|
|
5602
6023
|
}
|
|
@@ -5630,7 +6051,7 @@ function registerHotelFindDestinationCommand(parent, deps) {
|
|
|
5630
6051
|
message: "API Key:",
|
|
5631
6052
|
type: "password"
|
|
5632
6053
|
});
|
|
5633
|
-
const keyword =
|
|
6054
|
+
const keyword = need18(opts.keyword, "keyword");
|
|
5634
6055
|
const body = { keyword };
|
|
5635
6056
|
if (opts.dataType !== void 0) {
|
|
5636
6057
|
body.data_type = opts.dataType;
|
|
@@ -5654,14 +6075,14 @@ function registerHotelFindDestinationCommand(parent, deps) {
|
|
|
5654
6075
|
}
|
|
5655
6076
|
|
|
5656
6077
|
// src/hotel-redaug/hotel-filters.ts
|
|
5657
|
-
function
|
|
6078
|
+
function need19(value, flag) {
|
|
5658
6079
|
if (value === void 0 || value.trim() === "") {
|
|
5659
6080
|
throw new CliError("PARAM_INVALID", `Missing required --${flag}.`);
|
|
5660
6081
|
}
|
|
5661
6082
|
return value;
|
|
5662
6083
|
}
|
|
5663
6084
|
function num9(value, flag) {
|
|
5664
|
-
const n = Number(
|
|
6085
|
+
const n = Number(need19(value, flag));
|
|
5665
6086
|
if (!Number.isFinite(n)) {
|
|
5666
6087
|
throw new CliError("PARAM_INVALID", `--${flag} must be a number.`);
|
|
5667
6088
|
}
|
|
@@ -5741,7 +6162,7 @@ function registerHotelFiltersCommand(parent, deps) {
|
|
|
5741
6162
|
}
|
|
5742
6163
|
const body = {};
|
|
5743
6164
|
if (hasDestination) {
|
|
5744
|
-
body.destination_id =
|
|
6165
|
+
body.destination_id = need19(opts.destinationId, "destination-id");
|
|
5745
6166
|
} else {
|
|
5746
6167
|
body.lat = coord2(opts.lat, "lat", -90, 90);
|
|
5747
6168
|
body.lng = coord2(opts.lng, "lng", -180, 180);
|
|
@@ -5766,7 +6187,7 @@ function registerHotelFiltersCommand(parent, deps) {
|
|
|
5766
6187
|
}
|
|
5767
6188
|
|
|
5768
6189
|
// src/hotel-redaug/list-cities.ts
|
|
5769
|
-
function
|
|
6190
|
+
function need20(value, flag) {
|
|
5770
6191
|
if (value === void 0 || value.trim() === "") {
|
|
5771
6192
|
throw new CliError("PARAM_INVALID", `Missing required --${flag}.`);
|
|
5772
6193
|
}
|
|
@@ -5799,7 +6220,7 @@ function registerHotelListCitiesCommand(parent, deps) {
|
|
|
5799
6220
|
message: "API Key:",
|
|
5800
6221
|
type: "password"
|
|
5801
6222
|
});
|
|
5802
|
-
const country =
|
|
6223
|
+
const country = need20(opts.country, "country");
|
|
5803
6224
|
const body = { country_code: country };
|
|
5804
6225
|
const result = await deps.apiClient.post(
|
|
5805
6226
|
"/hotel/cities",
|
|
@@ -5820,7 +6241,7 @@ function registerHotelListCitiesCommand(parent, deps) {
|
|
|
5820
6241
|
}
|
|
5821
6242
|
|
|
5822
6243
|
// src/hotel-redaug/hotel-detail.ts
|
|
5823
|
-
function
|
|
6244
|
+
function need21(value, flag) {
|
|
5824
6245
|
if (value === void 0 || value.trim() === "") {
|
|
5825
6246
|
throw new CliError("PARAM_INVALID", `Missing required --${flag}.`);
|
|
5826
6247
|
}
|
|
@@ -5967,7 +6388,7 @@ function registerHotelDetailCommand(parent, deps) {
|
|
|
5967
6388
|
message: "API Key:",
|
|
5968
6389
|
type: "password"
|
|
5969
6390
|
});
|
|
5970
|
-
const hotelId =
|
|
6391
|
+
const hotelId = need21(opts.hotelId, "hotel-id");
|
|
5971
6392
|
const rawWithImages = opts.withImages;
|
|
5972
6393
|
const withImages = rawWithImages !== "false" && rawWithImages !== false;
|
|
5973
6394
|
const settings = parseSettings(opts.settings);
|
|
@@ -6175,14 +6596,14 @@ function registerHotelSkillCommand(parent) {
|
|
|
6175
6596
|
}
|
|
6176
6597
|
|
|
6177
6598
|
// src/flight-flink/_helpers.ts
|
|
6178
|
-
function
|
|
6599
|
+
function need22(value, flag) {
|
|
6179
6600
|
if (value === void 0) {
|
|
6180
6601
|
throw new CliError("PARAM_INVALID", `Missing required --${flag}.`);
|
|
6181
6602
|
}
|
|
6182
6603
|
return value;
|
|
6183
6604
|
}
|
|
6184
6605
|
function num10(value, flag) {
|
|
6185
|
-
const n = Number(
|
|
6606
|
+
const n = Number(need22(value, flag));
|
|
6186
6607
|
if (!Number.isFinite(n)) {
|
|
6187
6608
|
throw new CliError("PARAM_INVALID", `--${flag} must be a number.`);
|
|
6188
6609
|
}
|
|
@@ -6203,7 +6624,7 @@ function jsonArray(raw, flag) {
|
|
|
6203
6624
|
function resolveApiKey(flag) {
|
|
6204
6625
|
return PromptEngine.resolveInput(flag, { message: "API Key:", type: "password" });
|
|
6205
6626
|
}
|
|
6206
|
-
async function
|
|
6627
|
+
async function render3(data, format, text) {
|
|
6207
6628
|
const resolved = resolveFormat(format);
|
|
6208
6629
|
const result = { data, text: () => text(data) };
|
|
6209
6630
|
await renderWithContext(result, { format: resolved }, new ConfigManager());
|
|
@@ -6217,7 +6638,7 @@ function registerFindAirportCommand(parent, deps) {
|
|
|
6217
6638
|
const opts = cmd.optsWithGlobals();
|
|
6218
6639
|
const format = resolveFormat(opts.format);
|
|
6219
6640
|
const apiKey = await resolveApiKey(opts.apiKey);
|
|
6220
|
-
const keyword =
|
|
6641
|
+
const keyword = need22(opts.keyword, "keyword");
|
|
6221
6642
|
const spinner = format === "json" ? null : createSpinner("Resolving airports...");
|
|
6222
6643
|
const result = await deps.apiClient.post(
|
|
6223
6644
|
"/flight/find-airport",
|
|
@@ -6226,7 +6647,7 @@ function registerFindAirportCommand(parent, deps) {
|
|
|
6226
6647
|
);
|
|
6227
6648
|
spinner?.stop();
|
|
6228
6649
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6229
|
-
await
|
|
6650
|
+
await render3(
|
|
6230
6651
|
result.data,
|
|
6231
6652
|
opts.format,
|
|
6232
6653
|
(d) => JSON.stringify(d.airports ?? d, null, 2)
|
|
@@ -6255,7 +6676,7 @@ function registerListAirportsCommand(parent, deps) {
|
|
|
6255
6676
|
);
|
|
6256
6677
|
spinner?.stop();
|
|
6257
6678
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6258
|
-
await
|
|
6679
|
+
await render3(result.data, opts.format, (d) => JSON.stringify(d, null, 2));
|
|
6259
6680
|
});
|
|
6260
6681
|
}
|
|
6261
6682
|
|
|
@@ -6280,7 +6701,7 @@ function registerListAirlinesCommand(parent, deps) {
|
|
|
6280
6701
|
);
|
|
6281
6702
|
spinner?.stop();
|
|
6282
6703
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6283
|
-
await
|
|
6704
|
+
await render3(result.data, opts.format, (d) => JSON.stringify(d, null, 2));
|
|
6284
6705
|
});
|
|
6285
6706
|
}
|
|
6286
6707
|
|
|
@@ -6300,7 +6721,7 @@ function registerListNationalitiesCommand(parent, deps) {
|
|
|
6300
6721
|
);
|
|
6301
6722
|
spinner?.stop();
|
|
6302
6723
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6303
|
-
await
|
|
6724
|
+
await render3(result.data, opts.format, (d) => JSON.stringify(d, null, 2));
|
|
6304
6725
|
});
|
|
6305
6726
|
}
|
|
6306
6727
|
|
|
@@ -6314,7 +6735,7 @@ function registerSearchCommand(parent, deps) {
|
|
|
6314
6735
|
const apiKey = await resolveApiKey(opts.apiKey);
|
|
6315
6736
|
const body = {
|
|
6316
6737
|
trip_type: num10(opts.tripType, "trip-type"),
|
|
6317
|
-
journeys: jsonArray(
|
|
6738
|
+
journeys: jsonArray(need22(opts.journeys, "journeys"), "journeys"),
|
|
6318
6739
|
cabin_class: opts.cabinClass,
|
|
6319
6740
|
adult_num: num10(opts.adultNum, "adult-num"),
|
|
6320
6741
|
child_num: num10(opts.childNum, "child-num"),
|
|
@@ -6333,7 +6754,7 @@ function registerSearchCommand(parent, deps) {
|
|
|
6333
6754
|
);
|
|
6334
6755
|
spinner?.stop();
|
|
6335
6756
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6336
|
-
await
|
|
6757
|
+
await render3(result.data, opts.format, (d) => JSON.stringify(d, null, 2));
|
|
6337
6758
|
});
|
|
6338
6759
|
}
|
|
6339
6760
|
|
|
@@ -6345,7 +6766,7 @@ function registerMoreOffersCommand(parent, deps) {
|
|
|
6345
6766
|
const opts = cmd.optsWithGlobals();
|
|
6346
6767
|
const format = resolveFormat(opts.format);
|
|
6347
6768
|
const apiKey = await resolveApiKey(opts.apiKey);
|
|
6348
|
-
const productToken =
|
|
6769
|
+
const productToken = need22(opts.productToken, "product-token");
|
|
6349
6770
|
const spinner = format === "json" ? null : createSpinner("Fetching offers...");
|
|
6350
6771
|
const result = await deps.apiClient.post(
|
|
6351
6772
|
"/flight/more-offers",
|
|
@@ -6354,7 +6775,7 @@ function registerMoreOffersCommand(parent, deps) {
|
|
|
6354
6775
|
);
|
|
6355
6776
|
spinner?.stop();
|
|
6356
6777
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6357
|
-
await
|
|
6778
|
+
await render3(result.data, opts.format, (d) => JSON.stringify(d, null, 2));
|
|
6358
6779
|
});
|
|
6359
6780
|
}
|
|
6360
6781
|
|
|
@@ -6366,7 +6787,7 @@ function registerVerifyCommand(parent, deps) {
|
|
|
6366
6787
|
const opts = cmd.optsWithGlobals();
|
|
6367
6788
|
const format = resolveFormat(opts.format);
|
|
6368
6789
|
const apiKey = await resolveApiKey(opts.apiKey);
|
|
6369
|
-
const productToken =
|
|
6790
|
+
const productToken = need22(opts.productToken, "product-token");
|
|
6370
6791
|
const body = { product_token: productToken };
|
|
6371
6792
|
if (opts.previousTotalPrice !== void 0) {
|
|
6372
6793
|
body.previous_total_price = num10(opts.previousTotalPrice, "previous-total-price");
|
|
@@ -6383,7 +6804,7 @@ function registerVerifyCommand(parent, deps) {
|
|
|
6383
6804
|
);
|
|
6384
6805
|
spinner?.stop();
|
|
6385
6806
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6386
|
-
await
|
|
6807
|
+
await render3(
|
|
6387
6808
|
result.data,
|
|
6388
6809
|
opts.format,
|
|
6389
6810
|
(d) => Formatter.keyValue([
|
|
@@ -6400,7 +6821,10 @@ function registerVerifyCommand(parent, deps) {
|
|
|
6400
6821
|
// src/flight-flink/create-order.ts
|
|
6401
6822
|
import { confirm as confirm10 } from "@inquirer/prompts";
|
|
6402
6823
|
function registerCreateOrderCommand(parent, deps) {
|
|
6403
|
-
const cmd = parent.command("create-order").description("Create a flight order without charging (locks the fare, await payment)").option("--api-key <key>", "API Key for authentication (X-Api-Key)").option("--product-token <token>", "Authoritative rate token from verify").option("--total-amount <amount>", "Verified total price in decimal units").option("--currency <currency>", "ISO 4217 currency code").option("--trip-type <n>", "1/2/3", "1").option("--contact-name <name>", "Booking contact name").option("--contact-region <code>", "Contact phone country code (no '+')").option("--contact-phone <phone>", "Booking contact phone").option("--contact-email <email>", "Booking contact email").option(
|
|
6824
|
+
const cmd = parent.command("create-order").description("Create a flight order without charging (locks the fare, await payment)").option("--api-key <key>", "API Key for authentication (X-Api-Key)").option("--product-token <token>", "Authoritative rate token from verify").option("--total-amount <amount>", "Verified total price in decimal units").option("--currency <currency>", "ISO 4217 currency code").option("--trip-type <n>", "1/2/3", "1").option("--contact-name <name>", "Booking contact name").option("--contact-region <code>", "Contact phone country code (no '+')").option("--contact-phone <phone>", "Booking contact phone").option("--contact-email <email>", "Booking contact email").option(
|
|
6825
|
+
"--passengers <json>",
|
|
6826
|
+
'JSON array of passengers (gender/id_type are strings). A passenger may be just {"traveller_token":"tvp_...","type":"adult"} from token-cli travellers list.'
|
|
6827
|
+
).option("--save-travellers", "Save the fully filled passengers as frequent travellers (only when the user asked)").option("--payment-method-id <id>", "Optional bound-card id (pay_per_call only)").option("--payment-token-id <id>", "Optional UPI network-token id (unionpay charge path)").option(
|
|
6404
6828
|
"--authorized-merchant-trans-id <id>",
|
|
6405
6829
|
"EVO merchant transaction id of an already-authorised preauth (3DS challenge resume). When set, the server reuses that authorization instead of creating a new one, avoiding a second hold on the card (pay_per_call mode only)."
|
|
6406
6830
|
).option("--member <id>", MEMBER_OPTION_DESCRIPTION).option("--idempotency-key <key>", "Forwarded verbatim as the Idempotency-Key header");
|
|
@@ -6410,20 +6834,21 @@ function registerCreateOrderCommand(parent, deps) {
|
|
|
6410
6834
|
const format = resolveFormat(opts.format);
|
|
6411
6835
|
const isYes = Boolean(opts.yes);
|
|
6412
6836
|
const apiKey = await resolveApiKey(opts.apiKey);
|
|
6413
|
-
const productToken =
|
|
6837
|
+
const productToken = need22(opts.productToken, "product-token");
|
|
6414
6838
|
const totalAmount = num10(opts.totalAmount, "total-amount");
|
|
6415
|
-
const currency =
|
|
6839
|
+
const currency = need22(opts.currency, "currency");
|
|
6416
6840
|
const body = {
|
|
6417
6841
|
product_token: productToken,
|
|
6418
6842
|
total_amount: totalAmount,
|
|
6419
6843
|
currency,
|
|
6420
6844
|
trip_type: num10(opts.tripType, "trip-type"),
|
|
6421
|
-
contact_name:
|
|
6422
|
-
contact_region:
|
|
6423
|
-
contact_phone:
|
|
6424
|
-
contact_email:
|
|
6425
|
-
passengers: jsonArray(
|
|
6845
|
+
contact_name: need22(opts.contactName, "contact-name"),
|
|
6846
|
+
contact_region: need22(opts.contactRegion, "contact-region"),
|
|
6847
|
+
contact_phone: need22(opts.contactPhone, "contact-phone"),
|
|
6848
|
+
contact_email: need22(opts.contactEmail, "contact-email"),
|
|
6849
|
+
passengers: jsonArray(need22(opts.passengers, "passengers"), "passengers")
|
|
6426
6850
|
};
|
|
6851
|
+
if (opts.saveTravellers) body.save_travellers = true;
|
|
6427
6852
|
if (opts.paymentMethodId !== void 0) body.payment_method_id = opts.paymentMethodId;
|
|
6428
6853
|
if (opts.paymentTokenId !== void 0) body.payment_token_id = opts.paymentTokenId;
|
|
6429
6854
|
if (opts.authorizedMerchantTransId) {
|
|
@@ -6451,7 +6876,7 @@ function registerCreateOrderCommand(parent, deps) {
|
|
|
6451
6876
|
);
|
|
6452
6877
|
spinner?.stop();
|
|
6453
6878
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6454
|
-
await
|
|
6879
|
+
await render3(
|
|
6455
6880
|
result.data,
|
|
6456
6881
|
opts.format,
|
|
6457
6882
|
(d) => [
|
|
@@ -6488,14 +6913,20 @@ function registerPayOrderCommand(parent, deps) {
|
|
|
6488
6913
|
).option(
|
|
6489
6914
|
"--evo-explicit",
|
|
6490
6915
|
"[\u65B9\u6848 B/R16] Explicit opt-in to settle this pay_per_call order via the EVO bound-card fallback rail. Set ONLY when the user explicitly chose EVO; forwarded to the pay body as evo_explicit=true. Without it, a pay_per_call settlement lacking --payment-token-id is hard-gated server-side."
|
|
6491
|
-
).option("--idempotency-key <key>", "Forwarded verbatim as the Idempotency-Key header")
|
|
6916
|
+
).option("--idempotency-key <key>", "Forwarded verbatim as the Idempotency-Key header").option(
|
|
6917
|
+
"--original-amount-cents <cents>",
|
|
6918
|
+
PRICE_ANNOTATION_FLAGS["original-amount-cents"].description
|
|
6919
|
+
).option(
|
|
6920
|
+
"--discount-amount-cents <cents>",
|
|
6921
|
+
PRICE_ANNOTATION_FLAGS["discount-amount-cents"].description
|
|
6922
|
+
);
|
|
6492
6923
|
attachSchemaHelp(cmd, flightPayOrderSchema);
|
|
6493
6924
|
cmd.action(async () => {
|
|
6494
6925
|
const opts = cmd.optsWithGlobals();
|
|
6495
6926
|
const format = resolveFormat(opts.format);
|
|
6496
6927
|
const isYes = Boolean(opts.yes);
|
|
6497
6928
|
const apiKey = await resolveApiKey(opts.apiKey);
|
|
6498
|
-
const orderNo =
|
|
6929
|
+
const orderNo = need22(opts.orderNo, "order-no");
|
|
6499
6930
|
if (!isYes) {
|
|
6500
6931
|
const ok = await confirm11({
|
|
6501
6932
|
message: `Pay and ticket order ${orderNo}? This settles the order and issues tickets.`,
|
|
@@ -6520,6 +6951,7 @@ function registerPayOrderCommand(parent, deps) {
|
|
|
6520
6951
|
body.authorized_charge_no = opts.authorizedChargeNo;
|
|
6521
6952
|
}
|
|
6522
6953
|
if (opts.evoExplicit) body.evo_explicit = true;
|
|
6954
|
+
applyPriceAnnotation(body, opts);
|
|
6523
6955
|
const result = await deps.apiClient.post(
|
|
6524
6956
|
`/flight/${encodeURIComponent(orderNo)}/pay`,
|
|
6525
6957
|
{ type: "api-key", key: apiKey },
|
|
@@ -6528,7 +6960,7 @@ function registerPayOrderCommand(parent, deps) {
|
|
|
6528
6960
|
);
|
|
6529
6961
|
spinner?.stop();
|
|
6530
6962
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6531
|
-
await
|
|
6963
|
+
await render3(result.data, opts.format, (d) => {
|
|
6532
6964
|
const rows = [
|
|
6533
6965
|
["Order no", String(d.order_no ?? "-")],
|
|
6534
6966
|
["Status", String(d.status ?? "-")],
|
|
@@ -6553,7 +6985,7 @@ function registerGetOrderCommand(parent, deps) {
|
|
|
6553
6985
|
const opts = cmd.optsWithGlobals();
|
|
6554
6986
|
const format = resolveFormat(opts.format);
|
|
6555
6987
|
const apiKey = await resolveApiKey(opts.apiKey);
|
|
6556
|
-
const orderNo =
|
|
6988
|
+
const orderNo = need22(opts.orderNo, "order-no");
|
|
6557
6989
|
const path = `/flight/${encodeURIComponent(orderNo)}/status`;
|
|
6558
6990
|
const auth = { type: "api-key", key: apiKey };
|
|
6559
6991
|
if (opts.watch) {
|
|
@@ -6578,7 +7010,7 @@ function registerGetOrderCommand(parent, deps) {
|
|
|
6578
7010
|
const result = await deps.apiClient.get(path, auth);
|
|
6579
7011
|
spinner?.stop();
|
|
6580
7012
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6581
|
-
await
|
|
7013
|
+
await render3(
|
|
6582
7014
|
result.data,
|
|
6583
7015
|
opts.format,
|
|
6584
7016
|
(d) => Formatter.keyValue([
|
|
@@ -6602,7 +7034,7 @@ function registerCancelOrderCommand(parent, deps) {
|
|
|
6602
7034
|
const format = resolveFormat(opts.format);
|
|
6603
7035
|
const isYes = Boolean(opts.yes);
|
|
6604
7036
|
const apiKey = await resolveApiKey(opts.apiKey);
|
|
6605
|
-
const orderNo =
|
|
7037
|
+
const orderNo = need22(opts.orderNo, "order-no");
|
|
6606
7038
|
if (!isYes) {
|
|
6607
7039
|
const ok = await confirm12({
|
|
6608
7040
|
message: `Cancel order ${orderNo}? This requests cancellation and a refund.`,
|
|
@@ -6625,7 +7057,7 @@ function registerCancelOrderCommand(parent, deps) {
|
|
|
6625
7057
|
);
|
|
6626
7058
|
spinner?.stop();
|
|
6627
7059
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6628
|
-
await
|
|
7060
|
+
await render3(
|
|
6629
7061
|
result.data,
|
|
6630
7062
|
opts.format,
|
|
6631
7063
|
(d) => Formatter.keyValue([
|
|
@@ -6658,7 +7090,7 @@ function registerListOrdersCommand2(parent, deps) {
|
|
|
6658
7090
|
);
|
|
6659
7091
|
spinner?.stop();
|
|
6660
7092
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6661
|
-
await
|
|
7093
|
+
await render3(result.data, opts.format, (d) => {
|
|
6662
7094
|
const rows = (d.orders ?? []).map((o) => [
|
|
6663
7095
|
String(o.order_no ?? "-"),
|
|
6664
7096
|
String(o.status ?? "-"),
|
|
@@ -6678,10 +7110,10 @@ function registerChangeSearchCommand(parent, deps) {
|
|
|
6678
7110
|
const format = resolveFormat(opts.format);
|
|
6679
7111
|
const apiKey = await resolveApiKey(opts.apiKey);
|
|
6680
7112
|
const body = {
|
|
6681
|
-
order_no:
|
|
6682
|
-
date:
|
|
6683
|
-
passenger:
|
|
6684
|
-
segment_id:
|
|
7113
|
+
order_no: need22(opts.orderNo, "order-no"),
|
|
7114
|
+
date: need22(opts.date, "date"),
|
|
7115
|
+
passenger: need22(opts.passenger, "passenger"),
|
|
7116
|
+
segment_id: need22(opts.segmentId, "segment-id"),
|
|
6685
7117
|
cabin_class: opts.cabinClass
|
|
6686
7118
|
};
|
|
6687
7119
|
const spinner = format === "json" ? null : createSpinner("Searching change options...");
|
|
@@ -6692,7 +7124,7 @@ function registerChangeSearchCommand(parent, deps) {
|
|
|
6692
7124
|
);
|
|
6693
7125
|
spinner?.stop();
|
|
6694
7126
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6695
|
-
await
|
|
7127
|
+
await render3(result.data, opts.format, (d) => JSON.stringify(d, null, 2));
|
|
6696
7128
|
});
|
|
6697
7129
|
}
|
|
6698
7130
|
|
|
@@ -6707,14 +7139,14 @@ function registerChangeApplyCommand(parent, deps) {
|
|
|
6707
7139
|
const isYes = Boolean(opts.yes);
|
|
6708
7140
|
const apiKey = await resolveApiKey(opts.apiKey);
|
|
6709
7141
|
const body = {
|
|
6710
|
-
order_no:
|
|
6711
|
-
passenger:
|
|
6712
|
-
segment_id:
|
|
6713
|
-
product_token:
|
|
6714
|
-
contact_name:
|
|
6715
|
-
contact_region:
|
|
6716
|
-
contact_phone:
|
|
6717
|
-
contact_email:
|
|
7142
|
+
order_no: need22(opts.orderNo, "order-no"),
|
|
7143
|
+
passenger: need22(opts.passenger, "passenger"),
|
|
7144
|
+
segment_id: need22(opts.segmentId, "segment-id"),
|
|
7145
|
+
product_token: need22(opts.productToken, "product-token"),
|
|
7146
|
+
contact_name: need22(opts.contactName, "contact-name"),
|
|
7147
|
+
contact_region: need22(opts.contactRegion, "contact-region"),
|
|
7148
|
+
contact_phone: need22(opts.contactPhone, "contact-phone"),
|
|
7149
|
+
contact_email: need22(opts.contactEmail, "contact-email")
|
|
6718
7150
|
};
|
|
6719
7151
|
if (!isYes) {
|
|
6720
7152
|
const ok = await confirm13({
|
|
@@ -6736,7 +7168,7 @@ function registerChangeApplyCommand(parent, deps) {
|
|
|
6736
7168
|
);
|
|
6737
7169
|
spinner?.stop();
|
|
6738
7170
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6739
|
-
await
|
|
7171
|
+
await render3(result.data, opts.format, (d) => JSON.stringify(d, null, 2));
|
|
6740
7172
|
});
|
|
6741
7173
|
}
|
|
6742
7174
|
|
|
@@ -6748,7 +7180,7 @@ function registerChangeDetailCommand(parent, deps) {
|
|
|
6748
7180
|
const opts = cmd.optsWithGlobals();
|
|
6749
7181
|
const format = resolveFormat(opts.format);
|
|
6750
7182
|
const apiKey = await resolveApiKey(opts.apiKey);
|
|
6751
|
-
const changeOrderNo =
|
|
7183
|
+
const changeOrderNo = need22(opts.changeOrderNo, "change-order-no");
|
|
6752
7184
|
const spinner = format === "json" ? null : createSpinner("Fetching change detail...");
|
|
6753
7185
|
const result = await deps.apiClient.get(
|
|
6754
7186
|
`/flight/change/${encodeURIComponent(changeOrderNo)}`,
|
|
@@ -6756,7 +7188,7 @@ function registerChangeDetailCommand(parent, deps) {
|
|
|
6756
7188
|
);
|
|
6757
7189
|
spinner?.stop();
|
|
6758
7190
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6759
|
-
await
|
|
7191
|
+
await render3(result.data, opts.format, (d) => JSON.stringify(d, null, 2));
|
|
6760
7192
|
});
|
|
6761
7193
|
}
|
|
6762
7194
|
|
|
@@ -6770,7 +7202,7 @@ function registerChangeCancelCommand(parent, deps) {
|
|
|
6770
7202
|
const format = resolveFormat(opts.format);
|
|
6771
7203
|
const isYes = Boolean(opts.yes);
|
|
6772
7204
|
const apiKey = await resolveApiKey(opts.apiKey);
|
|
6773
|
-
const changeOrderNo =
|
|
7205
|
+
const changeOrderNo = need22(opts.changeOrderNo, "change-order-no");
|
|
6774
7206
|
if (!isYes) {
|
|
6775
7207
|
const ok = await confirm14({ message: `Cancel change request ${changeOrderNo}?`, default: false });
|
|
6776
7208
|
if (!ok) throw new CliError("CLIENT_ABORTED", "Change cancellation aborted by user.");
|
|
@@ -6788,7 +7220,7 @@ function registerChangeCancelCommand(parent, deps) {
|
|
|
6788
7220
|
);
|
|
6789
7221
|
spinner?.stop();
|
|
6790
7222
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6791
|
-
await
|
|
7223
|
+
await render3(result.data, opts.format, (d) => JSON.stringify(d, null, 2));
|
|
6792
7224
|
});
|
|
6793
7225
|
}
|
|
6794
7226
|
|
|
@@ -6798,17 +7230,23 @@ function registerChangePayCommand(parent, deps) {
|
|
|
6798
7230
|
const cmd = parent.command("change-pay").description("Pay a change request fee (like a normal order) and trigger change ticketing").option("--api-key <key>", "API Key for authentication (X-Api-Key)").option("--change-order-no <id>", "Change order number").option("--order-no <id>", "Original order reference (ownership check)").option("--amount <amount>", "Change fee total in decimal units (change-detail price_total)").option("--currency <currency>", "ISO 4217 currency code", "USD").option("--payment-method-id <id>", "Optional bound-card id (EVO path)").option("--payment-token-id <id>", "Optional UPI network-token id (unionpay charge path)").option(
|
|
6799
7231
|
"--authorized-merchant-trans-id <id>",
|
|
6800
7232
|
"Resume a 3DS challenge: merchant trans id of the already-authorised preauth"
|
|
6801
|
-
).option("--idempotency-key <key>", "Forwarded verbatim as the Idempotency-Key header")
|
|
7233
|
+
).option("--idempotency-key <key>", "Forwarded verbatim as the Idempotency-Key header").option(
|
|
7234
|
+
"--original-amount-cents <cents>",
|
|
7235
|
+
PRICE_ANNOTATION_FLAGS["original-amount-cents"].description
|
|
7236
|
+
).option(
|
|
7237
|
+
"--discount-amount-cents <cents>",
|
|
7238
|
+
PRICE_ANNOTATION_FLAGS["discount-amount-cents"].description
|
|
7239
|
+
);
|
|
6802
7240
|
attachSchemaHelp(cmd, flightChangePaySchema);
|
|
6803
7241
|
cmd.action(async () => {
|
|
6804
7242
|
const opts = cmd.optsWithGlobals();
|
|
6805
7243
|
const format = resolveFormat(opts.format);
|
|
6806
7244
|
const isYes = Boolean(opts.yes);
|
|
6807
7245
|
const apiKey = await resolveApiKey(opts.apiKey);
|
|
6808
|
-
const changeOrderNo =
|
|
6809
|
-
const orderNo =
|
|
7246
|
+
const changeOrderNo = need22(opts.changeOrderNo, "change-order-no");
|
|
7247
|
+
const orderNo = need22(opts.orderNo, "order-no");
|
|
6810
7248
|
const amount = num10(opts.amount, "amount");
|
|
6811
|
-
const currency =
|
|
7249
|
+
const currency = need22(opts.currency, "currency");
|
|
6812
7250
|
const body = {
|
|
6813
7251
|
order_no: orderNo,
|
|
6814
7252
|
amount,
|
|
@@ -6819,6 +7257,7 @@ function registerChangePayCommand(parent, deps) {
|
|
|
6819
7257
|
if (opts.authorizedMerchantTransId !== void 0) {
|
|
6820
7258
|
body.authorized_merchant_trans_id = opts.authorizedMerchantTransId;
|
|
6821
7259
|
}
|
|
7260
|
+
applyPriceAnnotation(body, opts);
|
|
6822
7261
|
if (!isYes) {
|
|
6823
7262
|
const isResume = opts.authorizedMerchantTransId !== void 0;
|
|
6824
7263
|
const message = isResume ? `Resume change fee ${amount} ${currency} for change order ${changeOrderNo}? The card is already authorised; this captures it and triggers change ticketing.` : `Pay change fee ${amount} ${currency} for change order ${changeOrderNo}? This charges the customer and triggers change ticketing.`;
|
|
@@ -6838,7 +7277,7 @@ function registerChangePayCommand(parent, deps) {
|
|
|
6838
7277
|
);
|
|
6839
7278
|
spinner?.stop();
|
|
6840
7279
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6841
|
-
await
|
|
7280
|
+
await render3(result.data, opts.format, (d) => {
|
|
6842
7281
|
const challenge = d.challenge ?? null;
|
|
6843
7282
|
if (challenge) {
|
|
6844
7283
|
return [
|
|
@@ -6879,14 +7318,14 @@ function registerRefundApplyCommand(parent, deps) {
|
|
|
6879
7318
|
const isYes = Boolean(opts.yes);
|
|
6880
7319
|
const apiKey = await resolveApiKey(opts.apiKey);
|
|
6881
7320
|
const body = {
|
|
6882
|
-
order_no:
|
|
6883
|
-
passenger:
|
|
6884
|
-
segment_id:
|
|
7321
|
+
order_no: need22(opts.orderNo, "order-no"),
|
|
7322
|
+
passenger: need22(opts.passenger, "passenger"),
|
|
7323
|
+
segment_id: need22(opts.segmentId, "segment-id"),
|
|
6885
7324
|
reason_type: num10(opts.reasonType, "reason-type"),
|
|
6886
|
-
contact_name:
|
|
6887
|
-
contact_region:
|
|
6888
|
-
contact_phone:
|
|
6889
|
-
contact_email:
|
|
7325
|
+
contact_name: need22(opts.contactName, "contact-name"),
|
|
7326
|
+
contact_region: need22(opts.contactRegion, "contact-region"),
|
|
7327
|
+
contact_phone: need22(opts.contactPhone, "contact-phone"),
|
|
7328
|
+
contact_email: need22(opts.contactEmail, "contact-email")
|
|
6890
7329
|
};
|
|
6891
7330
|
if (opts.reason !== void 0) body.reason = opts.reason;
|
|
6892
7331
|
if (!isYes) {
|
|
@@ -6909,7 +7348,7 @@ function registerRefundApplyCommand(parent, deps) {
|
|
|
6909
7348
|
);
|
|
6910
7349
|
spinner?.stop();
|
|
6911
7350
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6912
|
-
await
|
|
7351
|
+
await render3(result.data, opts.format, (d) => JSON.stringify(d, null, 2));
|
|
6913
7352
|
});
|
|
6914
7353
|
}
|
|
6915
7354
|
|
|
@@ -6921,7 +7360,7 @@ function registerRefundDetailCommand(parent, deps) {
|
|
|
6921
7360
|
const opts = cmd.optsWithGlobals();
|
|
6922
7361
|
const format = resolveFormat(opts.format);
|
|
6923
7362
|
const apiKey = await resolveApiKey(opts.apiKey);
|
|
6924
|
-
const refundOrderNo =
|
|
7363
|
+
const refundOrderNo = need22(opts.refundOrderNo, "refund-order-no");
|
|
6925
7364
|
const spinner = format === "json" ? null : createSpinner("Fetching refund detail...");
|
|
6926
7365
|
const result = await deps.apiClient.get(
|
|
6927
7366
|
`/flight/refund/${encodeURIComponent(refundOrderNo)}`,
|
|
@@ -6929,7 +7368,7 @@ function registerRefundDetailCommand(parent, deps) {
|
|
|
6929
7368
|
);
|
|
6930
7369
|
spinner?.stop();
|
|
6931
7370
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6932
|
-
await
|
|
7371
|
+
await render3(result.data, opts.format, (d) => JSON.stringify(d, null, 2));
|
|
6933
7372
|
});
|
|
6934
7373
|
}
|
|
6935
7374
|
|
|
@@ -6943,8 +7382,8 @@ function registerRefundConfirmCommand(parent, deps) {
|
|
|
6943
7382
|
const format = resolveFormat(opts.format);
|
|
6944
7383
|
const isYes = Boolean(opts.yes);
|
|
6945
7384
|
const apiKey = await resolveApiKey(opts.apiKey);
|
|
6946
|
-
const refundOrderNo =
|
|
6947
|
-
const confirmFlag =
|
|
7385
|
+
const refundOrderNo = need22(opts.refundOrderNo, "refund-order-no");
|
|
7386
|
+
const confirmFlag = need22(opts.confirm, "confirm");
|
|
6948
7387
|
if (confirmFlag !== "1" && confirmFlag !== "2") {
|
|
6949
7388
|
throw new CliError("PARAM_INVALID", '--confirm must be "1" (confirm) or "2" (cancel).');
|
|
6950
7389
|
}
|
|
@@ -6966,7 +7405,7 @@ function registerRefundConfirmCommand(parent, deps) {
|
|
|
6966
7405
|
);
|
|
6967
7406
|
spinner?.stop();
|
|
6968
7407
|
if (!result.success) throw CliError.fromApi(result, { auth: "api-key" });
|
|
6969
|
-
await
|
|
7408
|
+
await render3(result.data, opts.format, (d) => JSON.stringify(d, null, 2));
|
|
6970
7409
|
});
|
|
6971
7410
|
}
|
|
6972
7411
|
|
|
@@ -7099,6 +7538,9 @@ Workflow (typical order):
|
|
|
7099
7538
|
(write; needs --idempotency-key; the fare may change)
|
|
7100
7539
|
trip-status (optional) Status + driver location points of ONE leg of a multi-leg ride
|
|
7101
7540
|
list-orders (standalone) List the developer's previous ride orders
|
|
7541
|
+
callback-* (standalone) Status-event forwarding to your own https endpoint:
|
|
7542
|
+
callback-set/-get (one ride), callback-default-set/-get (fallback for all
|
|
7543
|
+
rides), callback-deliveries / callback-replay (inspect and re-send)
|
|
7102
7544
|
|
|
7103
7545
|
Key notes:
|
|
7104
7546
|
\u2022 Coordinates are NOT geocoded by the backend \u2014 supply --pickup-lat/lng and --dropoff-lat/lng.
|
|
@@ -7128,6 +7570,7 @@ Key notes:
|
|
|
7128
7570
|
registerRideUpdateCommand(rideCmd, deps);
|
|
7129
7571
|
registerRideTripStatusCommand(rideCmd, deps);
|
|
7130
7572
|
registerListOrdersCommand(rideCmd, deps);
|
|
7573
|
+
registerRideCallbackCommands(rideCmd, deps);
|
|
7131
7574
|
const servicesCmd = program.command("services").description("Merchant service discovery");
|
|
7132
7575
|
registerServicesListCommand(servicesCmd, { discoveryClient, program });
|
|
7133
7576
|
registerServiceGetCommand(servicesCmd, { discoveryClient, program });
|
|
@@ -7137,6 +7580,7 @@ Key notes:
|
|
|
7137
7580
|
registerOrdersListCommand(ordersCmd, deps);
|
|
7138
7581
|
registerOrdersGetCommand(ordersCmd, deps);
|
|
7139
7582
|
registerOrdersPayBatchCommand(ordersCmd, deps);
|
|
7583
|
+
registerOrdersGetPaymentGroupCommand(ordersCmd, deps);
|
|
7140
7584
|
const hotelCmd = program.command("hotel-redaug").description(
|
|
7141
7585
|
`Hotel booking (Redaug) \u2014 international hotel search, quote, create-order, pay-order, cancel, and check-out.
|
|
7142
7586
|
|