@stackbe/sdk 0.6.4 → 0.7.1
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 +151 -9
- package/dist/index.d.mts +394 -3
- package/dist/index.d.ts +394 -3
- package/dist/index.js +324 -2
- package/dist/index.mjs +321 -2
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -584,7 +584,7 @@ var CheckoutClient = class {
|
|
|
584
584
|
*
|
|
585
585
|
* @example
|
|
586
586
|
* ```typescript
|
|
587
|
-
* // With
|
|
587
|
+
* // With customer email (looks up or creates customer)
|
|
588
588
|
* const { url } = await stackbe.checkout.createSession({
|
|
589
589
|
* customer: { email: 'user@example.com', name: 'John' },
|
|
590
590
|
* planId: 'plan_pro_monthly',
|
|
@@ -592,6 +592,18 @@ var CheckoutClient = class {
|
|
|
592
592
|
* trialDays: 14,
|
|
593
593
|
* });
|
|
594
594
|
* ```
|
|
595
|
+
*
|
|
596
|
+
* @example
|
|
597
|
+
* ```typescript
|
|
598
|
+
* // Organization-level subscription (B2B)
|
|
599
|
+
* const { url } = await stackbe.checkout.createSession({
|
|
600
|
+
* customer: 'cust_123',
|
|
601
|
+
* organizationId: 'org_456', // Customer must be owner/admin
|
|
602
|
+
* planId: 'plan_team',
|
|
603
|
+
* successUrl: 'https://myapp.com/success',
|
|
604
|
+
* cancelUrl: 'https://myapp.com/pricing',
|
|
605
|
+
* });
|
|
606
|
+
* ```
|
|
595
607
|
*/
|
|
596
608
|
async createSession(options) {
|
|
597
609
|
const body = {
|
|
@@ -599,15 +611,25 @@ var CheckoutClient = class {
|
|
|
599
611
|
planId: options.planId,
|
|
600
612
|
successUrl: options.successUrl,
|
|
601
613
|
cancelUrl: options.cancelUrl,
|
|
614
|
+
organizationId: options.organizationId,
|
|
602
615
|
allowPromotionCodes: options.allowPromotionCodes,
|
|
603
616
|
trialDays: options.trialDays,
|
|
604
617
|
metadata: options.metadata
|
|
605
618
|
};
|
|
619
|
+
if (!options.customer) {
|
|
620
|
+
throw new Error(
|
|
621
|
+
'customer is required. Use customer: "cust_xxx" for existing customer ID, or customer: { email: "user@example.com" } for email-based lookup.'
|
|
622
|
+
);
|
|
623
|
+
}
|
|
606
624
|
if (typeof options.customer === "string") {
|
|
607
625
|
body.customerId = options.customer;
|
|
608
|
-
} else {
|
|
626
|
+
} else if (options.customer.email) {
|
|
609
627
|
body.customerEmail = options.customer.email;
|
|
610
628
|
body.customerName = options.customer.name;
|
|
629
|
+
} else {
|
|
630
|
+
throw new Error(
|
|
631
|
+
'customer.email is required when using object form. Use customer: { email: "user@example.com" }'
|
|
632
|
+
);
|
|
611
633
|
}
|
|
612
634
|
return this.http.post("/v1/checkout/session", body);
|
|
613
635
|
}
|
|
@@ -1299,6 +1321,297 @@ var OrganizationsClient = class {
|
|
|
1299
1321
|
}
|
|
1300
1322
|
};
|
|
1301
1323
|
|
|
1324
|
+
// src/plans.ts
|
|
1325
|
+
var PlansClient = class {
|
|
1326
|
+
constructor(http) {
|
|
1327
|
+
this.http = http;
|
|
1328
|
+
}
|
|
1329
|
+
/**
|
|
1330
|
+
* List all plans for the app.
|
|
1331
|
+
*
|
|
1332
|
+
* @example
|
|
1333
|
+
* ```typescript
|
|
1334
|
+
* // List all plans
|
|
1335
|
+
* const plans = await stackbe.plans.list();
|
|
1336
|
+
*
|
|
1337
|
+
* // Filter by product
|
|
1338
|
+
* const plans = await stackbe.plans.list({ productId: 'prod_123' });
|
|
1339
|
+
*
|
|
1340
|
+
* // Display in pricing page
|
|
1341
|
+
* plans.forEach(plan => {
|
|
1342
|
+
* console.log(`${plan.name}: $${plan.priceCents / 100}/${plan.interval}`);
|
|
1343
|
+
* });
|
|
1344
|
+
* ```
|
|
1345
|
+
*/
|
|
1346
|
+
async list(options) {
|
|
1347
|
+
const params = new URLSearchParams();
|
|
1348
|
+
if (options?.productId) {
|
|
1349
|
+
params.set("productId", options.productId);
|
|
1350
|
+
}
|
|
1351
|
+
const query = params.toString();
|
|
1352
|
+
return this.http.get(`/v1/plans${query ? `?${query}` : ""}`);
|
|
1353
|
+
}
|
|
1354
|
+
/**
|
|
1355
|
+
* Get a plan by ID.
|
|
1356
|
+
*
|
|
1357
|
+
* @example
|
|
1358
|
+
* ```typescript
|
|
1359
|
+
* const plan = await stackbe.plans.get('plan_123');
|
|
1360
|
+
* console.log(plan.name, plan.priceCents, plan.entitlements);
|
|
1361
|
+
* ```
|
|
1362
|
+
*/
|
|
1363
|
+
async get(planId) {
|
|
1364
|
+
return this.http.get(`/v1/plans/${planId}`);
|
|
1365
|
+
}
|
|
1366
|
+
/**
|
|
1367
|
+
* Get active plans only (excludes archived plans).
|
|
1368
|
+
*
|
|
1369
|
+
* @example
|
|
1370
|
+
* ```typescript
|
|
1371
|
+
* const activePlans = await stackbe.plans.getActive();
|
|
1372
|
+
* ```
|
|
1373
|
+
*/
|
|
1374
|
+
async getActive(options) {
|
|
1375
|
+
const plans = await this.list(options);
|
|
1376
|
+
return plans.filter((p) => p.status === "active");
|
|
1377
|
+
}
|
|
1378
|
+
/**
|
|
1379
|
+
* Get plans sorted by price (ascending).
|
|
1380
|
+
*
|
|
1381
|
+
* @example
|
|
1382
|
+
* ```typescript
|
|
1383
|
+
* const plans = await stackbe.plans.listByPrice();
|
|
1384
|
+
* // [Free, Starter, Pro, Enterprise]
|
|
1385
|
+
* ```
|
|
1386
|
+
*/
|
|
1387
|
+
async listByPrice(options) {
|
|
1388
|
+
const plans = await this.getActive(options);
|
|
1389
|
+
return plans.sort((a, b) => a.priceCents - b.priceCents);
|
|
1390
|
+
}
|
|
1391
|
+
};
|
|
1392
|
+
var ProductsClient = class {
|
|
1393
|
+
constructor(http, appId) {
|
|
1394
|
+
this.http = http;
|
|
1395
|
+
this.appId = appId;
|
|
1396
|
+
}
|
|
1397
|
+
/**
|
|
1398
|
+
* List all products for the app.
|
|
1399
|
+
*
|
|
1400
|
+
* @example
|
|
1401
|
+
* ```typescript
|
|
1402
|
+
* const products = await stackbe.products.list();
|
|
1403
|
+
* products.forEach(product => {
|
|
1404
|
+
* console.log(product.name, product.plans?.length, 'plans');
|
|
1405
|
+
* });
|
|
1406
|
+
* ```
|
|
1407
|
+
*/
|
|
1408
|
+
async list(options) {
|
|
1409
|
+
const params = new URLSearchParams();
|
|
1410
|
+
params.set("appId", options?.appId ?? this.appId);
|
|
1411
|
+
return this.http.get(`/v1/products?${params.toString()}`);
|
|
1412
|
+
}
|
|
1413
|
+
/**
|
|
1414
|
+
* Get a product by ID.
|
|
1415
|
+
*
|
|
1416
|
+
* @example
|
|
1417
|
+
* ```typescript
|
|
1418
|
+
* const product = await stackbe.products.get('prod_123');
|
|
1419
|
+
* console.log(product.name, product.description);
|
|
1420
|
+
* ```
|
|
1421
|
+
*/
|
|
1422
|
+
async get(productId) {
|
|
1423
|
+
return this.http.get(`/v1/products/${productId}`);
|
|
1424
|
+
}
|
|
1425
|
+
};
|
|
1426
|
+
|
|
1427
|
+
// src/feature-requests.ts
|
|
1428
|
+
var FeatureRequestsClient = class {
|
|
1429
|
+
constructor(http, appId) {
|
|
1430
|
+
this.http = http;
|
|
1431
|
+
this.appId = appId;
|
|
1432
|
+
}
|
|
1433
|
+
/**
|
|
1434
|
+
* List feature requests for the app.
|
|
1435
|
+
*
|
|
1436
|
+
* @example
|
|
1437
|
+
* ```typescript
|
|
1438
|
+
* // Get all feature requests
|
|
1439
|
+
* const { data, total } = await stackbe.featureRequests.list();
|
|
1440
|
+
*
|
|
1441
|
+
* // Filter by status
|
|
1442
|
+
* const planned = await stackbe.featureRequests.list({ status: 'planned' });
|
|
1443
|
+
*
|
|
1444
|
+
* // Sort by votes
|
|
1445
|
+
* const popular = await stackbe.featureRequests.list({ sortBy: 'votes' });
|
|
1446
|
+
* ```
|
|
1447
|
+
*/
|
|
1448
|
+
async list(options = {}) {
|
|
1449
|
+
const params = {};
|
|
1450
|
+
if (options.status) params.status = options.status;
|
|
1451
|
+
if (options.category) params.category = options.category;
|
|
1452
|
+
if (options.sortBy) params.sortBy = options.sortBy;
|
|
1453
|
+
if (options.limit) params.limit = options.limit;
|
|
1454
|
+
if (options.offset) params.offset = options.offset;
|
|
1455
|
+
return this.http.get(
|
|
1456
|
+
`/v1/apps/${this.appId}/feature-requests`,
|
|
1457
|
+
params
|
|
1458
|
+
);
|
|
1459
|
+
}
|
|
1460
|
+
/**
|
|
1461
|
+
* Submit a new feature request.
|
|
1462
|
+
* Requires customer session token.
|
|
1463
|
+
*
|
|
1464
|
+
* @example
|
|
1465
|
+
* ```typescript
|
|
1466
|
+
* const request = await stackbe.featureRequests.create({
|
|
1467
|
+
* title: 'Dark mode support',
|
|
1468
|
+
* description: 'Would love to have a dark theme option',
|
|
1469
|
+
* category: 'UI',
|
|
1470
|
+
* });
|
|
1471
|
+
* ```
|
|
1472
|
+
*/
|
|
1473
|
+
async create(options) {
|
|
1474
|
+
return this.http.post(
|
|
1475
|
+
`/v1/apps/${this.appId}/feature-requests`,
|
|
1476
|
+
options
|
|
1477
|
+
);
|
|
1478
|
+
}
|
|
1479
|
+
/**
|
|
1480
|
+
* Get a specific feature request by ID.
|
|
1481
|
+
*
|
|
1482
|
+
* @example
|
|
1483
|
+
* ```typescript
|
|
1484
|
+
* const request = await stackbe.featureRequests.get('req_123');
|
|
1485
|
+
* console.log(`${request.title} has ${request.voteCount} votes`);
|
|
1486
|
+
* ```
|
|
1487
|
+
*/
|
|
1488
|
+
async get(requestId) {
|
|
1489
|
+
return this.http.get(
|
|
1490
|
+
`/v1/apps/${this.appId}/feature-requests/${requestId}`
|
|
1491
|
+
);
|
|
1492
|
+
}
|
|
1493
|
+
/**
|
|
1494
|
+
* Upvote a feature request.
|
|
1495
|
+
* Requires customer session token. Idempotent.
|
|
1496
|
+
*
|
|
1497
|
+
* @example
|
|
1498
|
+
* ```typescript
|
|
1499
|
+
* await stackbe.featureRequests.vote('req_123');
|
|
1500
|
+
* ```
|
|
1501
|
+
*/
|
|
1502
|
+
async vote(requestId) {
|
|
1503
|
+
return this.http.post(
|
|
1504
|
+
`/v1/apps/${this.appId}/feature-requests/${requestId}/vote`
|
|
1505
|
+
);
|
|
1506
|
+
}
|
|
1507
|
+
/**
|
|
1508
|
+
* Remove your vote from a feature request.
|
|
1509
|
+
* Requires customer session token.
|
|
1510
|
+
*
|
|
1511
|
+
* @example
|
|
1512
|
+
* ```typescript
|
|
1513
|
+
* await stackbe.featureRequests.removeVote('req_123');
|
|
1514
|
+
* ```
|
|
1515
|
+
*/
|
|
1516
|
+
async removeVote(requestId) {
|
|
1517
|
+
return this.http.delete(
|
|
1518
|
+
`/v1/apps/${this.appId}/feature-requests/${requestId}/vote`
|
|
1519
|
+
);
|
|
1520
|
+
}
|
|
1521
|
+
/**
|
|
1522
|
+
* Add a comment to a feature request.
|
|
1523
|
+
* Requires customer session token.
|
|
1524
|
+
*
|
|
1525
|
+
* @example
|
|
1526
|
+
* ```typescript
|
|
1527
|
+
* await stackbe.featureRequests.addComment('req_123', {
|
|
1528
|
+
* content: 'This would be really helpful for my workflow!',
|
|
1529
|
+
* });
|
|
1530
|
+
* ```
|
|
1531
|
+
*/
|
|
1532
|
+
async addComment(requestId, options) {
|
|
1533
|
+
return this.http.post(
|
|
1534
|
+
`/v1/apps/${this.appId}/feature-requests/${requestId}/comments`,
|
|
1535
|
+
options
|
|
1536
|
+
);
|
|
1537
|
+
}
|
|
1538
|
+
// ==================== Admin Methods ====================
|
|
1539
|
+
/**
|
|
1540
|
+
* Update a feature request status or category.
|
|
1541
|
+
* Requires API key (admin).
|
|
1542
|
+
*
|
|
1543
|
+
* @example
|
|
1544
|
+
* ```typescript
|
|
1545
|
+
* await stackbe.featureRequests.update('req_123', {
|
|
1546
|
+
* status: 'planned',
|
|
1547
|
+
* category: 'Core Features',
|
|
1548
|
+
* });
|
|
1549
|
+
* ```
|
|
1550
|
+
*/
|
|
1551
|
+
async update(requestId, options) {
|
|
1552
|
+
return this.http.patch(
|
|
1553
|
+
`/v1/apps/${this.appId}/feature-requests/${requestId}`,
|
|
1554
|
+
options
|
|
1555
|
+
);
|
|
1556
|
+
}
|
|
1557
|
+
/**
|
|
1558
|
+
* Delete a feature request.
|
|
1559
|
+
* Requires API key (admin).
|
|
1560
|
+
*
|
|
1561
|
+
* @example
|
|
1562
|
+
* ```typescript
|
|
1563
|
+
* await stackbe.featureRequests.delete('req_123');
|
|
1564
|
+
* ```
|
|
1565
|
+
*/
|
|
1566
|
+
async delete(requestId) {
|
|
1567
|
+
return this.http.delete(
|
|
1568
|
+
`/v1/apps/${this.appId}/feature-requests/${requestId}`
|
|
1569
|
+
);
|
|
1570
|
+
}
|
|
1571
|
+
/**
|
|
1572
|
+
* Get all customers interested in a feature request (author + voters).
|
|
1573
|
+
* Useful for user research or notifying users when the feature ships.
|
|
1574
|
+
* Requires API key (admin).
|
|
1575
|
+
*
|
|
1576
|
+
* @example
|
|
1577
|
+
* ```typescript
|
|
1578
|
+
* const { author, voters, totalInterested } = await stackbe.featureRequests.getInterestedCustomers('req_123');
|
|
1579
|
+
*
|
|
1580
|
+
* // Notify all interested users
|
|
1581
|
+
* const emails = [author.email, ...voters.map(v => v.email)];
|
|
1582
|
+
* await sendNotification(emails, 'Your requested feature is now live!');
|
|
1583
|
+
* ```
|
|
1584
|
+
*/
|
|
1585
|
+
async getInterestedCustomers(requestId) {
|
|
1586
|
+
return this.http.get(
|
|
1587
|
+
`/v1/apps/${this.appId}/feature-requests/${requestId}/interested`
|
|
1588
|
+
);
|
|
1589
|
+
}
|
|
1590
|
+
/**
|
|
1591
|
+
* Get a customer's feature request activity (requests submitted + votes).
|
|
1592
|
+
* Useful for displaying on customer profile.
|
|
1593
|
+
* Requires API key (admin).
|
|
1594
|
+
*
|
|
1595
|
+
* @example
|
|
1596
|
+
* ```typescript
|
|
1597
|
+
* const activity = await stackbe.featureRequests.getCustomerActivity('cust_123');
|
|
1598
|
+
*
|
|
1599
|
+
* console.log(`Submitted ${activity.totalSubmitted} requests`);
|
|
1600
|
+
* console.log(`Voted on ${activity.totalVotes} requests`);
|
|
1601
|
+
*
|
|
1602
|
+
* // Show their most wanted features
|
|
1603
|
+
* activity.votedOn.forEach(r => {
|
|
1604
|
+
* console.log(`- ${r.title} (${r.status})`);
|
|
1605
|
+
* });
|
|
1606
|
+
* ```
|
|
1607
|
+
*/
|
|
1608
|
+
async getCustomerActivity(customerId) {
|
|
1609
|
+
return this.http.get(
|
|
1610
|
+
`/v1/apps/${this.appId}/feature-requests/customer/${customerId}/activity`
|
|
1611
|
+
);
|
|
1612
|
+
}
|
|
1613
|
+
};
|
|
1614
|
+
|
|
1302
1615
|
// src/client.ts
|
|
1303
1616
|
var DEFAULT_BASE_URL = "https://api.stackbe.io";
|
|
1304
1617
|
var DEFAULT_TIMEOUT = 3e4;
|
|
@@ -1359,6 +1672,9 @@ var StackBE = class {
|
|
|
1359
1672
|
devCallbackUrl: config.devCallbackUrl
|
|
1360
1673
|
});
|
|
1361
1674
|
this.organizations = new OrganizationsClient(this.http, config.appId);
|
|
1675
|
+
this.plans = new PlansClient(this.http);
|
|
1676
|
+
this.products = new ProductsClient(this.http, config.appId);
|
|
1677
|
+
this.featureRequests = new FeatureRequestsClient(this.http, config.appId);
|
|
1362
1678
|
}
|
|
1363
1679
|
/**
|
|
1364
1680
|
* Create a middleware for Express that tracks usage automatically.
|
|
@@ -1495,7 +1811,10 @@ export {
|
|
|
1495
1811
|
CheckoutClient,
|
|
1496
1812
|
CustomersClient,
|
|
1497
1813
|
EntitlementsClient,
|
|
1814
|
+
FeatureRequestsClient,
|
|
1498
1815
|
OrganizationsClient,
|
|
1816
|
+
PlansClient,
|
|
1817
|
+
ProductsClient,
|
|
1499
1818
|
StackBE,
|
|
1500
1819
|
StackBEError,
|
|
1501
1820
|
SubscriptionsClient,
|
package/package.json
CHANGED