alepha 0.20.1 → 0.20.2
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/dist/api/files/index.js +2 -1
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.browser.js +64 -148
- package/dist/api/jobs/index.browser.js.map +1 -1
- package/dist/api/jobs/index.d.ts +371 -573
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +605 -1012
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/notifications/index.d.ts +78 -17
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/notifications/index.js +90 -23
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/payments/index.d.ts +2 -1
- package/dist/api/payments/index.d.ts.map +1 -1
- package/dist/api/payments/index.js +4 -2
- package/dist/api/payments/index.js.map +1 -1
- package/dist/api/users/index.d.ts +34 -31
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +13 -7
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.js +2 -1
- package/dist/api/verifications/index.js.map +1 -1
- package/dist/cli/core/index.d.ts +8 -34
- package/dist/cli/core/index.d.ts.map +1 -1
- package/dist/cli/core/index.js +43 -232
- package/dist/cli/core/index.js.map +1 -1
- package/dist/cli/platform/index.d.ts +36 -11
- package/dist/cli/platform/index.d.ts.map +1 -1
- package/dist/cli/platform/index.js +93 -27
- package/dist/cli/platform/index.js.map +1 -1
- package/dist/command/index.d.ts +1 -1
- package/dist/core/index.browser.js +6 -0
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +6 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +6 -0
- package/dist/core/index.native.js.map +1 -1
- package/dist/core/index.workerd.js +6 -0
- package/dist/core/index.workerd.js.map +1 -1
- package/dist/react/form/index.d.ts +60 -1
- package/dist/react/form/index.d.ts.map +1 -1
- package/dist/react/form/index.js +86 -1
- package/dist/react/form/index.js.map +1 -1
- package/dist/react/head/index.browser.js +16 -1
- package/dist/react/head/index.browser.js.map +1 -1
- package/dist/react/head/index.d.ts +6 -0
- package/dist/react/head/index.d.ts.map +1 -1
- package/dist/react/head/index.js +16 -1
- package/dist/react/head/index.js.map +1 -1
- package/dist/react/router/index.browser.js +0 -10
- package/dist/react/router/index.browser.js.map +1 -1
- package/dist/react/router/index.d.ts +35 -12
- package/dist/react/router/index.d.ts.map +1 -1
- package/dist/react/router/index.js +0 -10
- package/dist/react/router/index.js.map +1 -1
- package/dist/react/ui/index.d.ts +124 -0
- package/dist/react/ui/index.d.ts.map +1 -0
- package/dist/react/ui/index.js +206 -0
- package/dist/react/ui/index.js.map +1 -0
- package/dist/router/index.d.ts +13 -13
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +45 -32
- package/dist/router/index.js.map +1 -1
- package/dist/system/index.d.ts.map +1 -1
- package/dist/system/index.js +1 -0
- package/dist/system/index.js.map +1 -1
- package/dist/topic/core/index.js +1 -1
- package/dist/topic/core/index.js.map +1 -1
- package/package.json +6 -23
- package/src/api/files/jobs/FileJobs.ts +2 -1
- package/src/api/jobs/__tests__/$job.spec.ts +316 -2867
- package/src/api/jobs/controllers/AdminJobController.ts +29 -138
- package/src/api/jobs/entities/jobExecutionEntity.ts +27 -19
- package/src/api/jobs/index.browser.ts +5 -7
- package/src/api/jobs/index.ts +23 -51
- package/src/api/jobs/primitives/$job.ts +66 -58
- package/src/api/jobs/providers/JobProvider.ts +561 -566
- package/src/api/jobs/providers/JobQueueProvider.ts +18 -19
- package/src/api/jobs/schemas/jobConfigAtom.ts +20 -23
- package/src/api/jobs/schemas/jobExecutionQuerySchema.ts +3 -27
- package/src/api/jobs/schemas/jobExecutionResourceSchema.ts +5 -7
- package/src/api/jobs/schemas/jobRegistrationSchema.ts +7 -4
- package/src/api/jobs/schemas/triggerJobSchema.ts +0 -1
- package/src/api/jobs/services/JobService.ts +90 -483
- package/src/api/notifications/controllers/AdminNotificationController.ts +19 -12
- package/src/api/notifications/index.ts +7 -4
- package/src/api/notifications/jobs/NotificationJobs.ts +83 -12
- package/src/api/payments/services/PaymentService.ts +4 -2
- package/src/api/users/__tests__/UserJobs.spec.ts +10 -49
- package/src/api/users/audits/UserAudits.ts +3 -1
- package/src/api/users/buckets/UserBuckets.ts +2 -1
- package/src/api/users/index.ts +1 -4
- package/src/api/users/jobs/UserJobs.ts +5 -4
- package/src/api/verifications/jobs/VerificationJobs.ts +2 -1
- package/src/cli/core/__tests__/init.spec.ts +1 -1
- package/src/cli/core/commands/init.ts +0 -12
- package/src/cli/core/services/PackageManagerUtils.ts +2 -9
- package/src/cli/core/services/ProjectScaffolder.ts +17 -65
- package/src/cli/core/templates/agentMd.ts +2 -8
- package/src/cli/core/templates/apiIndexTs.ts +4 -18
- package/src/cli/core/templates/mainCss.ts +1 -36
- package/src/cli/core/templates/vitestConfigTs.ts +17 -0
- package/src/cli/core/templates/webAppRouterTs.ts +2 -85
- package/src/cli/platform/__tests__/CloudflareAdapter.spec.ts +22 -71
- package/src/cli/platform/adapters/CloudflareAdapter.ts +12 -11
- package/src/cli/platform/atoms/platformOptions.ts +9 -0
- package/src/cli/platform/schemas/cloudflare.ts +3 -2
- package/src/cli/platform/services/CloudflareApi.ts +164 -25
- package/src/cli/platform/services/WranglerApi.ts +0 -17
- package/src/core/Alepha.ts +9 -0
- package/src/react/form/index.ts +2 -0
- package/src/react/form/services/parseField.ts +163 -0
- package/src/react/form/services/prettyName.ts +19 -0
- package/src/react/head/providers/BrowserHeadProvider.ts +31 -10
- package/src/react/router/primitives/$page.ts +35 -12
- package/src/react/ui/atoms/uiAtom.ts +28 -0
- package/src/react/ui/components/ColorScheme.tsx +36 -0
- package/src/react/ui/hooks/useColorMode.ts +49 -0
- package/src/react/ui/hooks/useSidebarState.ts +26 -0
- package/src/react/ui/hooks/useTheme.ts +22 -0
- package/src/react/ui/index.ts +35 -0
- package/src/react/ui/services/UiPersistence.ts +41 -0
- package/src/router/TemplatedPathParser.ts +50 -51
- package/src/router/__tests__/RouterProvider.spec.ts +62 -0
- package/src/router/__tests__/TemplatedPathParser.spec.ts +18 -0
- package/src/router/providers/RouterProvider.ts +10 -5
- package/src/system/providers/NodeShellProvider.ts +1 -0
- package/src/topic/core/providers/TopicProvider.ts +1 -1
- package/dist/api/invitations/index.d.ts +0 -790
- package/dist/api/invitations/index.d.ts.map +0 -1
- package/dist/api/invitations/index.js +0 -662
- package/dist/api/invitations/index.js.map +0 -1
- package/dist/api/issues/index.d.ts +0 -810
- package/dist/api/issues/index.d.ts.map +0 -1
- package/dist/api/issues/index.js +0 -444
- package/dist/api/issues/index.js.map +0 -1
- package/dist/api/subscriptions/index.d.ts +0 -1692
- package/dist/api/subscriptions/index.d.ts.map +0 -1
- package/dist/api/subscriptions/index.js +0 -1867
- package/dist/api/subscriptions/index.js.map +0 -1
- package/dist/api/workflows/index.browser.js +0 -246
- package/dist/api/workflows/index.browser.js.map +0 -1
- package/dist/api/workflows/index.d.ts +0 -1618
- package/dist/api/workflows/index.d.ts.map +0 -1
- package/dist/api/workflows/index.js +0 -1495
- package/dist/api/workflows/index.js.map +0 -1
- package/src/api/invitations/__tests__/InvitationService.spec.ts +0 -439
- package/src/api/invitations/controllers/AdminInvitationController.ts +0 -86
- package/src/api/invitations/controllers/InvitationController.ts +0 -84
- package/src/api/invitations/entities/invitations.ts +0 -33
- package/src/api/invitations/index.ts +0 -58
- package/src/api/invitations/jobs/InvitationJobs.ts +0 -37
- package/src/api/invitations/providers/InvitationProvider.ts +0 -45
- package/src/api/invitations/schemas/createInvitationSchema.ts +0 -12
- package/src/api/invitations/schemas/invitationConfigAtom.ts +0 -20
- package/src/api/invitations/schemas/invitationQuerySchema.ts +0 -15
- package/src/api/invitations/schemas/invitationResourceSchema.ts +0 -6
- package/src/api/invitations/schemas/invitationWithResourceInfoSchema.ts +0 -22
- package/src/api/invitations/schemas/myInvitationsQuerySchema.ts +0 -10
- package/src/api/invitations/services/InvitationService.ts +0 -556
- package/src/api/issues/__tests__/IssueService.spec.ts +0 -263
- package/src/api/issues/controllers/AdminIssueController.ts +0 -149
- package/src/api/issues/controllers/IssueController.ts +0 -44
- package/src/api/issues/entities/issues.ts +0 -49
- package/src/api/issues/index.ts +0 -50
- package/src/api/issues/schemas/createIssueSchema.ts +0 -13
- package/src/api/issues/schemas/issueConfigAtom.ts +0 -13
- package/src/api/issues/schemas/issueQuerySchema.ts +0 -18
- package/src/api/issues/schemas/issueResourceSchema.ts +0 -6
- package/src/api/issues/schemas/myIssueQuerySchema.ts +0 -10
- package/src/api/issues/schemas/updateIssueSchema.ts +0 -13
- package/src/api/issues/services/IssueService.ts +0 -264
- package/src/api/jobs/__tests__/$job-middleware.spec.ts +0 -126
- package/src/api/jobs/__tests__/JobService.spec.ts +0 -31
- package/src/api/jobs/entities/jobExecutionLogEntity.ts +0 -13
- package/src/api/jobs/schemas/jobActivitySchema.ts +0 -15
- package/src/api/jobs/schemas/jobCronInfoSchema.ts +0 -22
- package/src/api/jobs/schemas/jobExecutionDetailResourceSchema.ts +0 -20
- package/src/api/jobs/schemas/jobFailureSchema.ts +0 -9
- package/src/api/jobs/schemas/jobQueueDepthSchema.ts +0 -14
- package/src/api/jobs/schemas/jobStatsSchema.ts +0 -14
- package/src/api/jobs/services/JobService-tests.ts +0 -157
- package/src/api/subscriptions/__tests__/BillingService.spec.ts +0 -218
- package/src/api/subscriptions/__tests__/SubscriptionService.spec.ts +0 -278
- package/src/api/subscriptions/controllers/AdminSubscriptionController.ts +0 -212
- package/src/api/subscriptions/controllers/SubscriptionController.ts +0 -189
- package/src/api/subscriptions/entities/subscriptionEvents.ts +0 -54
- package/src/api/subscriptions/entities/subscriptions.ts +0 -68
- package/src/api/subscriptions/index.ts +0 -133
- package/src/api/subscriptions/jobs/SubscriptionJobs.ts +0 -382
- package/src/api/subscriptions/middleware/$requireLimit.ts +0 -50
- package/src/api/subscriptions/middleware/$requirePlan.ts +0 -49
- package/src/api/subscriptions/notifications/SubscriptionNotifications.ts +0 -110
- package/src/api/subscriptions/schemas/cancelSubscriptionSchema.ts +0 -8
- package/src/api/subscriptions/schemas/changePlanSchema.ts +0 -9
- package/src/api/subscriptions/schemas/createSubscriptionSchema.ts +0 -11
- package/src/api/subscriptions/schemas/entitlementsSchema.ts +0 -21
- package/src/api/subscriptions/schemas/mrrSchema.ts +0 -13
- package/src/api/subscriptions/schemas/planDefinitionSchema.ts +0 -71
- package/src/api/subscriptions/schemas/planResourceSchema.ts +0 -25
- package/src/api/subscriptions/schemas/subscriptionEventResourceSchema.ts +0 -8
- package/src/api/subscriptions/schemas/subscriptionQuerySchema.ts +0 -19
- package/src/api/subscriptions/schemas/subscriptionResourceSchema.ts +0 -6
- package/src/api/subscriptions/schemas/subscriptionSettingsSchema.ts +0 -32
- package/src/api/subscriptions/schemas/subscriptionStatsSchema.ts +0 -23
- package/src/api/subscriptions/services/BillingService.ts +0 -437
- package/src/api/subscriptions/services/SubscriptionConfig.ts +0 -56
- package/src/api/subscriptions/services/SubscriptionService.ts +0 -867
- package/src/api/subscriptions/services/UsageService.ts +0 -118
- package/src/api/workflows/__tests__/$workflow.spec.ts +0 -616
- package/src/api/workflows/controllers/AdminWorkflowController.ts +0 -191
- package/src/api/workflows/entities/workflowExecutions.ts +0 -74
- package/src/api/workflows/entities/workflowStepExecutions.ts +0 -74
- package/src/api/workflows/entities/workflowStepLogs.ts +0 -13
- package/src/api/workflows/index.browser.ts +0 -22
- package/src/api/workflows/index.ts +0 -115
- package/src/api/workflows/jobs/WorkflowJobs.ts +0 -77
- package/src/api/workflows/primitives/$workflow.ts +0 -202
- package/src/api/workflows/providers/WorkflowProvider.ts +0 -1284
- package/src/api/workflows/schemas/workflowActivitySchema.ts +0 -15
- package/src/api/workflows/schemas/workflowConfigAtom.ts +0 -51
- package/src/api/workflows/schemas/workflowExecutionDetailSchema.ts +0 -18
- package/src/api/workflows/schemas/workflowExecutionQuerySchema.ts +0 -26
- package/src/api/workflows/schemas/workflowExecutionResourceSchema.ts +0 -30
- package/src/api/workflows/schemas/workflowRegistrationSchema.ts +0 -26
- package/src/api/workflows/schemas/workflowStatsSchema.ts +0 -16
- package/src/api/workflows/schemas/workflowStepExecutionResourceSchema.ts +0 -15
- package/src/api/workflows/services/WorkflowService.ts +0 -382
- package/src/cli/core/templates/apiAppSecurityTs.ts +0 -43
- package/src/cli/core/templates/webAdminDashboardTsx.ts +0 -17
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/api/payments/entities/paymentIntents.ts","../../../src/api/payments/schemas/intentSchemas.ts","../../../src/api/payments/entities/refunds.ts","../../../src/api/payments/schemas/refundSchemas.ts","../../../src/api/payments/errors/PaymentError.ts","../../../src/api/payments/providers/PaymentProvider.ts","../../../src/api/payments/services/PaymentService.ts","../../../src/api/payments/controllers/AdminPaymentController.ts","../../../src/api/payments/entities/paymentMethods.ts","../../../src/api/payments/schemas/paymentMethodSchemas.ts","../../../src/api/payments/services/PaymentMethodService.ts","../../../src/api/payments/controllers/PaymentController.ts","../../../src/api/payments/providers/MemoryPaymentProvider.ts","../../../src/api/payments/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 \"partially_refunded\",\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 PaymentError 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 PaymentProvider {\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 and verify an incoming PSP webhook request.\n *\n * Implementations MUST verify the webhook signature before returning.\n * Throw an error if the signature is invalid or missing — this is the\n * only authentication on the webhook endpoint (no $secure middleware).\n *\n * Failure to verify signatures allows attackers to forge payment\n * confirmations by POSTing fake webhook events.\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 { PaymentError } from \"../errors/PaymentError.ts\";\nimport { PaymentProvider } from \"../providers/PaymentProvider.ts\";\n\nexport class PaymentService {\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n protected readonly dateTime = $inject(DateTimeProvider);\n protected readonly provider = $inject(PaymentProvider);\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: currency.toLowerCase(),\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 userId?: string,\n ): Promise<{ url: string; intentId: string }> {\n const intent = await this.getIntent(intentId);\n this.assertStatus(intent, \"created\", \"createSession\");\n\n // Verify intent ownership if userId is provided\n if (userId && intent.userId && intent.userId !== userId) {\n throw new PaymentError(\"Payment intent does not belong to this user\");\n }\n\n // Associate intent with user if not already set\n if (userId && !intent.userId) {\n await this.intentRepo.updateById(intent.id, { userId });\n }\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 payment event.\n */\n /**\n * Valid status transitions from webhook events.\n * Only these transitions are allowed — all others are silently ignored.\n */\n protected static readonly VALID_WEBHOOK_TRANSITIONS: Record<\n string,\n string[]\n > = {\n processing: [\"authorized\", \"captured\", \"failed\"],\n authorized: [\"captured\", \"failed\"],\n };\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: \"payments:authorized\",\n captured: \"payments:captured\",\n failed: \"payments: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 // Validate status transition\n const allowed = PaymentService.VALID_WEBHOOK_TRANSITIONS[intent.status];\n if (!allowed?.includes(webhookStatus)) {\n this.log.warn(\n `Ignoring webhook: cannot transition ${intent.status} → ${webhookStatus}`,\n { intentId: intent.id },\n );\n return;\n }\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 (amount > intent.amount) {\n throw new PaymentError(\n `Capture amount ${amount} exceeds authorized amount ${intent.amount}`,\n );\n }\n\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(\"payments: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(\"payments: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\n // Allow refunds from both \"captured\" and \"partially_refunded\" states\n if (\n intent.status !== \"captured\" &&\n intent.status !== \"partially_refunded\"\n ) {\n throw new PaymentError(\n `Cannot refund: intent ${intent.id} is '${intent.status}', expected 'captured' or 'partially_refunded'`,\n );\n }\n\n // Validate refund amount against remaining refundable amount\n const existingRefunds = await this.refundRepo.findMany({\n where: { intentId: { eq: intent.id } },\n });\n const totalRefunded = existingRefunds.reduce((sum, r) => sum + r.amount, 0);\n const remaining = intent.amount - totalRefunded;\n\n if (amount > remaining) {\n throw new PaymentError(\n `Refund amount ${amount} exceeds remaining refundable amount ${remaining}`,\n );\n }\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 // Set status based on whether fully or partially refunded\n const newTotalRefunded = totalRefunded + amount;\n const newStatus =\n newTotalRefunded >= intent.amount ? \"refunded\" : \"partially_refunded\";\n await this.intentRepo.updateById(intent.id, {\n status: newStatus,\n });\n\n await this.alepha.events.emit(\"payments: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: currency.toLowerCase(),\n status: \"captured\",\n metadata: metadata as any,\n });\n\n await this.alepha.events.emit(\"payments: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 const cancelled = await this.intentRepo.updateById(intent.id, {\n status: \"cancelled\",\n });\n\n await this.alepha.events.emit(\"payments:cancelled\", {\n intentId: intent.id,\n amount: intent.amount,\n currency: intent.currency,\n metadata: intent.metadata,\n });\n\n return cancelled;\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 PaymentError(\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 { PaymentService } from \"../services/PaymentService.ts\";\n\nexport class AdminPaymentController {\n protected readonly url = \"/admin/payments\";\n protected readonly group = \"admin:payments\";\n protected readonly payments = $inject(PaymentService);\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: [\"payments:read\"] })],\n description: \"List payment intents\",\n schema: {\n query: intentQuerySchema,\n response: t.page(intentResourceSchema),\n },\n handler: ({ query }) => this.payments.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: [\"payments:read\"] })],\n description: \"Get payment intent details\",\n schema: {\n params: t.object({ id: t.uuid() }),\n response: intentResourceSchema,\n },\n handler: ({ params }) => this.payments.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: [\"payments: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 }) =>\n this.payments.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: [\"payments: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.payments.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: [\"payments: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.payments.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: [\"payments: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.payments.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: [\"payments:write\"] })],\n description: \"Record a cash payment\",\n schema: {\n body: recordCashSchema,\n response: intentResourceSchema,\n },\n handler: ({ body }) =>\n this.payments.recordCashPayment(\n body.amount,\n body.currency,\n body.metadata,\n ),\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: \"/payments/webhook\",\n group: this.group,\n description: \"PSP webhook endpoint\",\n schema: {\n response: okSchema,\n },\n handler: async (request) => {\n await this.payments.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 { PaymentError } from \"../errors/PaymentError.ts\";\nimport { PaymentProvider } from \"../providers/PaymentProvider.ts\";\n\nexport class PaymentMethodService {\n protected readonly log = $logger();\n protected readonly provider = $inject(PaymentProvider);\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 PaymentError(\"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 PaymentError(\"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 { PaymentError } from \"../errors/PaymentError.ts\";\nimport {\n checkoutResponseSchema,\n createCheckoutSchema,\n} from \"../schemas/intentSchemas.ts\";\nimport {\n addPaymentMethodSchema,\n paymentMethodResourceSchema,\n} from \"../schemas/paymentMethodSchemas.ts\";\nimport { PaymentMethodService } from \"../services/PaymentMethodService.ts\";\nimport { PaymentService } from \"../services/PaymentService.ts\";\n\nexport class PaymentController {\n protected readonly url = \"/payments\";\n protected readonly group = \"payments\";\n protected readonly payments = $inject(PaymentService);\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 if (!user.organization) {\n throw new PaymentError(\n \"Organization is required to add a payment method\",\n );\n }\n return this.paymentMethods.addPaymentMethod(\n user.id,\n user.organization,\n body.token,\n );\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, user }) =>\n this.payments.createSession(\n body.intentId,\n body.returnUrl,\n body.authorize,\n user.id,\n ),\n });\n}\n","import { randomUUID } from \"node:crypto\";\nimport type { PaymentIntentEntity } from \"../entities/paymentIntents.ts\";\nimport type {\n CreatePaymentMethodResult,\n CreateSessionResult,\n PaymentProvider,\n RefundResult,\n WebhookEvent,\n} from \"./PaymentProvider.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 MemoryPaymentProvider implements PaymentProvider {\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: `/payments/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 { AdminPaymentController } from \"./controllers/AdminPaymentController.ts\";\nimport { PaymentController } from \"./controllers/PaymentController.ts\";\nimport { MemoryPaymentProvider } from \"./providers/MemoryPaymentProvider.ts\";\nimport { PaymentProvider } from \"./providers/PaymentProvider.ts\";\nimport { PaymentMethodService } from \"./services/PaymentMethodService.ts\";\nimport { PaymentService } from \"./services/PaymentService.ts\";\n\nexport * from \"./controllers/AdminPaymentController.ts\";\nexport * from \"./controllers/PaymentController.ts\";\nexport * from \"./entities/paymentIntents.ts\";\nexport * from \"./entities/paymentMethods.ts\";\nexport * from \"./entities/refunds.ts\";\nexport * from \"./errors/PaymentError.ts\";\nexport * from \"./providers/MemoryPaymentProvider.ts\";\nexport * from \"./providers/PaymentProvider.ts\";\nexport * from \"./schemas/intentSchemas.ts\";\nexport * from \"./schemas/paymentMethodSchemas.ts\";\nexport * from \"./schemas/refundSchemas.ts\";\nexport * from \"./services/PaymentMethodService.ts\";\nexport * from \"./services/PaymentService.ts\";\n\ndeclare module \"alepha\" {\n interface Hooks {\n \"payments:authorized\": {\n intentId: string;\n amount: number;\n currency: string;\n metadata?: unknown;\n };\n \"payments:captured\": {\n intentId: string;\n amount: number;\n currency: string;\n metadata?: unknown;\n };\n \"payments:failed\": {\n intentId: string;\n amount: number;\n currency: string;\n metadata?: unknown;\n };\n \"payments:voided\": {\n intentId: string;\n amount: number;\n currency: string;\n metadata?: unknown;\n };\n \"payments:refunded\": {\n intentId: string;\n refundId: string;\n amount: number;\n currency: string;\n metadata?: unknown;\n };\n \"payments:cancelled\": {\n intentId: string;\n amount: number;\n currency: string;\n metadata?: unknown;\n };\n }\n}\n\nexport const AlephaApiPayments = $module({\n name: \"alepha.api.payments\",\n services: [\n AdminPaymentController,\n PaymentController,\n PaymentProvider,\n PaymentService,\n PaymentMethodService,\n ],\n variants: [MemoryPaymentProvider],\n register: (alepha) => {\n alepha.with({\n optional: true,\n provide: PaymentProvider,\n use: MemoryPaymentProvider,\n });\n },\n});\n"],"mappings":";;;;;;;;;AAGA,MAAa,iBAAiB,QAAQ;CACpC,MAAM;CACN,QAAQ,EAAE,OAAO;EACf,IAAI,GAAG,WAAW,EAAE,MAAM,CAAC;EAC3B,SAAS,GAAG,SAAS;EACrB,WAAW,GAAG,WAAW;EACzB,WAAW,GAAG,WAAW;EACzB,gBAAgB,GAAG,cAAc;EACjC,QAAQ,EAAE,SAAS;EACnB,UAAU,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;EACnC,QAAQ,EAAE,KAAK;GACb;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD,CAAC;EACF,aAAa,EAAE,SAAS,EAAE,MAAM,CAAC;EACjC,aAAa,EAAE,SAAS,EAAE,MAAM,CAAC;EACjC,UAAU,EAAE,SAAS,EAAE,MAAM,CAAC;EAC9B,iBAAiB,EAAE,SAAS,EAAE,MAAM,CAAC;EACrC,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC;EAC7B,CAAC;CACF,SAAS;EAAC;EAAU;EAAkB;EAAU;EAAY;CAC7D,CAAC;;;AC3BF,MAAa,qBAAqB,EAAE,OAAO;CACzC,QAAQ,EAAE,QAAQ,EAAE,SAAS,GAAG,CAAC;CACjC,UAAU,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;CACnC,UAAU,EAAE,SAAS,EAAE,MAAM,CAAC;CAC9B,iBAAiB,EAAE,SAAS,EAAE,MAAM,CAAC;CACtC,CAAC;AAIF,MAAa,uBAAuB,EAAE,OAAO;CAC3C,UAAU,EAAE,MAAM;CAClB,WAAW,EAAE,MAAM;CACnB,WAAW,EAAE,SAAS,EAAE,SAAS,CAAC;CACnC,CAAC;AAIF,MAAa,yBAAyB,EAAE,OAAO;CAC7C,KAAK,EAAE,MAAM;CACb,UAAU,EAAE,MAAM;CACnB,CAAC;AAIF,MAAa,sBAAsB,EAAE,OAAO,EAC1C,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,GAAG,CAAC,CAAC,EAC9C,CAAC;AAIF,MAAa,qBAAqB,EAAE,OAAO;CACzC,QAAQ,EAAE,QAAQ,EAAE,SAAS,GAAG,CAAC;CACjC,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC;CAC7B,CAAC;AAIF,MAAa,mBAAmB,EAAE,OAAO;CACvC,QAAQ,EAAE,QAAQ,EAAE,SAAS,GAAG,CAAC;CACjC,UAAU,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;CACnC,UAAU,EAAE,SAAS,EAAE,MAAM,CAAC;CAC/B,CAAC;AAIF,MAAa,oBAAoB,EAAE,OAAO,iBAAiB;CACzD,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,oBAAoB,CAAC,CAAC;CAC/D,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,qBAAqB,CAAC,CAAC;CACjE,CAAC;AAIF,MAAa,uBAAuB,eAAe;;;ACtDnD,MAAa,UAAU,QAAQ;CAC7B,MAAM;CACN,QAAQ,EAAE,OAAO;EACf,IAAI,GAAG,WAAW,EAAE,MAAM,CAAC;EAC3B,SAAS,GAAG,SAAS;EACrB,WAAW,GAAG,WAAW;EACzB,WAAW,GAAG,WAAW;EACzB,gBAAgB,GAAG,cAAc;EACjC,UAAU,EAAE,MAAM;EAClB,QAAQ,EAAE,SAAS;EACnB,UAAU,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;EACnC,QAAQ,EAAE,KAAK;GAAC;GAAW;GAAc;GAAa;GAAS,CAAC;EAChE,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC;EAC5B,aAAa,EAAE,SAAS,EAAE,MAAM,CAAC;EAClC,CAAC;CACF,SAAS;EAAC;EAAY;EAAkB;EAAS;CAClD,CAAC;;;AChBF,MAAa,uBAAuB,QAAQ;;;ACD5C,IAAa,eAAb,cAAkC,YAAY;CAC5C,SAAyB;;;;ACuB3B,IAAsB,kBAAtB,MAAsC;;;ACbtC,IAAa,iBAAb,MAAa,eAAe;CAC1B,SAA4B,QAAQ,OAAO;CAC3C,MAAyB,SAAS;CAClC,WAA8B,QAAQ,iBAAiB;CACvD,WAA8B,QAAQ,gBAAgB;CACtD,aAAgC,YAAY,eAAe;CAC3D,aAAgC,YAAY,QAAQ;;;;;CAMpD,qBAAwC,KAAK;EAC3C,MAAM;EACN,SAAS,YAAY;GACnB,MAAM,SAAS,KAAK,SAAS,KAAK,CAAC,SAAS,IAAI,UAAU,CAAC,aAAa;GAExE,MAAM,QAAQ,MAAM,KAAK,WAAW,SAAS,EAC3C,OAAO;IAAE,QAAQ,EAAE,IAAI,cAAc;IAAE,WAAW,EAAE,IAAI,QAAQ;IAAE,EACnE,CAAC;AAEF,QAAK,MAAM,UAAU,OAAO;AAC1B,QAAI,OAAO,YACT,KAAI;AACF,WAAM,KAAK,SAAS,cAAc,OAAO,YAAY;aAC9C,OAAO;AACd,UAAK,IAAI,KACP,uCAAuC,OAAO,MAC9C,MACD;;AAGL,UAAM,KAAK,WAAW,WAAW,OAAO,IAAI,EAAE,QAAQ,WAAW,CAAC;AAClE,SAAK,IAAI,KAAK,wBAAwB,OAAO,KAAK;;;EAGvD,CAAC;;;;CAKF,MAAa,aACX,QACA,UACA,UACA,SAC8B;AAC9B,SAAO,MAAM,KAAK,WAAW,OAAO;GAClC;GACA,UAAU,SAAS,aAAa;GAChC,QAAQ;GACE;GACV,iBAAiB,SAAS;GAC1B,QAAQ,SAAS;GAClB,CAAC;;;;;;CAOJ,MAAa,cACX,UACA,WACA,WACA,QAC4C;EAC5C,MAAM,SAAS,MAAM,KAAK,UAAU,SAAS;AAC7C,OAAK,aAAa,QAAQ,WAAW,gBAAgB;AAGrD,MAAI,UAAU,OAAO,UAAU,OAAO,WAAW,OAC/C,OAAM,IAAI,aAAa,8CAA8C;AAIvE,MAAI,UAAU,CAAC,OAAO,OACpB,OAAM,KAAK,WAAW,WAAW,OAAO,IAAI,EAAE,QAAQ,CAAC;EAGzD,MAAM,SAAS,MAAM,KAAK,SAAS,cAAc,QAAQ;GACvD;GACA;GACD,CAAC;AAEF,QAAM,KAAK,WAAW,WAAW,OAAO,IAAI;GAC1C,QAAQ;GACR,aAAa,OAAO;GACrB,CAAC;AAEF,SAAO;GAAE,KAAK,OAAO;GAAK,UAAU,OAAO;GAAI;;;;;CAMjD,MAAa,cAAc,SAAiC;EAC1D,MAAM,QAAQ,MAAM,KAAK,SAAS,aAAa,QAAQ;EACvD,MAAM,UAAU,MAAM,KAAK,WAAW,SAAS;GAC7C,OAAO,EAAE,aAAa,EAAE,IAAI,MAAM,aAAa,EAAE;GACjD,OAAO;GACR,CAAC;AAEF,MAAI,QAAQ,WAAW,GAAG;AACxB,QAAK,IAAI,KAAK,oCAAoC,MAAM,cAAc;AACtE;;EAGF,MAAM,SAAS,QAAQ;AACvB,QAAM,KAAK,mBAAmB,OAAO,IAAI,MAAM,QAAQ,MAAM,IAAI;;;;;;;;;;CAWnE,OAA0B,4BAGtB;EACF,YAAY;GAAC;GAAc;GAAY;GAAS;EAChD,YAAY,CAAC,YAAY,SAAS;EACnC;CAED,MAAa,mBACX,UACA,QACA,KACe;EACf,MAAM,SAAS,MAAM,KAAK,UAAU,SAAS;EAE7C,MAAM,WAAW;GACf,YAAY;GACZ,UAAU;GACV,QAAQ;GACT;AAGD,MAAI,EAAE,UAAU,WAAW;AACzB,QAAK,IAAI,KAAK,2BAA2B,SAAS;AAClD;;EAGF,MAAM,gBAAgB;AAItB,MAAI,CADY,eAAe,0BAA0B,OAAO,SAClD,SAAS,cAAc,EAAE;AACrC,QAAK,IAAI,KACP,uCAAuC,OAAO,OAAO,KAAK,iBAC1D,EAAE,UAAU,OAAO,IAAI,CACxB;AACD;;AAGF,QAAM,KAAK,WAAW,WAAW,OAAO,IAAI;GAC1C,QAAQ;GACR,aAAa;GACd,CAAC;AAEF,QAAM,KAAK,OAAO,OAAO,KAAK,SAAS,gBAAgB;GACrD,UAAU,OAAO;GACjB,QAAQ,OAAO;GACf,UAAU,OAAO;GACjB,UAAU,OAAO;GAClB,CAAC;;;;;;CAOJ,MAAa,QACX,UACA,aAC8B;EAC9B,MAAM,SAAS,MAAM,KAAK,UAAU,SAAS;AAC7C,OAAK,aAAa,QAAQ,cAAc,UAAU;EAElD,MAAM,SAAS,eAAe,OAAO;AACrC,MAAI,SAAS,OAAO,OAClB,OAAM,IAAI,aACR,kBAAkB,OAAO,6BAA6B,OAAO,SAC9D;AAGH,MAAI,OAAO,YACT,OAAM,KAAK,SAAS,eAAe,OAAO,aAAa,OAAO;EAGhE,MAAM,UAAU,MAAM,KAAK,WAAW,WAAW,OAAO,IAAI;GAC1D,QAAQ;GACR;GACD,CAAC;AAEF,QAAM,KAAK,OAAO,OAAO,KAAK,qBAAqB;GACjD,UAAU,OAAO;GACjB;GACA,UAAU,OAAO;GACjB,UAAU,OAAO;GAClB,CAAC;AAEF,SAAO;;;;;CAMT,MAAa,KAAK,UAAgD;EAChE,MAAM,SAAS,MAAM,KAAK,UAAU,SAAS;AAC7C,OAAK,aAAa,QAAQ,cAAc,OAAO;AAE/C,MAAI,OAAO,YACT,OAAM,KAAK,SAAS,YAAY,OAAO,YAAY;EAGrD,MAAM,UAAU,MAAM,KAAK,WAAW,WAAW,OAAO,IAAI,EAC1D,QAAQ,UACT,CAAC;AAEF,QAAM,KAAK,OAAO,OAAO,KAAK,mBAAmB;GAC/C,UAAU,OAAO;GACjB,QAAQ,OAAO;GACf,UAAU,OAAO;GACjB,UAAU,OAAO;GAClB,CAAC;AAEF,SAAO;;;;;CAMT,MAAa,OACX,UACA,QACA,QACuB;EACvB,MAAM,SAAS,MAAM,KAAK,UAAU,SAAS;AAG7C,MACE,OAAO,WAAW,cAClB,OAAO,WAAW,qBAElB,OAAM,IAAI,aACR,yBAAyB,OAAO,GAAG,OAAO,OAAO,OAAO,gDACzD;EAOH,MAAM,iBAHkB,MAAM,KAAK,WAAW,SAAS,EACrD,OAAO,EAAE,UAAU,EAAE,IAAI,OAAO,IAAI,EAAE,EACvC,CAAC,EACoC,QAAQ,KAAK,MAAM,MAAM,EAAE,QAAQ,EAAE;EAC3E,MAAM,YAAY,OAAO,SAAS;AAElC,MAAI,SAAS,UACX,OAAM,IAAI,aACR,iBAAiB,OAAO,uCAAuC,YAChE;EAGH,IAAI;AACJ,MAAI,OAAO,YAKT,sBAJe,MAAM,KAAK,SAAS,cACjC,OAAO,aACP,OACD,EAC0B;EAG7B,MAAM,SAAS,MAAM,KAAK,WAAW,OAAO;GAC1C,UAAU,OAAO;GACjB,gBAAgB,OAAO;GACvB;GACA,UAAU,OAAO;GACjB,QAAQ;GACR;GACA,aAAa;GACd,CAAC;EAIF,MAAM,YADmB,gBAAgB,UAEnB,OAAO,SAAS,aAAa;AACnD,QAAM,KAAK,WAAW,WAAW,OAAO,IAAI,EAC1C,QAAQ,WACT,CAAC;AAEF,QAAM,KAAK,OAAO,OAAO,KAAK,qBAAqB;GACjD,UAAU,OAAO;GACjB,UAAU,OAAO;GACjB;GACA,UAAU,OAAO;GACjB,UAAU,OAAO;GAClB,CAAC;AAEF,SAAO;;;;;;CAOT,MAAa,kBACX,QACA,UACA,UAC8B;EAC9B,MAAM,SAAS,MAAM,KAAK,WAAW,OAAO;GAC1C;GACA,UAAU,SAAS,aAAa;GAChC,QAAQ;GACE;GACX,CAAC;AAEF,QAAM,KAAK,OAAO,OAAO,KAAK,qBAAqB;GACjD,UAAU,OAAO;GACjB;GACA;GACA;GACD,CAAC;AAEF,SAAO;;;;;CAMT,MAAa,OAAO,UAAgD;EAClE,MAAM,SAAS,MAAM,KAAK,UAAU,SAAS;AAC7C,OAAK,aAAa,QAAQ,WAAW,SAAS;EAE9C,MAAM,YAAY,MAAM,KAAK,WAAW,WAAW,OAAO,IAAI,EAC5D,QAAQ,aACT,CAAC;AAEF,QAAM,KAAK,OAAO,OAAO,KAAK,sBAAsB;GAClD,UAAU,OAAO;GACjB,QAAQ,OAAO;GACf,UAAU,OAAO;GACjB,UAAU,OAAO;GAClB,CAAC;AAEF,SAAO;;;;;CAMT,MAAa,UAAU,UAAgD;AACrE,SAAO,MAAM,KAAK,WAAW,QAAQ,SAAS;;;;;CAMhD,MAAa,YAAY,OAMtB;EACD,MAAM,QAAQ,KAAK,WAAW,kBAAkB;AAChD,MAAI,MAAM,OACR,OAAM,SAAS,EAAE,IAAI,MAAM,QAAyC;AACtE,MAAI,MAAM,OAAQ,OAAM,SAAS,EAAE,IAAI,MAAM,QAAQ;AACrD,SAAO,MAAM,KAAK,WAAW,SAAS,OAAO,EAAE,OAAO,EAAE,EAAE,OAAO,MAAM,CAAC;;CAG1E,aACE,QACA,UACA,WACM;AACN,MAAI,OAAO,WAAW,SACpB,OAAM,IAAI,aACR,UAAU,UAAU,WAAW,OAAO,GAAG,OAAO,OAAO,OAAO,eAAe,SAAS,GACvF;;;;;AChYP,IAAa,yBAAb,MAAoC;CAClC,MAAyB;CACzB,QAA2B;CAC3B,WAA8B,QAAQ,eAAe;;;;CAKrD,cAA8B,QAAQ;EACpC,MAAM,GAAG,KAAK,IAAI;EAClB,OAAO,KAAK;EACZ,KAAK,CAAC,QAAQ,EAAE,aAAa,CAAC,gBAAgB,EAAE,CAAC,CAAC;EAClD,aAAa;EACb,QAAQ;GACN,OAAO;GACP,UAAU,EAAE,KAAK,qBAAqB;GACvC;EACD,UAAU,EAAE,YAAY,KAAK,SAAS,YAAY,MAAM;EACzD,CAAC;;;;CAKF,YAA4B,QAAQ;EAClC,MAAM,GAAG,KAAK,IAAI;EAClB,OAAO,KAAK;EACZ,KAAK,CAAC,QAAQ,EAAE,aAAa,CAAC,gBAAgB,EAAE,CAAC,CAAC;EAClD,aAAa;EACb,QAAQ;GACN,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;GAClC,UAAU;GACX;EACD,UAAU,EAAE,aAAa,KAAK,SAAS,UAAU,OAAO,GAAG;EAC5D,CAAC;;;;CAKF,gBAAgC,QAAQ;EACtC,QAAQ;EACR,MAAM,GAAG,KAAK,IAAI;EAClB,OAAO,KAAK;EACZ,KAAK,CAAC,QAAQ,EAAE,aAAa,CAAC,iBAAiB,EAAE,CAAC,CAAC;EACnD,aAAa;EACb,QAAQ;GACN,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;GAClC,MAAM;GACN,UAAU;GACX;EACD,UAAU,EAAE,QAAQ,WAClB,KAAK,SAAS,QAAQ,OAAO,IAAI,KAAK,OAAO;EAChD,CAAC;;;;CAKF,aAA6B,QAAQ;EACnC,QAAQ;EACR,MAAM,GAAG,KAAK,IAAI;EAClB,OAAO,KAAK;EACZ,KAAK,CAAC,QAAQ,EAAE,aAAa,CAAC,iBAAiB,EAAE,CAAC,CAAC;EACnD,aAAa;EACb,QAAQ;GACN,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;GAClC,UAAU;GACX;EACD,UAAU,EAAE,aAAa,KAAK,SAAS,KAAK,OAAO,GAAG;EACvD,CAAC;;;;CAKF,eAA+B,QAAQ;EACrC,QAAQ;EACR,MAAM,GAAG,KAAK,IAAI;EAClB,OAAO,KAAK;EACZ,KAAK,CAAC,QAAQ,EAAE,aAAa,CAAC,iBAAiB,EAAE,CAAC,CAAC;EACnD,aAAa;EACb,QAAQ;GACN,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;GAClC,MAAM;GACN,UAAU;GACX;EACD,UAAU,EAAE,QAAQ,WAClB,KAAK,SAAS,OAAO,OAAO,IAAI,KAAK,QAAQ,KAAK,OAAO;EAC5D,CAAC;;;;CAKF,eAA+B,QAAQ;EACrC,QAAQ;EACR,MAAM,GAAG,KAAK,IAAI;EAClB,OAAO,KAAK;EACZ,KAAK,CAAC,QAAQ,EAAE,aAAa,CAAC,iBAAiB,EAAE,CAAC,CAAC;EACnD,aAAa;EACb,QAAQ;GACN,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;GAClC,UAAU;GACX;EACD,UAAU,EAAE,aAAa,KAAK,SAAS,OAAO,OAAO,GAAG;EACzD,CAAC;;;;CAKF,aAA6B,QAAQ;EACnC,QAAQ;EACR,MAAM,GAAG,KAAK,IAAI;EAClB,OAAO,KAAK;EACZ,KAAK,CAAC,QAAQ,EAAE,aAAa,CAAC,iBAAiB,EAAE,CAAC,CAAC;EACnD,aAAa;EACb,QAAQ;GACN,MAAM;GACN,UAAU;GACX;EACD,UAAU,EAAE,WACV,KAAK,SAAS,kBACZ,KAAK,QACL,KAAK,UACL,KAAK,SACN;EACJ,CAAC;;;;CAKF,UAA0B,QAAQ;EAChC,QAAQ;EACR,MAAM;EACN,OAAO,KAAK;EACZ,aAAa;EACb,QAAQ,EACN,UAAU,UACX;EACD,SAAS,OAAO,YAAY;AAC1B,SAAM,KAAK,SAAS,cAAc,QAAQ,IAAI,IAAK,IAAI;AACvD,UAAO,EAAE,IAAI,MAAM;;EAEtB,CAAC;;;;ACrJJ,MAAa,iBAAiB,QAAQ;CACpC,MAAM;CACN,QAAQ,EAAE,OAAO;EACf,IAAI,GAAG,WAAW,EAAE,MAAM,CAAC;EAC3B,SAAS,GAAG,SAAS;EACrB,WAAW,GAAG,WAAW;EACzB,WAAW,GAAG,WAAW;EACzB,gBAAgB,GAAG,cAAc;EACjC,QAAQ,EAAE,MAAM;EAChB,MAAM,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;EAC/B,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC,CAAC;EAC5C,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC,CAAC;EAC5C,UAAU,EAAE,SAAS,EAAE,SAAS,CAAC;EACjC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC;EAChC,WAAW,EAAE,SAAS;EACtB,aAAa,EAAE,MAAM;EACtB,CAAC;CACF,SAAS,CAAC,UAAU,iBAAiB;CACtC,CAAC;;;ACjBF,MAAa,yBAAyB,EAAE,OAAO,EAC7C,OAAO,EAAE,MAAM,EAChB,CAAC;AAIF,MAAa,8BAA8B,eAAe;;;ACA1D,IAAa,uBAAb,MAAkC;CAChC,MAAyB,SAAS;CAClC,WAA8B,QAAQ,gBAAgB;CACtD,aAAgC,YAAY,eAAe;CAE3D,MAAa,iBACX,QACA,gBACA,OAC8B;EAC9B,MAAM,SAAS,MAAM,KAAK,SAAS,oBAAoB,QAAQ,MAAM;EAErE,MAAM,WAAW,MAAM,KAAK,WAAW,SAAS,EAC9C,OAAO,EAAE,QAAQ,EAAE,IAAI,QAAQ,EAAE,EAClC,CAAC;AAEF,SAAO,MAAM,KAAK,WAAW,OAAO;GAClC;GACA;GACA,MAAM,OAAO;GACb,OAAO,OAAO;GACd,OAAO,OAAO;GACd,UAAU,OAAO;GACjB,SAAS,OAAO;GAChB,WAAW,SAAS,WAAW;GAC/B,aAAa,OAAO;GACrB,CAAC;;CAGJ,MAAa,mBACX,QACgC;AAChC,SAAO,MAAM,KAAK,WAAW,SAAS,EACpC,OAAO,EAAE,QAAQ,EAAE,IAAI,QAAQ,EAAE,EAClC,CAAC;;CAGJ,MAAa,oBACX,UACA,QACe;EACf,MAAM,SAAS,MAAM,KAAK,WAAW,QAAQ,SAAS;AACtD,MAAI,OAAO,WAAW,OACpB,OAAM,IAAI,aAAa,8CAA8C;AAGvE,QAAM,KAAK,SAAS,oBAAoB,OAAO,YAAY;AAC3D,QAAM,KAAK,WAAW,WAAW,OAAO,GAAG;;CAG7C,MAAa,WACX,UACA,QAC8B;EAC9B,MAAM,SAAS,MAAM,KAAK,WAAW,QAAQ,SAAS;AACtD,MAAI,OAAO,WAAW,OACpB,OAAM,IAAI,aAAa,8CAA8C;EAGvE,MAAM,cAAc,MAAM,KAAK,WAAW,SAAS,EACjD,OAAO,EAAE,QAAQ,EAAE,IAAI,QAAQ,EAAE,EAClC,CAAC;AAEF,OAAK,MAAM,KAAK,YACd,KAAI,EAAE,UACJ,OAAM,KAAK,WAAW,WAAW,EAAE,IAAI,EAAE,WAAW,OAAO,CAAC;AAIhE,SAAO,MAAM,KAAK,WAAW,WAAW,OAAO,IAAI,EAAE,WAAW,MAAM,CAAC;;;;;AChE3E,IAAa,oBAAb,MAA+B;CAC7B,MAAyB;CACzB,QAA2B;CAC3B,WAA8B,QAAQ,eAAe;CACrD,iBAAoC,QAAQ,qBAAqB;;;;CAKjE,qBAAqC,QAAQ;EAC3C,MAAM,GAAG,KAAK,IAAI;EAClB,OAAO,KAAK;EACZ,KAAK,CAAC,SAAS,CAAC;EAChB,aAAa;EACb,QAAQ,EACN,UAAU,EAAE,MAAM,4BAA4B,EAC/C;EACD,UAAU,EAAE,WAAW,KAAK,eAAe,mBAAmB,KAAK,GAAG;EACvE,CAAC;;;;CAKF,mBAAmC,QAAQ;EACzC,QAAQ;EACR,MAAM,GAAG,KAAK,IAAI;EAClB,OAAO,KAAK;EACZ,KAAK,CAAC,SAAS,CAAC;EAChB,aAAa;EACb,QAAQ;GACN,MAAM;GACN,UAAU;GACX;EACD,UAAU,EAAE,MAAM,WAAW;AAC3B,OAAI,CAAC,KAAK,aACR,OAAM,IAAI,aACR,mDACD;AAEH,UAAO,KAAK,eAAe,iBACzB,KAAK,IACL,KAAK,cACL,KAAK,MACN;;EAEJ,CAAC;;;;CAKF,sBAAsC,QAAQ;EAC5C,QAAQ;EACR,MAAM,GAAG,KAAK,IAAI;EAClB,OAAO,KAAK;EACZ,KAAK,CAAC,SAAS,CAAC;EAChB,aAAa;EACb,QAAQ;GACN,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;GAClC,UAAU;GACX;EACD,SAAS,OAAO,EAAE,QAAQ,WAAW;AACnC,SAAM,KAAK,eAAe,oBAAoB,OAAO,IAAI,KAAK,GAAG;AACjE,UAAO;IAAE,IAAI;IAAM,IAAI,OAAO;IAAI;;EAErC,CAAC;;;;CAKF,0BAA0C,QAAQ;EAChD,QAAQ;EACR,MAAM,GAAG,KAAK,IAAI;EAClB,OAAO,KAAK;EACZ,KAAK,CAAC,SAAS,CAAC;EAChB,aAAa;EACb,QAAQ;GACN,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;GAClC,UAAU;GACX;EACD,UAAU,EAAE,QAAQ,WAClB,KAAK,eAAe,WAAW,OAAO,IAAI,KAAK,GAAG;EACrD,CAAC;;;;CAKF,iBAAiC,QAAQ;EACvC,QAAQ;EACR,MAAM,GAAG,KAAK,IAAI;EAClB,OAAO,KAAK;EACZ,KAAK,CAAC,SAAS,CAAC;EAChB,aAAa;EACb,QAAQ;GACN,MAAM;GACN,UAAU;GACX;EACD,UAAU,EAAE,MAAM,WAChB,KAAK,SAAS,cACZ,KAAK,UACL,KAAK,WACL,KAAK,WACL,KAAK,GACN;EACJ,CAAC;;;;AChGJ,IAAa,wBAAb,MAA8D;CAC5D,0BAAwD,IAAI,KAAK;CACjE,gCAA8D,IAAI,KAAK;CACvE,0BACE,IAAI,KAAK;CACX,kCAAkD,IAAI,KAAK;CAE3D,MAAa,cACX,QACA,SAC8B;EAC9B,MAAM,cAAc,eAAe,YAAY;EAC/C,MAAM,SAAS,QAAQ,YAAY,eAAe;AAClD,OAAK,QAAQ,IAAI,aAAa;GAC5B;GACA,QAAQ,OAAO;GACf;GACD,CAAC;AACF,SAAO;GACL,KAAK,2BAA2B,OAAO;GACvC;GACD;;CAGH,MAAa,eACX,aACA,QACe;EACf,MAAM,SAAS,KAAK,QAAQ,IAAI,YAAY;AAC5C,MAAI,QAAQ;AACV,UAAO,SAAS;AAChB,UAAO,SAAS;;;CAIpB,MAAa,YAAY,aAAoC;EAC3D,MAAM,SAAS,KAAK,QAAQ,IAAI,YAAY;AAC5C,MAAI,OACF,QAAO,SAAS;;CAIpB,MAAa,cACX,aACA,QACuB;EACvB,MAAM,YAAY,cAAc,YAAY;AAC5C,OAAK,cAAc,IAAI,WAAW;GAChC,aAAa;GACb,WAAW;GACX;GACD,CAAC;AACF,SAAO,EAAE,aAAa,WAAW;;CAGnC,MAAa,aAAa,SAAyC;EACjE,MAAM,OAAQ,MAAM,QAAQ,MAAM;AAIlC,SAAO;GACL,aAAa,KAAK;GAClB,QAAQ,KAAK;GACb,KAAK;GACN;;CAGH,MAAa,oBACX,QACA,OACoC;EACpC,MAAM,cAAc,UAAU,YAAY;EAC1C,MAAM,SAAoC;GACxC;GACA,MAAM;GACN,OAAO;GACP,OAAO;GACP,UAAU;GACV,SAAS;GACV;AACD,OAAK,QAAQ,IAAI,aAAa,OAAO;AACrC,SAAO;;CAGT,MAAa,oBAAoB,aAAoC;AACnE,OAAK,QAAQ,OAAO,YAAY;;CAGlC,MAAa,cAAc,aAAoC;AAC7D,OAAK,gBAAgB,IAAI,YAAY;;CAKvC,WAAkB,aAA8B;AAE9C,SADe,KAAK,QAAQ,IAAI,YAAY,EAC7B,WAAW;;CAG5B,YAAmB,aAA8B;AAC/C,SAAO,MAAM,KAAK,KAAK,cAAc,QAAQ,CAAC,CAAC,MAC5C,MAAM,EAAE,cAAc,YACxB;;CAGH,WAAkB,aAA8B;AAC9C,SAAO,KAAK,gBAAgB,IAAI,YAAY;;CAG9C,aAAoC;AAClC,SAAO,MAAM,KAAK,KAAK,QAAQ,QAAQ,CAAC;;CAG1C,aAAoC;AAClC,SAAO,MAAM,KAAK,KAAK,cAAc,QAAQ,CAAC;;;;;ACxElD,MAAa,oBAAoB,QAAQ;CACvC,MAAM;CACN,UAAU;EACR;EACA;EACA;EACA;EACA;EACD;CACD,UAAU,CAAC,sBAAsB;CACjC,WAAW,WAAW;AACpB,SAAO,KAAK;GACV,UAAU;GACV,SAAS;GACT,KAAK;GACN,CAAC;;CAEL,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/api/payments/entities/paymentIntents.ts","../../../src/api/payments/schemas/intentSchemas.ts","../../../src/api/payments/entities/refunds.ts","../../../src/api/payments/schemas/refundSchemas.ts","../../../src/api/payments/errors/PaymentError.ts","../../../src/api/payments/providers/PaymentProvider.ts","../../../src/api/payments/services/PaymentService.ts","../../../src/api/payments/controllers/AdminPaymentController.ts","../../../src/api/payments/entities/paymentMethods.ts","../../../src/api/payments/schemas/paymentMethodSchemas.ts","../../../src/api/payments/services/PaymentMethodService.ts","../../../src/api/payments/controllers/PaymentController.ts","../../../src/api/payments/providers/MemoryPaymentProvider.ts","../../../src/api/payments/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 \"partially_refunded\",\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 PaymentError 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 PaymentProvider {\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 and verify an incoming PSP webhook request.\n *\n * Implementations MUST verify the webhook signature before returning.\n * Throw an error if the signature is invalid or missing — this is the\n * only authentication on the webhook endpoint (no $secure middleware).\n *\n * Failure to verify signatures allows attackers to forge payment\n * confirmations by POSTing fake webhook events.\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 { PaymentError } from \"../errors/PaymentError.ts\";\nimport { PaymentProvider } from \"../providers/PaymentProvider.ts\";\n\nexport class PaymentService {\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n protected readonly dateTime = $inject(DateTimeProvider);\n protected readonly provider = $inject(PaymentProvider);\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 5 minutes — shares the CF wrangler\n * trigger with the jobs sweep so no extra binding is consumed.\n */\n protected readonly expireStaleIntents = $job({\n name: \"api:payments:expireStaleIntents\",\n cron: \"*/5 * * * *\",\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: currency.toLowerCase(),\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 userId?: string,\n ): Promise<{ url: string; intentId: string }> {\n const intent = await this.getIntent(intentId);\n this.assertStatus(intent, \"created\", \"createSession\");\n\n // Verify intent ownership if userId is provided\n if (userId && intent.userId && intent.userId !== userId) {\n throw new PaymentError(\"Payment intent does not belong to this user\");\n }\n\n // Associate intent with user if not already set\n if (userId && !intent.userId) {\n await this.intentRepo.updateById(intent.id, { userId });\n }\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 payment event.\n */\n /**\n * Valid status transitions from webhook events.\n * Only these transitions are allowed — all others are silently ignored.\n */\n protected static readonly VALID_WEBHOOK_TRANSITIONS: Record<\n string,\n string[]\n > = {\n processing: [\"authorized\", \"captured\", \"failed\"],\n authorized: [\"captured\", \"failed\"],\n };\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: \"payments:authorized\",\n captured: \"payments:captured\",\n failed: \"payments: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 // Validate status transition\n const allowed = PaymentService.VALID_WEBHOOK_TRANSITIONS[intent.status];\n if (!allowed?.includes(webhookStatus)) {\n this.log.warn(\n `Ignoring webhook: cannot transition ${intent.status} → ${webhookStatus}`,\n { intentId: intent.id },\n );\n return;\n }\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 (amount > intent.amount) {\n throw new PaymentError(\n `Capture amount ${amount} exceeds authorized amount ${intent.amount}`,\n );\n }\n\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(\"payments: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(\"payments: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\n // Allow refunds from both \"captured\" and \"partially_refunded\" states\n if (\n intent.status !== \"captured\" &&\n intent.status !== \"partially_refunded\"\n ) {\n throw new PaymentError(\n `Cannot refund: intent ${intent.id} is '${intent.status}', expected 'captured' or 'partially_refunded'`,\n );\n }\n\n // Validate refund amount against remaining refundable amount\n const existingRefunds = await this.refundRepo.findMany({\n where: { intentId: { eq: intent.id } },\n });\n const totalRefunded = existingRefunds.reduce((sum, r) => sum + r.amount, 0);\n const remaining = intent.amount - totalRefunded;\n\n if (amount > remaining) {\n throw new PaymentError(\n `Refund amount ${amount} exceeds remaining refundable amount ${remaining}`,\n );\n }\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 // Set status based on whether fully or partially refunded\n const newTotalRefunded = totalRefunded + amount;\n const newStatus =\n newTotalRefunded >= intent.amount ? \"refunded\" : \"partially_refunded\";\n await this.intentRepo.updateById(intent.id, {\n status: newStatus,\n });\n\n await this.alepha.events.emit(\"payments: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: currency.toLowerCase(),\n status: \"captured\",\n metadata: metadata as any,\n });\n\n await this.alepha.events.emit(\"payments: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 const cancelled = await this.intentRepo.updateById(intent.id, {\n status: \"cancelled\",\n });\n\n await this.alepha.events.emit(\"payments:cancelled\", {\n intentId: intent.id,\n amount: intent.amount,\n currency: intent.currency,\n metadata: intent.metadata,\n });\n\n return cancelled;\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 PaymentError(\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 { PaymentService } from \"../services/PaymentService.ts\";\n\nexport class AdminPaymentController {\n protected readonly url = \"/admin/payments\";\n protected readonly group = \"admin:payments\";\n protected readonly payments = $inject(PaymentService);\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: [\"payments:read\"] })],\n description: \"List payment intents\",\n schema: {\n query: intentQuerySchema,\n response: t.page(intentResourceSchema),\n },\n handler: ({ query }) => this.payments.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: [\"payments:read\"] })],\n description: \"Get payment intent details\",\n schema: {\n params: t.object({ id: t.uuid() }),\n response: intentResourceSchema,\n },\n handler: ({ params }) => this.payments.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: [\"payments: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 }) =>\n this.payments.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: [\"payments: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.payments.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: [\"payments: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.payments.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: [\"payments: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.payments.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: [\"payments:write\"] })],\n description: \"Record a cash payment\",\n schema: {\n body: recordCashSchema,\n response: intentResourceSchema,\n },\n handler: ({ body }) =>\n this.payments.recordCashPayment(\n body.amount,\n body.currency,\n body.metadata,\n ),\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: \"/payments/webhook\",\n group: this.group,\n description: \"PSP webhook endpoint\",\n schema: {\n response: okSchema,\n },\n handler: async (request) => {\n await this.payments.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 { PaymentError } from \"../errors/PaymentError.ts\";\nimport { PaymentProvider } from \"../providers/PaymentProvider.ts\";\n\nexport class PaymentMethodService {\n protected readonly log = $logger();\n protected readonly provider = $inject(PaymentProvider);\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 PaymentError(\"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 PaymentError(\"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 { PaymentError } from \"../errors/PaymentError.ts\";\nimport {\n checkoutResponseSchema,\n createCheckoutSchema,\n} from \"../schemas/intentSchemas.ts\";\nimport {\n addPaymentMethodSchema,\n paymentMethodResourceSchema,\n} from \"../schemas/paymentMethodSchemas.ts\";\nimport { PaymentMethodService } from \"../services/PaymentMethodService.ts\";\nimport { PaymentService } from \"../services/PaymentService.ts\";\n\nexport class PaymentController {\n protected readonly url = \"/payments\";\n protected readonly group = \"payments\";\n protected readonly payments = $inject(PaymentService);\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 if (!user.organization) {\n throw new PaymentError(\n \"Organization is required to add a payment method\",\n );\n }\n return this.paymentMethods.addPaymentMethod(\n user.id,\n user.organization,\n body.token,\n );\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, user }) =>\n this.payments.createSession(\n body.intentId,\n body.returnUrl,\n body.authorize,\n user.id,\n ),\n });\n}\n","import { randomUUID } from \"node:crypto\";\nimport type { PaymentIntentEntity } from \"../entities/paymentIntents.ts\";\nimport type {\n CreatePaymentMethodResult,\n CreateSessionResult,\n PaymentProvider,\n RefundResult,\n WebhookEvent,\n} from \"./PaymentProvider.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 MemoryPaymentProvider implements PaymentProvider {\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: `/payments/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 { AdminPaymentController } from \"./controllers/AdminPaymentController.ts\";\nimport { PaymentController } from \"./controllers/PaymentController.ts\";\nimport { MemoryPaymentProvider } from \"./providers/MemoryPaymentProvider.ts\";\nimport { PaymentProvider } from \"./providers/PaymentProvider.ts\";\nimport { PaymentMethodService } from \"./services/PaymentMethodService.ts\";\nimport { PaymentService } from \"./services/PaymentService.ts\";\n\nexport * from \"./controllers/AdminPaymentController.ts\";\nexport * from \"./controllers/PaymentController.ts\";\nexport * from \"./entities/paymentIntents.ts\";\nexport * from \"./entities/paymentMethods.ts\";\nexport * from \"./entities/refunds.ts\";\nexport * from \"./errors/PaymentError.ts\";\nexport * from \"./providers/MemoryPaymentProvider.ts\";\nexport * from \"./providers/PaymentProvider.ts\";\nexport * from \"./schemas/intentSchemas.ts\";\nexport * from \"./schemas/paymentMethodSchemas.ts\";\nexport * from \"./schemas/refundSchemas.ts\";\nexport * from \"./services/PaymentMethodService.ts\";\nexport * from \"./services/PaymentService.ts\";\n\ndeclare module \"alepha\" {\n interface Hooks {\n \"payments:authorized\": {\n intentId: string;\n amount: number;\n currency: string;\n metadata?: unknown;\n };\n \"payments:captured\": {\n intentId: string;\n amount: number;\n currency: string;\n metadata?: unknown;\n };\n \"payments:failed\": {\n intentId: string;\n amount: number;\n currency: string;\n metadata?: unknown;\n };\n \"payments:voided\": {\n intentId: string;\n amount: number;\n currency: string;\n metadata?: unknown;\n };\n \"payments:refunded\": {\n intentId: string;\n refundId: string;\n amount: number;\n currency: string;\n metadata?: unknown;\n };\n \"payments:cancelled\": {\n intentId: string;\n amount: number;\n currency: string;\n metadata?: unknown;\n };\n }\n}\n\nexport const AlephaApiPayments = $module({\n name: \"alepha.api.payments\",\n services: [\n AdminPaymentController,\n PaymentController,\n PaymentProvider,\n PaymentService,\n PaymentMethodService,\n ],\n variants: [MemoryPaymentProvider],\n register: (alepha) => {\n alepha.with({\n optional: true,\n provide: PaymentProvider,\n use: MemoryPaymentProvider,\n });\n },\n});\n"],"mappings":"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"}
|
|
@@ -6701,7 +6701,9 @@ type AuditContext = Omit<CreateAudit, "type" | "action">;
|
|
|
6701
6701
|
* User-specific audit wrapper service.
|
|
6702
6702
|
*
|
|
6703
6703
|
* This service wraps the core AuditService to provide user-related audit logging.
|
|
6704
|
-
*
|
|
6704
|
+
*
|
|
6705
|
+
* Declared as a module variant — not auto-injected. It is instantiated
|
|
6706
|
+
* lazily the first time something calls `alepha.inject(UserAudits)`.
|
|
6705
6707
|
*/
|
|
6706
6708
|
declare class UserAudits {
|
|
6707
6709
|
protected readonly auditService: AuditService;
|
|
@@ -6741,11 +6743,11 @@ declare class UserAudits {
|
|
|
6741
6743
|
requestId?: string | undefined;
|
|
6742
6744
|
errorMessage?: string | undefined;
|
|
6743
6745
|
type: string;
|
|
6746
|
+
id: string;
|
|
6747
|
+
createdAt: string;
|
|
6744
6748
|
action: string;
|
|
6745
6749
|
severity: "info" | "warning" | "critical";
|
|
6746
6750
|
success: boolean;
|
|
6747
|
-
id: string;
|
|
6748
|
-
createdAt: string;
|
|
6749
6751
|
}>;
|
|
6750
6752
|
/**
|
|
6751
6753
|
* Record an authentication-related audit event.
|
|
@@ -6783,11 +6785,11 @@ declare class UserAudits {
|
|
|
6783
6785
|
requestId?: string | undefined;
|
|
6784
6786
|
errorMessage?: string | undefined;
|
|
6785
6787
|
type: string;
|
|
6788
|
+
id: string;
|
|
6789
|
+
createdAt: string;
|
|
6786
6790
|
action: string;
|
|
6787
6791
|
severity: "info" | "warning" | "critical";
|
|
6788
6792
|
success: boolean;
|
|
6789
|
-
id: string;
|
|
6790
|
-
createdAt: string;
|
|
6791
6793
|
}>;
|
|
6792
6794
|
/**
|
|
6793
6795
|
* Record a generic audit event.
|
|
@@ -6825,11 +6827,11 @@ declare class UserAudits {
|
|
|
6825
6827
|
requestId?: string | undefined;
|
|
6826
6828
|
errorMessage?: string | undefined;
|
|
6827
6829
|
type: string;
|
|
6830
|
+
id: string;
|
|
6831
|
+
createdAt: string;
|
|
6828
6832
|
action: string;
|
|
6829
6833
|
severity: "info" | "warning" | "critical";
|
|
6830
6834
|
success: boolean;
|
|
6831
|
-
id: string;
|
|
6832
|
-
createdAt: string;
|
|
6833
6835
|
}>;
|
|
6834
6836
|
}
|
|
6835
6837
|
//#endregion
|
|
@@ -6840,7 +6842,8 @@ declare class UserAudits {
|
|
|
6840
6842
|
* This service provides file storage for user-related files such as:
|
|
6841
6843
|
* - User avatars/profile pictures
|
|
6842
6844
|
*
|
|
6843
|
-
*
|
|
6845
|
+
* Declared as a module variant — not auto-injected. It is instantiated
|
|
6846
|
+
* lazily the first time something calls `alepha.inject(UserBuckets)`.
|
|
6844
6847
|
*/
|
|
6845
6848
|
declare class UserBuckets {
|
|
6846
6849
|
/**
|
|
@@ -7138,12 +7141,12 @@ declare class AdminIdentityController {
|
|
|
7138
7141
|
userRealmName: _$alepha.TOptional<_$alepha.TString>;
|
|
7139
7142
|
}>;
|
|
7140
7143
|
response: _$alepha.TPage<_$alepha.TObject<{
|
|
7141
|
-
userId: PgAttr<_$alepha.TString, typeof PG_REF>;
|
|
7142
7144
|
id: PgAttr<PgAttr<_$alepha.TString, typeof PG_PRIMARY_KEY>, typeof PG_DEFAULT>;
|
|
7143
|
-
createdAt: PgAttr<PgAttr<_$alepha.TString, typeof PG_CREATED_AT>, typeof PG_DEFAULT>;
|
|
7144
|
-
provider: _$alepha.TString;
|
|
7145
7145
|
version: PgAttr<PgAttr<_$alepha.TInteger, typeof PG_VERSION>, typeof PG_DEFAULT>;
|
|
7146
|
+
createdAt: PgAttr<PgAttr<_$alepha.TString, typeof PG_CREATED_AT>, typeof PG_DEFAULT>;
|
|
7146
7147
|
updatedAt: PgAttr<PgAttr<_$alepha.TString, typeof PG_UPDATED_AT>, typeof PG_DEFAULT>;
|
|
7148
|
+
userId: PgAttr<_$alepha.TString, typeof PG_REF>;
|
|
7149
|
+
provider: _$alepha.TString;
|
|
7147
7150
|
providerUserId: _$alepha.TOptional<_$alepha.TString>;
|
|
7148
7151
|
providerData: _$alepha.TOptional<_$alepha.TRecord<string, _$alepha.TAny>>;
|
|
7149
7152
|
}>>;
|
|
@@ -7159,12 +7162,12 @@ declare class AdminIdentityController {
|
|
|
7159
7162
|
userRealmName: _$alepha.TOptional<_$alepha.TString>;
|
|
7160
7163
|
}>;
|
|
7161
7164
|
response: _$alepha.TObject<{
|
|
7162
|
-
userId: PgAttr<_$alepha.TString, typeof PG_REF>;
|
|
7163
7165
|
id: PgAttr<PgAttr<_$alepha.TString, typeof PG_PRIMARY_KEY>, typeof PG_DEFAULT>;
|
|
7164
|
-
createdAt: PgAttr<PgAttr<_$alepha.TString, typeof PG_CREATED_AT>, typeof PG_DEFAULT>;
|
|
7165
|
-
provider: _$alepha.TString;
|
|
7166
7166
|
version: PgAttr<PgAttr<_$alepha.TInteger, typeof PG_VERSION>, typeof PG_DEFAULT>;
|
|
7167
|
+
createdAt: PgAttr<PgAttr<_$alepha.TString, typeof PG_CREATED_AT>, typeof PG_DEFAULT>;
|
|
7167
7168
|
updatedAt: PgAttr<PgAttr<_$alepha.TString, typeof PG_UPDATED_AT>, typeof PG_DEFAULT>;
|
|
7169
|
+
userId: PgAttr<_$alepha.TString, typeof PG_REF>;
|
|
7170
|
+
provider: _$alepha.TString;
|
|
7168
7171
|
providerUserId: _$alepha.TOptional<_$alepha.TString>;
|
|
7169
7172
|
providerData: _$alepha.TOptional<_$alepha.TRecord<string, _$alepha.TAny>>;
|
|
7170
7173
|
}>;
|
|
@@ -7340,18 +7343,18 @@ declare class UserNotifications {
|
|
|
7340
7343
|
//#endregion
|
|
7341
7344
|
//#region ../../src/api/users/schemas/createUserSchema.d.ts
|
|
7342
7345
|
declare const createUserSchema: _$alepha.TObject<{
|
|
7346
|
+
enabled: _$alepha.TOptional<PgAttr<_$alepha.TBoolean, typeof PG_DEFAULT>>;
|
|
7343
7347
|
email: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7344
|
-
username: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7345
7348
|
phoneNumber: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7346
7349
|
id: _$alepha.TOptional<PgAttr<PgAttr<_$alepha.TString, typeof PG_PRIMARY_KEY>, typeof PG_DEFAULT>>;
|
|
7347
|
-
createdAt: _$alepha.TOptional<PgAttr<PgAttr<_$alepha.TString, typeof PG_CREATED_AT>, typeof PG_DEFAULT>>;
|
|
7348
7350
|
version: _$alepha.TOptional<PgAttr<PgAttr<_$alepha.TInteger, typeof PG_VERSION>, typeof PG_DEFAULT>>;
|
|
7351
|
+
createdAt: _$alepha.TOptional<PgAttr<PgAttr<_$alepha.TString, typeof PG_CREATED_AT>, typeof PG_DEFAULT>>;
|
|
7349
7352
|
updatedAt: _$alepha.TOptional<PgAttr<PgAttr<_$alepha.TString, typeof PG_UPDATED_AT>, typeof PG_DEFAULT>>;
|
|
7353
|
+
username: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7350
7354
|
roles: _$alepha.TOptional<_$alepha.TArray<_$alepha.TString>>;
|
|
7351
7355
|
firstName: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7352
7356
|
lastName: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7353
7357
|
picture: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7354
|
-
enabled: _$alepha.TOptional<PgAttr<_$alepha.TBoolean, typeof PG_DEFAULT>>;
|
|
7355
7358
|
emailVerified: _$alepha.TOptional<PgAttr<_$alepha.TBoolean, typeof PG_DEFAULT>>;
|
|
7356
7359
|
organizationId: _$alepha.TOptional<PgAttr<_$alepha.TOptional<_$alepha.TString>, typeof PG_ORGANIZATION>>;
|
|
7357
7360
|
}>;
|
|
@@ -7359,6 +7362,7 @@ type CreateUser = Static<typeof createUserSchema>;
|
|
|
7359
7362
|
//#endregion
|
|
7360
7363
|
//#region ../../src/api/users/schemas/updateUserSchema.d.ts
|
|
7361
7364
|
declare const updateUserSchema: _$alepha.TObject<{
|
|
7365
|
+
enabled: _$alepha.TOptional<PgAttr<_$alepha.TBoolean, typeof PG_DEFAULT>>;
|
|
7362
7366
|
email: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7363
7367
|
phoneNumber: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7364
7368
|
realm: _$alepha.TOptional<PgAttr<_$alepha.TString, typeof PG_DEFAULT>>;
|
|
@@ -7366,7 +7370,6 @@ declare const updateUserSchema: _$alepha.TObject<{
|
|
|
7366
7370
|
firstName: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7367
7371
|
lastName: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7368
7372
|
picture: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7369
|
-
enabled: _$alepha.TOptional<PgAttr<_$alepha.TBoolean, typeof PG_DEFAULT>>;
|
|
7370
7373
|
organizationId: _$alepha.TOptional<PgAttr<_$alepha.TOptional<_$alepha.TString>, typeof PG_ORGANIZATION>>;
|
|
7371
7374
|
}>;
|
|
7372
7375
|
type UpdateUser = Static<typeof updateUserSchema>;
|
|
@@ -7522,18 +7525,18 @@ declare class AdminUserController {
|
|
|
7522
7525
|
userRealmName: _$alepha.TOptional<_$alepha.TString>;
|
|
7523
7526
|
}>;
|
|
7524
7527
|
body: _$alepha.TObject<{
|
|
7528
|
+
enabled: _$alepha.TOptional<PgAttr<_$alepha.TBoolean, typeof PG_DEFAULT>>;
|
|
7525
7529
|
email: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7526
|
-
username: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7527
7530
|
phoneNumber: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7528
7531
|
id: _$alepha.TOptional<PgAttr<PgAttr<_$alepha.TString, typeof PG_PRIMARY_KEY>, typeof PG_DEFAULT>>;
|
|
7529
|
-
createdAt: _$alepha.TOptional<PgAttr<PgAttr<_$alepha.TString, typeof PG_CREATED_AT>, typeof PG_DEFAULT>>;
|
|
7530
7532
|
version: _$alepha.TOptional<PgAttr<PgAttr<_$alepha.TInteger, typeof PG_VERSION>, typeof PG_DEFAULT>>;
|
|
7533
|
+
createdAt: _$alepha.TOptional<PgAttr<PgAttr<_$alepha.TString, typeof PG_CREATED_AT>, typeof PG_DEFAULT>>;
|
|
7531
7534
|
updatedAt: _$alepha.TOptional<PgAttr<PgAttr<_$alepha.TString, typeof PG_UPDATED_AT>, typeof PG_DEFAULT>>;
|
|
7535
|
+
username: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7532
7536
|
roles: _$alepha.TOptional<_$alepha.TArray<_$alepha.TString>>;
|
|
7533
7537
|
firstName: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7534
7538
|
lastName: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7535
7539
|
picture: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7536
|
-
enabled: _$alepha.TOptional<PgAttr<_$alepha.TBoolean, typeof PG_DEFAULT>>;
|
|
7537
7540
|
emailVerified: _$alepha.TOptional<PgAttr<_$alepha.TBoolean, typeof PG_DEFAULT>>;
|
|
7538
7541
|
organizationId: _$alepha.TOptional<PgAttr<_$alepha.TOptional<_$alepha.TString>, typeof PG_ORGANIZATION>>;
|
|
7539
7542
|
}>;
|
|
@@ -7566,6 +7569,7 @@ declare class AdminUserController {
|
|
|
7566
7569
|
userRealmName: _$alepha.TOptional<_$alepha.TString>;
|
|
7567
7570
|
}>;
|
|
7568
7571
|
body: _$alepha.TObject<{
|
|
7572
|
+
enabled: _$alepha.TOptional<PgAttr<_$alepha.TBoolean, typeof PG_DEFAULT>>;
|
|
7569
7573
|
email: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7570
7574
|
phoneNumber: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7571
7575
|
realm: _$alepha.TOptional<PgAttr<_$alepha.TString, typeof PG_DEFAULT>>;
|
|
@@ -7573,7 +7577,6 @@ declare class AdminUserController {
|
|
|
7573
7577
|
firstName: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7574
7578
|
lastName: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7575
7579
|
picture: _$alepha.TOptional<_$alepha.TOptional<_$alepha.TString>>;
|
|
7576
|
-
enabled: _$alepha.TOptional<PgAttr<_$alepha.TBoolean, typeof PG_DEFAULT>>;
|
|
7577
7580
|
organizationId: _$alepha.TOptional<PgAttr<_$alepha.TOptional<_$alepha.TString>, typeof PG_ORGANIZATION>>;
|
|
7578
7581
|
}>;
|
|
7579
7582
|
response: _$alepha.TObject<{
|
|
@@ -8121,7 +8124,8 @@ declare class UserController {
|
|
|
8121
8124
|
* - Verification code cleanup
|
|
8122
8125
|
* - Inactive user notifications
|
|
8123
8126
|
*
|
|
8124
|
-
*
|
|
8127
|
+
* Declared as a module variant — not auto-injected. It is instantiated
|
|
8128
|
+
* lazily the first time something calls `alepha.inject(UserJobs)`.
|
|
8125
8129
|
*/
|
|
8126
8130
|
declare class UserJobs {
|
|
8127
8131
|
protected readonly log: _$alepha_logger0.Logger;
|
|
@@ -8144,20 +8148,19 @@ declare class UserJobs {
|
|
|
8144
8148
|
/**
|
|
8145
8149
|
* Purge expired sessions from the database.
|
|
8146
8150
|
*
|
|
8147
|
-
*
|
|
8148
|
-
* where the `expiresAt` timestamp has passed.
|
|
8151
|
+
* Runs hourly (at :00) and deletes sessions whose `expiresAt` has passed.
|
|
8149
8152
|
*/
|
|
8150
8153
|
readonly purgeExpiredSessions: _$alepha_api_jobs0.JobPrimitive<_$alepha.TSchema>;
|
|
8151
8154
|
}
|
|
8152
8155
|
//#endregion
|
|
8153
8156
|
//#region ../../src/api/users/schemas/identityResourceSchema.d.ts
|
|
8154
8157
|
declare const identityResourceSchema: _$alepha.TObject<{
|
|
8155
|
-
userId: PgAttr<_$alepha.TString, typeof PG_REF>;
|
|
8156
8158
|
id: PgAttr<PgAttr<_$alepha.TString, typeof PG_PRIMARY_KEY>, typeof PG_DEFAULT>;
|
|
8157
|
-
createdAt: PgAttr<PgAttr<_$alepha.TString, typeof PG_CREATED_AT>, typeof PG_DEFAULT>;
|
|
8158
|
-
provider: _$alepha.TString;
|
|
8159
8159
|
version: PgAttr<PgAttr<_$alepha.TInteger, typeof PG_VERSION>, typeof PG_DEFAULT>;
|
|
8160
|
+
createdAt: PgAttr<PgAttr<_$alepha.TString, typeof PG_CREATED_AT>, typeof PG_DEFAULT>;
|
|
8160
8161
|
updatedAt: PgAttr<PgAttr<_$alepha.TString, typeof PG_UPDATED_AT>, typeof PG_DEFAULT>;
|
|
8162
|
+
userId: PgAttr<_$alepha.TString, typeof PG_REF>;
|
|
8163
|
+
provider: _$alepha.TString;
|
|
8161
8164
|
providerUserId: _$alepha.TOptional<_$alepha.TString>;
|
|
8162
8165
|
providerData: _$alepha.TOptional<_$alepha.TRecord<string, _$alepha.TAny>>;
|
|
8163
8166
|
}>;
|
|
@@ -8413,19 +8416,19 @@ declare class SessionService {
|
|
|
8413
8416
|
deleteSession(refreshToken: string, userRealmName?: string): Promise<void>;
|
|
8414
8417
|
link(provider: string, profile: OAuth2Profile, userRealmName?: string): Promise<{
|
|
8415
8418
|
email?: string | undefined;
|
|
8416
|
-
username?: string | undefined;
|
|
8417
8419
|
phoneNumber?: string | undefined;
|
|
8420
|
+
username?: string | undefined;
|
|
8418
8421
|
firstName?: string | undefined;
|
|
8419
8422
|
lastName?: string | undefined;
|
|
8420
8423
|
picture?: string | undefined;
|
|
8421
8424
|
organizationId?: string | undefined;
|
|
8425
|
+
enabled: boolean;
|
|
8422
8426
|
id: string;
|
|
8423
|
-
createdAt: string;
|
|
8424
8427
|
version: number;
|
|
8428
|
+
createdAt: string;
|
|
8425
8429
|
updatedAt: string;
|
|
8426
8430
|
realm: string;
|
|
8427
8431
|
roles: string[];
|
|
8428
|
-
enabled: boolean;
|
|
8429
8432
|
emailVerified: boolean;
|
|
8430
8433
|
} | {
|
|
8431
8434
|
sub: string;
|