@wefunder/sdk 0.1.0-beta.7 → 0.1.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +175 -134
- package/dist/index.cjs +464 -42
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6275 -1777
- package/dist/index.d.ts +6275 -1777
- package/dist/index.js +452 -39
- package/dist/index.js.map +1 -1
- package/examples_manifest.json +36 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1136,21 +1136,36 @@ var sdk_gen_exports = {};
|
|
|
1136
1136
|
__export(sdk_gen_exports, {
|
|
1137
1137
|
approveSyndicateMember: () => approveSyndicateMember,
|
|
1138
1138
|
closeSyndicateDeal: () => closeSyndicateDeal,
|
|
1139
|
+
createInstallation: () => createInstallation,
|
|
1140
|
+
createInstallationToken: () => createInstallationToken,
|
|
1139
1141
|
createIntent: () => createIntent,
|
|
1140
1142
|
createPartnerInvite: () => createPartnerInvite,
|
|
1143
|
+
createWebhookEndpoint: () => createWebhookEndpoint,
|
|
1141
1144
|
createWebhookSubscription: () => createWebhookSubscription,
|
|
1145
|
+
deleteWebhookEndpoint: () => deleteWebhookEndpoint,
|
|
1142
1146
|
deleteWebhookSubscription: () => deleteWebhookSubscription,
|
|
1143
1147
|
demoteSyndicateMember: () => demoteSyndicateMember,
|
|
1144
1148
|
exportSyndicateMembersCsv: () => exportSyndicateMembersCsv,
|
|
1145
1149
|
finalizeSyndicateDeal: () => finalizeSyndicateDeal,
|
|
1150
|
+
followCompany: () => followCompany,
|
|
1146
1151
|
getAttributionMe: () => getAttributionMe,
|
|
1147
1152
|
getAttributionStats: () => getAttributionStats,
|
|
1153
|
+
getCompany: () => getCompany,
|
|
1154
|
+
getCompanyDisclosures: () => getCompanyDisclosures,
|
|
1155
|
+
getCompanyPitch: () => getCompanyPitch,
|
|
1156
|
+
getCompanyUpdate: () => getCompanyUpdate,
|
|
1148
1157
|
getCurrentUser: () => getCurrentUser,
|
|
1158
|
+
getInstallation: () => getInstallation,
|
|
1149
1159
|
getIntent: () => getIntent,
|
|
1160
|
+
getInvestment: () => getInvestment,
|
|
1150
1161
|
getOffering: () => getOffering,
|
|
1162
|
+
getOfferingStats: () => getOfferingStats,
|
|
1163
|
+
getPortfolio: () => getPortfolio,
|
|
1151
1164
|
getSyndicate: () => getSyndicate,
|
|
1152
1165
|
getSyndicateDeal: () => getSyndicateDeal,
|
|
1166
|
+
getSyndicatePortfolio: () => getSyndicatePortfolio,
|
|
1153
1167
|
getSyndicateStatistics: () => getSyndicateStatistics,
|
|
1168
|
+
getWebhookEndpoint: () => getWebhookEndpoint,
|
|
1154
1169
|
getWebhookSubscription: () => getWebhookSubscription,
|
|
1155
1170
|
hideSyndicateMember: () => hideSyndicateMember,
|
|
1156
1171
|
inviteSyndicateMember: () => inviteSyndicateMember,
|
|
@@ -1158,19 +1173,30 @@ __export(sdk_gen_exports, {
|
|
|
1158
1173
|
listAttributedInvestments: () => listAttributedInvestments,
|
|
1159
1174
|
listAttributionCampaigns: () => listAttributionCampaigns,
|
|
1160
1175
|
listCampaigns: () => listCampaigns,
|
|
1176
|
+
listCompanyQuestions: () => listCompanyQuestions,
|
|
1177
|
+
listCompanyUpdates: () => listCompanyUpdates,
|
|
1161
1178
|
listConnectedApps: () => listConnectedApps,
|
|
1179
|
+
listEligibleInstallTargets: () => listEligibleInstallTargets,
|
|
1180
|
+
listFollowedCompanies: () => listFollowedCompanies,
|
|
1181
|
+
listInstallations: () => listInstallations,
|
|
1162
1182
|
listIntents: () => listIntents,
|
|
1163
1183
|
listInvestments: () => listInvestments,
|
|
1184
|
+
listMyCompanies: () => listMyCompanies,
|
|
1164
1185
|
listOfferings: () => listOfferings,
|
|
1165
1186
|
listPartnerInvites: () => listPartnerInvites,
|
|
1187
|
+
listPortfolioPositions: () => listPortfolioPositions,
|
|
1166
1188
|
listSyndicateDealInvestors: () => listSyndicateDealInvestors,
|
|
1167
1189
|
listSyndicateDeals: () => listSyndicateDeals,
|
|
1168
1190
|
listSyndicateMemberInvestments: () => listSyndicateMemberInvestments,
|
|
1169
1191
|
listSyndicateMembers: () => listSyndicateMembers,
|
|
1192
|
+
listSyndicatePortfolioPositions: () => listSyndicatePortfolioPositions,
|
|
1170
1193
|
listSyndicates: () => listSyndicates,
|
|
1194
|
+
listWebhookEndpoints: () => listWebhookEndpoints,
|
|
1171
1195
|
listWebhookSubscriptions: () => listWebhookSubscriptions,
|
|
1196
|
+
previewIntent: () => previewIntent,
|
|
1172
1197
|
promoteSyndicateMember: () => promoteSyndicateMember,
|
|
1173
1198
|
reactivateWebhookSubscription: () => reactivateWebhookSubscription,
|
|
1199
|
+
reenableWebhookEndpoint: () => reenableWebhookEndpoint,
|
|
1174
1200
|
regenerateWebhookSecret: () => regenerateWebhookSecret,
|
|
1175
1201
|
registerAsPartner: () => registerAsPartner,
|
|
1176
1202
|
removeSyndicateMember: () => removeSyndicateMember,
|
|
@@ -1178,10 +1204,16 @@ __export(sdk_gen_exports, {
|
|
|
1178
1204
|
resendSyndicateInvite: () => resendSyndicateInvite,
|
|
1179
1205
|
restoreSyndicateMember: () => restoreSyndicateMember,
|
|
1180
1206
|
revokeConnectedApp: () => revokeConnectedApp,
|
|
1207
|
+
revokeInstallation: () => revokeInstallation,
|
|
1181
1208
|
revokePartnerInvite: () => revokePartnerInvite,
|
|
1209
|
+
rotateWebhookEndpointSecret: () => rotateWebhookEndpointSecret,
|
|
1210
|
+
searchCompanies: () => searchCompanies,
|
|
1211
|
+
testWebhookEndpoint: () => testWebhookEndpoint,
|
|
1182
1212
|
testWebhookSubscription: () => testWebhookSubscription,
|
|
1213
|
+
unfollowCompany: () => unfollowCompany,
|
|
1183
1214
|
updateSyndicate: () => updateSyndicate,
|
|
1184
|
-
updateSyndicateMember: () => updateSyndicateMember
|
|
1215
|
+
updateSyndicateMember: () => updateSyndicateMember,
|
|
1216
|
+
updateWebhookEndpoint: () => updateWebhookEndpoint
|
|
1185
1217
|
});
|
|
1186
1218
|
|
|
1187
1219
|
// src/generated/client.gen.ts
|
|
@@ -1189,6 +1221,12 @@ var client = createClient(createConfig());
|
|
|
1189
1221
|
|
|
1190
1222
|
// src/generated/sdk.gen.ts
|
|
1191
1223
|
var listOfferings = (options) => (options?.client ?? client).get({
|
|
1224
|
+
querySerializer: {
|
|
1225
|
+
parameters: {
|
|
1226
|
+
industry: { array: { explode: false } },
|
|
1227
|
+
business_model: { array: { explode: false } }
|
|
1228
|
+
}
|
|
1229
|
+
},
|
|
1192
1230
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1193
1231
|
url: "/explore",
|
|
1194
1232
|
...options
|
|
@@ -1198,16 +1236,97 @@ var getOffering = (options) => (options.client ?? client).get({
|
|
|
1198
1236
|
url: "/offerings/{external_id}",
|
|
1199
1237
|
...options
|
|
1200
1238
|
});
|
|
1239
|
+
var getCompanyDisclosures = (options) => (options.client ?? client).get({
|
|
1240
|
+
querySerializer: {
|
|
1241
|
+
parameters: { sections: { array: { explode: false } } }
|
|
1242
|
+
},
|
|
1243
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1244
|
+
url: "/companies/{id}/disclosures",
|
|
1245
|
+
...options
|
|
1246
|
+
});
|
|
1247
|
+
var getCompanyPitch = (options) => (options.client ?? client).get({
|
|
1248
|
+
querySerializer: {
|
|
1249
|
+
parameters: { sections: { array: { explode: false } } }
|
|
1250
|
+
},
|
|
1251
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1252
|
+
url: "/companies/{id}/pitch",
|
|
1253
|
+
...options
|
|
1254
|
+
});
|
|
1255
|
+
var listCompanyUpdates = (options) => (options.client ?? client).get({
|
|
1256
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1257
|
+
url: "/companies/{id}/updates",
|
|
1258
|
+
...options
|
|
1259
|
+
});
|
|
1260
|
+
var getCompanyUpdate = (options) => (options.client ?? client).get({
|
|
1261
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1262
|
+
url: "/companies/{id}/updates/{update_id}",
|
|
1263
|
+
...options
|
|
1264
|
+
});
|
|
1265
|
+
var listCompanyQuestions = (options) => (options.client ?? client).get({
|
|
1266
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1267
|
+
url: "/companies/{id}/questions",
|
|
1268
|
+
...options
|
|
1269
|
+
});
|
|
1270
|
+
var searchCompanies = (options) => (options.client ?? client).get({
|
|
1271
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1272
|
+
url: "/companies/search",
|
|
1273
|
+
...options
|
|
1274
|
+
});
|
|
1275
|
+
var getCompany = (options) => (options.client ?? client).get({
|
|
1276
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1277
|
+
url: "/companies/{id}",
|
|
1278
|
+
...options
|
|
1279
|
+
});
|
|
1201
1280
|
var getCurrentUser = (options) => (options?.client ?? client).get({
|
|
1202
1281
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1203
1282
|
url: "/users/me",
|
|
1204
1283
|
...options
|
|
1205
1284
|
});
|
|
1285
|
+
var listMyCompanies = (options) => (options?.client ?? client).get({
|
|
1286
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1287
|
+
url: "/users/me/companies",
|
|
1288
|
+
...options
|
|
1289
|
+
});
|
|
1290
|
+
var listFollowedCompanies = (options) => (options?.client ?? client).get({
|
|
1291
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1292
|
+
url: "/users/me/follows",
|
|
1293
|
+
...options
|
|
1294
|
+
});
|
|
1295
|
+
var unfollowCompany = (options) => (options.client ?? client).delete({
|
|
1296
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1297
|
+
url: "/users/me/follows/{company_id}",
|
|
1298
|
+
...options
|
|
1299
|
+
});
|
|
1300
|
+
var followCompany = (options) => (options.client ?? client).put({
|
|
1301
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1302
|
+
url: "/users/me/follows/{company_id}",
|
|
1303
|
+
...options
|
|
1304
|
+
});
|
|
1206
1305
|
var listInvestments = (options) => (options?.client ?? client).get({
|
|
1207
1306
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1208
1307
|
url: "/investments",
|
|
1209
1308
|
...options
|
|
1210
1309
|
});
|
|
1310
|
+
var getInvestment = (options) => (options.client ?? client).get({
|
|
1311
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1312
|
+
url: "/investments/{id}",
|
|
1313
|
+
...options
|
|
1314
|
+
});
|
|
1315
|
+
var getOfferingStats = (options) => (options.client ?? client).get({
|
|
1316
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1317
|
+
url: "/offerings/{offering_id}/stats",
|
|
1318
|
+
...options
|
|
1319
|
+
});
|
|
1320
|
+
var getPortfolio = (options) => (options?.client ?? client).get({
|
|
1321
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1322
|
+
url: "/portfolio",
|
|
1323
|
+
...options
|
|
1324
|
+
});
|
|
1325
|
+
var listPortfolioPositions = (options) => (options?.client ?? client).get({
|
|
1326
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1327
|
+
url: "/portfolio/positions",
|
|
1328
|
+
...options
|
|
1329
|
+
});
|
|
1211
1330
|
var listCampaigns = (options) => (options?.client ?? client).get({
|
|
1212
1331
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1213
1332
|
url: "/campaigns",
|
|
@@ -1329,6 +1448,16 @@ var getSyndicateStatistics = (options) => (options.client ?? client).get({
|
|
|
1329
1448
|
url: "/syndicates/{syndicate_id}/statistics",
|
|
1330
1449
|
...options
|
|
1331
1450
|
});
|
|
1451
|
+
var getSyndicatePortfolio = (options) => (options.client ?? client).get({
|
|
1452
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1453
|
+
url: "/syndicates/{syndicate_id}/portfolio",
|
|
1454
|
+
...options
|
|
1455
|
+
});
|
|
1456
|
+
var listSyndicatePortfolioPositions = (options) => (options.client ?? client).get({
|
|
1457
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1458
|
+
url: "/syndicates/{syndicate_id}/portfolio/positions",
|
|
1459
|
+
...options
|
|
1460
|
+
});
|
|
1332
1461
|
var closeSyndicateDeal = (options) => (options.client ?? client).post({
|
|
1333
1462
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1334
1463
|
url: "/syndicates/{syndicate_id}/deals/{fundraise_id}/close",
|
|
@@ -1339,6 +1468,15 @@ var finalizeSyndicateDeal = (options) => (options.client ?? client).post({
|
|
|
1339
1468
|
url: "/syndicates/{syndicate_id}/deals/{fundraise_id}/finalize",
|
|
1340
1469
|
...options
|
|
1341
1470
|
});
|
|
1471
|
+
var previewIntent = (options) => (options.client ?? client).post({
|
|
1472
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1473
|
+
url: "/intents/preview",
|
|
1474
|
+
...options,
|
|
1475
|
+
headers: {
|
|
1476
|
+
"Content-Type": "application/json",
|
|
1477
|
+
...options.headers
|
|
1478
|
+
}
|
|
1479
|
+
});
|
|
1342
1480
|
var listIntents = (options) => (options?.client ?? client).get({
|
|
1343
1481
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1344
1482
|
url: "/intents",
|
|
@@ -1383,6 +1521,96 @@ var listAttributedInvestments = (options) => (options.client ?? client).get({
|
|
|
1383
1521
|
url: "/campaigns/{campaign_id}/attribution/investments",
|
|
1384
1522
|
...options
|
|
1385
1523
|
});
|
|
1524
|
+
var listInstallations = (options) => (options?.client ?? client).get({
|
|
1525
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1526
|
+
url: "/installations",
|
|
1527
|
+
...options
|
|
1528
|
+
});
|
|
1529
|
+
var createInstallation = (options) => (options.client ?? client).post({
|
|
1530
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1531
|
+
url: "/installations",
|
|
1532
|
+
...options,
|
|
1533
|
+
headers: {
|
|
1534
|
+
"Content-Type": "application/json",
|
|
1535
|
+
...options.headers
|
|
1536
|
+
}
|
|
1537
|
+
});
|
|
1538
|
+
var listEligibleInstallTargets = (options) => (options?.client ?? client).get({
|
|
1539
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1540
|
+
url: "/installations/eligible",
|
|
1541
|
+
...options
|
|
1542
|
+
});
|
|
1543
|
+
var revokeInstallation = (options) => (options.client ?? client).delete({
|
|
1544
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1545
|
+
url: "/installations/{external_id}",
|
|
1546
|
+
...options
|
|
1547
|
+
});
|
|
1548
|
+
var getInstallation = (options) => (options.client ?? client).get({
|
|
1549
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1550
|
+
url: "/installations/{external_id}",
|
|
1551
|
+
...options
|
|
1552
|
+
});
|
|
1553
|
+
var createInstallationToken = (options) => (options.client ?? client).post({
|
|
1554
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1555
|
+
url: "/installations/{external_id}/tokens",
|
|
1556
|
+
...options,
|
|
1557
|
+
headers: {
|
|
1558
|
+
"Content-Type": "application/json",
|
|
1559
|
+
...options.headers
|
|
1560
|
+
}
|
|
1561
|
+
});
|
|
1562
|
+
var listWebhookEndpoints = (options) => (options?.client ?? client).get({
|
|
1563
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1564
|
+
url: "/webhook_endpoints",
|
|
1565
|
+
...options
|
|
1566
|
+
});
|
|
1567
|
+
var createWebhookEndpoint = (options) => (options.client ?? client).post({
|
|
1568
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1569
|
+
url: "/webhook_endpoints",
|
|
1570
|
+
...options,
|
|
1571
|
+
headers: {
|
|
1572
|
+
"Content-Type": "application/json",
|
|
1573
|
+
...options.headers
|
|
1574
|
+
}
|
|
1575
|
+
});
|
|
1576
|
+
var deleteWebhookEndpoint = (options) => (options.client ?? client).delete({
|
|
1577
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1578
|
+
url: "/webhook_endpoints/{external_id}",
|
|
1579
|
+
...options
|
|
1580
|
+
});
|
|
1581
|
+
var getWebhookEndpoint = (options) => (options.client ?? client).get({
|
|
1582
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1583
|
+
url: "/webhook_endpoints/{external_id}",
|
|
1584
|
+
...options
|
|
1585
|
+
});
|
|
1586
|
+
var updateWebhookEndpoint = (options) => (options.client ?? client).patch({
|
|
1587
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1588
|
+
url: "/webhook_endpoints/{external_id}",
|
|
1589
|
+
...options,
|
|
1590
|
+
headers: {
|
|
1591
|
+
"Content-Type": "application/json",
|
|
1592
|
+
...options.headers
|
|
1593
|
+
}
|
|
1594
|
+
});
|
|
1595
|
+
var rotateWebhookEndpointSecret = (options) => (options.client ?? client).post({
|
|
1596
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1597
|
+
url: "/webhook_endpoints/{external_id}/rotate_secret",
|
|
1598
|
+
...options
|
|
1599
|
+
});
|
|
1600
|
+
var reenableWebhookEndpoint = (options) => (options.client ?? client).post({
|
|
1601
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1602
|
+
url: "/webhook_endpoints/{external_id}/reenable",
|
|
1603
|
+
...options
|
|
1604
|
+
});
|
|
1605
|
+
var testWebhookEndpoint = (options) => (options.client ?? client).post({
|
|
1606
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1607
|
+
url: "/webhook_endpoints/{external_id}/test",
|
|
1608
|
+
...options,
|
|
1609
|
+
headers: {
|
|
1610
|
+
"Content-Type": "application/json",
|
|
1611
|
+
...options.headers
|
|
1612
|
+
}
|
|
1613
|
+
});
|
|
1386
1614
|
var listWebhookSubscriptions = (options) => (options.client ?? client).get({
|
|
1387
1615
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1388
1616
|
url: "/campaigns/{campaign_id}/attribution/webhooks",
|
|
@@ -1600,10 +1828,27 @@ var Wefunder = class _Wefunder {
|
|
|
1600
1828
|
getOffering({ client: this.#client, path: { external_id: externalId } })
|
|
1601
1829
|
)
|
|
1602
1830
|
};
|
|
1831
|
+
/**
|
|
1832
|
+
* Investments (`read:investments`). `list` is a bootstrap listing; pass `updated_since`
|
|
1833
|
+
* or a saved `cursor` for sync mode (`meta.mode === "delta"`). Persist `meta.next_cursor`
|
|
1834
|
+
* from your last page — it is always present — and resume from it next time.
|
|
1835
|
+
*/
|
|
1603
1836
|
investments = {
|
|
1604
1837
|
list: this.#page(listInvestments),
|
|
1605
|
-
all: () => paginate((cursor) => this.investments.list({ cursor })),
|
|
1606
|
-
collect: () => collect((cursor) => this.investments.list({ cursor }))
|
|
1838
|
+
all: (query) => paginate((cursor) => this.investments.list({ ...query, cursor })),
|
|
1839
|
+
collect: (query) => collect((cursor) => this.investments.list({ ...query, cursor })),
|
|
1840
|
+
/** The current record (not the published projection) for one investment (`inv_…`). */
|
|
1841
|
+
get: (id) => this.#unwrapData(getInvestment({ client: this.#client, path: { id } }))
|
|
1842
|
+
};
|
|
1843
|
+
portfolio = {
|
|
1844
|
+
get: (query) => this.#unwrapData(getPortfolio({ client: this.#client, query })),
|
|
1845
|
+
positions: {
|
|
1846
|
+
list: this.#page(
|
|
1847
|
+
listPortfolioPositions
|
|
1848
|
+
),
|
|
1849
|
+
all: (query) => paginate((cursor) => this.portfolio.positions.list({ ...query, cursor })),
|
|
1850
|
+
collect: (query) => collect((cursor) => this.portfolio.positions.list({ ...query, cursor }))
|
|
1851
|
+
}
|
|
1607
1852
|
};
|
|
1608
1853
|
campaigns = {
|
|
1609
1854
|
list: this.#page(listCampaigns),
|
|
@@ -1623,17 +1868,76 @@ var Wefunder = class _Wefunder {
|
|
|
1623
1868
|
attribution = {
|
|
1624
1869
|
me: () => this.#unwrapData(getAttributionMe({ client: this.#client }))
|
|
1625
1870
|
};
|
|
1871
|
+
/**
|
|
1872
|
+
* Webhook endpoints (`/webhook_endpoints`, scopes `read:webhooks` / `write:webhooks`).
|
|
1873
|
+
* Endpoints belong to your application and are managed through the LIVE API —
|
|
1874
|
+
* create sandbox receivers there with `mode: "test"`; they're mirrored into
|
|
1875
|
+
* sandbox. The signing `secret` is returned ONLY by `create` and `rotateSecret`.
|
|
1876
|
+
* Verify deliveries with `constructEvent` (see the webhooks module).
|
|
1877
|
+
*/
|
|
1878
|
+
webhookEndpoints = {
|
|
1879
|
+
/** All of your app's endpoints (secret omitted). `meta.quota` is the per-app limit. */
|
|
1880
|
+
list: () => this.#unwrap(listWebhookEndpoints({ client: this.#client })),
|
|
1881
|
+
get: (id) => this.#unwrapData(
|
|
1882
|
+
getWebhookEndpoint({ client: this.#client, path: { external_id: id } })
|
|
1883
|
+
),
|
|
1884
|
+
/** Store `attributes.secret` from the result — it is never shown again. */
|
|
1885
|
+
create: (input) => this.#unwrapData(createWebhookEndpoint({ client: this.#client, body: input })),
|
|
1886
|
+
/** `events` replaces the subscription list wholesale (no merge); omit to leave unchanged. */
|
|
1887
|
+
update: (id, input) => this.#unwrapData(
|
|
1888
|
+
updateWebhookEndpoint({ client: this.#client, path: { external_id: id }, body: input })
|
|
1889
|
+
),
|
|
1890
|
+
/** Stops deliveries immediately. Removal is permanent — create a new endpoint to resume. */
|
|
1891
|
+
remove: (id) => this.#unwrapData(
|
|
1892
|
+
deleteWebhookEndpoint({ client: this.#client, path: { external_id: id } })
|
|
1893
|
+
),
|
|
1894
|
+
/**
|
|
1895
|
+
* New secret (shown once). The old one keeps signing for a 24h overlap — deliveries
|
|
1896
|
+
* carry a `v1` for both, and `constructEvent` accepts either.
|
|
1897
|
+
*/
|
|
1898
|
+
rotateSecret: (id) => this.#unwrapData(
|
|
1899
|
+
rotateWebhookEndpointSecret({ client: this.#client, path: { external_id: id } })
|
|
1900
|
+
),
|
|
1901
|
+
/** Recover an auto-disabled endpoint after fixing your server. Idempotent. */
|
|
1902
|
+
reenable: (id) => this.#unwrapData(
|
|
1903
|
+
reenableWebhookEndpoint({ client: this.#client, path: { external_id: id } })
|
|
1904
|
+
),
|
|
1905
|
+
/**
|
|
1906
|
+
* POST a real, signed example event at the endpoint (production envelope + signature)
|
|
1907
|
+
* and report the outcome inline. Defaults to the endpoint's first subscribed event.
|
|
1908
|
+
* Doesn't affect delivery health. Rate-limited to 10/min per endpoint.
|
|
1909
|
+
*/
|
|
1910
|
+
test: (id, event) => this.#unwrapData(
|
|
1911
|
+
testWebhookEndpoint({
|
|
1912
|
+
client: this.#client,
|
|
1913
|
+
path: { external_id: id },
|
|
1914
|
+
body: event ? { event } : void 0
|
|
1915
|
+
})
|
|
1916
|
+
)
|
|
1917
|
+
};
|
|
1626
1918
|
};
|
|
1627
1919
|
|
|
1628
1920
|
// src/webhooks.ts
|
|
1629
1921
|
import { createHmac, timingSafeEqual } from "crypto";
|
|
1630
|
-
var SIGNATURE_HEADER = "
|
|
1631
|
-
var
|
|
1632
|
-
var
|
|
1633
|
-
var
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1922
|
+
var SIGNATURE_HEADER = "wefunder-signature";
|
|
1923
|
+
var DEFAULT_TOLERANCE_SECONDS = 300;
|
|
1924
|
+
var LEGACY_SIGNATURE_HEADER = "x-wefunder-signature";
|
|
1925
|
+
var LEGACY_TIMESTAMP_HEADER = "x-wefunder-timestamp";
|
|
1926
|
+
var LEGACY_EVENT_HEADER = "x-wefunder-event";
|
|
1927
|
+
var LEGACY_DELIVERY_ID_HEADER = "x-wefunder-delivery-id";
|
|
1928
|
+
var WebhookSignatureError = class extends Error {
|
|
1929
|
+
reason;
|
|
1930
|
+
constructor(reason, message) {
|
|
1931
|
+
super(message);
|
|
1932
|
+
this.name = "WebhookSignatureError";
|
|
1933
|
+
this.reason = reason;
|
|
1934
|
+
}
|
|
1935
|
+
};
|
|
1936
|
+
function bodyBuffer(payload) {
|
|
1937
|
+
return typeof payload === "string" ? Buffer.from(payload, "utf8") : Buffer.from(payload);
|
|
1938
|
+
}
|
|
1939
|
+
function computeWebhookSignature(secret, timestamp, payload) {
|
|
1940
|
+
return createHmac("sha256", secret).update(`${timestamp}.`).update(bodyBuffer(payload)).digest("hex");
|
|
1637
1941
|
}
|
|
1638
1942
|
function constantTimeEqual(a, b) {
|
|
1639
1943
|
const ab = Buffer.from(a);
|
|
@@ -1641,66 +1945,175 @@ function constantTimeEqual(a, b) {
|
|
|
1641
1945
|
if (ab.length !== bb.length) return false;
|
|
1642
1946
|
return timingSafeEqual(ab, bb);
|
|
1643
1947
|
}
|
|
1948
|
+
function parseSignatureHeader(header) {
|
|
1949
|
+
let timestamp;
|
|
1950
|
+
const signatures = [];
|
|
1951
|
+
for (const part of header.split(",")) {
|
|
1952
|
+
const eq = part.indexOf("=");
|
|
1953
|
+
if (eq < 0) continue;
|
|
1954
|
+
const key = part.slice(0, eq).trim();
|
|
1955
|
+
const value = part.slice(eq + 1).trim();
|
|
1956
|
+
if (key === "t") {
|
|
1957
|
+
if (!/^\d+$/.test(value)) return null;
|
|
1958
|
+
timestamp = Number(value);
|
|
1959
|
+
} else if (key === "v1" && value) {
|
|
1960
|
+
signatures.push(value);
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
if (timestamp === void 0 || signatures.length === 0) return null;
|
|
1964
|
+
return { timestamp, signatures };
|
|
1965
|
+
}
|
|
1966
|
+
function signWebhook(opts) {
|
|
1967
|
+
const t = opts.timestamp ?? Math.floor(Date.now() / 1e3);
|
|
1968
|
+
const secrets = [opts.secret, ...opts.additionalSecrets ?? []];
|
|
1969
|
+
const entries = secrets.map((s) => `v1=${computeWebhookSignature(s, t, opts.payload)}`);
|
|
1970
|
+
return [`t=${t}`, ...entries].join(",");
|
|
1971
|
+
}
|
|
1972
|
+
function checkWebhookSignature(opts) {
|
|
1973
|
+
const parsed = parseSignatureHeader(opts.header);
|
|
1974
|
+
if (!parsed) return "malformed_header";
|
|
1975
|
+
const tolerance = opts.toleranceSeconds ?? DEFAULT_TOLERANCE_SECONDS;
|
|
1976
|
+
if (tolerance > 0) {
|
|
1977
|
+
const nowSec = (opts.now ?? Date.now)() / 1e3;
|
|
1978
|
+
if (Math.abs(nowSec - parsed.timestamp) > tolerance) return "timestamp_out_of_tolerance";
|
|
1979
|
+
}
|
|
1980
|
+
const expected = computeWebhookSignature(opts.secret, parsed.timestamp, opts.payload);
|
|
1981
|
+
return parsed.signatures.some((sig) => constantTimeEqual(sig, expected)) ? null : "signature_mismatch";
|
|
1982
|
+
}
|
|
1644
1983
|
function verifyWebhook(opts) {
|
|
1645
|
-
|
|
1646
|
-
|
|
1984
|
+
if ("header" in opts) return checkWebhookSignature(opts) === null;
|
|
1985
|
+
return verifyLegacyWebhook(opts);
|
|
1986
|
+
}
|
|
1987
|
+
function verifyLegacyWebhook(opts) {
|
|
1988
|
+
const tolerance = opts.toleranceSeconds ?? DEFAULT_TOLERANCE_SECONDS;
|
|
1647
1989
|
const ts = Number(opts.timestamp);
|
|
1648
1990
|
if (!Number.isFinite(ts)) return false;
|
|
1649
|
-
if (tolerance > 0 && Math.abs(now / 1e3 - ts) > tolerance) return false;
|
|
1650
|
-
const expected =
|
|
1991
|
+
if (tolerance > 0 && Math.abs((opts.now ?? Date.now)() / 1e3 - ts) > tolerance) return false;
|
|
1992
|
+
const expected = `sha256=${computeWebhookSignature(opts.secret, opts.timestamp, opts.payload)}`;
|
|
1651
1993
|
return constantTimeEqual(opts.signature, expected);
|
|
1652
1994
|
}
|
|
1653
|
-
function
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1995
|
+
function headerGetter(headers) {
|
|
1996
|
+
if (typeof headers === "string") {
|
|
1997
|
+
return (name) => name === SIGNATURE_HEADER ? headers : void 0;
|
|
1998
|
+
}
|
|
1999
|
+
if (headers instanceof Headers) return (name) => headers.get(name) ?? void 0;
|
|
2000
|
+
return (name) => {
|
|
2001
|
+
let v = headers[name];
|
|
2002
|
+
if (v === void 0) {
|
|
2003
|
+
const hit = Object.keys(headers).find((k) => k.toLowerCase() === name);
|
|
2004
|
+
if (hit) v = headers[hit];
|
|
2005
|
+
}
|
|
1657
2006
|
return Array.isArray(v) ? v[0] : v;
|
|
1658
2007
|
};
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
2008
|
+
}
|
|
2009
|
+
function constructEvent(payload, headers, secret, opts) {
|
|
2010
|
+
const get = headerGetter(headers);
|
|
2011
|
+
const header = get(SIGNATURE_HEADER);
|
|
2012
|
+
if (!header) {
|
|
2013
|
+
const legacySig = get(LEGACY_SIGNATURE_HEADER);
|
|
2014
|
+
const legacyTs = get(LEGACY_TIMESTAMP_HEADER);
|
|
2015
|
+
if (legacySig && legacyTs) return constructLegacyEvent(payload, get, legacySig, legacyTs, secret, opts);
|
|
2016
|
+
throw new WebhookSignatureError("missing_header", describeFailure("missing_header"));
|
|
2017
|
+
}
|
|
2018
|
+
const failure = checkWebhookSignature({ payload, header, secret, ...opts });
|
|
2019
|
+
if (failure) throw new WebhookSignatureError(failure, describeFailure(failure));
|
|
2020
|
+
const parsed = parseSignatureHeader(header);
|
|
2021
|
+
const env = parseEnvelope(payload);
|
|
1673
2022
|
return {
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
2023
|
+
id: String(env.id ?? ""),
|
|
2024
|
+
event: String(env.event ?? ""),
|
|
2025
|
+
created_at: String(env.created_at ?? ""),
|
|
2026
|
+
mode: env.mode === "test" ? "test" : "live",
|
|
2027
|
+
data: env.data,
|
|
2028
|
+
timestamp: parsed.timestamp
|
|
1678
2029
|
};
|
|
1679
2030
|
}
|
|
2031
|
+
function constructLegacyEvent(payload, get, signature, timestamp, secret, opts) {
|
|
2032
|
+
if (!verifyLegacyWebhook({ payload, signature, timestamp, secret, ...opts })) {
|
|
2033
|
+
throw new WebhookSignatureError("signature_mismatch", describeFailure("signature_mismatch"));
|
|
2034
|
+
}
|
|
2035
|
+
const env = parseEnvelope(payload);
|
|
2036
|
+
return {
|
|
2037
|
+
id: String(env.id ?? get(LEGACY_DELIVERY_ID_HEADER) ?? ""),
|
|
2038
|
+
event: String(env.event ?? get(LEGACY_EVENT_HEADER) ?? ""),
|
|
2039
|
+
created_at: String(env.created_at ?? ""),
|
|
2040
|
+
mode: env.mode === "test" ? "test" : "live",
|
|
2041
|
+
data: env.data ?? env,
|
|
2042
|
+
timestamp: Number(timestamp)
|
|
2043
|
+
};
|
|
2044
|
+
}
|
|
2045
|
+
function parseEnvelope(payload) {
|
|
2046
|
+
try {
|
|
2047
|
+
const parsed = JSON.parse(bodyBuffer(payload).toString("utf8"));
|
|
2048
|
+
if (parsed === null || typeof parsed !== "object") throw new Error("not an object");
|
|
2049
|
+
return parsed;
|
|
2050
|
+
} catch {
|
|
2051
|
+
throw new WebhookSignatureError("invalid_payload", describeFailure("invalid_payload"));
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
function describeFailure(reason) {
|
|
2055
|
+
switch (reason) {
|
|
2056
|
+
case "missing_header":
|
|
2057
|
+
return "Missing Wefunder-Signature header";
|
|
2058
|
+
case "malformed_header":
|
|
2059
|
+
return "Wefunder-Signature header is malformed (expected t=<unix>,v1=<hex>)";
|
|
2060
|
+
case "timestamp_out_of_tolerance":
|
|
2061
|
+
return "Webhook timestamp is outside the replay tolerance";
|
|
2062
|
+
case "signature_mismatch":
|
|
2063
|
+
return "Webhook signature verification failed";
|
|
2064
|
+
case "invalid_payload":
|
|
2065
|
+
return "Webhook body is not a JSON object";
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
async function constructEventFromRequest(request, secret, opts) {
|
|
2069
|
+
const payload = await request.text();
|
|
2070
|
+
return constructEvent(payload, request.headers, secret, opts);
|
|
2071
|
+
}
|
|
2072
|
+
async function dispatchWebhook(event, handlers) {
|
|
2073
|
+
const specific = event.event === "default" ? void 0 : handlers[event.event];
|
|
2074
|
+
if (specific) {
|
|
2075
|
+
await specific(event);
|
|
2076
|
+
return true;
|
|
2077
|
+
}
|
|
2078
|
+
if (handlers.default) {
|
|
2079
|
+
await handlers.default(event);
|
|
2080
|
+
return true;
|
|
2081
|
+
}
|
|
2082
|
+
return false;
|
|
2083
|
+
}
|
|
1680
2084
|
export {
|
|
1681
2085
|
DEFAULT_API_BASE_URL,
|
|
1682
2086
|
DEFAULT_API_VERSION,
|
|
1683
2087
|
DEFAULT_AUTHORIZE_BASE_URL,
|
|
1684
2088
|
DEFAULT_OAUTH_BASE_URL,
|
|
1685
2089
|
DEFAULT_TOKEN_BASE_URL,
|
|
1686
|
-
|
|
1687
|
-
|
|
2090
|
+
DEFAULT_TOLERANCE_SECONDS,
|
|
2091
|
+
LEGACY_DELIVERY_ID_HEADER,
|
|
2092
|
+
LEGACY_EVENT_HEADER,
|
|
2093
|
+
LEGACY_SIGNATURE_HEADER,
|
|
2094
|
+
LEGACY_TIMESTAMP_HEADER,
|
|
1688
2095
|
REQUEST_ID_HEADER,
|
|
1689
2096
|
SANDBOX_AUTHORIZE_BASE_URL,
|
|
1690
2097
|
SIGNATURE_HEADER,
|
|
1691
|
-
|
|
2098
|
+
WebhookSignatureError,
|
|
1692
2099
|
Wefunder,
|
|
1693
2100
|
WefunderAuthError,
|
|
1694
2101
|
WefunderError,
|
|
2102
|
+
checkWebhookSignature,
|
|
1695
2103
|
clientCredentialsGrant,
|
|
1696
2104
|
collect,
|
|
2105
|
+
computeWebhookSignature,
|
|
1697
2106
|
constructEvent,
|
|
2107
|
+
constructEventFromRequest,
|
|
1698
2108
|
createAuthorizationUrl,
|
|
2109
|
+
dispatchWebhook,
|
|
1699
2110
|
exchangeCode,
|
|
1700
2111
|
generatePkce,
|
|
1701
2112
|
modeForToken,
|
|
1702
2113
|
paginate,
|
|
2114
|
+
parseSignatureHeader,
|
|
1703
2115
|
refreshToken,
|
|
2116
|
+
signWebhook,
|
|
1704
2117
|
verifyWebhook
|
|
1705
2118
|
};
|
|
1706
2119
|
//# sourceMappingURL=index.js.map
|