@stripe/link-sdk 0.6.0 → 0.7.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/dist/client.d.ts +3 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +477 -124
- package/dist/index.js.map +1 -1
- package/dist/resources/__tests__/credentials.test.d.ts +2 -0
- package/dist/resources/__tests__/credentials.test.d.ts.map +1 -0
- package/dist/resources/__tests__/holder-jwk.test.d.ts +2 -0
- package/dist/resources/__tests__/holder-jwk.test.d.ts.map +1 -0
- package/dist/resources/__tests__/ucp.test.d.ts +2 -0
- package/dist/resources/__tests__/ucp.test.d.ts.map +1 -0
- package/dist/resources/base.d.ts +1 -0
- package/dist/resources/base.d.ts.map +1 -1
- package/dist/resources/holder-jwk.d.ts +11 -0
- package/dist/resources/holder-jwk.d.ts.map +1 -0
- package/dist/resources/identity-credentials.d.ts +9 -0
- package/dist/resources/identity-credentials.d.ts.map +1 -0
- package/dist/resources/interfaces.d.ts +67 -1
- package/dist/resources/interfaces.d.ts.map +1 -1
- package/dist/resources/ucp.d.ts +25 -0
- package/dist/resources/ucp.d.ts.map +1 -0
- package/dist/resources/user-info.d.ts.map +1 -1
- package/dist/types/index.d.ts +104 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -521,7 +521,8 @@ var BaseResource = class {
|
|
|
521
521
|
method: opts.method,
|
|
522
522
|
...opts.headers !== void 0 && { headers: opts.headers },
|
|
523
523
|
...opts.body !== void 0 && { body: opts.body },
|
|
524
|
-
...opts.signal !== void 0 && { signal: opts.signal }
|
|
524
|
+
...opts.signal !== void 0 && { signal: opts.signal },
|
|
525
|
+
...opts.redirect !== void 0 && { redirect: opts.redirect }
|
|
525
526
|
};
|
|
526
527
|
response = await this.fetchImpl(opts.url, init);
|
|
527
528
|
} catch (error) {
|
|
@@ -553,8 +554,13 @@ var BaseResource = class {
|
|
|
553
554
|
const res = await this.rawFetch(authedOpts);
|
|
554
555
|
if (res.status === 401 && this.canRefreshAccessToken) {
|
|
555
556
|
const refreshedToken = await this.getAccessToken({ forceRefresh: true });
|
|
556
|
-
|
|
557
|
-
|
|
557
|
+
return this.rawFetch({
|
|
558
|
+
...opts,
|
|
559
|
+
headers: {
|
|
560
|
+
...opts.headers,
|
|
561
|
+
Authorization: `Bearer ${refreshedToken}`
|
|
562
|
+
}
|
|
563
|
+
});
|
|
558
564
|
}
|
|
559
565
|
return res;
|
|
560
566
|
}
|
|
@@ -959,17 +965,143 @@ var BalancesResource = class extends BaseResource {
|
|
|
959
965
|
}
|
|
960
966
|
};
|
|
961
967
|
|
|
962
|
-
// src/resources/
|
|
968
|
+
// src/resources/identity-credentials.ts
|
|
963
969
|
import { z as z3 } from "zod";
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
+
|
|
971
|
+
// src/resources/holder-jwk.ts
|
|
972
|
+
import { createHash as createHash3 } from "crypto";
|
|
973
|
+
function isRecord2(value) {
|
|
974
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
975
|
+
}
|
|
976
|
+
function holderJwkThumbprint(jwk) {
|
|
977
|
+
const canonical = JSON.stringify({
|
|
978
|
+
crv: jwk.crv,
|
|
979
|
+
kty: jwk.kty,
|
|
980
|
+
x: jwk.x
|
|
981
|
+
});
|
|
982
|
+
return createHash3("sha256").update(canonical).digest("base64url");
|
|
983
|
+
}
|
|
984
|
+
function holderJwksEqual(left, right) {
|
|
985
|
+
return holderJwkThumbprint(left) === holderJwkThumbprint(right);
|
|
986
|
+
}
|
|
987
|
+
function parseHolderPublicJwk(value) {
|
|
988
|
+
if (!isRecord2(value)) {
|
|
989
|
+
throw new LinkConfigurationError("Holder public key must be a JWK object");
|
|
990
|
+
}
|
|
991
|
+
if (typeof value.kty !== "string") {
|
|
992
|
+
throw new LinkConfigurationError("Holder public key is missing kty");
|
|
993
|
+
}
|
|
994
|
+
if (value.kty !== "OKP" || value.crv !== "Ed25519" || typeof value.x !== "string" || value.x.length === 0) {
|
|
995
|
+
throw new LinkConfigurationError(
|
|
996
|
+
"Holder public key must be an Ed25519 OKP JWK with an x member"
|
|
997
|
+
);
|
|
998
|
+
}
|
|
999
|
+
return { kty: "OKP", crv: "Ed25519", x: value.x };
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
// src/resources/identity-credentials.ts
|
|
1003
|
+
var LINK_ISSUER2 = "https://api.link.com";
|
|
1004
|
+
var LINK_ISSUER_METADATA_URL2 = `${LINK_ISSUER2}/.well-known/aap-issuer`;
|
|
1005
|
+
var identityCredentialIssuerMetadataSchema = z3.looseObject({
|
|
1006
|
+
issuer: z3.literal(LINK_ISSUER2),
|
|
1007
|
+
credential_endpoint: z3.string()
|
|
1008
|
+
});
|
|
1009
|
+
var issueIdentityCredentialResponseSchema = z3.looseObject({
|
|
1010
|
+
credential: z3.string(),
|
|
1011
|
+
issuer: z3.literal(LINK_ISSUER2),
|
|
1012
|
+
expires_at: z3.string()
|
|
1013
|
+
});
|
|
1014
|
+
function requireLinkEndpoint2(value, field) {
|
|
1015
|
+
let url;
|
|
1016
|
+
try {
|
|
1017
|
+
url = new URL(value);
|
|
1018
|
+
} catch (error) {
|
|
1019
|
+
throw new TypeError(`${field} is not a valid URL`, { cause: error });
|
|
1020
|
+
}
|
|
1021
|
+
if (url.protocol !== "https:" || url.origin !== LINK_ISSUER2 || url.username || url.password) {
|
|
1022
|
+
throw new TypeError(`${field} must be an HTTPS URL on ${LINK_ISSUER2}`);
|
|
1023
|
+
}
|
|
1024
|
+
return url.href;
|
|
1025
|
+
}
|
|
1026
|
+
var IdentityCredentialsResource = class extends BaseResource {
|
|
1027
|
+
constructor(options) {
|
|
1028
|
+
super(options, "");
|
|
1029
|
+
}
|
|
1030
|
+
async discoverCredentialEndpoint() {
|
|
1031
|
+
const { status, data, rawBody } = await this.rawFetch({
|
|
1032
|
+
method: "GET",
|
|
1033
|
+
url: LINK_ISSUER_METADATA_URL2,
|
|
1034
|
+
redirect: "manual"
|
|
1035
|
+
});
|
|
1036
|
+
if (status >= 300 && status < 400) {
|
|
1037
|
+
throw new LinkApiError(
|
|
1038
|
+
`Refused redirect while fetching identity credential issuer metadata (${status})`,
|
|
1039
|
+
{ status, rawBody }
|
|
1040
|
+
);
|
|
1041
|
+
}
|
|
1042
|
+
if (status < 200 || status >= 300) {
|
|
1043
|
+
this.throwApiError(
|
|
1044
|
+
"fetch identity credential issuer metadata",
|
|
1045
|
+
status,
|
|
1046
|
+
data,
|
|
1047
|
+
rawBody
|
|
1048
|
+
);
|
|
1049
|
+
}
|
|
1050
|
+
const metadata = this.parseResponse(
|
|
1051
|
+
"parse identity credential issuer metadata",
|
|
1052
|
+
status,
|
|
1053
|
+
() => identityCredentialIssuerMetadataSchema.parse(data)
|
|
1054
|
+
);
|
|
1055
|
+
return this.parseResponse(
|
|
1056
|
+
"validate identity credential issuer metadata",
|
|
1057
|
+
status,
|
|
1058
|
+
() => requireLinkEndpoint2(
|
|
1059
|
+
metadata.credential_endpoint,
|
|
1060
|
+
"credential_endpoint"
|
|
1061
|
+
)
|
|
1062
|
+
);
|
|
1063
|
+
}
|
|
1064
|
+
async issue(params) {
|
|
1065
|
+
const publicJwk = parseHolderPublicJwk(params.cnf.jwk);
|
|
1066
|
+
const endpoint = await this.discoverCredentialEndpoint();
|
|
1067
|
+
const { status, data, rawBody } = await this.apiFetch({
|
|
1068
|
+
method: "POST",
|
|
1069
|
+
url: endpoint,
|
|
1070
|
+
redirect: "manual",
|
|
1071
|
+
headers: {
|
|
1072
|
+
"Content-Type": "application/json",
|
|
1073
|
+
Accept: "application/json"
|
|
1074
|
+
},
|
|
1075
|
+
body: JSON.stringify({ cnf: { jwk: publicJwk } })
|
|
1076
|
+
});
|
|
1077
|
+
if (status >= 300 && status < 400) {
|
|
1078
|
+
throw new LinkApiError(
|
|
1079
|
+
`Refused redirect while issuing identity credential (${status})`,
|
|
1080
|
+
{ status, rawBody }
|
|
1081
|
+
);
|
|
1082
|
+
}
|
|
1083
|
+
if (status < 200 || status >= 300) {
|
|
1084
|
+
this.throwApiError("issue identity credential", status, data, rawBody);
|
|
1085
|
+
}
|
|
1086
|
+
return this.parseResponse(
|
|
1087
|
+
"issue identity credential",
|
|
1088
|
+
status,
|
|
1089
|
+
() => issueIdentityCredentialResponseSchema.parse(data)
|
|
1090
|
+
);
|
|
1091
|
+
}
|
|
1092
|
+
};
|
|
1093
|
+
|
|
1094
|
+
// src/resources/payment-methods.ts
|
|
1095
|
+
import { z as z4 } from "zod";
|
|
1096
|
+
var paymentMethodSchema = z4.looseObject({
|
|
1097
|
+
id: z4.string(),
|
|
1098
|
+
type: z4.string(),
|
|
1099
|
+
is_default: z4.boolean(),
|
|
1100
|
+
name: z4.string(),
|
|
1101
|
+
nickname: z4.optional(z4.string().nullable())
|
|
970
1102
|
});
|
|
971
|
-
var paymentMethodsResponseSchema =
|
|
972
|
-
payment_details:
|
|
1103
|
+
var paymentMethodsResponseSchema = z4.looseObject({
|
|
1104
|
+
payment_details: z4.array(paymentMethodSchema)
|
|
973
1105
|
});
|
|
974
1106
|
var PaymentMethodsResource = class extends BaseResource {
|
|
975
1107
|
constructor(options) {
|
|
@@ -992,14 +1124,14 @@ var PaymentMethodsResource = class extends BaseResource {
|
|
|
992
1124
|
};
|
|
993
1125
|
|
|
994
1126
|
// src/resources/report.ts
|
|
995
|
-
import { z as
|
|
996
|
-
var reportRecordSchema =
|
|
997
|
-
object:
|
|
998
|
-
created_at:
|
|
999
|
-
domain:
|
|
1000
|
-
outcome:
|
|
1001
|
-
spend_request_id:
|
|
1002
|
-
status:
|
|
1127
|
+
import { z as z5 } from "zod";
|
|
1128
|
+
var reportRecordSchema = z5.looseObject({
|
|
1129
|
+
object: z5.string(),
|
|
1130
|
+
created_at: z5.string(),
|
|
1131
|
+
domain: z5.string(),
|
|
1132
|
+
outcome: z5.string(),
|
|
1133
|
+
spend_request_id: z5.string(),
|
|
1134
|
+
status: z5.string()
|
|
1003
1135
|
});
|
|
1004
1136
|
var ReportResource = class extends BaseResource {
|
|
1005
1137
|
constructor(options) {
|
|
@@ -1024,15 +1156,15 @@ var ReportResource = class extends BaseResource {
|
|
|
1024
1156
|
};
|
|
1025
1157
|
|
|
1026
1158
|
// src/resources/shipping-address.ts
|
|
1027
|
-
import { z as
|
|
1028
|
-
var shippingAddressSchema =
|
|
1029
|
-
id:
|
|
1030
|
-
is_default:
|
|
1031
|
-
nickname:
|
|
1032
|
-
address:
|
|
1159
|
+
import { z as z6 } from "zod";
|
|
1160
|
+
var shippingAddressSchema = z6.looseObject({
|
|
1161
|
+
id: z6.string(),
|
|
1162
|
+
is_default: z6.boolean(),
|
|
1163
|
+
nickname: z6.optional(z6.string().nullable()),
|
|
1164
|
+
address: z6.looseObject({}).nullable()
|
|
1033
1165
|
});
|
|
1034
|
-
var shippingAddressesResponseSchema =
|
|
1035
|
-
shipping_addresses:
|
|
1166
|
+
var shippingAddressesResponseSchema = z6.looseObject({
|
|
1167
|
+
shipping_addresses: z6.array(shippingAddressSchema)
|
|
1036
1168
|
});
|
|
1037
1169
|
var ShippingAddressResource = class extends BaseResource {
|
|
1038
1170
|
constructor(options) {
|
|
@@ -1055,21 +1187,21 @@ var ShippingAddressResource = class extends BaseResource {
|
|
|
1055
1187
|
};
|
|
1056
1188
|
|
|
1057
1189
|
// src/resources/sources.ts
|
|
1058
|
-
import { z as
|
|
1059
|
-
var nullableRecordSchema =
|
|
1060
|
-
var sourceSchema =
|
|
1061
|
-
id:
|
|
1062
|
-
name:
|
|
1063
|
-
type:
|
|
1190
|
+
import { z as z7 } from "zod";
|
|
1191
|
+
var nullableRecordSchema = z7.record(z7.string(), z7.unknown()).nullable().optional();
|
|
1192
|
+
var sourceSchema = z7.looseObject({
|
|
1193
|
+
id: z7.string().nullable().optional(),
|
|
1194
|
+
name: z7.string().nullable().optional(),
|
|
1195
|
+
type: z7.string().nullable().optional(),
|
|
1064
1196
|
capabilities: nullableRecordSchema,
|
|
1065
1197
|
external_connection: nullableRecordSchema,
|
|
1066
|
-
granted_actions:
|
|
1198
|
+
granted_actions: z7.array(z7.string()).nullable().optional(),
|
|
1067
1199
|
bank_account: nullableRecordSchema,
|
|
1068
1200
|
card: nullableRecordSchema
|
|
1069
1201
|
});
|
|
1070
|
-
var sourcesPageSchema =
|
|
1071
|
-
data:
|
|
1072
|
-
has_more:
|
|
1202
|
+
var sourcesPageSchema = z7.looseObject({
|
|
1203
|
+
data: z7.array(sourceSchema),
|
|
1204
|
+
has_more: z7.boolean().optional()
|
|
1073
1205
|
});
|
|
1074
1206
|
var SourcesResource = class extends BaseResource {
|
|
1075
1207
|
constructor(options) {
|
|
@@ -1105,34 +1237,34 @@ var SourcesResource = class extends BaseResource {
|
|
|
1105
1237
|
};
|
|
1106
1238
|
|
|
1107
1239
|
// src/resources/spend-request.ts
|
|
1108
|
-
import { z as
|
|
1109
|
-
var sharedPaymentTokenSchema =
|
|
1110
|
-
|
|
1111
|
-
|
|
1240
|
+
import { z as z8 } from "zod";
|
|
1241
|
+
var sharedPaymentTokenSchema = z8.union([
|
|
1242
|
+
z8.string().transform((id) => ({ id })),
|
|
1243
|
+
z8.looseObject({ id: z8.string() })
|
|
1112
1244
|
]);
|
|
1113
|
-
var spendRequestSchema =
|
|
1114
|
-
id:
|
|
1115
|
-
payment_details:
|
|
1116
|
-
status:
|
|
1117
|
-
line_items:
|
|
1118
|
-
totals:
|
|
1119
|
-
created_at:
|
|
1120
|
-
updated_at:
|
|
1245
|
+
var spendRequestSchema = z8.looseObject({
|
|
1246
|
+
id: z8.string(),
|
|
1247
|
+
payment_details: z8.string().optional(),
|
|
1248
|
+
status: z8.string(),
|
|
1249
|
+
line_items: z8.array(z8.unknown()).optional(),
|
|
1250
|
+
totals: z8.array(z8.unknown()).optional(),
|
|
1251
|
+
created_at: z8.string(),
|
|
1252
|
+
updated_at: z8.string(),
|
|
1121
1253
|
shared_payment_token: sharedPaymentTokenSchema.nullable().optional()
|
|
1122
1254
|
});
|
|
1123
|
-
var spendRequestsResponseSchema =
|
|
1124
|
-
data:
|
|
1255
|
+
var spendRequestsResponseSchema = z8.looseObject({
|
|
1256
|
+
data: z8.array(spendRequestSchema)
|
|
1125
1257
|
});
|
|
1126
|
-
var requestApprovalResponseSchema =
|
|
1127
|
-
id:
|
|
1128
|
-
approval_link:
|
|
1258
|
+
var requestApprovalResponseSchema = z8.looseObject({
|
|
1259
|
+
id: z8.string(),
|
|
1260
|
+
approval_link: z8.string()
|
|
1129
1261
|
}).transform(({ approval_link, ...response }) => ({
|
|
1130
1262
|
...response,
|
|
1131
1263
|
approval_url: approval_link
|
|
1132
1264
|
}));
|
|
1133
|
-
var duplicateSpendRequestErrorSchema =
|
|
1134
|
-
error:
|
|
1135
|
-
duplicate_spend_request:
|
|
1265
|
+
var duplicateSpendRequestErrorSchema = z8.looseObject({
|
|
1266
|
+
error: z8.looseObject({
|
|
1267
|
+
duplicate_spend_request: z8.unknown().optional()
|
|
1136
1268
|
})
|
|
1137
1269
|
});
|
|
1138
1270
|
function parseSpendRequest(value) {
|
|
@@ -1252,35 +1384,35 @@ var SpendRequestResource = class extends BaseResource {
|
|
|
1252
1384
|
};
|
|
1253
1385
|
|
|
1254
1386
|
// src/resources/summaries.ts
|
|
1255
|
-
import { z as
|
|
1256
|
-
var summaryValueSchema =
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
unit:
|
|
1260
|
-
amount:
|
|
1261
|
-
currency:
|
|
1387
|
+
import { z as z9 } from "zod";
|
|
1388
|
+
var summaryValueSchema = z9.discriminatedUnion("unit", [
|
|
1389
|
+
z9.looseObject({ unit: z9.literal("count"), count: z9.number() }),
|
|
1390
|
+
z9.looseObject({
|
|
1391
|
+
unit: z9.literal("payment_volume"),
|
|
1392
|
+
amount: z9.number(),
|
|
1393
|
+
currency: z9.string()
|
|
1262
1394
|
})
|
|
1263
1395
|
]);
|
|
1264
|
-
var summaryDataValueSchema =
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
unit:
|
|
1268
|
-
amount:
|
|
1269
|
-
currency:
|
|
1396
|
+
var summaryDataValueSchema = z9.discriminatedUnion("unit", [
|
|
1397
|
+
z9.looseObject({ unit: z9.literal("count"), amount: z9.number() }),
|
|
1398
|
+
z9.looseObject({
|
|
1399
|
+
unit: z9.literal("payment_volume"),
|
|
1400
|
+
amount: z9.number(),
|
|
1401
|
+
currency: z9.string()
|
|
1270
1402
|
})
|
|
1271
1403
|
]);
|
|
1272
|
-
var summarySchema =
|
|
1273
|
-
id:
|
|
1274
|
-
description:
|
|
1275
|
-
created_at:
|
|
1276
|
-
status:
|
|
1277
|
-
entries:
|
|
1278
|
-
as_of:
|
|
1279
|
-
data:
|
|
1404
|
+
var summarySchema = z9.looseObject({
|
|
1405
|
+
id: z9.string(),
|
|
1406
|
+
description: z9.string(),
|
|
1407
|
+
created_at: z9.string().nullable().optional(),
|
|
1408
|
+
status: z9.enum(["ready", "pending", "no_data"]),
|
|
1409
|
+
entries: z9.array(z9.looseObject({ label: z9.string(), value: summaryValueSchema })).default([]),
|
|
1410
|
+
as_of: z9.number().optional(),
|
|
1411
|
+
data: z9.array(z9.looseObject({ label: z9.string(), value: summaryDataValueSchema })).nullable().optional()
|
|
1280
1412
|
});
|
|
1281
|
-
var summariesPageSchema =
|
|
1282
|
-
data:
|
|
1283
|
-
has_more:
|
|
1413
|
+
var summariesPageSchema = z9.looseObject({
|
|
1414
|
+
data: z9.array(summarySchema),
|
|
1415
|
+
has_more: z9.boolean().optional()
|
|
1284
1416
|
});
|
|
1285
1417
|
var SummariesResource = class extends BaseResource {
|
|
1286
1418
|
constructor(options) {
|
|
@@ -1311,23 +1443,23 @@ var SummariesResource = class extends BaseResource {
|
|
|
1311
1443
|
};
|
|
1312
1444
|
|
|
1313
1445
|
// src/resources/transactions.ts
|
|
1314
|
-
import { z as
|
|
1315
|
-
var transactionSchema =
|
|
1316
|
-
id:
|
|
1317
|
-
source_id:
|
|
1318
|
-
amount:
|
|
1319
|
-
currency:
|
|
1320
|
-
created_date:
|
|
1321
|
-
description:
|
|
1322
|
-
origin:
|
|
1323
|
-
category:
|
|
1324
|
-
status:
|
|
1446
|
+
import { z as z10 } from "zod";
|
|
1447
|
+
var transactionSchema = z10.looseObject({
|
|
1448
|
+
id: z10.string(),
|
|
1449
|
+
source_id: z10.string().nullable(),
|
|
1450
|
+
amount: z10.number(),
|
|
1451
|
+
currency: z10.string(),
|
|
1452
|
+
created_date: z10.string(),
|
|
1453
|
+
description: z10.string(),
|
|
1454
|
+
origin: z10.enum(["link", "external_connection"]),
|
|
1455
|
+
category: z10.string().nullable(),
|
|
1456
|
+
status: z10.string()
|
|
1325
1457
|
});
|
|
1326
|
-
var transactionsPageSchema =
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
data:
|
|
1330
|
-
has_more:
|
|
1458
|
+
var transactionsPageSchema = z10.union([
|
|
1459
|
+
z10.array(transactionSchema).transform((data) => ({ data })),
|
|
1460
|
+
z10.looseObject({
|
|
1461
|
+
data: z10.array(transactionSchema),
|
|
1462
|
+
has_more: z10.boolean().optional()
|
|
1331
1463
|
})
|
|
1332
1464
|
]);
|
|
1333
1465
|
var TransactionsResource = class extends BaseResource {
|
|
@@ -1380,36 +1512,246 @@ var TransactionsResource = class extends BaseResource {
|
|
|
1380
1512
|
}
|
|
1381
1513
|
};
|
|
1382
1514
|
|
|
1515
|
+
// src/resources/ucp.ts
|
|
1516
|
+
function extractApiError(data, rawBody) {
|
|
1517
|
+
if (data && typeof data === "object") {
|
|
1518
|
+
const body = data;
|
|
1519
|
+
if (body.error && typeof body.error === "object") {
|
|
1520
|
+
const err = body.error;
|
|
1521
|
+
if (typeof err.message === "string") return err.message;
|
|
1522
|
+
}
|
|
1523
|
+
if (typeof body.error === "string") return body.error;
|
|
1524
|
+
if (typeof body.message === "string") return body.message;
|
|
1525
|
+
}
|
|
1526
|
+
return rawBody || "unknown error";
|
|
1527
|
+
}
|
|
1528
|
+
function normalizeSearchResult(data) {
|
|
1529
|
+
const body = data ?? {};
|
|
1530
|
+
const items = Array.isArray(body.data) ? body.data : [];
|
|
1531
|
+
return { ...body, data: items };
|
|
1532
|
+
}
|
|
1533
|
+
function normalizeCheckout(data) {
|
|
1534
|
+
const body = data ?? {};
|
|
1535
|
+
return { ...body, id: String(body.id ?? "") };
|
|
1536
|
+
}
|
|
1537
|
+
var UcpResource = class {
|
|
1538
|
+
verbose;
|
|
1539
|
+
getAccessToken;
|
|
1540
|
+
fetchImpl;
|
|
1541
|
+
ucpEndpoint;
|
|
1542
|
+
logger;
|
|
1543
|
+
constructor(options) {
|
|
1544
|
+
const config = resolveLinkSdkConfig(options);
|
|
1545
|
+
this.verbose = config.verbose;
|
|
1546
|
+
this.getAccessToken = config.getAccessToken;
|
|
1547
|
+
this.fetchImpl = requireFetchImplementation(config);
|
|
1548
|
+
this.ucpEndpoint = `${config.apiBaseUrl}/ucp`;
|
|
1549
|
+
this.logger = config.logger;
|
|
1550
|
+
}
|
|
1551
|
+
async rawFetch(opts) {
|
|
1552
|
+
if (this.verbose) {
|
|
1553
|
+
const redactedHeaders = { ...opts.headers };
|
|
1554
|
+
if (redactedHeaders.Authorization)
|
|
1555
|
+
redactedHeaders.Authorization = "Bearer <redacted>";
|
|
1556
|
+
this.logger.debug(`> ${opts.method} ${opts.url}`);
|
|
1557
|
+
this.logger.debug(` Headers: ${JSON.stringify(redactedHeaders)}`);
|
|
1558
|
+
if (opts.body) this.logger.debug(opts.body);
|
|
1559
|
+
}
|
|
1560
|
+
const fetchOpts = {
|
|
1561
|
+
method: opts.method,
|
|
1562
|
+
...opts.headers ? { headers: opts.headers } : {}
|
|
1563
|
+
};
|
|
1564
|
+
if (opts.body) fetchOpts.body = opts.body;
|
|
1565
|
+
let response;
|
|
1566
|
+
try {
|
|
1567
|
+
response = await this.fetchImpl(opts.url, fetchOpts);
|
|
1568
|
+
} catch (error) {
|
|
1569
|
+
throw new LinkTransportError(
|
|
1570
|
+
`Request failed: ${opts.method} ${opts.url}`,
|
|
1571
|
+
{
|
|
1572
|
+
cause: error
|
|
1573
|
+
}
|
|
1574
|
+
);
|
|
1575
|
+
}
|
|
1576
|
+
const rawBody = await response.text();
|
|
1577
|
+
let data = null;
|
|
1578
|
+
try {
|
|
1579
|
+
data = JSON.parse(rawBody);
|
|
1580
|
+
} catch {
|
|
1581
|
+
}
|
|
1582
|
+
if (this.verbose) {
|
|
1583
|
+
this.logger.debug(`< ${response.status} ${response.statusText}`);
|
|
1584
|
+
response.headers.forEach((value, key) => {
|
|
1585
|
+
this.logger.debug(` ${key}: ${value}`);
|
|
1586
|
+
});
|
|
1587
|
+
this.logger.debug(JSON.stringify(data, null, 2) ?? rawBody);
|
|
1588
|
+
}
|
|
1589
|
+
return { status: response.status, data, rawBody };
|
|
1590
|
+
}
|
|
1591
|
+
/** Injects the Bearer token; retries once on 401 after refreshing. */
|
|
1592
|
+
async apiFetch(opts) {
|
|
1593
|
+
const token = await this.getAccessToken();
|
|
1594
|
+
const authedOpts = {
|
|
1595
|
+
...opts,
|
|
1596
|
+
headers: { ...opts.headers, Authorization: `Bearer ${token}` }
|
|
1597
|
+
};
|
|
1598
|
+
const res = await this.rawFetch(authedOpts);
|
|
1599
|
+
if (res.status === 401) {
|
|
1600
|
+
const refreshedToken = await this.getAccessToken({ forceRefresh: true });
|
|
1601
|
+
authedOpts.headers.Authorization = `Bearer ${refreshedToken}`;
|
|
1602
|
+
return this.rawFetch(authedOpts);
|
|
1603
|
+
}
|
|
1604
|
+
return res;
|
|
1605
|
+
}
|
|
1606
|
+
buildSearchUrl(params) {
|
|
1607
|
+
const url = new URL(`${this.ucpEndpoint}/catalog/search`);
|
|
1608
|
+
const setIf = (key, value) => {
|
|
1609
|
+
if (value !== void 0) url.searchParams.set(key, String(value));
|
|
1610
|
+
};
|
|
1611
|
+
setIf("query", params.query);
|
|
1612
|
+
setIf("profile_id", params.profile_id);
|
|
1613
|
+
setIf("sku", params.sku);
|
|
1614
|
+
setIf("price_min", params.price_min);
|
|
1615
|
+
setIf("price_max", params.price_max);
|
|
1616
|
+
setIf("currency", params.currency);
|
|
1617
|
+
setIf("availability", params.availability);
|
|
1618
|
+
setIf("sort", params.sort);
|
|
1619
|
+
setIf("group_by", params.group_by);
|
|
1620
|
+
setIf("limit", params.limit);
|
|
1621
|
+
setIf("offset", params.offset);
|
|
1622
|
+
if (params.include_facets) url.searchParams.set("include_facets", "true");
|
|
1623
|
+
const arrays = [
|
|
1624
|
+
["brand", params.brand],
|
|
1625
|
+
["category", params.category],
|
|
1626
|
+
["color", params.color],
|
|
1627
|
+
["size", params.size],
|
|
1628
|
+
["material", params.material],
|
|
1629
|
+
["gender", params.gender],
|
|
1630
|
+
["condition", params.condition]
|
|
1631
|
+
];
|
|
1632
|
+
for (const [key, values] of arrays) {
|
|
1633
|
+
if (values)
|
|
1634
|
+
for (const value of values) url.searchParams.append(`${key}[]`, value);
|
|
1635
|
+
}
|
|
1636
|
+
if (params.test) url.searchParams.set("test", "true");
|
|
1637
|
+
return url.toString();
|
|
1638
|
+
}
|
|
1639
|
+
async searchCatalog(params) {
|
|
1640
|
+
const { status, data, rawBody } = await this.apiFetch({
|
|
1641
|
+
method: "GET",
|
|
1642
|
+
url: this.buildSearchUrl(params)
|
|
1643
|
+
});
|
|
1644
|
+
if (status < 200 || status >= 300) {
|
|
1645
|
+
throw new LinkApiError(
|
|
1646
|
+
`Failed to search UCP catalog (${status}): ${extractApiError(data, rawBody)}`,
|
|
1647
|
+
{ status, rawBody, details: data }
|
|
1648
|
+
);
|
|
1649
|
+
}
|
|
1650
|
+
return normalizeSearchResult(data);
|
|
1651
|
+
}
|
|
1652
|
+
async createCheckout(params) {
|
|
1653
|
+
const body = {
|
|
1654
|
+
profile_id: params.profile_id,
|
|
1655
|
+
line_items: params.line_items
|
|
1656
|
+
};
|
|
1657
|
+
if (params.currency !== void 0) body.currency = params.currency;
|
|
1658
|
+
if (params.fulfillment_details !== void 0)
|
|
1659
|
+
body.fulfillment_details = params.fulfillment_details;
|
|
1660
|
+
if (params.test) body.test = true;
|
|
1661
|
+
const { status, data, rawBody } = await this.apiFetch({
|
|
1662
|
+
method: "POST",
|
|
1663
|
+
url: `${this.ucpEndpoint}/checkout`,
|
|
1664
|
+
headers: { "Content-Type": "application/json" },
|
|
1665
|
+
body: JSON.stringify(body)
|
|
1666
|
+
});
|
|
1667
|
+
if (status < 200 || status >= 300) {
|
|
1668
|
+
throw new LinkApiError(
|
|
1669
|
+
`Failed to create UCP checkout (${status}): ${extractApiError(data, rawBody)}`,
|
|
1670
|
+
{ status, rawBody, details: data }
|
|
1671
|
+
);
|
|
1672
|
+
}
|
|
1673
|
+
return normalizeCheckout(data);
|
|
1674
|
+
}
|
|
1675
|
+
async completeCheckout(id, params) {
|
|
1676
|
+
const body = {
|
|
1677
|
+
spend_request_id: params.spend_request_id,
|
|
1678
|
+
profile_id: params.profile_id
|
|
1679
|
+
};
|
|
1680
|
+
if (params.test) body.test = true;
|
|
1681
|
+
const { status, data, rawBody } = await this.apiFetch({
|
|
1682
|
+
method: "POST",
|
|
1683
|
+
url: `${this.ucpEndpoint}/checkout/${encodeURIComponent(id)}/complete`,
|
|
1684
|
+
headers: { "Content-Type": "application/json" },
|
|
1685
|
+
body: JSON.stringify(body)
|
|
1686
|
+
});
|
|
1687
|
+
if (status < 200 || status >= 300) {
|
|
1688
|
+
throw new LinkApiError(
|
|
1689
|
+
`Failed to complete UCP checkout (${status}): ${extractApiError(data, rawBody)}`,
|
|
1690
|
+
{ status, rawBody, details: data }
|
|
1691
|
+
);
|
|
1692
|
+
}
|
|
1693
|
+
return normalizeCheckout(data);
|
|
1694
|
+
}
|
|
1695
|
+
async retrieveCheckout(id, params) {
|
|
1696
|
+
const url = new URL(
|
|
1697
|
+
`${this.ucpEndpoint}/checkout/${encodeURIComponent(id)}`
|
|
1698
|
+
);
|
|
1699
|
+
url.searchParams.set("spend_request_id", params.spend_request_id);
|
|
1700
|
+
if (params.test) url.searchParams.set("test", "true");
|
|
1701
|
+
const { status, data, rawBody } = await this.apiFetch({
|
|
1702
|
+
method: "GET",
|
|
1703
|
+
url: url.toString()
|
|
1704
|
+
});
|
|
1705
|
+
if (status < 200 || status >= 300) {
|
|
1706
|
+
throw new LinkApiError(
|
|
1707
|
+
`Failed to retrieve UCP checkout (${status}): ${extractApiError(data, rawBody)}`,
|
|
1708
|
+
{ status, rawBody, details: data }
|
|
1709
|
+
);
|
|
1710
|
+
}
|
|
1711
|
+
return normalizeCheckout(data);
|
|
1712
|
+
}
|
|
1713
|
+
};
|
|
1714
|
+
|
|
1383
1715
|
// src/resources/user-info.ts
|
|
1384
|
-
import { z as
|
|
1385
|
-
var rollingSpendLimitSchema =
|
|
1386
|
-
limit:
|
|
1387
|
-
used:
|
|
1388
|
-
remaining:
|
|
1716
|
+
import { z as z11 } from "zod";
|
|
1717
|
+
var rollingSpendLimitSchema = z11.object({
|
|
1718
|
+
limit: z11.number().int().nullable(),
|
|
1719
|
+
used: z11.number().int(),
|
|
1720
|
+
remaining: z11.number().int().nullable()
|
|
1389
1721
|
});
|
|
1390
|
-
var agentWalletSpendLimitsSchema =
|
|
1391
|
-
per_transaction:
|
|
1392
|
-
limit:
|
|
1722
|
+
var agentWalletSpendLimitsSchema = z11.object({
|
|
1723
|
+
per_transaction: z11.object({
|
|
1724
|
+
limit: z11.number().int().nullable()
|
|
1393
1725
|
}),
|
|
1394
1726
|
daily: rollingSpendLimitSchema,
|
|
1395
1727
|
thirty_day: rollingSpendLimitSchema
|
|
1396
1728
|
});
|
|
1397
|
-
var agentWalletVerificationRequirementSchema =
|
|
1398
|
-
status:
|
|
1729
|
+
var agentWalletVerificationRequirementSchema = z11.object({
|
|
1730
|
+
status: z11.enum([
|
|
1399
1731
|
"not_required",
|
|
1400
1732
|
"ssn_verification",
|
|
1401
1733
|
"identity_verification",
|
|
1402
1734
|
"contact_support",
|
|
1403
1735
|
"complete"
|
|
1404
1736
|
]),
|
|
1405
|
-
action_url:
|
|
1737
|
+
action_url: z11.string().nullable()
|
|
1738
|
+
});
|
|
1739
|
+
var userInfoAddressSchema = z11.object({
|
|
1740
|
+
line1: z11.string().nullable(),
|
|
1741
|
+
line2: z11.string().nullable(),
|
|
1742
|
+
city: z11.string().nullable(),
|
|
1743
|
+
state: z11.string().nullable(),
|
|
1744
|
+
postal_code: z11.string().nullable(),
|
|
1745
|
+
country: z11.string().nullable()
|
|
1406
1746
|
});
|
|
1407
|
-
var userInfoSchema =
|
|
1408
|
-
email:
|
|
1409
|
-
name:
|
|
1410
|
-
first_name:
|
|
1411
|
-
last_name:
|
|
1412
|
-
phone:
|
|
1747
|
+
var userInfoSchema = z11.looseObject({
|
|
1748
|
+
email: z11.string().nullable().optional(),
|
|
1749
|
+
name: z11.string().nullable().optional(),
|
|
1750
|
+
first_name: z11.string().nullable().optional(),
|
|
1751
|
+
last_name: z11.string().nullable().optional(),
|
|
1752
|
+
phone: z11.string().nullable().optional(),
|
|
1753
|
+
address: userInfoAddressSchema.nullable().optional(),
|
|
1754
|
+
eligible_for_balance: z11.boolean().optional(),
|
|
1413
1755
|
agent_wallet_spend_limits: agentWalletSpendLimitsSchema.optional(),
|
|
1414
1756
|
agent_wallet_step_up: agentWalletVerificationRequirementSchema.optional()
|
|
1415
1757
|
}).transform(
|
|
@@ -1419,6 +1761,8 @@ var userInfoSchema = z10.looseObject({
|
|
|
1419
1761
|
first_name,
|
|
1420
1762
|
last_name,
|
|
1421
1763
|
phone,
|
|
1764
|
+
address,
|
|
1765
|
+
eligible_for_balance,
|
|
1422
1766
|
agent_wallet_spend_limits,
|
|
1423
1767
|
agent_wallet_step_up
|
|
1424
1768
|
}) => ({
|
|
@@ -1427,6 +1771,8 @@ var userInfoSchema = z10.looseObject({
|
|
|
1427
1771
|
first_name: first_name ?? null,
|
|
1428
1772
|
last_name: last_name ?? null,
|
|
1429
1773
|
phone: phone ?? null,
|
|
1774
|
+
...address === void 0 ? {} : { address },
|
|
1775
|
+
...eligible_for_balance === void 0 ? {} : { eligible_for_balance },
|
|
1430
1776
|
...agent_wallet_spend_limits === void 0 ? {} : { agent_wallet_spend_limits },
|
|
1431
1777
|
...agent_wallet_step_up === void 0 ? {} : { agent_wallet_verification_requirement: agent_wallet_step_up }
|
|
1432
1778
|
})
|
|
@@ -1452,16 +1798,16 @@ var UserInfoResource = class extends BaseResource {
|
|
|
1452
1798
|
};
|
|
1453
1799
|
|
|
1454
1800
|
// src/resources/web-bot-auth.ts
|
|
1455
|
-
import { z as
|
|
1801
|
+
import { z as z12 } from "zod";
|
|
1456
1802
|
var EXPIRY_BUFFER_MS = 3e4;
|
|
1457
|
-
var webBotAuthBlockSchema =
|
|
1458
|
-
signature:
|
|
1459
|
-
signature_input:
|
|
1460
|
-
signature_agent:
|
|
1461
|
-
authority:
|
|
1462
|
-
expires_at:
|
|
1803
|
+
var webBotAuthBlockSchema = z12.looseObject({
|
|
1804
|
+
signature: z12.string(),
|
|
1805
|
+
signature_input: z12.string(),
|
|
1806
|
+
signature_agent: z12.string(),
|
|
1807
|
+
authority: z12.string(),
|
|
1808
|
+
expires_at: z12.string()
|
|
1463
1809
|
});
|
|
1464
|
-
var webBotAuthResponseSchema =
|
|
1810
|
+
var webBotAuthResponseSchema = z12.looseObject({
|
|
1465
1811
|
web_bot_auth: webBotAuthBlockSchema
|
|
1466
1812
|
});
|
|
1467
1813
|
var WebBotAuthResource = class extends BaseResource {
|
|
@@ -1508,6 +1854,7 @@ var WebBotAuthResource = class extends BaseResource {
|
|
|
1508
1854
|
// src/client.ts
|
|
1509
1855
|
var Link = class {
|
|
1510
1856
|
attestations;
|
|
1857
|
+
identityCredentials;
|
|
1511
1858
|
spendRequests;
|
|
1512
1859
|
paymentMethods;
|
|
1513
1860
|
shippingAddresses;
|
|
@@ -1518,8 +1865,10 @@ var Link = class {
|
|
|
1518
1865
|
summaries;
|
|
1519
1866
|
webBotAuth;
|
|
1520
1867
|
reports;
|
|
1868
|
+
ucp;
|
|
1521
1869
|
constructor(options) {
|
|
1522
1870
|
this.attestations = new AttestationsResource(options);
|
|
1871
|
+
this.identityCredentials = new IdentityCredentialsResource(options);
|
|
1523
1872
|
this.spendRequests = new SpendRequestResource(options);
|
|
1524
1873
|
this.paymentMethods = new PaymentMethodsResource(options);
|
|
1525
1874
|
this.shippingAddresses = new ShippingAddressResource(options);
|
|
@@ -1530,6 +1879,7 @@ var Link = class {
|
|
|
1530
1879
|
this.summaries = new SummariesResource(options);
|
|
1531
1880
|
this.webBotAuth = new WebBotAuthResource(options);
|
|
1532
1881
|
this.reports = new ReportResource(options);
|
|
1882
|
+
this.ucp = new UcpResource(options);
|
|
1533
1883
|
}
|
|
1534
1884
|
};
|
|
1535
1885
|
var client_default = Link;
|
|
@@ -1566,6 +1916,9 @@ export {
|
|
|
1566
1916
|
REPORT_TAGS,
|
|
1567
1917
|
SummariesResource,
|
|
1568
1918
|
client_default as default,
|
|
1569
|
-
getDuplicateSpendRequest
|
|
1919
|
+
getDuplicateSpendRequest,
|
|
1920
|
+
holderJwkThumbprint,
|
|
1921
|
+
holderJwksEqual,
|
|
1922
|
+
parseHolderPublicJwk
|
|
1570
1923
|
};
|
|
1571
1924
|
//# sourceMappingURL=index.js.map
|