alepha 0.19.3 → 0.19.4
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/assets/swagger-ui/swagger-ui-bundle.js +1 -1
- package/dist/api/audits/index.d.ts +8 -8
- package/dist/api/invitations/index.d.ts +790 -0
- package/dist/api/invitations/index.d.ts.map +1 -0
- package/dist/api/invitations/index.js +665 -0
- package/dist/api/invitations/index.js.map +1 -0
- package/dist/api/jobs/index.browser.js +8 -9
- package/dist/api/jobs/index.browser.js.map +1 -1
- package/dist/api/jobs/index.d.ts +99 -43
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +257 -40
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/keys/index.d.ts +5 -5
- package/dist/api/notifications/index.browser.js +0 -1
- package/dist/api/notifications/index.browser.js.map +1 -1
- package/dist/api/notifications/index.d.ts +3 -3
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/notifications/index.js +0 -1
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/parameters/index.browser.js +112 -1
- package/dist/api/parameters/index.browser.js.map +1 -1
- package/dist/api/parameters/index.d.ts +90 -3
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +79 -12
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/{billing → api/payments}/index.d.ts +67 -49
- package/dist/api/payments/index.d.ts.map +1 -0
- package/dist/{billing → api/payments}/index.js +108 -74
- package/dist/api/payments/index.js.map +1 -0
- package/dist/api/subscriptions/index.d.ts +1692 -0
- package/dist/api/subscriptions/index.d.ts.map +1 -0
- package/dist/api/subscriptions/index.js +1870 -0
- package/dist/api/subscriptions/index.js.map +1 -0
- package/dist/api/users/index.d.ts +18 -2
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +167 -34
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.d.ts +13 -13
- package/dist/api/workflows/index.browser.js +246 -0
- package/dist/api/workflows/index.browser.js.map +1 -0
- package/dist/api/workflows/index.d.ts +1618 -0
- package/dist/api/workflows/index.d.ts.map +1 -0
- package/dist/api/workflows/index.js +1504 -0
- package/dist/api/workflows/index.js.map +1 -0
- package/dist/cli/core/index.d.ts +44 -28
- package/dist/cli/core/index.d.ts.map +1 -1
- package/dist/cli/core/index.js +16 -61
- package/dist/cli/core/index.js.map +1 -1
- package/dist/cli/vendor/index.d.ts +31 -8
- package/dist/cli/vendor/index.d.ts.map +1 -1
- package/dist/cli/vendor/index.js +79 -24
- package/dist/cli/vendor/index.js.map +1 -1
- package/dist/core/index.browser.js +21 -2
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +33 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +21 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +21 -2
- package/dist/core/index.native.js.map +1 -1
- package/dist/core/index.workerd.js +21 -2
- package/dist/core/index.workerd.js.map +1 -1
- package/dist/email/smtp/index.js +24 -8
- package/dist/email/smtp/index.js.map +1 -1
- package/dist/orm/core/index.browser.js +0 -18
- package/dist/orm/core/index.browser.js.map +1 -1
- package/dist/orm/core/index.bun.js +0 -17
- package/dist/orm/core/index.bun.js.map +1 -1
- package/dist/orm/core/index.d.ts +1 -13
- package/dist/orm/core/index.d.ts.map +1 -1
- package/dist/orm/core/index.js +0 -17
- package/dist/orm/core/index.js.map +1 -1
- package/dist/orm/postgres/index.bun.js +3 -3
- package/dist/orm/postgres/index.bun.js.map +1 -1
- package/dist/orm/postgres/index.d.ts.map +1 -1
- package/dist/orm/postgres/index.js +3 -3
- package/dist/orm/postgres/index.js.map +1 -1
- package/dist/react/router/index.browser.js +25 -3
- package/dist/react/router/index.browser.js.map +1 -1
- package/dist/react/router/index.d.ts +16 -1
- package/dist/react/router/index.d.ts.map +1 -1
- package/dist/react/router/index.js +25 -3
- package/dist/react/router/index.js.map +1 -1
- package/dist/security/index.d.ts +28 -0
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +28 -0
- package/dist/security/index.js.map +1 -1
- package/package.json +37 -20
- package/src/api/invitations/__tests__/InvitationService.spec.ts +439 -0
- package/src/api/invitations/controllers/AdminInvitationController.ts +86 -0
- package/src/api/invitations/controllers/InvitationController.ts +84 -0
- package/src/api/invitations/entities/invitations.ts +33 -0
- package/src/api/invitations/index.ts +65 -0
- package/src/api/invitations/jobs/InvitationJobs.ts +37 -0
- package/src/api/invitations/providers/InvitationProvider.ts +45 -0
- package/src/api/invitations/schemas/createInvitationSchema.ts +12 -0
- package/src/api/invitations/schemas/invitationConfigAtom.ts +20 -0
- package/src/api/invitations/schemas/invitationQuerySchema.ts +15 -0
- package/src/api/invitations/schemas/invitationResourceSchema.ts +6 -0
- package/src/api/invitations/schemas/invitationWithResourceInfoSchema.ts +22 -0
- package/src/api/invitations/schemas/myInvitationsQuerySchema.ts +10 -0
- package/src/api/invitations/services/InvitationService.ts +556 -0
- package/src/api/jobs/__tests__/$job.spec.ts +876 -0
- package/src/api/jobs/controllers/AdminJobController.ts +44 -0
- package/src/api/jobs/entities/jobExecutionEntity.ts +0 -2
- package/src/api/jobs/index.ts +0 -3
- package/src/api/jobs/primitives/$job.ts +22 -11
- package/src/api/jobs/providers/JobProvider.ts +229 -19
- package/src/api/jobs/schemas/jobConfigAtom.ts +4 -0
- package/src/api/jobs/schemas/jobCronInfoSchema.ts +1 -0
- package/src/api/jobs/schemas/jobExecutionQuerySchema.ts +0 -1
- package/src/api/jobs/schemas/jobQueueDepthSchema.ts +1 -0
- package/src/api/jobs/schemas/jobRegistrationSchema.ts +1 -6
- package/src/api/jobs/services/JobService.ts +51 -12
- package/src/api/notifications/schemas/notificationQuerySchema.ts +0 -1
- package/src/api/parameters/__tests__/$parameter.spec.ts +327 -0
- package/src/api/parameters/controllers/AdminParameterController.ts +29 -3
- package/src/api/parameters/index.browser.ts +12 -0
- package/src/api/parameters/primitives/$parameter.ts +20 -3
- package/src/api/parameters/services/ParameterProvider.ts +48 -7
- package/src/{billing → api/payments}/__tests__/PaymentMethodService.spec.ts +32 -6
- package/src/api/payments/__tests__/PaymentService.spec.ts +279 -0
- package/src/{billing/controllers/AdminBillingController.ts → api/payments/controllers/AdminPaymentController.ts} +26 -21
- package/src/{billing/controllers/BillingController.ts → api/payments/controllers/PaymentController.ts} +23 -11
- package/src/{billing → api/payments}/entities/paymentIntents.ts +1 -0
- package/src/{billing/errors/BillingError.ts → api/payments/errors/PaymentError.ts} +1 -1
- package/src/{billing → api/payments}/index.ts +31 -25
- package/src/{billing/providers/MemoryBillingProvider.ts → api/payments/providers/MemoryPaymentProvider.ts} +4 -4
- package/src/{billing/providers/BillingProvider.ts → api/payments/providers/PaymentProvider.ts} +9 -2
- package/src/{billing → api/payments}/services/PaymentMethodService.ts +5 -5
- package/src/{billing/services/BillingService.ts → api/payments/services/PaymentService.ts} +94 -18
- package/src/api/subscriptions/__tests__/BillingService.spec.ts +218 -0
- package/src/api/subscriptions/__tests__/SubscriptionService.spec.ts +278 -0
- package/src/api/subscriptions/controllers/AdminSubscriptionController.ts +212 -0
- package/src/api/subscriptions/controllers/SubscriptionController.ts +189 -0
- package/src/api/subscriptions/entities/subscriptionEvents.ts +54 -0
- package/src/api/subscriptions/entities/subscriptions.ts +68 -0
- package/src/api/subscriptions/index.ts +144 -0
- package/src/api/subscriptions/jobs/SubscriptionJobs.ts +382 -0
- package/src/api/subscriptions/middleware/$requireLimit.ts +50 -0
- package/src/api/subscriptions/middleware/$requirePlan.ts +49 -0
- package/src/api/subscriptions/notifications/SubscriptionNotifications.ts +110 -0
- package/src/api/subscriptions/schemas/cancelSubscriptionSchema.ts +8 -0
- package/src/api/subscriptions/schemas/changePlanSchema.ts +9 -0
- package/src/api/subscriptions/schemas/createSubscriptionSchema.ts +11 -0
- package/src/api/subscriptions/schemas/entitlementsSchema.ts +21 -0
- package/src/api/subscriptions/schemas/mrrSchema.ts +13 -0
- package/src/api/subscriptions/schemas/planDefinitionSchema.ts +71 -0
- package/src/api/subscriptions/schemas/planResourceSchema.ts +25 -0
- package/src/api/subscriptions/schemas/subscriptionEventResourceSchema.ts +8 -0
- package/src/api/subscriptions/schemas/subscriptionQuerySchema.ts +19 -0
- package/src/api/subscriptions/schemas/subscriptionResourceSchema.ts +6 -0
- package/src/api/subscriptions/schemas/subscriptionSettingsSchema.ts +32 -0
- package/src/api/subscriptions/schemas/subscriptionStatsSchema.ts +23 -0
- package/src/api/subscriptions/services/BillingService.ts +437 -0
- package/src/api/subscriptions/services/SubscriptionConfig.ts +56 -0
- package/src/api/subscriptions/services/SubscriptionService.ts +867 -0
- package/src/api/subscriptions/services/UsageService.ts +118 -0
- package/src/api/users/__tests__/AdminUserController.spec.ts +80 -1
- package/src/api/users/__tests__/CredentialService.spec.ts +177 -0
- package/src/api/users/__tests__/EmailVerification.spec.ts +29 -18
- package/src/api/users/__tests__/PasswordReset.spec.ts +3 -0
- package/src/api/users/__tests__/RegistrationService.spec.ts +148 -1
- package/src/api/users/__tests__/SessionService.spec.ts +142 -1
- package/src/api/users/atoms/realmAuthSettingsAtom.ts +10 -1
- package/src/api/users/controllers/UserController.ts +3 -8
- package/src/api/users/notifications/UserNotifications.ts +23 -0
- package/src/api/users/schemas/loginSchema.ts +1 -1
- package/src/api/users/services/CredentialService.ts +51 -4
- package/src/api/users/services/RegistrationService.ts +38 -9
- package/src/api/users/services/SessionService.ts +62 -9
- package/src/api/users/services/UserService.ts +21 -12
- package/src/api/workflows/__tests__/$workflow.spec.ts +616 -0
- package/src/api/workflows/controllers/AdminWorkflowController.ts +191 -0
- package/src/api/workflows/entities/workflowExecutions.ts +74 -0
- package/src/api/workflows/entities/workflowStepExecutions.ts +74 -0
- package/src/api/workflows/entities/workflowStepLogs.ts +13 -0
- package/src/api/workflows/index.browser.ts +22 -0
- package/src/api/workflows/index.ts +124 -0
- package/src/api/workflows/jobs/WorkflowJobs.ts +77 -0
- package/src/api/workflows/primitives/$workflow.ts +202 -0
- package/src/api/workflows/providers/WorkflowProvider.ts +1284 -0
- package/src/api/workflows/schemas/workflowActivitySchema.ts +15 -0
- package/src/api/workflows/schemas/workflowConfigAtom.ts +51 -0
- package/src/api/workflows/schemas/workflowExecutionDetailSchema.ts +18 -0
- package/src/api/workflows/schemas/workflowExecutionQuerySchema.ts +26 -0
- package/src/api/workflows/schemas/workflowExecutionResourceSchema.ts +30 -0
- package/src/api/workflows/schemas/workflowRegistrationSchema.ts +26 -0
- package/src/api/workflows/schemas/workflowStatsSchema.ts +16 -0
- package/src/api/workflows/schemas/workflowStepExecutionResourceSchema.ts +15 -0
- package/src/api/workflows/services/WorkflowService.ts +382 -0
- package/src/cli/core/templates/webAppRouterTs.ts +5 -58
- package/src/cli/vendor/__tests__/VendorService.spec.ts +283 -178
- package/src/cli/vendor/services/VendorService.ts +126 -27
- package/src/core/__tests__/TypeProvider.spec.ts +4 -2
- package/src/core/providers/SchemaValidator.ts +1 -1
- package/src/core/providers/TypeProvider.ts +46 -3
- package/src/orm/__tests__/enums.spec.ts +22 -29
- package/src/orm/__tests__/orm-showcase-tests.ts +430 -0
- package/src/orm/__tests__/orm-showcase.spec.ts +167 -0
- package/src/orm/core/providers/DatabaseTypeProvider.ts +0 -29
- package/src/orm/postgres/services/PostgresModelBuilder.ts +3 -6
- package/src/react/router/__tests__/$page.browser.spec.tsx +157 -0
- package/src/react/router/providers/ReactBrowserProvider.ts +39 -0
- package/src/react/router/providers/ReactBrowserRouterProvider.ts +22 -0
- package/src/security/__tests__/$secure-combinations.spec.ts +945 -0
- package/src/security/primitives/$secure.ts +28 -0
- package/dist/billing/index.d.ts.map +0 -1
- package/dist/billing/index.js.map +0 -1
- package/src/billing/__tests__/BillingService.spec.ts +0 -136
- /package/src/{billing → api/payments}/entities/paymentMethods.ts +0 -0
- /package/src/{billing → api/payments}/entities/refunds.ts +0 -0
- /package/src/{billing → api/payments}/schemas/intentSchemas.ts +0 -0
- /package/src/{billing → api/payments}/schemas/paymentMethodSchemas.ts +0 -0
- /package/src/{billing → api/payments}/schemas/refundSchemas.ts +0 -0
|
@@ -41,6 +41,24 @@ export interface SecureOptions {
|
|
|
41
41
|
* 2. `request.user` — set by previous middleware
|
|
42
42
|
* 3. HTTP headers — JWT/API key resolution
|
|
43
43
|
*
|
|
44
|
+
* ## Check Order
|
|
45
|
+
*
|
|
46
|
+
* When multiple options are provided, they are checked in this fixed order.
|
|
47
|
+
* All provided options must pass (AND). Each option has its own logic:
|
|
48
|
+
*
|
|
49
|
+
* 1. **Authentication** — Is there a valid user? → `UnauthorizedError` (401)
|
|
50
|
+
* 2. **Issuers** (OR) — Does the user's realm match at least one? → `ForbiddenError` (403)
|
|
51
|
+
* 3. **Roles** (OR) — Does the user have at least one of the listed roles? → `ForbiddenError` (403)
|
|
52
|
+
* 4. **Permissions** (AND) — Does the user's role grant all listed permissions? → `ForbiddenError` (403)
|
|
53
|
+
* 5. **Guard** — Does the custom function return `true`? → `ForbiddenError` (403)
|
|
54
|
+
*
|
|
55
|
+
* Permissions declared in `$secure()` are auto-created in the permission registry at definition time.
|
|
56
|
+
*
|
|
57
|
+
* ## Browser Behavior
|
|
58
|
+
*
|
|
59
|
+
* On the server, `$secure` throws `UnauthorizedError` or `ForbiddenError`.
|
|
60
|
+
* In the browser, it returns `undefined` instead — the handler is never called.
|
|
61
|
+
*
|
|
44
62
|
* ```typescript
|
|
45
63
|
* class OrderController {
|
|
46
64
|
* getOrders = $action({
|
|
@@ -52,6 +70,16 @@ export interface SecureOptions {
|
|
|
52
70
|
* use: [$secure({ permissions: ["orders:delete"] })],
|
|
53
71
|
* handler: async ({ params }) => { ... },
|
|
54
72
|
* });
|
|
73
|
+
*
|
|
74
|
+
* adminManage = $action({
|
|
75
|
+
* use: [$secure({
|
|
76
|
+
* issuers: ["main"],
|
|
77
|
+
* roles: ["admin"],
|
|
78
|
+
* permissions: ["admin:manage"],
|
|
79
|
+
* guard: (user) => !!user.email,
|
|
80
|
+
* })],
|
|
81
|
+
* handler: () => { ... },
|
|
82
|
+
* });
|
|
55
83
|
* }
|
|
56
84
|
* ```
|
|
57
85
|
*/
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/orm/core/schemas/insertSchema.ts","../../src/orm/core/schemas/updateSchema.ts","../../src/orm/core/primitives/$entity.ts","../../src/orm/core/constants/PG_SYMBOLS.ts","../../src/orm/core/helpers/pgAttr.ts","../../src/orm/core/schemas/databaseEnvSchema.ts","../../src/billing/entities/paymentIntents.ts","../../src/billing/entities/refunds.ts","../../src/billing/providers/BillingProvider.ts","../../src/billing/services/BillingService.ts","../../src/billing/controllers/AdminBillingController.ts","../../src/billing/entities/paymentMethods.ts","../../src/billing/services/PaymentMethodService.ts","../../src/billing/controllers/BillingController.ts","../../src/billing/errors/BillingError.ts","../../src/billing/providers/MemoryBillingProvider.ts","../../src/billing/schemas/intentSchemas.ts","../../src/billing/schemas/paymentMethodSchemas.ts","../../src/billing/schemas/refundSchemas.ts","../../src/billing/index.ts"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/billing/entities/paymentIntents.ts","../../src/billing/schemas/intentSchemas.ts","../../src/billing/entities/refunds.ts","../../src/billing/schemas/refundSchemas.ts","../../src/billing/errors/BillingError.ts","../../src/billing/providers/BillingProvider.ts","../../src/billing/services/BillingService.ts","../../src/billing/controllers/AdminBillingController.ts","../../src/billing/entities/paymentMethods.ts","../../src/billing/schemas/paymentMethodSchemas.ts","../../src/billing/services/PaymentMethodService.ts","../../src/billing/controllers/BillingController.ts","../../src/billing/providers/MemoryBillingProvider.ts","../../src/billing/index.ts"],"sourcesContent":["import { type Static, t } from \"alepha\";\nimport { $entity, db } from \"alepha/orm\";\n\nexport const paymentIntents = $entity({\n name: \"payment_intents\",\n schema: t.object({\n id: db.primaryKey(t.uuid()),\n version: db.version(),\n createdAt: db.createdAt(),\n updatedAt: db.updatedAt(),\n organizationId: db.organization(),\n amount: t.integer(),\n currency: t.text({ size: \"short\" }),\n status: t.enum([\n \"created\",\n \"processing\",\n \"authorized\",\n \"captured\",\n \"voided\",\n \"failed\",\n \"cancelled\",\n \"refunded\",\n \"expired\",\n ]),\n providerRef: t.optional(t.text()),\n providerRaw: t.optional(t.json()),\n metadata: t.optional(t.json()),\n paymentMethodId: t.optional(t.uuid()),\n userId: t.optional(t.uuid()),\n }),\n indexes: [\"status\", \"organizationId\", \"userId\", \"createdAt\"],\n});\n\nexport type PaymentIntentEntity = Static<typeof paymentIntents.schema>;\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\nimport { pageQuerySchema } from \"alepha/orm\";\nimport { paymentIntents } from \"../entities/paymentIntents.ts\";\n\nexport const createIntentSchema = t.object({\n amount: t.integer({ minimum: 1 }),\n currency: t.text({ size: \"short\" }),\n metadata: t.optional(t.json()),\n paymentMethodId: t.optional(t.uuid()),\n});\n\nexport type CreateIntent = Static<typeof createIntentSchema>;\n\nexport const createCheckoutSchema = t.object({\n intentId: t.uuid(),\n returnUrl: t.text(),\n authorize: t.optional(t.boolean()),\n});\n\nexport type CreateCheckout = Static<typeof createCheckoutSchema>;\n\nexport const checkoutResponseSchema = t.object({\n url: t.text(),\n intentId: t.text(),\n});\n\nexport type CheckoutResponse = Static<typeof checkoutResponseSchema>;\n\nexport const captureIntentSchema = t.object({\n amount: t.optional(t.integer({ minimum: 1 })),\n});\n\nexport type CaptureIntent = Static<typeof captureIntentSchema>;\n\nexport const refundIntentSchema = t.object({\n amount: t.integer({ minimum: 1 }),\n reason: t.optional(t.text()),\n});\n\nexport type RefundIntent = Static<typeof refundIntentSchema>;\n\nexport const recordCashSchema = t.object({\n amount: t.integer({ minimum: 1 }),\n currency: t.text({ size: \"short\" }),\n metadata: t.optional(t.json()),\n});\n\nexport type RecordCash = Static<typeof recordCashSchema>;\n\nexport const intentQuerySchema = t.extend(pageQuerySchema, {\n status: t.optional(t.text({ description: \"Filter by status\" })),\n userId: t.optional(t.uuid({ description: \"Filter by user ID\" })),\n});\n\nexport type IntentQuery = Static<typeof intentQuerySchema>;\n\nexport const intentResourceSchema = paymentIntents.schema;\n\nexport type IntentResource = Static<typeof intentResourceSchema>;\n","import { type Static, t } from \"alepha\";\nimport { $entity, db } from \"alepha/orm\";\n\nexport const refunds = $entity({\n name: \"refunds\",\n schema: t.object({\n id: db.primaryKey(t.uuid()),\n version: db.version(),\n createdAt: db.createdAt(),\n updatedAt: db.updatedAt(),\n organizationId: db.organization(),\n intentId: t.uuid(),\n amount: t.integer(),\n currency: t.text({ size: \"short\" }),\n status: t.enum([\"pending\", \"processing\", \"completed\", \"failed\"]),\n reason: t.optional(t.text()),\n providerRef: t.optional(t.text()),\n }),\n indexes: [\"intentId\", \"organizationId\", \"status\"],\n});\n\nexport type RefundEntity = Static<typeof refunds.schema>;\n","import type { Static } from \"alepha\";\nimport { refunds } from \"../entities/refunds.ts\";\n\nexport const refundResourceSchema = refunds.schema;\n\nexport type RefundResource = Static<typeof refundResourceSchema>;\n","import { AlephaError } from \"alepha\";\n\nexport class BillingError extends AlephaError {\n public readonly status = 400;\n}\n","import type { PaymentIntentEntity } from \"../entities/paymentIntents.ts\";\n\nexport interface CreateSessionResult {\n url: string;\n providerRef: string;\n}\n\nexport interface RefundResult {\n providerRef: string;\n}\n\nexport interface WebhookEvent {\n providerRef: string;\n status: string;\n raw: unknown;\n}\n\nexport interface CreatePaymentMethodResult {\n providerRef: string;\n type: string;\n brand?: string;\n last4?: string;\n expMonth?: number;\n expYear?: number;\n}\n\nexport abstract class BillingProvider {\n /**\n * Create a checkout session with the PSP.\n * Returns a URL to redirect the user to, and the PSP's reference ID.\n */\n abstract createSession(\n intent: PaymentIntentEntity,\n options: { returnUrl: string; authorize?: boolean },\n ): Promise<CreateSessionResult>;\n\n /**\n * Capture a previously authorized payment.\n * Amount can differ from the original authorization (partial capture).\n */\n abstract capturePayment(providerRef: string, amount: number): Promise<void>;\n\n /**\n * Void/cancel a previously authorized payment before capture.\n */\n abstract voidPayment(providerRef: string): Promise<void>;\n\n /**\n * Refund a captured payment (partial or full).\n */\n abstract refundPayment(\n providerRef: string,\n amount: number,\n ): Promise<RefundResult>;\n\n /**\n * Parse an incoming PSP webhook request into a normalized event.\n */\n abstract parseWebhook(request: Request): Promise<WebhookEvent>;\n\n /**\n * Store a payment method token with the PSP.\n */\n abstract createPaymentMethod(\n userId: string,\n token: string,\n ): Promise<CreatePaymentMethodResult>;\n\n /**\n * Delete a stored payment method from the PSP.\n */\n abstract deletePaymentMethod(providerRef: string): Promise<void>;\n\n /**\n * Expire/cancel a checkout session on the PSP side.\n * Called during stale session cleanup.\n */\n abstract expireSession(providerRef: string): Promise<void>;\n}\n","import { $inject, Alepha } from \"alepha\";\nimport { $job } from \"alepha/api/jobs\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { $repository } from \"alepha/orm\";\nimport {\n type PaymentIntentEntity,\n paymentIntents,\n} from \"../entities/paymentIntents.ts\";\nimport { type RefundEntity, refunds } from \"../entities/refunds.ts\";\nimport { BillingError } from \"../errors/BillingError.ts\";\nimport { BillingProvider } from \"../providers/BillingProvider.ts\";\n\nexport class BillingService {\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n protected readonly dateTime = $inject(DateTimeProvider);\n protected readonly provider = $inject(BillingProvider);\n protected readonly intentRepo = $repository(paymentIntents);\n protected readonly refundRepo = $repository(refunds);\n\n /**\n * Expires stale payment intents that have been in \"processing\" status\n * for more than 30 minutes. Runs every 15 minutes.\n */\n protected readonly expireStaleIntents = $job({\n cron: \"*/15 * * * *\",\n handler: async () => {\n const cutoff = this.dateTime.now().subtract(30, \"minutes\").toISOString();\n\n const stale = await this.intentRepo.findMany({\n where: { status: { eq: \"processing\" }, createdAt: { lt: cutoff } },\n });\n\n for (const intent of stale) {\n if (intent.providerRef) {\n try {\n await this.provider.expireSession(intent.providerRef);\n } catch (error) {\n this.log.warn(\n `Failed to expire session for intent ${intent.id}`,\n error,\n );\n }\n }\n await this.intentRepo.updateById(intent.id, { status: \"expired\" });\n this.log.info(`Expired stale intent ${intent.id}`);\n }\n },\n });\n\n /**\n * Create a new payment intent in \"created\" status.\n */\n public async createIntent(\n amount: number,\n currency: string,\n metadata?: unknown,\n options?: { paymentMethodId?: string; userId?: string },\n ): Promise<PaymentIntentEntity> {\n return await this.intentRepo.create({\n amount,\n currency,\n status: \"created\",\n metadata: metadata as any,\n paymentMethodId: options?.paymentMethodId,\n userId: options?.userId,\n });\n }\n\n /**\n * Create a checkout session with the payment provider and\n * transition the intent to \"processing\".\n */\n public async createSession(\n intentId: string,\n returnUrl: string,\n authorize?: boolean,\n ): Promise<{ url: string; intentId: string }> {\n const intent = await this.getIntent(intentId);\n this.assertStatus(intent, \"created\", \"createSession\");\n\n const result = await this.provider.createSession(intent, {\n returnUrl,\n authorize,\n });\n\n await this.intentRepo.updateById(intent.id, {\n status: \"processing\",\n providerRef: result.providerRef,\n });\n\n return { url: result.url, intentId: intent.id };\n }\n\n /**\n * Handle an incoming webhook from the payment provider.\n */\n public async handleWebhook(request: Request): Promise<void> {\n const event = await this.provider.parseWebhook(request);\n const intents = await this.intentRepo.findMany({\n where: { providerRef: { eq: event.providerRef } },\n limit: 1,\n });\n\n if (intents.length === 0) {\n this.log.warn(`Webhook for unknown providerRef: ${event.providerRef}`);\n return;\n }\n\n const intent = intents[0];\n await this.handleWebhookEvent(intent.id, event.status, event.raw);\n }\n\n /**\n * Process a webhook event by updating the intent status and emitting\n * the corresponding billing event.\n */\n public async handleWebhookEvent(\n intentId: string,\n status: string,\n raw?: unknown,\n ): Promise<void> {\n const intent = await this.getIntent(intentId);\n\n const eventMap = {\n authorized: \"billing:authorized\",\n captured: \"billing:captured\",\n failed: \"billing:failed\",\n } as const;\n\n type WebhookStatus = keyof typeof eventMap;\n if (!(status in eventMap)) {\n this.log.warn(`Unknown webhook status: ${status}`);\n return;\n }\n\n const webhookStatus = status as WebhookStatus;\n\n await this.intentRepo.updateById(intent.id, {\n status: webhookStatus,\n providerRaw: raw as any,\n });\n\n await this.alepha.events.emit(eventMap[webhookStatus], {\n intentId: intent.id,\n amount: intent.amount,\n currency: intent.currency,\n metadata: intent.metadata,\n });\n }\n\n /**\n * Capture a previously authorized payment. Optionally specify a different\n * amount for partial capture.\n */\n public async capture(\n intentId: string,\n finalAmount?: number,\n ): Promise<PaymentIntentEntity> {\n const intent = await this.getIntent(intentId);\n this.assertStatus(intent, \"authorized\", \"capture\");\n\n const amount = finalAmount ?? intent.amount;\n if (intent.providerRef) {\n await this.provider.capturePayment(intent.providerRef, amount);\n }\n\n const updated = await this.intentRepo.updateById(intent.id, {\n status: \"captured\",\n amount,\n });\n\n await this.alepha.events.emit(\"billing:captured\", {\n intentId: intent.id,\n amount,\n currency: intent.currency,\n metadata: intent.metadata,\n });\n\n return updated;\n }\n\n /**\n * Void a previously authorized payment before capture.\n */\n public async void(intentId: string): Promise<PaymentIntentEntity> {\n const intent = await this.getIntent(intentId);\n this.assertStatus(intent, \"authorized\", \"void\");\n\n if (intent.providerRef) {\n await this.provider.voidPayment(intent.providerRef);\n }\n\n const updated = await this.intentRepo.updateById(intent.id, {\n status: \"voided\",\n });\n\n await this.alepha.events.emit(\"billing:voided\", {\n intentId: intent.id,\n amount: intent.amount,\n currency: intent.currency,\n metadata: intent.metadata,\n });\n\n return updated;\n }\n\n /**\n * Refund a captured payment (partial or full).\n */\n public async refund(\n intentId: string,\n amount: number,\n reason?: string,\n ): Promise<RefundEntity> {\n const intent = await this.getIntent(intentId);\n this.assertStatus(intent, \"captured\", \"refund\");\n\n let refundProviderRef: string | undefined;\n if (intent.providerRef) {\n const result = await this.provider.refundPayment(\n intent.providerRef,\n amount,\n );\n refundProviderRef = result.providerRef;\n }\n\n const refund = await this.refundRepo.create({\n intentId: intent.id,\n organizationId: intent.organizationId,\n amount,\n currency: intent.currency,\n status: \"completed\",\n reason,\n providerRef: refundProviderRef,\n });\n\n await this.intentRepo.updateById(intent.id, { status: \"refunded\" });\n\n await this.alepha.events.emit(\"billing:refunded\", {\n intentId: intent.id,\n refundId: refund.id,\n amount,\n currency: intent.currency,\n metadata: intent.metadata,\n });\n\n return refund;\n }\n\n /**\n * Record a cash or offline payment directly as captured,\n * bypassing the checkout flow.\n */\n public async recordCashPayment(\n amount: number,\n currency: string,\n metadata?: unknown,\n ): Promise<PaymentIntentEntity> {\n const intent = await this.intentRepo.create({\n amount,\n currency,\n status: \"captured\",\n metadata: metadata as any,\n });\n\n await this.alepha.events.emit(\"billing:captured\", {\n intentId: intent.id,\n amount,\n currency,\n metadata,\n });\n\n return intent;\n }\n\n /**\n * Cancel a payment intent that has not yet entered processing.\n */\n public async cancel(intentId: string): Promise<PaymentIntentEntity> {\n const intent = await this.getIntent(intentId);\n this.assertStatus(intent, \"created\", \"cancel\");\n\n return await this.intentRepo.updateById(intent.id, {\n status: \"cancelled\",\n });\n }\n\n /**\n * Get a payment intent by ID. Throws NotFoundError if not found.\n */\n public async getIntent(intentId: string): Promise<PaymentIntentEntity> {\n return await this.intentRepo.getById(intentId);\n }\n\n /**\n * Find payment intents with optional filters and pagination.\n */\n public async findIntents(query: {\n status?: string;\n userId?: string;\n sort?: string;\n size?: number;\n page?: number;\n }) {\n const where = this.intentRepo.createQueryWhere();\n if (query.status)\n where.status = { eq: query.status as PaymentIntentEntity[\"status\"] };\n if (query.userId) where.userId = { eq: query.userId };\n return await this.intentRepo.paginate(query, { where }, { count: true });\n }\n\n protected assertStatus(\n intent: PaymentIntentEntity,\n expected: PaymentIntentEntity[\"status\"],\n operation: string,\n ): void {\n if (intent.status !== expected) {\n throw new BillingError(\n `Cannot ${operation}: intent ${intent.id} is '${intent.status}', expected '${expected}'`,\n );\n }\n }\n}\n","import { $inject, t } from \"alepha\";\nimport { $secure } from \"alepha/security\";\nimport { $action, okSchema } from \"alepha/server\";\nimport {\n captureIntentSchema,\n intentQuerySchema,\n intentResourceSchema,\n recordCashSchema,\n refundIntentSchema,\n} from \"../schemas/intentSchemas.ts\";\nimport { refundResourceSchema } from \"../schemas/refundSchemas.ts\";\nimport { BillingService } from \"../services/BillingService.ts\";\n\nexport class AdminBillingController {\n protected readonly url = \"/admin/billing\";\n protected readonly group = \"admin:billing\";\n protected readonly billing = $inject(BillingService);\n\n /**\n * List payment intents with pagination and filtering.\n */\n public readonly listIntents = $action({\n path: `${this.url}/intents`,\n group: this.group,\n use: [$secure({ permissions: [\"billing:read\"] })],\n description: \"List payment intents\",\n schema: {\n query: intentQuerySchema,\n response: t.page(intentResourceSchema),\n },\n handler: ({ query }) => this.billing.findIntents(query),\n });\n\n /**\n * Get a payment intent by ID.\n */\n public readonly getIntent = $action({\n path: `${this.url}/intents/:id`,\n group: this.group,\n use: [$secure({ permissions: [\"billing:read\"] })],\n description: \"Get payment intent details\",\n schema: {\n params: t.object({ id: t.uuid() }),\n response: intentResourceSchema,\n },\n handler: ({ params }) => this.billing.getIntent(params.id),\n });\n\n /**\n * Capture an authorized intent.\n */\n public readonly captureIntent = $action({\n method: \"POST\",\n path: `${this.url}/intents/:id/capture`,\n group: this.group,\n use: [$secure({ permissions: [\"billing:write\"] })],\n description: \"Capture an authorized payment intent\",\n schema: {\n params: t.object({ id: t.uuid() }),\n body: captureIntentSchema,\n response: intentResourceSchema,\n },\n handler: ({ params, body }) => this.billing.capture(params.id, body.amount),\n });\n\n /**\n * Void an authorized intent.\n */\n public readonly voidIntent = $action({\n method: \"POST\",\n path: `${this.url}/intents/:id/void`,\n group: this.group,\n use: [$secure({ permissions: [\"billing:write\"] })],\n description: \"Void an authorized payment intent\",\n schema: {\n params: t.object({ id: t.uuid() }),\n response: intentResourceSchema,\n },\n handler: ({ params }) => this.billing.void(params.id),\n });\n\n /**\n * Refund a captured intent.\n */\n public readonly refundIntent = $action({\n method: \"POST\",\n path: `${this.url}/intents/:id/refund`,\n group: this.group,\n use: [$secure({ permissions: [\"billing:write\"] })],\n description: \"Issue partial or full refund\",\n schema: {\n params: t.object({ id: t.uuid() }),\n body: refundIntentSchema,\n response: refundResourceSchema,\n },\n handler: ({ params, body }) =>\n this.billing.refund(params.id, body.amount, body.reason),\n });\n\n /**\n * Cancel a created intent.\n */\n public readonly cancelIntent = $action({\n method: \"POST\",\n path: `${this.url}/intents/:id/cancel`,\n group: this.group,\n use: [$secure({ permissions: [\"billing:write\"] })],\n description: \"Cancel a created payment intent\",\n schema: {\n params: t.object({ id: t.uuid() }),\n response: intentResourceSchema,\n },\n handler: ({ params }) => this.billing.cancel(params.id),\n });\n\n /**\n * Record a cash payment.\n */\n public readonly recordCash = $action({\n method: \"POST\",\n path: `${this.url}/cash`,\n group: this.group,\n use: [$secure({ permissions: [\"billing:write\"] })],\n description: \"Record a cash payment\",\n schema: {\n body: recordCashSchema,\n response: intentResourceSchema,\n },\n handler: ({ body }) =>\n this.billing.recordCashPayment(body.amount, body.currency, body.metadata),\n });\n\n /**\n * PSP webhook endpoint (not under /admin, no auth — verified by provider).\n */\n public readonly webhook = $action({\n method: \"POST\",\n path: \"/billing/webhook\",\n group: this.group,\n description: \"PSP webhook endpoint\",\n schema: {\n response: okSchema,\n },\n handler: async (request) => {\n await this.billing.handleWebhook(request.raw.web!.req);\n return { ok: true };\n },\n });\n}\n","import { type Static, t } from \"alepha\";\nimport { $entity, db } from \"alepha/orm\";\n\nexport const paymentMethods = $entity({\n name: \"payment_methods\",\n schema: t.object({\n id: db.primaryKey(t.uuid()),\n version: db.version(),\n createdAt: db.createdAt(),\n updatedAt: db.updatedAt(),\n organizationId: db.organization(),\n userId: t.uuid(),\n type: t.text({ size: \"short\" }),\n brand: t.optional(t.text({ size: \"short\" })),\n last4: t.optional(t.text({ size: \"short\" })),\n expMonth: t.optional(t.integer()),\n expYear: t.optional(t.integer()),\n isDefault: t.boolean(),\n providerRef: t.text(),\n }),\n indexes: [\"userId\", \"organizationId\"],\n});\n\nexport type PaymentMethodEntity = Static<typeof paymentMethods.schema>;\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\nimport { paymentMethods } from \"../entities/paymentMethods.ts\";\n\nexport const addPaymentMethodSchema = t.object({\n token: t.text(),\n});\n\nexport type AddPaymentMethod = Static<typeof addPaymentMethodSchema>;\n\nexport const paymentMethodResourceSchema = paymentMethods.schema;\n\nexport type PaymentMethodResource = Static<typeof paymentMethodResourceSchema>;\n","import { $inject } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { $repository } from \"alepha/orm\";\nimport {\n type PaymentMethodEntity,\n paymentMethods,\n} from \"../entities/paymentMethods.ts\";\nimport { BillingError } from \"../errors/BillingError.ts\";\nimport { BillingProvider } from \"../providers/BillingProvider.ts\";\n\nexport class PaymentMethodService {\n protected readonly log = $logger();\n protected readonly provider = $inject(BillingProvider);\n protected readonly methodRepo = $repository(paymentMethods);\n\n public async addPaymentMethod(\n userId: string,\n organizationId: string,\n token: string,\n ): Promise<PaymentMethodEntity> {\n const result = await this.provider.createPaymentMethod(userId, token);\n\n const existing = await this.methodRepo.findMany({\n where: { userId: { eq: userId } },\n });\n\n return await this.methodRepo.create({\n userId,\n organizationId,\n type: result.type,\n brand: result.brand,\n last4: result.last4,\n expMonth: result.expMonth,\n expYear: result.expYear,\n isDefault: existing.length === 0,\n providerRef: result.providerRef,\n });\n }\n\n public async listPaymentMethods(\n userId: string,\n ): Promise<PaymentMethodEntity[]> {\n return await this.methodRepo.findMany({\n where: { userId: { eq: userId } },\n });\n }\n\n public async removePaymentMethod(\n methodId: string,\n userId: string,\n ): Promise<void> {\n const method = await this.methodRepo.getById(methodId);\n if (method.userId !== userId) {\n throw new BillingError(\"Cannot remove another user's payment method\");\n }\n\n await this.provider.deletePaymentMethod(method.providerRef);\n await this.methodRepo.deleteById(method.id);\n }\n\n public async setDefault(\n methodId: string,\n userId: string,\n ): Promise<PaymentMethodEntity> {\n const method = await this.methodRepo.getById(methodId);\n if (method.userId !== userId) {\n throw new BillingError(\"Cannot modify another user's payment method\");\n }\n\n const userMethods = await this.methodRepo.findMany({\n where: { userId: { eq: userId } },\n });\n\n for (const m of userMethods) {\n if (m.isDefault) {\n await this.methodRepo.updateById(m.id, { isDefault: false });\n }\n }\n\n return await this.methodRepo.updateById(method.id, { isDefault: true });\n }\n}\n","import { $inject, t } from \"alepha\";\nimport { $secure } from \"alepha/security\";\nimport { $action, okSchema } from \"alepha/server\";\nimport {\n checkoutResponseSchema,\n createCheckoutSchema,\n} from \"../schemas/intentSchemas.ts\";\nimport {\n addPaymentMethodSchema,\n paymentMethodResourceSchema,\n} from \"../schemas/paymentMethodSchemas.ts\";\nimport { BillingService } from \"../services/BillingService.ts\";\nimport { PaymentMethodService } from \"../services/PaymentMethodService.ts\";\n\nexport class BillingController {\n protected readonly url = \"/billing\";\n protected readonly group = \"billing\";\n protected readonly billing = $inject(BillingService);\n protected readonly paymentMethods = $inject(PaymentMethodService);\n\n /**\n * List the current user's saved payment methods.\n */\n public readonly listPaymentMethods = $action({\n path: `${this.url}/payment-methods`,\n group: this.group,\n use: [$secure()],\n description: \"List current user's saved payment methods\",\n schema: {\n response: t.array(paymentMethodResourceSchema),\n },\n handler: ({ user }) => this.paymentMethods.listPaymentMethods(user.id),\n });\n\n /**\n * Add a new payment method.\n */\n public readonly addPaymentMethod = $action({\n method: \"POST\",\n path: `${this.url}/payment-methods`,\n group: this.group,\n use: [$secure()],\n description: \"Tokenize and store a new payment method\",\n schema: {\n body: addPaymentMethodSchema,\n response: paymentMethodResourceSchema,\n },\n handler: ({ body, user }) =>\n this.paymentMethods.addPaymentMethod(\n user.id,\n user.organization!,\n body.token,\n ),\n });\n\n /**\n * Remove a payment method.\n */\n public readonly removePaymentMethod = $action({\n method: \"DELETE\",\n path: `${this.url}/payment-methods/:id`,\n group: this.group,\n use: [$secure()],\n description: \"Remove own payment method\",\n schema: {\n params: t.object({ id: t.uuid() }),\n response: okSchema,\n },\n handler: async ({ params, user }) => {\n await this.paymentMethods.removePaymentMethod(params.id, user.id);\n return { ok: true, id: params.id };\n },\n });\n\n /**\n * Set a payment method as default.\n */\n public readonly setDefaultPaymentMethod = $action({\n method: \"PATCH\",\n path: `${this.url}/payment-methods/:id/default`,\n group: this.group,\n use: [$secure()],\n description: \"Set as default payment method\",\n schema: {\n params: t.object({ id: t.uuid() }),\n response: paymentMethodResourceSchema,\n },\n handler: ({ params, user }) =>\n this.paymentMethods.setDefault(params.id, user.id),\n });\n\n /**\n * Create a checkout session.\n */\n public readonly createCheckout = $action({\n method: \"POST\",\n path: `${this.url}/checkout`,\n group: this.group,\n use: [$secure()],\n description: \"Create checkout session and return URL\",\n schema: {\n body: createCheckoutSchema,\n response: checkoutResponseSchema,\n },\n handler: ({ body }) =>\n this.billing.createSession(body.intentId, body.returnUrl, body.authorize),\n });\n}\n","import { randomUUID } from \"node:crypto\";\nimport type { PaymentIntentEntity } from \"../entities/paymentIntents.ts\";\nimport type {\n BillingProvider,\n CreatePaymentMethodResult,\n CreateSessionResult,\n RefundResult,\n WebhookEvent,\n} from \"./BillingProvider.ts\";\n\ninterface MemoryCharge {\n providerRef: string;\n amount: number;\n status: string;\n}\n\ninterface MemoryRefund {\n providerRef: string;\n chargeRef: string;\n amount: number;\n}\n\nexport class MemoryBillingProvider implements BillingProvider {\n protected readonly charges: Map<string, MemoryCharge> = new Map();\n protected readonly refundRecords: Map<string, MemoryRefund> = new Map();\n protected readonly methods: Map<string, CreatePaymentMethodResult> =\n new Map();\n protected readonly expiredSessions: Set<string> = new Set();\n\n public async createSession(\n intent: PaymentIntentEntity,\n options: { returnUrl: string; authorize?: boolean },\n ): Promise<CreateSessionResult> {\n const providerRef = `mem_session_${randomUUID()}`;\n const status = options.authorize ? \"authorized\" : \"captured\";\n this.charges.set(providerRef, {\n providerRef,\n amount: intent.amount,\n status,\n });\n return {\n url: `/billing/mock-checkout/${intent.id}`,\n providerRef,\n };\n }\n\n public async capturePayment(\n providerRef: string,\n amount: number,\n ): Promise<void> {\n const charge = this.charges.get(providerRef);\n if (charge) {\n charge.status = \"captured\";\n charge.amount = amount;\n }\n }\n\n public async voidPayment(providerRef: string): Promise<void> {\n const charge = this.charges.get(providerRef);\n if (charge) {\n charge.status = \"voided\";\n }\n }\n\n public async refundPayment(\n providerRef: string,\n amount: number,\n ): Promise<RefundResult> {\n const refundRef = `mem_refund_${randomUUID()}`;\n this.refundRecords.set(refundRef, {\n providerRef: refundRef,\n chargeRef: providerRef,\n amount,\n });\n return { providerRef: refundRef };\n }\n\n public async parseWebhook(request: Request): Promise<WebhookEvent> {\n const body = (await request.json()) as {\n providerRef: string;\n status: string;\n };\n return {\n providerRef: body.providerRef,\n status: body.status,\n raw: body,\n };\n }\n\n public async createPaymentMethod(\n userId: string,\n token: string,\n ): Promise<CreatePaymentMethodResult> {\n const providerRef = `mem_pm_${randomUUID()}`;\n const result: CreatePaymentMethodResult = {\n providerRef,\n type: \"card\",\n brand: \"visa\",\n last4: \"4242\",\n expMonth: 12,\n expYear: 2030,\n };\n this.methods.set(providerRef, result);\n return result;\n }\n\n public async deletePaymentMethod(providerRef: string): Promise<void> {\n this.methods.delete(providerRef);\n }\n\n public async expireSession(providerRef: string): Promise<void> {\n this.expiredSessions.add(providerRef);\n }\n\n // --- Test assertion helpers ---\n\n public wasCharged(providerRef: string): boolean {\n const charge = this.charges.get(providerRef);\n return charge?.status === \"captured\";\n }\n\n public wasRefunded(providerRef: string): boolean {\n return Array.from(this.refundRecords.values()).some(\n (r) => r.chargeRef === providerRef,\n );\n }\n\n public wasExpired(providerRef: string): boolean {\n return this.expiredSessions.has(providerRef);\n }\n\n public getCharges(): MemoryCharge[] {\n return Array.from(this.charges.values());\n }\n\n public getRefunds(): MemoryRefund[] {\n return Array.from(this.refundRecords.values());\n }\n}\n","import { $module } from \"alepha\";\nimport { AdminBillingController } from \"./controllers/AdminBillingController.ts\";\nimport { BillingController } from \"./controllers/BillingController.ts\";\nimport { BillingProvider } from \"./providers/BillingProvider.ts\";\nimport { MemoryBillingProvider } from \"./providers/MemoryBillingProvider.ts\";\nimport { BillingService } from \"./services/BillingService.ts\";\nimport { PaymentMethodService } from \"./services/PaymentMethodService.ts\";\n\nexport * from \"./controllers/AdminBillingController.ts\";\nexport * from \"./controllers/BillingController.ts\";\nexport * from \"./entities/paymentIntents.ts\";\nexport * from \"./entities/paymentMethods.ts\";\nexport * from \"./entities/refunds.ts\";\nexport * from \"./errors/BillingError.ts\";\nexport * from \"./providers/BillingProvider.ts\";\nexport * from \"./providers/MemoryBillingProvider.ts\";\nexport * from \"./schemas/intentSchemas.ts\";\nexport * from \"./schemas/paymentMethodSchemas.ts\";\nexport * from \"./schemas/refundSchemas.ts\";\nexport * from \"./services/BillingService.ts\";\nexport * from \"./services/PaymentMethodService.ts\";\n\ndeclare module \"alepha\" {\n interface Hooks {\n \"billing:authorized\": {\n intentId: string;\n amount: number;\n currency: string;\n metadata?: unknown;\n };\n \"billing:captured\": {\n intentId: string;\n amount: number;\n currency: string;\n metadata?: unknown;\n };\n \"billing:failed\": {\n intentId: string;\n amount: number;\n currency: string;\n metadata?: unknown;\n };\n \"billing:voided\": {\n intentId: string;\n amount: number;\n currency: string;\n metadata?: unknown;\n };\n \"billing:refunded\": {\n intentId: string;\n refundId: string;\n amount: number;\n currency: string;\n metadata?: unknown;\n };\n }\n}\n\nexport const AlephaBilling = $module({\n name: \"alepha.billing\",\n services: [\n AdminBillingController,\n BillingController,\n BillingProvider,\n MemoryBillingProvider,\n BillingService,\n PaymentMethodService,\n ],\n register: (alepha) => {\n alepha.with({\n optional: true,\n provide: BillingProvider,\n use: MemoryBillingProvider,\n });\n },\n});\n"],"mappings":"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"}
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import { Alepha } from "alepha";
|
|
2
|
-
import { AlephaOrmPostgres } from "alepha/orm/postgres";
|
|
3
|
-
import { describe, it } from "vitest";
|
|
4
|
-
import { AlephaBilling } from "../index.ts";
|
|
5
|
-
import { BillingService } from "../services/BillingService.ts";
|
|
6
|
-
|
|
7
|
-
describe("BillingService", () => {
|
|
8
|
-
it("should create an intent in 'created' status", async ({ expect }) => {
|
|
9
|
-
const alepha = Alepha.create().with(AlephaOrmPostgres).with(AlephaBilling);
|
|
10
|
-
const billing = alepha.inject(BillingService);
|
|
11
|
-
await alepha.start();
|
|
12
|
-
|
|
13
|
-
const intent = await billing.createIntent(1500, "eur");
|
|
14
|
-
expect(intent.amount).toBe(1500);
|
|
15
|
-
expect(intent.currency).toBe("eur");
|
|
16
|
-
expect(intent.status).toBe("created");
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it("should create a session and transition to 'processing'", async ({
|
|
20
|
-
expect,
|
|
21
|
-
}) => {
|
|
22
|
-
const alepha = Alepha.create().with(AlephaOrmPostgres).with(AlephaBilling);
|
|
23
|
-
const billing = alepha.inject(BillingService);
|
|
24
|
-
await alepha.start();
|
|
25
|
-
|
|
26
|
-
const intent = await billing.createIntent(1500, "eur");
|
|
27
|
-
const session = await billing.createSession(
|
|
28
|
-
intent.id,
|
|
29
|
-
"https://example.com/return",
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
expect(session.url).toContain("/billing/mock-checkout/");
|
|
33
|
-
expect(session.intentId).toBe(intent.id);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it("should capture an authorized intent", async ({ expect }) => {
|
|
37
|
-
const alepha = Alepha.create().with(AlephaOrmPostgres).with(AlephaBilling);
|
|
38
|
-
const billing = alepha.inject(BillingService);
|
|
39
|
-
await alepha.start();
|
|
40
|
-
|
|
41
|
-
const intent = await billing.createIntent(1500, "eur");
|
|
42
|
-
await billing.createSession(intent.id, "https://example.com", true);
|
|
43
|
-
await billing.handleWebhookEvent(intent.id, "authorized");
|
|
44
|
-
|
|
45
|
-
const captured = await billing.capture(intent.id);
|
|
46
|
-
expect(captured.status).toBe("captured");
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it("should void an authorized intent", async ({ expect }) => {
|
|
50
|
-
const alepha = Alepha.create().with(AlephaOrmPostgres).with(AlephaBilling);
|
|
51
|
-
const billing = alepha.inject(BillingService);
|
|
52
|
-
await alepha.start();
|
|
53
|
-
|
|
54
|
-
const intent = await billing.createIntent(1500, "eur");
|
|
55
|
-
await billing.createSession(intent.id, "https://example.com", true);
|
|
56
|
-
await billing.handleWebhookEvent(intent.id, "authorized");
|
|
57
|
-
|
|
58
|
-
const voided = await billing.void(intent.id);
|
|
59
|
-
expect(voided.status).toBe("voided");
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it("should refund a captured intent", async ({ expect }) => {
|
|
63
|
-
const alepha = Alepha.create().with(AlephaOrmPostgres).with(AlephaBilling);
|
|
64
|
-
const billing = alepha.inject(BillingService);
|
|
65
|
-
await alepha.start();
|
|
66
|
-
|
|
67
|
-
const intent = await billing.createIntent(1500, "eur");
|
|
68
|
-
await billing.createSession(intent.id, "https://example.com");
|
|
69
|
-
await billing.handleWebhookEvent(intent.id, "captured");
|
|
70
|
-
|
|
71
|
-
const refund = await billing.refund(intent.id, 500, "Customer request");
|
|
72
|
-
expect(refund.amount).toBe(500);
|
|
73
|
-
expect(refund.status).toBe("completed");
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it("should record a cash payment directly as captured", async ({
|
|
77
|
-
expect,
|
|
78
|
-
}) => {
|
|
79
|
-
const alepha = Alepha.create().with(AlephaOrmPostgres).with(AlephaBilling);
|
|
80
|
-
const billing = alepha.inject(BillingService);
|
|
81
|
-
await alepha.start();
|
|
82
|
-
|
|
83
|
-
const intent = await billing.recordCashPayment(1500, "eur", {
|
|
84
|
-
orderId: "order-1",
|
|
85
|
-
});
|
|
86
|
-
expect(intent.status).toBe("captured");
|
|
87
|
-
expect(intent.metadata).toEqual({ orderId: "order-1" });
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it("should cancel a created intent", async ({ expect }) => {
|
|
91
|
-
const alepha = Alepha.create().with(AlephaOrmPostgres).with(AlephaBilling);
|
|
92
|
-
const billing = alepha.inject(BillingService);
|
|
93
|
-
await alepha.start();
|
|
94
|
-
|
|
95
|
-
const intent = await billing.createIntent(1500, "eur");
|
|
96
|
-
const cancelled = await billing.cancel(intent.id);
|
|
97
|
-
expect(cancelled.status).toBe("cancelled");
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it("should reject capture from wrong status", async ({ expect }) => {
|
|
101
|
-
const alepha = Alepha.create().with(AlephaOrmPostgres).with(AlephaBilling);
|
|
102
|
-
const billing = alepha.inject(BillingService);
|
|
103
|
-
await alepha.start();
|
|
104
|
-
|
|
105
|
-
const intent = await billing.createIntent(1500, "eur");
|
|
106
|
-
await expect(billing.capture(intent.id)).rejects.toThrowError();
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it("should reject refund from wrong status", async ({ expect }) => {
|
|
110
|
-
const alepha = Alepha.create().with(AlephaOrmPostgres).with(AlephaBilling);
|
|
111
|
-
const billing = alepha.inject(BillingService);
|
|
112
|
-
await alepha.start();
|
|
113
|
-
|
|
114
|
-
const intent = await billing.createIntent(1500, "eur");
|
|
115
|
-
await expect(billing.refund(intent.id, 500)).rejects.toThrowError();
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it("should reject void from wrong status", async ({ expect }) => {
|
|
119
|
-
const alepha = Alepha.create().with(AlephaOrmPostgres).with(AlephaBilling);
|
|
120
|
-
const billing = alepha.inject(BillingService);
|
|
121
|
-
await alepha.start();
|
|
122
|
-
|
|
123
|
-
const intent = await billing.createIntent(1500, "eur");
|
|
124
|
-
await expect(billing.void(intent.id)).rejects.toThrowError();
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it("should reject cancel from wrong status", async ({ expect }) => {
|
|
128
|
-
const alepha = Alepha.create().with(AlephaOrmPostgres).with(AlephaBilling);
|
|
129
|
-
const billing = alepha.inject(BillingService);
|
|
130
|
-
await alepha.start();
|
|
131
|
-
|
|
132
|
-
const intent = await billing.createIntent(1500, "eur");
|
|
133
|
-
await billing.createSession(intent.id, "https://example.com");
|
|
134
|
-
await expect(billing.cancel(intent.id)).rejects.toThrowError();
|
|
135
|
-
});
|
|
136
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|