@wefunder/sdk 0.1.0-beta.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/index.js ADDED
@@ -0,0 +1,1221 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
7
+ // src/client.ts
8
+ import { createClient as createClient2 } from "@hey-api/client-fetch";
9
+
10
+ // src/http.ts
11
+ var IDEMPOTENT = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS"]);
12
+ function methodOf(input, init) {
13
+ if (init?.method) return init.method.toUpperCase();
14
+ if (input instanceof Request) return input.method.toUpperCase();
15
+ return "GET";
16
+ }
17
+ function rateLimitWaitMs(response, now, maxDelayMs) {
18
+ const raw = response.headers.get("x-ratelimit-reset");
19
+ if (!raw) return Math.min(1e3, maxDelayMs);
20
+ const n = Number(raw);
21
+ if (!Number.isFinite(n)) return Math.min(1e3, maxDelayMs);
22
+ const wait = n > 1e9 ? n * 1e3 - now : n * 1e3;
23
+ return Math.max(0, Math.min(wait, maxDelayMs));
24
+ }
25
+ function backoffMs(attempt, opts, random) {
26
+ const exp = opts.baseDelayMs * 2 ** attempt;
27
+ const jitter = exp * 0.5 * random();
28
+ return Math.min(exp + jitter, opts.maxDelayMs);
29
+ }
30
+ function withBearer(input, init, token) {
31
+ const headers = new Headers(
32
+ init?.headers ?? (input instanceof Request ? input.headers : void 0)
33
+ );
34
+ headers.set("Authorization", `Bearer ${token}`);
35
+ return { ...init, headers };
36
+ }
37
+ function createFetch(deps) {
38
+ const baseFetch = deps.fetch ?? fetch;
39
+ const sleep = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
40
+ const now = deps.now ?? Date.now;
41
+ const random = deps.random ?? Math.random;
42
+ const retry = {
43
+ maxRetries: deps.retry?.maxRetries ?? 2,
44
+ baseDelayMs: deps.retry?.baseDelayMs ?? 250,
45
+ maxDelayMs: deps.retry?.maxDelayMs ?? 6e4
46
+ };
47
+ return async function wrappedFetch(input, init) {
48
+ const method = methodOf(input, init);
49
+ const idempotent = IDEMPOTENT.has(method);
50
+ let refreshed = false;
51
+ let attempt = 0;
52
+ for (; ; ) {
53
+ let response;
54
+ let networkError;
55
+ try {
56
+ response = await baseFetch(input, init);
57
+ } catch (err) {
58
+ networkError = err;
59
+ }
60
+ const replayable = !(input instanceof Request && input.bodyUsed);
61
+ if (response?.status === 401 && !refreshed && replayable && deps.tokenManager?.canRefresh) {
62
+ refreshed = true;
63
+ const next = await deps.tokenManager.refresh();
64
+ init = withBearer(input, init, next.accessToken);
65
+ continue;
66
+ }
67
+ if (response?.status === 429 && attempt < retry.maxRetries) {
68
+ attempt++;
69
+ await sleep(rateLimitWaitMs(response, now(), retry.maxDelayMs));
70
+ continue;
71
+ }
72
+ const transient = networkError !== void 0 || response !== void 0 && response.status >= 500;
73
+ if (transient && idempotent && attempt < retry.maxRetries) {
74
+ attempt++;
75
+ await sleep(backoffMs(attempt, retry, random));
76
+ continue;
77
+ }
78
+ if (response) return response;
79
+ throw networkError;
80
+ }
81
+ };
82
+ }
83
+
84
+ // src/oauth.ts
85
+ import { createHash, randomBytes } from "crypto";
86
+ var DEFAULT_AUTHORIZE_BASE_URL = "https://wefunder.com/oauth";
87
+ var DEFAULT_TOKEN_BASE_URL = "https://wefunder.com/oauth";
88
+ var DEFAULT_OAUTH_BASE_URL = DEFAULT_AUTHORIZE_BASE_URL;
89
+ function resolveAuthorizeBase(o) {
90
+ return o.authorizeBaseUrl ?? o.oauthBaseUrl ?? DEFAULT_AUTHORIZE_BASE_URL;
91
+ }
92
+ function resolveTokenBase(o) {
93
+ return o.tokenBaseUrl ?? o.oauthBaseUrl ?? DEFAULT_TOKEN_BASE_URL;
94
+ }
95
+ function toTokenSet(raw, now) {
96
+ return {
97
+ accessToken: raw.access_token,
98
+ refreshToken: raw.refresh_token,
99
+ expiresAt: raw.expires_in ? now + raw.expires_in * 1e3 : void 0,
100
+ scope: raw.scope,
101
+ tokenType: raw.token_type
102
+ };
103
+ }
104
+ async function postToken(oauthBaseUrl, params, fetchImpl, now) {
105
+ const res = await fetchImpl(`${oauthBaseUrl}/token`, {
106
+ method: "POST",
107
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
108
+ body: new URLSearchParams(params).toString()
109
+ });
110
+ if (!res.ok) {
111
+ let detail = "";
112
+ try {
113
+ detail = JSON.stringify(await res.json());
114
+ } catch {
115
+ detail = await res.text().catch(() => "");
116
+ }
117
+ throw new Error(`OAuth token request failed (${res.status}): ${detail}`);
118
+ }
119
+ return toTokenSet(await res.json(), now());
120
+ }
121
+ function base64Url(buf) {
122
+ return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
123
+ }
124
+ function generatePkce() {
125
+ const codeVerifier = base64Url(randomBytes(32));
126
+ const codeChallenge = base64Url(createHash("sha256").update(codeVerifier).digest());
127
+ return { codeVerifier, codeChallenge, codeChallengeMethod: "S256" };
128
+ }
129
+ function createAuthorizationUrl(opts) {
130
+ const base = resolveAuthorizeBase(opts);
131
+ const q = new URLSearchParams({
132
+ response_type: "code",
133
+ client_id: opts.clientId,
134
+ redirect_uri: opts.redirectUri,
135
+ scope: opts.scopes.join(" "),
136
+ state: opts.state,
137
+ code_challenge: opts.pkce.codeChallenge,
138
+ code_challenge_method: opts.pkce.codeChallengeMethod
139
+ });
140
+ return `${base}/authorize?${q.toString()}`;
141
+ }
142
+ function exchangeCode(opts) {
143
+ const params = {
144
+ grant_type: "authorization_code",
145
+ client_id: opts.clientId,
146
+ code: opts.code,
147
+ redirect_uri: opts.redirectUri,
148
+ code_verifier: opts.codeVerifier
149
+ };
150
+ if (opts.clientSecret) params.client_secret = opts.clientSecret;
151
+ return postToken(resolveTokenBase(opts), params, opts.fetch ?? fetch, opts.now ?? Date.now);
152
+ }
153
+ function clientCredentialsGrant(opts) {
154
+ const params = {
155
+ grant_type: "client_credentials",
156
+ client_id: opts.clientId,
157
+ client_secret: opts.clientSecret
158
+ };
159
+ if (opts.scopes?.length) params.scope = opts.scopes.join(" ");
160
+ return postToken(resolveTokenBase(opts), params, opts.fetch ?? fetch, opts.now ?? Date.now);
161
+ }
162
+ function refreshToken(opts) {
163
+ const params = {
164
+ grant_type: "refresh_token",
165
+ client_id: opts.clientId,
166
+ refresh_token: opts.refreshToken
167
+ };
168
+ if (opts.clientSecret) params.client_secret = opts.clientSecret;
169
+ return postToken(resolveTokenBase(opts), params, opts.fetch ?? fetch, opts.now ?? Date.now);
170
+ }
171
+
172
+ // src/errors.ts
173
+ var REQUEST_ID_HEADER = "x-wf-request-id";
174
+ function requestIdFrom(response, bodyRequestId) {
175
+ return response?.headers.get(REQUEST_ID_HEADER) ?? bodyRequestId;
176
+ }
177
+ var WefunderError = class extends Error {
178
+ status;
179
+ type;
180
+ requestId;
181
+ details;
182
+ /** Server-provided hint on how to resolve the error, when present. */
183
+ remediation;
184
+ /** Documentation pointer surfaced to developers in stack traces / logs. */
185
+ documentationUrl = "https://docs.wefunder.com/api-reference";
186
+ constructor(args) {
187
+ super(args.message);
188
+ this.name = "WefunderError";
189
+ this.status = args.status;
190
+ this.type = args.type;
191
+ this.requestId = args.requestId;
192
+ this.details = args.details;
193
+ this.remediation = args.remediation;
194
+ }
195
+ };
196
+ var WefunderAuthError = class extends WefunderError {
197
+ constructor(message) {
198
+ super({ status: 401, type: "unauthorized", message });
199
+ this.name = "WefunderAuthError";
200
+ }
201
+ };
202
+
203
+ // src/token-manager.ts
204
+ var TokenManager = class {
205
+ #tokens;
206
+ #clientId;
207
+ #clientSecret;
208
+ #reMint;
209
+ #tokenBaseUrl;
210
+ #onTokenRefresh;
211
+ #store;
212
+ #fetch;
213
+ #now;
214
+ #leeway;
215
+ #inflight;
216
+ constructor(opts) {
217
+ this.#tokens = opts.tokens;
218
+ this.#clientId = opts.clientId;
219
+ this.#clientSecret = opts.clientSecret;
220
+ this.#reMint = opts.reMint;
221
+ this.#tokenBaseUrl = resolveTokenBase(opts);
222
+ this.#onTokenRefresh = opts.onTokenRefresh;
223
+ this.#store = opts.store;
224
+ this.#fetch = opts.fetch ?? fetch;
225
+ this.#now = opts.now ?? Date.now;
226
+ this.#leeway = opts.expiryLeewayMs ?? 3e4;
227
+ }
228
+ get current() {
229
+ return this.#tokens;
230
+ }
231
+ /** True if the manager can recover an expired token (rotate a refresh token or re-mint). */
232
+ get canRefresh() {
233
+ return Boolean(this.#tokens.refreshToken && this.#clientId || this.#reMint);
234
+ }
235
+ /** Returns a valid access token, refreshing proactively if it's expired/near-expiry. */
236
+ async getAccessToken() {
237
+ const { expiresAt } = this.#tokens;
238
+ if (expiresAt !== void 0 && this.#now() >= expiresAt - this.#leeway && this.canRefresh) {
239
+ await this.refresh();
240
+ }
241
+ return this.#tokens.accessToken;
242
+ }
243
+ /**
244
+ * Recover an expired/rejected token (e.g. after a 401): rotates the refresh token
245
+ * if there is one, otherwise re-mints (client_credentials). Coalesces concurrent
246
+ * calls into one network round-trip, then persists. Returns the new token set.
247
+ */
248
+ async refresh() {
249
+ if (this.#inflight) return this.#inflight;
250
+ const strategy = this.#recoveryStrategy();
251
+ if (!strategy) {
252
+ throw new WefunderAuthError(
253
+ "Access token expired and no refresh token / re-mint capability is configured."
254
+ );
255
+ }
256
+ this.#inflight = (async () => {
257
+ const next = await strategy();
258
+ this.#tokens = next;
259
+ await this.#store?.save(next);
260
+ await this.#onTokenRefresh?.(next);
261
+ return next;
262
+ })();
263
+ try {
264
+ return await this.#inflight;
265
+ } finally {
266
+ this.#inflight = void 0;
267
+ }
268
+ }
269
+ // Pick the recovery strategy: refresh_token rotation, else cc re-mint, else none.
270
+ #recoveryStrategy() {
271
+ const refreshTokenValue = this.#tokens.refreshToken;
272
+ if (refreshTokenValue && this.#clientId) {
273
+ const clientId = this.#clientId;
274
+ return async () => {
275
+ const next = await refreshToken({
276
+ clientId,
277
+ clientSecret: this.#clientSecret,
278
+ refreshToken: refreshTokenValue,
279
+ tokenBaseUrl: this.#tokenBaseUrl,
280
+ fetch: this.#fetch,
281
+ now: this.#now
282
+ });
283
+ if (!next.refreshToken) next.refreshToken = refreshTokenValue;
284
+ return next;
285
+ };
286
+ }
287
+ return this.#reMint;
288
+ }
289
+ };
290
+
291
+ // src/pagination.ts
292
+ async function* paginate(fetchPage) {
293
+ let cursor;
294
+ const seen = /* @__PURE__ */ new Set();
295
+ for (; ; ) {
296
+ const page = await fetchPage(cursor);
297
+ for (const item of page.data ?? []) yield item;
298
+ const meta = page.meta ?? {};
299
+ const next = meta.next_cursor;
300
+ if (meta.has_more === false) return;
301
+ if (next === void 0 || next === null) return;
302
+ if (seen.has(next)) return;
303
+ seen.add(next);
304
+ cursor = next;
305
+ }
306
+ }
307
+ async function collect(fetchPage) {
308
+ const out = [];
309
+ for await (const item of paginate(fetchPage)) out.push(item);
310
+ return out;
311
+ }
312
+
313
+ // src/generated/sdk.gen.ts
314
+ var sdk_gen_exports = {};
315
+ __export(sdk_gen_exports, {
316
+ approveSyndicateMember: () => approveSyndicateMember,
317
+ closeSyndicateDeal: () => closeSyndicateDeal,
318
+ createIntent: () => createIntent,
319
+ createPartnerInvite: () => createPartnerInvite,
320
+ createWebhookSubscription: () => createWebhookSubscription,
321
+ deleteWebhookSubscription: () => deleteWebhookSubscription,
322
+ demoteSyndicateMember: () => demoteSyndicateMember,
323
+ exportSyndicateMembersCsv: () => exportSyndicateMembersCsv,
324
+ finalizeSyndicateDeal: () => finalizeSyndicateDeal,
325
+ getAttributionMe: () => getAttributionMe,
326
+ getAttributionStats: () => getAttributionStats,
327
+ getCurrentUser: () => getCurrentUser,
328
+ getIntent: () => getIntent,
329
+ getOffering: () => getOffering,
330
+ getSyndicate: () => getSyndicate,
331
+ getSyndicateDeal: () => getSyndicateDeal,
332
+ getSyndicateStatistics: () => getSyndicateStatistics,
333
+ getWebhookSubscription: () => getWebhookSubscription,
334
+ hideSyndicateMember: () => hideSyndicateMember,
335
+ inviteSyndicateMember: () => inviteSyndicateMember,
336
+ listActivity: () => listActivity,
337
+ listAttributedInvestments: () => listAttributedInvestments,
338
+ listAttributionCampaigns: () => listAttributionCampaigns,
339
+ listCampaigns: () => listCampaigns,
340
+ listConnectedApps: () => listConnectedApps,
341
+ listIntents: () => listIntents,
342
+ listInvestments: () => listInvestments,
343
+ listOfferings: () => listOfferings,
344
+ listPartnerInvites: () => listPartnerInvites,
345
+ listSyndicateDealInvestors: () => listSyndicateDealInvestors,
346
+ listSyndicateDeals: () => listSyndicateDeals,
347
+ listSyndicateMemberInvestments: () => listSyndicateMemberInvestments,
348
+ listSyndicateMembers: () => listSyndicateMembers,
349
+ listSyndicates: () => listSyndicates,
350
+ listWebhookSubscriptions: () => listWebhookSubscriptions,
351
+ promoteSyndicateMember: () => promoteSyndicateMember,
352
+ reactivateWebhookSubscription: () => reactivateWebhookSubscription,
353
+ regenerateWebhookSecret: () => regenerateWebhookSecret,
354
+ registerAsPartner: () => registerAsPartner,
355
+ removeSyndicateMember: () => removeSyndicateMember,
356
+ reorderSyndicateMembers: () => reorderSyndicateMembers,
357
+ resendSyndicateInvite: () => resendSyndicateInvite,
358
+ restoreSyndicateMember: () => restoreSyndicateMember,
359
+ revokeConnectedApp: () => revokeConnectedApp,
360
+ revokePartnerInvite: () => revokePartnerInvite,
361
+ testWebhookSubscription: () => testWebhookSubscription,
362
+ updateSyndicate: () => updateSyndicate,
363
+ updateSyndicateMember: () => updateSyndicateMember
364
+ });
365
+
366
+ // src/generated/client.gen.ts
367
+ import { createClient, createConfig } from "@hey-api/client-fetch";
368
+ var client = createClient(createConfig());
369
+
370
+ // src/generated/sdk.gen.ts
371
+ var listOfferings = (options) => {
372
+ return (options?.client ?? client).get({
373
+ security: [
374
+ {
375
+ scheme: "bearer",
376
+ type: "http"
377
+ }
378
+ ],
379
+ url: "/explore",
380
+ ...options
381
+ });
382
+ };
383
+ var getOffering = (options) => {
384
+ return (options.client ?? client).get({
385
+ security: [
386
+ {
387
+ scheme: "bearer",
388
+ type: "http"
389
+ }
390
+ ],
391
+ url: "/offerings/{external_id}",
392
+ ...options
393
+ });
394
+ };
395
+ var getCurrentUser = (options) => {
396
+ return (options?.client ?? client).get({
397
+ security: [
398
+ {
399
+ scheme: "bearer",
400
+ type: "http"
401
+ }
402
+ ],
403
+ url: "/users/me",
404
+ ...options
405
+ });
406
+ };
407
+ var listInvestments = (options) => {
408
+ return (options?.client ?? client).get({
409
+ security: [
410
+ {
411
+ scheme: "bearer",
412
+ type: "http"
413
+ }
414
+ ],
415
+ url: "/investments",
416
+ ...options
417
+ });
418
+ };
419
+ var listCampaigns = (options) => {
420
+ return (options?.client ?? client).get({
421
+ security: [
422
+ {
423
+ scheme: "bearer",
424
+ type: "http"
425
+ }
426
+ ],
427
+ url: "/campaigns",
428
+ ...options
429
+ });
430
+ };
431
+ var listSyndicates = (options) => {
432
+ return (options?.client ?? client).get({
433
+ security: [
434
+ {
435
+ scheme: "bearer",
436
+ type: "http"
437
+ }
438
+ ],
439
+ url: "/syndicates",
440
+ ...options
441
+ });
442
+ };
443
+ var getSyndicate = (options) => {
444
+ return (options.client ?? client).get({
445
+ security: [
446
+ {
447
+ scheme: "bearer",
448
+ type: "http"
449
+ }
450
+ ],
451
+ url: "/syndicates/{syndicate_id}",
452
+ ...options
453
+ });
454
+ };
455
+ var updateSyndicate = (options) => {
456
+ return (options.client ?? client).patch({
457
+ security: [
458
+ {
459
+ scheme: "bearer",
460
+ type: "http"
461
+ }
462
+ ],
463
+ url: "/syndicates/{syndicate_id}",
464
+ ...options,
465
+ headers: {
466
+ "Content-Type": "application/json",
467
+ ...options?.headers
468
+ }
469
+ });
470
+ };
471
+ var listSyndicateMembers = (options) => {
472
+ return (options.client ?? client).get({
473
+ security: [
474
+ {
475
+ scheme: "bearer",
476
+ type: "http"
477
+ }
478
+ ],
479
+ url: "/syndicates/{syndicate_id}/members",
480
+ ...options
481
+ });
482
+ };
483
+ var inviteSyndicateMember = (options) => {
484
+ return (options.client ?? client).post({
485
+ security: [
486
+ {
487
+ scheme: "bearer",
488
+ type: "http"
489
+ }
490
+ ],
491
+ url: "/syndicates/{syndicate_id}/members/invite",
492
+ ...options,
493
+ headers: {
494
+ "Content-Type": "application/json",
495
+ ...options?.headers
496
+ }
497
+ });
498
+ };
499
+ var removeSyndicateMember = (options) => {
500
+ return (options.client ?? client).delete({
501
+ security: [
502
+ {
503
+ scheme: "bearer",
504
+ type: "http"
505
+ }
506
+ ],
507
+ url: "/syndicates/{syndicate_id}/members/{member_id}",
508
+ ...options
509
+ });
510
+ };
511
+ var updateSyndicateMember = (options) => {
512
+ return (options.client ?? client).patch({
513
+ security: [
514
+ {
515
+ scheme: "bearer",
516
+ type: "http"
517
+ }
518
+ ],
519
+ url: "/syndicates/{syndicate_id}/members/{member_id}",
520
+ ...options,
521
+ headers: {
522
+ "Content-Type": "application/json",
523
+ ...options?.headers
524
+ }
525
+ });
526
+ };
527
+ var approveSyndicateMember = (options) => {
528
+ return (options.client ?? client).post({
529
+ security: [
530
+ {
531
+ scheme: "bearer",
532
+ type: "http"
533
+ }
534
+ ],
535
+ url: "/syndicates/{syndicate_id}/members/{member_id}/approve",
536
+ ...options
537
+ });
538
+ };
539
+ var hideSyndicateMember = (options) => {
540
+ return (options.client ?? client).post({
541
+ security: [
542
+ {
543
+ scheme: "bearer",
544
+ type: "http"
545
+ }
546
+ ],
547
+ url: "/syndicates/{syndicate_id}/members/{member_id}/hide",
548
+ ...options
549
+ });
550
+ };
551
+ var promoteSyndicateMember = (options) => {
552
+ return (options.client ?? client).post({
553
+ security: [
554
+ {
555
+ scheme: "bearer",
556
+ type: "http"
557
+ }
558
+ ],
559
+ url: "/syndicates/{syndicate_id}/members/{member_id}/promote",
560
+ ...options
561
+ });
562
+ };
563
+ var demoteSyndicateMember = (options) => {
564
+ return (options.client ?? client).post({
565
+ security: [
566
+ {
567
+ scheme: "bearer",
568
+ type: "http"
569
+ }
570
+ ],
571
+ url: "/syndicates/{syndicate_id}/members/{member_id}/demote",
572
+ ...options
573
+ });
574
+ };
575
+ var restoreSyndicateMember = (options) => {
576
+ return (options.client ?? client).post({
577
+ security: [
578
+ {
579
+ scheme: "bearer",
580
+ type: "http"
581
+ }
582
+ ],
583
+ url: "/syndicates/{syndicate_id}/members/{member_id}/restore",
584
+ ...options
585
+ });
586
+ };
587
+ var resendSyndicateInvite = (options) => {
588
+ return (options.client ?? client).post({
589
+ security: [
590
+ {
591
+ scheme: "bearer",
592
+ type: "http"
593
+ }
594
+ ],
595
+ url: "/syndicates/{syndicate_id}/members/{member_id}/resend_invite",
596
+ ...options
597
+ });
598
+ };
599
+ var reorderSyndicateMembers = (options) => {
600
+ return (options.client ?? client).post({
601
+ security: [
602
+ {
603
+ scheme: "bearer",
604
+ type: "http"
605
+ }
606
+ ],
607
+ url: "/syndicates/{syndicate_id}/members/reorder",
608
+ ...options,
609
+ headers: {
610
+ "Content-Type": "application/json",
611
+ ...options?.headers
612
+ }
613
+ });
614
+ };
615
+ var exportSyndicateMembersCsv = (options) => {
616
+ return (options.client ?? client).post({
617
+ security: [
618
+ {
619
+ scheme: "bearer",
620
+ type: "http"
621
+ }
622
+ ],
623
+ url: "/syndicates/{syndicate_id}/members/export_csv",
624
+ ...options
625
+ });
626
+ };
627
+ var listSyndicateDeals = (options) => {
628
+ return (options.client ?? client).get({
629
+ security: [
630
+ {
631
+ scheme: "bearer",
632
+ type: "http"
633
+ }
634
+ ],
635
+ url: "/syndicates/{syndicate_id}/deals",
636
+ ...options
637
+ });
638
+ };
639
+ var getSyndicateDeal = (options) => {
640
+ return (options.client ?? client).get({
641
+ security: [
642
+ {
643
+ scheme: "bearer",
644
+ type: "http"
645
+ }
646
+ ],
647
+ url: "/syndicates/{syndicate_id}/deals/{fundraise_id}",
648
+ ...options
649
+ });
650
+ };
651
+ var listSyndicateDealInvestors = (options) => {
652
+ return (options.client ?? client).get({
653
+ security: [
654
+ {
655
+ scheme: "bearer",
656
+ type: "http"
657
+ }
658
+ ],
659
+ url: "/syndicates/{syndicate_id}/deals/{fundraise_id}/investors",
660
+ ...options
661
+ });
662
+ };
663
+ var listSyndicateMemberInvestments = (options) => {
664
+ return (options.client ?? client).get({
665
+ security: [
666
+ {
667
+ scheme: "bearer",
668
+ type: "http"
669
+ }
670
+ ],
671
+ url: "/syndicates/{syndicate_id}/members/{member_id}/investments",
672
+ ...options
673
+ });
674
+ };
675
+ var getSyndicateStatistics = (options) => {
676
+ return (options.client ?? client).get({
677
+ security: [
678
+ {
679
+ scheme: "bearer",
680
+ type: "http"
681
+ }
682
+ ],
683
+ url: "/syndicates/{syndicate_id}/statistics",
684
+ ...options
685
+ });
686
+ };
687
+ var closeSyndicateDeal = (options) => {
688
+ return (options.client ?? client).post({
689
+ security: [
690
+ {
691
+ scheme: "bearer",
692
+ type: "http"
693
+ }
694
+ ],
695
+ url: "/syndicates/{syndicate_id}/deals/{fundraise_id}/close",
696
+ ...options
697
+ });
698
+ };
699
+ var finalizeSyndicateDeal = (options) => {
700
+ return (options.client ?? client).post({
701
+ security: [
702
+ {
703
+ scheme: "bearer",
704
+ type: "http"
705
+ }
706
+ ],
707
+ url: "/syndicates/{syndicate_id}/deals/{fundraise_id}/finalize",
708
+ ...options
709
+ });
710
+ };
711
+ var listIntents = (options) => {
712
+ return (options?.client ?? client).get({
713
+ security: [
714
+ {
715
+ scheme: "bearer",
716
+ type: "http"
717
+ }
718
+ ],
719
+ url: "/intents",
720
+ ...options
721
+ });
722
+ };
723
+ var createIntent = (options) => {
724
+ return (options.client ?? client).post({
725
+ security: [
726
+ {
727
+ scheme: "bearer",
728
+ type: "http"
729
+ }
730
+ ],
731
+ url: "/intents",
732
+ ...options,
733
+ headers: {
734
+ "Content-Type": "application/json",
735
+ ...options?.headers
736
+ }
737
+ });
738
+ };
739
+ var getIntent = (options) => {
740
+ return (options.client ?? client).get({
741
+ security: [
742
+ {
743
+ scheme: "bearer",
744
+ type: "http"
745
+ }
746
+ ],
747
+ url: "/intents/{intent_id}",
748
+ ...options
749
+ });
750
+ };
751
+ var listActivity = (options) => {
752
+ return (options?.client ?? client).get({
753
+ security: [
754
+ {
755
+ scheme: "bearer",
756
+ type: "http"
757
+ }
758
+ ],
759
+ url: "/activity",
760
+ ...options
761
+ });
762
+ };
763
+ var listConnectedApps = (options) => {
764
+ return (options?.client ?? client).get({
765
+ security: [
766
+ {
767
+ scheme: "bearer",
768
+ type: "http"
769
+ }
770
+ ],
771
+ url: "/connected-apps",
772
+ ...options
773
+ });
774
+ };
775
+ var revokeConnectedApp = (options) => {
776
+ return (options.client ?? client).delete({
777
+ security: [
778
+ {
779
+ scheme: "bearer",
780
+ type: "http"
781
+ }
782
+ ],
783
+ url: "/connected-apps/{app_id}",
784
+ ...options
785
+ });
786
+ };
787
+ var getAttributionStats = (options) => {
788
+ return (options.client ?? client).get({
789
+ security: [
790
+ {
791
+ scheme: "bearer",
792
+ type: "http"
793
+ }
794
+ ],
795
+ url: "/campaigns/{campaign_id}/attribution/stats",
796
+ ...options
797
+ });
798
+ };
799
+ var listAttributedInvestments = (options) => {
800
+ return (options.client ?? client).get({
801
+ security: [
802
+ {
803
+ scheme: "bearer",
804
+ type: "http"
805
+ }
806
+ ],
807
+ url: "/campaigns/{campaign_id}/attribution/investments",
808
+ ...options
809
+ });
810
+ };
811
+ var listWebhookSubscriptions = (options) => {
812
+ return (options.client ?? client).get({
813
+ security: [
814
+ {
815
+ scheme: "bearer",
816
+ type: "http"
817
+ }
818
+ ],
819
+ url: "/campaigns/{campaign_id}/attribution/webhooks",
820
+ ...options
821
+ });
822
+ };
823
+ var createWebhookSubscription = (options) => {
824
+ return (options.client ?? client).post({
825
+ security: [
826
+ {
827
+ scheme: "bearer",
828
+ type: "http"
829
+ }
830
+ ],
831
+ url: "/campaigns/{campaign_id}/attribution/webhooks",
832
+ ...options,
833
+ headers: {
834
+ "Content-Type": "application/json",
835
+ ...options?.headers
836
+ }
837
+ });
838
+ };
839
+ var deleteWebhookSubscription = (options) => {
840
+ return (options.client ?? client).delete({
841
+ security: [
842
+ {
843
+ scheme: "bearer",
844
+ type: "http"
845
+ }
846
+ ],
847
+ url: "/campaigns/{campaign_id}/attribution/webhooks/{webhook_id}",
848
+ ...options
849
+ });
850
+ };
851
+ var getWebhookSubscription = (options) => {
852
+ return (options.client ?? client).get({
853
+ security: [
854
+ {
855
+ scheme: "bearer",
856
+ type: "http"
857
+ }
858
+ ],
859
+ url: "/campaigns/{campaign_id}/attribution/webhooks/{webhook_id}",
860
+ ...options
861
+ });
862
+ };
863
+ var testWebhookSubscription = (options) => {
864
+ return (options.client ?? client).post({
865
+ security: [
866
+ {
867
+ scheme: "bearer",
868
+ type: "http"
869
+ }
870
+ ],
871
+ url: "/campaigns/{campaign_id}/attribution/webhooks/{webhook_id}/test",
872
+ ...options
873
+ });
874
+ };
875
+ var regenerateWebhookSecret = (options) => {
876
+ return (options.client ?? client).post({
877
+ security: [
878
+ {
879
+ scheme: "bearer",
880
+ type: "http"
881
+ }
882
+ ],
883
+ url: "/campaigns/{campaign_id}/attribution/webhooks/{webhook_id}/regenerate_secret",
884
+ ...options
885
+ });
886
+ };
887
+ var reactivateWebhookSubscription = (options) => {
888
+ return (options.client ?? client).post({
889
+ security: [
890
+ {
891
+ scheme: "bearer",
892
+ type: "http"
893
+ }
894
+ ],
895
+ url: "/campaigns/{campaign_id}/attribution/webhooks/{webhook_id}/reactivate",
896
+ ...options
897
+ });
898
+ };
899
+ var getAttributionMe = (options) => {
900
+ return (options?.client ?? client).get({
901
+ security: [
902
+ {
903
+ scheme: "bearer",
904
+ type: "http"
905
+ }
906
+ ],
907
+ url: "/attribution/me",
908
+ ...options
909
+ });
910
+ };
911
+ var listAttributionCampaigns = (options) => {
912
+ return (options?.client ?? client).get({
913
+ security: [
914
+ {
915
+ scheme: "bearer",
916
+ type: "http"
917
+ }
918
+ ],
919
+ url: "/attribution/campaigns",
920
+ ...options
921
+ });
922
+ };
923
+ var registerAsPartner = (options) => {
924
+ return (options.client ?? client).post({
925
+ security: [
926
+ {
927
+ scheme: "bearer",
928
+ type: "http"
929
+ }
930
+ ],
931
+ url: "/attribution/partners/register",
932
+ ...options,
933
+ headers: {
934
+ "Content-Type": "application/json",
935
+ ...options?.headers
936
+ }
937
+ });
938
+ };
939
+ var listPartnerInvites = (options) => {
940
+ return (options?.client ?? client).get({
941
+ security: [
942
+ {
943
+ scheme: "bearer",
944
+ type: "http"
945
+ }
946
+ ],
947
+ url: "/attribution/invites",
948
+ ...options
949
+ });
950
+ };
951
+ var createPartnerInvite = (options) => {
952
+ return (options.client ?? client).post({
953
+ security: [
954
+ {
955
+ scheme: "bearer",
956
+ type: "http"
957
+ }
958
+ ],
959
+ url: "/attribution/invites",
960
+ ...options,
961
+ headers: {
962
+ "Content-Type": "application/json",
963
+ ...options?.headers
964
+ }
965
+ });
966
+ };
967
+ var revokePartnerInvite = (options) => {
968
+ return (options.client ?? client).delete({
969
+ security: [
970
+ {
971
+ scheme: "bearer",
972
+ type: "http"
973
+ }
974
+ ],
975
+ url: "/attribution/invites/{token}",
976
+ ...options
977
+ });
978
+ };
979
+
980
+ // src/client.ts
981
+ var DEFAULT_API_BASE_URL = "https://api.wefunder.com/api/v2";
982
+ var DEFAULT_API_VERSION = "2025-01-15";
983
+ function modeForToken(token) {
984
+ if (token.startsWith("at_live_")) return "live";
985
+ if (token.startsWith("at_test_")) return "test";
986
+ return "unknown";
987
+ }
988
+ var Wefunder = class _Wefunder {
989
+ mode;
990
+ raw;
991
+ #client;
992
+ #tokens;
993
+ constructor(opts) {
994
+ const tokenSet = opts.tokens ?? (opts.accessToken ? { accessToken: opts.accessToken } : void 0);
995
+ if (!tokenSet) {
996
+ throw new Error("Wefunder: provide `accessToken` or `tokens`.");
997
+ }
998
+ this.mode = modeForToken(tokenSet.accessToken);
999
+ const reMint = opts.clientCredentials && opts.clientId && opts.clientSecret ? () => clientCredentialsGrant({
1000
+ clientId: opts.clientId,
1001
+ clientSecret: opts.clientSecret,
1002
+ scopes: opts.clientCredentials.scopes,
1003
+ oauthBaseUrl: opts.oauthBaseUrl,
1004
+ tokenBaseUrl: opts.tokenBaseUrl,
1005
+ fetch: opts.fetch,
1006
+ now: opts.now
1007
+ }) : void 0;
1008
+ this.#tokens = new TokenManager({
1009
+ tokens: tokenSet,
1010
+ clientId: opts.clientId,
1011
+ clientSecret: opts.clientSecret,
1012
+ reMint,
1013
+ oauthBaseUrl: opts.oauthBaseUrl,
1014
+ tokenBaseUrl: opts.tokenBaseUrl,
1015
+ onTokenRefresh: opts.onTokenRefresh,
1016
+ store: opts.store,
1017
+ fetch: opts.fetch,
1018
+ now: opts.now
1019
+ });
1020
+ const wrappedFetch = createFetch({
1021
+ tokenManager: this.#tokens,
1022
+ fetch: opts.fetch,
1023
+ now: opts.now,
1024
+ sleep: opts.sleep,
1025
+ random: opts.random,
1026
+ retry: opts.retry
1027
+ });
1028
+ this.#client = createClient2({
1029
+ baseUrl: opts.baseUrl ?? DEFAULT_API_BASE_URL,
1030
+ headers: { "Wefunder-Version": opts.apiVersion ?? DEFAULT_API_VERSION },
1031
+ auth: () => this.#tokens.getAccessToken(),
1032
+ fetch: wrappedFetch
1033
+ });
1034
+ this.raw = this.#buildRaw();
1035
+ }
1036
+ /** Server-to-server: exchange client credentials for a token, then build a client. */
1037
+ static async fromClientCredentials(opts) {
1038
+ const tokens = await clientCredentialsGrant({
1039
+ clientId: opts.clientId,
1040
+ clientSecret: opts.clientSecret,
1041
+ scopes: opts.scopes,
1042
+ oauthBaseUrl: opts.oauthBaseUrl,
1043
+ tokenBaseUrl: opts.tokenBaseUrl,
1044
+ fetch: opts.fetch,
1045
+ now: opts.now
1046
+ });
1047
+ return new _Wefunder({
1048
+ tokens,
1049
+ clientId: opts.clientId,
1050
+ clientSecret: opts.clientSecret,
1051
+ clientCredentials: { scopes: opts.scopes },
1052
+ // enables auto-re-mint on expiry/401
1053
+ oauthBaseUrl: opts.oauthBaseUrl,
1054
+ tokenBaseUrl: opts.tokenBaseUrl,
1055
+ apiVersion: opts.apiVersion,
1056
+ baseUrl: opts.baseUrl,
1057
+ fetch: opts.fetch,
1058
+ now: opts.now
1059
+ });
1060
+ }
1061
+ /** The live token set (e.g. to persist after construction). */
1062
+ get tokens() {
1063
+ return this.#tokens.current;
1064
+ }
1065
+ // ---- unwrap: turn the {data,error,response} result into data-or-throw ----
1066
+ async #unwrap(p) {
1067
+ const { data, error, response } = await p;
1068
+ if (response && response.ok && error === void 0) return data;
1069
+ const status = response?.status ?? 0;
1070
+ const env = error ?? {};
1071
+ throw new WefunderError({
1072
+ status,
1073
+ type: env.error?.type ?? "api_error",
1074
+ message: env.error?.message ?? response?.statusText ?? "Request failed",
1075
+ // X-Wf-Request-Id header is primary (present even on non-JSON edge errors).
1076
+ requestId: requestIdFrom(response, env.error?.request_id ?? env.request_id),
1077
+ details: env.error?.details,
1078
+ remediation: env.error?.remediation
1079
+ });
1080
+ }
1081
+ // Single-resource ops return a `{ data: Entity }` envelope; strip it for ergonomics.
1082
+ async #unwrapData(p) {
1083
+ const env = await this.#unwrap(p);
1084
+ return env.data;
1085
+ }
1086
+ #buildRaw() {
1087
+ const raw = {};
1088
+ for (const [name, fn] of Object.entries(sdk_gen_exports)) {
1089
+ raw[name] = (options) => fn({ ...options, client: this.#client });
1090
+ }
1091
+ return raw;
1092
+ }
1093
+ /**
1094
+ * Unwrap any generated op result (incl. `wf.raw.*`) the way the ergonomic
1095
+ * namespaces do: returns the response body on success, throws a typed
1096
+ * `WefunderError` (with `request_id`) on failure. Lets `raw` callers keep the
1097
+ * SDK's error handling. (Stress-test finding C.)
1098
+ */
1099
+ unwrap(p) {
1100
+ return this.#unwrap(p);
1101
+ }
1102
+ // Generic page helper: forwards the endpoint's full query (cursor + documented
1103
+ // params like `sort`), not just the cursor. (Stress-test finding B.)
1104
+ #page(fn) {
1105
+ return (query) => this.#unwrap(fn({ client: this.#client, query }));
1106
+ }
1107
+ // ---- resource namespaces (common GA paths) ----
1108
+ users = {
1109
+ me: () => this.#unwrapData(getCurrentUser({ client: this.#client }))
1110
+ };
1111
+ offerings = {
1112
+ list: this.#page(listOfferings),
1113
+ all: (query) => paginate((cursor) => this.offerings.list({ ...query, cursor })),
1114
+ collect: (query) => collect((cursor) => this.offerings.list({ ...query, cursor })),
1115
+ get: (externalId) => this.#unwrapData(
1116
+ getOffering({ client: this.#client, path: { external_id: externalId } })
1117
+ )
1118
+ };
1119
+ investments = {
1120
+ list: this.#page(listInvestments),
1121
+ all: () => paginate((cursor) => this.investments.list({ cursor })),
1122
+ collect: () => collect((cursor) => this.investments.list({ cursor }))
1123
+ };
1124
+ campaigns = {
1125
+ list: this.#page(listCampaigns),
1126
+ all: () => paginate((cursor) => this.campaigns.list({ cursor })),
1127
+ collect: () => collect((cursor) => this.campaigns.list({ cursor }))
1128
+ };
1129
+ syndicates = {
1130
+ list: this.#page(listSyndicates),
1131
+ all: () => paginate((cursor) => this.syndicates.list({ cursor })),
1132
+ get: (id) => this.#unwrapData(getSyndicate({ client: this.#client, path: { id } }))
1133
+ };
1134
+ intents = {
1135
+ list: this.#page(listIntents),
1136
+ all: () => paginate((cursor) => this.intents.list({ cursor })),
1137
+ get: (id) => this.#unwrapData(getIntent({ client: this.#client, path: { id } }))
1138
+ };
1139
+ attribution = {
1140
+ me: () => this.#unwrapData(getAttributionMe({ client: this.#client }))
1141
+ };
1142
+ };
1143
+
1144
+ // src/webhooks.ts
1145
+ import { createHmac, timingSafeEqual } from "crypto";
1146
+ var SIGNATURE_HEADER = "x-wefunder-signature";
1147
+ var TIMESTAMP_HEADER = "x-wefunder-timestamp";
1148
+ var EVENT_HEADER = "x-wefunder-event";
1149
+ var DELIVERY_ID_HEADER = "x-wefunder-delivery-id";
1150
+ function computeSignature(secret, timestamp, payload) {
1151
+ const mac = createHmac("sha256", secret).update(`${timestamp}.${payload}`).digest("hex");
1152
+ return `sha256=${mac}`;
1153
+ }
1154
+ function constantTimeEqual(a, b) {
1155
+ const ab = Buffer.from(a);
1156
+ const bb = Buffer.from(b);
1157
+ if (ab.length !== bb.length) return false;
1158
+ return timingSafeEqual(ab, bb);
1159
+ }
1160
+ function verifyWebhook(opts) {
1161
+ const tolerance = opts.toleranceSeconds ?? 300;
1162
+ const now = (opts.now ?? Date.now)();
1163
+ const ts = Number(opts.timestamp);
1164
+ if (!Number.isFinite(ts)) return false;
1165
+ if (tolerance > 0 && Math.abs(now / 1e3 - ts) > tolerance) return false;
1166
+ const expected = computeSignature(opts.secret, opts.timestamp, opts.payload);
1167
+ return constantTimeEqual(opts.signature, expected);
1168
+ }
1169
+ function constructEvent(payload, headers, secret, opts) {
1170
+ const get = (name) => {
1171
+ if (headers instanceof Headers) return headers.get(name) ?? void 0;
1172
+ const v = headers[name] ?? headers[name.toLowerCase()];
1173
+ return Array.isArray(v) ? v[0] : v;
1174
+ };
1175
+ const signature = get(SIGNATURE_HEADER);
1176
+ const timestamp = get(TIMESTAMP_HEADER);
1177
+ if (!signature || !timestamp) {
1178
+ throw new Error("Missing X-Wefunder-Signature or X-Wefunder-Timestamp header");
1179
+ }
1180
+ const ok = verifyWebhook({
1181
+ payload,
1182
+ signature,
1183
+ timestamp,
1184
+ secret,
1185
+ toleranceSeconds: opts?.toleranceSeconds,
1186
+ now: opts?.now
1187
+ });
1188
+ if (!ok) throw new Error("Webhook signature verification failed");
1189
+ return {
1190
+ event: get(EVENT_HEADER) ?? "",
1191
+ deliveryId: get(DELIVERY_ID_HEADER) ?? "",
1192
+ timestamp: Number(timestamp),
1193
+ data: JSON.parse(payload)
1194
+ };
1195
+ }
1196
+ export {
1197
+ DEFAULT_API_BASE_URL,
1198
+ DEFAULT_API_VERSION,
1199
+ DEFAULT_AUTHORIZE_BASE_URL,
1200
+ DEFAULT_OAUTH_BASE_URL,
1201
+ DEFAULT_TOKEN_BASE_URL,
1202
+ DELIVERY_ID_HEADER,
1203
+ EVENT_HEADER,
1204
+ REQUEST_ID_HEADER,
1205
+ SIGNATURE_HEADER,
1206
+ TIMESTAMP_HEADER,
1207
+ Wefunder,
1208
+ WefunderAuthError,
1209
+ WefunderError,
1210
+ clientCredentialsGrant,
1211
+ collect,
1212
+ constructEvent,
1213
+ createAuthorizationUrl,
1214
+ exchangeCode,
1215
+ generatePkce,
1216
+ modeForToken,
1217
+ paginate,
1218
+ refreshToken,
1219
+ verifyWebhook
1220
+ };
1221
+ //# sourceMappingURL=index.js.map