@parsrun/payments 0.1.0

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.
@@ -0,0 +1,188 @@
1
+ // src/webhooks/index.ts
2
+ var WebhookHandlerRegistry = class {
3
+ handlers = /* @__PURE__ */ new Map();
4
+ /**
5
+ * Register a handler for a specific event type
6
+ */
7
+ on(type, handler) {
8
+ const handlers = this.handlers.get(type) ?? [];
9
+ handlers.push(handler);
10
+ this.handlers.set(type, handlers);
11
+ return this;
12
+ }
13
+ /**
14
+ * Register handlers for checkout events
15
+ */
16
+ onCheckout(handler) {
17
+ this.on("checkout.session.completed", handler);
18
+ this.on("checkout.session.expired", handler);
19
+ return this;
20
+ }
21
+ /**
22
+ * Register handlers for subscription events
23
+ */
24
+ onSubscription(handler) {
25
+ this.on("subscription.created", handler);
26
+ this.on("subscription.updated", handler);
27
+ this.on("subscription.deleted", handler);
28
+ this.on("subscription.trial_will_end", handler);
29
+ return this;
30
+ }
31
+ /**
32
+ * Register handlers for payment events
33
+ */
34
+ onPayment(handler) {
35
+ this.on("payment.succeeded", handler);
36
+ this.on("payment.failed", handler);
37
+ return this;
38
+ }
39
+ /**
40
+ * Register handlers for invoice events
41
+ */
42
+ onInvoice(handler) {
43
+ this.on("invoice.created", handler);
44
+ this.on("invoice.paid", handler);
45
+ this.on("invoice.payment_failed", handler);
46
+ this.on("invoice.upcoming", handler);
47
+ return this;
48
+ }
49
+ /**
50
+ * Register handlers for customer events
51
+ */
52
+ onCustomer(handler) {
53
+ this.on("customer.created", handler);
54
+ this.on("customer.updated", handler);
55
+ this.on("customer.deleted", handler);
56
+ return this;
57
+ }
58
+ /**
59
+ * Get handlers for an event type
60
+ */
61
+ getHandlers(type) {
62
+ const specificHandlers = this.handlers.get(type) ?? [];
63
+ const globalHandlers = this.handlers.get("*") ?? [];
64
+ return [...specificHandlers, ...globalHandlers];
65
+ }
66
+ /**
67
+ * Execute all handlers for an event
68
+ */
69
+ async handle(event) {
70
+ const handlers = this.getHandlers(event.type);
71
+ for (const handler of handlers) {
72
+ await handler(event);
73
+ }
74
+ }
75
+ };
76
+ var WebhookProcessor = class {
77
+ provider;
78
+ registry;
79
+ constructor(provider, registry) {
80
+ this.provider = provider;
81
+ this.registry = registry ?? new WebhookHandlerRegistry();
82
+ }
83
+ /**
84
+ * Get the handler registry
85
+ */
86
+ get handlers() {
87
+ return this.registry;
88
+ }
89
+ /**
90
+ * Process a webhook request
91
+ */
92
+ async process(request) {
93
+ try {
94
+ const payload = await request.text();
95
+ const signature = this.getSignature(request);
96
+ if (!signature) {
97
+ return {
98
+ success: false,
99
+ error: "Missing webhook signature"
100
+ };
101
+ }
102
+ const event = await this.provider.verifyWebhook(payload, signature);
103
+ if (!event) {
104
+ return {
105
+ success: false,
106
+ error: "Invalid webhook signature"
107
+ };
108
+ }
109
+ await this.registry.handle(event);
110
+ return {
111
+ success: true,
112
+ event
113
+ };
114
+ } catch (err) {
115
+ return {
116
+ success: false,
117
+ error: err instanceof Error ? err.message : "Unknown error"
118
+ };
119
+ }
120
+ }
121
+ /**
122
+ * Process raw webhook payload
123
+ */
124
+ async processRaw(payload, signature) {
125
+ try {
126
+ const event = await this.provider.verifyWebhook(payload, signature);
127
+ if (!event) {
128
+ return {
129
+ success: false,
130
+ error: "Invalid webhook signature"
131
+ };
132
+ }
133
+ await this.registry.handle(event);
134
+ return {
135
+ success: true,
136
+ event
137
+ };
138
+ } catch (err) {
139
+ return {
140
+ success: false,
141
+ error: err instanceof Error ? err.message : "Unknown error"
142
+ };
143
+ }
144
+ }
145
+ getSignature(request) {
146
+ const stripeSignature = request.headers.get("stripe-signature");
147
+ if (stripeSignature) return stripeSignature;
148
+ const paddleSignature = request.headers.get("paddle-signature");
149
+ if (paddleSignature) return paddleSignature;
150
+ return null;
151
+ }
152
+ };
153
+ function createWebhookProcessor(provider, registry) {
154
+ return new WebhookProcessor(provider, registry);
155
+ }
156
+ function createWebhookHandlerRegistry() {
157
+ return new WebhookHandlerRegistry();
158
+ }
159
+ function createWebhookHandler(provider, handlers) {
160
+ const registry = new WebhookHandlerRegistry();
161
+ for (const [type, handler] of Object.entries(handlers)) {
162
+ if (handler) {
163
+ registry.on(type, handler);
164
+ }
165
+ }
166
+ const processor = new WebhookProcessor(provider, registry);
167
+ return async (request) => {
168
+ const result = await processor.process(request);
169
+ if (result.success) {
170
+ return new Response(JSON.stringify({ received: true }), {
171
+ status: 200,
172
+ headers: { "Content-Type": "application/json" }
173
+ });
174
+ }
175
+ return new Response(JSON.stringify({ error: result.error }), {
176
+ status: 400,
177
+ headers: { "Content-Type": "application/json" }
178
+ });
179
+ };
180
+ }
181
+ export {
182
+ WebhookHandlerRegistry,
183
+ WebhookProcessor,
184
+ createWebhookHandler,
185
+ createWebhookHandlerRegistry,
186
+ createWebhookProcessor
187
+ };
188
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/webhooks/index.ts"],"sourcesContent":["/**\n * @parsrun/payments - Webhook Handlers\n * Utilities for handling payment webhooks\n */\n\nimport type {\n PaymentProvider,\n WebhookEvent,\n WebhookEventType,\n WebhookHandler,\n} from \"../types.js\";\n\n/**\n * Webhook event handler registry\n */\nexport class WebhookHandlerRegistry {\n private handlers = new Map<WebhookEventType | \"*\", WebhookHandler[]>();\n\n /**\n * Register a handler for a specific event type\n */\n on<T = unknown>(type: WebhookEventType | \"*\", handler: WebhookHandler<T>): this {\n const handlers = this.handlers.get(type) ?? [];\n handlers.push(handler as WebhookHandler);\n this.handlers.set(type, handlers);\n return this;\n }\n\n /**\n * Register handlers for checkout events\n */\n onCheckout(handler: WebhookHandler): this {\n this.on(\"checkout.session.completed\", handler);\n this.on(\"checkout.session.expired\", handler);\n return this;\n }\n\n /**\n * Register handlers for subscription events\n */\n onSubscription(handler: WebhookHandler): this {\n this.on(\"subscription.created\", handler);\n this.on(\"subscription.updated\", handler);\n this.on(\"subscription.deleted\", handler);\n this.on(\"subscription.trial_will_end\", handler);\n return this;\n }\n\n /**\n * Register handlers for payment events\n */\n onPayment(handler: WebhookHandler): this {\n this.on(\"payment.succeeded\", handler);\n this.on(\"payment.failed\", handler);\n return this;\n }\n\n /**\n * Register handlers for invoice events\n */\n onInvoice(handler: WebhookHandler): this {\n this.on(\"invoice.created\", handler);\n this.on(\"invoice.paid\", handler);\n this.on(\"invoice.payment_failed\", handler);\n this.on(\"invoice.upcoming\", handler);\n return this;\n }\n\n /**\n * Register handlers for customer events\n */\n onCustomer(handler: WebhookHandler): this {\n this.on(\"customer.created\", handler);\n this.on(\"customer.updated\", handler);\n this.on(\"customer.deleted\", handler);\n return this;\n }\n\n /**\n * Get handlers for an event type\n */\n getHandlers(type: WebhookEventType): WebhookHandler[] {\n const specificHandlers = this.handlers.get(type) ?? [];\n const globalHandlers = this.handlers.get(\"*\") ?? [];\n return [...specificHandlers, ...globalHandlers];\n }\n\n /**\n * Execute all handlers for an event\n */\n async handle(event: WebhookEvent): Promise<void> {\n const handlers = this.getHandlers(event.type);\n\n for (const handler of handlers) {\n await handler(event);\n }\n }\n}\n\n/**\n * Webhook processor for handling incoming webhooks\n */\nexport class WebhookProcessor {\n private provider: PaymentProvider;\n private registry: WebhookHandlerRegistry;\n\n constructor(provider: PaymentProvider, registry?: WebhookHandlerRegistry) {\n this.provider = provider;\n this.registry = registry ?? new WebhookHandlerRegistry();\n }\n\n /**\n * Get the handler registry\n */\n get handlers(): WebhookHandlerRegistry {\n return this.registry;\n }\n\n /**\n * Process a webhook request\n */\n async process(request: Request): Promise<WebhookProcessResult> {\n try {\n // Get payload and signature\n const payload = await request.text();\n const signature = this.getSignature(request);\n\n if (!signature) {\n return {\n success: false,\n error: \"Missing webhook signature\",\n };\n }\n\n // Verify webhook\n const event = await this.provider.verifyWebhook(payload, signature);\n\n if (!event) {\n return {\n success: false,\n error: \"Invalid webhook signature\",\n };\n }\n\n // Handle event\n await this.registry.handle(event);\n\n return {\n success: true,\n event,\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : \"Unknown error\",\n };\n }\n }\n\n /**\n * Process raw webhook payload\n */\n async processRaw(\n payload: string | Uint8Array,\n signature: string\n ): Promise<WebhookProcessResult> {\n try {\n // Verify webhook\n const event = await this.provider.verifyWebhook(payload, signature);\n\n if (!event) {\n return {\n success: false,\n error: \"Invalid webhook signature\",\n };\n }\n\n // Handle event\n await this.registry.handle(event);\n\n return {\n success: true,\n event,\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : \"Unknown error\",\n };\n }\n }\n\n private getSignature(request: Request): string | null {\n // Stripe uses stripe-signature header\n const stripeSignature = request.headers.get(\"stripe-signature\");\n if (stripeSignature) return stripeSignature;\n\n // Paddle uses paddle-signature header\n const paddleSignature = request.headers.get(\"paddle-signature\");\n if (paddleSignature) return paddleSignature;\n\n return null;\n }\n}\n\n/**\n * Webhook process result\n */\nexport interface WebhookProcessResult {\n success: boolean;\n event?: WebhookEvent | undefined;\n error?: string | undefined;\n}\n\n/**\n * Create a webhook processor\n */\nexport function createWebhookProcessor(\n provider: PaymentProvider,\n registry?: WebhookHandlerRegistry\n): WebhookProcessor {\n return new WebhookProcessor(provider, registry);\n}\n\n/**\n * Create a webhook handler registry\n */\nexport function createWebhookHandlerRegistry(): WebhookHandlerRegistry {\n return new WebhookHandlerRegistry();\n}\n\n/**\n * Create a Hono/Express-compatible webhook handler\n */\nexport function createWebhookHandler(\n provider: PaymentProvider,\n handlers: Partial<Record<WebhookEventType | \"*\", WebhookHandler>>\n): (request: Request) => Promise<Response> {\n const registry = new WebhookHandlerRegistry();\n\n for (const [type, handler] of Object.entries(handlers)) {\n if (handler) {\n registry.on(type as WebhookEventType, handler);\n }\n }\n\n const processor = new WebhookProcessor(provider, registry);\n\n return async (request: Request): Promise<Response> => {\n const result = await processor.process(request);\n\n if (result.success) {\n return new Response(JSON.stringify({ received: true }), {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n return new Response(JSON.stringify({ error: result.error }), {\n status: 400,\n headers: { \"Content-Type\": \"application/json\" },\n });\n };\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "@parsrun/payments",
3
+ "version": "0.1.0",
4
+ "description": "Edge-compatible payment processing for Pars - Stripe, Paddle, iyzico",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./types": {
15
+ "types": "./dist/types.d.ts",
16
+ "import": "./dist/types.js"
17
+ },
18
+ "./providers": {
19
+ "types": "./dist/providers/index.d.ts",
20
+ "import": "./dist/providers/index.js"
21
+ },
22
+ "./providers/stripe": {
23
+ "types": "./dist/providers/stripe.d.ts",
24
+ "import": "./dist/providers/stripe.js"
25
+ },
26
+ "./providers/paddle": {
27
+ "types": "./dist/providers/paddle.d.ts",
28
+ "import": "./dist/providers/paddle.js"
29
+ },
30
+ "./providers/iyzico": {
31
+ "types": "./dist/providers/iyzico.d.ts",
32
+ "import": "./dist/providers/iyzico.js"
33
+ },
34
+ "./webhooks": {
35
+ "types": "./dist/webhooks/index.d.ts",
36
+ "import": "./dist/webhooks/index.js"
37
+ },
38
+ "./billing": {
39
+ "types": "./dist/billing/index.d.ts",
40
+ "import": "./dist/billing/index.js"
41
+ },
42
+ "./usage": {
43
+ "types": "./dist/usage/index.d.ts",
44
+ "import": "./dist/usage/index.js"
45
+ },
46
+ "./dunning": {
47
+ "types": "./dist/dunning/index.d.ts",
48
+ "import": "./dist/dunning/index.js"
49
+ }
50
+ },
51
+ "files": [
52
+ "dist",
53
+ "README.md"
54
+ ],
55
+ "scripts": {
56
+ "build": "tsup",
57
+ "dev": "tsup --watch",
58
+ "test": "vitest run",
59
+ "typecheck": "tsc --noEmit"
60
+ },
61
+ "keywords": [
62
+ "payments",
63
+ "stripe",
64
+ "paddle",
65
+ "iyzico",
66
+ "subscriptions",
67
+ "billing",
68
+ "edge",
69
+ "pars"
70
+ ],
71
+ "author": "EMS Tech Solutions",
72
+ "license": "MIT",
73
+ "dependencies": {
74
+ "@parsrun/core": "workspace:*",
75
+ "@parsrun/types": "workspace:*"
76
+ },
77
+ "peerDependencies": {
78
+ "drizzle-orm": ">=0.30.0"
79
+ },
80
+ "peerDependenciesMeta": {
81
+ "drizzle-orm": {
82
+ "optional": true
83
+ }
84
+ },
85
+ "devDependencies": {
86
+ "drizzle-orm": "^0.38.0",
87
+ "tsup": "^8.0.0",
88
+ "typescript": "^5.0.0",
89
+ "vitest": "^2.0.0"
90
+ }
91
+ }