@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.js
CHANGED
|
@@ -24,7 +24,10 @@ __export(index_exports, {
|
|
|
24
24
|
CheckoutClient: () => CheckoutClient,
|
|
25
25
|
CustomersClient: () => CustomersClient,
|
|
26
26
|
EntitlementsClient: () => EntitlementsClient,
|
|
27
|
+
FeatureRequestsClient: () => FeatureRequestsClient,
|
|
27
28
|
OrganizationsClient: () => OrganizationsClient,
|
|
29
|
+
PlansClient: () => PlansClient,
|
|
30
|
+
ProductsClient: () => ProductsClient,
|
|
28
31
|
StackBE: () => StackBE,
|
|
29
32
|
StackBEError: () => StackBEError,
|
|
30
33
|
SubscriptionsClient: () => SubscriptionsClient,
|
|
@@ -618,7 +621,7 @@ var CheckoutClient = class {
|
|
|
618
621
|
*
|
|
619
622
|
* @example
|
|
620
623
|
* ```typescript
|
|
621
|
-
* // With
|
|
624
|
+
* // With customer email (looks up or creates customer)
|
|
622
625
|
* const { url } = await stackbe.checkout.createSession({
|
|
623
626
|
* customer: { email: 'user@example.com', name: 'John' },
|
|
624
627
|
* planId: 'plan_pro_monthly',
|
|
@@ -626,6 +629,18 @@ var CheckoutClient = class {
|
|
|
626
629
|
* trialDays: 14,
|
|
627
630
|
* });
|
|
628
631
|
* ```
|
|
632
|
+
*
|
|
633
|
+
* @example
|
|
634
|
+
* ```typescript
|
|
635
|
+
* // Organization-level subscription (B2B)
|
|
636
|
+
* const { url } = await stackbe.checkout.createSession({
|
|
637
|
+
* customer: 'cust_123',
|
|
638
|
+
* organizationId: 'org_456', // Customer must be owner/admin
|
|
639
|
+
* planId: 'plan_team',
|
|
640
|
+
* successUrl: 'https://myapp.com/success',
|
|
641
|
+
* cancelUrl: 'https://myapp.com/pricing',
|
|
642
|
+
* });
|
|
643
|
+
* ```
|
|
629
644
|
*/
|
|
630
645
|
async createSession(options) {
|
|
631
646
|
const body = {
|
|
@@ -633,15 +648,25 @@ var CheckoutClient = class {
|
|
|
633
648
|
planId: options.planId,
|
|
634
649
|
successUrl: options.successUrl,
|
|
635
650
|
cancelUrl: options.cancelUrl,
|
|
651
|
+
organizationId: options.organizationId,
|
|
636
652
|
allowPromotionCodes: options.allowPromotionCodes,
|
|
637
653
|
trialDays: options.trialDays,
|
|
638
654
|
metadata: options.metadata
|
|
639
655
|
};
|
|
656
|
+
if (!options.customer) {
|
|
657
|
+
throw new Error(
|
|
658
|
+
'customer is required. Use customer: "cust_xxx" for existing customer ID, or customer: { email: "user@example.com" } for email-based lookup.'
|
|
659
|
+
);
|
|
660
|
+
}
|
|
640
661
|
if (typeof options.customer === "string") {
|
|
641
662
|
body.customerId = options.customer;
|
|
642
|
-
} else {
|
|
663
|
+
} else if (options.customer.email) {
|
|
643
664
|
body.customerEmail = options.customer.email;
|
|
644
665
|
body.customerName = options.customer.name;
|
|
666
|
+
} else {
|
|
667
|
+
throw new Error(
|
|
668
|
+
'customer.email is required when using object form. Use customer: { email: "user@example.com" }'
|
|
669
|
+
);
|
|
645
670
|
}
|
|
646
671
|
return this.http.post("/v1/checkout/session", body);
|
|
647
672
|
}
|
|
@@ -1333,6 +1358,297 @@ var OrganizationsClient = class {
|
|
|
1333
1358
|
}
|
|
1334
1359
|
};
|
|
1335
1360
|
|
|
1361
|
+
// src/plans.ts
|
|
1362
|
+
var PlansClient = class {
|
|
1363
|
+
constructor(http) {
|
|
1364
|
+
this.http = http;
|
|
1365
|
+
}
|
|
1366
|
+
/**
|
|
1367
|
+
* List all plans for the app.
|
|
1368
|
+
*
|
|
1369
|
+
* @example
|
|
1370
|
+
* ```typescript
|
|
1371
|
+
* // List all plans
|
|
1372
|
+
* const plans = await stackbe.plans.list();
|
|
1373
|
+
*
|
|
1374
|
+
* // Filter by product
|
|
1375
|
+
* const plans = await stackbe.plans.list({ productId: 'prod_123' });
|
|
1376
|
+
*
|
|
1377
|
+
* // Display in pricing page
|
|
1378
|
+
* plans.forEach(plan => {
|
|
1379
|
+
* console.log(`${plan.name}: $${plan.priceCents / 100}/${plan.interval}`);
|
|
1380
|
+
* });
|
|
1381
|
+
* ```
|
|
1382
|
+
*/
|
|
1383
|
+
async list(options) {
|
|
1384
|
+
const params = new URLSearchParams();
|
|
1385
|
+
if (options?.productId) {
|
|
1386
|
+
params.set("productId", options.productId);
|
|
1387
|
+
}
|
|
1388
|
+
const query = params.toString();
|
|
1389
|
+
return this.http.get(`/v1/plans${query ? `?${query}` : ""}`);
|
|
1390
|
+
}
|
|
1391
|
+
/**
|
|
1392
|
+
* Get a plan by ID.
|
|
1393
|
+
*
|
|
1394
|
+
* @example
|
|
1395
|
+
* ```typescript
|
|
1396
|
+
* const plan = await stackbe.plans.get('plan_123');
|
|
1397
|
+
* console.log(plan.name, plan.priceCents, plan.entitlements);
|
|
1398
|
+
* ```
|
|
1399
|
+
*/
|
|
1400
|
+
async get(planId) {
|
|
1401
|
+
return this.http.get(`/v1/plans/${planId}`);
|
|
1402
|
+
}
|
|
1403
|
+
/**
|
|
1404
|
+
* Get active plans only (excludes archived plans).
|
|
1405
|
+
*
|
|
1406
|
+
* @example
|
|
1407
|
+
* ```typescript
|
|
1408
|
+
* const activePlans = await stackbe.plans.getActive();
|
|
1409
|
+
* ```
|
|
1410
|
+
*/
|
|
1411
|
+
async getActive(options) {
|
|
1412
|
+
const plans = await this.list(options);
|
|
1413
|
+
return plans.filter((p) => p.status === "active");
|
|
1414
|
+
}
|
|
1415
|
+
/**
|
|
1416
|
+
* Get plans sorted by price (ascending).
|
|
1417
|
+
*
|
|
1418
|
+
* @example
|
|
1419
|
+
* ```typescript
|
|
1420
|
+
* const plans = await stackbe.plans.listByPrice();
|
|
1421
|
+
* // [Free, Starter, Pro, Enterprise]
|
|
1422
|
+
* ```
|
|
1423
|
+
*/
|
|
1424
|
+
async listByPrice(options) {
|
|
1425
|
+
const plans = await this.getActive(options);
|
|
1426
|
+
return plans.sort((a, b) => a.priceCents - b.priceCents);
|
|
1427
|
+
}
|
|
1428
|
+
};
|
|
1429
|
+
var ProductsClient = class {
|
|
1430
|
+
constructor(http, appId) {
|
|
1431
|
+
this.http = http;
|
|
1432
|
+
this.appId = appId;
|
|
1433
|
+
}
|
|
1434
|
+
/**
|
|
1435
|
+
* List all products for the app.
|
|
1436
|
+
*
|
|
1437
|
+
* @example
|
|
1438
|
+
* ```typescript
|
|
1439
|
+
* const products = await stackbe.products.list();
|
|
1440
|
+
* products.forEach(product => {
|
|
1441
|
+
* console.log(product.name, product.plans?.length, 'plans');
|
|
1442
|
+
* });
|
|
1443
|
+
* ```
|
|
1444
|
+
*/
|
|
1445
|
+
async list(options) {
|
|
1446
|
+
const params = new URLSearchParams();
|
|
1447
|
+
params.set("appId", options?.appId ?? this.appId);
|
|
1448
|
+
return this.http.get(`/v1/products?${params.toString()}`);
|
|
1449
|
+
}
|
|
1450
|
+
/**
|
|
1451
|
+
* Get a product by ID.
|
|
1452
|
+
*
|
|
1453
|
+
* @example
|
|
1454
|
+
* ```typescript
|
|
1455
|
+
* const product = await stackbe.products.get('prod_123');
|
|
1456
|
+
* console.log(product.name, product.description);
|
|
1457
|
+
* ```
|
|
1458
|
+
*/
|
|
1459
|
+
async get(productId) {
|
|
1460
|
+
return this.http.get(`/v1/products/${productId}`);
|
|
1461
|
+
}
|
|
1462
|
+
};
|
|
1463
|
+
|
|
1464
|
+
// src/feature-requests.ts
|
|
1465
|
+
var FeatureRequestsClient = class {
|
|
1466
|
+
constructor(http, appId) {
|
|
1467
|
+
this.http = http;
|
|
1468
|
+
this.appId = appId;
|
|
1469
|
+
}
|
|
1470
|
+
/**
|
|
1471
|
+
* List feature requests for the app.
|
|
1472
|
+
*
|
|
1473
|
+
* @example
|
|
1474
|
+
* ```typescript
|
|
1475
|
+
* // Get all feature requests
|
|
1476
|
+
* const { data, total } = await stackbe.featureRequests.list();
|
|
1477
|
+
*
|
|
1478
|
+
* // Filter by status
|
|
1479
|
+
* const planned = await stackbe.featureRequests.list({ status: 'planned' });
|
|
1480
|
+
*
|
|
1481
|
+
* // Sort by votes
|
|
1482
|
+
* const popular = await stackbe.featureRequests.list({ sortBy: 'votes' });
|
|
1483
|
+
* ```
|
|
1484
|
+
*/
|
|
1485
|
+
async list(options = {}) {
|
|
1486
|
+
const params = {};
|
|
1487
|
+
if (options.status) params.status = options.status;
|
|
1488
|
+
if (options.category) params.category = options.category;
|
|
1489
|
+
if (options.sortBy) params.sortBy = options.sortBy;
|
|
1490
|
+
if (options.limit) params.limit = options.limit;
|
|
1491
|
+
if (options.offset) params.offset = options.offset;
|
|
1492
|
+
return this.http.get(
|
|
1493
|
+
`/v1/apps/${this.appId}/feature-requests`,
|
|
1494
|
+
params
|
|
1495
|
+
);
|
|
1496
|
+
}
|
|
1497
|
+
/**
|
|
1498
|
+
* Submit a new feature request.
|
|
1499
|
+
* Requires customer session token.
|
|
1500
|
+
*
|
|
1501
|
+
* @example
|
|
1502
|
+
* ```typescript
|
|
1503
|
+
* const request = await stackbe.featureRequests.create({
|
|
1504
|
+
* title: 'Dark mode support',
|
|
1505
|
+
* description: 'Would love to have a dark theme option',
|
|
1506
|
+
* category: 'UI',
|
|
1507
|
+
* });
|
|
1508
|
+
* ```
|
|
1509
|
+
*/
|
|
1510
|
+
async create(options) {
|
|
1511
|
+
return this.http.post(
|
|
1512
|
+
`/v1/apps/${this.appId}/feature-requests`,
|
|
1513
|
+
options
|
|
1514
|
+
);
|
|
1515
|
+
}
|
|
1516
|
+
/**
|
|
1517
|
+
* Get a specific feature request by ID.
|
|
1518
|
+
*
|
|
1519
|
+
* @example
|
|
1520
|
+
* ```typescript
|
|
1521
|
+
* const request = await stackbe.featureRequests.get('req_123');
|
|
1522
|
+
* console.log(`${request.title} has ${request.voteCount} votes`);
|
|
1523
|
+
* ```
|
|
1524
|
+
*/
|
|
1525
|
+
async get(requestId) {
|
|
1526
|
+
return this.http.get(
|
|
1527
|
+
`/v1/apps/${this.appId}/feature-requests/${requestId}`
|
|
1528
|
+
);
|
|
1529
|
+
}
|
|
1530
|
+
/**
|
|
1531
|
+
* Upvote a feature request.
|
|
1532
|
+
* Requires customer session token. Idempotent.
|
|
1533
|
+
*
|
|
1534
|
+
* @example
|
|
1535
|
+
* ```typescript
|
|
1536
|
+
* await stackbe.featureRequests.vote('req_123');
|
|
1537
|
+
* ```
|
|
1538
|
+
*/
|
|
1539
|
+
async vote(requestId) {
|
|
1540
|
+
return this.http.post(
|
|
1541
|
+
`/v1/apps/${this.appId}/feature-requests/${requestId}/vote`
|
|
1542
|
+
);
|
|
1543
|
+
}
|
|
1544
|
+
/**
|
|
1545
|
+
* Remove your vote from a feature request.
|
|
1546
|
+
* Requires customer session token.
|
|
1547
|
+
*
|
|
1548
|
+
* @example
|
|
1549
|
+
* ```typescript
|
|
1550
|
+
* await stackbe.featureRequests.removeVote('req_123');
|
|
1551
|
+
* ```
|
|
1552
|
+
*/
|
|
1553
|
+
async removeVote(requestId) {
|
|
1554
|
+
return this.http.delete(
|
|
1555
|
+
`/v1/apps/${this.appId}/feature-requests/${requestId}/vote`
|
|
1556
|
+
);
|
|
1557
|
+
}
|
|
1558
|
+
/**
|
|
1559
|
+
* Add a comment to a feature request.
|
|
1560
|
+
* Requires customer session token.
|
|
1561
|
+
*
|
|
1562
|
+
* @example
|
|
1563
|
+
* ```typescript
|
|
1564
|
+
* await stackbe.featureRequests.addComment('req_123', {
|
|
1565
|
+
* content: 'This would be really helpful for my workflow!',
|
|
1566
|
+
* });
|
|
1567
|
+
* ```
|
|
1568
|
+
*/
|
|
1569
|
+
async addComment(requestId, options) {
|
|
1570
|
+
return this.http.post(
|
|
1571
|
+
`/v1/apps/${this.appId}/feature-requests/${requestId}/comments`,
|
|
1572
|
+
options
|
|
1573
|
+
);
|
|
1574
|
+
}
|
|
1575
|
+
// ==================== Admin Methods ====================
|
|
1576
|
+
/**
|
|
1577
|
+
* Update a feature request status or category.
|
|
1578
|
+
* Requires API key (admin).
|
|
1579
|
+
*
|
|
1580
|
+
* @example
|
|
1581
|
+
* ```typescript
|
|
1582
|
+
* await stackbe.featureRequests.update('req_123', {
|
|
1583
|
+
* status: 'planned',
|
|
1584
|
+
* category: 'Core Features',
|
|
1585
|
+
* });
|
|
1586
|
+
* ```
|
|
1587
|
+
*/
|
|
1588
|
+
async update(requestId, options) {
|
|
1589
|
+
return this.http.patch(
|
|
1590
|
+
`/v1/apps/${this.appId}/feature-requests/${requestId}`,
|
|
1591
|
+
options
|
|
1592
|
+
);
|
|
1593
|
+
}
|
|
1594
|
+
/**
|
|
1595
|
+
* Delete a feature request.
|
|
1596
|
+
* Requires API key (admin).
|
|
1597
|
+
*
|
|
1598
|
+
* @example
|
|
1599
|
+
* ```typescript
|
|
1600
|
+
* await stackbe.featureRequests.delete('req_123');
|
|
1601
|
+
* ```
|
|
1602
|
+
*/
|
|
1603
|
+
async delete(requestId) {
|
|
1604
|
+
return this.http.delete(
|
|
1605
|
+
`/v1/apps/${this.appId}/feature-requests/${requestId}`
|
|
1606
|
+
);
|
|
1607
|
+
}
|
|
1608
|
+
/**
|
|
1609
|
+
* Get all customers interested in a feature request (author + voters).
|
|
1610
|
+
* Useful for user research or notifying users when the feature ships.
|
|
1611
|
+
* Requires API key (admin).
|
|
1612
|
+
*
|
|
1613
|
+
* @example
|
|
1614
|
+
* ```typescript
|
|
1615
|
+
* const { author, voters, totalInterested } = await stackbe.featureRequests.getInterestedCustomers('req_123');
|
|
1616
|
+
*
|
|
1617
|
+
* // Notify all interested users
|
|
1618
|
+
* const emails = [author.email, ...voters.map(v => v.email)];
|
|
1619
|
+
* await sendNotification(emails, 'Your requested feature is now live!');
|
|
1620
|
+
* ```
|
|
1621
|
+
*/
|
|
1622
|
+
async getInterestedCustomers(requestId) {
|
|
1623
|
+
return this.http.get(
|
|
1624
|
+
`/v1/apps/${this.appId}/feature-requests/${requestId}/interested`
|
|
1625
|
+
);
|
|
1626
|
+
}
|
|
1627
|
+
/**
|
|
1628
|
+
* Get a customer's feature request activity (requests submitted + votes).
|
|
1629
|
+
* Useful for displaying on customer profile.
|
|
1630
|
+
* Requires API key (admin).
|
|
1631
|
+
*
|
|
1632
|
+
* @example
|
|
1633
|
+
* ```typescript
|
|
1634
|
+
* const activity = await stackbe.featureRequests.getCustomerActivity('cust_123');
|
|
1635
|
+
*
|
|
1636
|
+
* console.log(`Submitted ${activity.totalSubmitted} requests`);
|
|
1637
|
+
* console.log(`Voted on ${activity.totalVotes} requests`);
|
|
1638
|
+
*
|
|
1639
|
+
* // Show their most wanted features
|
|
1640
|
+
* activity.votedOn.forEach(r => {
|
|
1641
|
+
* console.log(`- ${r.title} (${r.status})`);
|
|
1642
|
+
* });
|
|
1643
|
+
* ```
|
|
1644
|
+
*/
|
|
1645
|
+
async getCustomerActivity(customerId) {
|
|
1646
|
+
return this.http.get(
|
|
1647
|
+
`/v1/apps/${this.appId}/feature-requests/customer/${customerId}/activity`
|
|
1648
|
+
);
|
|
1649
|
+
}
|
|
1650
|
+
};
|
|
1651
|
+
|
|
1336
1652
|
// src/client.ts
|
|
1337
1653
|
var DEFAULT_BASE_URL = "https://api.stackbe.io";
|
|
1338
1654
|
var DEFAULT_TIMEOUT = 3e4;
|
|
@@ -1393,6 +1709,9 @@ var StackBE = class {
|
|
|
1393
1709
|
devCallbackUrl: config.devCallbackUrl
|
|
1394
1710
|
});
|
|
1395
1711
|
this.organizations = new OrganizationsClient(this.http, config.appId);
|
|
1712
|
+
this.plans = new PlansClient(this.http);
|
|
1713
|
+
this.products = new ProductsClient(this.http, config.appId);
|
|
1714
|
+
this.featureRequests = new FeatureRequestsClient(this.http, config.appId);
|
|
1396
1715
|
}
|
|
1397
1716
|
/**
|
|
1398
1717
|
* Create a middleware for Express that tracks usage automatically.
|
|
@@ -1530,7 +1849,10 @@ var StackBE = class {
|
|
|
1530
1849
|
CheckoutClient,
|
|
1531
1850
|
CustomersClient,
|
|
1532
1851
|
EntitlementsClient,
|
|
1852
|
+
FeatureRequestsClient,
|
|
1533
1853
|
OrganizationsClient,
|
|
1854
|
+
PlansClient,
|
|
1855
|
+
ProductsClient,
|
|
1534
1856
|
StackBE,
|
|
1535
1857
|
StackBEError,
|
|
1536
1858
|
SubscriptionsClient,
|