@stripe/link-cli 0.4.2 → 0.5.0
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 +86 -39
- package/dist/cli.js +1723 -851
- package/package.json +8 -6
package/dist/cli.js
CHANGED
|
@@ -3218,8 +3218,8 @@ var require_utils = __commonJS({
|
|
|
3218
3218
|
}
|
|
3219
3219
|
return ind;
|
|
3220
3220
|
}
|
|
3221
|
-
function removeDotSegments(
|
|
3222
|
-
let input =
|
|
3221
|
+
function removeDotSegments(path7) {
|
|
3222
|
+
let input = path7;
|
|
3223
3223
|
const output = [];
|
|
3224
3224
|
let nextSlash = -1;
|
|
3225
3225
|
let len = 0;
|
|
@@ -3418,8 +3418,8 @@ var require_schemes = __commonJS({
|
|
|
3418
3418
|
wsComponent.secure = void 0;
|
|
3419
3419
|
}
|
|
3420
3420
|
if (wsComponent.resourceName) {
|
|
3421
|
-
const [
|
|
3422
|
-
wsComponent.path =
|
|
3421
|
+
const [path7, query] = wsComponent.resourceName.split("?");
|
|
3422
|
+
wsComponent.path = path7 && path7 !== "/" ? path7 : void 0;
|
|
3423
3423
|
wsComponent.query = query;
|
|
3424
3424
|
wsComponent.resourceName = void 0;
|
|
3425
3425
|
}
|
|
@@ -7605,12 +7605,12 @@ var require_dist = __commonJS({
|
|
|
7605
7605
|
throw new Error(`Unknown format "${name}"`);
|
|
7606
7606
|
return f;
|
|
7607
7607
|
};
|
|
7608
|
-
function addFormats(ajv, list,
|
|
7608
|
+
function addFormats(ajv, list, fs5, exportName) {
|
|
7609
7609
|
var _a;
|
|
7610
7610
|
var _b;
|
|
7611
7611
|
(_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
7612
7612
|
for (const f of list)
|
|
7613
|
-
ajv.addFormat(f,
|
|
7613
|
+
ajv.addFormat(f, fs5[f]);
|
|
7614
7614
|
}
|
|
7615
7615
|
module.exports = exports = formatsPlugin;
|
|
7616
7616
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -9548,12 +9548,9 @@ var require_semver2 = __commonJS({
|
|
|
9548
9548
|
}
|
|
9549
9549
|
});
|
|
9550
9550
|
|
|
9551
|
-
// src/cli.tsx
|
|
9552
|
-
import { Cli as Cli7 } from "incur";
|
|
9553
|
-
import updateNotifier from "update-notifier";
|
|
9554
|
-
|
|
9555
9551
|
// ../sdk/dist/index.js
|
|
9556
9552
|
import fs3 from "fs";
|
|
9553
|
+
import path5 from "path";
|
|
9557
9554
|
|
|
9558
9555
|
// ../../node_modules/.pnpm/conf@13.1.0/node_modules/conf/dist/source/index.js
|
|
9559
9556
|
import { isDeepStrictEqual } from "util";
|
|
@@ -9574,12 +9571,12 @@ var disallowedKeys = /* @__PURE__ */ new Set([
|
|
|
9574
9571
|
"constructor"
|
|
9575
9572
|
]);
|
|
9576
9573
|
var digits = new Set("0123456789");
|
|
9577
|
-
function getPathSegments(
|
|
9574
|
+
function getPathSegments(path7) {
|
|
9578
9575
|
const parts = [];
|
|
9579
9576
|
let currentSegment = "";
|
|
9580
9577
|
let currentPart = "start";
|
|
9581
9578
|
let isIgnoring = false;
|
|
9582
|
-
for (const character of
|
|
9579
|
+
for (const character of path7) {
|
|
9583
9580
|
switch (character) {
|
|
9584
9581
|
case "\\": {
|
|
9585
9582
|
if (currentPart === "index") {
|
|
@@ -9701,11 +9698,11 @@ function assertNotStringIndex(object, key) {
|
|
|
9701
9698
|
throw new Error("Cannot use string index");
|
|
9702
9699
|
}
|
|
9703
9700
|
}
|
|
9704
|
-
function getProperty(object,
|
|
9705
|
-
if (!isObject(object) || typeof
|
|
9701
|
+
function getProperty(object, path7, value) {
|
|
9702
|
+
if (!isObject(object) || typeof path7 !== "string") {
|
|
9706
9703
|
return value === void 0 ? object : value;
|
|
9707
9704
|
}
|
|
9708
|
-
const pathArray = getPathSegments(
|
|
9705
|
+
const pathArray = getPathSegments(path7);
|
|
9709
9706
|
if (pathArray.length === 0) {
|
|
9710
9707
|
return value;
|
|
9711
9708
|
}
|
|
@@ -9725,12 +9722,12 @@ function getProperty(object, path5, value) {
|
|
|
9725
9722
|
}
|
|
9726
9723
|
return object === void 0 ? value : object;
|
|
9727
9724
|
}
|
|
9728
|
-
function setProperty(object,
|
|
9729
|
-
if (!isObject(object) || typeof
|
|
9725
|
+
function setProperty(object, path7, value) {
|
|
9726
|
+
if (!isObject(object) || typeof path7 !== "string") {
|
|
9730
9727
|
return object;
|
|
9731
9728
|
}
|
|
9732
9729
|
const root = object;
|
|
9733
|
-
const pathArray = getPathSegments(
|
|
9730
|
+
const pathArray = getPathSegments(path7);
|
|
9734
9731
|
for (let index = 0; index < pathArray.length; index++) {
|
|
9735
9732
|
const key = pathArray[index];
|
|
9736
9733
|
assertNotStringIndex(object, key);
|
|
@@ -9743,11 +9740,11 @@ function setProperty(object, path5, value) {
|
|
|
9743
9740
|
}
|
|
9744
9741
|
return root;
|
|
9745
9742
|
}
|
|
9746
|
-
function deleteProperty(object,
|
|
9747
|
-
if (!isObject(object) || typeof
|
|
9743
|
+
function deleteProperty(object, path7) {
|
|
9744
|
+
if (!isObject(object) || typeof path7 !== "string") {
|
|
9748
9745
|
return false;
|
|
9749
9746
|
}
|
|
9750
|
-
const pathArray = getPathSegments(
|
|
9747
|
+
const pathArray = getPathSegments(path7);
|
|
9751
9748
|
for (let index = 0; index < pathArray.length; index++) {
|
|
9752
9749
|
const key = pathArray[index];
|
|
9753
9750
|
assertNotStringIndex(object, key);
|
|
@@ -9761,11 +9758,11 @@ function deleteProperty(object, path5) {
|
|
|
9761
9758
|
}
|
|
9762
9759
|
}
|
|
9763
9760
|
}
|
|
9764
|
-
function hasProperty(object,
|
|
9765
|
-
if (!isObject(object) || typeof
|
|
9761
|
+
function hasProperty(object, path7) {
|
|
9762
|
+
if (!isObject(object) || typeof path7 !== "string") {
|
|
9766
9763
|
return false;
|
|
9767
9764
|
}
|
|
9768
|
-
const pathArray = getPathSegments(
|
|
9765
|
+
const pathArray = getPathSegments(path7);
|
|
9769
9766
|
if (pathArray.length === 0) {
|
|
9770
9767
|
return false;
|
|
9771
9768
|
}
|
|
@@ -10861,12 +10858,27 @@ function withComputedExpiry(auth) {
|
|
|
10861
10858
|
expires_at: auth.expires_at ?? Date.now() + auth.expires_in * 1e3
|
|
10862
10859
|
};
|
|
10863
10860
|
}
|
|
10861
|
+
var CONFIG_FILE_MODE = 384;
|
|
10864
10862
|
var Storage = class {
|
|
10865
10863
|
config;
|
|
10864
|
+
options;
|
|
10865
|
+
constructor(options = {}) {
|
|
10866
|
+
this.options = options;
|
|
10867
|
+
}
|
|
10866
10868
|
getConfig() {
|
|
10867
10869
|
if (!this.config) {
|
|
10870
|
+
let locationOverride;
|
|
10871
|
+
if (this.options.configPath) {
|
|
10872
|
+
const parsed = path5.parse(path5.resolve(this.options.configPath));
|
|
10873
|
+
const configName = parsed.ext === ".json" ? parsed.name : parsed.base;
|
|
10874
|
+
locationOverride = { cwd: parsed.dir, configName };
|
|
10875
|
+
} else if (this.options.cwd) {
|
|
10876
|
+
locationOverride = { cwd: this.options.cwd };
|
|
10877
|
+
}
|
|
10868
10878
|
this.config = new Conf({
|
|
10869
10879
|
projectName: "link-cli",
|
|
10880
|
+
configFileMode: CONFIG_FILE_MODE,
|
|
10881
|
+
...locationOverride,
|
|
10870
10882
|
defaults: {
|
|
10871
10883
|
auth: null,
|
|
10872
10884
|
pendingDeviceAuth: null
|
|
@@ -11076,6 +11088,91 @@ var PaymentMethodsResource = class {
|
|
|
11076
11088
|
return body?.payment_details ?? [];
|
|
11077
11089
|
}
|
|
11078
11090
|
};
|
|
11091
|
+
var ShippingAddressResource = class {
|
|
11092
|
+
verbose;
|
|
11093
|
+
getAccessToken;
|
|
11094
|
+
fetchImpl;
|
|
11095
|
+
shippingAddressesEndpoint;
|
|
11096
|
+
logger;
|
|
11097
|
+
constructor(options) {
|
|
11098
|
+
const config = resolveLinkSdkConfig(options);
|
|
11099
|
+
this.verbose = config.verbose;
|
|
11100
|
+
this.getAccessToken = config.getAccessToken;
|
|
11101
|
+
this.fetchImpl = requireFetchImplementation(config);
|
|
11102
|
+
this.shippingAddressesEndpoint = `${config.apiBaseUrl}/shipping_addresses`;
|
|
11103
|
+
this.logger = config.logger;
|
|
11104
|
+
}
|
|
11105
|
+
async rawFetch(opts) {
|
|
11106
|
+
if (this.verbose) {
|
|
11107
|
+
const redactedHeaders = { ...opts.headers };
|
|
11108
|
+
if (redactedHeaders.Authorization)
|
|
11109
|
+
redactedHeaders.Authorization = "Bearer <redacted>";
|
|
11110
|
+
this.logger.debug(`> ${opts.method} ${opts.url}`);
|
|
11111
|
+
this.logger.debug(` Headers: ${JSON.stringify(redactedHeaders)}`);
|
|
11112
|
+
}
|
|
11113
|
+
let response;
|
|
11114
|
+
try {
|
|
11115
|
+
response = await this.fetchImpl(opts.url, {
|
|
11116
|
+
method: opts.method,
|
|
11117
|
+
headers: opts.headers
|
|
11118
|
+
});
|
|
11119
|
+
} catch (error) {
|
|
11120
|
+
throw new LinkTransportError(
|
|
11121
|
+
`Request failed: ${opts.method} ${opts.url}`,
|
|
11122
|
+
{
|
|
11123
|
+
cause: error
|
|
11124
|
+
}
|
|
11125
|
+
);
|
|
11126
|
+
}
|
|
11127
|
+
const rawBody = await response.text();
|
|
11128
|
+
let data = null;
|
|
11129
|
+
try {
|
|
11130
|
+
data = JSON.parse(rawBody);
|
|
11131
|
+
} catch {
|
|
11132
|
+
}
|
|
11133
|
+
if (this.verbose) {
|
|
11134
|
+
this.logger.debug(`< ${response.status} ${response.statusText}`);
|
|
11135
|
+
response.headers.forEach((value, key) => {
|
|
11136
|
+
this.logger.debug(` ${key}: ${value}`);
|
|
11137
|
+
});
|
|
11138
|
+
this.logger.debug(rawBody);
|
|
11139
|
+
}
|
|
11140
|
+
return { status: response.status, data, rawBody };
|
|
11141
|
+
}
|
|
11142
|
+
async apiFetch(opts) {
|
|
11143
|
+
const token = await this.getAccessToken();
|
|
11144
|
+
const authedOpts = {
|
|
11145
|
+
...opts,
|
|
11146
|
+
headers: { ...opts.headers, Authorization: `Bearer ${token}` }
|
|
11147
|
+
};
|
|
11148
|
+
const res = await this.rawFetch(authedOpts);
|
|
11149
|
+
if (res.status === 401) {
|
|
11150
|
+
const refreshedToken = await this.getAccessToken({ forceRefresh: true });
|
|
11151
|
+
authedOpts.headers.Authorization = `Bearer ${refreshedToken}`;
|
|
11152
|
+
return this.rawFetch(authedOpts);
|
|
11153
|
+
}
|
|
11154
|
+
return res;
|
|
11155
|
+
}
|
|
11156
|
+
list() {
|
|
11157
|
+
return this.listShippingAddresses();
|
|
11158
|
+
}
|
|
11159
|
+
async listShippingAddresses() {
|
|
11160
|
+
const { status, data, rawBody } = await this.apiFetch({
|
|
11161
|
+
method: "GET",
|
|
11162
|
+
url: this.shippingAddressesEndpoint
|
|
11163
|
+
});
|
|
11164
|
+
if (status < 200 || status >= 300) {
|
|
11165
|
+
const body2 = data;
|
|
11166
|
+
const msg = body2?.error ?? body2?.message ?? (rawBody || "unknown error");
|
|
11167
|
+
throw new LinkApiError(
|
|
11168
|
+
`Failed to list shipping addresses (${status}): ${msg}`,
|
|
11169
|
+
{ status, rawBody, details: data }
|
|
11170
|
+
);
|
|
11171
|
+
}
|
|
11172
|
+
const body = data;
|
|
11173
|
+
return body?.shipping_addresses ?? [];
|
|
11174
|
+
}
|
|
11175
|
+
};
|
|
11079
11176
|
function normalizeSpendRequest(data) {
|
|
11080
11177
|
const sr = data;
|
|
11081
11178
|
if (typeof sr.shared_payment_token === "string") {
|
|
@@ -11208,6 +11305,22 @@ var SpendRequestResource = class {
|
|
|
11208
11305
|
}
|
|
11209
11306
|
return normalizeSpendRequest(data);
|
|
11210
11307
|
}
|
|
11308
|
+
cancel(id) {
|
|
11309
|
+
return this.cancelSpendRequest(id);
|
|
11310
|
+
}
|
|
11311
|
+
async cancelSpendRequest(id) {
|
|
11312
|
+
const { status, data, rawBody } = await this.apiFetch({
|
|
11313
|
+
method: "POST",
|
|
11314
|
+
url: `${this.spendRequestsEndpoint}/${id}/cancel`
|
|
11315
|
+
});
|
|
11316
|
+
if (status < 200 || status >= 300) {
|
|
11317
|
+
throw new LinkApiError(
|
|
11318
|
+
`Failed to cancel spend request (${status}): ${extractApiError(data, rawBody)}`,
|
|
11319
|
+
{ status, rawBody, details: data }
|
|
11320
|
+
);
|
|
11321
|
+
}
|
|
11322
|
+
return normalizeSpendRequest(data);
|
|
11323
|
+
}
|
|
11211
11324
|
async requestApproval(id) {
|
|
11212
11325
|
const { status, data, rawBody } = await this.apiFetch({
|
|
11213
11326
|
method: "POST",
|
|
@@ -11245,16 +11358,155 @@ var SpendRequestResource = class {
|
|
|
11245
11358
|
return normalizeSpendRequest(data);
|
|
11246
11359
|
}
|
|
11247
11360
|
};
|
|
11361
|
+
var UserInfoResource = class {
|
|
11362
|
+
verbose;
|
|
11363
|
+
getAccessToken;
|
|
11364
|
+
fetchImpl;
|
|
11365
|
+
userInfoEndpoint;
|
|
11366
|
+
logger;
|
|
11367
|
+
constructor(options) {
|
|
11368
|
+
const config = resolveLinkSdkConfig(options);
|
|
11369
|
+
this.verbose = config.verbose;
|
|
11370
|
+
this.getAccessToken = config.getAccessToken;
|
|
11371
|
+
this.fetchImpl = requireFetchImplementation(config);
|
|
11372
|
+
this.userInfoEndpoint = `${config.apiBaseUrl}/userinfo`;
|
|
11373
|
+
this.logger = config.logger;
|
|
11374
|
+
}
|
|
11375
|
+
async rawFetch(opts) {
|
|
11376
|
+
if (this.verbose) {
|
|
11377
|
+
const redactedHeaders = { ...opts.headers };
|
|
11378
|
+
if (redactedHeaders.Authorization)
|
|
11379
|
+
redactedHeaders.Authorization = "Bearer <redacted>";
|
|
11380
|
+
this.logger.debug(`> ${opts.method} ${opts.url}`);
|
|
11381
|
+
this.logger.debug(` Headers: ${JSON.stringify(redactedHeaders)}`);
|
|
11382
|
+
}
|
|
11383
|
+
let response;
|
|
11384
|
+
try {
|
|
11385
|
+
response = await this.fetchImpl(opts.url, {
|
|
11386
|
+
method: opts.method,
|
|
11387
|
+
headers: opts.headers
|
|
11388
|
+
});
|
|
11389
|
+
} catch (error) {
|
|
11390
|
+
throw new LinkTransportError(
|
|
11391
|
+
`Request failed: ${opts.method} ${opts.url}`,
|
|
11392
|
+
{
|
|
11393
|
+
cause: error
|
|
11394
|
+
}
|
|
11395
|
+
);
|
|
11396
|
+
}
|
|
11397
|
+
const rawBody = await response.text();
|
|
11398
|
+
let data = null;
|
|
11399
|
+
try {
|
|
11400
|
+
data = JSON.parse(rawBody);
|
|
11401
|
+
} catch {
|
|
11402
|
+
}
|
|
11403
|
+
if (this.verbose) {
|
|
11404
|
+
this.logger.debug(`< ${response.status} ${response.statusText}`);
|
|
11405
|
+
response.headers.forEach((value, key) => {
|
|
11406
|
+
this.logger.debug(` ${key}: ${value}`);
|
|
11407
|
+
});
|
|
11408
|
+
this.logger.debug(rawBody);
|
|
11409
|
+
}
|
|
11410
|
+
return { status: response.status, data, rawBody };
|
|
11411
|
+
}
|
|
11412
|
+
async apiFetch(opts) {
|
|
11413
|
+
const token = await this.getAccessToken();
|
|
11414
|
+
const authedOpts = {
|
|
11415
|
+
...opts,
|
|
11416
|
+
headers: { ...opts.headers, Authorization: `Bearer ${token}` }
|
|
11417
|
+
};
|
|
11418
|
+
const res = await this.rawFetch(authedOpts);
|
|
11419
|
+
if (res.status === 401) {
|
|
11420
|
+
const refreshedToken = await this.getAccessToken({ forceRefresh: true });
|
|
11421
|
+
authedOpts.headers.Authorization = `Bearer ${refreshedToken}`;
|
|
11422
|
+
return this.rawFetch(authedOpts);
|
|
11423
|
+
}
|
|
11424
|
+
return res;
|
|
11425
|
+
}
|
|
11426
|
+
async retrieve() {
|
|
11427
|
+
const { status, data, rawBody } = await this.apiFetch({
|
|
11428
|
+
method: "GET",
|
|
11429
|
+
url: this.userInfoEndpoint
|
|
11430
|
+
});
|
|
11431
|
+
if (status < 200 || status >= 300) {
|
|
11432
|
+
const body2 = data;
|
|
11433
|
+
const msg = body2?.error ?? body2?.message ?? (rawBody || "unknown error");
|
|
11434
|
+
throw new LinkApiError(
|
|
11435
|
+
`Failed to retrieve user info (${status}): ${msg}`,
|
|
11436
|
+
{
|
|
11437
|
+
status,
|
|
11438
|
+
rawBody,
|
|
11439
|
+
details: data
|
|
11440
|
+
}
|
|
11441
|
+
);
|
|
11442
|
+
}
|
|
11443
|
+
const body = data;
|
|
11444
|
+
return {
|
|
11445
|
+
email: body?.email ?? null,
|
|
11446
|
+
name: body?.name ?? null,
|
|
11447
|
+
first_name: body?.first_name ?? null,
|
|
11448
|
+
last_name: body?.last_name ?? null,
|
|
11449
|
+
phone: body?.phone ?? null
|
|
11450
|
+
};
|
|
11451
|
+
}
|
|
11452
|
+
};
|
|
11453
|
+
|
|
11454
|
+
// src/cli.tsx
|
|
11455
|
+
import { Cli as Cli9 } from "incur";
|
|
11248
11456
|
|
|
11249
11457
|
// src/commands/auth/index.tsx
|
|
11250
11458
|
import { Cli } from "incur";
|
|
11459
|
+
|
|
11460
|
+
// src/utils/poll-until.ts
|
|
11461
|
+
async function* pollUntil(options) {
|
|
11462
|
+
const { fn, isTerminal, interval, timeout, maxAttempts } = options;
|
|
11463
|
+
const deadline = timeout !== void 0 && timeout >= 0 ? Date.now() + timeout * 1e3 : void 0;
|
|
11464
|
+
let attempts = 0;
|
|
11465
|
+
let previousSnapshot;
|
|
11466
|
+
while (true) {
|
|
11467
|
+
const value = await fn();
|
|
11468
|
+
if (isTerminal(value) || interval <= 0) {
|
|
11469
|
+
yield { value, terminal: true };
|
|
11470
|
+
return;
|
|
11471
|
+
}
|
|
11472
|
+
attempts++;
|
|
11473
|
+
const maxAttemptsExhausted = maxAttempts > 0 && attempts >= maxAttempts;
|
|
11474
|
+
const timeoutReached = deadline !== void 0 && Date.now() >= deadline;
|
|
11475
|
+
if (maxAttemptsExhausted) {
|
|
11476
|
+
yield { value, terminal: true, reason: "max_attempts" };
|
|
11477
|
+
return;
|
|
11478
|
+
}
|
|
11479
|
+
if (timeoutReached) {
|
|
11480
|
+
yield { value, terminal: true, reason: "timeout" };
|
|
11481
|
+
return;
|
|
11482
|
+
}
|
|
11483
|
+
const snapshot = JSON.stringify(value);
|
|
11484
|
+
if (snapshot !== previousSnapshot) {
|
|
11485
|
+
previousSnapshot = snapshot;
|
|
11486
|
+
yield { value, terminal: false };
|
|
11487
|
+
}
|
|
11488
|
+
await new Promise((resolve) => setTimeout(resolve, interval * 1e3));
|
|
11489
|
+
}
|
|
11490
|
+
}
|
|
11491
|
+
|
|
11492
|
+
// src/utils/render-interactive.tsx
|
|
11251
11493
|
import { render } from "ink";
|
|
11494
|
+
async function renderInteractive(element, getResult) {
|
|
11495
|
+
const { waitUntilExit } = render(element);
|
|
11496
|
+
await waitUntilExit();
|
|
11497
|
+
if (getResult) {
|
|
11498
|
+
return getResult();
|
|
11499
|
+
}
|
|
11500
|
+
}
|
|
11252
11501
|
|
|
11253
11502
|
// src/commands/auth/login.tsx
|
|
11254
11503
|
import { Box, Text, useInput } from "ink";
|
|
11255
11504
|
import Spinner from "ink-spinner";
|
|
11256
11505
|
import { useEffect, useState } from "react";
|
|
11257
11506
|
|
|
11507
|
+
// src/utils/constants.ts
|
|
11508
|
+
var DISPLAY_DELAY_MS = 1500;
|
|
11509
|
+
|
|
11258
11510
|
// src/utils/open-url.ts
|
|
11259
11511
|
import { spawn } from "child_process";
|
|
11260
11512
|
function openUrl(url) {
|
|
@@ -11286,8 +11538,10 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
11286
11538
|
var Login = ({
|
|
11287
11539
|
authResource,
|
|
11288
11540
|
clientName,
|
|
11541
|
+
authStorage: authStorage2 = storage,
|
|
11289
11542
|
onComplete
|
|
11290
11543
|
}) => {
|
|
11544
|
+
const storage2 = authStorage2;
|
|
11291
11545
|
const [status, setStatus] = useState("initiating");
|
|
11292
11546
|
const [userCode, setUserCode] = useState("");
|
|
11293
11547
|
const [verificationUrl, setVerificationUrl] = useState("");
|
|
@@ -11324,9 +11578,9 @@ var Login = ({
|
|
|
11324
11578
|
const tokens = await authResource.pollDeviceAuth(deviceCode);
|
|
11325
11579
|
if (tokens) {
|
|
11326
11580
|
clearInterval(pollInterval);
|
|
11327
|
-
|
|
11581
|
+
storage2.setAuth(tokens);
|
|
11328
11582
|
setStatus("success");
|
|
11329
|
-
setTimeout(onComplete,
|
|
11583
|
+
setTimeout(onComplete, DISPLAY_DELAY_MS);
|
|
11330
11584
|
}
|
|
11331
11585
|
} catch (err) {
|
|
11332
11586
|
clearInterval(pollInterval);
|
|
@@ -11338,7 +11592,7 @@ var Login = ({
|
|
|
11338
11592
|
};
|
|
11339
11593
|
const timeout = setTimeout(startPolling, 1e3);
|
|
11340
11594
|
return () => clearTimeout(timeout);
|
|
11341
|
-
}, [status, deviceCode, authResource, onComplete]);
|
|
11595
|
+
}, [status, deviceCode, authResource, onComplete, storage2]);
|
|
11342
11596
|
if (status === "initiating") {
|
|
11343
11597
|
return /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
|
|
11344
11598
|
/* @__PURE__ */ jsx(Spinner, { type: "dots" }),
|
|
@@ -11391,28 +11645,75 @@ var Login = ({
|
|
|
11391
11645
|
|
|
11392
11646
|
// src/commands/auth/logout.tsx
|
|
11393
11647
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
11394
|
-
import
|
|
11395
|
-
import {
|
|
11396
|
-
|
|
11397
|
-
|
|
11648
|
+
import Spinner2 from "ink-spinner";
|
|
11649
|
+
import { useCallback } from "react";
|
|
11650
|
+
|
|
11651
|
+
// src/hooks/use-async-action.ts
|
|
11652
|
+
import { useEffect as useEffect2, useRef, useState as useState2 } from "react";
|
|
11653
|
+
function useAsyncAction(action, onComplete) {
|
|
11654
|
+
const [status, setStatus] = useState2("loading");
|
|
11655
|
+
const [data, setData] = useState2(null);
|
|
11656
|
+
const [error, setError] = useState2("");
|
|
11657
|
+
const onCompleteRef = useRef(onComplete);
|
|
11658
|
+
onCompleteRef.current = onComplete;
|
|
11398
11659
|
useEffect2(() => {
|
|
11660
|
+
let timeoutId = null;
|
|
11661
|
+
let cancelled = false;
|
|
11399
11662
|
const run = async () => {
|
|
11400
|
-
|
|
11401
|
-
|
|
11402
|
-
|
|
11403
|
-
|
|
11404
|
-
|
|
11405
|
-
|
|
11663
|
+
try {
|
|
11664
|
+
const result = await action();
|
|
11665
|
+
if (cancelled) return;
|
|
11666
|
+
setData(result);
|
|
11667
|
+
setStatus("success");
|
|
11668
|
+
timeoutId = setTimeout(
|
|
11669
|
+
() => onCompleteRef.current(result),
|
|
11670
|
+
DISPLAY_DELAY_MS
|
|
11671
|
+
);
|
|
11672
|
+
} catch (err) {
|
|
11673
|
+
if (cancelled) return;
|
|
11674
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
11675
|
+
setError(message);
|
|
11676
|
+
setStatus("error");
|
|
11677
|
+
timeoutId = setTimeout(
|
|
11678
|
+
() => onCompleteRef.current(null),
|
|
11679
|
+
DISPLAY_DELAY_MS
|
|
11680
|
+
);
|
|
11406
11681
|
}
|
|
11407
|
-
storage.clearAuth();
|
|
11408
|
-
storage.deleteConfig();
|
|
11409
|
-
setDone(true);
|
|
11410
|
-
setTimeout(onComplete, 1e3);
|
|
11411
11682
|
};
|
|
11412
11683
|
run();
|
|
11413
|
-
|
|
11414
|
-
|
|
11415
|
-
|
|
11684
|
+
return () => {
|
|
11685
|
+
cancelled = true;
|
|
11686
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
11687
|
+
};
|
|
11688
|
+
}, [action]);
|
|
11689
|
+
return { status, data, error };
|
|
11690
|
+
}
|
|
11691
|
+
|
|
11692
|
+
// src/commands/auth/logout.tsx
|
|
11693
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
11694
|
+
var Logout = ({
|
|
11695
|
+
authResource,
|
|
11696
|
+
authStorage: authStorage2 = storage,
|
|
11697
|
+
onComplete
|
|
11698
|
+
}) => {
|
|
11699
|
+
const storage2 = authStorage2;
|
|
11700
|
+
const action = useCallback(async () => {
|
|
11701
|
+
const auth = storage2.getAuth();
|
|
11702
|
+
if (auth?.refresh_token) {
|
|
11703
|
+
try {
|
|
11704
|
+
await authResource.revokeToken(auth.refresh_token);
|
|
11705
|
+
} catch {
|
|
11706
|
+
}
|
|
11707
|
+
}
|
|
11708
|
+
storage2.clearAuth();
|
|
11709
|
+
storage2.deleteConfig();
|
|
11710
|
+
}, [authResource, storage2]);
|
|
11711
|
+
const { status } = useAsyncAction(action, onComplete);
|
|
11712
|
+
if (status === "loading") {
|
|
11713
|
+
return /* @__PURE__ */ jsx2(Box2, { children: /* @__PURE__ */ jsxs2(Text2, { color: "cyan", children: [
|
|
11714
|
+
/* @__PURE__ */ jsx2(Spinner2, { type: "dots" }),
|
|
11715
|
+
" Logging out..."
|
|
11716
|
+
] }) });
|
|
11416
11717
|
}
|
|
11417
11718
|
return /* @__PURE__ */ jsx2(Box2, { children: /* @__PURE__ */ jsx2(Text2, { color: "green", children: "\u2713 Logged out successfully" }) });
|
|
11418
11719
|
};
|
|
@@ -11435,16 +11736,20 @@ var statusOptions = z.object({
|
|
|
11435
11736
|
// src/commands/auth/status.tsx
|
|
11436
11737
|
import { Box as Box3, Text as Text3 } from "ink";
|
|
11437
11738
|
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
11438
|
-
import { jsx as jsx3, jsxs as
|
|
11439
|
-
var AuthStatus = ({
|
|
11739
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
11740
|
+
var AuthStatus = ({
|
|
11741
|
+
authStorage: authStorage2 = storage,
|
|
11742
|
+
onComplete
|
|
11743
|
+
}) => {
|
|
11744
|
+
const storage2 = authStorage2;
|
|
11440
11745
|
const [checked, setChecked] = useState3(false);
|
|
11441
11746
|
const [authenticated, setAuthenticated] = useState3(false);
|
|
11442
11747
|
const [tokenPreview, setTokenPreview] = useState3("");
|
|
11443
11748
|
const [tokenType, setTokenType] = useState3("");
|
|
11444
11749
|
const [credentialsPath, setCredentialsPath] = useState3("");
|
|
11445
11750
|
useEffect3(() => {
|
|
11446
|
-
const auth =
|
|
11447
|
-
const credentialsPath2 =
|
|
11751
|
+
const auth = storage2.getAuth();
|
|
11752
|
+
const credentialsPath2 = storage2.getPath();
|
|
11448
11753
|
if (auth) {
|
|
11449
11754
|
setAuthenticated(true);
|
|
11450
11755
|
setTokenPreview(`${auth.access_token.substring(0, 20)}...`);
|
|
@@ -11452,34 +11757,34 @@ var AuthStatus = ({ onComplete }) => {
|
|
|
11452
11757
|
}
|
|
11453
11758
|
setCredentialsPath(credentialsPath2);
|
|
11454
11759
|
setChecked(true);
|
|
11455
|
-
setTimeout(onComplete,
|
|
11456
|
-
}, [onComplete]);
|
|
11760
|
+
setTimeout(onComplete, DISPLAY_DELAY_MS);
|
|
11761
|
+
}, [onComplete, storage2]);
|
|
11457
11762
|
if (!checked) {
|
|
11458
11763
|
return null;
|
|
11459
11764
|
}
|
|
11460
11765
|
if (authenticated) {
|
|
11461
|
-
return /* @__PURE__ */
|
|
11766
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
11462
11767
|
/* @__PURE__ */ jsx3(Text3, { color: "green", children: "\u2713 Authenticated" }),
|
|
11463
|
-
/* @__PURE__ */
|
|
11464
|
-
/* @__PURE__ */
|
|
11768
|
+
/* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
|
|
11769
|
+
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
11465
11770
|
"Access token: ",
|
|
11466
11771
|
/* @__PURE__ */ jsx3(Text3, { bold: true, children: tokenPreview })
|
|
11467
11772
|
] }),
|
|
11468
|
-
/* @__PURE__ */
|
|
11773
|
+
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
11469
11774
|
"Token type: ",
|
|
11470
11775
|
/* @__PURE__ */ jsx3(Text3, { bold: true, children: tokenType })
|
|
11471
11776
|
] }),
|
|
11472
|
-
/* @__PURE__ */
|
|
11777
|
+
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
11473
11778
|
"Credentials: ",
|
|
11474
11779
|
/* @__PURE__ */ jsx3(Text3, { bold: true, children: credentialsPath })
|
|
11475
11780
|
] })
|
|
11476
11781
|
] })
|
|
11477
11782
|
] });
|
|
11478
11783
|
}
|
|
11479
|
-
return /* @__PURE__ */
|
|
11784
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
11480
11785
|
/* @__PURE__ */ jsx3(Text3, { color: "yellow", children: "\u2717 Not authenticated" }),
|
|
11481
11786
|
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: 'Run "link-cli auth login" to authenticate' }),
|
|
11482
|
-
/* @__PURE__ */ jsx3(Box3, { marginTop: 1, paddingX: 2, children: /* @__PURE__ */
|
|
11787
|
+
/* @__PURE__ */ jsx3(Box3, { marginTop: 1, paddingX: 2, children: /* @__PURE__ */ jsxs3(Text3, { children: [
|
|
11483
11788
|
"Credentials: ",
|
|
11484
11789
|
/* @__PURE__ */ jsx3(Text3, { bold: true, children: credentialsPath })
|
|
11485
11790
|
] }) })
|
|
@@ -11488,7 +11793,8 @@ var AuthStatus = ({ onComplete }) => {
|
|
|
11488
11793
|
|
|
11489
11794
|
// src/commands/auth/index.tsx
|
|
11490
11795
|
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
11491
|
-
function createAuthCli(authResource,
|
|
11796
|
+
function createAuthCli(authResource, getUpdateInfo2, authStorage2) {
|
|
11797
|
+
const storage2 = authStorage2 ?? storage;
|
|
11492
11798
|
const cli2 = Cli.create("auth", {
|
|
11493
11799
|
description: "Authentication commands"
|
|
11494
11800
|
});
|
|
@@ -11505,25 +11811,22 @@ function createAuthCli(authResource, updateInfo) {
|
|
|
11505
11811
|
});
|
|
11506
11812
|
}
|
|
11507
11813
|
if (!c.agent && !c.formatExplicit) {
|
|
11508
|
-
return
|
|
11509
|
-
|
|
11510
|
-
|
|
11511
|
-
|
|
11512
|
-
|
|
11513
|
-
|
|
11514
|
-
|
|
11515
|
-
|
|
11516
|
-
}
|
|
11814
|
+
return renderInteractive(
|
|
11815
|
+
/* @__PURE__ */ jsx4(
|
|
11816
|
+
Login,
|
|
11817
|
+
{
|
|
11818
|
+
authResource,
|
|
11819
|
+
clientName,
|
|
11820
|
+
authStorage: storage2,
|
|
11821
|
+
onComplete: () => {
|
|
11517
11822
|
}
|
|
11518
|
-
|
|
11519
|
-
)
|
|
11520
|
-
|
|
11521
|
-
|
|
11522
|
-
);
|
|
11523
|
-
});
|
|
11823
|
+
}
|
|
11824
|
+
),
|
|
11825
|
+
() => ({ authenticated: true, token_type: "Bearer" })
|
|
11826
|
+
);
|
|
11524
11827
|
}
|
|
11525
11828
|
const authRequest = await authResource.initiateDeviceAuth(clientName);
|
|
11526
|
-
|
|
11829
|
+
storage2.setPendingDeviceAuth({
|
|
11527
11830
|
device_code: authRequest.device_code,
|
|
11528
11831
|
interval: authRequest.interval,
|
|
11529
11832
|
expires_at: Date.now() + authRequest.expires_in * 1e3,
|
|
@@ -11546,25 +11849,30 @@ function createAuthCli(authResource, updateInfo) {
|
|
|
11546
11849
|
description: "Log out from Link",
|
|
11547
11850
|
outputPolicy: "agent-only",
|
|
11548
11851
|
async run(c) {
|
|
11549
|
-
const auth =
|
|
11852
|
+
const auth = storage2.getAuth();
|
|
11550
11853
|
if (auth?.refresh_token) {
|
|
11551
11854
|
try {
|
|
11552
11855
|
await authResource.revokeToken(auth.refresh_token);
|
|
11553
11856
|
} catch {
|
|
11554
11857
|
}
|
|
11555
11858
|
}
|
|
11556
|
-
|
|
11557
|
-
|
|
11558
|
-
|
|
11859
|
+
storage2.clearAuth();
|
|
11860
|
+
storage2.clearPendingDeviceAuth();
|
|
11861
|
+
storage2.deleteConfig();
|
|
11559
11862
|
const result = { authenticated: false };
|
|
11560
11863
|
if (!c.agent && !c.formatExplicit) {
|
|
11561
|
-
return
|
|
11562
|
-
|
|
11563
|
-
|
|
11564
|
-
|
|
11565
|
-
|
|
11566
|
-
|
|
11567
|
-
|
|
11864
|
+
return renderInteractive(
|
|
11865
|
+
/* @__PURE__ */ jsx4(
|
|
11866
|
+
Logout,
|
|
11867
|
+
{
|
|
11868
|
+
authResource,
|
|
11869
|
+
authStorage: storage2,
|
|
11870
|
+
onComplete: () => {
|
|
11871
|
+
}
|
|
11872
|
+
}
|
|
11873
|
+
),
|
|
11874
|
+
() => result
|
|
11875
|
+
);
|
|
11568
11876
|
}
|
|
11569
11877
|
return result;
|
|
11570
11878
|
}
|
|
@@ -11574,79 +11882,75 @@ function createAuthCli(authResource, updateInfo) {
|
|
|
11574
11882
|
options: statusOptions,
|
|
11575
11883
|
outputPolicy: "agent-only",
|
|
11576
11884
|
async *run(c) {
|
|
11885
|
+
const opts = c.options;
|
|
11886
|
+
const interval = opts.interval;
|
|
11887
|
+
const maxAttempts = opts.maxAttempts;
|
|
11888
|
+
const updateInfo = await getUpdateInfo2?.({
|
|
11889
|
+
polling: interval > 0
|
|
11890
|
+
});
|
|
11891
|
+
const update = updateInfo ? {
|
|
11892
|
+
current_version: updateInfo.current,
|
|
11893
|
+
latest_version: updateInfo.latest,
|
|
11894
|
+
update_command: "npm install -g @stripe/link-cli"
|
|
11895
|
+
} : void 0;
|
|
11577
11896
|
if (!c.agent && !c.formatExplicit) {
|
|
11578
|
-
return
|
|
11579
|
-
|
|
11580
|
-
|
|
11581
|
-
|
|
11582
|
-
|
|
11583
|
-
|
|
11584
|
-
const auth = storage.getAuth();
|
|
11585
|
-
resolve({
|
|
11897
|
+
return renderInteractive(
|
|
11898
|
+
/* @__PURE__ */ jsx4(AuthStatus, { authStorage: storage2, onComplete: () => {
|
|
11899
|
+
} }),
|
|
11900
|
+
() => {
|
|
11901
|
+
const auth = storage2.getAuth();
|
|
11902
|
+
return {
|
|
11586
11903
|
authenticated: !!auth,
|
|
11587
11904
|
...auth ? {
|
|
11588
11905
|
access_token: `${auth.access_token.substring(0, 20)}...`,
|
|
11589
11906
|
token_type: auth.token_type
|
|
11590
11907
|
} : {},
|
|
11591
|
-
credentials_path:
|
|
11592
|
-
|
|
11593
|
-
|
|
11594
|
-
|
|
11908
|
+
credentials_path: storage2.getPath(),
|
|
11909
|
+
...update && { update }
|
|
11910
|
+
};
|
|
11911
|
+
}
|
|
11912
|
+
);
|
|
11595
11913
|
}
|
|
11596
|
-
const
|
|
11597
|
-
|
|
11598
|
-
|
|
11599
|
-
|
|
11600
|
-
|
|
11601
|
-
|
|
11602
|
-
|
|
11603
|
-
|
|
11604
|
-
|
|
11605
|
-
|
|
11606
|
-
|
|
11607
|
-
|
|
11608
|
-
|
|
11609
|
-
|
|
11610
|
-
|
|
11611
|
-
|
|
11612
|
-
|
|
11613
|
-
|
|
11614
|
-
|
|
11615
|
-
|
|
11616
|
-
|
|
11617
|
-
|
|
11618
|
-
|
|
11619
|
-
|
|
11620
|
-
|
|
11621
|
-
|
|
11622
|
-
|
|
11623
|
-
...
|
|
11914
|
+
for await (const result of pollUntil({
|
|
11915
|
+
fn: async () => {
|
|
11916
|
+
const pending = storage2.getPendingDeviceAuth();
|
|
11917
|
+
if (pending && !storage2.isAuthenticated()) {
|
|
11918
|
+
const tokens = await authResource.pollDeviceAuth(
|
|
11919
|
+
pending.device_code
|
|
11920
|
+
);
|
|
11921
|
+
if (tokens) {
|
|
11922
|
+
storage2.setAuth(tokens);
|
|
11923
|
+
storage2.clearPendingDeviceAuth();
|
|
11924
|
+
}
|
|
11925
|
+
}
|
|
11926
|
+
const auth = storage2.getAuth();
|
|
11927
|
+
if (auth) {
|
|
11928
|
+
return {
|
|
11929
|
+
authenticated: true,
|
|
11930
|
+
access_token: `${auth.access_token.substring(0, 20)}...`,
|
|
11931
|
+
token_type: auth.token_type,
|
|
11932
|
+
credentials_path: storage2.getPath(),
|
|
11933
|
+
...update && { update }
|
|
11934
|
+
};
|
|
11935
|
+
}
|
|
11936
|
+
const currentPending = storage2.getPendingDeviceAuth();
|
|
11937
|
+
return {
|
|
11938
|
+
authenticated: false,
|
|
11939
|
+
credentials_path: storage2.getPath(),
|
|
11940
|
+
...update && { update },
|
|
11941
|
+
...currentPending ? {
|
|
11942
|
+
pending: true,
|
|
11943
|
+
verification_url: currentPending.verification_url,
|
|
11944
|
+
phrase: currentPending.phrase
|
|
11945
|
+
} : {}
|
|
11624
11946
|
};
|
|
11625
|
-
|
|
11626
|
-
|
|
11627
|
-
|
|
11628
|
-
|
|
11629
|
-
|
|
11630
|
-
|
|
11631
|
-
|
|
11632
|
-
...currentPending ? {
|
|
11633
|
-
pending: true,
|
|
11634
|
-
verification_url: currentPending.verification_url,
|
|
11635
|
-
phrase: currentPending.phrase
|
|
11636
|
-
} : {}
|
|
11637
|
-
};
|
|
11638
|
-
attempts++;
|
|
11639
|
-
const shouldStop = interval <= 0 || maxAttempts > 0 && attempts >= maxAttempts || Date.now() >= deadline;
|
|
11640
|
-
if (shouldStop) {
|
|
11641
|
-
yield status;
|
|
11642
|
-
return;
|
|
11643
|
-
}
|
|
11644
|
-
const snapshot = JSON.stringify(status);
|
|
11645
|
-
if (snapshot !== previousAttemptData) {
|
|
11646
|
-
previousAttemptData = snapshot;
|
|
11647
|
-
yield status;
|
|
11648
|
-
}
|
|
11649
|
-
await new Promise((resolve) => setTimeout(resolve, interval * 1e3));
|
|
11947
|
+
},
|
|
11948
|
+
isTerminal: (status) => status.authenticated,
|
|
11949
|
+
interval,
|
|
11950
|
+
maxAttempts,
|
|
11951
|
+
timeout: opts.timeout
|
|
11952
|
+
})) {
|
|
11953
|
+
yield result.value;
|
|
11650
11954
|
}
|
|
11651
11955
|
}
|
|
11652
11956
|
});
|
|
@@ -11655,11 +11959,10 @@ function createAuthCli(authResource, updateInfo) {
|
|
|
11655
11959
|
|
|
11656
11960
|
// src/commands/demo/index.tsx
|
|
11657
11961
|
import { Cli as Cli2, z as z2 } from "incur";
|
|
11658
|
-
import { render as render2 } from "ink";
|
|
11659
11962
|
|
|
11660
11963
|
// src/commands/demo/demo-runner.tsx
|
|
11661
|
-
import { Box as Box8, Text as Text9, useInput as useInput4 } from "ink";
|
|
11662
|
-
import { useCallback, useState as useState7 } from "react";
|
|
11964
|
+
import { Box as Box8, Text as Text9, useApp, useInput as useInput4 } from "ink";
|
|
11965
|
+
import { useCallback as useCallback2, useState as useState7 } from "react";
|
|
11663
11966
|
|
|
11664
11967
|
// src/utils/markdown-text.tsx
|
|
11665
11968
|
import { Text as Text4 } from "ink";
|
|
@@ -11748,13 +12051,13 @@ function renderQrMatrix(url) {
|
|
|
11748
12051
|
}
|
|
11749
12052
|
|
|
11750
12053
|
// src/commands/spend-request/app-download-qr-codes.tsx
|
|
11751
|
-
import { jsx as jsx6, jsxs as
|
|
12054
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
11752
12055
|
var DOWNLOAD_URL = "https://link.com/download";
|
|
11753
12056
|
var AppDownloadQrCodes = () => {
|
|
11754
12057
|
const qrLines = useMemo(() => renderQrMatrix(DOWNLOAD_URL), []);
|
|
11755
|
-
return /* @__PURE__ */
|
|
12058
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, children: [
|
|
11756
12059
|
/* @__PURE__ */ jsx6(Text5, { dimColor: true, children: "Get the Link app to approve spend requests from your phone" }),
|
|
11757
|
-
/* @__PURE__ */
|
|
12060
|
+
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", alignItems: "flex-start", marginTop: 1, children: [
|
|
11758
12061
|
qrLines.map((line, i) => (
|
|
11759
12062
|
// biome-ignore lint/suspicious/noArrayIndexKey: stable static array
|
|
11760
12063
|
/* @__PURE__ */ jsx6(Text5, { children: line }, i)
|
|
@@ -11766,7 +12069,7 @@ var AppDownloadQrCodes = () => {
|
|
|
11766
12069
|
|
|
11767
12070
|
// src/commands/demo/card-flow.tsx
|
|
11768
12071
|
import { Box as Box5, Text as Text6, useInput as useInput2 } from "ink";
|
|
11769
|
-
import { useEffect as useEffect4, useRef, useState as useState4 } from "react";
|
|
12072
|
+
import { useEffect as useEffect4, useRef as useRef2, useState as useState4 } from "react";
|
|
11770
12073
|
|
|
11771
12074
|
// src/utils/poll-until-approved.ts
|
|
11772
12075
|
function pollUntilApproved(repository, id, options = {}) {
|
|
@@ -11930,7 +12233,7 @@ var ONBOARD = {
|
|
|
11930
12233
|
};
|
|
11931
12234
|
|
|
11932
12235
|
// src/commands/demo/card-flow.tsx
|
|
11933
|
-
import { Fragment, jsx as jsx7, jsxs as
|
|
12236
|
+
import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
11934
12237
|
function formatPmLabel(pm) {
|
|
11935
12238
|
return `${pm.card_details?.brand ?? pm.type} ****${pm.card_details?.last4 ?? ""}`;
|
|
11936
12239
|
}
|
|
@@ -11955,9 +12258,9 @@ var CardFlow = ({
|
|
|
11955
12258
|
const [spendRequest, setSpendRequest] = useState4(null);
|
|
11956
12259
|
const [error, setError] = useState4("");
|
|
11957
12260
|
const approvalUrl = spendRequest?.approval_url ?? "";
|
|
11958
|
-
const enterResolver =
|
|
11959
|
-
const pmResolver =
|
|
11960
|
-
const retryChoiceResolver =
|
|
12261
|
+
const enterResolver = useRef2(null);
|
|
12262
|
+
const pmResolver = useRef2(null);
|
|
12263
|
+
const retryChoiceResolver = useRef2(null);
|
|
11961
12264
|
function waitForEnter() {
|
|
11962
12265
|
return new Promise((resolve) => {
|
|
11963
12266
|
enterResolver.current = resolve;
|
|
@@ -12005,7 +12308,7 @@ var CardFlow = ({
|
|
|
12005
12308
|
}
|
|
12006
12309
|
}
|
|
12007
12310
|
});
|
|
12008
|
-
const started =
|
|
12311
|
+
const started = useRef2(false);
|
|
12009
12312
|
useEffect4(() => {
|
|
12010
12313
|
if (started.current) return;
|
|
12011
12314
|
started.current = true;
|
|
@@ -12056,7 +12359,12 @@ var CardFlow = ({
|
|
|
12056
12359
|
setStep("await-approval");
|
|
12057
12360
|
for (; ; ) {
|
|
12058
12361
|
try {
|
|
12059
|
-
await pollUntilApproved(spendRequestRepo2, result.id);
|
|
12362
|
+
const final = await pollUntilApproved(spendRequestRepo2, result.id);
|
|
12363
|
+
if (final.status !== "approved") {
|
|
12364
|
+
throw new Error(
|
|
12365
|
+
`Spend request did not reach approved (status: ${final.status})`
|
|
12366
|
+
);
|
|
12367
|
+
}
|
|
12060
12368
|
break;
|
|
12061
12369
|
} catch (err) {
|
|
12062
12370
|
if (err.message === "Approval polling timed out") {
|
|
@@ -12109,21 +12417,21 @@ var CardFlow = ({
|
|
|
12109
12417
|
];
|
|
12110
12418
|
return order.indexOf(step) > order.indexOf(target);
|
|
12111
12419
|
};
|
|
12112
|
-
const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */
|
|
12420
|
+
const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */ jsxs5(Text6, { dimColor: true, children: [
|
|
12113
12421
|
"\n",
|
|
12114
12422
|
">",
|
|
12115
12423
|
" ",
|
|
12116
12424
|
label
|
|
12117
12425
|
] });
|
|
12118
|
-
return /* @__PURE__ */
|
|
12426
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", gap: 1, children: [
|
|
12119
12427
|
/* @__PURE__ */ jsx7(Text6, { bold: true, color: "cyan", children: CARD_FLOW.title }),
|
|
12120
|
-
/* @__PURE__ */
|
|
12121
|
-
/* @__PURE__ */
|
|
12428
|
+
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
12429
|
+
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "row", gap: 1, children: [
|
|
12122
12430
|
/* @__PURE__ */ jsx7(Text6, { color: "yellow", children: "[testmode]" }),
|
|
12123
12431
|
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: DEMO_MERCHANT_URL })
|
|
12124
12432
|
] }),
|
|
12125
12433
|
/* @__PURE__ */ jsx7(MarkdownText, { children: CARD_FLOW.intro.description }),
|
|
12126
|
-
/* @__PURE__ */
|
|
12434
|
+
/* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", children: [
|
|
12127
12435
|
/* @__PURE__ */ jsx7(Text6, { children: "What happens:" }),
|
|
12128
12436
|
CARD_FLOW.intro.steps.map((s, i) => {
|
|
12129
12437
|
const doneAfter = [
|
|
@@ -12140,17 +12448,17 @@ var CardFlow = ({
|
|
|
12140
12448
|
];
|
|
12141
12449
|
const done = pastStep(doneAfter[i]);
|
|
12142
12450
|
const active = !done && (step === activeFrom[i] || pastStep(activeFrom[i]));
|
|
12143
|
-
return done ? /* @__PURE__ */
|
|
12451
|
+
return done ? /* @__PURE__ */ jsxs5(Text6, { dimColor: true, strikethrough: true, children: [
|
|
12144
12452
|
" ",
|
|
12145
12453
|
i + 1,
|
|
12146
12454
|
". ",
|
|
12147
12455
|
s
|
|
12148
|
-
] }, s) : active ? /* @__PURE__ */
|
|
12456
|
+
] }, s) : active ? /* @__PURE__ */ jsxs5(Text6, { bold: true, color: "cyan", children: [
|
|
12149
12457
|
" ",
|
|
12150
12458
|
i + 1,
|
|
12151
12459
|
". ",
|
|
12152
12460
|
s
|
|
12153
|
-
] }, s) : /* @__PURE__ */
|
|
12461
|
+
] }, s) : /* @__PURE__ */ jsxs5(Text6, { dimColor: true, children: [
|
|
12154
12462
|
" ",
|
|
12155
12463
|
i + 1,
|
|
12156
12464
|
". ",
|
|
@@ -12161,23 +12469,23 @@ var CardFlow = ({
|
|
|
12161
12469
|
step === "intro" && prompt(CARD_FLOW.intro.prompt)
|
|
12162
12470
|
] }),
|
|
12163
12471
|
step === "fetch-pm" && /* @__PURE__ */ jsx7(Box5, { flexDirection: "column", children: /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Fetching payment methods from your Link wallet..." }) }),
|
|
12164
|
-
(step === "pick-pm" || step === "explain-pm") && /* @__PURE__ */
|
|
12165
|
-
step === "pick-pm" && paymentMethods.length > 1 && /* @__PURE__ */
|
|
12472
|
+
(step === "pick-pm" || step === "explain-pm") && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
12473
|
+
step === "pick-pm" && paymentMethods.length > 1 && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
12166
12474
|
/* @__PURE__ */ jsx7(Text6, { children: "Which payment method should we use for the demo?" }),
|
|
12167
|
-
/* @__PURE__ */ jsx7(Box5, { flexDirection: "column", marginTop: 1, children: paymentMethods.map((pm, i) => /* @__PURE__ */ jsx7(Text6, { children: i === selectedPmIndex ? /* @__PURE__ */
|
|
12475
|
+
/* @__PURE__ */ jsx7(Box5, { flexDirection: "column", marginTop: 1, children: paymentMethods.map((pm, i) => /* @__PURE__ */ jsx7(Text6, { children: i === selectedPmIndex ? /* @__PURE__ */ jsxs5(Text6, { color: "cyan", bold: true, children: [
|
|
12168
12476
|
">",
|
|
12169
12477
|
" ",
|
|
12170
12478
|
formatPmLabel(pm),
|
|
12171
12479
|
pm.is_default ? " (default)" : ""
|
|
12172
|
-
] }) : /* @__PURE__ */
|
|
12480
|
+
] }) : /* @__PURE__ */ jsxs5(Text6, { dimColor: true, children: [
|
|
12173
12481
|
" ",
|
|
12174
12482
|
formatPmLabel(pm),
|
|
12175
12483
|
pm.is_default ? " (default)" : ""
|
|
12176
12484
|
] }) }, pm.id)) }),
|
|
12177
12485
|
/* @__PURE__ */ jsx7(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Use \u2191\u2193 to select, [Enter] to confirm" }) })
|
|
12178
12486
|
] }),
|
|
12179
|
-
paymentMethod && /* @__PURE__ */
|
|
12180
|
-
/* @__PURE__ */
|
|
12487
|
+
paymentMethod && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
12488
|
+
/* @__PURE__ */ jsxs5(Text6, { color: "green", children: [
|
|
12181
12489
|
"\u2713 Using ",
|
|
12182
12490
|
/* @__PURE__ */ jsx7(Text6, { bold: true, children: pmLabel }),
|
|
12183
12491
|
paymentMethod.is_default ? " (default)" : ""
|
|
@@ -12185,19 +12493,19 @@ var CardFlow = ({
|
|
|
12185
12493
|
step === "explain-pm" && prompt(CARD_FLOW.explainPm.prompt)
|
|
12186
12494
|
] })
|
|
12187
12495
|
] }),
|
|
12188
|
-
step === "create-spend" && /* @__PURE__ */
|
|
12496
|
+
step === "create-spend" && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
12189
12497
|
/* @__PURE__ */ jsx7(MarkdownText, { children: CARD_FLOW.createSpend.description }),
|
|
12190
12498
|
/* @__PURE__ */ jsx7(Box5, { marginY: 1, children: /* @__PURE__ */ jsx7(Text6, { color: "cyan", children: CARD_FLOW.createSpend.loading }) })
|
|
12191
12499
|
] }),
|
|
12192
|
-
(step === "await-approval" || step === "approval-timeout") && spendRequest && /* @__PURE__ */
|
|
12193
|
-
/* @__PURE__ */
|
|
12500
|
+
(step === "await-approval" || step === "approval-timeout") && spendRequest && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
12501
|
+
/* @__PURE__ */ jsxs5(Text6, { color: "green", children: [
|
|
12194
12502
|
"\u2713 Spend request created (",
|
|
12195
12503
|
spendRequest.id,
|
|
12196
12504
|
")"
|
|
12197
12505
|
] }),
|
|
12198
|
-
step === "await-approval" && /* @__PURE__ */
|
|
12506
|
+
step === "await-approval" && /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
12199
12507
|
/* @__PURE__ */ jsx7(Text6, { children: CARD_FLOW.approval.description }),
|
|
12200
|
-
/* @__PURE__ */
|
|
12508
|
+
/* @__PURE__ */ jsxs5(
|
|
12201
12509
|
Box5,
|
|
12202
12510
|
{
|
|
12203
12511
|
flexDirection: "column",
|
|
@@ -12207,7 +12515,7 @@ var CardFlow = ({
|
|
|
12207
12515
|
paddingY: 1,
|
|
12208
12516
|
marginTop: 1,
|
|
12209
12517
|
children: [
|
|
12210
|
-
/* @__PURE__ */
|
|
12518
|
+
/* @__PURE__ */ jsxs5(Text6, { children: [
|
|
12211
12519
|
"Approve at:",
|
|
12212
12520
|
" ",
|
|
12213
12521
|
/* @__PURE__ */ jsx7(Text6, { bold: true, color: "cyan", children: approvalUrl })
|
|
@@ -12218,9 +12526,9 @@ var CardFlow = ({
|
|
|
12218
12526
|
),
|
|
12219
12527
|
/* @__PURE__ */ jsx7(Box5, { marginY: 1, children: /* @__PURE__ */ jsx7(Text6, { color: "cyan", children: CARD_FLOW.approval.loading }) })
|
|
12220
12528
|
] }),
|
|
12221
|
-
step === "approval-timeout" && /* @__PURE__ */
|
|
12529
|
+
step === "approval-timeout" && /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
12222
12530
|
/* @__PURE__ */ jsx7(Text6, { color: "yellow", children: "\u26A0 Approval timed out (5 min). Still pending \u2014 you can still approve." }),
|
|
12223
|
-
/* @__PURE__ */
|
|
12531
|
+
/* @__PURE__ */ jsxs5(
|
|
12224
12532
|
Box5,
|
|
12225
12533
|
{
|
|
12226
12534
|
flexDirection: "column",
|
|
@@ -12230,7 +12538,7 @@ var CardFlow = ({
|
|
|
12230
12538
|
paddingY: 1,
|
|
12231
12539
|
marginTop: 1,
|
|
12232
12540
|
children: [
|
|
12233
|
-
/* @__PURE__ */
|
|
12541
|
+
/* @__PURE__ */ jsxs5(Text6, { children: [
|
|
12234
12542
|
"Approve at:",
|
|
12235
12543
|
" ",
|
|
12236
12544
|
/* @__PURE__ */ jsx7(Text6, { bold: true, color: "cyan", children: approvalUrl })
|
|
@@ -12242,10 +12550,10 @@ var CardFlow = ({
|
|
|
12242
12550
|
/* @__PURE__ */ jsx7(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "r Retry polling q Quit demo" }) })
|
|
12243
12551
|
] })
|
|
12244
12552
|
] }),
|
|
12245
|
-
(step === "show-card" || step === "open-url" || step === "done") && card && /* @__PURE__ */
|
|
12553
|
+
(step === "show-card" || step === "open-url" || step === "done") && card && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
12246
12554
|
/* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u2713 Approved!" }),
|
|
12247
12555
|
/* @__PURE__ */ jsx7(MarkdownText, { children: CARD_FLOW.showCard.description }),
|
|
12248
|
-
/* @__PURE__ */ jsx7(Box5, { flexDirection: "column", paddingX: 2, marginTop: 1, children: /* @__PURE__ */
|
|
12556
|
+
/* @__PURE__ */ jsx7(Box5, { flexDirection: "column", paddingX: 2, marginTop: 1, children: /* @__PURE__ */ jsxs5(Text6, { children: [
|
|
12249
12557
|
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Number " }),
|
|
12250
12558
|
/* @__PURE__ */ jsx7(Text6, { bold: true, children: formatCardNumber(card.number) }),
|
|
12251
12559
|
" ",
|
|
@@ -12254,14 +12562,14 @@ var CardFlow = ({
|
|
|
12254
12562
|
" ",
|
|
12255
12563
|
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "CVC " }),
|
|
12256
12564
|
/* @__PURE__ */ jsx7(Text6, { bold: true, children: card.cvc }),
|
|
12257
|
-
card.billing_address?.postal_code && /* @__PURE__ */
|
|
12565
|
+
card.billing_address?.postal_code && /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
12258
12566
|
" ",
|
|
12259
12567
|
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Zip " }),
|
|
12260
12568
|
/* @__PURE__ */ jsx7(Text6, { bold: true, children: card.billing_address.postal_code })
|
|
12261
12569
|
] }),
|
|
12262
|
-
card.valid_until && /* @__PURE__ */
|
|
12570
|
+
card.valid_until && /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
12263
12571
|
" ",
|
|
12264
|
-
/* @__PURE__ */
|
|
12572
|
+
/* @__PURE__ */ jsxs5(Text6, { dimColor: true, children: [
|
|
12265
12573
|
"expires",
|
|
12266
12574
|
" ",
|
|
12267
12575
|
new Date(card.valid_until).toLocaleTimeString([], {
|
|
@@ -12273,14 +12581,14 @@ var CardFlow = ({
|
|
|
12273
12581
|
] }) }),
|
|
12274
12582
|
step === "show-card" && prompt(CARD_FLOW.showCard.prompt)
|
|
12275
12583
|
] }),
|
|
12276
|
-
step === "done" && /* @__PURE__ */
|
|
12277
|
-
/* @__PURE__ */
|
|
12584
|
+
step === "done" && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
12585
|
+
/* @__PURE__ */ jsxs5(Text6, { color: "green", children: [
|
|
12278
12586
|
"\u2713 ",
|
|
12279
12587
|
CARD_FLOW.done.success
|
|
12280
12588
|
] }),
|
|
12281
12589
|
/* @__PURE__ */ jsx7(Text6, { children: CARD_FLOW.done.detail })
|
|
12282
12590
|
] }),
|
|
12283
|
-
step === "error" && /* @__PURE__ */
|
|
12591
|
+
step === "error" && /* @__PURE__ */ jsxs5(Text6, { color: "red", children: [
|
|
12284
12592
|
"Error: ",
|
|
12285
12593
|
error
|
|
12286
12594
|
] })
|
|
@@ -12289,20 +12597,20 @@ var CardFlow = ({
|
|
|
12289
12597
|
|
|
12290
12598
|
// src/commands/demo/spt-flow.tsx
|
|
12291
12599
|
import { Box as Box7, Text as Text8, useInput as useInput3 } from "ink";
|
|
12292
|
-
import { useEffect as useEffect6, useRef as
|
|
12600
|
+
import { useEffect as useEffect6, useRef as useRef3, useState as useState6 } from "react";
|
|
12293
12601
|
|
|
12294
12602
|
// src/commands/mpp/decode.ts
|
|
12295
12603
|
import { Challenge } from "mppx";
|
|
12296
|
-
function getString(value,
|
|
12604
|
+
function getString(value, path7, required = true) {
|
|
12297
12605
|
if (value == null) {
|
|
12298
12606
|
if (required) {
|
|
12299
|
-
throw new Error(`Invalid stripe challenge request: ${
|
|
12607
|
+
throw new Error(`Invalid stripe challenge request: ${path7}: missing`);
|
|
12300
12608
|
}
|
|
12301
12609
|
return void 0;
|
|
12302
12610
|
}
|
|
12303
12611
|
if (typeof value !== "string") {
|
|
12304
12612
|
throw new Error(
|
|
12305
|
-
`Invalid stripe challenge request: ${
|
|
12613
|
+
`Invalid stripe challenge request: ${path7}: expected string, received ${typeof value}`
|
|
12306
12614
|
);
|
|
12307
12615
|
}
|
|
12308
12616
|
return value;
|
|
@@ -12371,12 +12679,12 @@ function decodeStripeChallenge(challengeHeader) {
|
|
|
12371
12679
|
|
|
12372
12680
|
// src/commands/mpp/pay.tsx
|
|
12373
12681
|
import { Box as Box6, Text as Text7 } from "ink";
|
|
12374
|
-
import
|
|
12682
|
+
import Spinner3 from "ink-spinner";
|
|
12375
12683
|
import { Credential, Method } from "mppx";
|
|
12376
12684
|
import { Mppx, Transport } from "mppx/client";
|
|
12377
12685
|
import { Methods as StripeMethods } from "mppx/stripe";
|
|
12378
12686
|
import { useEffect as useEffect5, useState as useState5 } from "react";
|
|
12379
|
-
import { jsx as jsx8, jsxs as
|
|
12687
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
12380
12688
|
function buildHeaders(data, headers) {
|
|
12381
12689
|
const result = {};
|
|
12382
12690
|
if (data !== void 0) {
|
|
@@ -12391,14 +12699,9 @@ function buildHeaders(data, headers) {
|
|
|
12391
12699
|
}
|
|
12392
12700
|
return result;
|
|
12393
12701
|
}
|
|
12394
|
-
async function readPayResult(response
|
|
12702
|
+
async function readPayResult(response) {
|
|
12395
12703
|
const responseHeaders = Object.fromEntries(response.headers.entries());
|
|
12396
12704
|
const body = await response.text();
|
|
12397
|
-
if (options?.failOnError && !response.ok) {
|
|
12398
|
-
throw new Error(
|
|
12399
|
-
`Payment submission failed with status ${response.status}: ${body}`
|
|
12400
|
-
);
|
|
12401
|
-
}
|
|
12402
12705
|
return { status: response.status, headers: responseHeaders, body };
|
|
12403
12706
|
}
|
|
12404
12707
|
function createStripePaymentClient(spt) {
|
|
@@ -12470,7 +12773,7 @@ async function runMppPay(url, spendRequestId, method, data, headers, repository)
|
|
|
12470
12773
|
Authorization: authHeader
|
|
12471
12774
|
}
|
|
12472
12775
|
});
|
|
12473
|
-
return readPayResult(retryResponse
|
|
12776
|
+
return readPayResult(retryResponse);
|
|
12474
12777
|
}
|
|
12475
12778
|
function MppPay({
|
|
12476
12779
|
url,
|
|
@@ -12518,9 +12821,10 @@ function MppPay({
|
|
|
12518
12821
|
headers: requestHeaders
|
|
12519
12822
|
});
|
|
12520
12823
|
if (initialResponse.status !== 402) {
|
|
12521
|
-
|
|
12824
|
+
const payResult2 = await readPayResult(initialResponse);
|
|
12825
|
+
setResult(payResult2);
|
|
12522
12826
|
setStep("done");
|
|
12523
|
-
onComplete();
|
|
12827
|
+
onComplete(payResult2);
|
|
12524
12828
|
return;
|
|
12525
12829
|
}
|
|
12526
12830
|
setStep("signing");
|
|
@@ -12536,12 +12840,13 @@ function MppPay({
|
|
|
12536
12840
|
Authorization: authHeader
|
|
12537
12841
|
}
|
|
12538
12842
|
});
|
|
12539
|
-
|
|
12843
|
+
const payResult = await readPayResult(retryResponse);
|
|
12844
|
+
setResult(payResult);
|
|
12540
12845
|
setStep("done");
|
|
12541
|
-
onComplete();
|
|
12846
|
+
onComplete(payResult);
|
|
12542
12847
|
} catch (err) {
|
|
12543
12848
|
setError(err.message);
|
|
12544
|
-
onComplete();
|
|
12849
|
+
onComplete(null);
|
|
12545
12850
|
}
|
|
12546
12851
|
})();
|
|
12547
12852
|
}, [url, spendRequestId, method, data, headers, repository, onComplete]);
|
|
@@ -12553,30 +12858,36 @@ function MppPay({
|
|
|
12553
12858
|
done: "Done"
|
|
12554
12859
|
};
|
|
12555
12860
|
if (error) {
|
|
12556
|
-
return /* @__PURE__ */
|
|
12861
|
+
return /* @__PURE__ */ jsxs6(Text7, { color: "red", children: [
|
|
12557
12862
|
"Error: ",
|
|
12558
12863
|
error
|
|
12559
12864
|
] });
|
|
12560
12865
|
}
|
|
12561
|
-
return /* @__PURE__ */
|
|
12562
|
-
step !== "done" && /* @__PURE__ */ jsx8(Box6, { children: /* @__PURE__ */
|
|
12563
|
-
/* @__PURE__ */ jsx8(
|
|
12866
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
12867
|
+
step !== "done" && /* @__PURE__ */ jsx8(Box6, { children: /* @__PURE__ */ jsxs6(Text7, { color: "cyan", children: [
|
|
12868
|
+
/* @__PURE__ */ jsx8(Spinner3, { type: "dots" }),
|
|
12564
12869
|
" ",
|
|
12565
12870
|
stepLabels[step],
|
|
12566
12871
|
"..."
|
|
12567
12872
|
] }) }),
|
|
12568
|
-
result && /* @__PURE__ */
|
|
12569
|
-
/* @__PURE__ */
|
|
12570
|
-
|
|
12571
|
-
|
|
12572
|
-
|
|
12873
|
+
result && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
12874
|
+
/* @__PURE__ */ jsxs6(
|
|
12875
|
+
Text7,
|
|
12876
|
+
{
|
|
12877
|
+
color: result.status >= 400 ? "red" : result.status >= 300 ? "yellow" : "green",
|
|
12878
|
+
children: [
|
|
12879
|
+
"HTTP ",
|
|
12880
|
+
result.status
|
|
12881
|
+
]
|
|
12882
|
+
}
|
|
12883
|
+
),
|
|
12573
12884
|
/* @__PURE__ */ jsx8(Text7, { children: result.body })
|
|
12574
12885
|
] })
|
|
12575
12886
|
] });
|
|
12576
12887
|
}
|
|
12577
12888
|
|
|
12578
12889
|
// src/commands/demo/spt-flow.tsx
|
|
12579
|
-
import { Fragment as Fragment2, jsx as jsx9, jsxs as
|
|
12890
|
+
import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
12580
12891
|
var SptFlow = ({
|
|
12581
12892
|
spendRequestRepo: spendRequestRepo2,
|
|
12582
12893
|
paymentMethodsResource,
|
|
@@ -12591,9 +12902,9 @@ var SptFlow = ({
|
|
|
12591
12902
|
const [payResult, setPayResult] = useState6(null);
|
|
12592
12903
|
const [error, setError] = useState6("");
|
|
12593
12904
|
const approvalUrl = spendRequest?.approval_url ?? "";
|
|
12594
|
-
const enterResolver =
|
|
12595
|
-
const pmResolver =
|
|
12596
|
-
const retryChoiceResolver =
|
|
12905
|
+
const enterResolver = useRef3(null);
|
|
12906
|
+
const pmResolver = useRef3(null);
|
|
12907
|
+
const retryChoiceResolver = useRef3(null);
|
|
12597
12908
|
function waitForEnter() {
|
|
12598
12909
|
return new Promise((resolve) => {
|
|
12599
12910
|
enterResolver.current = resolve;
|
|
@@ -12641,7 +12952,7 @@ var SptFlow = ({
|
|
|
12641
12952
|
}
|
|
12642
12953
|
}
|
|
12643
12954
|
});
|
|
12644
|
-
const started =
|
|
12955
|
+
const started = useRef3(false);
|
|
12645
12956
|
useEffect6(() => {
|
|
12646
12957
|
if (started.current) return;
|
|
12647
12958
|
started.current = true;
|
|
@@ -12701,6 +13012,11 @@ var SptFlow = ({
|
|
|
12701
13012
|
spendRequestRepo2,
|
|
12702
13013
|
result.id
|
|
12703
13014
|
);
|
|
13015
|
+
if (approved.status !== "approved") {
|
|
13016
|
+
throw new Error(
|
|
13017
|
+
`Spend request did not reach approved (status: ${approved.status})`
|
|
13018
|
+
);
|
|
13019
|
+
}
|
|
12704
13020
|
setSpendRequest(approved);
|
|
12705
13021
|
break;
|
|
12706
13022
|
} catch (err) {
|
|
@@ -12754,25 +13070,25 @@ var SptFlow = ({
|
|
|
12754
13070
|
];
|
|
12755
13071
|
return order.indexOf(step) > order.indexOf(target);
|
|
12756
13072
|
};
|
|
12757
|
-
const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */
|
|
13073
|
+
const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */ jsxs7(Text8, { dimColor: true, children: [
|
|
12758
13074
|
"\n",
|
|
12759
13075
|
">",
|
|
12760
13076
|
" ",
|
|
12761
13077
|
label
|
|
12762
13078
|
] });
|
|
12763
|
-
return /* @__PURE__ */
|
|
13079
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", gap: 1, children: [
|
|
12764
13080
|
/* @__PURE__ */ jsx9(Text8, { bold: true, color: "cyan", children: SPT_FLOW.title }),
|
|
12765
|
-
/* @__PURE__ */
|
|
12766
|
-
/* @__PURE__ */
|
|
13081
|
+
/* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
13082
|
+
/* @__PURE__ */ jsxs7(Box7, { flexDirection: "row", gap: 1, children: [
|
|
12767
13083
|
/* @__PURE__ */ jsx9(Text8, { color: "yellow", children: "[testmode]" }),
|
|
12768
|
-
/* @__PURE__ */
|
|
13084
|
+
/* @__PURE__ */ jsxs7(Text8, { dimColor: true, children: [
|
|
12769
13085
|
DEMO_CLIMATE_API_URL,
|
|
12770
13086
|
" ",
|
|
12771
13087
|
DEMO_MPP_DEV_URL
|
|
12772
13088
|
] })
|
|
12773
13089
|
] }),
|
|
12774
13090
|
/* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.intro.description }),
|
|
12775
|
-
/* @__PURE__ */
|
|
13091
|
+
/* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
12776
13092
|
/* @__PURE__ */ jsx9(Text8, { children: SPT_FLOW.intro.preamble }),
|
|
12777
13093
|
SPT_FLOW.intro.steps.map((s, i) => {
|
|
12778
13094
|
const doneAfter = [
|
|
@@ -12792,17 +13108,17 @@ var SptFlow = ({
|
|
|
12792
13108
|
const done = pastStep(doneAfter[i]);
|
|
12793
13109
|
const active = !done && (step === activeFrom[i] || pastStep(activeFrom[i]));
|
|
12794
13110
|
const label = s.replace(/`/g, "");
|
|
12795
|
-
return done ? /* @__PURE__ */
|
|
13111
|
+
return done ? /* @__PURE__ */ jsxs7(Text8, { dimColor: true, strikethrough: true, children: [
|
|
12796
13112
|
" ",
|
|
12797
13113
|
i + 1,
|
|
12798
13114
|
". ",
|
|
12799
13115
|
label
|
|
12800
|
-
] }, s) : active ? /* @__PURE__ */
|
|
13116
|
+
] }, s) : active ? /* @__PURE__ */ jsxs7(Text8, { bold: true, color: "cyan", children: [
|
|
12801
13117
|
" ",
|
|
12802
13118
|
i + 1,
|
|
12803
13119
|
". ",
|
|
12804
13120
|
label
|
|
12805
|
-
] }, s) : /* @__PURE__ */
|
|
13121
|
+
] }, s) : /* @__PURE__ */ jsxs7(Text8, { dimColor: true, children: [
|
|
12806
13122
|
" ",
|
|
12807
13123
|
i + 1,
|
|
12808
13124
|
". ",
|
|
@@ -12813,45 +13129,45 @@ var SptFlow = ({
|
|
|
12813
13129
|
step === "intro" && prompt(SPT_FLOW.intro.prompt)
|
|
12814
13130
|
] }),
|
|
12815
13131
|
step === "fetch-pm" && /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: "Fetching payment methods..." }) }),
|
|
12816
|
-
step === "pick-pm" && paymentMethods.length > 1 && /* @__PURE__ */
|
|
13132
|
+
step === "pick-pm" && paymentMethods.length > 1 && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
12817
13133
|
/* @__PURE__ */ jsx9(Text8, { children: "Which payment method should we use for the demo?" }),
|
|
12818
|
-
/* @__PURE__ */ jsx9(Box7, { flexDirection: "column", marginTop: 1, children: paymentMethods.map((pm, i) => /* @__PURE__ */ jsx9(Text8, { children: i === selectedPmIndex ? /* @__PURE__ */
|
|
13134
|
+
/* @__PURE__ */ jsx9(Box7, { flexDirection: "column", marginTop: 1, children: paymentMethods.map((pm, i) => /* @__PURE__ */ jsx9(Text8, { children: i === selectedPmIndex ? /* @__PURE__ */ jsxs7(Text8, { color: "cyan", bold: true, children: [
|
|
12819
13135
|
">",
|
|
12820
13136
|
" ",
|
|
12821
13137
|
pm.card_details ? `${pm.card_details.brand} ****${pm.card_details.last4}` : pm.type,
|
|
12822
13138
|
pm.is_default ? " (default)" : ""
|
|
12823
|
-
] }) : /* @__PURE__ */
|
|
13139
|
+
] }) : /* @__PURE__ */ jsxs7(Text8, { dimColor: true, children: [
|
|
12824
13140
|
" ",
|
|
12825
13141
|
pm.card_details ? `${pm.card_details.brand} ****${pm.card_details.last4}` : pm.type,
|
|
12826
13142
|
pm.is_default ? " (default)" : ""
|
|
12827
13143
|
] }) }, pm.id)) }),
|
|
12828
13144
|
/* @__PURE__ */ jsx9(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Use \u2191\u2193 to select, [Enter] to confirm" }) })
|
|
12829
13145
|
] }),
|
|
12830
|
-
(step === "probe" || step === "explain-402") && /* @__PURE__ */
|
|
13146
|
+
(step === "probe" || step === "explain-402") && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
12831
13147
|
/* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.probe.description }),
|
|
12832
13148
|
step === "probe" && /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: SPT_FLOW.probe.loading }) }),
|
|
12833
|
-
step === "explain-402" && networkId && /* @__PURE__ */
|
|
13149
|
+
step === "explain-402" && networkId && /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
12834
13150
|
/* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.probe.detail }),
|
|
12835
|
-
/* @__PURE__ */
|
|
13151
|
+
/* @__PURE__ */ jsxs7(Text8, { color: "green", children: [
|
|
12836
13152
|
"\u2713 Got HTTP 402 \u2014 network_id: ",
|
|
12837
13153
|
/* @__PURE__ */ jsx9(Text8, { bold: true, children: networkId })
|
|
12838
13154
|
] }),
|
|
12839
13155
|
prompt(SPT_FLOW.probe.prompt)
|
|
12840
13156
|
] })
|
|
12841
13157
|
] }),
|
|
12842
|
-
step === "create-spend" && /* @__PURE__ */
|
|
13158
|
+
step === "create-spend" && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
12843
13159
|
/* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.createSpend.description }),
|
|
12844
13160
|
/* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: SPT_FLOW.createSpend.loading }) })
|
|
12845
13161
|
] }),
|
|
12846
|
-
(step === "await-approval" || step === "approval-timeout") && spendRequest && /* @__PURE__ */
|
|
12847
|
-
/* @__PURE__ */
|
|
13162
|
+
(step === "await-approval" || step === "approval-timeout") && spendRequest && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
13163
|
+
/* @__PURE__ */ jsxs7(Text8, { color: "green", children: [
|
|
12848
13164
|
"\u2713 Spend request created (",
|
|
12849
13165
|
spendRequest.id,
|
|
12850
13166
|
")"
|
|
12851
13167
|
] }),
|
|
12852
|
-
step === "await-approval" && /* @__PURE__ */
|
|
13168
|
+
step === "await-approval" && /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
12853
13169
|
/* @__PURE__ */ jsx9(Text8, { children: SPT_FLOW.approval.description }),
|
|
12854
|
-
/* @__PURE__ */
|
|
13170
|
+
/* @__PURE__ */ jsxs7(
|
|
12855
13171
|
Box7,
|
|
12856
13172
|
{
|
|
12857
13173
|
flexDirection: "column",
|
|
@@ -12861,7 +13177,7 @@ var SptFlow = ({
|
|
|
12861
13177
|
paddingY: 1,
|
|
12862
13178
|
marginTop: 1,
|
|
12863
13179
|
children: [
|
|
12864
|
-
/* @__PURE__ */
|
|
13180
|
+
/* @__PURE__ */ jsxs7(Text8, { children: [
|
|
12865
13181
|
"Approve at:",
|
|
12866
13182
|
" ",
|
|
12867
13183
|
/* @__PURE__ */ jsx9(Text8, { bold: true, color: "cyan", children: approvalUrl })
|
|
@@ -12872,9 +13188,9 @@ var SptFlow = ({
|
|
|
12872
13188
|
),
|
|
12873
13189
|
/* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: SPT_FLOW.approval.loading }) })
|
|
12874
13190
|
] }),
|
|
12875
|
-
step === "approval-timeout" && /* @__PURE__ */
|
|
13191
|
+
step === "approval-timeout" && /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
12876
13192
|
/* @__PURE__ */ jsx9(Text8, { color: "yellow", children: "\u26A0 Approval timed out (5 min). Still pending \u2014 you can still approve." }),
|
|
12877
|
-
/* @__PURE__ */
|
|
13193
|
+
/* @__PURE__ */ jsxs7(
|
|
12878
13194
|
Box7,
|
|
12879
13195
|
{
|
|
12880
13196
|
flexDirection: "column",
|
|
@@ -12884,7 +13200,7 @@ var SptFlow = ({
|
|
|
12884
13200
|
paddingY: 1,
|
|
12885
13201
|
marginTop: 1,
|
|
12886
13202
|
children: [
|
|
12887
|
-
/* @__PURE__ */
|
|
13203
|
+
/* @__PURE__ */ jsxs7(Text8, { children: [
|
|
12888
13204
|
"Approve at:",
|
|
12889
13205
|
" ",
|
|
12890
13206
|
/* @__PURE__ */ jsx9(Text8, { bold: true, color: "cyan", children: approvalUrl })
|
|
@@ -12896,14 +13212,14 @@ var SptFlow = ({
|
|
|
12896
13212
|
/* @__PURE__ */ jsx9(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "r Retry polling q Quit demo" }) })
|
|
12897
13213
|
] })
|
|
12898
13214
|
] }),
|
|
12899
|
-
(step === "mpp-pay-gate" || step === "mpp-pay") && /* @__PURE__ */
|
|
13215
|
+
(step === "mpp-pay-gate" || step === "mpp-pay") && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
12900
13216
|
/* @__PURE__ */ jsx9(Text8, { color: "green", children: "\u2713 Approved!" }),
|
|
12901
13217
|
/* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.mppPay.description }),
|
|
12902
13218
|
step === "mpp-pay-gate" && prompt(SPT_FLOW.mppPay.prompt),
|
|
12903
13219
|
step === "mpp-pay" && /* @__PURE__ */ jsx9(Box7, { marginY: 1, children: /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: SPT_FLOW.mppPay.loading }) })
|
|
12904
13220
|
] }),
|
|
12905
|
-
step === "done" && payResult && /* @__PURE__ */
|
|
12906
|
-
/* @__PURE__ */
|
|
13221
|
+
step === "done" && payResult && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
13222
|
+
/* @__PURE__ */ jsxs7(Text8, { bold: true, color: "green", children: [
|
|
12907
13223
|
"\u2713 ",
|
|
12908
13224
|
SPT_FLOW.done.success,
|
|
12909
13225
|
" (HTTP ",
|
|
@@ -12912,7 +13228,7 @@ var SptFlow = ({
|
|
|
12912
13228
|
] }),
|
|
12913
13229
|
/* @__PURE__ */ jsx9(MarkdownText, { children: SPT_FLOW.done.detail })
|
|
12914
13230
|
] }),
|
|
12915
|
-
step === "error" && /* @__PURE__ */
|
|
13231
|
+
step === "error" && /* @__PURE__ */ jsxs7(Text8, { color: "red", children: [
|
|
12916
13232
|
"Error: ",
|
|
12917
13233
|
error
|
|
12918
13234
|
] })
|
|
@@ -12920,22 +13236,25 @@ var SptFlow = ({
|
|
|
12920
13236
|
};
|
|
12921
13237
|
|
|
12922
13238
|
// src/commands/demo/demo-runner.tsx
|
|
12923
|
-
import { Fragment as Fragment3, jsx as jsx10, jsxs as
|
|
13239
|
+
import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
12924
13240
|
var DemoRunner = ({
|
|
12925
13241
|
authRepo: authRepo2,
|
|
12926
13242
|
spendRequestRepo: spendRequestRepo2,
|
|
12927
13243
|
paymentMethodsResource,
|
|
13244
|
+
authStorage: authStorage2 = storage,
|
|
12928
13245
|
paymentMethodId: preselectedPmId,
|
|
12929
13246
|
onlyCard,
|
|
12930
13247
|
onlySpt,
|
|
12931
13248
|
onComplete
|
|
12932
13249
|
}) => {
|
|
13250
|
+
const { exit } = useApp();
|
|
13251
|
+
const storage2 = authStorage2;
|
|
12933
13252
|
const preselected = onlyCard ? "card" : onlySpt ? "spt" : null;
|
|
12934
13253
|
const [choice, setChoice] = useState7(preselected);
|
|
12935
13254
|
const [menuIndex, setMenuIndex] = useState7(0);
|
|
12936
13255
|
const postAuthPhase = preselected === "spt" ? "spt-flow" : preselected ? "card-flow" : "menu";
|
|
12937
13256
|
const [phase, setPhase] = useState7(
|
|
12938
|
-
|
|
13257
|
+
storage2.isAuthenticated() ? postAuthPhase : "auth"
|
|
12939
13258
|
);
|
|
12940
13259
|
const [paymentMethodId, setPaymentMethodId] = useState7(
|
|
12941
13260
|
preselectedPmId ?? ""
|
|
@@ -12959,29 +13278,35 @@ var DemoRunner = ({
|
|
|
12959
13278
|
setPhase("spt-flow");
|
|
12960
13279
|
}
|
|
12961
13280
|
});
|
|
12962
|
-
const onCardComplete =
|
|
13281
|
+
const onCardComplete = useCallback2(
|
|
12963
13282
|
(result) => {
|
|
12964
13283
|
setPaymentMethodId(result.paymentMethodId);
|
|
12965
13284
|
setCardSuccess(result.success);
|
|
12966
13285
|
if (!runSpt) {
|
|
12967
13286
|
setPhase("summary");
|
|
12968
|
-
setTimeout(
|
|
13287
|
+
setTimeout(() => {
|
|
13288
|
+
onComplete();
|
|
13289
|
+
exit();
|
|
13290
|
+
}, DISPLAY_DELAY_MS);
|
|
12969
13291
|
} else {
|
|
12970
13292
|
setPhase("card-done");
|
|
12971
13293
|
}
|
|
12972
13294
|
},
|
|
12973
|
-
[runSpt, onComplete]
|
|
13295
|
+
[runSpt, onComplete, exit]
|
|
12974
13296
|
);
|
|
12975
|
-
const onSptComplete =
|
|
13297
|
+
const onSptComplete = useCallback2(
|
|
12976
13298
|
(success) => {
|
|
12977
13299
|
setSptSuccess(success);
|
|
12978
13300
|
setPhase("summary");
|
|
12979
|
-
setTimeout(
|
|
13301
|
+
setTimeout(() => {
|
|
13302
|
+
onComplete();
|
|
13303
|
+
exit();
|
|
13304
|
+
}, DISPLAY_DELAY_MS);
|
|
12980
13305
|
},
|
|
12981
|
-
[onComplete]
|
|
13306
|
+
[onComplete, exit]
|
|
12982
13307
|
);
|
|
12983
|
-
return /* @__PURE__ */
|
|
12984
|
-
/* @__PURE__ */
|
|
13308
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", gap: 1, children: [
|
|
13309
|
+
/* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
12985
13310
|
/* @__PURE__ */ jsx10(Text9, { bold: true, children: DEMO_MENU.title }),
|
|
12986
13311
|
/* @__PURE__ */ jsx10(Text9, { children: DEMO_MENU.subtitle })
|
|
12987
13312
|
] }),
|
|
@@ -12990,22 +13315,23 @@ var DemoRunner = ({
|
|
|
12990
13315
|
{
|
|
12991
13316
|
authResource: authRepo2,
|
|
12992
13317
|
clientName: ONBOARD.auth.clientName,
|
|
13318
|
+
authStorage: storage2,
|
|
12993
13319
|
onComplete: () => setPhase(postAuthPhase)
|
|
12994
13320
|
}
|
|
12995
13321
|
),
|
|
12996
|
-
phase === "menu" && /* @__PURE__ */
|
|
13322
|
+
phase === "menu" && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
12997
13323
|
/* @__PURE__ */ jsx10(Text9, { children: DEMO_MENU.question }),
|
|
12998
|
-
/* @__PURE__ */ jsx10(Box8, { flexDirection: "column", marginTop: 1, gap: 1, children: DEMO_MENU.options.map((opt, i) => /* @__PURE__ */ jsx10(Box8, { flexDirection: "column", children: i === menuIndex ? /* @__PURE__ */
|
|
12999
|
-
/* @__PURE__ */
|
|
13324
|
+
/* @__PURE__ */ jsx10(Box8, { flexDirection: "column", marginTop: 1, gap: 1, children: DEMO_MENU.options.map((opt, i) => /* @__PURE__ */ jsx10(Box8, { flexDirection: "column", children: i === menuIndex ? /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
13325
|
+
/* @__PURE__ */ jsxs8(Text9, { color: "cyan", bold: true, children: [
|
|
13000
13326
|
">",
|
|
13001
13327
|
" ",
|
|
13002
13328
|
opt.label
|
|
13003
13329
|
] }),
|
|
13004
|
-
/* @__PURE__ */
|
|
13330
|
+
/* @__PURE__ */ jsxs8(Text9, { color: "cyan", children: [
|
|
13005
13331
|
" ",
|
|
13006
13332
|
opt.description
|
|
13007
13333
|
] })
|
|
13008
|
-
] }) : /* @__PURE__ */
|
|
13334
|
+
] }) : /* @__PURE__ */ jsxs8(Text9, { dimColor: true, children: [
|
|
13009
13335
|
" ",
|
|
13010
13336
|
opt.label
|
|
13011
13337
|
] }) }, opt.key)) }),
|
|
@@ -13020,17 +13346,17 @@ var DemoRunner = ({
|
|
|
13020
13346
|
onComplete: onCardComplete
|
|
13021
13347
|
}
|
|
13022
13348
|
),
|
|
13023
|
-
phase === "card-done" && /* @__PURE__ */
|
|
13349
|
+
phase === "card-done" && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
13024
13350
|
/* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u2500\u2500\u2500" }),
|
|
13025
13351
|
/* @__PURE__ */ jsx10(MarkdownText, { children: DEMO_MENU.transition }),
|
|
13026
|
-
/* @__PURE__ */
|
|
13352
|
+
/* @__PURE__ */ jsxs8(Text9, { dimColor: true, children: [
|
|
13027
13353
|
"\n",
|
|
13028
13354
|
">",
|
|
13029
13355
|
" ",
|
|
13030
13356
|
DEMO_MENU.transitionPrompt
|
|
13031
13357
|
] })
|
|
13032
13358
|
] }),
|
|
13033
|
-
runSpt && (phase === "spt-flow" || phase === "summary") && /* @__PURE__ */
|
|
13359
|
+
runSpt && (phase === "spt-flow" || phase === "summary") && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
13034
13360
|
runCard && /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u2500\u2500\u2500" }),
|
|
13035
13361
|
/* @__PURE__ */ jsx10(
|
|
13036
13362
|
SptFlow,
|
|
@@ -13042,14 +13368,14 @@ var DemoRunner = ({
|
|
|
13042
13368
|
}
|
|
13043
13369
|
)
|
|
13044
13370
|
] }),
|
|
13045
|
-
phase === "summary" && /* @__PURE__ */
|
|
13371
|
+
phase === "summary" && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
13046
13372
|
/* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u2500\u2500\u2500" }),
|
|
13047
13373
|
/* @__PURE__ */ jsx10(Text9, { bold: true, children: "Done!" }),
|
|
13048
|
-
cardSuccess !== null && /* @__PURE__ */
|
|
13374
|
+
cardSuccess !== null && /* @__PURE__ */ jsxs8(Text9, { color: cardSuccess ? "green" : "red", children: [
|
|
13049
13375
|
cardSuccess ? "\u2713" : "\u2717",
|
|
13050
13376
|
" Virtual card flow"
|
|
13051
13377
|
] }),
|
|
13052
|
-
sptSuccess !== null && /* @__PURE__ */
|
|
13378
|
+
sptSuccess !== null && /* @__PURE__ */ jsxs8(Text9, { color: sptSuccess ? "green" : "red", children: [
|
|
13053
13379
|
sptSuccess ? "\u2713" : "\u2717",
|
|
13054
13380
|
" Machine payment flow"
|
|
13055
13381
|
] }),
|
|
@@ -13064,7 +13390,7 @@ var demoOptions = z2.object({
|
|
|
13064
13390
|
onlyCard: z2.boolean().default(false).describe("Run only the virtual card flow"),
|
|
13065
13391
|
onlySpt: z2.boolean().default(false).describe("Run only the machine payment (SPT) flow")
|
|
13066
13392
|
});
|
|
13067
|
-
function createDemoCli(authRepo2, spendRequestRepo2, createPaymentMethodsResource) {
|
|
13393
|
+
function createDemoCli(authRepo2, spendRequestRepo2, createPaymentMethodsResource, authStorage2) {
|
|
13068
13394
|
return Cli2.create("demo", {
|
|
13069
13395
|
description: "Run an interactive demo of both Link payment flows (virtual card + machine payment)",
|
|
13070
13396
|
options: demoOptions,
|
|
@@ -13077,48 +13403,71 @@ function createDemoCli(authRepo2, spendRequestRepo2, createPaymentMethodsResourc
|
|
|
13077
13403
|
});
|
|
13078
13404
|
}
|
|
13079
13405
|
const paymentMethodsResource = createPaymentMethodsResource();
|
|
13080
|
-
return
|
|
13081
|
-
|
|
13082
|
-
|
|
13083
|
-
|
|
13084
|
-
|
|
13085
|
-
|
|
13086
|
-
|
|
13087
|
-
|
|
13088
|
-
|
|
13089
|
-
|
|
13090
|
-
|
|
13406
|
+
return renderInteractive(
|
|
13407
|
+
/* @__PURE__ */ jsx11(
|
|
13408
|
+
DemoRunner,
|
|
13409
|
+
{
|
|
13410
|
+
authRepo: authRepo2,
|
|
13411
|
+
spendRequestRepo: spendRequestRepo2,
|
|
13412
|
+
paymentMethodsResource,
|
|
13413
|
+
authStorage: authStorage2,
|
|
13414
|
+
onlyCard: c.options.onlyCard,
|
|
13415
|
+
onlySpt: c.options.onlySpt,
|
|
13416
|
+
onComplete: () => {
|
|
13091
13417
|
}
|
|
13092
|
-
|
|
13093
|
-
)
|
|
13094
|
-
|
|
13095
|
-
|
|
13418
|
+
}
|
|
13419
|
+
),
|
|
13420
|
+
() => ({})
|
|
13421
|
+
);
|
|
13096
13422
|
}
|
|
13097
13423
|
});
|
|
13098
13424
|
}
|
|
13099
13425
|
|
|
13100
13426
|
// src/commands/mpp/index.tsx
|
|
13101
13427
|
import { Cli as Cli3, z as z4 } from "incur";
|
|
13102
|
-
|
|
13428
|
+
|
|
13429
|
+
// src/utils/require-auth.ts
|
|
13430
|
+
var NOT_AUTHENTICATED_ERROR = {
|
|
13431
|
+
code: "NOT_AUTHENTICATED",
|
|
13432
|
+
message: 'Not authenticated. Run "link-cli auth login" first.',
|
|
13433
|
+
cta: {
|
|
13434
|
+
commands: [{ command: "auth login", description: "Log in to Link" }]
|
|
13435
|
+
}
|
|
13436
|
+
};
|
|
13437
|
+
function requireAuth(authStorage2) {
|
|
13438
|
+
const store = authStorage2 ?? storage;
|
|
13439
|
+
return (c, next) => {
|
|
13440
|
+
if (!store.isAuthenticated()) {
|
|
13441
|
+
return c.error(NOT_AUTHENTICATED_ERROR);
|
|
13442
|
+
}
|
|
13443
|
+
return next();
|
|
13444
|
+
};
|
|
13445
|
+
}
|
|
13446
|
+
function requireAuthGuard(c, authStorage2) {
|
|
13447
|
+
const store = authStorage2 ?? storage;
|
|
13448
|
+
if (!store.isAuthenticated()) {
|
|
13449
|
+
c.error(NOT_AUTHENTICATED_ERROR);
|
|
13450
|
+
}
|
|
13451
|
+
}
|
|
13103
13452
|
|
|
13104
13453
|
// src/commands/mpp/decode-view.tsx
|
|
13105
13454
|
import { Box as Box9, Text as Text10 } from "ink";
|
|
13106
|
-
import { jsx as jsx12, jsxs as
|
|
13455
|
+
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
13107
13456
|
function DecodeChallengeView({
|
|
13108
13457
|
decoded
|
|
13109
13458
|
}) {
|
|
13110
|
-
return /* @__PURE__ */
|
|
13459
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
|
|
13111
13460
|
/* @__PURE__ */ jsx12(Text10, { color: "green", children: "\u2713 Stripe challenge decoded" }),
|
|
13112
|
-
/* @__PURE__ */
|
|
13113
|
-
/* @__PURE__ */
|
|
13461
|
+
/* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
|
|
13462
|
+
/* @__PURE__ */ jsxs9(Text10, { children: [
|
|
13114
13463
|
"ID: ",
|
|
13115
13464
|
/* @__PURE__ */ jsx12(Text10, { bold: true, children: decoded.id })
|
|
13116
13465
|
] }),
|
|
13117
|
-
/* @__PURE__ */
|
|
13466
|
+
/* @__PURE__ */ jsxs9(Text10, { children: [
|
|
13118
13467
|
"Realm: ",
|
|
13119
13468
|
/* @__PURE__ */ jsx12(Text10, { bold: true, children: decoded.realm })
|
|
13120
13469
|
] }),
|
|
13121
|
-
/* @__PURE__ */
|
|
13470
|
+
/* @__PURE__ */ jsxs9(Text10, { children: [
|
|
13122
13471
|
"Network ID: ",
|
|
13123
13472
|
/* @__PURE__ */ jsx12(Text10, { bold: true, children: decoded.network_id })
|
|
13124
13473
|
] }),
|
|
@@ -13146,7 +13495,7 @@ var decodeOptions = z3.object({
|
|
|
13146
13495
|
|
|
13147
13496
|
// src/commands/mpp/index.tsx
|
|
13148
13497
|
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
13149
|
-
function createMppCli(repository) {
|
|
13498
|
+
function createMppCli(repository, authStorage2) {
|
|
13150
13499
|
const cli2 = Cli3.create("mpp", {
|
|
13151
13500
|
description: "Machine payment protocol (MPP) commands"
|
|
13152
13501
|
});
|
|
@@ -13158,53 +13507,36 @@ function createMppCli(repository) {
|
|
|
13158
13507
|
options: payOptions,
|
|
13159
13508
|
alias: { method: "X", data: "d", header: "H" },
|
|
13160
13509
|
outputPolicy: "agent-only",
|
|
13510
|
+
middleware: [requireAuth(authStorage2)],
|
|
13161
13511
|
async run(c) {
|
|
13162
|
-
if (!storage.isAuthenticated()) {
|
|
13163
|
-
return c.error({
|
|
13164
|
-
code: "NOT_AUTHENTICATED",
|
|
13165
|
-
message: 'Not authenticated. Run "link-cli auth login" first.',
|
|
13166
|
-
cta: {
|
|
13167
|
-
commands: [
|
|
13168
|
-
{ command: "auth login", description: "Log in to Link" }
|
|
13169
|
-
]
|
|
13170
|
-
}
|
|
13171
|
-
});
|
|
13172
|
-
}
|
|
13173
13512
|
const url = c.args.url;
|
|
13174
13513
|
const opts = c.options;
|
|
13175
13514
|
const method = opts.method;
|
|
13176
13515
|
const data = opts.data;
|
|
13177
13516
|
const headers = opts.header?.length ? opts.header : void 0;
|
|
13178
13517
|
if (!c.agent && !c.formatExplicit) {
|
|
13179
|
-
|
|
13180
|
-
|
|
13181
|
-
|
|
13182
|
-
|
|
13183
|
-
|
|
13184
|
-
|
|
13185
|
-
|
|
13186
|
-
|
|
13187
|
-
|
|
13188
|
-
|
|
13189
|
-
|
|
13190
|
-
|
|
13191
|
-
|
|
13518
|
+
let capturedResult = null;
|
|
13519
|
+
return renderInteractive(
|
|
13520
|
+
/* @__PURE__ */ jsx13(
|
|
13521
|
+
MppPay,
|
|
13522
|
+
{
|
|
13523
|
+
url,
|
|
13524
|
+
spendRequestId: opts.spendRequestId,
|
|
13525
|
+
method,
|
|
13526
|
+
data,
|
|
13527
|
+
headers,
|
|
13528
|
+
repository,
|
|
13529
|
+
onComplete: (result) => {
|
|
13530
|
+
capturedResult = result;
|
|
13192
13531
|
}
|
|
13193
|
-
|
|
13194
|
-
)
|
|
13195
|
-
|
|
13196
|
-
|
|
13197
|
-
|
|
13198
|
-
|
|
13199
|
-
|
|
13200
|
-
|
|
13201
|
-
data,
|
|
13202
|
-
headers,
|
|
13203
|
-
repository
|
|
13204
|
-
)
|
|
13205
|
-
);
|
|
13206
|
-
});
|
|
13207
|
-
});
|
|
13532
|
+
}
|
|
13533
|
+
),
|
|
13534
|
+
() => {
|
|
13535
|
+
if (!capturedResult)
|
|
13536
|
+
throw new Error("Component exited without producing a result");
|
|
13537
|
+
return capturedResult;
|
|
13538
|
+
}
|
|
13539
|
+
);
|
|
13208
13540
|
}
|
|
13209
13541
|
return runMppPay(
|
|
13210
13542
|
url,
|
|
@@ -13223,12 +13555,10 @@ function createMppCli(repository) {
|
|
|
13223
13555
|
async run(c) {
|
|
13224
13556
|
const decoded = decodeStripeChallenge(c.options.challenge);
|
|
13225
13557
|
if (!c.agent && !c.formatExplicit) {
|
|
13226
|
-
return
|
|
13227
|
-
|
|
13228
|
-
|
|
13229
|
-
|
|
13230
|
-
waitUntilExit().then(() => resolve(decoded));
|
|
13231
|
-
});
|
|
13558
|
+
return renderInteractive(
|
|
13559
|
+
/* @__PURE__ */ jsx13(DecodeChallengeView, { decoded }),
|
|
13560
|
+
() => decoded
|
|
13561
|
+
);
|
|
13232
13562
|
}
|
|
13233
13563
|
return decoded;
|
|
13234
13564
|
}
|
|
@@ -13238,29 +13568,31 @@ function createMppCli(repository) {
|
|
|
13238
13568
|
|
|
13239
13569
|
// src/commands/onboard/index.tsx
|
|
13240
13570
|
import { Cli as Cli4 } from "incur";
|
|
13241
|
-
import { render as render4 } from "ink";
|
|
13242
13571
|
|
|
13243
13572
|
// src/commands/onboard/onboard-runner.tsx
|
|
13244
|
-
import { Box as Box10, Text as Text11, useInput as useInput5 } from "ink";
|
|
13245
|
-
import { useEffect as useEffect7, useRef as
|
|
13246
|
-
import { jsx as jsx14, jsxs as
|
|
13573
|
+
import { Box as Box10, Text as Text11, useApp as useApp2, useInput as useInput5 } from "ink";
|
|
13574
|
+
import { useEffect as useEffect7, useRef as useRef4, useState as useState8 } from "react";
|
|
13575
|
+
import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
13247
13576
|
var OnboardRunner = ({
|
|
13248
13577
|
authRepo: authRepo2,
|
|
13249
13578
|
spendRequestRepo: spendRequestRepo2,
|
|
13250
13579
|
paymentMethodsResource,
|
|
13580
|
+
authStorage: authStorage2 = storage,
|
|
13251
13581
|
onComplete
|
|
13252
13582
|
}) => {
|
|
13583
|
+
const { exit } = useApp2();
|
|
13584
|
+
const storage2 = authStorage2;
|
|
13253
13585
|
const [phase, setPhase] = useState8("welcome");
|
|
13254
13586
|
const [authSkipped, setAuthSkipped] = useState8(false);
|
|
13255
13587
|
const [pmMissing, setPmMissing] = useState8(false);
|
|
13256
13588
|
const [error, setError] = useState8("");
|
|
13257
|
-
const enterResolver =
|
|
13589
|
+
const enterResolver = useRef4(null);
|
|
13258
13590
|
function waitForEnter() {
|
|
13259
13591
|
return new Promise((resolve) => {
|
|
13260
13592
|
enterResolver.current = resolve;
|
|
13261
13593
|
});
|
|
13262
13594
|
}
|
|
13263
|
-
const authResolver =
|
|
13595
|
+
const authResolver = useRef4(null);
|
|
13264
13596
|
function waitForAuth() {
|
|
13265
13597
|
return new Promise((resolve) => {
|
|
13266
13598
|
authResolver.current = resolve;
|
|
@@ -13273,14 +13605,14 @@ var OnboardRunner = ({
|
|
|
13273
13605
|
resolve();
|
|
13274
13606
|
}
|
|
13275
13607
|
});
|
|
13276
|
-
const started =
|
|
13608
|
+
const started = useRef4(false);
|
|
13277
13609
|
useEffect7(() => {
|
|
13278
13610
|
if (started.current) return;
|
|
13279
13611
|
started.current = true;
|
|
13280
13612
|
const run = async () => {
|
|
13281
13613
|
try {
|
|
13282
13614
|
setPhase("auth");
|
|
13283
|
-
if (
|
|
13615
|
+
if (storage2.isAuthenticated()) {
|
|
13284
13616
|
setAuthSkipped(true);
|
|
13285
13617
|
} else {
|
|
13286
13618
|
setAuthSkipped(false);
|
|
@@ -13297,6 +13629,7 @@ var OnboardRunner = ({
|
|
|
13297
13629
|
setPhase("demo");
|
|
13298
13630
|
} catch (err) {
|
|
13299
13631
|
setError(err.message);
|
|
13632
|
+
setTimeout(exit, 2e3);
|
|
13300
13633
|
}
|
|
13301
13634
|
};
|
|
13302
13635
|
run();
|
|
@@ -13305,33 +13638,34 @@ var OnboardRunner = ({
|
|
|
13305
13638
|
const order = ["welcome", "auth", "payment-methods", "demo"];
|
|
13306
13639
|
return order.indexOf(phase) > order.indexOf(target);
|
|
13307
13640
|
};
|
|
13308
|
-
const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */
|
|
13641
|
+
const prompt = (label = "Press [Enter] to continue") => /* @__PURE__ */ jsxs10(Text11, { dimColor: true, children: [
|
|
13309
13642
|
"\n",
|
|
13310
13643
|
">",
|
|
13311
13644
|
" ",
|
|
13312
13645
|
label
|
|
13313
13646
|
] });
|
|
13314
|
-
return /* @__PURE__ */
|
|
13315
|
-
/* @__PURE__ */
|
|
13647
|
+
return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", gap: 1, children: [
|
|
13648
|
+
/* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
|
|
13316
13649
|
/* @__PURE__ */ jsx14(Text11, { bold: true, children: ONBOARD.title }),
|
|
13317
13650
|
/* @__PURE__ */ jsx14(Text11, { children: ONBOARD.subtitle })
|
|
13318
13651
|
] }),
|
|
13319
|
-
/* @__PURE__ */ jsx14(Box10, { flexDirection: "column", children: authSkipped || pastPhase("auth") ? /* @__PURE__ */
|
|
13652
|
+
/* @__PURE__ */ jsx14(Box10, { flexDirection: "column", children: authSkipped || pastPhase("auth") ? /* @__PURE__ */ jsxs10(Text11, { color: "green", children: [
|
|
13320
13653
|
"\u2713 ",
|
|
13321
13654
|
authSkipped ? ONBOARD.auth.alreadyLoggedIn : ONBOARD.auth.authenticated
|
|
13322
|
-
] }) : phase === "auth" && !
|
|
13655
|
+
] }) : phase === "auth" && !storage2.isAuthenticated() ? /* @__PURE__ */ jsx14(
|
|
13323
13656
|
Login,
|
|
13324
13657
|
{
|
|
13325
13658
|
authResource: authRepo2,
|
|
13326
13659
|
clientName: ONBOARD.auth.clientName,
|
|
13660
|
+
authStorage: storage2,
|
|
13327
13661
|
onComplete: () => authResolver.current?.()
|
|
13328
13662
|
}
|
|
13329
13663
|
) : null }),
|
|
13330
|
-
pastPhase("auth") && /* @__PURE__ */
|
|
13664
|
+
pastPhase("auth") && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
|
|
13331
13665
|
phase === "payment-methods" && !pmMissing && /* @__PURE__ */ jsx14(Text11, { color: "cyan", children: ONBOARD.paymentMethods.loading }),
|
|
13332
|
-
pmMissing && /* @__PURE__ */
|
|
13666
|
+
pmMissing && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
|
|
13333
13667
|
/* @__PURE__ */ jsx14(Text11, { color: "yellow", children: ONBOARD.paymentMethods.missing }),
|
|
13334
|
-
/* @__PURE__ */ jsx14(Box10, { marginTop: 1, children: /* @__PURE__ */
|
|
13668
|
+
/* @__PURE__ */ jsx14(Box10, { marginTop: 1, children: /* @__PURE__ */ jsxs10(Text11, { children: [
|
|
13335
13669
|
"Visit",
|
|
13336
13670
|
" ",
|
|
13337
13671
|
/* @__PURE__ */ jsx14(Text11, { bold: true, color: "cyan", children: "app.link.com/wallet" }),
|
|
@@ -13342,7 +13676,7 @@ var OnboardRunner = ({
|
|
|
13342
13676
|
] }),
|
|
13343
13677
|
pastPhase("payment-methods") && /* @__PURE__ */ jsx14(Text11, { color: "green", children: "\u2713 Payment method found" })
|
|
13344
13678
|
] }),
|
|
13345
|
-
phase === "demo" && /* @__PURE__ */
|
|
13679
|
+
phase === "demo" && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
|
|
13346
13680
|
/* @__PURE__ */ jsx14(Text11, { dimColor: true, children: "\u2500\u2500\u2500" }),
|
|
13347
13681
|
/* @__PURE__ */ jsx14(
|
|
13348
13682
|
DemoRunner,
|
|
@@ -13350,11 +13684,12 @@ var OnboardRunner = ({
|
|
|
13350
13684
|
authRepo: authRepo2,
|
|
13351
13685
|
spendRequestRepo: spendRequestRepo2,
|
|
13352
13686
|
paymentMethodsResource,
|
|
13687
|
+
authStorage: storage2,
|
|
13353
13688
|
onComplete
|
|
13354
13689
|
}
|
|
13355
13690
|
)
|
|
13356
13691
|
] }),
|
|
13357
|
-
error && /* @__PURE__ */
|
|
13692
|
+
error && /* @__PURE__ */ jsxs10(Text11, { color: "red", children: [
|
|
13358
13693
|
"Error: ",
|
|
13359
13694
|
error
|
|
13360
13695
|
] })
|
|
@@ -13363,7 +13698,7 @@ var OnboardRunner = ({
|
|
|
13363
13698
|
|
|
13364
13699
|
// src/commands/onboard/index.tsx
|
|
13365
13700
|
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
13366
|
-
function createOnboardCli(authRepo2, spendRequestRepo2, createPaymentMethodsResource) {
|
|
13701
|
+
function createOnboardCli(authRepo2, spendRequestRepo2, createPaymentMethodsResource, authStorage2) {
|
|
13367
13702
|
return Cli4.create("onboard", {
|
|
13368
13703
|
description: "Guided setup: authenticate, verify payment methods, and demo both payment flows",
|
|
13369
13704
|
outputPolicy: "agent-only",
|
|
@@ -13375,43 +13710,42 @@ function createOnboardCli(authRepo2, spendRequestRepo2, createPaymentMethodsReso
|
|
|
13375
13710
|
});
|
|
13376
13711
|
}
|
|
13377
13712
|
const paymentMethodsResource = createPaymentMethodsResource();
|
|
13378
|
-
return
|
|
13379
|
-
|
|
13380
|
-
|
|
13381
|
-
|
|
13382
|
-
|
|
13383
|
-
|
|
13384
|
-
|
|
13385
|
-
|
|
13386
|
-
|
|
13713
|
+
return renderInteractive(
|
|
13714
|
+
/* @__PURE__ */ jsx15(
|
|
13715
|
+
OnboardRunner,
|
|
13716
|
+
{
|
|
13717
|
+
authRepo: authRepo2,
|
|
13718
|
+
spendRequestRepo: spendRequestRepo2,
|
|
13719
|
+
paymentMethodsResource,
|
|
13720
|
+
authStorage: authStorage2,
|
|
13721
|
+
onComplete: () => {
|
|
13387
13722
|
}
|
|
13388
|
-
|
|
13389
|
-
)
|
|
13390
|
-
|
|
13391
|
-
|
|
13723
|
+
}
|
|
13724
|
+
),
|
|
13725
|
+
() => ({})
|
|
13726
|
+
);
|
|
13392
13727
|
}
|
|
13393
13728
|
});
|
|
13394
13729
|
}
|
|
13395
13730
|
|
|
13396
13731
|
// src/commands/payment-methods/index.tsx
|
|
13397
13732
|
import { Cli as Cli5 } from "incur";
|
|
13398
|
-
import { render as render5 } from "ink";
|
|
13399
13733
|
|
|
13400
13734
|
// src/commands/payment-methods/add.tsx
|
|
13401
|
-
import { Box as Box11, Text as Text12, useApp, useInput as useInput6 } from "ink";
|
|
13402
|
-
import { jsx as jsx16, jsxs as
|
|
13735
|
+
import { Box as Box11, Text as Text12, useApp as useApp3, useInput as useInput6 } from "ink";
|
|
13736
|
+
import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
13403
13737
|
var WALLET_URL = "https://app.link.com/wallet";
|
|
13404
13738
|
var AddPaymentMethod = () => {
|
|
13405
|
-
const { exit } =
|
|
13739
|
+
const { exit } = useApp3();
|
|
13406
13740
|
useInput6((_input, key) => {
|
|
13407
13741
|
if (key.return) {
|
|
13408
13742
|
openUrl(WALLET_URL);
|
|
13409
13743
|
exit();
|
|
13410
13744
|
}
|
|
13411
13745
|
});
|
|
13412
|
-
return /* @__PURE__ */
|
|
13746
|
+
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingY: 1, children: [
|
|
13413
13747
|
/* @__PURE__ */ jsx16(Box11, { marginBottom: 1, children: /* @__PURE__ */ jsx16(Text12, { bold: true, children: "Add Payment Method" }) }),
|
|
13414
|
-
/* @__PURE__ */
|
|
13748
|
+
/* @__PURE__ */ jsxs11(
|
|
13415
13749
|
Box11,
|
|
13416
13750
|
{
|
|
13417
13751
|
flexDirection: "column",
|
|
@@ -13420,7 +13754,7 @@ var AddPaymentMethod = () => {
|
|
|
13420
13754
|
paddingX: 2,
|
|
13421
13755
|
paddingY: 1,
|
|
13422
13756
|
children: [
|
|
13423
|
-
/* @__PURE__ */
|
|
13757
|
+
/* @__PURE__ */ jsxs11(Text12, { children: [
|
|
13424
13758
|
"Open:",
|
|
13425
13759
|
" ",
|
|
13426
13760
|
/* @__PURE__ */ jsx16(Text12, { bold: true, color: "cyan", children: WALLET_URL })
|
|
@@ -13434,55 +13768,37 @@ var AddPaymentMethod = () => {
|
|
|
13434
13768
|
|
|
13435
13769
|
// src/commands/payment-methods/list.tsx
|
|
13436
13770
|
import { Box as Box12, Text as Text13 } from "ink";
|
|
13437
|
-
import
|
|
13438
|
-
import {
|
|
13439
|
-
import { jsx as jsx17, jsxs as
|
|
13771
|
+
import Spinner4 from "ink-spinner";
|
|
13772
|
+
import { useCallback as useCallback3 } from "react";
|
|
13773
|
+
import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
13440
13774
|
var PaymentMethodsList = ({
|
|
13441
13775
|
resource,
|
|
13442
13776
|
onComplete
|
|
13443
13777
|
}) => {
|
|
13444
|
-
const
|
|
13445
|
-
|
|
13446
|
-
);
|
|
13447
|
-
const [methods, setMethods] = useState9([]);
|
|
13448
|
-
const [error, setError] = useState9("");
|
|
13449
|
-
useEffect8(() => {
|
|
13450
|
-
const fetch2 = async () => {
|
|
13451
|
-
try {
|
|
13452
|
-
const result = await resource.listPaymentMethods();
|
|
13453
|
-
setMethods(result);
|
|
13454
|
-
setStatus("success");
|
|
13455
|
-
setTimeout(onComplete, 1500);
|
|
13456
|
-
} catch (err) {
|
|
13457
|
-
setError(err.message);
|
|
13458
|
-
setStatus("error");
|
|
13459
|
-
setTimeout(onComplete, 1500);
|
|
13460
|
-
}
|
|
13461
|
-
};
|
|
13462
|
-
fetch2();
|
|
13463
|
-
}, [resource, onComplete]);
|
|
13778
|
+
const action = useCallback3(() => resource.listPaymentMethods(), [resource]);
|
|
13779
|
+
const { status, data: methods, error } = useAsyncAction(action, onComplete);
|
|
13464
13780
|
if (status === "loading") {
|
|
13465
|
-
return /* @__PURE__ */ jsx17(Box12, { children: /* @__PURE__ */
|
|
13466
|
-
/* @__PURE__ */ jsx17(
|
|
13781
|
+
return /* @__PURE__ */ jsx17(Box12, { children: /* @__PURE__ */ jsxs12(Text13, { color: "cyan", children: [
|
|
13782
|
+
/* @__PURE__ */ jsx17(Spinner4, { type: "dots" }),
|
|
13467
13783
|
" Loading payment methods..."
|
|
13468
13784
|
] }) });
|
|
13469
13785
|
}
|
|
13470
13786
|
if (status === "error") {
|
|
13471
|
-
return /* @__PURE__ */
|
|
13787
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
|
|
13472
13788
|
/* @__PURE__ */ jsx17(Text13, { color: "red", children: "\u2717 Failed to load payment methods" }),
|
|
13473
13789
|
/* @__PURE__ */ jsx17(Text13, { color: "red", children: error })
|
|
13474
13790
|
] });
|
|
13475
13791
|
}
|
|
13476
|
-
if (methods.length === 0) {
|
|
13792
|
+
if (!methods || methods.length === 0) {
|
|
13477
13793
|
return /* @__PURE__ */ jsx17(Box12, { children: /* @__PURE__ */ jsx17(Text13, { dimColor: true, children: "No payment methods found" }) });
|
|
13478
13794
|
}
|
|
13479
|
-
return /* @__PURE__ */
|
|
13795
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
|
|
13480
13796
|
/* @__PURE__ */ jsx17(Text13, { bold: true, children: "Payment Methods" }),
|
|
13481
13797
|
/* @__PURE__ */ jsx17(Box12, { flexDirection: "column", marginTop: 1, children: methods.map((pm) => {
|
|
13482
13798
|
const label = pm.card_details?.brand ?? pm.bank_account_details?.bank_name ?? "Bank account";
|
|
13483
13799
|
const last4 = pm.card_details?.last4 ?? pm.bank_account_details?.last4;
|
|
13484
|
-
const suffix =
|
|
13485
|
-
return /* @__PURE__ */ jsx17(Box12, { paddingX: 2, children: /* @__PURE__ */
|
|
13800
|
+
const suffix = pm.nickname ? `(${pm.nickname})` : "";
|
|
13801
|
+
return /* @__PURE__ */ jsx17(Box12, { paddingX: 2, children: /* @__PURE__ */ jsxs12(Text13, { children: [
|
|
13486
13802
|
/* @__PURE__ */ jsx17(Text13, { dimColor: true, children: pm.id }),
|
|
13487
13803
|
" ",
|
|
13488
13804
|
label,
|
|
@@ -13497,36 +13813,22 @@ var PaymentMethodsList = ({
|
|
|
13497
13813
|
|
|
13498
13814
|
// src/commands/payment-methods/index.tsx
|
|
13499
13815
|
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
13500
|
-
function createPaymentMethodsCli(createResource) {
|
|
13816
|
+
function createPaymentMethodsCli(createResource, authStorage2) {
|
|
13501
13817
|
const cli2 = Cli5.create("payment-methods", {
|
|
13502
13818
|
description: "Payment methods management commands"
|
|
13503
13819
|
});
|
|
13504
13820
|
cli2.command("list", {
|
|
13505
13821
|
description: "List all payment methods on your account",
|
|
13506
13822
|
outputPolicy: "agent-only",
|
|
13823
|
+
middleware: [requireAuth(authStorage2)],
|
|
13507
13824
|
async run(c) {
|
|
13508
|
-
if (!storage.isAuthenticated()) {
|
|
13509
|
-
return c.error({
|
|
13510
|
-
code: "NOT_AUTHENTICATED",
|
|
13511
|
-
message: 'Not authenticated. Run "link-cli auth login" first.',
|
|
13512
|
-
cta: {
|
|
13513
|
-
commands: [
|
|
13514
|
-
{ command: "auth login", description: "Log in to Link" }
|
|
13515
|
-
]
|
|
13516
|
-
}
|
|
13517
|
-
});
|
|
13518
|
-
}
|
|
13519
13825
|
const resource = createResource();
|
|
13520
13826
|
if (!c.agent && !c.formatExplicit) {
|
|
13521
|
-
return
|
|
13522
|
-
|
|
13523
|
-
|
|
13524
|
-
|
|
13525
|
-
|
|
13526
|
-
waitUntilExit().then(async () => {
|
|
13527
|
-
resolve(await resource.listPaymentMethods());
|
|
13528
|
-
});
|
|
13529
|
-
});
|
|
13827
|
+
return renderInteractive(
|
|
13828
|
+
/* @__PURE__ */ jsx18(PaymentMethodsList, { resource, onComplete: () => {
|
|
13829
|
+
} }),
|
|
13830
|
+
() => resource.listPaymentMethods()
|
|
13831
|
+
);
|
|
13530
13832
|
}
|
|
13531
13833
|
return resource.listPaymentMethods();
|
|
13532
13834
|
}
|
|
@@ -13534,23 +13836,12 @@ function createPaymentMethodsCli(createResource) {
|
|
|
13534
13836
|
cli2.command("add", {
|
|
13535
13837
|
description: "Open the Link wallet to add a new payment method",
|
|
13536
13838
|
outputPolicy: "agent-only",
|
|
13839
|
+
middleware: [requireAuth(authStorage2)],
|
|
13537
13840
|
async run(c) {
|
|
13538
|
-
if (!storage.isAuthenticated()) {
|
|
13539
|
-
return c.error({
|
|
13540
|
-
code: "NOT_AUTHENTICATED",
|
|
13541
|
-
message: 'Not authenticated. Run "link-cli auth login" first.',
|
|
13542
|
-
cta: {
|
|
13543
|
-
commands: [
|
|
13544
|
-
{ command: "auth login", description: "Log in to Link" }
|
|
13545
|
-
]
|
|
13546
|
-
}
|
|
13547
|
-
});
|
|
13548
|
-
}
|
|
13549
13841
|
if (!c.agent && !c.formatExplicit) {
|
|
13550
|
-
return
|
|
13551
|
-
|
|
13552
|
-
|
|
13553
|
-
});
|
|
13842
|
+
return renderInteractive(/* @__PURE__ */ jsx18(AddPaymentMethod, {}), () => ({
|
|
13843
|
+
url: WALLET_URL
|
|
13844
|
+
}));
|
|
13554
13845
|
}
|
|
13555
13846
|
return { url: WALLET_URL };
|
|
13556
13847
|
}
|
|
@@ -13558,9 +13849,147 @@ function createPaymentMethodsCli(createResource) {
|
|
|
13558
13849
|
return cli2;
|
|
13559
13850
|
}
|
|
13560
13851
|
|
|
13852
|
+
// src/commands/shipping-address/index.tsx
|
|
13853
|
+
import { Cli as Cli6 } from "incur";
|
|
13854
|
+
|
|
13855
|
+
// src/commands/shipping-address/list.tsx
|
|
13856
|
+
import { Box as Box13, Text as Text14 } from "ink";
|
|
13857
|
+
import Spinner5 from "ink-spinner";
|
|
13858
|
+
import { useCallback as useCallback4 } from "react";
|
|
13859
|
+
import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
13860
|
+
function formatStreetLine(address) {
|
|
13861
|
+
const parts = [address.line_1, address.line_2].filter(Boolean);
|
|
13862
|
+
return parts.length > 0 ? parts.join(", ") : null;
|
|
13863
|
+
}
|
|
13864
|
+
function formatLocalityLine(address) {
|
|
13865
|
+
const locality = [
|
|
13866
|
+
address.dependent_locality,
|
|
13867
|
+
address.locality,
|
|
13868
|
+
address.administrative_area
|
|
13869
|
+
].filter(Boolean).join(", ");
|
|
13870
|
+
const postal = [address.postal_code, address.sorting_code].filter(Boolean).join(" ");
|
|
13871
|
+
const localityPostal = locality && postal ? `${locality} ${postal}` : locality || postal || null;
|
|
13872
|
+
if (localityPostal && address.country_code) {
|
|
13873
|
+
return `${localityPostal}, ${address.country_code}`;
|
|
13874
|
+
}
|
|
13875
|
+
return localityPostal || address.country_code || null;
|
|
13876
|
+
}
|
|
13877
|
+
function formatAddressLines(addressRecord) {
|
|
13878
|
+
if (!addressRecord.address) {
|
|
13879
|
+
return ["Address details unavailable"];
|
|
13880
|
+
}
|
|
13881
|
+
const address = addressRecord.address;
|
|
13882
|
+
const lines = [formatStreetLine(address), formatLocalityLine(address)].filter(
|
|
13883
|
+
(line) => Boolean(line)
|
|
13884
|
+
);
|
|
13885
|
+
return lines.length > 0 ? lines : ["Address details unavailable"];
|
|
13886
|
+
}
|
|
13887
|
+
var ShippingAddressList = ({
|
|
13888
|
+
resource,
|
|
13889
|
+
onComplete
|
|
13890
|
+
}) => {
|
|
13891
|
+
const action = useCallback4(
|
|
13892
|
+
() => resource.listShippingAddresses(),
|
|
13893
|
+
[resource]
|
|
13894
|
+
);
|
|
13895
|
+
const {
|
|
13896
|
+
status,
|
|
13897
|
+
data: shippingAddresses,
|
|
13898
|
+
error
|
|
13899
|
+
} = useAsyncAction(action, onComplete);
|
|
13900
|
+
if (status === "loading") {
|
|
13901
|
+
return /* @__PURE__ */ jsx19(Box13, { children: /* @__PURE__ */ jsxs13(Text14, { color: "cyan", children: [
|
|
13902
|
+
/* @__PURE__ */ jsx19(Spinner5, { type: "dots" }),
|
|
13903
|
+
" Loading shipping addresses..."
|
|
13904
|
+
] }) });
|
|
13905
|
+
}
|
|
13906
|
+
if (status === "error") {
|
|
13907
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
|
|
13908
|
+
/* @__PURE__ */ jsx19(Text14, { color: "red", children: "\u2717 Failed to load shipping addresses" }),
|
|
13909
|
+
/* @__PURE__ */ jsx19(Text14, { color: "red", children: error })
|
|
13910
|
+
] });
|
|
13911
|
+
}
|
|
13912
|
+
if (!shippingAddresses || shippingAddresses.length === 0) {
|
|
13913
|
+
return /* @__PURE__ */ jsx19(Box13, { children: /* @__PURE__ */ jsx19(Text14, { dimColor: true, children: "No shipping addresses found" }) });
|
|
13914
|
+
}
|
|
13915
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
|
|
13916
|
+
/* @__PURE__ */ jsx19(Text14, { bold: true, children: "Shipping Addresses" }),
|
|
13917
|
+
/* @__PURE__ */ jsx19(Box13, { flexDirection: "column", marginTop: 1, children: shippingAddresses.map((shippingAddress) => {
|
|
13918
|
+
const addressName = shippingAddress.address?.name;
|
|
13919
|
+
const nickname = shippingAddress.nickname ? ` (${shippingAddress.nickname})` : "";
|
|
13920
|
+
return /* @__PURE__ */ jsxs13(
|
|
13921
|
+
Box13,
|
|
13922
|
+
{
|
|
13923
|
+
flexDirection: "column",
|
|
13924
|
+
paddingX: 2,
|
|
13925
|
+
marginBottom: 1,
|
|
13926
|
+
children: [
|
|
13927
|
+
/* @__PURE__ */ jsxs13(Text14, { children: [
|
|
13928
|
+
/* @__PURE__ */ jsx19(Text14, { dimColor: true, children: shippingAddress.id }),
|
|
13929
|
+
nickname,
|
|
13930
|
+
shippingAddress.is_default ? /* @__PURE__ */ jsx19(Text14, { color: "green", children: " (default)" }) : null
|
|
13931
|
+
] }),
|
|
13932
|
+
/* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", marginTop: 1, children: [
|
|
13933
|
+
addressName ? /* @__PURE__ */ jsx19(Text14, { bold: true, children: addressName }) : null,
|
|
13934
|
+
formatAddressLines(shippingAddress).map((line) => /* @__PURE__ */ jsx19(Text14, { children: line }, `${shippingAddress.id}:${line}`))
|
|
13935
|
+
] })
|
|
13936
|
+
]
|
|
13937
|
+
},
|
|
13938
|
+
shippingAddress.id
|
|
13939
|
+
);
|
|
13940
|
+
}) })
|
|
13941
|
+
] });
|
|
13942
|
+
};
|
|
13943
|
+
|
|
13944
|
+
// src/commands/shipping-address/index.tsx
|
|
13945
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
13946
|
+
function createShippingAddressCli(createResource, authStorage2) {
|
|
13947
|
+
const cli2 = Cli6.create("shipping-address", {
|
|
13948
|
+
description: "Shipping address management commands"
|
|
13949
|
+
});
|
|
13950
|
+
cli2.command("list", {
|
|
13951
|
+
description: "List all shipping addresses on your account",
|
|
13952
|
+
outputPolicy: "agent-only",
|
|
13953
|
+
middleware: [requireAuth(authStorage2)],
|
|
13954
|
+
async run(c) {
|
|
13955
|
+
const resource = createResource();
|
|
13956
|
+
if (!c.agent && !c.formatExplicit) {
|
|
13957
|
+
return renderInteractive(
|
|
13958
|
+
/* @__PURE__ */ jsx20(ShippingAddressList, { resource, onComplete: () => {
|
|
13959
|
+
} }),
|
|
13960
|
+
() => resource.listShippingAddresses()
|
|
13961
|
+
);
|
|
13962
|
+
}
|
|
13963
|
+
return resource.listShippingAddresses();
|
|
13964
|
+
}
|
|
13965
|
+
});
|
|
13966
|
+
return cli2;
|
|
13967
|
+
}
|
|
13968
|
+
|
|
13561
13969
|
// src/commands/spend-request/index.tsx
|
|
13562
|
-
import { Cli as
|
|
13563
|
-
|
|
13970
|
+
import { Cli as Cli7, z as z7 } from "incur";
|
|
13971
|
+
|
|
13972
|
+
// src/utils/credential-output.ts
|
|
13973
|
+
import fs4 from "fs/promises";
|
|
13974
|
+
import path6 from "path";
|
|
13975
|
+
async function writeCredentialFile(filePath, data, force) {
|
|
13976
|
+
const resolved = path6.resolve(filePath);
|
|
13977
|
+
if (!force) {
|
|
13978
|
+
try {
|
|
13979
|
+
await fs4.access(resolved);
|
|
13980
|
+
throw new Error(
|
|
13981
|
+
`OUTPUT_FILE_EXISTS: ${resolved} already exists. Use --force to overwrite.`
|
|
13982
|
+
);
|
|
13983
|
+
} catch (err) {
|
|
13984
|
+
if (err.code !== "ENOENT") throw err;
|
|
13985
|
+
}
|
|
13986
|
+
}
|
|
13987
|
+
await fs4.writeFile(resolved, JSON.stringify(data, null, 2), {
|
|
13988
|
+
mode: 384
|
|
13989
|
+
});
|
|
13990
|
+
await fs4.chmod(resolved, 384);
|
|
13991
|
+
return resolved;
|
|
13992
|
+
}
|
|
13564
13993
|
|
|
13565
13994
|
// src/utils/line-item-parser.ts
|
|
13566
13995
|
import { z as z5 } from "zod";
|
|
@@ -13623,21 +14052,59 @@ function parseTotalFlag(raw) {
|
|
|
13623
14052
|
}
|
|
13624
14053
|
}
|
|
13625
14054
|
|
|
13626
|
-
// src/commands/spend-request/
|
|
14055
|
+
// src/commands/spend-request/cancel.tsx
|
|
13627
14056
|
import { Box as Box14, Text as Text15 } from "ink";
|
|
13628
|
-
import
|
|
13629
|
-
import { useCallback as
|
|
14057
|
+
import Spinner6 from "ink-spinner";
|
|
14058
|
+
import { useCallback as useCallback5 } from "react";
|
|
14059
|
+
import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
14060
|
+
var CancelSpendRequest = ({
|
|
14061
|
+
repository,
|
|
14062
|
+
id,
|
|
14063
|
+
onComplete
|
|
14064
|
+
}) => {
|
|
14065
|
+
const action = useCallback5(
|
|
14066
|
+
() => repository.cancelSpendRequest(id),
|
|
14067
|
+
[repository, id]
|
|
14068
|
+
);
|
|
14069
|
+
const { status, data: request, error } = useAsyncAction(action, onComplete);
|
|
14070
|
+
if (status === "loading") {
|
|
14071
|
+
return /* @__PURE__ */ jsx21(Box14, { children: /* @__PURE__ */ jsxs14(Text15, { color: "cyan", children: [
|
|
14072
|
+
/* @__PURE__ */ jsx21(Spinner6, { type: "dots" }),
|
|
14073
|
+
" Canceling spend request ",
|
|
14074
|
+
id,
|
|
14075
|
+
"..."
|
|
14076
|
+
] }) });
|
|
14077
|
+
}
|
|
14078
|
+
if (status === "error") {
|
|
14079
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
|
|
14080
|
+
/* @__PURE__ */ jsx21(Text15, { color: "red", children: "\u2717 Failed to cancel spend request" }),
|
|
14081
|
+
/* @__PURE__ */ jsx21(Text15, { color: "red", children: error })
|
|
14082
|
+
] });
|
|
14083
|
+
}
|
|
14084
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
|
|
14085
|
+
/* @__PURE__ */ jsx21(Text15, { color: "green", children: "\u2713 Spend request canceled" }),
|
|
14086
|
+
/* @__PURE__ */ jsx21(Box14, { flexDirection: "column", marginTop: 1, paddingX: 2, children: /* @__PURE__ */ jsxs14(Text15, { children: [
|
|
14087
|
+
"ID: ",
|
|
14088
|
+
/* @__PURE__ */ jsx21(Text15, { bold: true, children: request?.id })
|
|
14089
|
+
] }) })
|
|
14090
|
+
] });
|
|
14091
|
+
};
|
|
14092
|
+
|
|
14093
|
+
// src/commands/spend-request/create.tsx
|
|
14094
|
+
import { Box as Box16, Text as Text17 } from "ink";
|
|
14095
|
+
import Spinner8 from "ink-spinner";
|
|
14096
|
+
import { useCallback as useCallback6, useEffect as useEffect9, useState as useState9 } from "react";
|
|
13630
14097
|
|
|
13631
14098
|
// src/commands/spend-request/approval-waiting-view.tsx
|
|
13632
|
-
import { Box as
|
|
13633
|
-
import
|
|
13634
|
-
import { jsx as
|
|
14099
|
+
import { Box as Box15, Text as Text16 } from "ink";
|
|
14100
|
+
import Spinner7 from "ink-spinner";
|
|
14101
|
+
import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
13635
14102
|
var ApprovalWaitingView = ({
|
|
13636
14103
|
status,
|
|
13637
14104
|
approvalUrl
|
|
13638
|
-
}) => /* @__PURE__ */
|
|
13639
|
-
/* @__PURE__ */
|
|
13640
|
-
|
|
14105
|
+
}) => /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", paddingY: 1, children: [
|
|
14106
|
+
/* @__PURE__ */ jsxs15(
|
|
14107
|
+
Box15,
|
|
13641
14108
|
{
|
|
13642
14109
|
flexDirection: "column",
|
|
13643
14110
|
borderStyle: "round",
|
|
@@ -13645,25 +14112,25 @@ var ApprovalWaitingView = ({
|
|
|
13645
14112
|
paddingX: 2,
|
|
13646
14113
|
paddingY: 1,
|
|
13647
14114
|
children: [
|
|
13648
|
-
/* @__PURE__ */
|
|
14115
|
+
/* @__PURE__ */ jsxs15(Text16, { children: [
|
|
13649
14116
|
"Approve at:",
|
|
13650
14117
|
" ",
|
|
13651
|
-
/* @__PURE__ */
|
|
14118
|
+
/* @__PURE__ */ jsx22(Text16, { bold: true, color: "cyan", children: approvalUrl })
|
|
13652
14119
|
] }),
|
|
13653
|
-
/* @__PURE__ */
|
|
14120
|
+
/* @__PURE__ */ jsx22(Text16, { dimColor: true, children: "Press Enter to open in browser" })
|
|
13654
14121
|
]
|
|
13655
14122
|
}
|
|
13656
14123
|
),
|
|
13657
|
-
/* @__PURE__ */
|
|
13658
|
-
/* @__PURE__ */
|
|
13659
|
-
/* @__PURE__ */
|
|
14124
|
+
/* @__PURE__ */ jsx22(AppDownloadQrCodes, {}),
|
|
14125
|
+
/* @__PURE__ */ jsx22(Box15, { marginTop: 1, children: status === "polling" ? /* @__PURE__ */ jsxs15(Text16, { color: "cyan", children: [
|
|
14126
|
+
/* @__PURE__ */ jsx22(Spinner7, { type: "dots" }),
|
|
13660
14127
|
" Waiting for approval..."
|
|
13661
|
-
] }) : /* @__PURE__ */
|
|
14128
|
+
] }) : /* @__PURE__ */ jsx22(Text16, { dimColor: true, children: "Waiting..." }) })
|
|
13662
14129
|
] });
|
|
13663
14130
|
|
|
13664
14131
|
// src/commands/spend-request/use-approval-polling.ts
|
|
13665
14132
|
import { useInput as useInput7 } from "ink";
|
|
13666
|
-
import { useEffect as
|
|
14133
|
+
import { useEffect as useEffect8 } from "react";
|
|
13667
14134
|
function useApprovalPolling({
|
|
13668
14135
|
status,
|
|
13669
14136
|
setStatus,
|
|
@@ -13681,22 +14148,29 @@ function useApprovalPolling({
|
|
|
13681
14148
|
},
|
|
13682
14149
|
{ isActive: isWaiting }
|
|
13683
14150
|
);
|
|
13684
|
-
|
|
14151
|
+
useEffect8(() => {
|
|
13685
14152
|
if (status !== "waiting") return;
|
|
13686
14153
|
const timeout = setTimeout(() => setStatus("polling"), 1e3);
|
|
13687
14154
|
return () => clearTimeout(timeout);
|
|
13688
14155
|
}, [status, setStatus]);
|
|
13689
|
-
|
|
14156
|
+
useEffect8(() => {
|
|
13690
14157
|
if (status !== "polling" || !requestId) return;
|
|
13691
14158
|
let cancelled = false;
|
|
13692
14159
|
const poll = async () => {
|
|
13693
14160
|
try {
|
|
13694
14161
|
const final = await pollUntilApproved(repository, requestId);
|
|
13695
|
-
if (
|
|
13696
|
-
|
|
13697
|
-
|
|
13698
|
-
|
|
14162
|
+
if (cancelled) return;
|
|
14163
|
+
if (final.status !== "approved") {
|
|
14164
|
+
onError(
|
|
14165
|
+
`Spend request did not reach approved (status: ${final.status})`
|
|
14166
|
+
);
|
|
14167
|
+
setStatus("error");
|
|
14168
|
+
setTimeout(() => onComplete(final), DISPLAY_DELAY_MS);
|
|
14169
|
+
return;
|
|
13699
14170
|
}
|
|
14171
|
+
onSuccess(final);
|
|
14172
|
+
setStatus("success");
|
|
14173
|
+
setTimeout(() => onComplete(final), DISPLAY_DELAY_MS);
|
|
13700
14174
|
} catch (err) {
|
|
13701
14175
|
if (!cancelled) {
|
|
13702
14176
|
onError(err.message);
|
|
@@ -13720,22 +14194,26 @@ function useApprovalPolling({
|
|
|
13720
14194
|
}
|
|
13721
14195
|
|
|
13722
14196
|
// src/commands/spend-request/create.tsx
|
|
13723
|
-
import { Fragment as Fragment4, jsx as
|
|
14197
|
+
import { Fragment as Fragment4, jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
13724
14198
|
var CreateSpendRequest = ({
|
|
13725
14199
|
repository,
|
|
13726
14200
|
params,
|
|
13727
14201
|
requestApproval = false,
|
|
14202
|
+
outputFile,
|
|
14203
|
+
force,
|
|
13728
14204
|
onComplete
|
|
13729
14205
|
}) => {
|
|
13730
|
-
const [status, setStatus] =
|
|
13731
|
-
const [request, setRequest] =
|
|
13732
|
-
const [error, setError] =
|
|
14206
|
+
const [status, setStatus] = useState9("creating");
|
|
14207
|
+
const [request, setRequest] = useState9(null);
|
|
14208
|
+
const [error, setError] = useState9("");
|
|
14209
|
+
const [outputFilePath, setOutputFilePath] = useState9(null);
|
|
14210
|
+
const [fileError, setFileError] = useState9("");
|
|
13733
14211
|
const approvalUrl = request?.approval_url ?? "";
|
|
13734
|
-
const onSuccess =
|
|
14212
|
+
const onSuccess = useCallback6(
|
|
13735
14213
|
(result) => setRequest(result),
|
|
13736
14214
|
[]
|
|
13737
14215
|
);
|
|
13738
|
-
const onError =
|
|
14216
|
+
const onError = useCallback6((msg) => setError(msg), []);
|
|
13739
14217
|
useApprovalPolling({
|
|
13740
14218
|
status,
|
|
13741
14219
|
setStatus,
|
|
@@ -13746,7 +14224,7 @@ var CreateSpendRequest = ({
|
|
|
13746
14224
|
onSuccess,
|
|
13747
14225
|
onError
|
|
13748
14226
|
});
|
|
13749
|
-
|
|
14227
|
+
useEffect9(() => {
|
|
13750
14228
|
const create = async () => {
|
|
13751
14229
|
try {
|
|
13752
14230
|
const result = await repository.createSpendRequest(params);
|
|
@@ -13755,69 +14233,124 @@ var CreateSpendRequest = ({
|
|
|
13755
14233
|
setStatus("waiting");
|
|
13756
14234
|
} else {
|
|
13757
14235
|
setStatus("success");
|
|
13758
|
-
setTimeout(() => onComplete(result),
|
|
14236
|
+
setTimeout(() => onComplete(result), DISPLAY_DELAY_MS);
|
|
13759
14237
|
}
|
|
13760
14238
|
} catch (err) {
|
|
13761
14239
|
setError(err.message);
|
|
13762
14240
|
setStatus("error");
|
|
13763
|
-
setTimeout(() => onComplete(null),
|
|
14241
|
+
setTimeout(() => onComplete(null), DISPLAY_DELAY_MS);
|
|
13764
14242
|
}
|
|
13765
14243
|
};
|
|
13766
14244
|
create();
|
|
13767
14245
|
}, [repository, params, requestApproval, onComplete]);
|
|
14246
|
+
useEffect9(() => {
|
|
14247
|
+
if (status !== "success" || !outputFile || !request?.card) return;
|
|
14248
|
+
const fileData = {
|
|
14249
|
+
spend_request_id: request.id,
|
|
14250
|
+
merchant_name: request.merchant_name,
|
|
14251
|
+
merchant_url: request.merchant_url,
|
|
14252
|
+
context: request.context,
|
|
14253
|
+
created_at: request.created_at,
|
|
14254
|
+
card: request.card
|
|
14255
|
+
};
|
|
14256
|
+
writeCredentialFile(outputFile, fileData, force ?? false).then((path7) => setOutputFilePath(path7)).catch((err) => setFileError(err.message));
|
|
14257
|
+
}, [status, outputFile, force, request]);
|
|
13768
14258
|
if (status === "creating") {
|
|
13769
|
-
return /* @__PURE__ */
|
|
13770
|
-
/* @__PURE__ */
|
|
14259
|
+
return /* @__PURE__ */ jsx23(Box16, { children: /* @__PURE__ */ jsxs16(Text17, { color: "cyan", children: [
|
|
14260
|
+
/* @__PURE__ */ jsx23(Spinner8, { type: "dots" }),
|
|
13771
14261
|
" Creating spend request..."
|
|
13772
14262
|
] }) });
|
|
13773
14263
|
}
|
|
13774
14264
|
if (status === "error") {
|
|
13775
|
-
return /* @__PURE__ */
|
|
13776
|
-
/* @__PURE__ */
|
|
13777
|
-
/* @__PURE__ */
|
|
14265
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
|
|
14266
|
+
/* @__PURE__ */ jsx23(Text17, { color: "red", children: "\u2717 Failed to create spend request" }),
|
|
14267
|
+
/* @__PURE__ */ jsx23(Text17, { color: "red", children: error })
|
|
13778
14268
|
] });
|
|
13779
14269
|
}
|
|
13780
14270
|
if (status === "success") {
|
|
13781
|
-
return /* @__PURE__ */
|
|
13782
|
-
/* @__PURE__ */
|
|
13783
|
-
/* @__PURE__ */
|
|
13784
|
-
/* @__PURE__ */
|
|
14271
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
|
|
14272
|
+
/* @__PURE__ */ jsx23(Text17, { color: "green", children: "\u2713 Spend request created" }),
|
|
14273
|
+
/* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
|
|
14274
|
+
/* @__PURE__ */ jsxs16(Text17, { children: [
|
|
13785
14275
|
"ID: ",
|
|
13786
|
-
/* @__PURE__ */
|
|
14276
|
+
/* @__PURE__ */ jsx23(Text17, { bold: true, children: request?.id })
|
|
13787
14277
|
] }),
|
|
13788
|
-
/* @__PURE__ */
|
|
14278
|
+
/* @__PURE__ */ jsxs16(Text17, { children: [
|
|
13789
14279
|
"Status: ",
|
|
13790
|
-
/* @__PURE__ */
|
|
14280
|
+
/* @__PURE__ */ jsx23(Text17, { bold: true, children: request?.status })
|
|
13791
14281
|
] }),
|
|
13792
|
-
/* @__PURE__ */
|
|
14282
|
+
/* @__PURE__ */ jsxs16(Text17, { children: [
|
|
13793
14283
|
"Amount:",
|
|
13794
14284
|
" ",
|
|
13795
|
-
/* @__PURE__ */
|
|
14285
|
+
/* @__PURE__ */ jsx23(Text17, { bold: true, children: request?.amount != null ? `${request.amount} ${request.currency?.toUpperCase() ?? ""}`.trim() : "N/A" })
|
|
13796
14286
|
] }),
|
|
13797
|
-
/* @__PURE__ */
|
|
14287
|
+
/* @__PURE__ */ jsxs16(Text17, { children: [
|
|
13798
14288
|
"Merchant: ",
|
|
13799
|
-
/* @__PURE__ */
|
|
14289
|
+
/* @__PURE__ */ jsx23(Text17, { bold: true, children: request?.merchant_name })
|
|
13800
14290
|
] }),
|
|
13801
|
-
/* @__PURE__ */
|
|
14291
|
+
/* @__PURE__ */ jsxs16(Text17, { children: [
|
|
13802
14292
|
"Line Items:",
|
|
13803
14293
|
" ",
|
|
13804
|
-
/* @__PURE__ */
|
|
14294
|
+
/* @__PURE__ */ jsx23(Text17, { bold: true, children: request?.line_items.map((li) => li.name).join(", ") || "N/A" })
|
|
13805
14295
|
] }),
|
|
13806
|
-
request?.credential_type === "shared_payment_token" && request.shared_payment_token && /* @__PURE__ */
|
|
14296
|
+
request?.credential_type === "shared_payment_token" && request.shared_payment_token && /* @__PURE__ */ jsxs16(Text17, { children: [
|
|
13807
14297
|
"Token: ",
|
|
13808
|
-
/* @__PURE__ */
|
|
14298
|
+
/* @__PURE__ */ jsx23(Text17, { bold: true, children: request.shared_payment_token.id })
|
|
14299
|
+
] })
|
|
14300
|
+
] }),
|
|
14301
|
+
request?.card && !outputFile && /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginTop: 1, children: [
|
|
14302
|
+
/* @__PURE__ */ jsx23(Text17, { bold: true, children: "Card Details:" }),
|
|
14303
|
+
/* @__PURE__ */ jsxs16(Text17, { children: [
|
|
14304
|
+
" ",
|
|
14305
|
+
"Number: ",
|
|
14306
|
+
/* @__PURE__ */ jsx23(Text17, { bold: true, children: request.card.number })
|
|
14307
|
+
] }),
|
|
14308
|
+
/* @__PURE__ */ jsxs16(Text17, { children: [
|
|
14309
|
+
" ",
|
|
14310
|
+
"Brand: ",
|
|
14311
|
+
/* @__PURE__ */ jsx23(Text17, { bold: true, children: request.card.brand })
|
|
14312
|
+
] }),
|
|
14313
|
+
/* @__PURE__ */ jsxs16(Text17, { children: [
|
|
14314
|
+
" ",
|
|
14315
|
+
"Expiry:",
|
|
14316
|
+
" ",
|
|
14317
|
+
/* @__PURE__ */ jsxs16(Text17, { bold: true, children: [
|
|
14318
|
+
String(request.card.exp_month).padStart(2, "0"),
|
|
14319
|
+
"/",
|
|
14320
|
+
request.card.exp_year
|
|
14321
|
+
] })
|
|
14322
|
+
] }),
|
|
14323
|
+
request.card.cvc && /* @__PURE__ */ jsxs16(Text17, { children: [
|
|
14324
|
+
" ",
|
|
14325
|
+
"CVC: ",
|
|
14326
|
+
/* @__PURE__ */ jsx23(Text17, { bold: true, children: request.card.cvc })
|
|
14327
|
+
] }),
|
|
14328
|
+
request.card.valid_until && /* @__PURE__ */ jsxs16(Text17, { children: [
|
|
14329
|
+
" ",
|
|
14330
|
+
"Valid Until: ",
|
|
14331
|
+
/* @__PURE__ */ jsx23(Text17, { bold: true, children: request.card.valid_until })
|
|
14332
|
+
] })
|
|
14333
|
+
] }),
|
|
14334
|
+
request?.card && outputFile && /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginTop: 1, children: [
|
|
14335
|
+
outputFilePath && /* @__PURE__ */ jsxs16(Text17, { color: "green", children: [
|
|
14336
|
+
"Card credentials written to ",
|
|
14337
|
+
/* @__PURE__ */ jsx23(Text17, { bold: true, children: outputFilePath })
|
|
14338
|
+
] }),
|
|
14339
|
+
fileError && /* @__PURE__ */ jsxs16(Text17, { color: "red", children: [
|
|
14340
|
+
"Failed to write card file: ",
|
|
14341
|
+
fileError
|
|
13809
14342
|
] })
|
|
13810
14343
|
] }),
|
|
13811
|
-
/* @__PURE__ */
|
|
14344
|
+
/* @__PURE__ */ jsx23(AppDownloadQrCodes, {})
|
|
13812
14345
|
] });
|
|
13813
14346
|
}
|
|
13814
|
-
return /* @__PURE__ */
|
|
13815
|
-
/* @__PURE__ */
|
|
14347
|
+
return /* @__PURE__ */ jsxs16(Fragment4, { children: [
|
|
14348
|
+
/* @__PURE__ */ jsx23(Box16, { children: /* @__PURE__ */ jsxs16(Text17, { color: "green", children: [
|
|
13816
14349
|
"\u2713 Spend request created (ID: ",
|
|
13817
|
-
/* @__PURE__ */
|
|
14350
|
+
/* @__PURE__ */ jsx23(Text17, { bold: true, children: request?.id }),
|
|
13818
14351
|
")"
|
|
13819
14352
|
] }) }),
|
|
13820
|
-
/* @__PURE__ */
|
|
14353
|
+
/* @__PURE__ */ jsx23(
|
|
13821
14354
|
ApprovalWaitingView,
|
|
13822
14355
|
{
|
|
13823
14356
|
status,
|
|
@@ -13828,21 +14361,21 @@ var CreateSpendRequest = ({
|
|
|
13828
14361
|
};
|
|
13829
14362
|
|
|
13830
14363
|
// src/commands/spend-request/request-approval.tsx
|
|
13831
|
-
import { Box as
|
|
13832
|
-
import
|
|
13833
|
-
import { useCallback as
|
|
13834
|
-
import { jsx as
|
|
14364
|
+
import { Box as Box17, Text as Text18 } from "ink";
|
|
14365
|
+
import Spinner9 from "ink-spinner";
|
|
14366
|
+
import { useCallback as useCallback7, useEffect as useEffect10, useState as useState10 } from "react";
|
|
14367
|
+
import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
13835
14368
|
var RequestApproval = ({
|
|
13836
14369
|
repository,
|
|
13837
14370
|
id,
|
|
13838
14371
|
onComplete
|
|
13839
14372
|
}) => {
|
|
13840
|
-
const [status, setStatus] =
|
|
13841
|
-
const [approvalUrl, setApprovalUrl] =
|
|
13842
|
-
const [result, setResult] =
|
|
13843
|
-
const [error, setError] =
|
|
13844
|
-
const onSuccess =
|
|
13845
|
-
const onError =
|
|
14373
|
+
const [status, setStatus] = useState10("requesting");
|
|
14374
|
+
const [approvalUrl, setApprovalUrl] = useState10("");
|
|
14375
|
+
const [result, setResult] = useState10(null);
|
|
14376
|
+
const [error, setError] = useState10("");
|
|
14377
|
+
const onSuccess = useCallback7((r) => setResult(r), []);
|
|
14378
|
+
const onError = useCallback7((msg) => setError(msg), []);
|
|
13846
14379
|
useApprovalPolling({
|
|
13847
14380
|
status,
|
|
13848
14381
|
setStatus,
|
|
@@ -13853,7 +14386,7 @@ var RequestApproval = ({
|
|
|
13853
14386
|
onSuccess,
|
|
13854
14387
|
onError
|
|
13855
14388
|
});
|
|
13856
|
-
|
|
14389
|
+
useEffect10(() => {
|
|
13857
14390
|
const request = async () => {
|
|
13858
14391
|
try {
|
|
13859
14392
|
const res = await repository.requestApproval(id);
|
|
@@ -13867,46 +14400,46 @@ var RequestApproval = ({
|
|
|
13867
14400
|
request();
|
|
13868
14401
|
}, [repository, id]);
|
|
13869
14402
|
if (status === "requesting") {
|
|
13870
|
-
return /* @__PURE__ */
|
|
13871
|
-
/* @__PURE__ */
|
|
14403
|
+
return /* @__PURE__ */ jsx24(Box17, { children: /* @__PURE__ */ jsxs17(Text18, { color: "cyan", children: [
|
|
14404
|
+
/* @__PURE__ */ jsx24(Spinner9, { type: "dots" }),
|
|
13872
14405
|
" Requesting approval..."
|
|
13873
14406
|
] }) });
|
|
13874
14407
|
}
|
|
13875
14408
|
if (status === "error") {
|
|
13876
|
-
return /* @__PURE__ */
|
|
13877
|
-
/* @__PURE__ */
|
|
13878
|
-
/* @__PURE__ */
|
|
14409
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", children: [
|
|
14410
|
+
/* @__PURE__ */ jsx24(Text18, { color: "red", children: "\u2717 Failed to request approval" }),
|
|
14411
|
+
/* @__PURE__ */ jsx24(Text18, { color: "red", children: error })
|
|
13879
14412
|
] });
|
|
13880
14413
|
}
|
|
13881
14414
|
if (status === "success") {
|
|
13882
|
-
return /* @__PURE__ */
|
|
13883
|
-
/* @__PURE__ */
|
|
13884
|
-
/* @__PURE__ */
|
|
13885
|
-
/* @__PURE__ */
|
|
14415
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", children: [
|
|
14416
|
+
/* @__PURE__ */ jsx24(Text18, { color: "green", children: "\u2713 Approval completed" }),
|
|
14417
|
+
/* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
|
|
14418
|
+
/* @__PURE__ */ jsxs17(Text18, { children: [
|
|
13886
14419
|
"ID: ",
|
|
13887
|
-
/* @__PURE__ */
|
|
14420
|
+
/* @__PURE__ */ jsx24(Text18, { bold: true, children: result?.id })
|
|
13888
14421
|
] }),
|
|
13889
|
-
/* @__PURE__ */
|
|
14422
|
+
/* @__PURE__ */ jsxs17(Text18, { children: [
|
|
13890
14423
|
"Status: ",
|
|
13891
|
-
/* @__PURE__ */
|
|
14424
|
+
/* @__PURE__ */ jsx24(Text18, { bold: true, children: result?.status })
|
|
13892
14425
|
] }),
|
|
13893
|
-
/* @__PURE__ */
|
|
14426
|
+
/* @__PURE__ */ jsxs17(Text18, { children: [
|
|
13894
14427
|
"Amount:",
|
|
13895
14428
|
" ",
|
|
13896
|
-
/* @__PURE__ */
|
|
14429
|
+
/* @__PURE__ */ jsx24(Text18, { bold: true, children: result?.amount != null ? `${result.amount} ${result.currency?.toUpperCase() ?? ""}`.trim() : "N/A" })
|
|
13897
14430
|
] }),
|
|
13898
|
-
/* @__PURE__ */
|
|
14431
|
+
/* @__PURE__ */ jsxs17(Text18, { children: [
|
|
13899
14432
|
"Merchant: ",
|
|
13900
|
-
/* @__PURE__ */
|
|
14433
|
+
/* @__PURE__ */ jsx24(Text18, { bold: true, children: result?.merchant_name })
|
|
13901
14434
|
] }),
|
|
13902
|
-
result?.credential_type === "shared_payment_token" && result.shared_payment_token && /* @__PURE__ */
|
|
14435
|
+
result?.credential_type === "shared_payment_token" && result.shared_payment_token && /* @__PURE__ */ jsxs17(Text18, { children: [
|
|
13903
14436
|
"Token: ",
|
|
13904
|
-
/* @__PURE__ */
|
|
14437
|
+
/* @__PURE__ */ jsx24(Text18, { bold: true, children: result.shared_payment_token.id })
|
|
13905
14438
|
] })
|
|
13906
14439
|
] })
|
|
13907
14440
|
] });
|
|
13908
14441
|
}
|
|
13909
|
-
return /* @__PURE__ */
|
|
14442
|
+
return /* @__PURE__ */ jsx24(
|
|
13910
14443
|
ApprovalWaitingView,
|
|
13911
14444
|
{
|
|
13912
14445
|
status,
|
|
@@ -13916,49 +14449,76 @@ var RequestApproval = ({
|
|
|
13916
14449
|
};
|
|
13917
14450
|
|
|
13918
14451
|
// src/commands/spend-request/retrieve.tsx
|
|
13919
|
-
import { Box as
|
|
13920
|
-
import
|
|
13921
|
-
import { useEffect as
|
|
13922
|
-
import { jsx as
|
|
14452
|
+
import { Box as Box18, Text as Text19 } from "ink";
|
|
14453
|
+
import Spinner10 from "ink-spinner";
|
|
14454
|
+
import { useEffect as useEffect11, useRef as useRef5, useState as useState11 } from "react";
|
|
14455
|
+
import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
14456
|
+
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
14457
|
+
"approved",
|
|
14458
|
+
"denied",
|
|
14459
|
+
"expired",
|
|
14460
|
+
"succeeded",
|
|
14461
|
+
"failed",
|
|
14462
|
+
"canceled"
|
|
14463
|
+
]);
|
|
13923
14464
|
var RetrieveSpendRequest = ({
|
|
13924
14465
|
repository,
|
|
13925
14466
|
id,
|
|
13926
|
-
timeout =
|
|
14467
|
+
timeout = 600,
|
|
13927
14468
|
include,
|
|
14469
|
+
outputFile,
|
|
14470
|
+
force,
|
|
13928
14471
|
onComplete
|
|
13929
14472
|
}) => {
|
|
13930
|
-
const [phase, setPhase] =
|
|
13931
|
-
const [request, setRequest] =
|
|
13932
|
-
const [error, setError] =
|
|
13933
|
-
const [elapsed, setElapsed] =
|
|
13934
|
-
const
|
|
13935
|
-
const
|
|
13936
|
-
const
|
|
13937
|
-
const
|
|
13938
|
-
|
|
14473
|
+
const [phase, setPhase] = useState11("fetching");
|
|
14474
|
+
const [request, setRequest] = useState11(null);
|
|
14475
|
+
const [error, setError] = useState11("");
|
|
14476
|
+
const [elapsed, setElapsed] = useState11(0);
|
|
14477
|
+
const [outputFilePath, setOutputFilePath] = useState11(null);
|
|
14478
|
+
const [fileError, setFileError] = useState11("");
|
|
14479
|
+
const startTimeRef = useRef5(Date.now());
|
|
14480
|
+
const pollRef = useRef5(null);
|
|
14481
|
+
const timerRef = useRef5(null);
|
|
14482
|
+
const requestRef = useRef5(null);
|
|
14483
|
+
useEffect11(() => {
|
|
13939
14484
|
return () => {
|
|
13940
14485
|
if (pollRef.current) clearInterval(pollRef.current);
|
|
13941
14486
|
if (timerRef.current) clearInterval(timerRef.current);
|
|
13942
14487
|
};
|
|
13943
14488
|
}, []);
|
|
13944
|
-
|
|
14489
|
+
useEffect11(() => {
|
|
14490
|
+
if (phase !== "success" || !outputFile || !request?.card) return;
|
|
14491
|
+
const fileData = {
|
|
14492
|
+
spend_request_id: request.id,
|
|
14493
|
+
merchant_name: request.merchant_name,
|
|
14494
|
+
merchant_url: request.merchant_url,
|
|
14495
|
+
context: request.context,
|
|
14496
|
+
created_at: request.created_at,
|
|
14497
|
+
card: request.card
|
|
14498
|
+
};
|
|
14499
|
+
writeCredentialFile(outputFile, fileData, force ?? false).then((path7) => setOutputFilePath(path7)).catch((err) => setFileError(err.message));
|
|
14500
|
+
}, [phase, outputFile, force, request]);
|
|
14501
|
+
useEffect11(() => {
|
|
13945
14502
|
const fetch2 = async () => {
|
|
13946
14503
|
try {
|
|
13947
14504
|
const result = await repository.getSpendRequest(id, { include });
|
|
13948
14505
|
if (!result) {
|
|
13949
14506
|
setError(`Spend request ${id} not found`);
|
|
13950
14507
|
setPhase("error");
|
|
13951
|
-
setTimeout(() => onComplete(null),
|
|
14508
|
+
setTimeout(() => onComplete(null), DISPLAY_DELAY_MS);
|
|
13952
14509
|
return;
|
|
13953
14510
|
}
|
|
13954
14511
|
requestRef.current = result;
|
|
13955
14512
|
setRequest(result);
|
|
13956
14513
|
if (result.status === "approved") {
|
|
13957
14514
|
setPhase("success");
|
|
13958
|
-
setTimeout(() => onComplete(result),
|
|
14515
|
+
setTimeout(() => onComplete(result), DISPLAY_DELAY_MS);
|
|
13959
14516
|
} else if (result.status === "denied") {
|
|
13960
14517
|
setPhase("declined");
|
|
13961
|
-
setTimeout(() => onComplete(result),
|
|
14518
|
+
setTimeout(() => onComplete(result), DISPLAY_DELAY_MS);
|
|
14519
|
+
} else if (TERMINAL_STATUSES.has(result.status)) {
|
|
14520
|
+
setPhase("finalized");
|
|
14521
|
+
setTimeout(() => onComplete(result), DISPLAY_DELAY_MS);
|
|
13962
14522
|
} else {
|
|
13963
14523
|
startTimeRef.current = Date.now();
|
|
13964
14524
|
setPhase("polling");
|
|
@@ -13966,12 +14526,12 @@ var RetrieveSpendRequest = ({
|
|
|
13966
14526
|
} catch (err) {
|
|
13967
14527
|
setError(err.message);
|
|
13968
14528
|
setPhase("error");
|
|
13969
|
-
setTimeout(() => onComplete(null),
|
|
14529
|
+
setTimeout(() => onComplete(null), DISPLAY_DELAY_MS);
|
|
13970
14530
|
}
|
|
13971
14531
|
};
|
|
13972
14532
|
fetch2();
|
|
13973
14533
|
}, [repository, id, include, onComplete]);
|
|
13974
|
-
|
|
14534
|
+
useEffect11(() => {
|
|
13975
14535
|
if (phase !== "polling") return;
|
|
13976
14536
|
timerRef.current = setInterval(() => {
|
|
13977
14537
|
const secs = Math.floor((Date.now() - startTimeRef.current) / 1e3);
|
|
@@ -13983,7 +14543,7 @@ var RetrieveSpendRequest = ({
|
|
|
13983
14543
|
if (pollRef.current) clearInterval(pollRef.current);
|
|
13984
14544
|
if (timerRef.current) clearInterval(timerRef.current);
|
|
13985
14545
|
setPhase("timeout");
|
|
13986
|
-
setTimeout(() => onComplete(requestRef.current),
|
|
14546
|
+
setTimeout(() => onComplete(requestRef.current), DISPLAY_DELAY_MS);
|
|
13987
14547
|
return;
|
|
13988
14548
|
}
|
|
13989
14549
|
try {
|
|
@@ -13995,12 +14555,17 @@ var RetrieveSpendRequest = ({
|
|
|
13995
14555
|
if (pollRef.current) clearInterval(pollRef.current);
|
|
13996
14556
|
if (timerRef.current) clearInterval(timerRef.current);
|
|
13997
14557
|
setPhase("success");
|
|
13998
|
-
setTimeout(() => onComplete(result),
|
|
14558
|
+
setTimeout(() => onComplete(result), DISPLAY_DELAY_MS);
|
|
13999
14559
|
} else if (result.status === "denied") {
|
|
14000
14560
|
if (pollRef.current) clearInterval(pollRef.current);
|
|
14001
14561
|
if (timerRef.current) clearInterval(timerRef.current);
|
|
14002
14562
|
setPhase("declined");
|
|
14003
|
-
setTimeout(() => onComplete(result),
|
|
14563
|
+
setTimeout(() => onComplete(result), DISPLAY_DELAY_MS);
|
|
14564
|
+
} else if (TERMINAL_STATUSES.has(result.status)) {
|
|
14565
|
+
if (pollRef.current) clearInterval(pollRef.current);
|
|
14566
|
+
if (timerRef.current) clearInterval(timerRef.current);
|
|
14567
|
+
setPhase("finalized");
|
|
14568
|
+
setTimeout(() => onComplete(result), DISPLAY_DELAY_MS);
|
|
14004
14569
|
}
|
|
14005
14570
|
} catch {
|
|
14006
14571
|
}
|
|
@@ -14011,163 +14576,181 @@ var RetrieveSpendRequest = ({
|
|
|
14011
14576
|
};
|
|
14012
14577
|
}, [phase, repository, id, include, timeout, onComplete]);
|
|
14013
14578
|
if (phase === "fetching") {
|
|
14014
|
-
return /* @__PURE__ */
|
|
14015
|
-
/* @__PURE__ */
|
|
14579
|
+
return /* @__PURE__ */ jsx25(Box18, { children: /* @__PURE__ */ jsxs18(Text19, { color: "cyan", children: [
|
|
14580
|
+
/* @__PURE__ */ jsx25(Spinner10, { type: "dots" }),
|
|
14016
14581
|
" Retrieving spend request ",
|
|
14017
14582
|
id,
|
|
14018
14583
|
"..."
|
|
14019
14584
|
] }) });
|
|
14020
14585
|
}
|
|
14021
14586
|
if (phase === "error") {
|
|
14022
|
-
return /* @__PURE__ */
|
|
14587
|
+
return /* @__PURE__ */ jsx25(Box18, { flexDirection: "column", children: /* @__PURE__ */ jsxs18(Text19, { color: "red", children: [
|
|
14023
14588
|
"\u2717 ",
|
|
14024
14589
|
error
|
|
14025
14590
|
] }) });
|
|
14026
14591
|
}
|
|
14027
14592
|
if (phase === "timeout") {
|
|
14028
|
-
return /* @__PURE__ */
|
|
14029
|
-
/* @__PURE__ */
|
|
14593
|
+
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
|
|
14594
|
+
/* @__PURE__ */ jsxs18(Text19, { color: "yellow", children: [
|
|
14030
14595
|
"\u2717 Timed out waiting for approval after ",
|
|
14031
14596
|
timeout,
|
|
14032
14597
|
"s"
|
|
14033
14598
|
] }),
|
|
14034
|
-
request && /* @__PURE__ */
|
|
14035
|
-
/* @__PURE__ */
|
|
14599
|
+
request && /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
|
|
14600
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14036
14601
|
"ID: ",
|
|
14037
|
-
/* @__PURE__ */
|
|
14602
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: request.id })
|
|
14038
14603
|
] }),
|
|
14039
|
-
/* @__PURE__ */
|
|
14604
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14040
14605
|
"Status: ",
|
|
14041
|
-
/* @__PURE__ */
|
|
14606
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: request.status })
|
|
14042
14607
|
] })
|
|
14043
14608
|
] })
|
|
14044
14609
|
] });
|
|
14045
14610
|
}
|
|
14046
14611
|
if (phase === "polling") {
|
|
14047
|
-
return /* @__PURE__ */
|
|
14048
|
-
/* @__PURE__ */
|
|
14049
|
-
/* @__PURE__ */
|
|
14612
|
+
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
|
|
14613
|
+
/* @__PURE__ */ jsx25(Box18, { children: /* @__PURE__ */ jsxs18(Text19, { color: "cyan", children: [
|
|
14614
|
+
/* @__PURE__ */ jsx25(Spinner10, { type: "dots" }),
|
|
14050
14615
|
" Awaiting approval... (",
|
|
14051
14616
|
elapsed,
|
|
14052
14617
|
"s elapsed)"
|
|
14053
14618
|
] }) }),
|
|
14054
|
-
request?.approval_url && /* @__PURE__ */
|
|
14619
|
+
request?.approval_url && /* @__PURE__ */ jsx25(Box18, { marginTop: 1, paddingX: 2, children: /* @__PURE__ */ jsxs18(Text19, { dimColor: true, children: [
|
|
14055
14620
|
"Approval URL: ",
|
|
14056
|
-
/* @__PURE__ */
|
|
14621
|
+
/* @__PURE__ */ jsx25(Text19, { color: "cyan", children: request.approval_url })
|
|
14057
14622
|
] }) })
|
|
14058
14623
|
] });
|
|
14059
14624
|
}
|
|
14625
|
+
if (phase === "finalized") {
|
|
14626
|
+
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
|
|
14627
|
+
/* @__PURE__ */ jsxs18(Text19, { color: "yellow", children: [
|
|
14628
|
+
"Spend request reached terminal status: ",
|
|
14629
|
+
request?.status
|
|
14630
|
+
] }),
|
|
14631
|
+
/* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
|
|
14632
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14633
|
+
"ID: ",
|
|
14634
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: request?.id })
|
|
14635
|
+
] }),
|
|
14636
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14637
|
+
"Status: ",
|
|
14638
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: request?.status })
|
|
14639
|
+
] })
|
|
14640
|
+
] })
|
|
14641
|
+
] });
|
|
14642
|
+
}
|
|
14060
14643
|
if (phase === "declined") {
|
|
14061
|
-
return /* @__PURE__ */
|
|
14062
|
-
/* @__PURE__ */
|
|
14063
|
-
/* @__PURE__ */
|
|
14064
|
-
/* @__PURE__ */
|
|
14644
|
+
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
|
|
14645
|
+
/* @__PURE__ */ jsx25(Text19, { color: "red", children: "\u2717 Spend request declined" }),
|
|
14646
|
+
/* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
|
|
14647
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14065
14648
|
"ID: ",
|
|
14066
|
-
/* @__PURE__ */
|
|
14649
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: request?.id })
|
|
14067
14650
|
] }),
|
|
14068
|
-
/* @__PURE__ */
|
|
14651
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14069
14652
|
"Status:",
|
|
14070
14653
|
" ",
|
|
14071
|
-
/* @__PURE__ */
|
|
14654
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, color: "red", children: request?.status })
|
|
14072
14655
|
] }),
|
|
14073
|
-
/* @__PURE__ */
|
|
14656
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14074
14657
|
"Amount:",
|
|
14075
14658
|
" ",
|
|
14076
|
-
/* @__PURE__ */
|
|
14659
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: request?.amount != null ? String(request.amount) : "N/A" })
|
|
14077
14660
|
] }),
|
|
14078
|
-
/* @__PURE__ */
|
|
14661
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14079
14662
|
"Merchant: ",
|
|
14080
|
-
/* @__PURE__ */
|
|
14663
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: request?.merchant_name })
|
|
14081
14664
|
] })
|
|
14082
14665
|
] })
|
|
14083
14666
|
] });
|
|
14084
14667
|
}
|
|
14085
|
-
return /* @__PURE__ */
|
|
14086
|
-
/* @__PURE__ */
|
|
14087
|
-
/* @__PURE__ */
|
|
14088
|
-
/* @__PURE__ */
|
|
14668
|
+
return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
|
|
14669
|
+
/* @__PURE__ */ jsx25(Text19, { color: "green", children: "\u2713 Spend request approved" }),
|
|
14670
|
+
/* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
|
|
14671
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14089
14672
|
"ID: ",
|
|
14090
|
-
/* @__PURE__ */
|
|
14673
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: request?.id })
|
|
14091
14674
|
] }),
|
|
14092
|
-
/* @__PURE__ */
|
|
14675
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14093
14676
|
"Status:",
|
|
14094
14677
|
" ",
|
|
14095
|
-
/* @__PURE__ */
|
|
14678
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, color: "green", children: request?.status })
|
|
14096
14679
|
] }),
|
|
14097
|
-
/* @__PURE__ */
|
|
14680
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14098
14681
|
"Amount:",
|
|
14099
14682
|
" ",
|
|
14100
|
-
/* @__PURE__ */
|
|
14683
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: request?.amount != null ? String(request.amount) : "N/A" })
|
|
14101
14684
|
] }),
|
|
14102
|
-
/* @__PURE__ */
|
|
14685
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14103
14686
|
"Merchant: ",
|
|
14104
|
-
/* @__PURE__ */
|
|
14687
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: request?.merchant_name })
|
|
14105
14688
|
] }),
|
|
14106
|
-
/* @__PURE__ */
|
|
14689
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14107
14690
|
"Line Items:",
|
|
14108
14691
|
" ",
|
|
14109
|
-
/* @__PURE__ */
|
|
14692
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: request?.line_items.map((li) => li.name).join(", ") })
|
|
14110
14693
|
] }),
|
|
14111
|
-
request?.shared_payment_token && /* @__PURE__ */
|
|
14112
|
-
/* @__PURE__ */
|
|
14694
|
+
request?.shared_payment_token && /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginTop: 1, children: [
|
|
14695
|
+
/* @__PURE__ */ jsxs18(Text19, { bold: true, children: [
|
|
14113
14696
|
"\x1B]8;;https://docs.stripe.com/agentic-commerce/concepts/shared-payment-tokens\x07",
|
|
14114
14697
|
"Shared Payment Token",
|
|
14115
14698
|
"\x1B]8;;\x07",
|
|
14116
14699
|
":"
|
|
14117
14700
|
] }),
|
|
14118
|
-
/* @__PURE__ */
|
|
14701
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14119
14702
|
" ",
|
|
14120
14703
|
"Token: ",
|
|
14121
|
-
/* @__PURE__ */
|
|
14704
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: request.shared_payment_token.id })
|
|
14122
14705
|
] })
|
|
14123
14706
|
] }),
|
|
14124
|
-
request?.card && /* @__PURE__ */
|
|
14125
|
-
/* @__PURE__ */
|
|
14126
|
-
/* @__PURE__ */
|
|
14707
|
+
request?.card && !outputFile && /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginTop: 1, children: [
|
|
14708
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: "Card Details:" }),
|
|
14709
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14127
14710
|
" ",
|
|
14128
14711
|
"Number: ",
|
|
14129
|
-
/* @__PURE__ */
|
|
14712
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: request?.card.number })
|
|
14130
14713
|
] }),
|
|
14131
|
-
/* @__PURE__ */
|
|
14714
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14132
14715
|
" ",
|
|
14133
14716
|
"Brand: ",
|
|
14134
|
-
/* @__PURE__ */
|
|
14717
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: request?.card.brand })
|
|
14135
14718
|
] }),
|
|
14136
|
-
/* @__PURE__ */
|
|
14719
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14137
14720
|
" ",
|
|
14138
14721
|
"Expiry:",
|
|
14139
14722
|
" ",
|
|
14140
|
-
/* @__PURE__ */
|
|
14723
|
+
/* @__PURE__ */ jsxs18(Text19, { bold: true, children: [
|
|
14141
14724
|
String(request?.card.exp_month).padStart(2, "0"),
|
|
14142
14725
|
"/",
|
|
14143
14726
|
request?.card.exp_year
|
|
14144
14727
|
] })
|
|
14145
14728
|
] }),
|
|
14146
|
-
request?.card.cvc && /* @__PURE__ */
|
|
14729
|
+
request?.card.cvc && /* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14147
14730
|
" ",
|
|
14148
14731
|
"CVC: ",
|
|
14149
|
-
/* @__PURE__ */
|
|
14732
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: request.card.cvc })
|
|
14150
14733
|
] }),
|
|
14151
|
-
request?.card.valid_until && /* @__PURE__ */
|
|
14734
|
+
request?.card.valid_until && /* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14152
14735
|
" ",
|
|
14153
14736
|
"Valid Until: ",
|
|
14154
|
-
/* @__PURE__ */
|
|
14737
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: request.card.valid_until })
|
|
14155
14738
|
] }),
|
|
14156
|
-
request?.card.billing_address && /* @__PURE__ */
|
|
14157
|
-
/* @__PURE__ */
|
|
14158
|
-
/* @__PURE__ */
|
|
14739
|
+
request?.card.billing_address && /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginTop: 1, children: [
|
|
14740
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: " Billing Address:" }),
|
|
14741
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14159
14742
|
" ",
|
|
14160
14743
|
request.card.billing_address.name
|
|
14161
14744
|
] }),
|
|
14162
|
-
/* @__PURE__ */
|
|
14745
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14163
14746
|
" ",
|
|
14164
14747
|
request.card.billing_address.line1
|
|
14165
14748
|
] }),
|
|
14166
|
-
request.card.billing_address.line2 && /* @__PURE__ */
|
|
14749
|
+
request.card.billing_address.line2 && /* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14167
14750
|
" ",
|
|
14168
14751
|
request.card.billing_address.line2
|
|
14169
14752
|
] }),
|
|
14170
|
-
/* @__PURE__ */
|
|
14753
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14171
14754
|
" ",
|
|
14172
14755
|
[
|
|
14173
14756
|
request.card.billing_address.city,
|
|
@@ -14175,11 +14758,21 @@ var RetrieveSpendRequest = ({
|
|
|
14175
14758
|
request.card.billing_address.postal_code
|
|
14176
14759
|
].filter(Boolean).join(", ")
|
|
14177
14760
|
] }),
|
|
14178
|
-
/* @__PURE__ */
|
|
14761
|
+
/* @__PURE__ */ jsxs18(Text19, { children: [
|
|
14179
14762
|
" ",
|
|
14180
14763
|
request.card.billing_address.country
|
|
14181
14764
|
] })
|
|
14182
14765
|
] })
|
|
14766
|
+
] }),
|
|
14767
|
+
request?.card && outputFile && /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginTop: 1, children: [
|
|
14768
|
+
outputFilePath && /* @__PURE__ */ jsxs18(Text19, { color: "green", children: [
|
|
14769
|
+
"Card credentials written to ",
|
|
14770
|
+
/* @__PURE__ */ jsx25(Text19, { bold: true, children: outputFilePath })
|
|
14771
|
+
] }),
|
|
14772
|
+
fileError && /* @__PURE__ */ jsxs18(Text19, { color: "red", children: [
|
|
14773
|
+
"Failed to write card file: ",
|
|
14774
|
+
fileError
|
|
14775
|
+
] })
|
|
14183
14776
|
] })
|
|
14184
14777
|
] })
|
|
14185
14778
|
] });
|
|
@@ -14210,16 +14803,20 @@ var createOptions = z6.object({
|
|
|
14210
14803
|
'Line item (repeatable, key:value format). Keys: name (required), quantity, unit_amount, description, sku, url, image_url, product_url. Example: "name:Shoes,unit_amount:5000,quantity:2"'
|
|
14211
14804
|
),
|
|
14212
14805
|
total: z6.array(z6.union([z6.string(), z6.record(z6.string(), z6.unknown())])).default([]).describe(
|
|
14213
|
-
'Total (repeatable, key:value format). Keys: type (required), display_text (required), amount (required). Example: "type:total,display_text:Total,amount:5000"'
|
|
14806
|
+
'Total (repeatable, key:value format). Keys: type (required; one of: subtotal, tax, total, items_base_amount, items_discount, discount, fulfillment, shipping, fee, gift_wrap, tip, store_credit), display_text (required), amount (required). Example: "type:total,display_text:Total,amount:5000"'
|
|
14214
14807
|
),
|
|
14215
14808
|
requestApproval: z6.boolean().default(true).describe("Request approval and poll until approved/denied/expired"),
|
|
14216
14809
|
test: z6.boolean().default(false).describe(
|
|
14217
14810
|
"Use test mode (creates testmode credentials from test card data)"
|
|
14218
|
-
)
|
|
14811
|
+
),
|
|
14812
|
+
outputFile: z6.string().optional().describe(
|
|
14813
|
+
"Write full card credentials to this file path; stdout shows redacted card data only"
|
|
14814
|
+
),
|
|
14815
|
+
force: z6.boolean().default(false).describe("Overwrite output file if it already exists")
|
|
14219
14816
|
});
|
|
14220
14817
|
var retrieveOptions = z6.object({
|
|
14221
|
-
timeout: z6.coerce.number().default(
|
|
14222
|
-
"Polling timeout in seconds. When reached during active polling, exits non-zero with POLLING_TIMEOUT."
|
|
14818
|
+
timeout: z6.coerce.number().default(600).describe(
|
|
14819
|
+
"Polling timeout in seconds. When reached during active polling, exits non-zero with POLLING_TIMEOUT. Default exceeds the server-side spend-request expiry so polling outlives the request itself."
|
|
14223
14820
|
),
|
|
14224
14821
|
interval: z6.coerce.number().default(0).describe(
|
|
14225
14822
|
"Poll interval in seconds. When > 0, polls until status is terminal, timeout is reached, or max attempts are exhausted."
|
|
@@ -14227,7 +14824,11 @@ var retrieveOptions = z6.object({
|
|
|
14227
14824
|
maxAttempts: z6.coerce.number().default(0).describe(
|
|
14228
14825
|
"Max poll attempts. 0 = unlimited. Exhaustion during active polling exits non-zero with POLLING_TIMEOUT."
|
|
14229
14826
|
),
|
|
14230
|
-
include: z6.array(z6.string()).default([]).describe("Include extra data (repeatable, e.g. --include card)")
|
|
14827
|
+
include: z6.array(z6.string()).default([]).describe("Include extra data (repeatable, e.g. --include card)"),
|
|
14828
|
+
outputFile: z6.string().optional().describe(
|
|
14829
|
+
"Write full card credentials to this file path; stdout shows redacted card data only"
|
|
14830
|
+
),
|
|
14831
|
+
force: z6.boolean().default(false).describe("Overwrite output file if it already exists")
|
|
14231
14832
|
});
|
|
14232
14833
|
var updateOptions = z6.object({
|
|
14233
14834
|
paymentMethodId: z6.string().optional().describe("Payment method ID"),
|
|
@@ -14240,91 +14841,93 @@ var updateOptions = z6.object({
|
|
|
14240
14841
|
'Line item (repeatable, key:value format). Keys: name (required), quantity, unit_amount, description, sku, url, image_url, product_url. Example: "name:Shoes,unit_amount:5000,quantity:2"'
|
|
14241
14842
|
),
|
|
14242
14843
|
total: z6.array(z6.union([z6.string(), z6.record(z6.string(), z6.unknown())])).default([]).describe(
|
|
14243
|
-
'Total (repeatable, key:value format). Keys: type (required), display_text (required), amount (required). Example: "type:total,display_text:Total,amount:5000"'
|
|
14844
|
+
'Total (repeatable, key:value format). Keys: type (required; one of: subtotal, tax, total, items_base_amount, items_discount, discount, fulfillment, shipping, fee, gift_wrap, tip, store_credit), display_text (required), amount (required). Example: "type:total,display_text:Total,amount:5000"'
|
|
14244
14845
|
)
|
|
14245
14846
|
});
|
|
14246
14847
|
|
|
14247
14848
|
// src/commands/spend-request/update.tsx
|
|
14248
|
-
import { Box as
|
|
14249
|
-
import
|
|
14250
|
-
import {
|
|
14251
|
-
import { jsx as
|
|
14849
|
+
import { Box as Box19, Text as Text20 } from "ink";
|
|
14850
|
+
import Spinner11 from "ink-spinner";
|
|
14851
|
+
import { useCallback as useCallback8 } from "react";
|
|
14852
|
+
import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
14252
14853
|
var UpdateSpendRequest = ({
|
|
14253
14854
|
repository,
|
|
14254
14855
|
id,
|
|
14255
14856
|
params,
|
|
14256
14857
|
onComplete
|
|
14257
14858
|
}) => {
|
|
14258
|
-
const
|
|
14259
|
-
|
|
14859
|
+
const action = useCallback8(
|
|
14860
|
+
() => repository.updateSpendRequest(id, params),
|
|
14861
|
+
[repository, id, params]
|
|
14260
14862
|
);
|
|
14261
|
-
const
|
|
14262
|
-
const [error, setError] = useState13("");
|
|
14263
|
-
useEffect13(() => {
|
|
14264
|
-
const update = async () => {
|
|
14265
|
-
try {
|
|
14266
|
-
const result = await repository.updateSpendRequest(id, params);
|
|
14267
|
-
setRequest(result);
|
|
14268
|
-
setStatus("success");
|
|
14269
|
-
setTimeout(() => onComplete(result), 1500);
|
|
14270
|
-
} catch (err) {
|
|
14271
|
-
setError(err.message);
|
|
14272
|
-
setStatus("error");
|
|
14273
|
-
setTimeout(() => onComplete(null), 1500);
|
|
14274
|
-
}
|
|
14275
|
-
};
|
|
14276
|
-
update();
|
|
14277
|
-
}, [repository, id, params, onComplete]);
|
|
14863
|
+
const { status, data: request, error } = useAsyncAction(action, onComplete);
|
|
14278
14864
|
if (status === "loading") {
|
|
14279
|
-
return /* @__PURE__ */
|
|
14280
|
-
/* @__PURE__ */
|
|
14865
|
+
return /* @__PURE__ */ jsx26(Box19, { children: /* @__PURE__ */ jsxs19(Text20, { color: "cyan", children: [
|
|
14866
|
+
/* @__PURE__ */ jsx26(Spinner11, { type: "dots" }),
|
|
14281
14867
|
" Updating spend request ",
|
|
14282
14868
|
id,
|
|
14283
14869
|
"..."
|
|
14284
14870
|
] }) });
|
|
14285
14871
|
}
|
|
14286
14872
|
if (status === "error") {
|
|
14287
|
-
return /* @__PURE__ */
|
|
14288
|
-
/* @__PURE__ */
|
|
14289
|
-
/* @__PURE__ */
|
|
14873
|
+
return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
|
|
14874
|
+
/* @__PURE__ */ jsx26(Text20, { color: "red", children: "\u2717 Failed to update spend request" }),
|
|
14875
|
+
/* @__PURE__ */ jsx26(Text20, { color: "red", children: error })
|
|
14290
14876
|
] });
|
|
14291
14877
|
}
|
|
14292
|
-
return /* @__PURE__ */
|
|
14293
|
-
/* @__PURE__ */
|
|
14294
|
-
/* @__PURE__ */
|
|
14295
|
-
/* @__PURE__ */
|
|
14878
|
+
return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
|
|
14879
|
+
/* @__PURE__ */ jsx26(Text20, { color: "green", children: "\u2713 Spend request updated" }),
|
|
14880
|
+
/* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
|
|
14881
|
+
/* @__PURE__ */ jsxs19(Text20, { children: [
|
|
14296
14882
|
"ID: ",
|
|
14297
|
-
/* @__PURE__ */
|
|
14883
|
+
/* @__PURE__ */ jsx26(Text20, { bold: true, children: request?.id })
|
|
14298
14884
|
] }),
|
|
14299
|
-
/* @__PURE__ */
|
|
14885
|
+
/* @__PURE__ */ jsxs19(Text20, { children: [
|
|
14300
14886
|
"Status: ",
|
|
14301
|
-
/* @__PURE__ */
|
|
14887
|
+
/* @__PURE__ */ jsx26(Text20, { bold: true, children: request?.status })
|
|
14302
14888
|
] }),
|
|
14303
|
-
/* @__PURE__ */
|
|
14889
|
+
/* @__PURE__ */ jsxs19(Text20, { children: [
|
|
14304
14890
|
"Amount:",
|
|
14305
14891
|
" ",
|
|
14306
|
-
/* @__PURE__ */
|
|
14892
|
+
/* @__PURE__ */ jsx26(Text20, { bold: true, children: (() => {
|
|
14307
14893
|
const t = request?.totals.find((t2) => t2.type === "total");
|
|
14308
14894
|
return t ? String(t.amount) : "N/A";
|
|
14309
14895
|
})() })
|
|
14310
14896
|
] }),
|
|
14311
|
-
/* @__PURE__ */
|
|
14897
|
+
/* @__PURE__ */ jsxs19(Text20, { children: [
|
|
14312
14898
|
"Merchant: ",
|
|
14313
|
-
/* @__PURE__ */
|
|
14899
|
+
/* @__PURE__ */ jsx26(Text20, { bold: true, children: request?.merchant_name })
|
|
14314
14900
|
] }),
|
|
14315
|
-
/* @__PURE__ */
|
|
14901
|
+
/* @__PURE__ */ jsxs19(Text20, { children: [
|
|
14316
14902
|
"Line Items:",
|
|
14317
14903
|
" ",
|
|
14318
|
-
/* @__PURE__ */
|
|
14904
|
+
/* @__PURE__ */ jsx26(Text20, { bold: true, children: request?.line_items.map((li) => li.name).join(", ") })
|
|
14319
14905
|
] })
|
|
14320
14906
|
] })
|
|
14321
14907
|
] });
|
|
14322
14908
|
};
|
|
14323
14909
|
|
|
14324
14910
|
// src/commands/spend-request/index.tsx
|
|
14325
|
-
import { jsx as
|
|
14326
|
-
function
|
|
14327
|
-
|
|
14911
|
+
import { jsx as jsx27 } from "react/jsx-runtime";
|
|
14912
|
+
async function applyOutputFile(request, outputFile, force) {
|
|
14913
|
+
if (!outputFile || !request.card) return request;
|
|
14914
|
+
const fileData = {
|
|
14915
|
+
spend_request_id: request.id,
|
|
14916
|
+
merchant_name: request.merchant_name,
|
|
14917
|
+
merchant_url: request.merchant_url,
|
|
14918
|
+
context: request.context,
|
|
14919
|
+
created_at: request.created_at,
|
|
14920
|
+
card: request.card
|
|
14921
|
+
};
|
|
14922
|
+
const resolvedPath = await writeCredentialFile(outputFile, fileData, force);
|
|
14923
|
+
const { card: _, ...withoutCard } = request;
|
|
14924
|
+
return {
|
|
14925
|
+
...withoutCard,
|
|
14926
|
+
card_output_file: resolvedPath
|
|
14927
|
+
};
|
|
14928
|
+
}
|
|
14929
|
+
function createSpendRequestCli(repository, authStorage2) {
|
|
14930
|
+
const cli2 = Cli7.create("spend-request", {
|
|
14328
14931
|
description: "Spend request management commands"
|
|
14329
14932
|
});
|
|
14330
14933
|
cli2.command("create", {
|
|
@@ -14333,17 +14936,7 @@ function createSpendRequestCli(repository) {
|
|
|
14333
14936
|
alias: { merchantName: "m" },
|
|
14334
14937
|
outputPolicy: "agent-only",
|
|
14335
14938
|
async *run(c) {
|
|
14336
|
-
|
|
14337
|
-
return c.error({
|
|
14338
|
-
code: "NOT_AUTHENTICATED",
|
|
14339
|
-
message: 'Not authenticated. Run "link-cli auth login" first.',
|
|
14340
|
-
cta: {
|
|
14341
|
-
commands: [
|
|
14342
|
-
{ command: "auth login", description: "Log in to Link" }
|
|
14343
|
-
]
|
|
14344
|
-
}
|
|
14345
|
-
});
|
|
14346
|
-
}
|
|
14939
|
+
requireAuthGuard(c, authStorage2);
|
|
14347
14940
|
const opts = c.options;
|
|
14348
14941
|
const requestApproval = !!opts.requestApproval;
|
|
14349
14942
|
const credentialType = opts.credentialType;
|
|
@@ -14400,37 +14993,49 @@ function createSpendRequestCli(repository) {
|
|
|
14400
14993
|
request_approval: requestApproval || void 0,
|
|
14401
14994
|
test: opts.test ? true : void 0
|
|
14402
14995
|
};
|
|
14996
|
+
const outputFile = opts.outputFile;
|
|
14997
|
+
const forceOverwrite = opts.force;
|
|
14403
14998
|
if (!c.agent && !c.formatExplicit) {
|
|
14404
|
-
|
|
14405
|
-
|
|
14406
|
-
|
|
14407
|
-
|
|
14408
|
-
|
|
14409
|
-
|
|
14410
|
-
|
|
14411
|
-
|
|
14412
|
-
|
|
14413
|
-
|
|
14414
|
-
|
|
14415
|
-
|
|
14999
|
+
let capturedResult = null;
|
|
15000
|
+
return renderInteractive(
|
|
15001
|
+
/* @__PURE__ */ jsx27(
|
|
15002
|
+
CreateSpendRequest,
|
|
15003
|
+
{
|
|
15004
|
+
repository,
|
|
15005
|
+
params: createParams,
|
|
15006
|
+
requestApproval,
|
|
15007
|
+
outputFile,
|
|
15008
|
+
force: forceOverwrite,
|
|
15009
|
+
onComplete: (result) => {
|
|
15010
|
+
capturedResult = result;
|
|
14416
15011
|
}
|
|
14417
|
-
|
|
14418
|
-
)
|
|
14419
|
-
|
|
14420
|
-
|
|
14421
|
-
|
|
14422
|
-
|
|
15012
|
+
}
|
|
15013
|
+
),
|
|
15014
|
+
() => {
|
|
15015
|
+
if (!capturedResult)
|
|
15016
|
+
throw new Error("Component exited without producing a result");
|
|
15017
|
+
return capturedResult;
|
|
15018
|
+
}
|
|
15019
|
+
);
|
|
14423
15020
|
}
|
|
14424
15021
|
const created = await repository.createSpendRequest(createParams);
|
|
14425
15022
|
if (!requestApproval) {
|
|
14426
|
-
|
|
15023
|
+
try {
|
|
15024
|
+
yield await applyOutputFile(created, outputFile, forceOverwrite);
|
|
15025
|
+
} catch (err) {
|
|
15026
|
+
const message = err.message;
|
|
15027
|
+
if (message.startsWith("OUTPUT_FILE_EXISTS")) {
|
|
15028
|
+
return c.error({ code: "OUTPUT_FILE_EXISTS", message });
|
|
15029
|
+
}
|
|
15030
|
+
return c.error({ code: "OUTPUT_FILE_WRITE_ERROR", message });
|
|
15031
|
+
}
|
|
14427
15032
|
return;
|
|
14428
15033
|
}
|
|
14429
15034
|
yield {
|
|
14430
15035
|
...created,
|
|
14431
|
-
instruction: `Present the approval_url to the user and ask them to approve in the Link app. Then call \`spend-request retrieve ${created.id} --interval 2 --max-attempts
|
|
15036
|
+
instruction: `Present the approval_url to the user and ask them to approve in the Link app. Then call \`spend-request retrieve ${created.id} --interval 2 --max-attempts 300\` to poll until approved. Do not wait for the user to reply \u2014 start polling immediately.`,
|
|
14432
15037
|
_next: {
|
|
14433
|
-
command: `spend-request retrieve ${created.id} --interval 2 --max-attempts
|
|
15038
|
+
command: `spend-request retrieve ${created.id} --interval 2 --max-attempts 300`,
|
|
14434
15039
|
until: "status changes from pending_approval"
|
|
14435
15040
|
}
|
|
14436
15041
|
};
|
|
@@ -14443,18 +15048,8 @@ function createSpendRequestCli(repository) {
|
|
|
14443
15048
|
}),
|
|
14444
15049
|
options: updateOptions,
|
|
14445
15050
|
outputPolicy: "agent-only",
|
|
15051
|
+
middleware: [requireAuth(authStorage2)],
|
|
14446
15052
|
async run(c) {
|
|
14447
|
-
if (!storage.isAuthenticated()) {
|
|
14448
|
-
return c.error({
|
|
14449
|
-
code: "NOT_AUTHENTICATED",
|
|
14450
|
-
message: 'Not authenticated. Run "link-cli auth login" first.',
|
|
14451
|
-
cta: {
|
|
14452
|
-
commands: [
|
|
14453
|
-
{ command: "auth login", description: "Log in to Link" }
|
|
14454
|
-
]
|
|
14455
|
-
}
|
|
14456
|
-
});
|
|
14457
|
-
}
|
|
14458
15053
|
const id = c.args.id;
|
|
14459
15054
|
const opts = c.options;
|
|
14460
15055
|
const params = {};
|
|
@@ -14475,25 +15070,25 @@ function createSpendRequestCli(repository) {
|
|
|
14475
15070
|
(item) => typeof item === "string" ? parseTotalFlag(item) : item
|
|
14476
15071
|
);
|
|
14477
15072
|
if (!c.agent && !c.formatExplicit) {
|
|
14478
|
-
|
|
14479
|
-
|
|
14480
|
-
|
|
14481
|
-
|
|
14482
|
-
|
|
14483
|
-
|
|
14484
|
-
|
|
14485
|
-
|
|
14486
|
-
|
|
14487
|
-
|
|
14488
|
-
capturedResult = result;
|
|
14489
|
-
}
|
|
15073
|
+
let capturedResult = null;
|
|
15074
|
+
return renderInteractive(
|
|
15075
|
+
/* @__PURE__ */ jsx27(
|
|
15076
|
+
UpdateSpendRequest,
|
|
15077
|
+
{
|
|
15078
|
+
repository,
|
|
15079
|
+
id,
|
|
15080
|
+
params,
|
|
15081
|
+
onComplete: (result) => {
|
|
15082
|
+
capturedResult = result;
|
|
14490
15083
|
}
|
|
14491
|
-
|
|
14492
|
-
)
|
|
14493
|
-
|
|
14494
|
-
|
|
14495
|
-
|
|
14496
|
-
|
|
15084
|
+
}
|
|
15085
|
+
),
|
|
15086
|
+
() => {
|
|
15087
|
+
if (!capturedResult)
|
|
15088
|
+
throw new Error("Component exited without producing a result");
|
|
15089
|
+
return capturedResult;
|
|
15090
|
+
}
|
|
15091
|
+
);
|
|
14497
15092
|
}
|
|
14498
15093
|
return repository.updateSpendRequest(id, params);
|
|
14499
15094
|
}
|
|
@@ -14505,44 +15100,34 @@ function createSpendRequestCli(repository) {
|
|
|
14505
15100
|
}),
|
|
14506
15101
|
outputPolicy: "agent-only",
|
|
14507
15102
|
async *run(c) {
|
|
14508
|
-
|
|
14509
|
-
return c.error({
|
|
14510
|
-
code: "NOT_AUTHENTICATED",
|
|
14511
|
-
message: 'Not authenticated. Run "link-cli auth login" first.',
|
|
14512
|
-
cta: {
|
|
14513
|
-
commands: [
|
|
14514
|
-
{ command: "auth login", description: "Log in to Link" }
|
|
14515
|
-
]
|
|
14516
|
-
}
|
|
14517
|
-
});
|
|
14518
|
-
}
|
|
15103
|
+
requireAuthGuard(c, authStorage2);
|
|
14519
15104
|
const id = c.args.id;
|
|
14520
15105
|
if (!c.agent && !c.formatExplicit) {
|
|
14521
|
-
|
|
14522
|
-
|
|
14523
|
-
|
|
14524
|
-
|
|
14525
|
-
|
|
14526
|
-
|
|
14527
|
-
|
|
14528
|
-
|
|
14529
|
-
|
|
14530
|
-
capturedResult = result;
|
|
14531
|
-
}
|
|
15106
|
+
let capturedResult = null;
|
|
15107
|
+
return renderInteractive(
|
|
15108
|
+
/* @__PURE__ */ jsx27(
|
|
15109
|
+
RequestApproval,
|
|
15110
|
+
{
|
|
15111
|
+
repository,
|
|
15112
|
+
id,
|
|
15113
|
+
onComplete: (result) => {
|
|
15114
|
+
capturedResult = result;
|
|
14532
15115
|
}
|
|
14533
|
-
|
|
14534
|
-
)
|
|
14535
|
-
|
|
14536
|
-
|
|
14537
|
-
|
|
14538
|
-
|
|
15116
|
+
}
|
|
15117
|
+
),
|
|
15118
|
+
() => {
|
|
15119
|
+
if (!capturedResult)
|
|
15120
|
+
throw new Error("Component exited without producing a result");
|
|
15121
|
+
return capturedResult;
|
|
15122
|
+
}
|
|
15123
|
+
);
|
|
14539
15124
|
}
|
|
14540
15125
|
const approval = await repository.requestApproval(id);
|
|
14541
15126
|
yield {
|
|
14542
15127
|
...approval,
|
|
14543
|
-
instruction: `Present the approval_url to the user and ask them to approve in the Link app. Then call \`spend-request retrieve ${id} --interval 2 --max-attempts
|
|
15128
|
+
instruction: `Present the approval_url to the user and ask them to approve in the Link app. Then call \`spend-request retrieve ${id} --interval 2 --max-attempts 300\` to poll until approved. Do not wait for the user to reply \u2014 start polling immediately.`,
|
|
14544
15129
|
_next: {
|
|
14545
|
-
command: `spend-request retrieve ${id} --interval 2 --max-attempts
|
|
15130
|
+
command: `spend-request retrieve ${id} --interval 2 --max-attempts 300`,
|
|
14546
15131
|
until: "status changes from pending_approval"
|
|
14547
15132
|
}
|
|
14548
15133
|
};
|
|
@@ -14556,17 +15141,7 @@ function createSpendRequestCli(repository) {
|
|
|
14556
15141
|
options: retrieveOptions,
|
|
14557
15142
|
outputPolicy: "agent-only",
|
|
14558
15143
|
async *run(c) {
|
|
14559
|
-
|
|
14560
|
-
return c.error({
|
|
14561
|
-
code: "NOT_AUTHENTICATED",
|
|
14562
|
-
message: 'Not authenticated. Run "link-cli auth login" first.',
|
|
14563
|
-
cta: {
|
|
14564
|
-
commands: [
|
|
14565
|
-
{ command: "auth login", description: "Log in to Link" }
|
|
14566
|
-
]
|
|
14567
|
-
}
|
|
14568
|
-
});
|
|
14569
|
-
}
|
|
15144
|
+
requireAuthGuard(c, authStorage2);
|
|
14570
15145
|
const id = c.args.id;
|
|
14571
15146
|
const opts = c.options;
|
|
14572
15147
|
const timeout = opts.timeout;
|
|
@@ -14574,74 +15149,183 @@ function createSpendRequestCli(repository) {
|
|
|
14574
15149
|
const maxAttempts = opts.maxAttempts;
|
|
14575
15150
|
const includeArr = opts.include;
|
|
14576
15151
|
const include = includeArr?.length ? includeArr : void 0;
|
|
15152
|
+
const outputFile = opts.outputFile;
|
|
15153
|
+
const forceOverwrite = opts.force;
|
|
14577
15154
|
if (!c.agent && !c.formatExplicit) {
|
|
14578
|
-
|
|
14579
|
-
|
|
14580
|
-
|
|
14581
|
-
|
|
14582
|
-
|
|
14583
|
-
|
|
14584
|
-
|
|
14585
|
-
|
|
14586
|
-
|
|
14587
|
-
|
|
14588
|
-
|
|
14589
|
-
|
|
14590
|
-
|
|
15155
|
+
let capturedResult = null;
|
|
15156
|
+
return renderInteractive(
|
|
15157
|
+
/* @__PURE__ */ jsx27(
|
|
15158
|
+
RetrieveSpendRequest,
|
|
15159
|
+
{
|
|
15160
|
+
repository,
|
|
15161
|
+
id,
|
|
15162
|
+
timeout,
|
|
15163
|
+
include,
|
|
15164
|
+
outputFile,
|
|
15165
|
+
force: forceOverwrite,
|
|
15166
|
+
onComplete: (result) => {
|
|
15167
|
+
capturedResult = result;
|
|
14591
15168
|
}
|
|
14592
|
-
|
|
14593
|
-
)
|
|
14594
|
-
|
|
14595
|
-
|
|
14596
|
-
|
|
14597
|
-
|
|
15169
|
+
}
|
|
15170
|
+
),
|
|
15171
|
+
() => {
|
|
15172
|
+
if (!capturedResult)
|
|
15173
|
+
throw new Error("Component exited without producing a result");
|
|
15174
|
+
return capturedResult;
|
|
15175
|
+
}
|
|
15176
|
+
);
|
|
14598
15177
|
}
|
|
14599
15178
|
const terminalStatuses = /* @__PURE__ */ new Set([
|
|
14600
15179
|
"approved",
|
|
14601
15180
|
"denied",
|
|
14602
15181
|
"expired",
|
|
14603
15182
|
"succeeded",
|
|
14604
|
-
"failed"
|
|
15183
|
+
"failed",
|
|
15184
|
+
"canceled"
|
|
14605
15185
|
]);
|
|
14606
|
-
|
|
14607
|
-
|
|
14608
|
-
|
|
14609
|
-
|
|
14610
|
-
|
|
14611
|
-
|
|
15186
|
+
for await (const result of pollUntil({
|
|
15187
|
+
fn: () => repository.getSpendRequest(id, { include }),
|
|
15188
|
+
isTerminal: (req) => req === null || terminalStatuses.has(req.status),
|
|
15189
|
+
interval,
|
|
15190
|
+
maxAttempts,
|
|
15191
|
+
timeout
|
|
15192
|
+
})) {
|
|
15193
|
+
if (result.value === null) {
|
|
14612
15194
|
return c.error({
|
|
14613
15195
|
code: "NOT_FOUND",
|
|
14614
15196
|
message: `Spend request ${id} not found`
|
|
14615
15197
|
});
|
|
14616
15198
|
}
|
|
14617
|
-
if (
|
|
14618
|
-
|
|
14619
|
-
|
|
14620
|
-
|
|
14621
|
-
|
|
14622
|
-
|
|
14623
|
-
|
|
14624
|
-
|
|
14625
|
-
|
|
14626
|
-
|
|
14627
|
-
|
|
14628
|
-
|
|
14629
|
-
|
|
15199
|
+
if (result.terminal) {
|
|
15200
|
+
if (terminalStatuses.has(result.value.status) || !result.reason) {
|
|
15201
|
+
try {
|
|
15202
|
+
yield await applyOutputFile(
|
|
15203
|
+
result.value,
|
|
15204
|
+
outputFile,
|
|
15205
|
+
forceOverwrite
|
|
15206
|
+
);
|
|
15207
|
+
} catch (err) {
|
|
15208
|
+
const message = err.message;
|
|
15209
|
+
if (message.startsWith("OUTPUT_FILE_EXISTS")) {
|
|
15210
|
+
return c.error({ code: "OUTPUT_FILE_EXISTS", message });
|
|
15211
|
+
}
|
|
15212
|
+
return c.error({ code: "OUTPUT_FILE_WRITE_ERROR", message });
|
|
15213
|
+
}
|
|
15214
|
+
return;
|
|
15215
|
+
}
|
|
15216
|
+
const reason = result.reason === "max_attempts" ? `max attempts (${maxAttempts}) exhausted` : `timeout (${timeout}s) reached`;
|
|
14630
15217
|
return c.error({
|
|
14631
15218
|
code: "POLLING_TIMEOUT",
|
|
14632
|
-
message: `Polling stopped before spend request ${id} reached a terminal status: ${reason}; current status is ${
|
|
15219
|
+
message: `Polling stopped before spend request ${id} reached a terminal status: ${reason}; current status is ${result.value.status}.`,
|
|
14633
15220
|
retryable: true
|
|
14634
15221
|
});
|
|
14635
15222
|
}
|
|
14636
|
-
|
|
14637
|
-
if (snapshot !== previousAttemptData) {
|
|
14638
|
-
previousAttemptData = snapshot;
|
|
14639
|
-
yield request;
|
|
14640
|
-
}
|
|
14641
|
-
await new Promise((resolve) => setTimeout(resolve, interval * 1e3));
|
|
15223
|
+
yield result.value;
|
|
14642
15224
|
}
|
|
14643
15225
|
}
|
|
14644
15226
|
});
|
|
15227
|
+
cli2.command("cancel", {
|
|
15228
|
+
description: "Cancel a spend request",
|
|
15229
|
+
args: z7.object({
|
|
15230
|
+
id: z7.string().describe("Spend request ID")
|
|
15231
|
+
}),
|
|
15232
|
+
outputPolicy: "agent-only",
|
|
15233
|
+
middleware: [requireAuth(authStorage2)],
|
|
15234
|
+
async run(c) {
|
|
15235
|
+
const id = c.args.id;
|
|
15236
|
+
if (!c.agent && !c.formatExplicit) {
|
|
15237
|
+
let capturedResult = null;
|
|
15238
|
+
return renderInteractive(
|
|
15239
|
+
/* @__PURE__ */ jsx27(
|
|
15240
|
+
CancelSpendRequest,
|
|
15241
|
+
{
|
|
15242
|
+
repository,
|
|
15243
|
+
id,
|
|
15244
|
+
onComplete: (result) => {
|
|
15245
|
+
capturedResult = result;
|
|
15246
|
+
}
|
|
15247
|
+
}
|
|
15248
|
+
),
|
|
15249
|
+
() => {
|
|
15250
|
+
if (!capturedResult)
|
|
15251
|
+
throw new Error("Component exited without producing a result");
|
|
15252
|
+
return capturedResult;
|
|
15253
|
+
}
|
|
15254
|
+
);
|
|
15255
|
+
}
|
|
15256
|
+
return repository.cancelSpendRequest(id);
|
|
15257
|
+
}
|
|
15258
|
+
});
|
|
15259
|
+
return cli2;
|
|
15260
|
+
}
|
|
15261
|
+
|
|
15262
|
+
// src/commands/user-info/index.tsx
|
|
15263
|
+
import { Cli as Cli8 } from "incur";
|
|
15264
|
+
|
|
15265
|
+
// src/commands/user-info/retrieve.tsx
|
|
15266
|
+
import { Box as Box20, Text as Text21 } from "ink";
|
|
15267
|
+
import Spinner12 from "ink-spinner";
|
|
15268
|
+
import { useCallback as useCallback9 } from "react";
|
|
15269
|
+
import { jsx as jsx28, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
15270
|
+
var UserInfoRetrieve = ({
|
|
15271
|
+
resource,
|
|
15272
|
+
onComplete
|
|
15273
|
+
}) => {
|
|
15274
|
+
const action = useCallback9(() => resource.retrieve(), [resource]);
|
|
15275
|
+
const { status, data: userInfo, error } = useAsyncAction(action, onComplete);
|
|
15276
|
+
if (status === "loading") {
|
|
15277
|
+
return /* @__PURE__ */ jsx28(Box20, { children: /* @__PURE__ */ jsxs20(Text21, { color: "cyan", children: [
|
|
15278
|
+
/* @__PURE__ */ jsx28(Spinner12, { type: "dots" }),
|
|
15279
|
+
" Loading user info..."
|
|
15280
|
+
] }) });
|
|
15281
|
+
}
|
|
15282
|
+
if (status === "error") {
|
|
15283
|
+
return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", children: [
|
|
15284
|
+
/* @__PURE__ */ jsx28(Text21, { color: "red", children: "\u2717 Failed to load user info" }),
|
|
15285
|
+
/* @__PURE__ */ jsx28(Text21, { color: "red", children: error })
|
|
15286
|
+
] });
|
|
15287
|
+
}
|
|
15288
|
+
return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", children: [
|
|
15289
|
+
/* @__PURE__ */ jsx28(Text21, { bold: true, children: "User Info" }),
|
|
15290
|
+
/* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", marginTop: 1, paddingX: 2, children: [
|
|
15291
|
+
/* @__PURE__ */ jsxs20(Text21, { children: [
|
|
15292
|
+
/* @__PURE__ */ jsx28(Text21, { dimColor: true, children: "Email: " }),
|
|
15293
|
+
userInfo?.email ?? /* @__PURE__ */ jsx28(Text21, { dimColor: true, children: "Not set" })
|
|
15294
|
+
] }),
|
|
15295
|
+
/* @__PURE__ */ jsxs20(Text21, { children: [
|
|
15296
|
+
/* @__PURE__ */ jsx28(Text21, { dimColor: true, children: "Name: " }),
|
|
15297
|
+
userInfo?.name ?? /* @__PURE__ */ jsx28(Text21, { dimColor: true, children: "Not set" })
|
|
15298
|
+
] }),
|
|
15299
|
+
/* @__PURE__ */ jsxs20(Text21, { children: [
|
|
15300
|
+
/* @__PURE__ */ jsx28(Text21, { dimColor: true, children: "Phone: " }),
|
|
15301
|
+
userInfo?.phone ?? /* @__PURE__ */ jsx28(Text21, { dimColor: true, children: "Not set" })
|
|
15302
|
+
] })
|
|
15303
|
+
] })
|
|
15304
|
+
] });
|
|
15305
|
+
};
|
|
15306
|
+
|
|
15307
|
+
// src/commands/user-info/index.tsx
|
|
15308
|
+
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
15309
|
+
function createUserInfoCli(createResource, authStorage2) {
|
|
15310
|
+
const cli2 = Cli8.create("user-info", {
|
|
15311
|
+
description: "User information commands"
|
|
15312
|
+
});
|
|
15313
|
+
cli2.command("retrieve", {
|
|
15314
|
+
description: "Retrieve user info (email, name, phone)",
|
|
15315
|
+
outputPolicy: "agent-only",
|
|
15316
|
+
middleware: [requireAuth(authStorage2)],
|
|
15317
|
+
async run(c) {
|
|
15318
|
+
const resource = createResource();
|
|
15319
|
+
if (!c.agent && !c.formatExplicit) {
|
|
15320
|
+
return renderInteractive(
|
|
15321
|
+
/* @__PURE__ */ jsx29(UserInfoRetrieve, { resource, onComplete: () => {
|
|
15322
|
+
} }),
|
|
15323
|
+
() => resource.retrieve()
|
|
15324
|
+
);
|
|
15325
|
+
}
|
|
15326
|
+
return resource.retrieve();
|
|
15327
|
+
}
|
|
15328
|
+
});
|
|
14645
15329
|
return cli2;
|
|
14646
15330
|
}
|
|
14647
15331
|
|
|
@@ -14869,9 +15553,9 @@ ${JSON.stringify(redacted, null, 2)}`
|
|
|
14869
15553
|
|
|
14870
15554
|
// src/auth/session.ts
|
|
14871
15555
|
var EXPIRY_BUFFER_MS = 6e4;
|
|
14872
|
-
function createAccessTokenProvider(authResource,
|
|
15556
|
+
function createAccessTokenProvider(authResource, authStorage2 = storage) {
|
|
14873
15557
|
return async ({ forceRefresh } = {}) => {
|
|
14874
|
-
const auth =
|
|
15558
|
+
const auth = authStorage2.getAuth();
|
|
14875
15559
|
if (!auth) {
|
|
14876
15560
|
throw new LinkAuthenticationError(
|
|
14877
15561
|
'Not authenticated. Run "link-cli auth login" first.'
|
|
@@ -14882,22 +15566,78 @@ function createAccessTokenProvider(authResource, authStorage = storage) {
|
|
|
14882
15566
|
return auth.access_token;
|
|
14883
15567
|
}
|
|
14884
15568
|
const refreshed = await authResource.refreshToken(auth.refresh_token);
|
|
14885
|
-
|
|
15569
|
+
authStorage2.setAuth(refreshed);
|
|
14886
15570
|
return refreshed.access_token;
|
|
14887
15571
|
};
|
|
14888
15572
|
}
|
|
14889
15573
|
|
|
15574
|
+
// src/utils/sanitize-text.ts
|
|
15575
|
+
import stripAnsi from "strip-ansi";
|
|
15576
|
+
var CONTROL_CHAR_RE = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f\r]/g;
|
|
15577
|
+
var NEEDS_SANITIZE_RE = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f\r\x1b]/;
|
|
15578
|
+
function sanitizeText(input) {
|
|
15579
|
+
if (!input) {
|
|
15580
|
+
return "";
|
|
15581
|
+
}
|
|
15582
|
+
if (!NEEDS_SANITIZE_RE.test(input)) {
|
|
15583
|
+
return input;
|
|
15584
|
+
}
|
|
15585
|
+
return stripAnsi(input).replace(CONTROL_CHAR_RE, "");
|
|
15586
|
+
}
|
|
15587
|
+
function sanitizeDeep(value) {
|
|
15588
|
+
if (value === null || value === void 0) {
|
|
15589
|
+
return value;
|
|
15590
|
+
}
|
|
15591
|
+
if (typeof value === "string") {
|
|
15592
|
+
return sanitizeText(value);
|
|
15593
|
+
}
|
|
15594
|
+
if (Array.isArray(value)) {
|
|
15595
|
+
return value.map(sanitizeDeep);
|
|
15596
|
+
}
|
|
15597
|
+
if (typeof value === "object") {
|
|
15598
|
+
const result = {};
|
|
15599
|
+
const keys = Object.keys(value);
|
|
15600
|
+
for (let i = 0; i < keys.length; i++) {
|
|
15601
|
+
const k = keys[i];
|
|
15602
|
+
result[k] = sanitizeDeep(value[k]);
|
|
15603
|
+
}
|
|
15604
|
+
return result;
|
|
15605
|
+
}
|
|
15606
|
+
return value;
|
|
15607
|
+
}
|
|
15608
|
+
|
|
14890
15609
|
// src/utils/resource-factory.ts
|
|
15610
|
+
function sanitizeResource(resource) {
|
|
15611
|
+
return new Proxy(resource, {
|
|
15612
|
+
get(target, prop, receiver) {
|
|
15613
|
+
const value = Reflect.get(target, prop, receiver);
|
|
15614
|
+
if (typeof value !== "function") {
|
|
15615
|
+
return value;
|
|
15616
|
+
}
|
|
15617
|
+
return (...args) => {
|
|
15618
|
+
const result = value.apply(target, args);
|
|
15619
|
+
if (result && typeof result.then === "function") {
|
|
15620
|
+
return result.then(sanitizeDeep);
|
|
15621
|
+
}
|
|
15622
|
+
return result;
|
|
15623
|
+
};
|
|
15624
|
+
}
|
|
15625
|
+
});
|
|
15626
|
+
}
|
|
14891
15627
|
var ResourceFactory = class {
|
|
14892
15628
|
verbose;
|
|
14893
15629
|
defaultHeaders;
|
|
15630
|
+
authStorage;
|
|
14894
15631
|
authResource;
|
|
14895
15632
|
accessTokenProvider;
|
|
14896
15633
|
spendRequestResource;
|
|
14897
15634
|
paymentMethodsResource;
|
|
15635
|
+
shippingAddressResource;
|
|
15636
|
+
userInfoResource;
|
|
14898
15637
|
constructor(options = {}) {
|
|
14899
15638
|
this.verbose = options.verbose ?? false;
|
|
14900
15639
|
this.defaultHeaders = options.defaultHeaders;
|
|
15640
|
+
this.authStorage = options.authStorage;
|
|
14901
15641
|
}
|
|
14902
15642
|
createAuthResource() {
|
|
14903
15643
|
if (this.authResource) {
|
|
@@ -14909,12 +15649,16 @@ var ResourceFactory = class {
|
|
|
14909
15649
|
});
|
|
14910
15650
|
return this.authResource;
|
|
14911
15651
|
}
|
|
15652
|
+
getAuthStorage() {
|
|
15653
|
+
return this.authStorage;
|
|
15654
|
+
}
|
|
14912
15655
|
createSdkAccessTokenProvider() {
|
|
14913
15656
|
if (this.accessTokenProvider) {
|
|
14914
15657
|
return this.accessTokenProvider;
|
|
14915
15658
|
}
|
|
14916
15659
|
this.accessTokenProvider = createAccessTokenProvider(
|
|
14917
|
-
this.createAuthResource()
|
|
15660
|
+
this.createAuthResource(),
|
|
15661
|
+
this.authStorage
|
|
14918
15662
|
);
|
|
14919
15663
|
return this.accessTokenProvider;
|
|
14920
15664
|
}
|
|
@@ -14923,11 +15667,13 @@ var ResourceFactory = class {
|
|
|
14923
15667
|
return this.spendRequestResource;
|
|
14924
15668
|
}
|
|
14925
15669
|
const getAccessToken = this.createSdkAccessTokenProvider();
|
|
14926
|
-
this.spendRequestResource =
|
|
14927
|
-
|
|
14928
|
-
|
|
14929
|
-
|
|
14930
|
-
|
|
15670
|
+
this.spendRequestResource = sanitizeResource(
|
|
15671
|
+
new SpendRequestResource({
|
|
15672
|
+
verbose: this.verbose,
|
|
15673
|
+
defaultHeaders: this.defaultHeaders,
|
|
15674
|
+
getAccessToken
|
|
15675
|
+
})
|
|
15676
|
+
);
|
|
14931
15677
|
return this.spendRequestResource;
|
|
14932
15678
|
}
|
|
14933
15679
|
createPaymentMethodsResource() {
|
|
@@ -14935,17 +15681,117 @@ var ResourceFactory = class {
|
|
|
14935
15681
|
return this.paymentMethodsResource;
|
|
14936
15682
|
}
|
|
14937
15683
|
const getAccessToken = this.createSdkAccessTokenProvider();
|
|
14938
|
-
this.paymentMethodsResource =
|
|
14939
|
-
|
|
14940
|
-
|
|
14941
|
-
|
|
14942
|
-
|
|
15684
|
+
this.paymentMethodsResource = sanitizeResource(
|
|
15685
|
+
new PaymentMethodsResource({
|
|
15686
|
+
verbose: this.verbose,
|
|
15687
|
+
defaultHeaders: this.defaultHeaders,
|
|
15688
|
+
getAccessToken
|
|
15689
|
+
})
|
|
15690
|
+
);
|
|
14943
15691
|
return this.paymentMethodsResource;
|
|
14944
15692
|
}
|
|
15693
|
+
createShippingAddressResource() {
|
|
15694
|
+
if (this.shippingAddressResource) {
|
|
15695
|
+
return this.shippingAddressResource;
|
|
15696
|
+
}
|
|
15697
|
+
const getAccessToken = this.createSdkAccessTokenProvider();
|
|
15698
|
+
this.shippingAddressResource = sanitizeResource(
|
|
15699
|
+
new ShippingAddressResource({
|
|
15700
|
+
verbose: this.verbose,
|
|
15701
|
+
defaultHeaders: this.defaultHeaders,
|
|
15702
|
+
getAccessToken
|
|
15703
|
+
})
|
|
15704
|
+
);
|
|
15705
|
+
return this.shippingAddressResource;
|
|
15706
|
+
}
|
|
15707
|
+
createUserInfoResource() {
|
|
15708
|
+
if (this.userInfoResource) {
|
|
15709
|
+
return this.userInfoResource;
|
|
15710
|
+
}
|
|
15711
|
+
const getAccessToken = this.createSdkAccessTokenProvider();
|
|
15712
|
+
this.userInfoResource = sanitizeResource(
|
|
15713
|
+
new UserInfoResource({
|
|
15714
|
+
verbose: this.verbose,
|
|
15715
|
+
defaultHeaders: this.defaultHeaders,
|
|
15716
|
+
getAccessToken
|
|
15717
|
+
})
|
|
15718
|
+
);
|
|
15719
|
+
return this.userInfoResource;
|
|
15720
|
+
}
|
|
14945
15721
|
};
|
|
14946
15722
|
|
|
15723
|
+
// src/utils/update-info.ts
|
|
15724
|
+
import process8 from "process";
|
|
15725
|
+
import updateNotifier from "update-notifier";
|
|
15726
|
+
var UPDATE_CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
15727
|
+
var FAILURE_CACHE_TTL_MS = 60 * 1e3;
|
|
15728
|
+
var cachedUpdateInfo;
|
|
15729
|
+
var inflightUpdateInfo;
|
|
15730
|
+
function createAgentUpdateInfoProvider(packageName, cliVersion2) {
|
|
15731
|
+
return async ({ polling }) => {
|
|
15732
|
+
if (polling) {
|
|
15733
|
+
return cachedUpdateInfo?.value;
|
|
15734
|
+
}
|
|
15735
|
+
const now = Date.now();
|
|
15736
|
+
if (cachedUpdateInfo && cachedUpdateInfo.expiresAt > now) {
|
|
15737
|
+
return cachedUpdateInfo.value;
|
|
15738
|
+
}
|
|
15739
|
+
if (!inflightUpdateInfo) {
|
|
15740
|
+
inflightUpdateInfo = fetchLatestVersion(packageName, cliVersion2).finally(
|
|
15741
|
+
() => {
|
|
15742
|
+
inflightUpdateInfo = void 0;
|
|
15743
|
+
}
|
|
15744
|
+
);
|
|
15745
|
+
}
|
|
15746
|
+
return inflightUpdateInfo;
|
|
15747
|
+
};
|
|
15748
|
+
}
|
|
15749
|
+
function createInteractiveUpdateInfoProvider(updateInfo) {
|
|
15750
|
+
return async () => updateInfo;
|
|
15751
|
+
}
|
|
15752
|
+
function renderInteractiveUpdateNotice(updateInfo) {
|
|
15753
|
+
return [
|
|
15754
|
+
"",
|
|
15755
|
+
`Update available for @stripe/link-cli: ${updateInfo.current} -> ${updateInfo.latest}`,
|
|
15756
|
+
"Run: npm install -g @stripe/link-cli",
|
|
15757
|
+
""
|
|
15758
|
+
].join("\n");
|
|
15759
|
+
}
|
|
15760
|
+
async function fetchLatestVersion(packageName, cliVersion2) {
|
|
15761
|
+
const previousDisableFlag = process8.env.NO_UPDATE_NOTIFIER;
|
|
15762
|
+
try {
|
|
15763
|
+
process8.env.NO_UPDATE_NOTIFIER = "1";
|
|
15764
|
+
const notifier = updateNotifier({
|
|
15765
|
+
pkg: {
|
|
15766
|
+
name: packageName,
|
|
15767
|
+
version: cliVersion2
|
|
15768
|
+
}
|
|
15769
|
+
});
|
|
15770
|
+
const payload = await notifier.fetchInfo();
|
|
15771
|
+
const latest = payload.latest?.trim();
|
|
15772
|
+
const value = latest && latest.length > 0 && latest !== cliVersion2 ? { current: cliVersion2, latest } : void 0;
|
|
15773
|
+
cacheUpdateInfo(value);
|
|
15774
|
+
return value;
|
|
15775
|
+
} catch {
|
|
15776
|
+
cacheUpdateInfo(void 0, FAILURE_CACHE_TTL_MS);
|
|
15777
|
+
return void 0;
|
|
15778
|
+
} finally {
|
|
15779
|
+
if (previousDisableFlag === void 0) {
|
|
15780
|
+
process8.env.NO_UPDATE_NOTIFIER = void 0;
|
|
15781
|
+
} else {
|
|
15782
|
+
process8.env.NO_UPDATE_NOTIFIER = previousDisableFlag;
|
|
15783
|
+
}
|
|
15784
|
+
}
|
|
15785
|
+
}
|
|
15786
|
+
function cacheUpdateInfo(value, ttlMs = UPDATE_CACHE_TTL_MS) {
|
|
15787
|
+
cachedUpdateInfo = {
|
|
15788
|
+
expiresAt: Date.now() + ttlMs,
|
|
15789
|
+
value
|
|
15790
|
+
};
|
|
15791
|
+
}
|
|
15792
|
+
|
|
14947
15793
|
// src/cli.tsx
|
|
14948
|
-
var cliVersion = "0.
|
|
15794
|
+
var cliVersion = "0.5.0";
|
|
14949
15795
|
var buildNumber = "1";
|
|
14950
15796
|
var cliName = "@stripe/link-cli";
|
|
14951
15797
|
var defaultHeaders = {
|
|
@@ -14953,40 +15799,66 @@ var defaultHeaders = {
|
|
|
14953
15799
|
"X-Build-Number": buildNumber
|
|
14954
15800
|
};
|
|
14955
15801
|
var verbose = process.argv.includes("--verbose");
|
|
14956
|
-
var
|
|
15802
|
+
var authFileIndex = process.argv.indexOf("--auth");
|
|
15803
|
+
var credentialFilePath = authFileIndex !== -1 ? process.argv[authFileIndex + 1] : process.env.LINK_AUTH_FILE;
|
|
15804
|
+
if (authFileIndex !== -1) {
|
|
15805
|
+
process.argv.splice(authFileIndex, 2);
|
|
15806
|
+
}
|
|
15807
|
+
var authStorage = credentialFilePath ? new Storage({ configPath: credentialFilePath }) : storage;
|
|
15808
|
+
var factory = new ResourceFactory({ verbose, defaultHeaders, authStorage });
|
|
14957
15809
|
var authRepo = factory.createAuthResource();
|
|
14958
15810
|
var spendRequestRepo = factory.createSpendRequestResource();
|
|
14959
|
-
var
|
|
14960
|
-
pkg: { name: cliName, version: cliVersion }
|
|
14961
|
-
});
|
|
14962
|
-
var cli = Cli7.create("link-cli", {
|
|
15811
|
+
var cli = Cli9.create("link-cli", {
|
|
14963
15812
|
description: "Create a secure, one-time payment credential from a Link wallet to let agents complete purchases on behalf of users.",
|
|
14964
15813
|
version: `${cliVersion} (build ${buildNumber})`
|
|
14965
15814
|
});
|
|
14966
|
-
|
|
14967
|
-
|
|
15815
|
+
var isAgent = process.argv.includes("--format") || process.argv.includes("--mcp");
|
|
15816
|
+
var agentUpdateInfoProvider = createAgentUpdateInfoProvider(
|
|
15817
|
+
cliName,
|
|
15818
|
+
cliVersion
|
|
15819
|
+
);
|
|
15820
|
+
var getUpdateInfo = agentUpdateInfoProvider;
|
|
15821
|
+
if (!isAgent && process.stdout.isTTY) {
|
|
15822
|
+
const updateInfo = await agentUpdateInfoProvider({ polling: false });
|
|
15823
|
+
getUpdateInfo = createInteractiveUpdateInfoProvider(updateInfo);
|
|
15824
|
+
if (updateInfo) {
|
|
15825
|
+
process.stderr.write(renderInteractiveUpdateNotice(updateInfo));
|
|
15826
|
+
}
|
|
15827
|
+
}
|
|
15828
|
+
cli.command(createAuthCli(authRepo, getUpdateInfo, authStorage));
|
|
15829
|
+
cli.command(createSpendRequestCli(spendRequestRepo, authStorage));
|
|
14968
15830
|
cli.command(
|
|
14969
|
-
createPaymentMethodsCli(
|
|
15831
|
+
createPaymentMethodsCli(
|
|
15832
|
+
() => factory.createPaymentMethodsResource(),
|
|
15833
|
+
authStorage
|
|
15834
|
+
)
|
|
14970
15835
|
);
|
|
14971
|
-
cli.command(
|
|
15836
|
+
cli.command(
|
|
15837
|
+
createShippingAddressCli(
|
|
15838
|
+
() => factory.createShippingAddressResource(),
|
|
15839
|
+
authStorage
|
|
15840
|
+
)
|
|
15841
|
+
);
|
|
15842
|
+
cli.command(
|
|
15843
|
+
createUserInfoCli(() => factory.createUserInfoResource(), authStorage)
|
|
15844
|
+
);
|
|
15845
|
+
cli.command(createMppCli(spendRequestRepo, authStorage));
|
|
14972
15846
|
cli.command(
|
|
14973
15847
|
createDemoCli(
|
|
14974
15848
|
authRepo,
|
|
14975
15849
|
spendRequestRepo,
|
|
14976
|
-
() => factory.createPaymentMethodsResource()
|
|
15850
|
+
() => factory.createPaymentMethodsResource(),
|
|
15851
|
+
authStorage
|
|
14977
15852
|
)
|
|
14978
15853
|
);
|
|
14979
15854
|
cli.command(
|
|
14980
15855
|
createOnboardCli(
|
|
14981
15856
|
authRepo,
|
|
14982
15857
|
spendRequestRepo,
|
|
14983
|
-
() => factory.createPaymentMethodsResource()
|
|
15858
|
+
() => factory.createPaymentMethodsResource(),
|
|
15859
|
+
authStorage
|
|
14984
15860
|
)
|
|
14985
15861
|
);
|
|
14986
|
-
var isAgent = process.argv.includes("--format") || process.argv.includes("--mcp");
|
|
14987
|
-
if (!isAgent) {
|
|
14988
|
-
notifier.notify({ defer: false });
|
|
14989
|
-
}
|
|
14990
15862
|
cli.serve();
|
|
14991
15863
|
var cli_default = cli;
|
|
14992
15864
|
export {
|