@tarileo/avileo-catalog-cli 0.3.2 → 0.3.3

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 CHANGED
@@ -3,7 +3,7 @@
3
3
  The Avileo tenant-agent command line interface for a registered business with effective catalog-agent access.
4
4
 
5
5
  The origin-pinning contract below describes this checkout. A package version in
6
- `package.json` does not prove npm availability: `0.3.2` has not been published
6
+ `package.json` does not prove npm availability: `0.3.3` has not been published
7
7
  by this release closure. Public handoff must wait for the operator's verified
8
8
  package version/artifact and an activated destination. Never substitute an older
9
9
  CLI that lacks these flags or silently pair with the integrated deployment.
package/dist/index.js CHANGED
@@ -14605,7 +14605,7 @@ function isRetryableStatus(status2) {
14605
14605
  function requestIdFrom(response, payload) {
14606
14606
  return payload?.requestId ?? response.headers.get("x-request-id") ?? void 0;
14607
14607
  }
14608
- function agentError(response, payload) {
14608
+ function agentError(response, payload, retry) {
14609
14609
  const code = payload?.code ?? "AGENT_REQUEST_FAILED";
14610
14610
  const message = payload?.message ?? "La API de Avileo devolvi\xF3 una respuesta inv\xE1lida";
14611
14611
  const options = {
@@ -14613,7 +14613,7 @@ function agentError(response, payload) {
14613
14613
  status: response.status,
14614
14614
  ...payload?.details === void 0 ? {} : { details: payload.details },
14615
14615
  ...requestIdFrom(response, payload) === void 0 ? {} : { requestId: requestIdFrom(response, payload) },
14616
- retryable: isRetryableStatus(response.status)
14616
+ retryable: retry && isRetryableStatus(response.status)
14617
14617
  };
14618
14618
  if (response.status === 401 || code === "UNAUTHORIZED") {
14619
14619
  return new AgentAuthenticationError(message, options);
@@ -14656,16 +14656,18 @@ var AgentHttpClient = class {
14656
14656
  constructor(config2) {
14657
14657
  this.#apiKey = configuredApiKey(config2);
14658
14658
  this.#baseUrl = (config2.baseUrl ?? AVILEO_AGENT_API_URL).replace(/\/$/, "");
14659
- this.#fetchImpl = config2.fetch ?? fetch;
14659
+ this.#fetchImpl = config2.fetch ?? ((...args) => fetch(...args));
14660
14660
  this.#timeoutMs = config2.timeoutMs;
14661
14661
  }
14662
14662
  request(path, options = {}) {
14663
- return this.perform(path, options, options.mutation ? crypto.randomUUID() : void 0);
14663
+ return this.perform(path, options);
14664
14664
  }
14665
- async perform(path, options, operationId) {
14665
+ async perform(path, options = {}) {
14666
14666
  const url2 = `${this.#baseUrl}${path}`;
14667
14667
  const formData = options.body instanceof FormData ? options.body : void 0;
14668
14668
  const body = options.body === void 0 ? void 0 : formData ?? JSON.stringify(options.body);
14669
+ const idempotencyKey = options.dispatchIdempotency ? crypto.randomUUID() : void 0;
14670
+ const retry = options.retry !== false;
14669
14671
  for (let attempt = 0; attempt < 3; attempt += 1) {
14670
14672
  const abort = createAbortSignal(this.#timeoutMs);
14671
14673
  let response;
@@ -14674,8 +14676,8 @@ var AgentHttpClient = class {
14674
14676
  method: options.method ?? "GET",
14675
14677
  headers: {
14676
14678
  ...formData || options.body === void 0 ? {} : { "content-type": "application/json" },
14677
- ...operationId ? { "idempotency-key": operationId } : {},
14678
14679
  ...options.approvalId ? { "x-avileo-approval-id": options.approvalId } : {},
14680
+ ...idempotencyKey ? { "idempotency-key": idempotencyKey } : {},
14679
14681
  ...this.#apiKey ? { "x-avileo-agent-key": this.#apiKey } : {}
14680
14682
  },
14681
14683
  body,
@@ -14683,18 +14685,18 @@ var AgentHttpClient = class {
14683
14685
  });
14684
14686
  } catch {
14685
14687
  abort.cancel();
14686
- if (attempt < 2) {
14688
+ if (retry && attempt < 2) {
14687
14689
  await new Promise((resolve) => setTimeout(resolve, retryDelayMs(attempt)));
14688
14690
  continue;
14689
14691
  }
14690
14692
  throw new AgentNetworkError("No se pudo conectar con la API de Avileo", {
14691
14693
  code: "NETWORK_ERROR",
14692
14694
  status: 0,
14693
- retryable: true
14695
+ retryable: retry
14694
14696
  });
14695
14697
  }
14696
14698
  abort.cancel();
14697
- if (isRetryableStatus(response.status) && attempt < 2) {
14699
+ if (retry && isRetryableStatus(response.status) && attempt < 2) {
14698
14700
  await new Promise((resolve) => setTimeout(resolve, retryDelayMs(attempt, response)));
14699
14701
  continue;
14700
14702
  }
@@ -14706,12 +14708,12 @@ var AgentHttpClient = class {
14706
14708
  code: "INVALID_RESPONSE",
14707
14709
  status: response.status,
14708
14710
  requestId: response.headers.get("x-request-id") ?? void 0,
14709
- retryable: isRetryableStatus(response.status)
14711
+ retryable: retry && isRetryableStatus(response.status)
14710
14712
  });
14711
14713
  }
14712
14714
  const failure = errorPayload(payload);
14713
14715
  if (failure || !response.ok || !successPayload(payload)) {
14714
- throw agentError(response, failure);
14716
+ throw agentError(response, failure, retry);
14715
14717
  }
14716
14718
  return payload.data;
14717
14719
  }
@@ -15304,6 +15306,14 @@ var AgentPaymentLinkPageSchema = external_exports.object({
15304
15306
  items: external_exports.array(AgentPaymentLinkDtoSchema),
15305
15307
  total: external_exports.number().int().nonnegative()
15306
15308
  }).strict();
15309
+ var AGENT_PAYMENT_METHODS = ["yape", "plin", "transferencia"];
15310
+ var AgentPaymentMethodSchema = external_exports.enum(AGENT_PAYMENT_METHODS);
15311
+ var AgentPaymentMethodDtoSchema = external_exports.object({
15312
+ id: uuidSchema,
15313
+ metodo: AgentPaymentMethodSchema,
15314
+ qrRenderUrl: external_exports.string().nullable(),
15315
+ habilitado: external_exports.boolean()
15316
+ }).strict();
15307
15317
  var AGENT_DEVICE_AUTH_STATUSES = ["pending", "approved", "denied", "expired"];
15308
15318
  var AGENT_DEVICE_AUTH_DEFAULT_PERMISSIONS = [
15309
15319
  ...AGENT_KEY_READ_ACTIONS
@@ -15328,7 +15338,8 @@ var AvileoAgentDeviceAuthClient = class {
15328
15338
  async start(input = {}) {
15329
15339
  return this.http.request("/api/v1/agent-auth/device", {
15330
15340
  method: "POST",
15331
- body: input
15341
+ body: input,
15342
+ retry: false
15332
15343
  });
15333
15344
  }
15334
15345
  async poll(deviceCode) {
@@ -15381,7 +15392,7 @@ var AgentProductsResource = class {
15381
15392
  return this.http.request("/api/v1/agent/catalog/products", {
15382
15393
  method: "POST",
15383
15394
  body: input,
15384
- mutation: true,
15395
+ dispatchIdempotency: true,
15385
15396
  approvalId
15386
15397
  });
15387
15398
  }
@@ -15389,14 +15400,14 @@ var AgentProductsResource = class {
15389
15400
  return this.http.request(`/api/v1/agent/catalog/products/${encodeURIComponent(productId)}`, {
15390
15401
  method: "PATCH",
15391
15402
  body: input,
15392
- mutation: true,
15403
+ dispatchIdempotency: true,
15393
15404
  approvalId
15394
15405
  });
15395
15406
  }
15396
15407
  deactivate(productId, approvalId) {
15397
15408
  return this.http.request(
15398
15409
  `/api/v1/agent/catalog/products/${encodeURIComponent(productId)}/deactivate`,
15399
- { method: "POST", mutation: true, approvalId }
15410
+ { method: "POST", dispatchIdempotency: true, approvalId }
15400
15411
  );
15401
15412
  }
15402
15413
  };
@@ -15416,27 +15427,27 @@ var AgentVariantsResource = class {
15416
15427
  create(productId, input, approvalId) {
15417
15428
  return this.http.request(
15418
15429
  `/api/v1/agent/catalog/products/${encodeURIComponent(productId)}/variants`,
15419
- { method: "POST", body: input, mutation: true, approvalId }
15430
+ { method: "POST", body: input, dispatchIdempotency: true, approvalId }
15420
15431
  );
15421
15432
  }
15422
15433
  update(variantId, input, approvalId) {
15423
15434
  return this.http.request(`/api/v1/agent/catalog/variants/${encodeURIComponent(variantId)}`, {
15424
15435
  method: "PATCH",
15425
15436
  body: input,
15426
- mutation: true,
15437
+ dispatchIdempotency: true,
15427
15438
  approvalId
15428
15439
  });
15429
15440
  }
15430
15441
  deactivate(variantId, approvalId) {
15431
15442
  return this.http.request(
15432
15443
  `/api/v1/agent/catalog/variants/${encodeURIComponent(variantId)}/deactivate`,
15433
- { method: "POST", mutation: true, approvalId }
15444
+ { method: "POST", dispatchIdempotency: true, approvalId }
15434
15445
  );
15435
15446
  }
15436
15447
  reorder(productId, input, approvalId) {
15437
15448
  return this.http.request(
15438
15449
  `/api/v1/agent/catalog/products/${encodeURIComponent(productId)}/variants/reorder`,
15439
- { method: "POST", body: input, mutation: true, approvalId }
15450
+ { method: "POST", body: input, dispatchIdempotency: true, approvalId }
15440
15451
  );
15441
15452
  }
15442
15453
  };
@@ -15455,7 +15466,7 @@ var AgentCategoriesResource = class {
15455
15466
  return this.http.request("/api/v1/agent/catalog/categories", {
15456
15467
  method: "POST",
15457
15468
  body: input,
15458
- mutation: true,
15469
+ dispatchIdempotency: true,
15459
15470
  approvalId
15460
15471
  });
15461
15472
  }
@@ -15463,14 +15474,14 @@ var AgentCategoriesResource = class {
15463
15474
  return this.http.request(`/api/v1/agent/catalog/categories/${encodeURIComponent(categoryId)}`, {
15464
15475
  method: "PATCH",
15465
15476
  body: input,
15466
- mutation: true,
15477
+ dispatchIdempotency: true,
15467
15478
  approvalId
15468
15479
  });
15469
15480
  }
15470
15481
  delete(categoryId, approvalId) {
15471
15482
  return this.http.request(`/api/v1/agent/catalog/categories/${encodeURIComponent(categoryId)}`, {
15472
15483
  method: "DELETE",
15473
- mutation: true,
15484
+ dispatchIdempotency: true,
15474
15485
  approvalId
15475
15486
  });
15476
15487
  }
@@ -15490,7 +15501,7 @@ var AgentTagsResource = class {
15490
15501
  return this.http.request("/api/v1/agent/catalog/tags", {
15491
15502
  method: "POST",
15492
15503
  body: input,
15493
- mutation: true,
15504
+ dispatchIdempotency: true,
15494
15505
  approvalId
15495
15506
  });
15496
15507
  }
@@ -15498,14 +15509,14 @@ var AgentTagsResource = class {
15498
15509
  return this.http.request(`/api/v1/agent/catalog/tags/${encodeURIComponent(tagId)}`, {
15499
15510
  method: "PATCH",
15500
15511
  body: input,
15501
- mutation: true,
15512
+ dispatchIdempotency: true,
15502
15513
  approvalId
15503
15514
  });
15504
15515
  }
15505
15516
  delete(tagId, approvalId) {
15506
15517
  return this.http.request(`/api/v1/agent/catalog/tags/${encodeURIComponent(tagId)}`, {
15507
15518
  method: "DELETE",
15508
- mutation: true,
15519
+ dispatchIdempotency: true,
15509
15520
  approvalId
15510
15521
  });
15511
15522
  }
@@ -15527,7 +15538,7 @@ var AgentAssetsResource = class {
15527
15538
  return this.http.request("/api/v1/agent/catalog/assets/upload", {
15528
15539
  method: "POST",
15529
15540
  body,
15530
- mutation: true,
15541
+ dispatchIdempotency: true,
15531
15542
  approvalId
15532
15543
  });
15533
15544
  }
@@ -15535,7 +15546,7 @@ var AgentAssetsResource = class {
15535
15546
  return this.http.request("/api/v1/agent/catalog/assets/import", {
15536
15547
  method: "POST",
15537
15548
  body: input,
15538
- mutation: true,
15549
+ dispatchIdempotency: true,
15539
15550
  approvalId
15540
15551
  });
15541
15552
  }
@@ -15558,13 +15569,13 @@ var AgentInventoryResource = class {
15558
15569
  adjust(variantId, input, approvalId) {
15559
15570
  return this.http.request(
15560
15571
  `/api/v1/agent/catalog/variants/${encodeURIComponent(variantId)}/inventory/adjust`,
15561
- { method: "POST", body: input, mutation: true, approvalId }
15572
+ { method: "POST", body: input, dispatchIdempotency: true, approvalId }
15562
15573
  );
15563
15574
  }
15564
15575
  set(variantId, input, approvalId) {
15565
15576
  return this.http.request(
15566
15577
  `/api/v1/agent/catalog/variants/${encodeURIComponent(variantId)}/inventory`,
15567
- { method: "PUT", body: input, mutation: true, approvalId }
15578
+ { method: "PUT", body: input, dispatchIdempotency: true, approvalId }
15568
15579
  );
15569
15580
  }
15570
15581
  };
@@ -15577,7 +15588,7 @@ var AgentImportsResource = class {
15577
15588
  return this.http.request("/api/v1/agent/catalog/imports/preview", {
15578
15589
  method: "POST",
15579
15590
  body: input,
15580
- mutation: true
15591
+ dispatchIdempotency: true
15581
15592
  });
15582
15593
  }
15583
15594
  apply(importId, approvalId) {
@@ -15585,7 +15596,7 @@ var AgentImportsResource = class {
15585
15596
  `/api/v1/agent/catalog/imports/${encodeURIComponent(importId)}/apply`,
15586
15597
  {
15587
15598
  method: "POST",
15588
- mutation: true,
15599
+ dispatchIdempotency: true,
15589
15600
  approvalId
15590
15601
  }
15591
15602
  );
@@ -15602,8 +15613,7 @@ var AgentOperationsResource = class {
15602
15613
  propose(input) {
15603
15614
  return this.http.request("/api/v1/agent/operations", {
15604
15615
  method: "POST",
15605
- body: input,
15606
- mutation: true
15616
+ body: input
15607
15617
  });
15608
15618
  }
15609
15619
  proposeClientKey(name) {
@@ -15618,11 +15628,45 @@ var AgentOperationsResource = class {
15618
15628
  apply(operationId) {
15619
15629
  return this.http.request(`/api/v1/agent/operations/${encodeURIComponent(operationId)}/apply`, {
15620
15630
  method: "POST",
15621
- mutation: true,
15622
15631
  approvalId: operationId
15623
15632
  });
15624
15633
  }
15625
15634
  };
15635
+ var AgentPaymentMethodListSchema = external_exports.array(AgentPaymentMethodDtoSchema);
15636
+ var AgentPaymentMethodsResource = class {
15637
+ constructor(http) {
15638
+ this.http = http;
15639
+ }
15640
+ http;
15641
+ /** Lists the payment methods with their QR render info. */
15642
+ list() {
15643
+ return this.http.request("/api/v1/agent/payment-methods").then((response) => AgentPaymentMethodListSchema.parse(response));
15644
+ }
15645
+ };
15646
+ var AgentPaymentLinkPublicMethodSchema = external_exports.object({
15647
+ phone: external_exports.string().optional(),
15648
+ accountNumber: external_exports.string().optional(),
15649
+ accountName: external_exports.string(),
15650
+ bank: external_exports.string().optional(),
15651
+ cci: external_exports.string().optional(),
15652
+ qrUrl: external_exports.string().nullable()
15653
+ }).strict();
15654
+ var AgentPaymentLinkPublicViewSchema = external_exports.object({
15655
+ businessName: external_exports.string(),
15656
+ amountMinor: external_exports.number().int().positive(),
15657
+ currency: external_exports.string().length(3),
15658
+ concept: external_exports.string().nullable(),
15659
+ expectedMethod: AgentPaymentLinkExpectedMethodSchema,
15660
+ status: AgentPaymentLinkStatusSchema,
15661
+ methods: external_exports.object({
15662
+ yape: AgentPaymentLinkPublicMethodSchema.optional(),
15663
+ plin: AgentPaymentLinkPublicMethodSchema.optional(),
15664
+ transferencia: AgentPaymentLinkPublicMethodSchema.optional()
15665
+ }).strict(),
15666
+ expiresAt: external_exports.string(),
15667
+ proofAttempts: external_exports.number().int().nonnegative(),
15668
+ maxProofAttempts: external_exports.number().int().positive()
15669
+ }).strict();
15626
15670
  var AgentPaymentLinksResource = class {
15627
15671
  constructor(http) {
15628
15672
  this.http = http;
@@ -15631,15 +15675,33 @@ var AgentPaymentLinksResource = class {
15631
15675
  /**
15632
15676
  * Creates a payment link. `amount` is in soles (major units); the backend
15633
15677
  * converts it to minor units — never convert it here. The URL is only
15634
- * non-null for the initial create response.
15678
+ * non-null for the initial create response. Automatic retries require an
15679
+ * explicit idempotencyKey; a replay can only return `url: null`.
15635
15680
  */
15636
15681
  create(input) {
15637
15682
  return this.http.request("/api/v1/agent/payment-links", {
15638
15683
  method: "POST",
15639
15684
  body: input,
15640
- mutation: true
15685
+ retry: Boolean(input.idempotencyKey?.trim())
15641
15686
  }).then((response) => AgentCreatedPaymentLinkDtoSchema.parse(response));
15642
15687
  }
15688
+ /**
15689
+ * Fetches the public payer view of a link by its plaintext token (no agent
15690
+ * credential required). Use it right after `create` to render the QR and
15691
+ * per-method instructions in your own UI instead of redirecting the payer
15692
+ * to the hosted page: `methods.<yape|plin|transferencia>.qrUrl` is a
15693
+ * backend-resolved render URL ready for `<img src>`.
15694
+ */
15695
+ getPublicView(token) {
15696
+ const trimmed = token.trim();
15697
+ if (trimmed.length < 20 || trimmed.length > 128 || !/^lnk_[0-9A-Za-z]+$/.test(trimmed)) {
15698
+ throw new AgentValidationError("Token de link de pago inv\xE1lido", {
15699
+ code: "INVALID_PAYMENT_LINK_TOKEN",
15700
+ status: 0
15701
+ });
15702
+ }
15703
+ return this.http.request(`/api/v1/public/pagar/${encodeURIComponent(trimmed)}`).then((response) => AgentPaymentLinkPublicViewSchema.parse(response));
15704
+ }
15643
15705
  /** Fetches a persisted link; `url` is always `null`. */
15644
15706
  get(paymentLinkId) {
15645
15707
  return this.http.request(`/api/v1/agent/payment-links/${encodeURIComponent(paymentLinkId)}`).then((response) => AgentPaymentLinkDtoSchema.parse(response));
@@ -15661,7 +15723,8 @@ function createAvileoAgent(config2) {
15661
15723
  assets: new AgentAssetsResource(http),
15662
15724
  inventory: new AgentInventoryResource(http),
15663
15725
  imports: new AgentImportsResource(http),
15664
- paymentLinks: new AgentPaymentLinksResource(http)
15726
+ paymentLinks: new AgentPaymentLinksResource(http),
15727
+ paymentMethods: new AgentPaymentMethodsResource(http)
15665
15728
  };
15666
15729
  }
15667
15730
 
@@ -16508,7 +16571,29 @@ async function login(options) {
16508
16571
  const expiresAt = Date.parse(start.expiresAt);
16509
16572
  const deadline = Number.isFinite(expiresAt) ? expiresAt : Date.now() + 10 * 60 * 1e3;
16510
16573
  while (Date.now() < deadline) {
16511
- const result = await deviceAuth.poll(start.deviceCode);
16574
+ let result;
16575
+ try {
16576
+ result = await deviceAuth.poll(start.deviceCode);
16577
+ } catch (error51) {
16578
+ if (error51 instanceof AgentError && error51.code === "AGENT_DEVICE_AUTH_CONSUMED") {
16579
+ throw new AgentConflictError(
16580
+ `${error51.message} La clave solo se entrega una vez y no se puede recuperar. Revoca la clave de este intento en Mis agentes y ejecuta \xABavileo auth login\xBB nuevamente. Tu credencial local anterior no se modific\xF3.`,
16581
+ {
16582
+ code: error51.code,
16583
+ status: error51.status,
16584
+ details: error51.details,
16585
+ requestId: error51.requestId
16586
+ }
16587
+ );
16588
+ }
16589
+ if (error51 instanceof AgentError && error51.code === "NETWORK_ERROR") {
16590
+ throw new CliProtocolError(
16591
+ "CLI_AUTH_DELIVERY_UNCERTAIN",
16592
+ "No se pudo confirmar la entrega de la clave. Revisa Mis agentes y revoca la clave de este intento si aparece; luego ejecuta \xABavileo auth login\xBB nuevamente. Tu credencial local anterior no se modific\xF3."
16593
+ );
16594
+ }
16595
+ throw error51;
16596
+ }
16512
16597
  if (result.status === "pending") {
16513
16598
  const remaining = Math.max(0, deadline - Date.now());
16514
16599
  await sleep(Math.min(Math.max(250, start.pollInterval * 1e3), remaining));
@@ -16521,7 +16606,7 @@ async function login(options) {
16521
16606
  if (!result.agentKey || !result.keyId || !result.businessId) {
16522
16607
  throw new CliProtocolError(
16523
16608
  "CLI_AUTH_ERROR",
16524
- "La autorizaci\xF3n aprobada no devolvi\xF3 una credencial v\xE1lida"
16609
+ "La autorizaci\xF3n aprobada no devolvi\xF3 una credencial v\xE1lida. Revoca la clave de este intento en Mis agentes y ejecuta \xABavileo auth login\xBB nuevamente. Tu credencial local anterior no se modific\xF3."
16525
16610
  );
16526
16611
  }
16527
16612
  saveLocalCredential({ apiKey: result.agentKey, baseUrl }, options.env);