@agenzo/merchant-cli 0.8.4 → 0.8.5

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/dist/index.js CHANGED
@@ -314,6 +314,25 @@ function compareVersions(a, b) {
314
314
  function isBelow(current, minimum) {
315
315
  return compareVersions(current, minimum) < 0;
316
316
  }
317
+ var TRACEPARENT_PATTERN = /^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}$/;
318
+ var DEFAULT_HTTP_TIMEOUT_MS = 7e4;
319
+ function httpTimeoutFromEnv(env = process.env) {
320
+ const raw = env.AGENZO_CLI_HTTP_TIMEOUT_MS;
321
+ if (raw === void 0 || raw.trim() === "") return null;
322
+ const parsed = Number(raw);
323
+ if (!Number.isFinite(parsed) || parsed <= 0) return null;
324
+ return parsed;
325
+ }
326
+ var DEADLINE_HEADER = "x-deadline-ms";
327
+ var DEADLINE_RESERVE_MS = 200;
328
+ function deadlineFromEnv(env = process.env) {
329
+ const raw = env.DEADLINE_MS;
330
+ if (raw === void 0 || raw.trim() === "") return null;
331
+ if (!/^\d+$/.test(raw.trim())) return null;
332
+ const parsed = Number(raw);
333
+ if (!Number.isFinite(parsed) || parsed <= 0) return null;
334
+ return parsed;
335
+ }
317
336
  var ApiClient = class {
318
337
  baseUrl;
319
338
  timeout;
@@ -329,16 +348,43 @@ var ApiClient = class {
329
348
  * a single trace_id server-side and can be followed as one chain in logs.
330
349
  */
331
350
  requestId;
351
+ /**
352
+ * 上游给的剩余预算(毫秒),来自 `DEADLINE_MS`;未注入时为 null。
353
+ *
354
+ * 进程启动时读一次而不是每请求读:一次 CLI 调用就是链路上的一跳,预算属于这一跳
355
+ * 整体。每请求重读会让多步流程(如 `payment-methods add` 的 create + poll + get)
356
+ * 各自拿到完整预算,等于凭空放大了本跳的时间上限。
357
+ */
358
+ deadlineMs;
359
+ /** 本进程开始时刻(单调时钟),用于算已用时间。 */
360
+ startedAt;
332
361
  constructor(config) {
333
362
  this.baseUrl = config.baseUrl.replace(/\/+$/, "");
334
- this.timeout = config.timeout ?? 6e4;
363
+ this.deadlineMs = deadlineFromEnv();
364
+ this.startedAt = performance.now();
365
+ const configured = config.timeout ?? httpTimeoutFromEnv() ?? DEFAULT_HTTP_TIMEOUT_MS;
366
+ this.timeout = this.deadlineMs === null ? configured : Math.min(configured, Math.max(1, this.deadlineMs - DEADLINE_RESERVE_MS));
335
367
  this.requestId = crypto.randomUUID();
336
368
  }
369
+ /** 交给下游的剩余毫秒:扣掉本进程已用时间与回程预留;无预算时返回 null。 */
370
+ remainingDeadlineMs() {
371
+ if (this.deadlineMs === null) return null;
372
+ const elapsed = performance.now() - this.startedAt;
373
+ return Math.max(0, Math.round(this.deadlineMs - elapsed - DEADLINE_RESERVE_MS));
374
+ }
337
375
  buildHeaders(auth) {
338
376
  const headers = {
339
377
  "User-Agent": `agenzo-admin-cli/${getCurrentVersion()}`,
340
378
  "X-Request-Id": this.requestId
341
379
  };
380
+ const remaining = this.remainingDeadlineMs();
381
+ if (remaining !== null) {
382
+ headers[DEADLINE_HEADER] = String(remaining);
383
+ }
384
+ const traceparent = process.env.TRACEPARENT;
385
+ if (traceparent && TRACEPARENT_PATTERN.test(traceparent.trim())) {
386
+ headers["traceparent"] = traceparent.trim();
387
+ }
342
388
  if (auth.type === "bearer") {
343
389
  headers["Authorization"] = `Bearer ${auth.token}`;
344
390
  } else if (auth.type === "api-key") {
@@ -1291,6 +1337,11 @@ var hotelCreateOrderSchema = {
1291
1337
  required: false,
1292
1338
  description: "Product bed-type code from the chosen quote rate's beds[].code (e.g. 'L000000' King / '1000000' Queen). Forwarded verbatim to upstream createOrder bedType; upstream recommends passing the product-dimension bed type at booking."
1293
1339
  },
1340
+ "payment-method-id": {
1341
+ type: "string",
1342
+ required: false,
1343
+ description: "Optional bound-card id (pay_per_call / EVO path). When set, the platform settles this order by pre-authorizing + capturing on that specific bound card; omit to let billing_mode decide."
1344
+ },
1294
1345
  "payment-token-id": {
1295
1346
  type: "string",
1296
1347
  required: false,
@@ -3380,19 +3431,6 @@ function parseTips(raw) {
3380
3431
  }
3381
3432
  return parsed;
3382
3433
  }
3383
- function parseCancellation(raw) {
3384
- const INVALID = "--cancellation must be a JSON object.";
3385
- let parsed;
3386
- try {
3387
- parsed = JSON.parse(raw);
3388
- } catch {
3389
- throw new CliError("PARAM_INVALID", INVALID);
3390
- }
3391
- if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
3392
- throw new CliError("PARAM_INVALID", INVALID);
3393
- }
3394
- return parsed;
3395
- }
3396
3434
  function need7(value, flag) {
3397
3435
  if (value === void 0) {
3398
3436
  throw new CliError("PARAM_INVALID", `Missing required --${flag}.`);
@@ -3447,14 +3485,11 @@ function registerHotelCreateOrderCommand(parent, deps) {
3447
3485
  "--tips <json>",
3448
3486
  "\u5BA2\u6237\u81EA\u6D4B\u70B95 \u63D0\u793A\u4FE1\u606F: the chosen quote rate's tips as a JSON array [{title,text}]. Stored on the order for the order-detail page ONLY \u2014 platform-local, not sent upstream."
3449
3487
  ).option("--hotel-name <name>", "Hotel name (display-only, stored for order summary)").option(
3450
- "--cancellation <json>",
3451
- "Cancellation policy JSON from the chosen rate ({restriction_type,restriction_day,restriction_time,penalties[]}); stored on the order for cancellation gating and free-cancel deadline display. Not sent upstream."
3452
- ).option(
3453
- "--hotel-timezone <tz>",
3454
- "Hotel timezone from quote (e.g. 'UTC-5'); stored to compute the free-cancellation deadline in hotel-local time."
3455
- ).option(
3456
3488
  "--bed-type <code>",
3457
3489
  "Product bed-type code from the chosen quote rate's beds[].code (e.g. 'L000000' King / '1000000' Queen); forwarded verbatim to upstream createOrder bedType."
3490
+ ).option(
3491
+ "--payment-method-id <id>",
3492
+ "Optional bound-card id (pay_per_call / EVO path). When set, the platform settles this order by pre-authorizing + capturing on that specific bound card. Omit to let the platform pick by billing_mode."
3458
3493
  ).option(
3459
3494
  "--payment-token-id <id>",
3460
3495
  "UPI Agent Pay: payment token id from an already-completed UnionPay network-token capture. When set, the platform skips EVO preauth/capture and only locks the order + records this credential (funds already charged)."
@@ -3503,10 +3538,9 @@ function registerHotelCreateOrderCommand(parent, deps) {
3503
3538
  if (opts.arriveTime !== void 0) body.arrive_time = opts.arriveTime;
3504
3539
  if (opts.specialRequests !== void 0) body.special_requests = opts.specialRequests;
3505
3540
  if (opts.tips !== void 0) body.tips = parseTips(opts.tips);
3506
- if (opts.cancellation !== void 0) body.cancellation = parseCancellation(opts.cancellation);
3507
- if (opts.hotelTimezone !== void 0) body.hotel_timezone = opts.hotelTimezone;
3508
3541
  if (opts.hotelName !== void 0) body.hotel_name = opts.hotelName;
3509
3542
  if (opts.bedType !== void 0) body.bed_type = opts.bedType;
3543
+ if (opts.paymentMethodId !== void 0) body.payment_method_id = opts.paymentMethodId;
3510
3544
  if (opts.paymentTokenId !== void 0) body.payment_token_id = opts.paymentTokenId;
3511
3545
  if (!isYes) {
3512
3546
  const chargeNote = opts.paymentTokenId !== void 0 ? "Payment has already been captured via UPI Agent Pay; this only locks the room." : "This locks the rate but does NOT charge anything yet.";