@stripe/link-sdk 0.6.0 → 0.8.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.
Files changed (37) hide show
  1. package/README.md +7 -1
  2. package/dist/client.d.ts +4 -2
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/index.d.ts +2 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +749 -373
  7. package/dist/index.js.map +1 -1
  8. package/dist/resources/__tests__/approval-policy.test.d.ts +2 -0
  9. package/dist/resources/__tests__/approval-policy.test.d.ts.map +1 -0
  10. package/dist/resources/__tests__/credentials.test.d.ts +2 -0
  11. package/dist/resources/__tests__/credentials.test.d.ts.map +1 -0
  12. package/dist/resources/__tests__/holder-jwk.test.d.ts +2 -0
  13. package/dist/resources/__tests__/holder-jwk.test.d.ts.map +1 -0
  14. package/dist/resources/__tests__/ucp.test.d.ts +2 -0
  15. package/dist/resources/__tests__/ucp.test.d.ts.map +1 -0
  16. package/dist/resources/approval-policy.d.ts +9 -0
  17. package/dist/resources/approval-policy.d.ts.map +1 -0
  18. package/dist/resources/base.d.ts +1 -0
  19. package/dist/resources/base.d.ts.map +1 -1
  20. package/dist/resources/holder-jwk.d.ts +11 -0
  21. package/dist/resources/holder-jwk.d.ts.map +1 -0
  22. package/dist/resources/identity-credentials.d.ts +9 -0
  23. package/dist/resources/identity-credentials.d.ts.map +1 -0
  24. package/dist/resources/interfaces.d.ts +75 -8
  25. package/dist/resources/interfaces.d.ts.map +1 -1
  26. package/dist/resources/payment-methods.d.ts +3 -1
  27. package/dist/resources/payment-methods.d.ts.map +1 -1
  28. package/dist/resources/ucp.d.ts +25 -0
  29. package/dist/resources/ucp.d.ts.map +1 -0
  30. package/dist/resources/user-info.d.ts.map +1 -1
  31. package/dist/types/index.d.ts +132 -48
  32. package/dist/types/index.d.ts.map +1 -1
  33. package/package.json +1 -1
  34. package/dist/resources/__tests__/summaries.test.d.ts +0 -2
  35. package/dist/resources/__tests__/summaries.test.d.ts.map +0 -1
  36. package/dist/resources/summaries.d.ts +0 -10
  37. package/dist/resources/summaries.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
- // src/resources/attestations.ts
2
- import { createHash as createHash2 } from "crypto";
1
+ // src/resources/approval-policy.ts
3
2
  import { z } from "zod";
4
3
 
5
4
  // src/errors.ts
@@ -45,6 +44,224 @@ var LinkApiError = class extends LinkSdkError {
45
44
  }
46
45
  };
47
46
 
47
+ // src/config.ts
48
+ var DEFAULT_API_BASE_URL = "https://api.link.com";
49
+ function createDefaultHeadersFetch(baseFetch, defaultHeaders) {
50
+ return ((input, init) => {
51
+ const headers = new Headers(init?.headers);
52
+ for (const [key, value] of Object.entries(defaultHeaders)) {
53
+ if (!headers.has(key)) {
54
+ headers.set(key, value);
55
+ }
56
+ }
57
+ return baseFetch(input, { ...init, headers });
58
+ });
59
+ }
60
+ function createDefaultLogger() {
61
+ return {
62
+ debug() {
63
+ }
64
+ };
65
+ }
66
+ function resolveLinkSdkConfig(options, defaults = {}) {
67
+ const verbose = options.verbose ?? false;
68
+ const logger = options.logger ?? createDefaultLogger();
69
+ if (options.accessToken !== void 0 && options.getAccessToken !== void 0) {
70
+ throw new LinkConfigurationError(
71
+ "Pass either `accessToken` or `getAccessToken`, not both."
72
+ );
73
+ }
74
+ let getAccessToken;
75
+ let canRefreshAccessToken;
76
+ if (options.accessToken !== void 0) {
77
+ if (options.accessToken.trim().length === 0) {
78
+ throw new LinkConfigurationError("`accessToken` cannot be empty.");
79
+ }
80
+ const accessToken = options.accessToken;
81
+ getAccessToken = () => accessToken;
82
+ canRefreshAccessToken = false;
83
+ } else if (typeof options.getAccessToken === "function") {
84
+ getAccessToken = options.getAccessToken;
85
+ canRefreshAccessToken = true;
86
+ } else {
87
+ throw new LinkConfigurationError(
88
+ "Pass `accessToken` or `getAccessToken` to the Link client."
89
+ );
90
+ }
91
+ const apiBaseUrl = options.apiBaseUrl ?? defaults.apiBaseUrl ?? DEFAULT_API_BASE_URL;
92
+ const spendRequestBaseUrl = options.spendRequestBaseUrl ?? defaults.spendRequestBaseUrl ?? apiBaseUrl;
93
+ const baseFetch = options.fetch ?? globalThis.fetch;
94
+ const effectiveFetch = options.defaultHeaders && Object.keys(options.defaultHeaders).length > 0 ? createDefaultHeadersFetch(baseFetch, options.defaultHeaders) : baseFetch;
95
+ return {
96
+ verbose,
97
+ getAccessToken,
98
+ canRefreshAccessToken,
99
+ fetch: effectiveFetch,
100
+ apiBaseUrl,
101
+ spendRequestBaseUrl,
102
+ logger
103
+ };
104
+ }
105
+ function requireFetchImplementation(config) {
106
+ if (!config.fetch) {
107
+ throw new LinkConfigurationError(
108
+ "No fetch implementation available. Pass `fetch` in Link SDK options."
109
+ );
110
+ }
111
+ return config.fetch;
112
+ }
113
+
114
+ // src/resources/base.ts
115
+ function isRecord(value) {
116
+ return value !== null && typeof value === "object" && !Array.isArray(value);
117
+ }
118
+ function extractErrorMessage(data, rawBody) {
119
+ if (isRecord(data)) {
120
+ if (typeof data.error === "string") {
121
+ return data.error;
122
+ }
123
+ if (isRecord(data.error)) {
124
+ const nested = data.error;
125
+ if (typeof nested.message === "string") {
126
+ return nested.message;
127
+ }
128
+ if (typeof nested.code === "string") {
129
+ return nested.code;
130
+ }
131
+ }
132
+ if (typeof data.message === "string") {
133
+ return data.message;
134
+ }
135
+ }
136
+ return rawBody || "unknown error";
137
+ }
138
+ var BaseResource = class {
139
+ verbose;
140
+ getAccessToken;
141
+ canRefreshAccessToken;
142
+ fetchImpl;
143
+ endpoint;
144
+ logger;
145
+ constructor(options, endpointPath, base = "api") {
146
+ const config = resolveLinkSdkConfig(options);
147
+ this.verbose = config.verbose;
148
+ this.getAccessToken = config.getAccessToken;
149
+ this.canRefreshAccessToken = config.canRefreshAccessToken;
150
+ this.fetchImpl = requireFetchImplementation(config);
151
+ const baseUrl = base === "spend" ? config.spendRequestBaseUrl : config.apiBaseUrl;
152
+ this.endpoint = `${baseUrl}${endpointPath}`;
153
+ this.logger = config.logger;
154
+ }
155
+ async rawFetch(opts) {
156
+ if (this.verbose) {
157
+ this.logger.debug(`> ${opts.method} ${opts.url}`);
158
+ }
159
+ let response;
160
+ try {
161
+ const init = {
162
+ method: opts.method,
163
+ ...opts.headers !== void 0 && { headers: opts.headers },
164
+ ...opts.body !== void 0 && { body: opts.body },
165
+ ...opts.signal !== void 0 && { signal: opts.signal },
166
+ ...opts.redirect !== void 0 && { redirect: opts.redirect }
167
+ };
168
+ response = await this.fetchImpl(opts.url, init);
169
+ } catch (error) {
170
+ throw new LinkTransportError(
171
+ `Request failed: ${opts.method} ${opts.url}`,
172
+ { cause: error }
173
+ );
174
+ }
175
+ const rawBody = await response.text();
176
+ let data = null;
177
+ try {
178
+ data = JSON.parse(rawBody);
179
+ } catch {
180
+ }
181
+ if (this.verbose) {
182
+ this.logger.debug(`< ${response.status} ${response.statusText}`);
183
+ }
184
+ return { status: response.status, data, rawBody };
185
+ }
186
+ async apiFetch(opts) {
187
+ const token = await this.getAccessToken();
188
+ const authedOpts = {
189
+ ...opts,
190
+ headers: {
191
+ ...opts.headers,
192
+ Authorization: `Bearer ${token}`
193
+ }
194
+ };
195
+ const res = await this.rawFetch(authedOpts);
196
+ if (res.status === 401 && this.canRefreshAccessToken) {
197
+ const refreshedToken = await this.getAccessToken({ forceRefresh: true });
198
+ return this.rawFetch({
199
+ ...opts,
200
+ headers: {
201
+ ...opts.headers,
202
+ Authorization: `Bearer ${refreshedToken}`
203
+ }
204
+ });
205
+ }
206
+ return res;
207
+ }
208
+ throwApiError(operation, status, data, rawBody, cause) {
209
+ const msg = extractErrorMessage(data, rawBody);
210
+ throw new LinkApiError(`Failed to ${operation} (${status}): ${msg}`, {
211
+ status,
212
+ rawBody,
213
+ details: data,
214
+ cause
215
+ });
216
+ }
217
+ parseResponse(operation, status, parser) {
218
+ try {
219
+ return parser();
220
+ } catch (error) {
221
+ throw new LinkResponseError(operation, status, { cause: error });
222
+ }
223
+ }
224
+ };
225
+
226
+ // src/resources/approval-policy.ts
227
+ var approvalPolicySchema = z.looseObject({
228
+ rules: z.array(
229
+ z.looseObject({
230
+ action: z.string(),
231
+ limits: z.looseObject({
232
+ per_purchase: z.looseObject({
233
+ amount: z.number().int(),
234
+ currency: z.string()
235
+ })
236
+ }),
237
+ allowed_payment_methods: z.array(z.string()).optional()
238
+ })
239
+ )
240
+ });
241
+ var ApprovalPolicyResource = class extends BaseResource {
242
+ constructor(options) {
243
+ super(options, "/approval-policy");
244
+ }
245
+ async retrieve() {
246
+ const { status, data, rawBody } = await this.apiFetch({
247
+ method: "GET",
248
+ url: this.endpoint
249
+ });
250
+ if (status < 200 || status >= 300) {
251
+ this.throwApiError("retrieve approval policy", status, data, rawBody);
252
+ }
253
+ return this.parseResponse(
254
+ "retrieve approval policy",
255
+ status,
256
+ () => approvalPolicySchema.parse(data)
257
+ );
258
+ }
259
+ };
260
+
261
+ // src/resources/attestations.ts
262
+ import { createHash as createHash2 } from "crypto";
263
+ import { z as z2 } from "zod";
264
+
48
265
  // src/resources/attestations-crypto.ts
49
266
  import {
50
267
  createHash,
@@ -385,196 +602,23 @@ function computeChallengeDigest(tokenType, issuerName) {
385
602
  }
386
603
  const challenge = Buffer.alloc(
387
604
  2 + 2 + issuerBytes.length + 1 + 2 + originBytes.length
388
- );
389
- let offset = 0;
390
- challenge.writeUInt16BE(tokenType, offset);
391
- offset += 2;
392
- challenge.writeUInt16BE(issuerBytes.length, offset);
393
- offset += 2;
394
- issuerBytes.copy(challenge, offset);
395
- offset += issuerBytes.length;
396
- challenge.writeUInt8(0, offset);
397
- offset += 1;
398
- challenge.writeUInt16BE(originBytes.length, offset);
399
- offset += 2;
400
- if (originBytes.length > 0) {
401
- originBytes.copy(challenge, offset);
402
- }
403
- return new Uint8Array(createHash("sha256").update(challenge).digest());
404
- }
405
-
406
- // src/config.ts
407
- var DEFAULT_API_BASE_URL = "https://api.link.com";
408
- function createDefaultHeadersFetch(baseFetch, defaultHeaders) {
409
- return ((input, init) => {
410
- const headers = new Headers(init?.headers);
411
- for (const [key, value] of Object.entries(defaultHeaders)) {
412
- if (!headers.has(key)) {
413
- headers.set(key, value);
414
- }
415
- }
416
- return baseFetch(input, { ...init, headers });
417
- });
418
- }
419
- function createDefaultLogger() {
420
- return {
421
- debug() {
422
- }
423
- };
424
- }
425
- function resolveLinkSdkConfig(options, defaults = {}) {
426
- const verbose = options.verbose ?? false;
427
- const logger = options.logger ?? createDefaultLogger();
428
- if (options.accessToken !== void 0 && options.getAccessToken !== void 0) {
429
- throw new LinkConfigurationError(
430
- "Pass either `accessToken` or `getAccessToken`, not both."
431
- );
432
- }
433
- let getAccessToken;
434
- let canRefreshAccessToken;
435
- if (options.accessToken !== void 0) {
436
- if (options.accessToken.trim().length === 0) {
437
- throw new LinkConfigurationError("`accessToken` cannot be empty.");
438
- }
439
- const accessToken = options.accessToken;
440
- getAccessToken = () => accessToken;
441
- canRefreshAccessToken = false;
442
- } else if (typeof options.getAccessToken === "function") {
443
- getAccessToken = options.getAccessToken;
444
- canRefreshAccessToken = true;
445
- } else {
446
- throw new LinkConfigurationError(
447
- "Pass `accessToken` or `getAccessToken` to the Link client."
448
- );
449
- }
450
- const apiBaseUrl = options.apiBaseUrl ?? defaults.apiBaseUrl ?? DEFAULT_API_BASE_URL;
451
- const spendRequestBaseUrl = options.spendRequestBaseUrl ?? defaults.spendRequestBaseUrl ?? apiBaseUrl;
452
- const baseFetch = options.fetch ?? globalThis.fetch;
453
- const effectiveFetch = options.defaultHeaders && Object.keys(options.defaultHeaders).length > 0 ? createDefaultHeadersFetch(baseFetch, options.defaultHeaders) : baseFetch;
454
- return {
455
- verbose,
456
- getAccessToken,
457
- canRefreshAccessToken,
458
- fetch: effectiveFetch,
459
- apiBaseUrl,
460
- spendRequestBaseUrl,
461
- logger
462
- };
463
- }
464
- function requireFetchImplementation(config) {
465
- if (!config.fetch) {
466
- throw new LinkConfigurationError(
467
- "No fetch implementation available. Pass `fetch` in Link SDK options."
468
- );
469
- }
470
- return config.fetch;
471
- }
472
-
473
- // src/resources/base.ts
474
- function isRecord(value) {
475
- return value !== null && typeof value === "object" && !Array.isArray(value);
476
- }
477
- function extractErrorMessage(data, rawBody) {
478
- if (isRecord(data)) {
479
- if (typeof data.error === "string") {
480
- return data.error;
481
- }
482
- if (isRecord(data.error)) {
483
- const nested = data.error;
484
- if (typeof nested.message === "string") {
485
- return nested.message;
486
- }
487
- if (typeof nested.code === "string") {
488
- return nested.code;
489
- }
490
- }
491
- if (typeof data.message === "string") {
492
- return data.message;
493
- }
494
- }
495
- return rawBody || "unknown error";
496
- }
497
- var BaseResource = class {
498
- verbose;
499
- getAccessToken;
500
- canRefreshAccessToken;
501
- fetchImpl;
502
- endpoint;
503
- logger;
504
- constructor(options, endpointPath, base = "api") {
505
- const config = resolveLinkSdkConfig(options);
506
- this.verbose = config.verbose;
507
- this.getAccessToken = config.getAccessToken;
508
- this.canRefreshAccessToken = config.canRefreshAccessToken;
509
- this.fetchImpl = requireFetchImplementation(config);
510
- const baseUrl = base === "spend" ? config.spendRequestBaseUrl : config.apiBaseUrl;
511
- this.endpoint = `${baseUrl}${endpointPath}`;
512
- this.logger = config.logger;
513
- }
514
- async rawFetch(opts) {
515
- if (this.verbose) {
516
- this.logger.debug(`> ${opts.method} ${opts.url}`);
517
- }
518
- let response;
519
- try {
520
- const init = {
521
- method: opts.method,
522
- ...opts.headers !== void 0 && { headers: opts.headers },
523
- ...opts.body !== void 0 && { body: opts.body },
524
- ...opts.signal !== void 0 && { signal: opts.signal }
525
- };
526
- response = await this.fetchImpl(opts.url, init);
527
- } catch (error) {
528
- throw new LinkTransportError(
529
- `Request failed: ${opts.method} ${opts.url}`,
530
- { cause: error }
531
- );
532
- }
533
- const rawBody = await response.text();
534
- let data = null;
535
- try {
536
- data = JSON.parse(rawBody);
537
- } catch {
538
- }
539
- if (this.verbose) {
540
- this.logger.debug(`< ${response.status} ${response.statusText}`);
541
- }
542
- return { status: response.status, data, rawBody };
543
- }
544
- async apiFetch(opts) {
545
- const token = await this.getAccessToken();
546
- const authedOpts = {
547
- ...opts,
548
- headers: {
549
- ...opts.headers,
550
- Authorization: `Bearer ${token}`
551
- }
552
- };
553
- const res = await this.rawFetch(authedOpts);
554
- if (res.status === 401 && this.canRefreshAccessToken) {
555
- const refreshedToken = await this.getAccessToken({ forceRefresh: true });
556
- authedOpts.headers.Authorization = `Bearer ${refreshedToken}`;
557
- return this.rawFetch(authedOpts);
558
- }
559
- return res;
560
- }
561
- throwApiError(operation, status, data, rawBody, cause) {
562
- const msg = extractErrorMessage(data, rawBody);
563
- throw new LinkApiError(`Failed to ${operation} (${status}): ${msg}`, {
564
- status,
565
- rawBody,
566
- details: data,
567
- cause
568
- });
569
- }
570
- parseResponse(operation, status, parser) {
571
- try {
572
- return parser();
573
- } catch (error) {
574
- throw new LinkResponseError(operation, status, { cause: error });
575
- }
605
+ );
606
+ let offset = 0;
607
+ challenge.writeUInt16BE(tokenType, offset);
608
+ offset += 2;
609
+ challenge.writeUInt16BE(issuerBytes.length, offset);
610
+ offset += 2;
611
+ issuerBytes.copy(challenge, offset);
612
+ offset += issuerBytes.length;
613
+ challenge.writeUInt8(0, offset);
614
+ offset += 1;
615
+ challenge.writeUInt16BE(originBytes.length, offset);
616
+ offset += 2;
617
+ if (originBytes.length > 0) {
618
+ originBytes.copy(challenge, offset);
576
619
  }
577
- };
620
+ return new Uint8Array(createHash("sha256").update(challenge).digest());
621
+ }
578
622
 
579
623
  // src/resources/attestations.ts
580
624
  var TOKEN_TYPE_BLIND_RSA = 2;
@@ -583,17 +627,17 @@ var CONTENT_TYPE_TOKEN_RESPONSE = "application/private-token-generic-batch-respo
583
627
  var LINK_ISSUER = "https://api.link.com";
584
628
  var LINK_ISSUER_HOSTNAME = "api.link.com";
585
629
  var LINK_ISSUER_METADATA_URL = `${LINK_ISSUER}/.well-known/aap-issuer`;
586
- var issuerMetadataSchema = z.looseObject({
587
- issuer: z.literal(LINK_ISSUER),
588
- token_issuance_endpoint: z.string(),
589
- token_keys: z.string()
630
+ var issuerMetadataSchema = z2.looseObject({
631
+ issuer: z2.literal(LINK_ISSUER),
632
+ token_issuance_endpoint: z2.string(),
633
+ token_keys: z2.string()
590
634
  });
591
- var tokenKeyDirectorySchema = z.looseObject({
592
- "token-keys": z.array(
593
- z.looseObject({
594
- "token-type": z.number(),
595
- "token-key": z.string(),
596
- "not-before": z.number().int().nonnegative().optional()
635
+ var tokenKeyDirectorySchema = z2.looseObject({
636
+ "token-keys": z2.array(
637
+ z2.looseObject({
638
+ "token-type": z2.number(),
639
+ "token-key": z2.string(),
640
+ "not-before": z2.number().int().nonnegative().optional()
597
641
  })
598
642
  )
599
643
  });
@@ -906,20 +950,20 @@ var AttestationsResource = class extends BaseResource {
906
950
  };
907
951
 
908
952
  // src/resources/balances.ts
909
- import { z as z2 } from "zod";
910
- var currencyAmountsSchema = z2.record(z2.string(), z2.number());
911
- var balanceSchema = z2.looseObject({
912
- source_id: z2.string(),
913
- type: z2.enum(["cash", "credit"]),
914
- cash: z2.looseObject({ available: currencyAmountsSchema }).nullable().optional(),
915
- credit: z2.looseObject({ used: currencyAmountsSchema.nullable() }).nullable().optional(),
916
- current: z2.number(),
917
- currency: z2.string(),
918
- as_of: z2.string()
953
+ import { z as z3 } from "zod";
954
+ var currencyAmountsSchema = z3.record(z3.string(), z3.number());
955
+ var balanceSchema = z3.looseObject({
956
+ source_id: z3.string(),
957
+ type: z3.enum(["cash", "credit"]),
958
+ cash: z3.looseObject({ available: currencyAmountsSchema }).nullable().optional(),
959
+ credit: z3.looseObject({ used: currencyAmountsSchema.nullable() }).nullable().optional(),
960
+ current: z3.number(),
961
+ currency: z3.string(),
962
+ as_of: z3.string()
919
963
  });
920
- var balancesPageSchema = z2.looseObject({
921
- data: z2.array(balanceSchema),
922
- has_more: z2.boolean().optional()
964
+ var balancesPageSchema = z3.looseObject({
965
+ data: z3.array(balanceSchema),
966
+ has_more: z3.boolean().optional()
923
967
  });
924
968
  var BalancesResource = class extends BaseResource {
925
969
  constructor(options) {
@@ -959,17 +1003,150 @@ var BalancesResource = class extends BaseResource {
959
1003
  }
960
1004
  };
961
1005
 
1006
+ // src/resources/identity-credentials.ts
1007
+ import { z as z4 } from "zod";
1008
+
1009
+ // src/resources/holder-jwk.ts
1010
+ import { createHash as createHash3 } from "crypto";
1011
+ function isRecord2(value) {
1012
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1013
+ }
1014
+ function holderJwkThumbprint(jwk) {
1015
+ const canonical = JSON.stringify({
1016
+ crv: jwk.crv,
1017
+ kty: jwk.kty,
1018
+ x: jwk.x
1019
+ });
1020
+ return createHash3("sha256").update(canonical).digest("base64url");
1021
+ }
1022
+ function holderJwksEqual(left, right) {
1023
+ return holderJwkThumbprint(left) === holderJwkThumbprint(right);
1024
+ }
1025
+ function parseHolderPublicJwk(value) {
1026
+ if (!isRecord2(value)) {
1027
+ throw new LinkConfigurationError("Holder public key must be a JWK object");
1028
+ }
1029
+ if (typeof value.kty !== "string") {
1030
+ throw new LinkConfigurationError("Holder public key is missing kty");
1031
+ }
1032
+ if (value.kty !== "OKP" || value.crv !== "Ed25519" || typeof value.x !== "string" || value.x.length === 0) {
1033
+ throw new LinkConfigurationError(
1034
+ "Holder public key must be an Ed25519 OKP JWK with an x member"
1035
+ );
1036
+ }
1037
+ return { kty: "OKP", crv: "Ed25519", x: value.x };
1038
+ }
1039
+
1040
+ // src/resources/identity-credentials.ts
1041
+ var LINK_ISSUER2 = "https://api.link.com";
1042
+ var LINK_ISSUER_METADATA_URL2 = `${LINK_ISSUER2}/.well-known/aap-issuer`;
1043
+ var identityCredentialIssuerMetadataSchema = z4.looseObject({
1044
+ issuer: z4.literal(LINK_ISSUER2),
1045
+ credential_endpoint: z4.string()
1046
+ });
1047
+ var issueIdentityCredentialResponseSchema = z4.looseObject({
1048
+ credential: z4.string(),
1049
+ issuer: z4.literal(LINK_ISSUER2),
1050
+ expires_at: z4.string()
1051
+ });
1052
+ function requireLinkEndpoint2(value, field) {
1053
+ let url;
1054
+ try {
1055
+ url = new URL(value);
1056
+ } catch (error) {
1057
+ throw new TypeError(`${field} is not a valid URL`, { cause: error });
1058
+ }
1059
+ if (url.protocol !== "https:" || url.origin !== LINK_ISSUER2 || url.username || url.password) {
1060
+ throw new TypeError(`${field} must be an HTTPS URL on ${LINK_ISSUER2}`);
1061
+ }
1062
+ return url.href;
1063
+ }
1064
+ var IdentityCredentialsResource = class extends BaseResource {
1065
+ constructor(options) {
1066
+ super(options, "");
1067
+ }
1068
+ async discoverCredentialEndpoint() {
1069
+ const { status, data, rawBody } = await this.rawFetch({
1070
+ method: "GET",
1071
+ url: LINK_ISSUER_METADATA_URL2,
1072
+ redirect: "manual"
1073
+ });
1074
+ if (status >= 300 && status < 400) {
1075
+ throw new LinkApiError(
1076
+ `Refused redirect while fetching identity credential issuer metadata (${status})`,
1077
+ { status, rawBody }
1078
+ );
1079
+ }
1080
+ if (status < 200 || status >= 300) {
1081
+ this.throwApiError(
1082
+ "fetch identity credential issuer metadata",
1083
+ status,
1084
+ data,
1085
+ rawBody
1086
+ );
1087
+ }
1088
+ const metadata = this.parseResponse(
1089
+ "parse identity credential issuer metadata",
1090
+ status,
1091
+ () => identityCredentialIssuerMetadataSchema.parse(data)
1092
+ );
1093
+ return this.parseResponse(
1094
+ "validate identity credential issuer metadata",
1095
+ status,
1096
+ () => requireLinkEndpoint2(
1097
+ metadata.credential_endpoint,
1098
+ "credential_endpoint"
1099
+ )
1100
+ );
1101
+ }
1102
+ async issue(params) {
1103
+ const publicJwk = parseHolderPublicJwk(params.cnf.jwk);
1104
+ const endpoint = await this.discoverCredentialEndpoint();
1105
+ const { status, data, rawBody } = await this.apiFetch({
1106
+ method: "POST",
1107
+ url: endpoint,
1108
+ redirect: "manual",
1109
+ headers: {
1110
+ "Content-Type": "application/json",
1111
+ Accept: "application/json"
1112
+ },
1113
+ body: JSON.stringify({ cnf: { jwk: publicJwk } })
1114
+ });
1115
+ if (status >= 300 && status < 400) {
1116
+ throw new LinkApiError(
1117
+ `Refused redirect while issuing identity credential (${status})`,
1118
+ { status, rawBody }
1119
+ );
1120
+ }
1121
+ if (status < 200 || status >= 300) {
1122
+ this.throwApiError("issue identity credential", status, data, rawBody);
1123
+ }
1124
+ return this.parseResponse(
1125
+ "issue identity credential",
1126
+ status,
1127
+ () => issueIdentityCredentialResponseSchema.parse(data)
1128
+ );
1129
+ }
1130
+ };
1131
+
962
1132
  // src/resources/payment-methods.ts
963
- import { z as z3 } from "zod";
964
- var paymentMethodSchema = z3.looseObject({
965
- id: z3.string(),
966
- type: z3.string(),
967
- is_default: z3.boolean(),
968
- name: z3.string(),
969
- nickname: z3.optional(z3.string().nullable())
1133
+ import { z as z5 } from "zod";
1134
+ var balanceDetailsSchema = z5.looseObject({
1135
+ available_balance: z5.looseObject({
1136
+ amount: z5.number().int(),
1137
+ currency: z5.string()
1138
+ }).optional()
970
1139
  });
971
- var paymentMethodsResponseSchema = z3.looseObject({
972
- payment_details: z3.array(paymentMethodSchema)
1140
+ var paymentMethodSchema = z5.looseObject({
1141
+ id: z5.string(),
1142
+ type: z5.string(),
1143
+ is_default: z5.boolean(),
1144
+ name: z5.string(),
1145
+ nickname: z5.optional(z5.string().nullable()),
1146
+ balance_details: balanceDetailsSchema.nullable().optional()
1147
+ });
1148
+ var paymentMethodsResponseSchema = z5.looseObject({
1149
+ payment_details: z5.array(paymentMethodSchema)
973
1150
  });
974
1151
  var PaymentMethodsResource = class extends BaseResource {
975
1152
  constructor(options) {
@@ -989,17 +1166,48 @@ var PaymentMethodsResource = class extends BaseResource {
989
1166
  () => paymentMethodsResponseSchema.parse(data).payment_details
990
1167
  );
991
1168
  }
1169
+ async retrieve(id) {
1170
+ const { status, data, rawBody } = await this.apiFetch({
1171
+ method: "GET",
1172
+ url: `${this.endpoint}/${encodeURIComponent(id)}`
1173
+ });
1174
+ if (status === 404) return null;
1175
+ if (status < 200 || status >= 300) {
1176
+ this.throwApiError("retrieve payment method", status, data, rawBody);
1177
+ }
1178
+ return this.parseResponse(
1179
+ "retrieve payment method",
1180
+ status,
1181
+ () => paymentMethodSchema.parse(data)
1182
+ );
1183
+ }
1184
+ async update(id, params) {
1185
+ const { status, data, rawBody } = await this.apiFetch({
1186
+ method: "POST",
1187
+ url: `${this.endpoint}/${encodeURIComponent(id)}`,
1188
+ headers: { "Content-Type": "application/json" },
1189
+ body: JSON.stringify({ nickname: params.nickname })
1190
+ });
1191
+ if (status < 200 || status >= 300) {
1192
+ this.throwApiError("update payment method", status, data, rawBody);
1193
+ }
1194
+ return this.parseResponse(
1195
+ "update payment method",
1196
+ status,
1197
+ () => paymentMethodSchema.parse(data)
1198
+ );
1199
+ }
992
1200
  };
993
1201
 
994
1202
  // src/resources/report.ts
995
- import { z as z4 } from "zod";
996
- var reportRecordSchema = z4.looseObject({
997
- object: z4.string(),
998
- created_at: z4.string(),
999
- domain: z4.string(),
1000
- outcome: z4.string(),
1001
- spend_request_id: z4.string(),
1002
- status: z4.string()
1203
+ import { z as z6 } from "zod";
1204
+ var reportRecordSchema = z6.looseObject({
1205
+ object: z6.string(),
1206
+ created_at: z6.string(),
1207
+ domain: z6.string(),
1208
+ outcome: z6.string(),
1209
+ spend_request_id: z6.string(),
1210
+ status: z6.string()
1003
1211
  });
1004
1212
  var ReportResource = class extends BaseResource {
1005
1213
  constructor(options) {
@@ -1024,15 +1232,15 @@ var ReportResource = class extends BaseResource {
1024
1232
  };
1025
1233
 
1026
1234
  // src/resources/shipping-address.ts
1027
- import { z as z5 } from "zod";
1028
- var shippingAddressSchema = z5.looseObject({
1029
- id: z5.string(),
1030
- is_default: z5.boolean(),
1031
- nickname: z5.optional(z5.string().nullable()),
1032
- address: z5.looseObject({}).nullable()
1235
+ import { z as z7 } from "zod";
1236
+ var shippingAddressSchema = z7.looseObject({
1237
+ id: z7.string(),
1238
+ is_default: z7.boolean(),
1239
+ nickname: z7.optional(z7.string().nullable()),
1240
+ address: z7.looseObject({}).nullable()
1033
1241
  });
1034
- var shippingAddressesResponseSchema = z5.looseObject({
1035
- shipping_addresses: z5.array(shippingAddressSchema)
1242
+ var shippingAddressesResponseSchema = z7.looseObject({
1243
+ shipping_addresses: z7.array(shippingAddressSchema)
1036
1244
  });
1037
1245
  var ShippingAddressResource = class extends BaseResource {
1038
1246
  constructor(options) {
@@ -1055,21 +1263,21 @@ var ShippingAddressResource = class extends BaseResource {
1055
1263
  };
1056
1264
 
1057
1265
  // src/resources/sources.ts
1058
- import { z as z6 } from "zod";
1059
- var nullableRecordSchema = z6.record(z6.string(), z6.unknown()).nullable().optional();
1060
- var sourceSchema = z6.looseObject({
1061
- id: z6.string().nullable().optional(),
1062
- name: z6.string().nullable().optional(),
1063
- type: z6.string().nullable().optional(),
1266
+ import { z as z8 } from "zod";
1267
+ var nullableRecordSchema = z8.record(z8.string(), z8.unknown()).nullable().optional();
1268
+ var sourceSchema = z8.looseObject({
1269
+ id: z8.string().nullable().optional(),
1270
+ name: z8.string().nullable().optional(),
1271
+ type: z8.string().nullable().optional(),
1064
1272
  capabilities: nullableRecordSchema,
1065
1273
  external_connection: nullableRecordSchema,
1066
- granted_actions: z6.array(z6.string()).nullable().optional(),
1274
+ granted_actions: z8.array(z8.string()).nullable().optional(),
1067
1275
  bank_account: nullableRecordSchema,
1068
1276
  card: nullableRecordSchema
1069
1277
  });
1070
- var sourcesPageSchema = z6.looseObject({
1071
- data: z6.array(sourceSchema),
1072
- has_more: z6.boolean().optional()
1278
+ var sourcesPageSchema = z8.looseObject({
1279
+ data: z8.array(sourceSchema),
1280
+ has_more: z8.boolean().optional()
1073
1281
  });
1074
1282
  var SourcesResource = class extends BaseResource {
1075
1283
  constructor(options) {
@@ -1105,34 +1313,34 @@ var SourcesResource = class extends BaseResource {
1105
1313
  };
1106
1314
 
1107
1315
  // src/resources/spend-request.ts
1108
- import { z as z7 } from "zod";
1109
- var sharedPaymentTokenSchema = z7.union([
1110
- z7.string().transform((id) => ({ id })),
1111
- z7.looseObject({ id: z7.string() })
1316
+ import { z as z9 } from "zod";
1317
+ var sharedPaymentTokenSchema = z9.union([
1318
+ z9.string().transform((id) => ({ id })),
1319
+ z9.looseObject({ id: z9.string() })
1112
1320
  ]);
1113
- var spendRequestSchema = z7.looseObject({
1114
- id: z7.string(),
1115
- payment_details: z7.string().optional(),
1116
- status: z7.string(),
1117
- line_items: z7.array(z7.unknown()).optional(),
1118
- totals: z7.array(z7.unknown()).optional(),
1119
- created_at: z7.string(),
1120
- updated_at: z7.string(),
1321
+ var spendRequestSchema = z9.looseObject({
1322
+ id: z9.string(),
1323
+ payment_details: z9.string().optional(),
1324
+ status: z9.string(),
1325
+ line_items: z9.array(z9.unknown()).optional(),
1326
+ totals: z9.array(z9.unknown()).optional(),
1327
+ created_at: z9.string(),
1328
+ updated_at: z9.string(),
1121
1329
  shared_payment_token: sharedPaymentTokenSchema.nullable().optional()
1122
1330
  });
1123
- var spendRequestsResponseSchema = z7.looseObject({
1124
- data: z7.array(spendRequestSchema)
1331
+ var spendRequestsResponseSchema = z9.looseObject({
1332
+ data: z9.array(spendRequestSchema)
1125
1333
  });
1126
- var requestApprovalResponseSchema = z7.looseObject({
1127
- id: z7.string(),
1128
- approval_link: z7.string()
1334
+ var requestApprovalResponseSchema = z9.looseObject({
1335
+ id: z9.string(),
1336
+ approval_link: z9.string()
1129
1337
  }).transform(({ approval_link, ...response }) => ({
1130
1338
  ...response,
1131
1339
  approval_url: approval_link
1132
1340
  }));
1133
- var duplicateSpendRequestErrorSchema = z7.looseObject({
1134
- error: z7.looseObject({
1135
- duplicate_spend_request: z7.unknown().optional()
1341
+ var duplicateSpendRequestErrorSchema = z9.looseObject({
1342
+ error: z9.looseObject({
1343
+ duplicate_spend_request: z9.unknown().optional()
1136
1344
  })
1137
1345
  });
1138
1346
  function parseSpendRequest(value) {
@@ -1251,83 +1459,24 @@ var SpendRequestResource = class extends BaseResource {
1251
1459
  }
1252
1460
  };
1253
1461
 
1254
- // src/resources/summaries.ts
1255
- import { z as z8 } from "zod";
1256
- var summaryValueSchema = z8.discriminatedUnion("unit", [
1257
- z8.looseObject({ unit: z8.literal("count"), count: z8.number() }),
1258
- z8.looseObject({
1259
- unit: z8.literal("payment_volume"),
1260
- amount: z8.number(),
1261
- currency: z8.string()
1262
- })
1263
- ]);
1264
- var summaryDataValueSchema = z8.discriminatedUnion("unit", [
1265
- z8.looseObject({ unit: z8.literal("count"), amount: z8.number() }),
1266
- z8.looseObject({
1267
- unit: z8.literal("payment_volume"),
1268
- amount: z8.number(),
1269
- currency: z8.string()
1270
- })
1271
- ]);
1272
- var summarySchema = z8.looseObject({
1273
- id: z8.string(),
1274
- description: z8.string(),
1275
- created_at: z8.string().nullable().optional(),
1276
- status: z8.enum(["ready", "pending", "no_data"]),
1277
- entries: z8.array(z8.looseObject({ label: z8.string(), value: summaryValueSchema })).default([]),
1278
- as_of: z8.number().optional(),
1279
- data: z8.array(z8.looseObject({ label: z8.string(), value: summaryDataValueSchema })).nullable().optional()
1280
- });
1281
- var summariesPageSchema = z8.looseObject({
1282
- data: z8.array(summarySchema),
1283
- has_more: z8.boolean().optional()
1284
- });
1285
- var SummariesResource = class extends BaseResource {
1286
- constructor(options) {
1287
- super(options, "/summaries");
1288
- }
1289
- buildUrl(params) {
1290
- const url = new URL(this.endpoint);
1291
- if (params.starting_after !== void 0)
1292
- url.searchParams.set("starting_after", params.starting_after);
1293
- if (params.summaries !== void 0)
1294
- for (const summary of params.summaries)
1295
- url.searchParams.append("summaries[]", summary);
1296
- return url.toString();
1297
- }
1298
- async list(params = {}) {
1299
- const { status, data, rawBody } = await this.apiFetch({
1300
- method: "GET",
1301
- url: this.buildUrl(params)
1302
- });
1303
- if (status < 200 || status >= 300)
1304
- this.throwApiError("list summaries", status, data, rawBody);
1305
- return this.parseResponse(
1306
- "list summaries",
1307
- status,
1308
- () => summariesPageSchema.parse(data)
1309
- );
1310
- }
1311
- };
1312
-
1313
1462
  // src/resources/transactions.ts
1314
- import { z as z9 } from "zod";
1315
- var transactionSchema = z9.looseObject({
1316
- id: z9.string(),
1317
- source_id: z9.string().nullable(),
1318
- amount: z9.number(),
1319
- currency: z9.string(),
1320
- created_date: z9.string(),
1321
- description: z9.string(),
1322
- origin: z9.enum(["link", "external_connection"]),
1323
- category: z9.string().nullable(),
1324
- status: z9.string()
1463
+ import { z as z10 } from "zod";
1464
+ var transactionSchema = z10.looseObject({
1465
+ id: z10.string(),
1466
+ source_id: z10.string().nullable(),
1467
+ amount: z10.number(),
1468
+ currency: z10.string(),
1469
+ created_date: z10.string(),
1470
+ description: z10.string(),
1471
+ origin: z10.enum(["link", "external_connection"]),
1472
+ category: z10.string().nullable(),
1473
+ status: z10.string()
1325
1474
  });
1326
- var transactionsPageSchema = z9.union([
1327
- z9.array(transactionSchema).transform((data) => ({ data })),
1328
- z9.looseObject({
1329
- data: z9.array(transactionSchema),
1330
- has_more: z9.boolean().optional()
1475
+ var transactionsPageSchema = z10.union([
1476
+ z10.array(transactionSchema).transform((data) => ({ data })),
1477
+ z10.looseObject({
1478
+ data: z10.array(transactionSchema),
1479
+ has_more: z10.boolean().optional()
1331
1480
  })
1332
1481
  ]);
1333
1482
  var TransactionsResource = class extends BaseResource {
@@ -1380,53 +1529,273 @@ var TransactionsResource = class extends BaseResource {
1380
1529
  }
1381
1530
  };
1382
1531
 
1532
+ // src/resources/ucp.ts
1533
+ function extractApiError(data, rawBody) {
1534
+ if (data && typeof data === "object") {
1535
+ const body = data;
1536
+ if (body.error && typeof body.error === "object") {
1537
+ const err = body.error;
1538
+ if (typeof err.message === "string") return err.message;
1539
+ }
1540
+ if (typeof body.error === "string") return body.error;
1541
+ if (typeof body.message === "string") return body.message;
1542
+ }
1543
+ return rawBody || "unknown error";
1544
+ }
1545
+ function normalizeSearchResult(data) {
1546
+ const body = data ?? {};
1547
+ const items = Array.isArray(body.data) ? body.data : [];
1548
+ return { ...body, data: items };
1549
+ }
1550
+ function normalizeCheckout(data) {
1551
+ const body = data ?? {};
1552
+ return { ...body, id: String(body.id ?? "") };
1553
+ }
1554
+ var UcpResource = class {
1555
+ verbose;
1556
+ getAccessToken;
1557
+ fetchImpl;
1558
+ ucpEndpoint;
1559
+ logger;
1560
+ constructor(options) {
1561
+ const config = resolveLinkSdkConfig(options);
1562
+ this.verbose = config.verbose;
1563
+ this.getAccessToken = config.getAccessToken;
1564
+ this.fetchImpl = requireFetchImplementation(config);
1565
+ this.ucpEndpoint = `${config.apiBaseUrl}/ucp`;
1566
+ this.logger = config.logger;
1567
+ }
1568
+ async rawFetch(opts) {
1569
+ if (this.verbose) {
1570
+ const redactedHeaders = { ...opts.headers };
1571
+ if (redactedHeaders.Authorization)
1572
+ redactedHeaders.Authorization = "Bearer <redacted>";
1573
+ this.logger.debug(`> ${opts.method} ${opts.url}`);
1574
+ this.logger.debug(` Headers: ${JSON.stringify(redactedHeaders)}`);
1575
+ if (opts.body) this.logger.debug(opts.body);
1576
+ }
1577
+ const fetchOpts = {
1578
+ method: opts.method,
1579
+ ...opts.headers ? { headers: opts.headers } : {}
1580
+ };
1581
+ if (opts.body) fetchOpts.body = opts.body;
1582
+ let response;
1583
+ try {
1584
+ response = await this.fetchImpl(opts.url, fetchOpts);
1585
+ } catch (error) {
1586
+ throw new LinkTransportError(
1587
+ `Request failed: ${opts.method} ${opts.url}`,
1588
+ {
1589
+ cause: error
1590
+ }
1591
+ );
1592
+ }
1593
+ const rawBody = await response.text();
1594
+ let data = null;
1595
+ try {
1596
+ data = JSON.parse(rawBody);
1597
+ } catch {
1598
+ }
1599
+ if (this.verbose) {
1600
+ this.logger.debug(`< ${response.status} ${response.statusText}`);
1601
+ response.headers.forEach((value, key) => {
1602
+ this.logger.debug(` ${key}: ${value}`);
1603
+ });
1604
+ this.logger.debug(JSON.stringify(data, null, 2) ?? rawBody);
1605
+ }
1606
+ return { status: response.status, data, rawBody };
1607
+ }
1608
+ /** Injects the Bearer token; retries once on 401 after refreshing. */
1609
+ async apiFetch(opts) {
1610
+ const token = await this.getAccessToken();
1611
+ const authedOpts = {
1612
+ ...opts,
1613
+ headers: { ...opts.headers, Authorization: `Bearer ${token}` }
1614
+ };
1615
+ const res = await this.rawFetch(authedOpts);
1616
+ if (res.status === 401) {
1617
+ const refreshedToken = await this.getAccessToken({ forceRefresh: true });
1618
+ authedOpts.headers.Authorization = `Bearer ${refreshedToken}`;
1619
+ return this.rawFetch(authedOpts);
1620
+ }
1621
+ return res;
1622
+ }
1623
+ buildSearchUrl(params) {
1624
+ const url = new URL(`${this.ucpEndpoint}/catalog/search`);
1625
+ const setIf = (key, value) => {
1626
+ if (value !== void 0) url.searchParams.set(key, String(value));
1627
+ };
1628
+ setIf("query", params.query);
1629
+ setIf("profile_id", params.profile_id);
1630
+ setIf("sku", params.sku);
1631
+ setIf("price_min", params.price_min);
1632
+ setIf("price_max", params.price_max);
1633
+ setIf("currency", params.currency);
1634
+ setIf("availability", params.availability);
1635
+ setIf("sort", params.sort);
1636
+ setIf("group_by", params.group_by);
1637
+ setIf("limit", params.limit);
1638
+ setIf("offset", params.offset);
1639
+ if (params.include_facets) url.searchParams.set("include_facets", "true");
1640
+ const arrays = [
1641
+ ["brand", params.brand],
1642
+ ["category", params.category],
1643
+ ["color", params.color],
1644
+ ["size", params.size],
1645
+ ["material", params.material],
1646
+ ["gender", params.gender],
1647
+ ["condition", params.condition]
1648
+ ];
1649
+ for (const [key, values] of arrays) {
1650
+ if (values)
1651
+ for (const value of values) url.searchParams.append(`${key}[]`, value);
1652
+ }
1653
+ if (params.test) url.searchParams.set("test", "true");
1654
+ return url.toString();
1655
+ }
1656
+ async searchCatalog(params) {
1657
+ const { status, data, rawBody } = await this.apiFetch({
1658
+ method: "GET",
1659
+ url: this.buildSearchUrl(params)
1660
+ });
1661
+ if (status < 200 || status >= 300) {
1662
+ throw new LinkApiError(
1663
+ `Failed to search UCP catalog (${status}): ${extractApiError(data, rawBody)}`,
1664
+ { status, rawBody, details: data }
1665
+ );
1666
+ }
1667
+ return normalizeSearchResult(data);
1668
+ }
1669
+ async createCheckout(params) {
1670
+ const body = {
1671
+ profile_id: params.profile_id,
1672
+ line_items: params.line_items
1673
+ };
1674
+ if (params.currency !== void 0) body.currency = params.currency;
1675
+ if (params.fulfillment_details !== void 0)
1676
+ body.fulfillment_details = params.fulfillment_details;
1677
+ if (params.test) body.test = true;
1678
+ const { status, data, rawBody } = await this.apiFetch({
1679
+ method: "POST",
1680
+ url: `${this.ucpEndpoint}/checkout`,
1681
+ headers: { "Content-Type": "application/json" },
1682
+ body: JSON.stringify(body)
1683
+ });
1684
+ if (status < 200 || status >= 300) {
1685
+ throw new LinkApiError(
1686
+ `Failed to create UCP checkout (${status}): ${extractApiError(data, rawBody)}`,
1687
+ { status, rawBody, details: data }
1688
+ );
1689
+ }
1690
+ return normalizeCheckout(data);
1691
+ }
1692
+ async completeCheckout(id, params) {
1693
+ const body = {
1694
+ spend_request_id: params.spend_request_id,
1695
+ profile_id: params.profile_id
1696
+ };
1697
+ if (params.test) body.test = true;
1698
+ const { status, data, rawBody } = await this.apiFetch({
1699
+ method: "POST",
1700
+ url: `${this.ucpEndpoint}/checkout/${encodeURIComponent(id)}/complete`,
1701
+ headers: { "Content-Type": "application/json" },
1702
+ body: JSON.stringify(body)
1703
+ });
1704
+ if (status < 200 || status >= 300) {
1705
+ throw new LinkApiError(
1706
+ `Failed to complete UCP checkout (${status}): ${extractApiError(data, rawBody)}`,
1707
+ { status, rawBody, details: data }
1708
+ );
1709
+ }
1710
+ return normalizeCheckout(data);
1711
+ }
1712
+ async retrieveCheckout(id, params) {
1713
+ const url = new URL(
1714
+ `${this.ucpEndpoint}/checkout/${encodeURIComponent(id)}`
1715
+ );
1716
+ url.searchParams.set("spend_request_id", params.spend_request_id);
1717
+ if (params.test) url.searchParams.set("test", "true");
1718
+ const { status, data, rawBody } = await this.apiFetch({
1719
+ method: "GET",
1720
+ url: url.toString()
1721
+ });
1722
+ if (status < 200 || status >= 300) {
1723
+ throw new LinkApiError(
1724
+ `Failed to retrieve UCP checkout (${status}): ${extractApiError(data, rawBody)}`,
1725
+ { status, rawBody, details: data }
1726
+ );
1727
+ }
1728
+ return normalizeCheckout(data);
1729
+ }
1730
+ };
1731
+
1383
1732
  // src/resources/user-info.ts
1384
- import { z as z10 } from "zod";
1385
- var rollingSpendLimitSchema = z10.object({
1386
- limit: z10.number().int().nullable(),
1387
- used: z10.number().int(),
1388
- remaining: z10.number().int().nullable()
1733
+ import { z as z11 } from "zod";
1734
+ var rollingSpendLimitSchema = z11.object({
1735
+ limit: z11.number().int().nullable(),
1736
+ used: z11.number().int(),
1737
+ remaining: z11.number().int().nullable()
1389
1738
  });
1390
- var agentWalletSpendLimitsSchema = z10.object({
1391
- per_transaction: z10.object({
1392
- limit: z10.number().int().nullable()
1739
+ var agentWalletSpendLimitsSchema = z11.object({
1740
+ per_transaction: z11.object({
1741
+ limit: z11.number().int().nullable()
1393
1742
  }),
1394
1743
  daily: rollingSpendLimitSchema,
1395
1744
  thirty_day: rollingSpendLimitSchema
1396
1745
  });
1397
- var agentWalletVerificationRequirementSchema = z10.object({
1398
- status: z10.enum([
1746
+ var agentWalletVerificationRequirementSchema = z11.object({
1747
+ status: z11.enum([
1399
1748
  "not_required",
1400
1749
  "ssn_verification",
1401
1750
  "identity_verification",
1402
1751
  "contact_support",
1403
1752
  "complete"
1404
1753
  ]),
1405
- action_url: z10.string().nullable()
1754
+ action_url: z11.string().nullable()
1406
1755
  });
1407
- var userInfoSchema = z10.looseObject({
1408
- email: z10.string().nullable().optional(),
1409
- name: z10.string().nullable().optional(),
1410
- first_name: z10.string().nullable().optional(),
1411
- last_name: z10.string().nullable().optional(),
1412
- phone: z10.string().nullable().optional(),
1756
+ var userInfoAddressSchema = z11.object({
1757
+ line1: z11.string().nullable(),
1758
+ line2: z11.string().nullable().optional(),
1759
+ city: z11.string().nullable(),
1760
+ state: z11.string().nullable(),
1761
+ postal_code: z11.string().nullable(),
1762
+ country: z11.string().nullable()
1763
+ }).transform(({ line2, ...address }) => ({
1764
+ ...address,
1765
+ ...line2 === void 0 ? {} : { line2 }
1766
+ }));
1767
+ var userInfoSchema = z11.looseObject({
1768
+ id: z11.string().min(1).optional(),
1769
+ email: z11.string().nullable().optional(),
1770
+ name: z11.string().nullable().optional(),
1771
+ first_name: z11.string().nullable().optional(),
1772
+ last_name: z11.string().nullable().optional(),
1773
+ phone: z11.string().nullable().optional(),
1774
+ address: userInfoAddressSchema.nullable().optional(),
1775
+ eligible_for_balance: z11.boolean().optional(),
1413
1776
  agent_wallet_spend_limits: agentWalletSpendLimitsSchema.optional(),
1414
1777
  agent_wallet_step_up: agentWalletVerificationRequirementSchema.optional()
1415
1778
  }).transform(
1416
1779
  ({
1780
+ id,
1417
1781
  email,
1418
1782
  name,
1419
1783
  first_name,
1420
1784
  last_name,
1421
1785
  phone,
1786
+ address,
1787
+ eligible_for_balance,
1422
1788
  agent_wallet_spend_limits,
1423
1789
  agent_wallet_step_up
1424
1790
  }) => ({
1791
+ ...id === void 0 ? {} : { id },
1425
1792
  email: email ?? null,
1426
1793
  name: name ?? null,
1427
1794
  first_name: first_name ?? null,
1428
1795
  last_name: last_name ?? null,
1429
1796
  phone: phone ?? null,
1797
+ ...address === void 0 ? {} : { address },
1798
+ ...eligible_for_balance === void 0 ? {} : { eligible_for_balance },
1430
1799
  ...agent_wallet_spend_limits === void 0 ? {} : { agent_wallet_spend_limits },
1431
1800
  ...agent_wallet_step_up === void 0 ? {} : { agent_wallet_verification_requirement: agent_wallet_step_up }
1432
1801
  })
@@ -1452,16 +1821,16 @@ var UserInfoResource = class extends BaseResource {
1452
1821
  };
1453
1822
 
1454
1823
  // src/resources/web-bot-auth.ts
1455
- import { z as z11 } from "zod";
1824
+ import { z as z12 } from "zod";
1456
1825
  var EXPIRY_BUFFER_MS = 3e4;
1457
- var webBotAuthBlockSchema = z11.looseObject({
1458
- signature: z11.string(),
1459
- signature_input: z11.string(),
1460
- signature_agent: z11.string(),
1461
- authority: z11.string(),
1462
- expires_at: z11.string()
1826
+ var webBotAuthBlockSchema = z12.looseObject({
1827
+ signature: z12.string(),
1828
+ signature_input: z12.string(),
1829
+ signature_agent: z12.string(),
1830
+ authority: z12.string(),
1831
+ expires_at: z12.string()
1463
1832
  });
1464
- var webBotAuthResponseSchema = z11.looseObject({
1833
+ var webBotAuthResponseSchema = z12.looseObject({
1465
1834
  web_bot_auth: webBotAuthBlockSchema
1466
1835
  });
1467
1836
  var WebBotAuthResource = class extends BaseResource {
@@ -1508,28 +1877,32 @@ var WebBotAuthResource = class extends BaseResource {
1508
1877
  // src/client.ts
1509
1878
  var Link = class {
1510
1879
  attestations;
1880
+ identityCredentials;
1511
1881
  spendRequests;
1512
1882
  paymentMethods;
1513
1883
  shippingAddresses;
1514
1884
  userInfo;
1885
+ approvalPolicy;
1515
1886
  transactions;
1516
1887
  sources;
1517
1888
  balances;
1518
- summaries;
1519
1889
  webBotAuth;
1520
1890
  reports;
1891
+ ucp;
1521
1892
  constructor(options) {
1522
1893
  this.attestations = new AttestationsResource(options);
1894
+ this.identityCredentials = new IdentityCredentialsResource(options);
1523
1895
  this.spendRequests = new SpendRequestResource(options);
1524
1896
  this.paymentMethods = new PaymentMethodsResource(options);
1525
1897
  this.shippingAddresses = new ShippingAddressResource(options);
1526
1898
  this.userInfo = new UserInfoResource(options);
1899
+ this.approvalPolicy = new ApprovalPolicyResource(options);
1527
1900
  this.transactions = new TransactionsResource(options);
1528
1901
  this.sources = new SourcesResource(options);
1529
1902
  this.balances = new BalancesResource(options);
1530
- this.summaries = new SummariesResource(options);
1531
1903
  this.webBotAuth = new WebBotAuthResource(options);
1532
1904
  this.reports = new ReportResource(options);
1905
+ this.ucp = new UcpResource(options);
1533
1906
  }
1534
1907
  };
1535
1908
  var client_default = Link;
@@ -1554,6 +1927,7 @@ var REPORT_TAGS = [
1554
1927
  ];
1555
1928
  var REPORT_ATTEMPT_TRACE_MAX_LENGTH = 8e3;
1556
1929
  export {
1930
+ ApprovalPolicyResource,
1557
1931
  AttestationsResource,
1558
1932
  Link,
1559
1933
  LinkApiError,
@@ -1564,8 +1938,10 @@ export {
1564
1938
  REPORT_ATTEMPT_TRACE_MAX_LENGTH,
1565
1939
  REPORT_OUTCOMES,
1566
1940
  REPORT_TAGS,
1567
- SummariesResource,
1568
1941
  client_default as default,
1569
- getDuplicateSpendRequest
1942
+ getDuplicateSpendRequest,
1943
+ holderJwkThumbprint,
1944
+ holderJwksEqual,
1945
+ parseHolderPublicJwk
1570
1946
  };
1571
1947
  //# sourceMappingURL=index.js.map