fresh-squeezy 1.0.20 → 1.0.47
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.
Potentially problematic release.
This version of fresh-squeezy might be problematic. Click here for more details.
- package/README.md +176 -108
- package/dist/src/cli/cli.js +1 -1
- package/dist/src/cli/cli.js.map +1 -1
- package/dist/src/cli/paths.d.ts +4 -0
- package/dist/src/cli/paths.d.ts.map +1 -0
- package/dist/src/cli/paths.js +7 -0
- package/dist/src/cli/paths.js.map +1 -0
- package/dist/src/core/cache.d.ts.map +1 -1
- package/dist/src/core/cache.js +1 -1
- package/dist/src/core/cache.js.map +1 -1
- package/dist/src/core/licenses.d.ts.map +1 -1
- package/dist/src/core/licenses.js +55 -21
- package/dist/src/core/licenses.js.map +1 -1
- package/dist/src/core/paths.d.ts +6 -0
- package/dist/src/core/paths.d.ts.map +1 -0
- package/dist/src/core/paths.js +6 -0
- package/dist/src/core/paths.js.map +1 -0
- package/dist/src/core/webhook.d.ts.map +1 -1
- package/dist/src/core/webhook.js +19 -39
- package/dist/src/core/webhook.js.map +1 -1
- package/dist/src/types/billing/billing.d.ts +4 -1
- package/dist/src/types/billing/billing.d.ts.map +1 -1
- package/dist/src/types/billing/types.d.ts +3 -9
- package/dist/src/types/billing/types.d.ts.map +1 -1
- package/dist/src/types/config/types.d.ts +2 -96
- package/dist/src/types/config/types.d.ts.map +1 -1
- package/dist/src/types/license/types.d.ts +14 -2
- package/dist/src/types/license/types.d.ts.map +1 -1
- package/dist/src/types/management/types.d.ts +4 -1
- package/dist/src/types/management/types.d.ts.map +1 -1
- package/dist/src/types/subscription/types.d.ts +2 -0
- package/dist/src/types/subscription/types.d.ts.map +1 -1
- package/dist/src/wizard/components/banner.d.ts +2 -0
- package/dist/src/wizard/components/banner.d.ts.map +1 -0
- package/dist/src/wizard/components/banner.js +6 -0
- package/dist/src/wizard/components/banner.js.map +1 -0
- package/dist/src/wizard/components/loading.d.ts +9 -0
- package/dist/src/wizard/components/loading.d.ts.map +1 -0
- package/dist/src/wizard/components/loading.js +31 -0
- package/dist/src/wizard/components/loading.js.map +1 -0
- package/dist/src/wizard/index.d.ts +2 -0
- package/dist/src/wizard/index.d.ts.map +1 -0
- package/dist/src/wizard/index.js +2 -0
- package/dist/src/wizard/index.js.map +1 -0
- package/dist/src/wizard/main.d.ts +6 -0
- package/dist/src/wizard/main.d.ts.map +1 -0
- package/dist/src/wizard/main.js +98 -0
- package/dist/src/wizard/main.js.map +1 -0
- package/dist/src/wizard/state.d.ts +15 -0
- package/dist/src/wizard/state.d.ts.map +1 -0
- package/dist/src/wizard/state.js +2 -0
- package/dist/src/wizard/state.js.map +1 -0
- package/dist/src/wizard/steps/api-key.d.ts +9 -0
- package/dist/src/wizard/steps/api-key.d.ts.map +1 -0
- package/dist/src/wizard/steps/api-key.js +91 -0
- package/dist/src/wizard/steps/api-key.js.map +1 -0
- package/dist/src/wizard/steps/checkout-optional.d.ts +2 -0
- package/dist/src/wizard/steps/checkout-optional.d.ts.map +1 -0
- package/dist/src/wizard/steps/checkout-optional.js +63 -0
- package/dist/src/wizard/steps/checkout-optional.js.map +1 -0
- package/dist/src/wizard/steps/configuration.d.ts +10 -0
- package/dist/src/wizard/steps/configuration.d.ts.map +1 -0
- package/dist/src/wizard/steps/configuration.js +33 -0
- package/dist/src/wizard/steps/configuration.js.map +1 -0
- package/dist/src/wizard/steps/generate-files.d.ts +4 -0
- package/dist/src/wizard/steps/generate-files.d.ts.map +1 -0
- package/dist/src/wizard/steps/generate-files.js +48 -0
- package/dist/src/wizard/steps/generate-files.js.map +1 -0
- package/dist/src/wizard/steps/product-selection.d.ts +7 -0
- package/dist/src/wizard/steps/product-selection.d.ts.map +1 -0
- package/dist/src/wizard/steps/product-selection.js +54 -0
- package/dist/src/wizard/steps/product-selection.js.map +1 -0
- package/dist/src/wizard/steps/store-selection.d.ts +3 -0
- package/dist/src/wizard/steps/store-selection.d.ts.map +1 -0
- package/dist/src/wizard/steps/store-selection.js +33 -0
- package/dist/src/wizard/steps/store-selection.js.map +1 -0
- package/dist/src/wizard/steps/webhook-setup.d.ts +5 -0
- package/dist/src/wizard/steps/webhook-setup.d.ts.map +1 -0
- package/dist/src/wizard/steps/webhook-setup.js +70 -0
- package/dist/src/wizard/steps/webhook-setup.js.map +1 -0
- package/dist/src/wizard/test-runner/config.d.ts +15 -0
- package/dist/src/wizard/test-runner/config.d.ts.map +1 -0
- package/dist/src/wizard/test-runner/config.js +2 -0
- package/dist/src/wizard/test-runner/config.js.map +1 -0
- package/dist/src/wizard/test-runner/logger.d.ts +3 -0
- package/dist/src/wizard/test-runner/logger.d.ts.map +1 -0
- package/dist/src/wizard/test-runner/logger.js +25 -0
- package/dist/src/wizard/test-runner/logger.js.map +1 -0
- package/dist/src/wizard/test-runner/phase-customer.d.ts +4 -0
- package/dist/src/wizard/test-runner/phase-customer.d.ts.map +1 -0
- package/dist/src/wizard/test-runner/phase-customer.js +66 -0
- package/dist/src/wizard/test-runner/phase-customer.js.map +1 -0
- package/dist/src/wizard/test-runner/phase-license.d.ts +4 -0
- package/dist/src/wizard/test-runner/phase-license.d.ts.map +1 -0
- package/dist/src/wizard/test-runner/phase-license.js +53 -0
- package/dist/src/wizard/test-runner/phase-license.js.map +1 -0
- package/dist/src/wizard/test-runner/phase-order.d.ts +4 -0
- package/dist/src/wizard/test-runner/phase-order.d.ts.map +1 -0
- package/dist/src/wizard/test-runner/phase-order.js +24 -0
- package/dist/src/wizard/test-runner/phase-order.js.map +1 -0
- package/dist/src/wizard/test-runner/phase-resolution.d.ts +4 -0
- package/dist/src/wizard/test-runner/phase-resolution.d.ts.map +1 -0
- package/dist/src/wizard/test-runner/phase-resolution.js +24 -0
- package/dist/src/wizard/test-runner/phase-resolution.js.map +1 -0
- package/dist/src/wizard/test-runner/phase-setup.d.ts +4 -0
- package/dist/src/wizard/test-runner/phase-setup.d.ts.map +1 -0
- package/dist/src/wizard/test-runner/phase-setup.js +61 -0
- package/dist/src/wizard/test-runner/phase-setup.js.map +1 -0
- package/dist/src/wizard/test-runner/phase-subscription.d.ts +4 -0
- package/dist/src/wizard/test-runner/phase-subscription.d.ts.map +1 -0
- package/dist/src/wizard/test-runner/phase-subscription.js +31 -0
- package/dist/src/wizard/test-runner/phase-subscription.js.map +1 -0
- package/dist/src/wizard/test-runner/phases.d.ts +4 -0
- package/dist/src/wizard/test-runner/phases.d.ts.map +1 -0
- package/dist/src/wizard/test-runner/phases.js +35 -0
- package/dist/src/wizard/test-runner/phases.js.map +1 -0
- package/dist/src/wizard/utils/config-content.d.ts +3 -0
- package/dist/src/wizard/utils/config-content.d.ts.map +1 -0
- package/dist/src/wizard/utils/config-content.js +44 -0
- package/dist/src/wizard/utils/config-content.js.map +1 -0
- package/dist/src/wizard/utils/example-content.d.ts +3 -0
- package/dist/src/wizard/utils/example-content.d.ts.map +1 -0
- package/dist/src/wizard/utils/example-content.js +53 -0
- package/dist/src/wizard/utils/example-content.js.map +1 -0
- package/dist/src/wizard/utils/validation.d.ts +3 -0
- package/dist/src/wizard/utils/validation.d.ts.map +1 -0
- package/dist/src/wizard/utils/validation.js +37 -0
- package/dist/src/wizard/utils/validation.js.map +1 -0
- package/package.json +22 -23
- package/dist/.cursor/skills/wizard/utils/validation.d.ts +0 -3
- package/dist/.cursor/skills/wizard/utils/validation.d.ts.map +0 -1
- package/dist/.cursor/skills/wizard/utils/validation.js +0 -113
- package/dist/.cursor/skills/wizard/utils/validation.js.map +0 -1
- package/dist/billing-config.d.ts +0 -3
- package/dist/billing-config.d.ts.map +0 -1
- package/dist/billing-config.js +0 -37
- package/dist/billing-config.js.map +0 -1
- package/dist/bootstrap.d.ts +0 -8
- package/dist/bootstrap.d.ts.map +0 -1
- package/dist/bootstrap.js +0 -42
- package/dist/bootstrap.js.map +0 -1
- package/dist/cache.d.ts +0 -5
- package/dist/cache.d.ts.map +0 -1
- package/dist/cache.js +0 -27
- package/dist/cache.js.map +0 -1
- package/dist/checkout.d.ts +0 -3
- package/dist/checkout.d.ts.map +0 -1
- package/dist/checkout.js +0 -42
- package/dist/checkout.js.map +0 -1
- package/dist/cli-validate.d.ts +0 -2
- package/dist/cli-validate.d.ts.map +0 -1
- package/dist/cli-validate.js +0 -206
- package/dist/cli-validate.js.map +0 -1
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -40
- package/dist/cli.js.map +0 -1
- package/dist/createBilling.d.ts +0 -3
- package/dist/createBilling.d.ts.map +0 -1
- package/dist/createBilling.js +0 -82
- package/dist/createBilling.js.map +0 -1
- package/dist/customers.d.ts +0 -3
- package/dist/customers.d.ts.map +0 -1
- package/dist/customers.js +0 -57
- package/dist/customers.js.map +0 -1
- package/dist/dedup.d.ts +0 -60
- package/dist/dedup.d.ts.map +0 -1
- package/dist/dedup.js +0 -74
- package/dist/dedup.js.map +0 -1
- package/dist/express.d.ts +0 -13
- package/dist/express.d.ts.map +0 -1
- package/dist/express.js +0 -70
- package/dist/express.js.map +0 -1
- package/dist/health.d.ts +0 -3
- package/dist/health.d.ts.map +0 -1
- package/dist/health.js +0 -38
- package/dist/health.js.map +0 -1
- package/dist/index.d.ts +0 -9
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -9
- package/dist/index.js.map +0 -1
- package/dist/licenses.d.ts +0 -3
- package/dist/licenses.d.ts.map +0 -1
- package/dist/licenses.js +0 -70
- package/dist/licenses.js.map +0 -1
- package/dist/logger.d.ts +0 -4
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -75
- package/dist/logger.js.map +0 -1
- package/dist/plans.d.ts +0 -5
- package/dist/plans.d.ts.map +0 -1
- package/dist/plans.js +0 -72
- package/dist/plans.js.map +0 -1
- package/dist/portal.d.ts +0 -2
- package/dist/portal.d.ts.map +0 -1
- package/dist/portal.js +0 -15
- package/dist/portal.js.map +0 -1
- package/dist/retry.d.ts +0 -2
- package/dist/retry.d.ts.map +0 -1
- package/dist/retry.js +0 -35
- package/dist/retry.js.map +0 -1
- package/dist/src/billing-config.d.ts +0 -3
- package/dist/src/billing-config.d.ts.map +0 -1
- package/dist/src/billing-config.js +0 -34
- package/dist/src/billing-config.js.map +0 -1
- package/dist/src/wizard.d.ts +0 -22
- package/dist/src/wizard.d.ts.map +0 -1
- package/dist/src/wizard.js +0 -628
- package/dist/src/wizard.js.map +0 -1
- package/dist/subscriptions.d.ts +0 -3
- package/dist/subscriptions.d.ts.map +0 -1
- package/dist/subscriptions.js +0 -46
- package/dist/subscriptions.js.map +0 -1
- package/dist/types.d.ts +0 -286
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/webhook.d.ts +0 -7
- package/dist/webhook.d.ts.map +0 -1
- package/dist/webhook.js +0 -227
- package/dist/webhook.js.map +0 -1
- package/dist/webhooks.d.ts +0 -3
- package/dist/webhooks.d.ts.map +0 -1
- package/dist/webhooks.js +0 -28
- package/dist/webhooks.js.map +0 -1
- package/dist/wizard.d.ts +0 -22
- package/dist/wizard.d.ts.map +0 -1
- package/dist/wizard.js +0 -615
- package/dist/wizard.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,114 +1,182 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
Successfully completed the refactoring of the `src/wizard.ts` file and reorganized the project structure to enable better modularity and maintainability.
|
|
6
|
-
|
|
7
|
-
## Changes Made
|
|
8
|
-
|
|
9
|
-
### 1. Created Skills Folder Structure
|
|
10
|
-
|
|
11
|
-
- **Root Skills Directory**: `/skills/`
|
|
12
|
-
- **Wizard Skill**: `/skills/wizard/` - Interactive setup wizard functionality
|
|
13
|
-
- `components/` - Reusable UI components (banner, loading animations)
|
|
14
|
-
- `steps/` - Individual wizard steps (API key, store selection, etc.)
|
|
15
|
-
- `utils/` - Wizard-specific utilities (validation, file generation)
|
|
16
|
-
- `types.ts` - Wizard-specific type definitions
|
|
17
|
-
- **CLI Skill**: `/skills/cli/` - Command-line interface functionality
|
|
18
|
-
- `commands/` - Individual CLI command implementations
|
|
19
|
-
- `utils/` - CLI utilities and helpers
|
|
20
|
-
- **Validation Skill**: `/skills/validation/` - Testing and validation functionality
|
|
21
|
-
- `tests/` - Validation test implementations
|
|
22
|
-
- `utils/` - Validation utilities and helpers
|
|
23
|
-
|
|
24
|
-
### 2. Reorganized Source Code Structure
|
|
25
|
-
|
|
26
|
-
- **Core Directory**: `/src/core/` - Core billing functionality
|
|
27
|
-
- Moved all core billing logic from root src/ directory
|
|
28
|
-
- Updated all import paths to use new structure
|
|
29
|
-
- **CLI Directory**: `/src/cli/` - CLI-related files
|
|
30
|
-
- `cli.ts` - Main CLI entry point
|
|
31
|
-
- `cli-validate.ts` - Validation functionality
|
|
32
|
-
- **Types Directory**: `/src/types/` - Type definitions
|
|
33
|
-
- `types.ts` - Main types export
|
|
34
|
-
- Existing type subdirectories preserved
|
|
35
|
-
- **Utils Directory**: `/src/utils/` - Utility files (created but empty for now)
|
|
36
|
-
|
|
37
|
-
### 3. Split Wizard.ts into Modular Components
|
|
38
|
-
|
|
39
|
-
The original monolithic `wizard.ts` (~1000 lines) was split into:
|
|
40
|
-
|
|
41
|
-
- **Main Wizard Class**: `/skills/wizard/main.ts`
|
|
42
|
-
- **Type Definitions**: `/skills/wizard/types.ts`
|
|
43
|
-
- **UI Components**:
|
|
44
|
-
- `/skills/wizard/components/banner.ts`
|
|
45
|
-
- `/skills/wizard/components/loading.ts`
|
|
46
|
-
- **Wizard Steps**:
|
|
47
|
-
- `/skills/wizard/steps/api-key.ts`
|
|
48
|
-
- `/skills/wizard/steps/store-selection.ts`
|
|
49
|
-
- `/skills/wizard/steps/product-selection.ts`
|
|
50
|
-
- `/skills/wizard/steps/webhook-setup.ts`
|
|
51
|
-
- `/skills/wizard/steps/configuration.ts`
|
|
52
|
-
- `/skills/wizard/steps/generate-files.ts`
|
|
53
|
-
- **Utilities**:
|
|
54
|
-
- `/skills/wizard/utils/file-generation.ts`
|
|
55
|
-
- `/skills/wizard/utils/validation.ts`
|
|
56
|
-
- `/skills/wizard/utils/real-cycle.ts`
|
|
57
|
-
|
|
58
|
-
### 4. Updated Import Paths
|
|
59
|
-
|
|
60
|
-
- Updated all import statements throughout the project to use the new directory structure
|
|
61
|
-
- Fixed TypeScript compilation issues
|
|
62
|
-
- Ensured all modules can find their dependencies
|
|
63
|
-
|
|
64
|
-
### 5. Created Comprehensive Documentation
|
|
65
|
-
|
|
66
|
-
- **Root README**: This summary document
|
|
67
|
-
- **Skills README**: Architecture overview and usage instructions
|
|
68
|
-
- **Wizard README**: Detailed wizard functionality documentation
|
|
69
|
-
- **CLI README**: CLI command documentation
|
|
70
|
-
- **Validation README**: Testing and validation documentation
|
|
71
|
-
|
|
72
|
-
## Benefits Achieved
|
|
73
|
-
|
|
74
|
-
1. **Improved Modularity**: Each wizard step is now a separate, testable module
|
|
75
|
-
2. **Better Maintainability**: Clear separation of concerns makes code easier to understand and modify
|
|
76
|
-
3. **Enhanced Reusability**: Components can be reused across different parts of the system
|
|
77
|
-
4. **Cleaner Architecture**: Logical grouping of related functionality
|
|
78
|
-
5. **Easier Testing**: Individual modules can be tested independently
|
|
79
|
-
6. **Better Developer Experience**: Clear documentation and organized structure
|
|
80
|
-
|
|
81
|
-
## Project Structure
|
|
1
|
+
# fresh-squeezy
|
|
82
2
|
|
|
3
|
+
> The missing billing layer for Lemon Squeezy — auto-discover, checkout, webhooks, subscriptions, and licenses in one function call.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/fresh-squeezy)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install fresh-squeezy
|
|
12
|
+
# peer deps
|
|
13
|
+
npm install @lemonsqueezy/lemonsqueezy.js
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import { createBilling } from "fresh-squeezy";
|
|
20
|
+
|
|
21
|
+
const billing = await createBilling({
|
|
22
|
+
apiKey: process.env.LS_API_KEY!,
|
|
23
|
+
webhookSecret: process.env.LS_WEBHOOK_SECRET!,
|
|
24
|
+
callbacks: {
|
|
25
|
+
onPurchase: async ({ userId, email, orderId, productName, price }) => {
|
|
26
|
+
await db.grantAccess(userId);
|
|
27
|
+
},
|
|
28
|
+
onSubscription: async (event, method) => {
|
|
29
|
+
if (method === "cancelled") await db.revokeAccess(event.userId);
|
|
30
|
+
},
|
|
31
|
+
onSubscriptionPayment: async (event, method) => {
|
|
32
|
+
if (method === "success") await db.extendAccess(event.userId);
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Create a checkout URL
|
|
38
|
+
const url = await billing.createCheckout({
|
|
39
|
+
variantId: "123456",
|
|
40
|
+
email: "user@example.com",
|
|
41
|
+
userId: "user_abc",
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Verify + handle a webhook (Express example)
|
|
45
|
+
app.post("/webhook", express.raw({ type: "application/json" }), async (req, res) => {
|
|
46
|
+
const sig = req.headers["x-signature"] as string;
|
|
47
|
+
if (!billing.verifyWebhook(req.body.toString(), sig)) return res.sendStatus(401);
|
|
48
|
+
await billing.handleWebhook(JSON.parse(req.body.toString()));
|
|
49
|
+
res.json({ ok: true });
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Setup Wizard
|
|
54
|
+
|
|
55
|
+
Run the interactive wizard to generate a `billing-config.ts` for your project:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pnpm wizard
|
|
59
|
+
# or after installing the package globally:
|
|
60
|
+
npx fresh-squeezy-billing wizard
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The wizard:
|
|
64
|
+
- Validates your API key against Lemon Squeezy
|
|
65
|
+
- Lets you select stores, products, and webhook events
|
|
66
|
+
- Generates `billing-config.ts` and `example.ts` in your project root
|
|
67
|
+
- Optionally runs all 6 API lifecycle test phases (setup → customer → order → subscription → license → cleanup)
|
|
68
|
+
|
|
69
|
+
## Configuration
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
interface BillingConfig {
|
|
73
|
+
apiKey: string;
|
|
74
|
+
storeId?: string;
|
|
75
|
+
webhookSecret?: string;
|
|
76
|
+
cachePath?: string; // default: "./billing-cache.json"
|
|
77
|
+
cacheTtlMs?: number; // default: 3 600 000 (1 hour)
|
|
78
|
+
checkoutExpiresInMs?: number | null;
|
|
79
|
+
logger?: { filePath: string } | { custom: BillingLogger };
|
|
80
|
+
callbacks: BillingCallbacks;
|
|
81
|
+
dedup?: DedupConfig;
|
|
82
|
+
}
|
|
83
83
|
```
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
84
|
+
|
|
85
|
+
## Callbacks
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
interface BillingCallbacks {
|
|
89
|
+
onPurchase: (event: PurchaseEvent) => Promise<void>;
|
|
90
|
+
onRefund?: (event: RefundEvent) => Promise<void>;
|
|
91
|
+
onSubscription?: (event: AnySubscriptionEvent, method: SubscriptionMethod) => Promise<void>;
|
|
92
|
+
// method: 'created' | 'updated' | 'cancelled' | 'expired' | 'paused' | 'resumed'
|
|
93
|
+
onSubscriptionPayment?: (event: SubscriptionPaymentSuccessEvent | SubscriptionPaymentRecoveredEvent, method: 'success' | 'recovered') => Promise<void>;
|
|
94
|
+
onPaymentFailed?: (event: PaymentFailedEvent) => Promise<void>;
|
|
95
|
+
onLicenseKey?: (method: 'created' | 'updated', event: LicenseKeyEvent) => Promise<void>;
|
|
96
|
+
onWebhook?: (eventType: string, event: unknown) => Promise<void>;
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Billing API
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
billing.stores // StoreInfo[]
|
|
104
|
+
billing.plans // Plan[] (auto-refreshed from cache)
|
|
105
|
+
billing.createCheckout(params) // Promise<string> — checkout URL
|
|
106
|
+
billing.verifyWebhook(rawBody, sig) // boolean
|
|
107
|
+
billing.handleWebhook(payload) // Promise<void>
|
|
108
|
+
billing.refreshPlans() // Promise<void>
|
|
109
|
+
billing.getCustomerPortal(customerId) // Promise<string> — portal URL
|
|
110
|
+
billing.getExpressRouter(options) // Express Router
|
|
111
|
+
|
|
112
|
+
// Subscriptions
|
|
113
|
+
billing.pauseSubscription(id, reason?)
|
|
114
|
+
billing.resumeSubscription(id)
|
|
115
|
+
billing.cancelSubscription(id, immediately?)
|
|
116
|
+
billing.changeSubscriptionVariant(id, variantId)
|
|
117
|
+
billing.resumeCancelledSubscription(id)
|
|
118
|
+
|
|
119
|
+
// Licenses
|
|
120
|
+
billing.validateLicense(key) // Promise<{ valid: boolean; details? }>
|
|
121
|
+
billing.getLicenseDetails(key) // Promise<LicenseKeyEvent | null>
|
|
122
|
+
billing.activateLicense(key, instanceName) // Promise<{ activated: boolean; instanceId? }>
|
|
123
|
+
billing.deactivateLicense(key, instanceId) // Promise<boolean>
|
|
124
|
+
|
|
125
|
+
// Customers
|
|
126
|
+
billing.getCustomerByEmail(email)
|
|
127
|
+
billing.getSubscriptionsForUser(userId)
|
|
128
|
+
|
|
129
|
+
// Webhooks
|
|
130
|
+
billing.createWebhook(url, events, secret?)
|
|
131
|
+
billing.deleteWebhook(webhookId)
|
|
132
|
+
|
|
133
|
+
// Other
|
|
134
|
+
billing.healthCheck()
|
|
135
|
+
billing.dedupBackend
|
|
104
136
|
```
|
|
105
137
|
|
|
106
|
-
##
|
|
138
|
+
## Express Router
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
import express from "express";
|
|
142
|
+
|
|
143
|
+
const app = express();
|
|
144
|
+
app.use("/billing", billing.getExpressRouter({
|
|
145
|
+
webhookPath: "/webhook",
|
|
146
|
+
checkoutPath: "/checkout",
|
|
147
|
+
}));
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Deduplication
|
|
151
|
+
|
|
152
|
+
By default, webhook deduplication is in-memory and process-local. Swap in Redis or a database backend:
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
import { RedisDedupBackend } from "fresh-squeezy";
|
|
156
|
+
|
|
157
|
+
const billing = await createBilling({
|
|
158
|
+
// ...
|
|
159
|
+
dedup: {
|
|
160
|
+
backend: new RedisDedupBackend(redisClient),
|
|
161
|
+
ttlMs: 86_400_000,
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## CLI
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
npx fresh-squeezy-billing wizard # interactive setup
|
|
170
|
+
npx fresh-squeezy-billing validate # run validation suite
|
|
171
|
+
npx fresh-squeezy-billing help
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Requirements
|
|
175
|
+
|
|
176
|
+
- Node.js ≥ 20
|
|
177
|
+
- `@lemonsqueezy/lemonsqueezy.js` ≥ 3.2.0
|
|
178
|
+
- Express ≥ 4.18 (optional, only if using `getExpressRouter`)
|
|
107
179
|
|
|
108
|
-
|
|
109
|
-
- ✅ Build process completes successfully
|
|
110
|
-
- ✅ All import paths updated and working
|
|
111
|
-
- ✅ Modular structure implemented
|
|
112
|
-
- ✅ Documentation created
|
|
180
|
+
## License
|
|
113
181
|
|
|
114
|
-
|
|
182
|
+
MIT
|
package/dist/src/cli/cli.js
CHANGED
package/dist/src/cli/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/cli/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/cli/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIhD,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;CAab,CAAC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,OAAO,GAAa,IAAI,CAAC,CAAC,CAAa,IAAI,MAAM,CAAC;IAExD,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,QAAQ;YACX,MAAM,SAAS,EAAE,CAAC;YAClB,MAAM;QACR,KAAK,UAAU;YACb,MAAM,WAAW,EAAE,CAAC;YACpB,MAAM;QACR,KAAK,MAAM,CAAC;QACZ;YACE,SAAS,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAY,EAAE,EAAE;IAC5B,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/cli/paths.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,mBAAmB,QAAkD,CAAC;AACnF,eAAO,MAAM,iBAAiB,QAA2C,CAAC;AAC1E,eAAO,MAAM,wBAAwB,QAA8C,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { tmpdir } from "node:os";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
const PREFIX = "lemonsqueezy-billing";
|
|
4
|
+
export const VALIDATE_CACHE_PATH = join(tmpdir(), `${PREFIX}-validate-cache.json`);
|
|
5
|
+
export const VALIDATE_LOG_PATH = join(tmpdir(), `${PREFIX}-validate.log`);
|
|
6
|
+
export const VALIDATE_LIVE_CACHE_PATH = join(tmpdir(), `${PREFIX}-live-cache.json`);
|
|
7
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/cli/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,MAAM,GAAG,sBAAsB,CAAC;AAEtC,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,MAAM,sBAAsB,CAAC,CAAC;AACnF,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,MAAM,eAAe,CAAC,CAAC;AAC1E,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,MAAM,kBAAkB,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/core/cache.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/core/cache.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAItD,wBAAgB,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAQtE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAIxE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAKrF"}
|
package/dist/src/core/cache.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
2
2
|
import { dirname } from "node:path";
|
|
3
|
-
|
|
3
|
+
import { DEFAULT_CACHE_PATH } from "./paths.js";
|
|
4
4
|
const DEFAULT_TTL_MS = 3_600_000;
|
|
5
5
|
export function readCache(cachePath) {
|
|
6
6
|
const path = cachePath ?? DEFAULT_CACHE_PATH;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/core/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/core/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,MAAM,cAAc,GAAG,SAAS,CAAC;AAEjC,MAAM,UAAU,SAAS,CAAC,SAAkB;IAC1C,MAAM,IAAI,GAAG,SAAS,IAAI,kBAAkB,CAAC;IAC7C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAiB,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAmB,EAAE,SAAkB;IAChE,MAAM,IAAI,GAAG,SAAS,IAAI,kBAAkB,CAAC;IAC7C,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAA+B,EAAE,KAAc;IAC1E,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,GAAG,GAAG,KAAK,IAAI,cAAc,CAAC;IACpC,MAAM,WAAW,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC;IAC1D,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,GAAG,GAAG,CAAC;AACxC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"licenses.d.ts","sourceRoot":"","sources":["../../../src/core/licenses.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"licenses.d.ts","sourceRoot":"","sources":["../../../src/core/licenses.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,oBAAoB,EAKrB,MAAM,mBAAmB,CAAC;AAuB3B,wBAAgB,0BAA0B,IAAI,oBAAoB,CAiHjE"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getLicenseKey } from "@lemonsqueezy/lemonsqueezy.js";
|
|
2
2
|
import { withRetry } from "./retry.js";
|
|
3
|
+
const LS_LICENSE_API_BASE = "https://api.lemonsqueezy.com/v1/licenses";
|
|
3
4
|
function mapAttributesToLicenseKeyEvent(attrs, licenseKeyId, key) {
|
|
4
5
|
return {
|
|
5
6
|
userId: attrs.user_email,
|
|
@@ -26,7 +27,7 @@ export function createLicenseKeyManagement() {
|
|
|
26
27
|
const attrs = response.data.data.attributes;
|
|
27
28
|
const details = mapAttributesToLicenseKeyEvent(attrs, response.data.data.id, attrs.key);
|
|
28
29
|
const valid = details.status === "active" &&
|
|
29
|
-
details.activationCount
|
|
30
|
+
(details.maxActivations === null || details.activationCount <= details.maxActivations);
|
|
30
31
|
return { valid, details };
|
|
31
32
|
}
|
|
32
33
|
catch {
|
|
@@ -34,31 +35,64 @@ export function createLicenseKeyManagement() {
|
|
|
34
35
|
}
|
|
35
36
|
};
|
|
36
37
|
const getLicenseDetails = async (key) => {
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
try {
|
|
39
|
+
const response = await withRetry(() => getLicenseKey(key), "getLicenseKey");
|
|
40
|
+
if (response.error || !response.data?.data) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const attrs = response.data.data.attributes;
|
|
44
|
+
return mapAttributesToLicenseKeyEvent(attrs, response.data.data.id, attrs.key);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
39
47
|
return null;
|
|
40
48
|
}
|
|
41
|
-
const attrs = response.data.data.attributes;
|
|
42
|
-
return mapAttributesToLicenseKeyEvent(attrs, response.data.data.id, attrs.key);
|
|
43
49
|
};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
// Note: License API is a direct HTTP call; retries are intentionally omitted (callers should retry at the application level)
|
|
51
|
+
const activateLicense = async (key, instanceName) => {
|
|
52
|
+
const resolvedName = instanceName ?? "default";
|
|
53
|
+
const body = new URLSearchParams({ license_key: key, instance_name: resolvedName });
|
|
54
|
+
try {
|
|
55
|
+
const response = await fetch(`${LS_LICENSE_API_BASE}/activate`, {
|
|
56
|
+
method: "POST",
|
|
57
|
+
headers: {
|
|
58
|
+
Accept: "application/json",
|
|
59
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
60
|
+
},
|
|
61
|
+
body: body.toString(),
|
|
62
|
+
});
|
|
63
|
+
if (!response.ok) {
|
|
64
|
+
return { activated: false };
|
|
65
|
+
}
|
|
66
|
+
const data = (await response.json());
|
|
67
|
+
return { activated: data.activated === true, instanceId: data.instance?.id };
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return { activated: false };
|
|
51
71
|
}
|
|
52
|
-
// Here you would typically:
|
|
53
|
-
// 1. Check if this instanceId is already activated
|
|
54
|
-
// 2. Increment activation count in your database
|
|
55
|
-
// 3. Return success/failure based on your business logic
|
|
56
|
-
return true; // Placeholder - implement based on your needs
|
|
57
72
|
};
|
|
58
|
-
const deactivateLicense = async (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
73
|
+
const deactivateLicense = async (key, instanceId) => {
|
|
74
|
+
if (!instanceId) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
const body = new URLSearchParams({ license_key: key, instance_id: instanceId });
|
|
78
|
+
try {
|
|
79
|
+
const response = await fetch(`${LS_LICENSE_API_BASE}/deactivate`, {
|
|
80
|
+
method: "POST",
|
|
81
|
+
headers: {
|
|
82
|
+
Accept: "application/json",
|
|
83
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
84
|
+
},
|
|
85
|
+
body: body.toString(),
|
|
86
|
+
});
|
|
87
|
+
if (!response.ok) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
const data = (await response.json());
|
|
91
|
+
return data.deactivated === true;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
62
96
|
};
|
|
63
97
|
return {
|
|
64
98
|
validateLicense,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"licenses.js","sourceRoot":"","sources":["../../../src/core/licenses.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"licenses.js","sourceRoot":"","sources":["../../../src/core/licenses.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const BILLING_DIR = ".billing";
|
|
2
|
+
export declare const DEFAULT_CACHE_PATH = ".billing/cache.json";
|
|
3
|
+
export declare const DEFAULT_LOG_PATH = ".billing/billing.log";
|
|
4
|
+
export declare const WIZARD_CONFIG_FILE = ".billing/billing-config.ts";
|
|
5
|
+
export declare const WIZARD_EXAMPLE_FILE = ".billing/example.ts";
|
|
6
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/core/paths.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,aAAa,CAAC;AAEtC,eAAO,MAAM,kBAAkB,wBAA8B,CAAC;AAC9D,eAAO,MAAM,gBAAgB,yBAA+B,CAAC;AAE7D,eAAO,MAAM,kBAAkB,+BAAqC,CAAC;AACrE,eAAO,MAAM,mBAAmB,wBAA8B,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const BILLING_DIR = ".billing";
|
|
2
|
+
export const DEFAULT_CACHE_PATH = `${BILLING_DIR}/cache.json`;
|
|
3
|
+
export const DEFAULT_LOG_PATH = `${BILLING_DIR}/billing.log`;
|
|
4
|
+
export const WIZARD_CONFIG_FILE = `${BILLING_DIR}/billing-config.ts`;
|
|
5
|
+
export const WIZARD_EXAMPLE_FILE = `${BILLING_DIR}/example.ts`;
|
|
6
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/core/paths.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAC;AAEtC,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,WAAW,aAAa,CAAC;AAC9D,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,WAAW,cAAc,CAAC;AAE7D,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,WAAW,oBAAoB,CAAC;AACrE,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,WAAW,aAAa,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../../src/core/webhook.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,
|
|
1
|
+
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../../src/core/webhook.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EAef,MAAM,mBAAmB,CAAC;AAI3B,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,IAC1C,SAAS,MAAM,EAAE,WAAW,MAAM,KAAG,OAAO,CAQrD;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,gBAAgB,EAAE,UAAU,CAAC,EAAE,MAAM,IAyBrE,SAAS,cAAc,KAAG,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAyKjG"}
|
package/dist/src/core/webhook.js
CHANGED
|
@@ -66,37 +66,17 @@ export function createWebhookHandler(callbacks, dedupTtlMs) {
|
|
|
66
66
|
await dispatchWebhook(eventName, event);
|
|
67
67
|
return { dispatched: callbacks.onRefund ? "onRefund" : null, skipped: false };
|
|
68
68
|
}
|
|
69
|
-
case "subscription_created":
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
await callbacks.onSubscriptionCreated(event);
|
|
73
|
-
}
|
|
74
|
-
await dispatchWebhook(eventName, event);
|
|
75
|
-
return { dispatched: callbacks.onSubscriptionCreated ? "onSubscriptionCreated" : null, skipped: false };
|
|
76
|
-
}
|
|
77
|
-
case "subscription_updated": {
|
|
78
|
-
const event = buildSubscriptionEvent(userId, email, dataId, attrs);
|
|
79
|
-
if (callbacks.onSubscriptionUpdated) {
|
|
80
|
-
await callbacks.onSubscriptionUpdated(event);
|
|
81
|
-
}
|
|
82
|
-
await dispatchWebhook(eventName, event);
|
|
83
|
-
return { dispatched: callbacks.onSubscriptionUpdated ? "onSubscriptionUpdated" : null, skipped: false };
|
|
84
|
-
}
|
|
85
|
-
case "subscription_cancelled": {
|
|
86
|
-
const event = buildSubscriptionEvent(userId, email, dataId, attrs);
|
|
87
|
-
if (callbacks.onSubscriptionCancelled) {
|
|
88
|
-
await callbacks.onSubscriptionCancelled(event);
|
|
89
|
-
}
|
|
90
|
-
await dispatchWebhook(eventName, event);
|
|
91
|
-
return { dispatched: callbacks.onSubscriptionCancelled ? "onSubscriptionCancelled" : null, skipped: false };
|
|
92
|
-
}
|
|
69
|
+
case "subscription_created":
|
|
70
|
+
case "subscription_updated":
|
|
71
|
+
case "subscription_cancelled":
|
|
93
72
|
case "subscription_expired": {
|
|
73
|
+
const method = eventName.replace("subscription_", "");
|
|
94
74
|
const event = buildSubscriptionEvent(userId, email, dataId, attrs);
|
|
95
|
-
if (callbacks.
|
|
96
|
-
await callbacks.
|
|
75
|
+
if (callbacks.onSubscription) {
|
|
76
|
+
await callbacks.onSubscription(event, method);
|
|
97
77
|
}
|
|
98
78
|
await dispatchWebhook(eventName, event);
|
|
99
|
-
return { dispatched: callbacks.
|
|
79
|
+
return { dispatched: callbacks.onSubscription ? `onSubscription:${method}` : null, skipped: false };
|
|
100
80
|
}
|
|
101
81
|
case "subscription_payment_failed": {
|
|
102
82
|
const event = {
|
|
@@ -120,11 +100,11 @@ export function createWebhookHandler(callbacks, dedupTtlMs) {
|
|
|
120
100
|
customerId: String(attrs.customer_id ?? ""),
|
|
121
101
|
reason: String(attrs.pause_reason ?? ""),
|
|
122
102
|
};
|
|
123
|
-
if (callbacks.
|
|
124
|
-
await callbacks.
|
|
103
|
+
if (callbacks.onSubscription) {
|
|
104
|
+
await callbacks.onSubscription(event, "paused");
|
|
125
105
|
}
|
|
126
106
|
await dispatchWebhook(eventName, event);
|
|
127
|
-
return { dispatched: callbacks.
|
|
107
|
+
return { dispatched: callbacks.onSubscription ? "onSubscription:paused" : null, skipped: false };
|
|
128
108
|
}
|
|
129
109
|
case "subscription_resumed":
|
|
130
110
|
case "subscription_unpaused": {
|
|
@@ -134,11 +114,11 @@ export function createWebhookHandler(callbacks, dedupTtlMs) {
|
|
|
134
114
|
subscriptionId: dataId,
|
|
135
115
|
customerId: String(attrs.customer_id ?? ""),
|
|
136
116
|
};
|
|
137
|
-
if (callbacks.
|
|
138
|
-
await callbacks.
|
|
117
|
+
if (callbacks.onSubscription) {
|
|
118
|
+
await callbacks.onSubscription(event, "resumed");
|
|
139
119
|
}
|
|
140
120
|
await dispatchWebhook(eventName, event);
|
|
141
|
-
return { dispatched: callbacks.
|
|
121
|
+
return { dispatched: callbacks.onSubscription ? "onSubscription:resumed" : null, skipped: false };
|
|
142
122
|
}
|
|
143
123
|
case "subscription_payment_success": {
|
|
144
124
|
const event = {
|
|
@@ -149,11 +129,11 @@ export function createWebhookHandler(callbacks, dedupTtlMs) {
|
|
|
149
129
|
orderId: String(attrs.order_id ?? ""),
|
|
150
130
|
amount: Number(attrs.total ?? 0),
|
|
151
131
|
};
|
|
152
|
-
if (callbacks.
|
|
153
|
-
await callbacks.
|
|
132
|
+
if (callbacks.onSubscriptionPayment) {
|
|
133
|
+
await callbacks.onSubscriptionPayment(event, "success");
|
|
154
134
|
}
|
|
155
135
|
await dispatchWebhook(eventName, event);
|
|
156
|
-
return { dispatched: callbacks.
|
|
136
|
+
return { dispatched: callbacks.onSubscriptionPayment ? "onSubscriptionPayment:success" : null, skipped: false };
|
|
157
137
|
}
|
|
158
138
|
case "subscription_payment_recovered": {
|
|
159
139
|
const event = {
|
|
@@ -164,11 +144,11 @@ export function createWebhookHandler(callbacks, dedupTtlMs) {
|
|
|
164
144
|
orderId: String(attrs.order_id ?? ""),
|
|
165
145
|
amount: Number(attrs.total ?? 0),
|
|
166
146
|
};
|
|
167
|
-
if (callbacks.
|
|
168
|
-
await callbacks.
|
|
147
|
+
if (callbacks.onSubscriptionPayment) {
|
|
148
|
+
await callbacks.onSubscriptionPayment(event, "recovered");
|
|
169
149
|
}
|
|
170
150
|
await dispatchWebhook(eventName, event);
|
|
171
|
-
return { dispatched: callbacks.
|
|
151
|
+
return { dispatched: callbacks.onSubscriptionPayment ? "onSubscriptionPayment:recovered" : null, skipped: false };
|
|
172
152
|
}
|
|
173
153
|
case "license_key_created": {
|
|
174
154
|
const event = {
|