@revstackhq/node 0.0.0-dev-20260226054346

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +136 -0
  3. package/dist/errors.d.ts +106 -0
  4. package/dist/errors.d.ts.map +1 -0
  5. package/dist/errors.js +102 -0
  6. package/dist/index.d.ts +75 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +94 -0
  9. package/dist/modules/admin/entitlements.d.ts +68 -0
  10. package/dist/modules/admin/entitlements.d.ts.map +1 -0
  11. package/dist/modules/admin/entitlements.js +87 -0
  12. package/dist/modules/admin/environments.d.ts +71 -0
  13. package/dist/modules/admin/environments.d.ts.map +1 -0
  14. package/dist/modules/admin/environments.js +84 -0
  15. package/dist/modules/admin/index.d.ts +30 -0
  16. package/dist/modules/admin/index.d.ts.map +1 -0
  17. package/dist/modules/admin/index.js +31 -0
  18. package/dist/modules/admin/integrations.d.ts +79 -0
  19. package/dist/modules/admin/integrations.d.ts.map +1 -0
  20. package/dist/modules/admin/integrations.js +97 -0
  21. package/dist/modules/admin/plans.d.ts +72 -0
  22. package/dist/modules/admin/plans.d.ts.map +1 -0
  23. package/dist/modules/admin/plans.js +93 -0
  24. package/dist/modules/admin/system.d.ts +53 -0
  25. package/dist/modules/admin/system.d.ts.map +1 -0
  26. package/dist/modules/admin/system.js +61 -0
  27. package/dist/modules/base.d.ts +43 -0
  28. package/dist/modules/base.d.ts.map +1 -0
  29. package/dist/modules/base.js +84 -0
  30. package/dist/modules/customers.d.ts +56 -0
  31. package/dist/modules/customers.d.ts.map +1 -0
  32. package/dist/modules/customers.js +72 -0
  33. package/dist/modules/entitlements.d.ts +49 -0
  34. package/dist/modules/entitlements.d.ts.map +1 -0
  35. package/dist/modules/entitlements.js +64 -0
  36. package/dist/modules/invoices.d.ts +33 -0
  37. package/dist/modules/invoices.d.ts.map +1 -0
  38. package/dist/modules/invoices.js +37 -0
  39. package/dist/modules/plans.d.ts +35 -0
  40. package/dist/modules/plans.d.ts.map +1 -0
  41. package/dist/modules/plans.js +39 -0
  42. package/dist/modules/subscriptions.d.ts +55 -0
  43. package/dist/modules/subscriptions.d.ts.map +1 -0
  44. package/dist/modules/subscriptions.js +71 -0
  45. package/dist/modules/usage.d.ts +59 -0
  46. package/dist/modules/usage.d.ts.map +1 -0
  47. package/dist/modules/usage.js +80 -0
  48. package/dist/modules/wallets.d.ts +53 -0
  49. package/dist/modules/wallets.d.ts.map +1 -0
  50. package/dist/modules/wallets.js +69 -0
  51. package/dist/modules/webhooks.d.ts +51 -0
  52. package/dist/modules/webhooks.d.ts.map +1 -0
  53. package/dist/modules/webhooks.js +90 -0
  54. package/dist/src/errors.d.ts +91 -0
  55. package/dist/src/errors.d.ts.map +1 -0
  56. package/dist/src/errors.js +101 -0
  57. package/dist/src/index.d.ts +71 -0
  58. package/dist/src/index.d.ts.map +1 -0
  59. package/dist/src/index.js +91 -0
  60. package/dist/src/modules/admin/entitlements.d.ts +73 -0
  61. package/dist/src/modules/admin/entitlements.d.ts.map +1 -0
  62. package/dist/src/modules/admin/entitlements.js +90 -0
  63. package/dist/src/modules/admin/environments.d.ts +76 -0
  64. package/dist/src/modules/admin/environments.d.ts.map +1 -0
  65. package/dist/src/modules/admin/environments.js +87 -0
  66. package/dist/src/modules/admin/index.d.ts +16 -0
  67. package/dist/src/modules/admin/index.d.ts.map +1 -0
  68. package/dist/src/modules/admin/index.js +16 -0
  69. package/dist/src/modules/admin/integrations.d.ts +84 -0
  70. package/dist/src/modules/admin/integrations.d.ts.map +1 -0
  71. package/dist/src/modules/admin/integrations.js +100 -0
  72. package/dist/src/modules/admin/plans.d.ts +77 -0
  73. package/dist/src/modules/admin/plans.d.ts.map +1 -0
  74. package/dist/src/modules/admin/plans.js +96 -0
  75. package/dist/src/modules/admin/system.d.ts +53 -0
  76. package/dist/src/modules/admin/system.d.ts.map +1 -0
  77. package/dist/src/modules/admin/system.js +61 -0
  78. package/dist/src/modules/base.d.ts +43 -0
  79. package/dist/src/modules/base.d.ts.map +1 -0
  80. package/dist/src/modules/base.js +84 -0
  81. package/dist/src/modules/customers.d.ts +61 -0
  82. package/dist/src/modules/customers.d.ts.map +1 -0
  83. package/dist/src/modules/customers.js +75 -0
  84. package/dist/src/modules/entitlements.d.ts +54 -0
  85. package/dist/src/modules/entitlements.d.ts.map +1 -0
  86. package/dist/src/modules/entitlements.js +67 -0
  87. package/dist/src/modules/invoices.d.ts +38 -0
  88. package/dist/src/modules/invoices.d.ts.map +1 -0
  89. package/dist/src/modules/invoices.js +40 -0
  90. package/dist/src/modules/plans.d.ts +40 -0
  91. package/dist/src/modules/plans.d.ts.map +1 -0
  92. package/dist/src/modules/plans.js +42 -0
  93. package/dist/src/modules/subscriptions.d.ts +60 -0
  94. package/dist/src/modules/subscriptions.d.ts.map +1 -0
  95. package/dist/src/modules/subscriptions.js +74 -0
  96. package/dist/src/modules/usage.d.ts +64 -0
  97. package/dist/src/modules/usage.d.ts.map +1 -0
  98. package/dist/src/modules/usage.js +83 -0
  99. package/dist/src/modules/wallets.d.ts +58 -0
  100. package/dist/src/modules/wallets.d.ts.map +1 -0
  101. package/dist/src/modules/wallets.js +72 -0
  102. package/dist/src/modules/webhooks.d.ts +51 -0
  103. package/dist/src/modules/webhooks.d.ts.map +1 -0
  104. package/dist/src/modules/webhooks.js +90 -0
  105. package/dist/src/types.d.ts +676 -0
  106. package/dist/src/types.d.ts.map +1 -0
  107. package/dist/src/types.js +7 -0
  108. package/dist/types.d.ts +720 -0
  109. package/dist/types.d.ts.map +1 -0
  110. package/dist/types.js +7 -0
  111. package/package.json +40 -0
@@ -0,0 +1,55 @@
1
+ import { BaseClient } from "@/modules/base";
2
+ import { Subscription, CreateSubscriptionParams, ChangePlanParams, ListSubscriptionsParams, PaginatedResponse } from "@/types";
3
+ /**
4
+ * Client for managing customer subscriptions.
5
+ * Handles creating, retrieving, canceling, and upgrading/downgrading subscriptions.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * const sub = await revstack.subscriptions.create({
10
+ * customerId: "usr_abc",
11
+ * planId: "plan_pro",
12
+ * });
13
+ * ```
14
+ */
15
+ export declare class SubscriptionsClient extends BaseClient {
16
+ /**
17
+ * List subscriptions with optional filters.
18
+ *
19
+ * @param params - Filter and pagination parameters.
20
+ * @returns A paginated list of subscriptions.
21
+ */
22
+ list(params?: ListSubscriptionsParams): Promise<PaginatedResponse<Subscription>>;
23
+ /**
24
+ * Retrieve a subscription by ID.
25
+ *
26
+ * @param subscriptionId - The subscription's unique identifier.
27
+ * @returns The subscription record.
28
+ */
29
+ get(subscriptionId: string): Promise<Subscription>;
30
+ /**
31
+ * Create a new subscription for a customer.
32
+ *
33
+ * @param params - Subscription creation parameters (customerId, planId).
34
+ * @returns The newly created subscription.
35
+ */
36
+ create(params: CreateSubscriptionParams): Promise<Subscription>;
37
+ /**
38
+ * Cancel an active subscription. The subscription will remain active until
39
+ * the end of the current billing period.
40
+ *
41
+ * @param subscriptionId - The subscription to cancel.
42
+ * @returns The updated subscription with `canceled` status.
43
+ */
44
+ cancel(subscriptionId: string): Promise<Subscription>;
45
+ /**
46
+ * Change the plan of an existing subscription (upgrade or downgrade).
47
+ * Proration is handled automatically by the billing engine.
48
+ *
49
+ * @param subscriptionId - The subscription to modify.
50
+ * @param params - The new plan and optional price to switch to.
51
+ * @returns The updated subscription.
52
+ */
53
+ changePlan(subscriptionId: string, params: ChangePlanParams): Promise<Subscription>;
54
+ }
55
+ //# sourceMappingURL=subscriptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscriptions.d.ts","sourceRoot":"","sources":["../../src/modules/subscriptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EACL,YAAY,EACZ,wBAAwB,EACxB,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;GAWG;AACH,qBAAa,mBAAoB,SAAQ,UAAU;IACjD;;;;;OAKG;IACG,IAAI,CACR,MAAM,CAAC,EAAE,uBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;IAO3C;;;;;OAKG;IACG,GAAG,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAMxD;;;;;OAKG;IACG,MAAM,CAAC,MAAM,EAAE,wBAAwB,GAAG,OAAO,CAAC,YAAY,CAAC;IAOrE;;;;;;OAMG;IACG,MAAM,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAO3D;;;;;;;OAOG;IACG,UAAU,CACd,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,YAAY,CAAC;CASzB"}
@@ -0,0 +1,71 @@
1
+ import { BaseClient } from "@/modules/base";
2
+ /**
3
+ * Client for managing customer subscriptions.
4
+ * Handles creating, retrieving, canceling, and upgrading/downgrading subscriptions.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * const sub = await revstack.subscriptions.create({
9
+ * customerId: "usr_abc",
10
+ * planId: "plan_pro",
11
+ * });
12
+ * ```
13
+ */
14
+ export class SubscriptionsClient extends BaseClient {
15
+ /**
16
+ * List subscriptions with optional filters.
17
+ *
18
+ * @param params - Filter and pagination parameters.
19
+ * @returns A paginated list of subscriptions.
20
+ */
21
+ async list(params) {
22
+ return this.request(`/subscriptions${this.buildQuery(params)}`, { method: "GET" });
23
+ }
24
+ /**
25
+ * Retrieve a subscription by ID.
26
+ *
27
+ * @param subscriptionId - The subscription's unique identifier.
28
+ * @returns The subscription record.
29
+ */
30
+ async get(subscriptionId) {
31
+ return this.request(`/subscriptions/${subscriptionId}`, {
32
+ method: "GET",
33
+ });
34
+ }
35
+ /**
36
+ * Create a new subscription for a customer.
37
+ *
38
+ * @param params - Subscription creation parameters (customerId, planId).
39
+ * @returns The newly created subscription.
40
+ */
41
+ async create(params) {
42
+ return this.request("/subscriptions", {
43
+ method: "POST",
44
+ body: JSON.stringify(params),
45
+ });
46
+ }
47
+ /**
48
+ * Cancel an active subscription. The subscription will remain active until
49
+ * the end of the current billing period.
50
+ *
51
+ * @param subscriptionId - The subscription to cancel.
52
+ * @returns The updated subscription with `canceled` status.
53
+ */
54
+ async cancel(subscriptionId) {
55
+ return this.request(`/subscriptions/${subscriptionId}/cancel`, { method: "POST" });
56
+ }
57
+ /**
58
+ * Change the plan of an existing subscription (upgrade or downgrade).
59
+ * Proration is handled automatically by the billing engine.
60
+ *
61
+ * @param subscriptionId - The subscription to modify.
62
+ * @param params - The new plan and optional price to switch to.
63
+ * @returns The updated subscription.
64
+ */
65
+ async changePlan(subscriptionId, params) {
66
+ return this.request(`/subscriptions/${subscriptionId}/change-plan`, {
67
+ method: "POST",
68
+ body: JSON.stringify(params),
69
+ });
70
+ }
71
+ }
@@ -0,0 +1,59 @@
1
+ import { BaseClient } from "@/modules/base";
2
+ import { ReportUsageParams, RevertUsageParams, UsageMeter } from "@/types";
3
+ /**
4
+ * Client for reporting and querying metered feature usage.
5
+ * Works in conjunction with {@link EntitlementsClient} — report usage after
6
+ * a successful entitlement check, and revert it if downstream operations fail.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * // Optimistic usage pattern for AI applications
11
+ * const { allowed } = await revstack.entitlements.check(userId, "ai-tokens", { amount: 500 });
12
+ * if (!allowed) throw new Error("Limit exceeded");
13
+ *
14
+ * await revstack.usage.report({ customerId: userId, featureId: "ai-tokens", amount: 500 });
15
+ * try {
16
+ * await openai.chat.completions.create({ ... });
17
+ * } catch {
18
+ * await revstack.usage.revert({ customerId: userId, featureId: "ai-tokens", amount: 500 });
19
+ * }
20
+ * ```
21
+ */
22
+ export declare class UsageClient extends BaseClient {
23
+ /**
24
+ * Report usage of a metered feature. Increments the customer's usage meter.
25
+ *
26
+ * @param params - Usage report parameters.
27
+ * @returns Confirmation of the reported usage.
28
+ */
29
+ report(params: ReportUsageParams): Promise<{
30
+ success: boolean;
31
+ }>;
32
+ /**
33
+ * Retrieve all usage meters for a customer (one per metered entitlement).
34
+ *
35
+ * @param customerId - The customer whose meters to retrieve.
36
+ * @returns Array of usage meters with current counts and reset times.
37
+ */
38
+ getMeters(customerId: string): Promise<UsageMeter[]>;
39
+ /**
40
+ * Retrieve a single usage meter for a specific customer and feature.
41
+ *
42
+ * @param customerId - The customer whose meter to retrieve.
43
+ * @param featureId - The entitlement slug or ID.
44
+ * @returns The usage meter with current count and reset time.
45
+ */
46
+ getMeter(customerId: string, featureId: string): Promise<UsageMeter>;
47
+ /**
48
+ * Revert (roll back) previously reported usage. Decrements the customer's
49
+ * usage meter. Essential for maintaining accurate billing when downstream
50
+ * operations fail after usage was already recorded.
51
+ *
52
+ * @param params - Revert parameters including reason for audit trail.
53
+ * @returns Confirmation of the reverted usage.
54
+ */
55
+ revert(params: RevertUsageParams): Promise<{
56
+ success: boolean;
57
+ }>;
58
+ }
59
+ //# sourceMappingURL=usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../src/modules/usage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE3E;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,WAAY,SAAQ,UAAU;IACzC;;;;;OAKG;IACG,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAYtE;;;;;OAKG;IACG,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAM1D;;;;;;OAMG;IACG,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAO1E;;;;;;;OAOG;IACG,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CAYvE"}
@@ -0,0 +1,80 @@
1
+ import { BaseClient } from "@/modules/base";
2
+ /**
3
+ * Client for reporting and querying metered feature usage.
4
+ * Works in conjunction with {@link EntitlementsClient} — report usage after
5
+ * a successful entitlement check, and revert it if downstream operations fail.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // Optimistic usage pattern for AI applications
10
+ * const { allowed } = await revstack.entitlements.check(userId, "ai-tokens", { amount: 500 });
11
+ * if (!allowed) throw new Error("Limit exceeded");
12
+ *
13
+ * await revstack.usage.report({ customerId: userId, featureId: "ai-tokens", amount: 500 });
14
+ * try {
15
+ * await openai.chat.completions.create({ ... });
16
+ * } catch {
17
+ * await revstack.usage.revert({ customerId: userId, featureId: "ai-tokens", amount: 500 });
18
+ * }
19
+ * ```
20
+ */
21
+ export class UsageClient extends BaseClient {
22
+ /**
23
+ * Report usage of a metered feature. Increments the customer's usage meter.
24
+ *
25
+ * @param params - Usage report parameters.
26
+ * @returns Confirmation of the reported usage.
27
+ */
28
+ async report(params) {
29
+ return this.request("/usage/report", {
30
+ method: "POST",
31
+ idempotencyKey: params.idempotencyKey,
32
+ body: JSON.stringify({
33
+ customerId: params.customerId,
34
+ featureId: params.featureId,
35
+ amount: params.amount,
36
+ }),
37
+ });
38
+ }
39
+ /**
40
+ * Retrieve all usage meters for a customer (one per metered entitlement).
41
+ *
42
+ * @param customerId - The customer whose meters to retrieve.
43
+ * @returns Array of usage meters with current counts and reset times.
44
+ */
45
+ async getMeters(customerId) {
46
+ return this.request(`/usage/meters/${customerId}`, {
47
+ method: "GET",
48
+ });
49
+ }
50
+ /**
51
+ * Retrieve a single usage meter for a specific customer and feature.
52
+ *
53
+ * @param customerId - The customer whose meter to retrieve.
54
+ * @param featureId - The entitlement slug or ID.
55
+ * @returns The usage meter with current count and reset time.
56
+ */
57
+ async getMeter(customerId, featureId) {
58
+ return this.request(`/usage/meters/${customerId}/${featureId}`, { method: "GET" });
59
+ }
60
+ /**
61
+ * Revert (roll back) previously reported usage. Decrements the customer's
62
+ * usage meter. Essential for maintaining accurate billing when downstream
63
+ * operations fail after usage was already recorded.
64
+ *
65
+ * @param params - Revert parameters including reason for audit trail.
66
+ * @returns Confirmation of the reverted usage.
67
+ */
68
+ async revert(params) {
69
+ return this.request("/usage/revert", {
70
+ method: "POST",
71
+ idempotencyKey: params.idempotencyKey,
72
+ body: JSON.stringify({
73
+ customerId: params.customerId,
74
+ featureId: params.featureId,
75
+ amount: params.amount,
76
+ reason: params.reason,
77
+ }),
78
+ });
79
+ }
80
+ }
@@ -0,0 +1,53 @@
1
+ import { BaseClient } from "@/modules/base";
2
+ import { BalanceResponse, GrantBalanceParams, RevokeBalanceParams } from "@/types";
3
+ /**
4
+ * Client for managing customer wallet balances.
5
+ * Supports granting credits (bonuses, top-ups) and revoking them (refunds, penalties).
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // Grant a welcome bonus
10
+ * await revstack.wallets.grantBalance({
11
+ * customerId: "usr_abc",
12
+ * currency: "USD",
13
+ * amount: 10.00,
14
+ * description: "Welcome bonus",
15
+ * });
16
+ *
17
+ * // Check remaining balance
18
+ * const { amount } = await revstack.wallets.getBalance("usr_abc", "USD");
19
+ * ```
20
+ */
21
+ export declare class WalletsClient extends BaseClient {
22
+ /**
23
+ * Retrieve a customer's balance for a specific currency.
24
+ *
25
+ * @param customerId - The customer whose balance to query.
26
+ * @param currency - ISO 4217 currency code (e.g. `USD`).
27
+ * @returns The balance response with currency and amount.
28
+ */
29
+ getBalance(customerId: string, currency: string): Promise<BalanceResponse>;
30
+ /**
31
+ * List all balances across all currencies for a customer.
32
+ *
33
+ * @param customerId - The customer whose balances to list.
34
+ * @returns Array of balance responses (one per currency).
35
+ */
36
+ listBalances(customerId: string): Promise<BalanceResponse[]>;
37
+ /**
38
+ * Grant (add) credit to a customer's wallet.
39
+ *
40
+ * @param params - Grant parameters including amount, currency, and description.
41
+ * @returns The updated balance after the grant.
42
+ */
43
+ grantBalance(params: GrantBalanceParams): Promise<BalanceResponse>;
44
+ /**
45
+ * Revoke (deduct) credit from a customer's wallet.
46
+ * Used for manual deductions, penalties, or credit refunds.
47
+ *
48
+ * @param params - Revoke parameters including amount, currency, and audit reason.
49
+ * @returns The updated balance after the deduction.
50
+ */
51
+ revokeBalance(params: RevokeBalanceParams): Promise<BalanceResponse>;
52
+ }
53
+ //# sourceMappingURL=wallets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallets.d.ts","sourceRoot":"","sources":["../../src/modules/wallets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,aAAc,SAAQ,UAAU;IAC3C;;;;;;OAMG;IACG,UAAU,CACd,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,eAAe,CAAC;IAM3B;;;;;OAKG;IACG,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAMlE;;;;;OAKG;IACG,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,eAAe,CAAC;IAOxE;;;;;;OAMG;IACG,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,eAAe,CAAC;CAM3E"}
@@ -0,0 +1,69 @@
1
+ import { BaseClient } from "@/modules/base";
2
+ /**
3
+ * Client for managing customer wallet balances.
4
+ * Supports granting credits (bonuses, top-ups) and revoking them (refunds, penalties).
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * // Grant a welcome bonus
9
+ * await revstack.wallets.grantBalance({
10
+ * customerId: "usr_abc",
11
+ * currency: "USD",
12
+ * amount: 10.00,
13
+ * description: "Welcome bonus",
14
+ * });
15
+ *
16
+ * // Check remaining balance
17
+ * const { amount } = await revstack.wallets.getBalance("usr_abc", "USD");
18
+ * ```
19
+ */
20
+ export class WalletsClient extends BaseClient {
21
+ /**
22
+ * Retrieve a customer's balance for a specific currency.
23
+ *
24
+ * @param customerId - The customer whose balance to query.
25
+ * @param currency - ISO 4217 currency code (e.g. `USD`).
26
+ * @returns The balance response with currency and amount.
27
+ */
28
+ async getBalance(customerId, currency) {
29
+ return this.request(`/wallets/${customerId}/${currency}`, {
30
+ method: "GET",
31
+ });
32
+ }
33
+ /**
34
+ * List all balances across all currencies for a customer.
35
+ *
36
+ * @param customerId - The customer whose balances to list.
37
+ * @returns Array of balance responses (one per currency).
38
+ */
39
+ async listBalances(customerId) {
40
+ return this.request(`/wallets/${customerId}`, {
41
+ method: "GET",
42
+ });
43
+ }
44
+ /**
45
+ * Grant (add) credit to a customer's wallet.
46
+ *
47
+ * @param params - Grant parameters including amount, currency, and description.
48
+ * @returns The updated balance after the grant.
49
+ */
50
+ async grantBalance(params) {
51
+ return this.request("/wallets/grant", {
52
+ method: "POST",
53
+ body: JSON.stringify(params),
54
+ });
55
+ }
56
+ /**
57
+ * Revoke (deduct) credit from a customer's wallet.
58
+ * Used for manual deductions, penalties, or credit refunds.
59
+ *
60
+ * @param params - Revoke parameters including amount, currency, and audit reason.
61
+ * @returns The updated balance after the deduction.
62
+ */
63
+ async revokeBalance(params) {
64
+ return this.request("/wallets/revoke", {
65
+ method: "POST",
66
+ body: JSON.stringify(params),
67
+ });
68
+ }
69
+ }
@@ -0,0 +1,51 @@
1
+ import type { WebhookEvent } from "@/types";
2
+ /**
3
+ * Client for verifying inbound webhooks from Revstack Cloud.
4
+ * Uses HMAC-SHA256 with constant-time comparison to prevent timing attacks,
5
+ * plus timestamp validation for replay protection.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // Express.js webhook handler
10
+ * app.post("/webhooks/revstack", express.raw({ type: "application/json" }), (req, res) => {
11
+ * try {
12
+ * const event = revstack.webhooks.constructEvent(
13
+ * req.body,
14
+ * req.headers["revstack-signature"] as string,
15
+ * process.env.REVSTACK_WEBHOOK_SECRET!
16
+ * );
17
+ * console.log(`Received event: ${event.type}`);
18
+ * res.sendStatus(200);
19
+ * } catch (error) {
20
+ * if (error instanceof SignatureVerificationError) {
21
+ * res.status(400).send("Invalid signature");
22
+ * }
23
+ * }
24
+ * });
25
+ * ```
26
+ */
27
+ export declare class WebhooksClient {
28
+ /**
29
+ * Verify the signature of an incoming webhook and parse the event payload.
30
+ *
31
+ * @param payload - Raw request body (`Buffer` or `string`). **Must NOT be parsed JSON.**
32
+ * @param signature - Value of the `revstack-signature` HTTP header.
33
+ * @param secret - Webhook signing secret (from the Revstack Dashboard).
34
+ * @param tolerance - Maximum age of the webhook in seconds. Defaults to `300` (5 min). Set to `0` to disable replay protection.
35
+ * @returns The verified and parsed webhook event.
36
+ *
37
+ * @throws {SignatureVerificationError} If the signature is invalid, the header is malformed, or the timestamp exceeds the tolerance.
38
+ */
39
+ constructEvent(payload: string | Buffer, signature: string, secret: string, tolerance?: number): WebhookEvent;
40
+ /**
41
+ * Parse the `revstack-signature` header into its component parts.
42
+ *
43
+ * @param header - Raw header value in the format `t=<timestamp>,v1=<signature>`.
44
+ * @returns Parsed timestamp and v1 signature.
45
+ *
46
+ * @throws {SignatureVerificationError} If the header format is invalid.
47
+ * @internal
48
+ */
49
+ private parseSignatureHeader;
50
+ }
51
+ //# sourceMappingURL=webhooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../src/modules/webhooks.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAK5C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,cAAc;IACzB;;;;;;;;;;OAUG;IACH,cAAc,CACZ,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,GAAE,MAAkC,GAC5C,YAAY;IAoCf;;;;;;;;OAQG;IACH,OAAO,CAAC,oBAAoB;CAsB7B"}
@@ -0,0 +1,90 @@
1
+ import { createHmac, timingSafeEqual } from "node:crypto";
2
+ import { SignatureVerificationError } from "@/errors";
3
+ /** Default maximum age for webhook timestamps (5 minutes). */
4
+ const DEFAULT_TOLERANCE_SECONDS = 300;
5
+ /**
6
+ * Client for verifying inbound webhooks from Revstack Cloud.
7
+ * Uses HMAC-SHA256 with constant-time comparison to prevent timing attacks,
8
+ * plus timestamp validation for replay protection.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // Express.js webhook handler
13
+ * app.post("/webhooks/revstack", express.raw({ type: "application/json" }), (req, res) => {
14
+ * try {
15
+ * const event = revstack.webhooks.constructEvent(
16
+ * req.body,
17
+ * req.headers["revstack-signature"] as string,
18
+ * process.env.REVSTACK_WEBHOOK_SECRET!
19
+ * );
20
+ * console.log(`Received event: ${event.type}`);
21
+ * res.sendStatus(200);
22
+ * } catch (error) {
23
+ * if (error instanceof SignatureVerificationError) {
24
+ * res.status(400).send("Invalid signature");
25
+ * }
26
+ * }
27
+ * });
28
+ * ```
29
+ */
30
+ export class WebhooksClient {
31
+ /**
32
+ * Verify the signature of an incoming webhook and parse the event payload.
33
+ *
34
+ * @param payload - Raw request body (`Buffer` or `string`). **Must NOT be parsed JSON.**
35
+ * @param signature - Value of the `revstack-signature` HTTP header.
36
+ * @param secret - Webhook signing secret (from the Revstack Dashboard).
37
+ * @param tolerance - Maximum age of the webhook in seconds. Defaults to `300` (5 min). Set to `0` to disable replay protection.
38
+ * @returns The verified and parsed webhook event.
39
+ *
40
+ * @throws {SignatureVerificationError} If the signature is invalid, the header is malformed, or the timestamp exceeds the tolerance.
41
+ */
42
+ constructEvent(payload, signature, secret, tolerance = DEFAULT_TOLERANCE_SECONDS) {
43
+ const rawBody = typeof payload === "string" ? payload : payload.toString("utf8");
44
+ const parts = this.parseSignatureHeader(signature);
45
+ // Compute expected HMAC-SHA256 signature
46
+ const expectedSignature = createHmac("sha256", secret)
47
+ .update(`${parts.timestamp}.${rawBody}`)
48
+ .digest("hex");
49
+ // Constant-time comparison to prevent timing attacks
50
+ const expectedBuffer = Buffer.from(expectedSignature, "utf8");
51
+ const receivedBuffer = Buffer.from(parts.v1, "utf8");
52
+ if (expectedBuffer.length !== receivedBuffer.length ||
53
+ !timingSafeEqual(expectedBuffer, receivedBuffer)) {
54
+ throw new SignatureVerificationError("Webhook signature does not match the expected signature");
55
+ }
56
+ // Replay protection: reject stale timestamps
57
+ if (tolerance > 0) {
58
+ const timestampAge = Math.floor(Date.now() / 1000) - parts.timestamp;
59
+ if (timestampAge > tolerance) {
60
+ throw new SignatureVerificationError(`Webhook timestamp too old (${timestampAge}s > ${tolerance}s tolerance)`);
61
+ }
62
+ }
63
+ return JSON.parse(rawBody);
64
+ }
65
+ /**
66
+ * Parse the `revstack-signature` header into its component parts.
67
+ *
68
+ * @param header - Raw header value in the format `t=<timestamp>,v1=<signature>`.
69
+ * @returns Parsed timestamp and v1 signature.
70
+ *
71
+ * @throws {SignatureVerificationError} If the header format is invalid.
72
+ * @internal
73
+ */
74
+ parseSignatureHeader(header) {
75
+ const pairs = header.split(",");
76
+ let timestamp = 0;
77
+ let v1 = "";
78
+ for (const pair of pairs) {
79
+ const [key, value] = pair.trim().split("=");
80
+ if (key === "t")
81
+ timestamp = parseInt(value, 10);
82
+ if (key === "v1")
83
+ v1 = value;
84
+ }
85
+ if (!timestamp || !v1) {
86
+ throw new SignatureVerificationError("Invalid signature header format. Expected: t=<timestamp>,v1=<signature>");
87
+ }
88
+ return { timestamp, v1 };
89
+ }
90
+ }
@@ -0,0 +1,91 @@
1
+ /**
2
+ * @module @revstackhq/node/errors
3
+ * @description Typed error hierarchy for the Revstack SDK. All errors thrown by the
4
+ * SDK extend {@link RevstackError}, enabling precise error handling with `instanceof`.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { RateLimitError, RevstackAPIError } from "@revstackhq/node";
9
+ *
10
+ * try {
11
+ * await revstack.entitlements.check(userId, "api-calls");
12
+ * } catch (error) {
13
+ * if (error instanceof RateLimitError) {
14
+ * console.log(`Rate limited. Retry after ${error.retryAfter}s`);
15
+ * } else if (error instanceof RevstackAPIError) {
16
+ * console.log(`API error ${error.status}: ${error.code}`);
17
+ * }
18
+ * }
19
+ * ```
20
+ */
21
+ /**
22
+ * Base class for all Revstack SDK errors.
23
+ * Use `instanceof RevstackError` to catch any SDK-originated error.
24
+ */
25
+ export declare class RevstackError extends Error {
26
+ constructor(message: string);
27
+ }
28
+ /** Shape of the JSON error body returned by the Revstack API. */
29
+ export interface APIErrorResponse {
30
+ /** Human-readable error message. */
31
+ message?: string;
32
+ /** Machine-readable error code (e.g. `INSUFFICIENT_BALANCE`). */
33
+ code?: string;
34
+ /** Unique request identifier for debugging and support tickets. */
35
+ requestId?: string;
36
+ /** Seconds to wait before retrying (for 429 responses). */
37
+ retryAfter?: number;
38
+ /** List of conflicts in case of a 409 response */
39
+ conflicts?: any[];
40
+ }
41
+ /**
42
+ * Thrown when the Revstack API returns a non-2xx HTTP response.
43
+ * Contains structured fields for programmatic error handling.
44
+ */
45
+ export declare class RevstackAPIError extends RevstackError {
46
+ /** HTTP status code (e.g. `400`, `401`, `404`, `500`). */
47
+ readonly status: number;
48
+ /** Machine-readable error code (e.g. `INSUFFICIENT_BALANCE`, `NOT_FOUND`). */
49
+ readonly code: string;
50
+ /** Unique request ID for tracing. Include this in support tickets. */
51
+ readonly requestId?: string;
52
+ constructor(message: string, status: number, code: string, requestId?: string);
53
+ }
54
+ /**
55
+ * Thrown when the API returns HTTP 429 (Too Many Requests).
56
+ * The `retryAfter` field indicates how long to wait before retrying.
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * try {
61
+ * await revstack.usage.report(params);
62
+ * } catch (error) {
63
+ * if (error instanceof RateLimitError) {
64
+ * await sleep(error.retryAfter * 1000);
65
+ * await revstack.usage.report(params); // retry
66
+ * }
67
+ * }
68
+ * ```
69
+ */
70
+ export declare class RateLimitError extends RevstackAPIError {
71
+ /** Number of seconds to wait before retrying the request. */
72
+ readonly retryAfter: number;
73
+ constructor(message: string, retryAfter: number, requestId?: string);
74
+ }
75
+ /**
76
+ * Thrown when webhook signature verification fails.
77
+ * This indicates the webhook payload was tampered with, the signing secret is wrong,
78
+ * or the webhook timestamp has expired (replay protection).
79
+ */
80
+ export declare class SignatureVerificationError extends RevstackError {
81
+ constructor(message?: string);
82
+ }
83
+ /**
84
+ * Thrown when the system sync endpoint detects a conflict (HTTP 409).
85
+ */
86
+ export declare class SyncConflictError extends RevstackAPIError {
87
+ /** The conflicts discovered during sync attempts. */
88
+ readonly conflicts: any[];
89
+ constructor(message: string, conflicts: any[], requestId?: string);
90
+ }
91
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH;;;GAGG;AACH,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAID,iEAAiE;AACjE,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC;CACnB;AAED;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,aAAa;IACjD,0DAA0D;IAC1D,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,8EAA8E;IAC9E,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,sEAAsE;IACtE,SAAgB,SAAS,CAAC,EAAE,MAAM,CAAC;gBAGjC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM;CAQrB;AAID;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,cAAe,SAAQ,gBAAgB;IAClD,6DAA6D;IAC7D,SAAgB,UAAU,EAAE,MAAM,CAAC;gBAEvB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;CAKpE;AAID;;;;GAIG;AACH,qBAAa,0BAA2B,SAAQ,aAAa;gBAC/C,OAAO,GAAE,MAAgD;CAItE;AAID;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,gBAAgB;IACrD,qDAAqD;IACrD,SAAgB,SAAS,EAAE,GAAG,EAAE,CAAC;gBAErB,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM;CAKlE"}