@tarileo/avileo-catalog-cli 0.3.1 → 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 +41 -10
- package/dist/index.js +227 -75
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
14663
|
+
return this.perform(path, options);
|
|
14664
14664
|
}
|
|
14665
|
-
async perform(path, options
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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",
|
|
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,
|
|
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
|
-
|
|
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",
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
|
@@ -15670,6 +15733,53 @@ import { chmodSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSy
|
|
|
15670
15733
|
import { randomUUID } from "crypto";
|
|
15671
15734
|
import { homedir } from "os";
|
|
15672
15735
|
import { dirname, join } from "path";
|
|
15736
|
+
import { isIP } from "net";
|
|
15737
|
+
var LOCAL_IPV4_HOST_PATTERN = /^(?:127\.|10\.|192\.168\.|169\.254\.|172\.(?:1[6-9]|2\d|3[01])\.|100\.(?:6[4-9]|[7-9]\d|1[01]\d|12[0-7])\.)/;
|
|
15738
|
+
function isLocalHostname(hostname3) {
|
|
15739
|
+
const host = hostname3.replace(/^\[|\]$/g, "").toLowerCase();
|
|
15740
|
+
if (host === "localhost" || host.endsWith(".localhost") || host.endsWith(".local")) return true;
|
|
15741
|
+
if (host === "::1" || host === "::" || /^f[cd][0-9a-f]{2}:/.test(host)) return true;
|
|
15742
|
+
if (host.includes(":")) return false;
|
|
15743
|
+
if (!host.includes(".")) return true;
|
|
15744
|
+
return isIP(host) === 4 && LOCAL_IPV4_HOST_PATTERN.test(host);
|
|
15745
|
+
}
|
|
15746
|
+
function normalizeApiBaseUrl(rawUrl) {
|
|
15747
|
+
const candidate = rawUrl.trim().replace(/\/+$/, "");
|
|
15748
|
+
if (!candidate) {
|
|
15749
|
+
throw new CliOriginUnsupportedError("La URL base de la API est\xE1 vac\xEDa");
|
|
15750
|
+
}
|
|
15751
|
+
let parsed;
|
|
15752
|
+
try {
|
|
15753
|
+
parsed = new URL(candidate);
|
|
15754
|
+
} catch {
|
|
15755
|
+
throw new CliOriginUnsupportedError(`La URL base de la API no es v\xE1lida: ${candidate}`);
|
|
15756
|
+
}
|
|
15757
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
15758
|
+
throw new CliOriginUnsupportedError(
|
|
15759
|
+
`La URL base debe usar HTTPS (o HTTP local de desarrollo); se recibi\xF3 ${parsed.protocol}//`
|
|
15760
|
+
);
|
|
15761
|
+
}
|
|
15762
|
+
if (parsed.protocol === "http:" && !isLocalHostname(parsed.hostname)) {
|
|
15763
|
+
throw new CliOriginUnsupportedError(
|
|
15764
|
+
"Solo se permite HTTP para hosts locales de desarrollo; usa un origen HTTPS"
|
|
15765
|
+
);
|
|
15766
|
+
}
|
|
15767
|
+
if (parsed.username || parsed.password) {
|
|
15768
|
+
throw new CliOriginUnsupportedError("La URL base no debe incluir credenciales embebidas");
|
|
15769
|
+
}
|
|
15770
|
+
if (parsed.search || parsed.hash) {
|
|
15771
|
+
throw new CliOriginUnsupportedError("La URL base no debe incluir query ni fragmento");
|
|
15772
|
+
}
|
|
15773
|
+
return `${parsed.protocol}//${parsed.host}${parsed.pathname.replace(/\/+$/, "")}`;
|
|
15774
|
+
}
|
|
15775
|
+
function apiOrigin(baseUrl) {
|
|
15776
|
+
const parsed = new URL(baseUrl);
|
|
15777
|
+
return `${parsed.protocol}//${parsed.host}`;
|
|
15778
|
+
}
|
|
15779
|
+
function overrideBaseUrl(env) {
|
|
15780
|
+
const raw = env.AVILEO_AGENT_BASE_URL?.trim();
|
|
15781
|
+
return raw ? normalizeApiBaseUrl(raw) : void 0;
|
|
15782
|
+
}
|
|
15673
15783
|
var AGENT_KEY_PATTERN = /^avileo_sk_[^\s]+$/;
|
|
15674
15784
|
function normalizeAgentKey(value, message) {
|
|
15675
15785
|
const key = value.trim();
|
|
@@ -15700,10 +15810,15 @@ function readLocalCredential(env = process.env) {
|
|
|
15700
15810
|
throw new CliConfigurationError("La credencial local no es una Agent Key v\xE1lida");
|
|
15701
15811
|
}
|
|
15702
15812
|
const apiKey = normalizeAgentKey(record2.apiKey, "La credencial local no es una Agent Key v\xE1lida");
|
|
15703
|
-
|
|
15704
|
-
|
|
15813
|
+
if (typeof record2.baseUrl !== "string" || !record2.baseUrl.trim()) {
|
|
15814
|
+
throw new CliConfigurationError(
|
|
15815
|
+
"La credencial local no tiene un origen vinculado. Vuelve a autorizar con auth login --base-url <URL_DEL_PORTAL> antes de usarla."
|
|
15816
|
+
);
|
|
15817
|
+
}
|
|
15818
|
+
return { apiKey, baseUrl: normalizeApiBaseUrl(record2.baseUrl) };
|
|
15705
15819
|
}
|
|
15706
15820
|
function resolveCredential(env = process.env) {
|
|
15821
|
+
const override = overrideBaseUrl(env);
|
|
15707
15822
|
const environmentValue = env.AVILEO_AGENT_API_KEY;
|
|
15708
15823
|
if (environmentValue !== void 0) {
|
|
15709
15824
|
return {
|
|
@@ -15712,31 +15827,29 @@ function resolveCredential(env = process.env) {
|
|
|
15712
15827
|
"AVILEO_AGENT_API_KEY no es una Agent Key v\xE1lida"
|
|
15713
15828
|
),
|
|
15714
15829
|
source: "environment",
|
|
15715
|
-
|
|
15830
|
+
baseUrl: override ?? AVILEO_AGENT_API_URL
|
|
15716
15831
|
};
|
|
15717
15832
|
}
|
|
15718
15833
|
const local = readLocalCredential(env);
|
|
15719
15834
|
if (!local) return null;
|
|
15720
|
-
|
|
15721
|
-
|
|
15722
|
-
|
|
15723
|
-
|
|
15724
|
-
}
|
|
15835
|
+
if (override && apiOrigin(local.baseUrl) !== apiOrigin(override)) {
|
|
15836
|
+
throw new CliOriginConflictError(
|
|
15837
|
+
`La credencial local est\xE1 vinculada al origen ${apiOrigin(local.baseUrl)}, pero AVILEO_AGENT_BASE_URL apunta a ${apiOrigin(override)}. La clave nunca se env\xEDa a otro origen: quita la variable de entorno o vuelve a autenticar con auth login --base-url ${apiOrigin(override)} para emitir una clave en ese origen.`
|
|
15838
|
+
);
|
|
15839
|
+
}
|
|
15840
|
+
return { ...local, source: "local" };
|
|
15725
15841
|
}
|
|
15726
15842
|
function saveLocalCredential(credential, env = process.env) {
|
|
15727
15843
|
const apiKey = normalizeAgentKey(
|
|
15728
15844
|
credential.apiKey,
|
|
15729
15845
|
"Solo se pueden guardar Agent Keys de Avileo"
|
|
15730
15846
|
);
|
|
15847
|
+
const baseUrl = normalizeApiBaseUrl(credential.baseUrl);
|
|
15731
15848
|
const path = localCredentialPath(env);
|
|
15732
15849
|
mkdirSync(dirname(path), { recursive: true, mode: 448 });
|
|
15733
15850
|
const temporaryPath = `${path}.${randomUUID()}.tmp`;
|
|
15734
|
-
writeFileSync(
|
|
15735
|
-
|
|
15736
|
-
`${JSON.stringify({ apiKey, ...credential.baseUrl ? { baseUrl: credential.baseUrl } : {} })}
|
|
15737
|
-
`,
|
|
15738
|
-
{ mode: 384 }
|
|
15739
|
-
);
|
|
15851
|
+
writeFileSync(temporaryPath, `${JSON.stringify({ apiKey, baseUrl })}
|
|
15852
|
+
`, { mode: 384 });
|
|
15740
15853
|
chmodSync(temporaryPath, 384);
|
|
15741
15854
|
renameSync(temporaryPath, path);
|
|
15742
15855
|
chmodSync(path, 384);
|
|
@@ -15760,7 +15873,7 @@ function createClientFromEnvironment({
|
|
|
15760
15873
|
}
|
|
15761
15874
|
return clientFactory({
|
|
15762
15875
|
apiKey: credential.apiKey,
|
|
15763
|
-
|
|
15876
|
+
baseUrl: credential.baseUrl
|
|
15764
15877
|
});
|
|
15765
15878
|
}
|
|
15766
15879
|
var CliConfigurationError = class extends Error {
|
|
@@ -15770,6 +15883,20 @@ var CliConfigurationError = class extends Error {
|
|
|
15770
15883
|
this.name = "CliConfigurationError";
|
|
15771
15884
|
}
|
|
15772
15885
|
};
|
|
15886
|
+
var CliOriginUnsupportedError = class extends CliConfigurationError {
|
|
15887
|
+
code = "CLI_ORIGIN_UNSUPPORTED";
|
|
15888
|
+
constructor(message) {
|
|
15889
|
+
super(message);
|
|
15890
|
+
this.name = "CliOriginUnsupportedError";
|
|
15891
|
+
}
|
|
15892
|
+
};
|
|
15893
|
+
var CliOriginConflictError = class extends CliConfigurationError {
|
|
15894
|
+
code = "CLI_ORIGIN_CONFLICT";
|
|
15895
|
+
constructor(message) {
|
|
15896
|
+
super(message);
|
|
15897
|
+
this.name = "CliOriginConflictError";
|
|
15898
|
+
}
|
|
15899
|
+
};
|
|
15773
15900
|
|
|
15774
15901
|
// src/output.ts
|
|
15775
15902
|
var CliProtocolError = class extends Error {
|
|
@@ -16426,9 +16553,15 @@ async function openVerificationUri(uri) {
|
|
|
16426
16553
|
}
|
|
16427
16554
|
return false;
|
|
16428
16555
|
}
|
|
16556
|
+
function resolveSelectedBaseUrl(options) {
|
|
16557
|
+
const explicit = options.baseUrl?.trim();
|
|
16558
|
+
if (explicit) return normalizeApiBaseUrl(explicit);
|
|
16559
|
+
const fromEnvironment = options.env.AVILEO_AGENT_BASE_URL?.trim();
|
|
16560
|
+
return fromEnvironment ? normalizeApiBaseUrl(fromEnvironment) : AVILEO_AGENT_API_URL;
|
|
16561
|
+
}
|
|
16429
16562
|
async function login(options) {
|
|
16430
|
-
const baseUrl = options
|
|
16431
|
-
const deviceAuth = options.deviceAuthFactory(
|
|
16563
|
+
const baseUrl = resolveSelectedBaseUrl(options);
|
|
16564
|
+
const deviceAuth = options.deviceAuthFactory({ baseUrl });
|
|
16432
16565
|
const start = await deviceAuth.start({ name: "Avileo CLI" });
|
|
16433
16566
|
const browserOpened = await options.openBrowser(start.verificationUri);
|
|
16434
16567
|
process.stderr.write(
|
|
@@ -16438,46 +16571,58 @@ async function login(options) {
|
|
|
16438
16571
|
const expiresAt = Date.parse(start.expiresAt);
|
|
16439
16572
|
const deadline = Number.isFinite(expiresAt) ? expiresAt : Date.now() + 10 * 60 * 1e3;
|
|
16440
16573
|
while (Date.now() < deadline) {
|
|
16441
|
-
|
|
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
|
+
}
|
|
16442
16597
|
if (result.status === "pending") {
|
|
16443
16598
|
const remaining = Math.max(0, deadline - Date.now());
|
|
16444
16599
|
await sleep(Math.min(Math.max(250, start.pollInterval * 1e3), remaining));
|
|
16445
16600
|
continue;
|
|
16446
16601
|
}
|
|
16447
16602
|
if (result.status === "denied" || result.status === "expired") {
|
|
16448
|
-
emitSuccess(safeFinalResult(start, browserOpened, result));
|
|
16603
|
+
emitSuccess({ ...safeFinalResult(start, browserOpened, result), baseUrl });
|
|
16449
16604
|
return;
|
|
16450
16605
|
}
|
|
16451
16606
|
if (!result.agentKey || !result.keyId || !result.businessId) {
|
|
16452
16607
|
throw new CliProtocolError(
|
|
16453
16608
|
"CLI_AUTH_ERROR",
|
|
16454
|
-
"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."
|
|
16455
16610
|
);
|
|
16456
16611
|
}
|
|
16457
|
-
saveLocalCredential(
|
|
16458
|
-
|
|
16459
|
-
apiKey: result.agentKey,
|
|
16460
|
-
...baseUrl ? { baseUrl } : {}
|
|
16461
|
-
},
|
|
16462
|
-
options.env
|
|
16463
|
-
);
|
|
16464
|
-
emitSuccess(safeFinalResult(start, browserOpened, result));
|
|
16612
|
+
saveLocalCredential({ apiKey: result.agentKey, baseUrl }, options.env);
|
|
16613
|
+
emitSuccess({ ...safeFinalResult(start, browserOpened, result), baseUrl });
|
|
16465
16614
|
return;
|
|
16466
16615
|
}
|
|
16467
16616
|
throw new CliProtocolError("CLI_AUTH_TIMEOUT", "La autorizaci\xF3n expir\xF3 antes de ser aprobada");
|
|
16468
16617
|
}
|
|
16469
16618
|
async function configure(options) {
|
|
16619
|
+
const baseUrl = resolveSelectedBaseUrl(options);
|
|
16470
16620
|
const apiKey = await options.readSecret("Agent Key de Avileo (no se mostrar\xE1): ");
|
|
16471
|
-
saveLocalCredential(
|
|
16472
|
-
{
|
|
16473
|
-
apiKey,
|
|
16474
|
-
...options.env.AVILEO_AGENT_BASE_URL?.trim() ? { baseUrl: options.env.AVILEO_AGENT_BASE_URL.trim() } : {}
|
|
16475
|
-
},
|
|
16476
|
-
options.env
|
|
16477
|
-
);
|
|
16621
|
+
saveLocalCredential({ apiKey, baseUrl }, options.env);
|
|
16478
16622
|
emitSuccess({
|
|
16479
16623
|
configured: true,
|
|
16480
16624
|
source: "local",
|
|
16625
|
+
baseUrl,
|
|
16481
16626
|
credentialPath: localCredentialPath(options.env)
|
|
16482
16627
|
});
|
|
16483
16628
|
}
|
|
@@ -16498,7 +16643,7 @@ async function status(options) {
|
|
|
16498
16643
|
emitSuccess({
|
|
16499
16644
|
configured: true,
|
|
16500
16645
|
source: credential.source,
|
|
16501
|
-
|
|
16646
|
+
baseUrl: credential.baseUrl ?? AVILEO_AGENT_API_URL,
|
|
16502
16647
|
business,
|
|
16503
16648
|
...businessLookupError ? { businessLookupError } : {}
|
|
16504
16649
|
});
|
|
@@ -16514,8 +16659,15 @@ async function logout(options) {
|
|
|
16514
16659
|
}
|
|
16515
16660
|
function registerAuthCommands(root, options) {
|
|
16516
16661
|
const auth = root.command("auth").description("Conecta la CLI con Avileo sin copiar claves en el chat");
|
|
16517
|
-
auth.command("configure").description("Guarda una Agent Key existente sin mostrarla en pantalla").
|
|
16518
|
-
|
|
16662
|
+
auth.command("configure").description("Guarda una Agent Key existente sin mostrarla en pantalla").option("--base-url <url>", "Origen de la API donde se usar\xE1 la clave").action(
|
|
16663
|
+
(commandOptions) => configure({ ...options, baseUrl: commandOptions.baseUrl })
|
|
16664
|
+
);
|
|
16665
|
+
auth.command("login").description("Autoriza esta CLI mediante un link temporal").option(
|
|
16666
|
+
"--base-url <url>",
|
|
16667
|
+
"Origen de la API a vincular; tiene prioridad sobre AVILEO_AGENT_BASE_URL"
|
|
16668
|
+
).action(
|
|
16669
|
+
(commandOptions) => login({ ...options, baseUrl: commandOptions.baseUrl })
|
|
16670
|
+
);
|
|
16519
16671
|
auth.command("status").description("Muestra el estado de la credencial sin revelar secretos").action(() => status(options));
|
|
16520
16672
|
auth.command("logout").description("Elimina solamente la credencial local").action(() => logout(options));
|
|
16521
16673
|
}
|