alepha 0.13.6 → 0.13.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/dist/api-audits/index.browser.js +116 -0
  2. package/dist/api-audits/index.browser.js.map +1 -0
  3. package/dist/api-audits/index.d.ts +1194 -0
  4. package/dist/api-audits/index.js +674 -0
  5. package/dist/api-audits/index.js.map +1 -0
  6. package/dist/api-notifications/index.d.ts +147 -147
  7. package/dist/api-parameters/index.browser.js +36 -5
  8. package/dist/api-parameters/index.browser.js.map +1 -1
  9. package/dist/api-parameters/index.d.ts +711 -33
  10. package/dist/api-parameters/index.js +831 -17
  11. package/dist/api-parameters/index.js.map +1 -1
  12. package/dist/api-users/index.d.ts +793 -780
  13. package/dist/api-users/index.js +699 -19
  14. package/dist/api-users/index.js.map +1 -1
  15. package/dist/api-verifications/index.js +2 -1
  16. package/dist/api-verifications/index.js.map +1 -1
  17. package/dist/bin/index.js +1 -0
  18. package/dist/bin/index.js.map +1 -1
  19. package/dist/cli/index.d.ts +85 -31
  20. package/dist/cli/index.js +205 -33
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/command/index.d.ts +67 -6
  23. package/dist/command/index.js +30 -3
  24. package/dist/command/index.js.map +1 -1
  25. package/dist/core/index.browser.js +241 -61
  26. package/dist/core/index.browser.js.map +1 -1
  27. package/dist/core/index.d.ts +170 -90
  28. package/dist/core/index.js +264 -67
  29. package/dist/core/index.js.map +1 -1
  30. package/dist/core/index.native.js +248 -65
  31. package/dist/core/index.native.js.map +1 -1
  32. package/dist/email/index.js +15 -10554
  33. package/dist/email/index.js.map +1 -1
  34. package/dist/logger/index.d.ts +4 -4
  35. package/dist/logger/index.js +77 -72
  36. package/dist/logger/index.js.map +1 -1
  37. package/dist/orm/index.d.ts +5 -1
  38. package/dist/orm/index.js +24 -7
  39. package/dist/orm/index.js.map +1 -1
  40. package/dist/queue/index.d.ts +4 -4
  41. package/dist/scheduler/index.d.ts +6 -6
  42. package/dist/server/index.d.ts +10 -1
  43. package/dist/server/index.js +20 -6
  44. package/dist/server/index.js.map +1 -1
  45. package/dist/server-auth/index.d.ts +163 -152
  46. package/dist/server-auth/index.js +40 -10
  47. package/dist/server-auth/index.js.map +1 -1
  48. package/dist/server-cookies/index.js +5 -1
  49. package/dist/server-cookies/index.js.map +1 -1
  50. package/dist/server-links/index.d.ts +33 -33
  51. package/dist/server-security/index.d.ts +9 -9
  52. package/dist/thread/index.js +2 -2
  53. package/dist/thread/index.js.map +1 -1
  54. package/dist/vite/index.d.ts +2 -2
  55. package/dist/vite/index.js +102 -45
  56. package/dist/vite/index.js.map +1 -1
  57. package/dist/websocket/index.browser.js +3 -3
  58. package/dist/websocket/index.browser.js.map +1 -1
  59. package/dist/websocket/index.js +4 -4
  60. package/dist/websocket/index.js.map +1 -1
  61. package/package.json +14 -9
  62. package/src/api-audits/controllers/AuditController.ts +186 -0
  63. package/src/api-audits/entities/audits.ts +132 -0
  64. package/src/api-audits/index.browser.ts +18 -0
  65. package/src/api-audits/index.ts +58 -0
  66. package/src/api-audits/primitives/$audit.ts +159 -0
  67. package/src/api-audits/schemas/auditQuerySchema.ts +23 -0
  68. package/src/api-audits/schemas/auditResourceSchema.ts +9 -0
  69. package/src/api-audits/schemas/createAuditSchema.ts +27 -0
  70. package/src/api-audits/services/AuditService.ts +412 -0
  71. package/src/api-parameters/controllers/ConfigController.ts +324 -0
  72. package/src/api-parameters/entities/parameters.ts +93 -10
  73. package/src/api-parameters/index.ts +43 -4
  74. package/src/api-parameters/primitives/$config.ts +291 -19
  75. package/src/api-parameters/schedulers/ConfigActivationScheduler.ts +30 -0
  76. package/src/api-parameters/services/ConfigStore.ts +491 -0
  77. package/src/api-users/atoms/realmAuthSettingsAtom.ts +19 -0
  78. package/src/api-users/controllers/UserRealmController.ts +0 -2
  79. package/src/api-users/index.ts +2 -0
  80. package/src/api-users/primitives/$userRealm.ts +18 -3
  81. package/src/api-users/providers/UserRealmProvider.ts +6 -3
  82. package/src/api-users/services/RegistrationService.ts +2 -1
  83. package/src/api-users/services/SessionService.ts +4 -0
  84. package/src/api-users/services/UserService.ts +3 -0
  85. package/src/api-verifications/index.ts +7 -1
  86. package/src/bin/index.ts +1 -0
  87. package/src/cli/assets/biomeJson.ts +1 -1
  88. package/src/cli/assets/dummySpecTs.ts +7 -0
  89. package/src/cli/assets/editorconfig.ts +13 -0
  90. package/src/cli/assets/mainTs.ts +14 -0
  91. package/src/cli/commands/BiomeCommands.ts +2 -0
  92. package/src/cli/commands/CoreCommands.ts +28 -9
  93. package/src/cli/commands/VerifyCommands.ts +2 -1
  94. package/src/cli/commands/ViteCommands.ts +8 -9
  95. package/src/cli/services/AlephaCliUtils.ts +214 -23
  96. package/src/command/helpers/Asker.ts +0 -1
  97. package/src/command/primitives/$command.ts +67 -0
  98. package/src/command/providers/CliProvider.ts +39 -8
  99. package/src/core/Alepha.ts +40 -30
  100. package/src/core/helpers/jsonSchemaToTypeBox.ts +307 -0
  101. package/src/core/index.shared.ts +1 -0
  102. package/src/core/index.ts +30 -3
  103. package/src/core/providers/EventManager.ts +1 -1
  104. package/src/core/providers/StateManager.ts +23 -12
  105. package/src/core/providers/TypeProvider.ts +26 -34
  106. package/src/logger/index.ts +8 -6
  107. package/src/logger/primitives/$logger.ts +1 -1
  108. package/src/logger/providers/{SimpleFormatterProvider.ts → PrettyFormatterProvider.ts} +10 -1
  109. package/src/orm/index.ts +6 -0
  110. package/src/orm/services/PgRelationManager.ts +2 -2
  111. package/src/orm/services/PostgresModelBuilder.ts +11 -7
  112. package/src/orm/services/Repository.ts +16 -7
  113. package/src/orm/services/SqliteModelBuilder.ts +10 -0
  114. package/src/server/index.ts +6 -0
  115. package/src/server/primitives/$action.ts +10 -1
  116. package/src/server/providers/ServerBodyParserProvider.ts +11 -5
  117. package/src/server/providers/ServerRouterProvider.ts +13 -7
  118. package/src/server-auth/primitives/$auth.ts +7 -0
  119. package/src/server-auth/providers/ServerAuthProvider.ts +51 -8
  120. package/src/server-cookies/index.ts +2 -1
  121. package/src/thread/primitives/$thread.ts +2 -2
  122. package/src/vite/index.ts +0 -2
  123. package/src/vite/tasks/buildServer.ts +3 -4
  124. package/src/vite/tasks/generateCloudflare.ts +35 -19
  125. package/src/vite/tasks/generateDocker.ts +18 -4
  126. package/src/vite/tasks/generateSitemap.ts +5 -7
  127. package/src/vite/tasks/generateVercel.ts +76 -41
  128. package/src/vite/tasks/runAlepha.ts +16 -1
  129. package/src/websocket/providers/NodeWebSocketServerProvider.ts +3 -11
  130. package/src/websocket/services/WebSocketClient.ts +3 -3
  131. package/dist/cli/dist-BlfFtOk2.js +0 -2770
  132. package/dist/cli/dist-BlfFtOk2.js.map +0 -1
  133. package/src/api-parameters/controllers/ParameterController.ts +0 -45
  134. package/src/api-parameters/services/ParameterStore.ts +0 -23
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["contextData: Partial<CreateAudit>","stats: AuditStats","t","definition: AuditTypeDefinition"],"sources":["../../src/api-audits/entities/audits.ts","../../src/api-audits/schemas/auditQuerySchema.ts","../../src/api-audits/schemas/auditResourceSchema.ts","../../src/api-audits/schemas/createAuditSchema.ts","../../src/api-audits/services/AuditService.ts","../../src/api-audits/controllers/AuditController.ts","../../src/api-audits/primitives/$audit.ts","../../src/api-audits/index.ts"],"sourcesContent":["import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\nimport { $entity, pg } from \"alepha/orm\";\n\n/**\n * Audit severity levels for categorizing events.\n */\nexport const auditSeveritySchema = t.enum([\"info\", \"warning\", \"critical\"], {\n default: \"info\",\n description: \"Severity level of the audit event\",\n});\n\nexport type AuditSeverity = Static<typeof auditSeveritySchema>;\n\n/**\n * Audit log entity for tracking important system events.\n *\n * Stores comprehensive audit information including:\n * - Who performed the action (userId, userRealm)\n * - What happened (type, action, resource)\n * - When it happened (createdAt)\n * - Context and details (metadata, ipAddress, userAgent)\n */\nexport const audits = $entity({\n name: \"audits\",\n schema: t.object({\n id: pg.primaryKey(t.bigint()),\n createdAt: pg.createdAt(),\n\n /**\n * Audit event type (e.g., \"auth\", \"user\", \"payment\", \"system\").\n * Used for categorizing and filtering audit events.\n */\n type: t.text({\n description: \"Audit event type (e.g., auth, user, payment, system)\",\n }),\n\n /**\n * Specific action performed (e.g., \"login\", \"logout\", \"create\", \"update\", \"delete\").\n */\n action: t.text({\n description: \"Specific action performed (e.g., login, create, update)\",\n }),\n\n /**\n * Severity level of the event.\n */\n severity: pg.default(auditSeveritySchema, \"info\"),\n\n /**\n * User ID who performed the action (null for system events).\n */\n userId: t.optional(t.uuid()),\n\n /**\n * User realm for multi-tenant support.\n */\n userRealm: t.optional(t.text()),\n\n /**\n * User email at the time of the event (denormalized for history).\n */\n userEmail: t.optional(t.email()),\n\n /**\n * Resource type affected (e.g., \"user\", \"order\", \"file\").\n */\n resourceType: t.optional(t.text()),\n\n /**\n * Resource ID affected.\n */\n resourceId: t.optional(t.text()),\n\n /**\n * Human-readable description of the event.\n */\n description: t.optional(t.text()),\n\n /**\n * Additional metadata/context as JSON.\n */\n metadata: t.optional(t.json()),\n\n /**\n * Client IP address.\n */\n ipAddress: t.optional(t.text()),\n\n /**\n * Client user agent.\n */\n userAgent: t.optional(t.text()),\n\n /**\n * Session ID if applicable.\n */\n sessionId: t.optional(t.uuid()),\n\n /**\n * Request ID for correlation.\n */\n requestId: t.optional(t.text()),\n\n /**\n * Whether the action was successful.\n */\n success: pg.default(t.boolean(), true),\n\n /**\n * Error message if the action failed.\n */\n errorMessage: t.optional(t.text()),\n }),\n indexes: [\n \"createdAt\",\n \"type\",\n \"action\",\n \"userId\",\n \"userRealm\",\n \"resourceType\",\n \"resourceId\",\n \"severity\",\n { columns: [\"type\", \"action\"] },\n { columns: [\"userId\", \"createdAt\"] },\n { columns: [\"userRealm\", \"createdAt\"] },\n ],\n});\n\nexport const auditEntitySchema = audits.schema;\nexport const auditEntityInsertSchema = audits.insertSchema;\nexport type AuditEntity = Static<typeof audits.schema>;\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\nimport { pageQuerySchema } from \"alepha/orm\";\nimport { auditSeveritySchema } from \"../entities/audits.ts\";\n\n/**\n * Query schema for searching and filtering audit logs.\n */\nexport const auditQuerySchema = t.extend(pageQuerySchema, {\n type: t.optional(t.text({ description: \"Filter by audit type\" })),\n action: t.optional(t.text({ description: \"Filter by action\" })),\n severity: t.optional(auditSeveritySchema),\n userId: t.optional(t.uuid({ description: \"Filter by user ID\" })),\n userRealm: t.optional(t.text({ description: \"Filter by user realm\" })),\n resourceType: t.optional(t.text({ description: \"Filter by resource type\" })),\n resourceId: t.optional(t.text({ description: \"Filter by resource ID\" })),\n success: t.optional(t.boolean({ description: \"Filter by success status\" })),\n from: t.optional(t.datetime({ description: \"Start date filter\" })),\n to: t.optional(t.datetime({ description: \"End date filter\" })),\n search: t.optional(t.text({ description: \"Search in description\" })),\n});\n\nexport type AuditQuery = Static<typeof auditQuerySchema>;\n","import type { Static } from \"alepha\";\nimport { audits } from \"../entities/audits.ts\";\n\n/**\n * Resource schema for audit log responses.\n */\nexport const auditResourceSchema = audits.schema;\n\nexport type AuditResource = Static<typeof auditResourceSchema>;\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\nimport { auditSeveritySchema } from \"../entities/audits.ts\";\n\n/**\n * Schema for creating a new audit log entry.\n */\nexport const createAuditSchema = t.object({\n type: t.text({ description: \"Audit event type\" }),\n action: t.text({ description: \"Specific action performed\" }),\n severity: t.optional(auditSeveritySchema),\n userId: t.optional(t.uuid()),\n userRealm: t.optional(t.text()),\n userEmail: t.optional(t.email()),\n resourceType: t.optional(t.text()),\n resourceId: t.optional(t.text()),\n description: t.optional(t.text()),\n metadata: t.optional(t.json()),\n ipAddress: t.optional(t.text()),\n userAgent: t.optional(t.text()),\n sessionId: t.optional(t.uuid()),\n requestId: t.optional(t.text()),\n success: t.optional(t.boolean()),\n errorMessage: t.optional(t.text()),\n});\n\nexport type CreateAudit = Static<typeof createAuditSchema>;\n","import { $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { $repository, type Page } from \"alepha/orm\";\nimport type { ServerRequest } from \"alepha/server\";\nimport {\n type AuditEntity,\n type AuditSeverity,\n audits,\n} from \"../entities/audits.ts\";\nimport type { AuditQuery } from \"../schemas/auditQuerySchema.ts\";\nimport type { CreateAudit } from \"../schemas/createAuditSchema.ts\";\n\n/**\n * Registered audit type definition.\n */\nexport interface AuditTypeDefinition {\n type: string;\n description?: string;\n actions: string[];\n}\n\n/**\n * Service for managing audit logs.\n *\n * Provides methods for:\n * - Creating audit entries\n * - Querying audit history\n * - Aggregating audit statistics\n * - Managing registered audit types\n */\nexport class AuditService {\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n protected readonly repo = $repository(audits);\n\n /**\n * Registry of audit types and their allowed actions.\n */\n protected readonly auditTypes = new Map<string, AuditTypeDefinition>();\n\n /**\n * Register an audit type with its allowed actions.\n */\n public registerType(definition: AuditTypeDefinition): void {\n this.auditTypes.set(definition.type, definition);\n this.log.debug(\"Audit type registered\", {\n type: definition.type,\n actions: definition.actions,\n });\n }\n\n /**\n * Get all registered audit types.\n */\n public getRegisteredTypes(): AuditTypeDefinition[] {\n return Array.from(this.auditTypes.values());\n }\n\n /**\n * Get current request context if available.\n */\n protected getRequestContext(): ServerRequest | undefined {\n return this.alepha.context.get<ServerRequest>(\"request\");\n }\n\n /**\n * Create a new audit log entry.\n * Automatically populates ipAddress, userAgent, and requestId from the current request context.\n */\n public async create(data: CreateAudit): Promise<AuditEntity> {\n const request = this.getRequestContext();\n\n // Auto-populate from request context if not provided\n const contextData: Partial<CreateAudit> = {};\n\n if (request) {\n if (!data.ipAddress && request.ip) {\n contextData.ipAddress = request.ip;\n }\n if (!data.userAgent && request.headers[\"user-agent\"]) {\n contextData.userAgent = request.headers[\"user-agent\"];\n }\n if (!data.requestId && request.requestId) {\n contextData.requestId = request.requestId;\n }\n // Check for session in metadata\n if (!data.sessionId && request.metadata?.sessionId) {\n contextData.sessionId = request.metadata.sessionId;\n }\n // Extract user from request.user (set by ServerSecurityProvider)\n const user = request.user;\n if (user) {\n if (!data.userId && user.id) {\n contextData.userId = user.id;\n }\n if (!data.userEmail && user.email) {\n contextData.userEmail = user.email;\n }\n if (!data.userRealm && user.realm) {\n contextData.userRealm = user.realm;\n }\n }\n }\n\n this.log.trace(\"Creating audit entry\", {\n type: data.type,\n action: data.action,\n userId: data.userId ?? contextData.userId,\n });\n\n const entry = await this.repo.create({\n ...contextData,\n ...data,\n severity: data.severity ?? \"info\",\n success: data.success ?? true,\n });\n\n this.log.debug(\"Audit entry created\", {\n id: entry.id,\n type: data.type,\n action: data.action,\n });\n\n return entry;\n }\n\n /**\n * Record an audit event (convenience method).\n */\n public async record(\n type: string,\n action: string,\n options: Omit<CreateAudit, \"type\" | \"action\"> = {},\n ): Promise<AuditEntity> {\n return this.create({ type, action, ...options });\n }\n\n /**\n * Record an authentication event.\n */\n public async recordAuth(\n action:\n | \"login\"\n | \"logout\"\n | \"login_failed\"\n | \"token_refresh\"\n | \"mfa_setup\"\n | \"mfa_verify\",\n options: Omit<CreateAudit, \"type\" | \"action\"> = {},\n ): Promise<AuditEntity> {\n return this.create({\n type: \"auth\",\n action,\n severity: action === \"login_failed\" ? \"warning\" : \"info\",\n ...options,\n });\n }\n\n /**\n * Record a user management event.\n */\n public async recordUser(\n action:\n | \"create\"\n | \"update\"\n | \"delete\"\n | \"enable\"\n | \"disable\"\n | \"role_change\",\n options: Omit<CreateAudit, \"type\" | \"action\"> = {},\n ): Promise<AuditEntity> {\n return this.create({\n type: \"user\",\n action,\n resourceType: \"user\",\n ...options,\n });\n }\n\n /**\n * Record a data access event.\n */\n public async recordAccess(\n action: \"view\" | \"export\" | \"download\",\n options: Omit<CreateAudit, \"type\" | \"action\"> = {},\n ): Promise<AuditEntity> {\n return this.create({ type: \"access\", action, ...options });\n }\n\n /**\n * Record a security event.\n */\n public async recordSecurity(\n action:\n | \"permission_denied\"\n | \"suspicious_activity\"\n | \"rate_limited\"\n | \"blocked\",\n options: Omit<CreateAudit, \"type\" | \"action\"> = {},\n ): Promise<AuditEntity> {\n return this.create({\n type: \"security\",\n action,\n severity: \"warning\",\n ...options,\n });\n }\n\n /**\n * Record a system event.\n */\n public async recordSystem(\n action: \"startup\" | \"shutdown\" | \"config_change\" | \"maintenance\" | \"error\",\n options: Omit<CreateAudit, \"type\" | \"action\"> = {},\n ): Promise<AuditEntity> {\n return this.create({\n type: \"system\",\n action,\n severity: action === \"error\" ? \"critical\" : \"info\",\n ...options,\n });\n }\n\n /**\n * Find audit entries with filtering and pagination.\n */\n public async find(query: AuditQuery = {}): Promise<Page<AuditEntity>> {\n this.log.trace(\"Finding audit entries\", { query });\n\n query.sort ??= \"-createdAt\";\n\n const where = this.repo.createQueryWhere();\n\n if (query.type) {\n where.type = { eq: query.type };\n }\n\n if (query.action) {\n where.action = { eq: query.action };\n }\n\n if (query.severity) {\n where.severity = { eq: query.severity };\n }\n\n if (query.userId) {\n where.userId = { eq: query.userId };\n }\n\n if (query.userRealm) {\n where.userRealm = { eq: query.userRealm };\n }\n\n if (query.resourceType) {\n where.resourceType = { eq: query.resourceType };\n }\n\n if (query.resourceId) {\n where.resourceId = { eq: query.resourceId };\n }\n\n if (query.success !== undefined) {\n where.success = { eq: query.success };\n }\n\n if (query.from) {\n where.createdAt = { ...(where.createdAt as object), gte: query.from };\n }\n\n if (query.to) {\n where.createdAt = { ...(where.createdAt as object), lte: query.to };\n }\n\n if (query.search) {\n where.description = { like: `%${query.search}%` };\n }\n\n const result = await this.repo.paginate(query, { where }, { count: true });\n\n this.log.debug(\"Audit entries found\", {\n count: result.content.length,\n total: result.page.totalElements,\n });\n\n return result;\n }\n\n /**\n * Get audit entry by ID.\n */\n public async getById(id: string): Promise<AuditEntity> {\n return this.repo.findById(id);\n }\n\n /**\n * Get audit entries for a specific user.\n */\n public async findByUser(\n userId: string,\n query: Omit<AuditQuery, \"userId\"> = {},\n ): Promise<Page<AuditEntity>> {\n return this.find({ ...query, userId });\n }\n\n /**\n * Get audit entries for a specific resource.\n */\n public async findByResource(\n resourceType: string,\n resourceId: string,\n query: Omit<AuditQuery, \"resourceType\" | \"resourceId\"> = {},\n ): Promise<Page<AuditEntity>> {\n return this.find({ ...query, resourceType, resourceId });\n }\n\n /**\n * Get audit statistics for a time period.\n */\n public async getStats(\n options: { from?: Date; to?: Date; userRealm?: string } = {},\n ): Promise<AuditStats> {\n this.log.trace(\"Getting audit stats\", options);\n\n const where = this.repo.createQueryWhere();\n\n if (options.from) {\n where.createdAt = { gte: options.from.toISOString() };\n }\n\n if (options.to) {\n where.createdAt = {\n ...(where.createdAt as object),\n lte: options.to.toISOString(),\n };\n }\n\n if (options.userRealm) {\n where.userRealm = { eq: options.userRealm };\n }\n\n const all = await this.repo.findMany({ where });\n\n const stats: AuditStats = {\n total: all.length,\n byType: {},\n bySeverity: { info: 0, warning: 0, critical: 0 },\n successRate: 0,\n recentFailures: [],\n };\n\n let successCount = 0;\n\n for (const entry of all) {\n // Count by type\n stats.byType[entry.type] = (stats.byType[entry.type] || 0) + 1;\n\n // Count by severity\n const severity = entry.severity as AuditSeverity;\n stats.bySeverity[severity]++;\n\n // Count successes\n if (entry.success) {\n successCount++;\n }\n }\n\n stats.successRate = stats.total > 0 ? successCount / stats.total : 1;\n\n // Get recent failures\n const failures = all\n .filter((e) => !e.success)\n .sort(\n (a, b) =>\n new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),\n )\n .slice(0, 10);\n\n stats.recentFailures = failures;\n\n return stats;\n }\n\n /**\n * Delete old audit entries (for retention policy).\n */\n public async deleteOlderThan(date: Date): Promise<number> {\n this.log.info(\"Deleting old audit entries\", { olderThan: date });\n\n const old = await this.repo.findMany({\n where: { createdAt: { lt: date.toISOString() } },\n });\n\n for (const entry of old) {\n await this.repo.deleteById(entry.id);\n }\n\n this.log.info(\"Old audit entries deleted\", { count: old.length });\n\n return old.length;\n }\n}\n\n/**\n * Audit statistics summary.\n */\nexport interface AuditStats {\n total: number;\n byType: Record<string, number>;\n bySeverity: Record<AuditSeverity, number>;\n successRate: number;\n recentFailures: AuditEntity[];\n}\n","import { $inject, t } from \"alepha\";\nimport { pg } from \"alepha/orm\";\nimport { $action } from \"alepha/server\";\nimport { auditQuerySchema } from \"../schemas/auditQuerySchema.ts\";\nimport { auditResourceSchema } from \"../schemas/auditResourceSchema.ts\";\nimport { createAuditSchema } from \"../schemas/createAuditSchema.ts\";\nimport { AuditService } from \"../services/AuditService.ts\";\n\n/**\n * REST API controller for audit log management.\n *\n * Provides endpoints for:\n * - Querying audit logs with filtering\n * - Creating audit entries\n * - Getting audit statistics\n * - Viewing registered audit types\n */\nexport class AuditController {\n protected readonly url = \"/audits\";\n protected readonly group = \"audits\";\n protected readonly auditService = $inject(AuditService);\n\n /**\n * Find audit entries with filtering and pagination.\n */\n public readonly findAudits = $action({\n path: this.url,\n group: this.group,\n description: \"Find audit entries with filtering and pagination\",\n schema: {\n query: auditQuerySchema,\n response: pg.page(auditResourceSchema),\n },\n handler: ({ query }) => this.auditService.find(query),\n });\n\n /**\n * Get a single audit entry by ID.\n */\n public readonly getAudit = $action({\n path: `${this.url}/:id`,\n group: this.group,\n description: \"Get a single audit entry by ID\",\n schema: {\n params: t.object({\n id: t.text(),\n }),\n response: auditResourceSchema,\n },\n handler: ({ params }) => this.auditService.getById(params.id),\n });\n\n /**\n * Create a new audit entry.\n */\n public readonly createAudit = $action({\n method: \"POST\",\n path: this.url,\n group: this.group,\n description: \"Create a new audit entry\",\n schema: {\n body: createAuditSchema,\n response: auditResourceSchema,\n },\n handler: ({ body }) => this.auditService.create(body),\n });\n\n /**\n * Get audit entries for a specific user.\n */\n public readonly findByUser = $action({\n path: `${this.url}/user/:userId`,\n group: this.group,\n description: \"Get audit entries for a specific user\",\n schema: {\n params: t.object({\n userId: t.uuid(),\n }),\n query: t.omit(auditQuerySchema, [\"userId\"]),\n response: pg.page(auditResourceSchema),\n },\n handler: ({ params, query }) =>\n this.auditService.findByUser(params.userId, query),\n });\n\n /**\n * Get audit entries for a specific resource.\n */\n public readonly findByResource = $action({\n path: `${this.url}/resource/:resourceType/:resourceId`,\n group: this.group,\n description: \"Get audit entries for a specific resource\",\n schema: {\n params: t.object({\n resourceType: t.text(),\n resourceId: t.text(),\n }),\n query: t.omit(auditQuerySchema, [\"resourceType\", \"resourceId\"]),\n response: pg.page(auditResourceSchema),\n },\n handler: ({ params, query }) =>\n this.auditService.findByResource(\n params.resourceType,\n params.resourceId,\n query,\n ),\n });\n\n /**\n * Get audit statistics.\n */\n public readonly getStats = $action({\n path: `${this.url}/stats`,\n group: this.group,\n description: \"Get audit statistics for a time period\",\n schema: {\n query: t.object({\n from: t.optional(t.datetime()),\n to: t.optional(t.datetime()),\n userRealm: t.optional(t.text()),\n }),\n response: t.object({\n total: t.integer(),\n byType: t.record(t.text(), t.integer()),\n bySeverity: t.object({\n info: t.integer(),\n warning: t.integer(),\n critical: t.integer(),\n }),\n successRate: t.number(),\n recentFailures: t.array(auditResourceSchema),\n }),\n },\n handler: ({ query }) =>\n this.auditService.getStats({\n from: query.from ? new Date(query.from) : undefined,\n to: query.to ? new Date(query.to) : undefined,\n userRealm: query.userRealm,\n }),\n });\n\n /**\n * Get registered audit types.\n */\n public readonly getTypes = $action({\n path: `${this.url}/types`,\n group: this.group,\n description: \"Get all registered audit types\",\n schema: {\n response: t.array(\n t.object({\n type: t.text(),\n description: t.optional(t.text()),\n actions: t.array(t.text()),\n }),\n ),\n },\n handler: () => this.auditService.getRegisteredTypes(),\n });\n\n /**\n * Get distinct values for filters.\n */\n public readonly getFilterOptions = $action({\n path: `${this.url}/filters`,\n group: this.group,\n description: \"Get distinct values for audit filters\",\n schema: {\n response: t.object({\n types: t.array(t.text()),\n actions: t.array(t.text()),\n resourceTypes: t.array(t.text()),\n userRealms: t.array(t.text()),\n }),\n },\n handler: async () => {\n const types = this.auditService.getRegisteredTypes();\n return {\n types: types.map((t) => t.type),\n actions: types.flatMap((t) => t.actions),\n resourceTypes: [\"user\", \"session\", \"file\", \"order\", \"payment\"],\n userRealms: [\"default\"],\n };\n },\n });\n}\n","import { $inject, createPrimitive, KIND, Primitive } from \"alepha\";\nimport {\n AuditService,\n type AuditTypeDefinition,\n} from \"../services/AuditService.ts\";\n\n/**\n * Options for creating an audit type primitive.\n */\nexport interface AuditPrimitiveOptions {\n /**\n * Unique audit type identifier (e.g., \"auth\", \"payment\", \"order\").\n */\n type: string;\n\n /**\n * Human-readable description of this audit type.\n */\n description?: string;\n\n /**\n * List of allowed actions for this audit type.\n */\n actions: string[];\n}\n\n/**\n * Audit type primitive for registering domain-specific audit events.\n *\n * Provides a type-safe way to define and log audit events within a specific domain.\n *\n * @example\n * ```ts\n * class PaymentAudits {\n * audit = $audit({\n * type: \"payment\",\n * description: \"Payment-related audit events\",\n * actions: [\"create\", \"refund\", \"cancel\", \"dispute\"],\n * });\n *\n * async logPaymentCreated(paymentId: string, userId: string, amount: number) {\n * await this.audit.log(\"create\", {\n * userId,\n * resourceType: \"payment\",\n * resourceId: paymentId,\n * description: `Payment of ${amount} created`,\n * metadata: { amount },\n * });\n * }\n * }\n * ```\n */\nexport class AuditPrimitive extends Primitive<AuditPrimitiveOptions> {\n protected readonly auditService = $inject(AuditService);\n\n /**\n * The audit type identifier.\n */\n public get type(): string {\n return this.options.type;\n }\n\n /**\n * The audit type description.\n */\n public get description(): string | undefined {\n return this.options.description;\n }\n\n /**\n * The allowed actions for this audit type.\n */\n public get actions(): string[] {\n return this.options.actions;\n }\n\n /**\n * Log an audit event for this type.\n */\n public async log(\n action: string,\n options: AuditLogOptions = {},\n ): Promise<void> {\n await this.auditService.record(this.options.type, action, options);\n }\n\n /**\n * Log a successful audit event.\n */\n public async logSuccess(\n action: string,\n options: Omit<AuditLogOptions, \"success\"> = {},\n ): Promise<void> {\n await this.log(action, { ...options, success: true });\n }\n\n /**\n * Log a failed audit event.\n */\n public async logFailure(\n action: string,\n errorMessage: string,\n options: Omit<AuditLogOptions, \"success\" | \"errorMessage\"> = {},\n ): Promise<void> {\n await this.log(action, { ...options, success: false, errorMessage });\n }\n\n /**\n * Called during initialization to register this audit type.\n */\n protected onInit(): void {\n const definition: AuditTypeDefinition = {\n type: this.options.type,\n description: this.options.description,\n actions: this.options.actions,\n };\n this.auditService.registerType(definition);\n }\n}\n\n/**\n * Options for logging an audit event.\n */\nexport interface AuditLogOptions {\n severity?: \"info\" | \"warning\" | \"critical\";\n userId?: string;\n userRealm?: string;\n userEmail?: string;\n resourceType?: string;\n resourceId?: string;\n description?: string;\n metadata?: Record<string, unknown>;\n ipAddress?: string;\n userAgent?: string;\n sessionId?: string;\n requestId?: string;\n success?: boolean;\n errorMessage?: string;\n}\n\n/**\n * Create an audit type primitive.\n *\n * @example\n * ```ts\n * class OrderAudits {\n * audit = $audit({\n * type: \"order\",\n * description: \"Order management events\",\n * actions: [\"create\", \"update\", \"cancel\", \"fulfill\", \"ship\"],\n * });\n * }\n * ```\n */\nexport const $audit = (options: AuditPrimitiveOptions) => {\n return createPrimitive(AuditPrimitive, options);\n};\n\n$audit[KIND] = AuditPrimitive;\n","import { $module } from \"alepha\";\nimport { AuditController } from \"./controllers/AuditController.ts\";\nimport { AuditService } from \"./services/AuditService.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./controllers/AuditController.ts\";\nexport * from \"./entities/audits.ts\";\nexport * from \"./primitives/$audit.ts\";\nexport * from \"./schemas/auditQuerySchema.ts\";\nexport * from \"./schemas/auditResourceSchema.ts\";\nexport * from \"./schemas/createAuditSchema.ts\";\nexport * from \"./services/AuditService.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Provides audit logging API endpoints for Alepha applications.\n *\n * This module includes:\n * - Audit log CRUD operations\n * - Filtering and searching audit events\n * - Audit statistics and analytics\n * - `$audit` primitive for domain-specific audit types\n *\n * @module alepha.api.audits\n *\n * @example\n * ```ts\n * // In your app module\n * import { AlephaApiAudits } from \"alepha/api/audits\";\n *\n * const App = $module({\n * name: \"app\",\n * services: [AlephaApiAudits, ...],\n * });\n *\n * // Create domain-specific audit types\n * class PaymentAudits {\n * audit = $audit({\n * type: \"payment\",\n * actions: [\"create\", \"refund\", \"cancel\"],\n * });\n *\n * async onPaymentCreated(paymentId: string, userId: string) {\n * await this.audit.log(\"create\", {\n * userId,\n * resourceType: \"payment\",\n * resourceId: paymentId,\n * });\n * }\n * }\n * ```\n */\nexport const AlephaApiAudits = $module({\n name: \"alepha.api.audits\",\n services: [AuditService, AuditController],\n});\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import * as alepha45 from "alepha";
1
+ import * as alepha192 from "alepha";
2
2
  import { Alepha, KIND, Primitive, Static, StaticEncode, TObject } from "alepha";
3
- import * as alepha_orm15 from "alepha/orm";
3
+ import * as alepha_orm83 from "alepha/orm";
4
4
  import { Page } from "alepha/orm";
5
5
  import * as alepha_server0 from "alepha/server";
6
6
  import * as alepha_batch0 from "alepha/batch";
@@ -11,47 +11,47 @@ import { EmailProvider } from "alepha/email";
11
11
  import { SmsProvider } from "alepha/sms";
12
12
 
13
13
  //#region ../../src/api-notifications/entities/notifications.d.ts
14
- declare const notifications: alepha_orm15.EntityPrimitive<alepha45.TObject<{
15
- id: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_PRIMARY_KEY>, typeof alepha_orm15.PG_DEFAULT>;
16
- version: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TInteger, typeof alepha_orm15.PG_VERSION>, typeof alepha_orm15.PG_DEFAULT>;
17
- createdAt: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_CREATED_AT>, typeof alepha_orm15.PG_DEFAULT>;
18
- updatedAt: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_UPDATED_AT>, typeof alepha_orm15.PG_DEFAULT>;
19
- type: alepha45.TUnsafe<"email" | "sms">;
20
- template: alepha45.TString;
21
- category: alepha45.TOptional<alepha45.TString>;
22
- critical: alepha45.TOptional<alepha45.TBoolean>;
23
- sensitive: alepha45.TOptional<alepha45.TBoolean>;
24
- contact: alepha45.TString;
25
- variables: alepha45.TOptional<alepha45.TRecord<"^.*$", alepha45.TAny>>;
26
- scheduledAt: alepha45.TOptional<alepha45.TString>;
27
- sentAt: alepha45.TOptional<alepha45.TString>;
28
- error: alepha45.TOptional<alepha45.TObject<{
29
- at: alepha45.TString;
30
- name: alepha45.TString;
31
- message: alepha45.TString;
14
+ declare const notifications: alepha_orm83.EntityPrimitive<alepha192.TObject<{
15
+ id: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_PRIMARY_KEY>, typeof alepha_orm83.PG_DEFAULT>;
16
+ version: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TInteger, typeof alepha_orm83.PG_VERSION>, typeof alepha_orm83.PG_DEFAULT>;
17
+ createdAt: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_CREATED_AT>, typeof alepha_orm83.PG_DEFAULT>;
18
+ updatedAt: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_UPDATED_AT>, typeof alepha_orm83.PG_DEFAULT>;
19
+ type: alepha192.TUnsafe<"email" | "sms">;
20
+ template: alepha192.TString;
21
+ category: alepha192.TOptional<alepha192.TString>;
22
+ critical: alepha192.TOptional<alepha192.TBoolean>;
23
+ sensitive: alepha192.TOptional<alepha192.TBoolean>;
24
+ contact: alepha192.TString;
25
+ variables: alepha192.TOptional<alepha192.TRecord<"^.*$", alepha192.TAny>>;
26
+ scheduledAt: alepha192.TOptional<alepha192.TString>;
27
+ sentAt: alepha192.TOptional<alepha192.TString>;
28
+ error: alepha192.TOptional<alepha192.TObject<{
29
+ at: alepha192.TString;
30
+ name: alepha192.TString;
31
+ message: alepha192.TString;
32
32
  }>>;
33
33
  }>>;
34
34
  type NotificationEntity = Static<typeof notifications.schema>;
35
35
  //#endregion
36
36
  //#region ../../src/api-notifications/schemas/notificationCreateSchema.d.ts
37
- declare const notificationCreateSchema: alepha45.TObject<{
38
- type: alepha45.TUnsafe<"email" | "sms">;
39
- template: alepha45.TString;
40
- contact: alepha45.TString;
41
- variables: alepha45.TOptional<alepha45.TRecord<"^.*$", alepha45.TAny>>;
37
+ declare const notificationCreateSchema: alepha192.TObject<{
38
+ type: alepha192.TUnsafe<"email" | "sms">;
39
+ template: alepha192.TString;
40
+ contact: alepha192.TString;
41
+ variables: alepha192.TOptional<alepha192.TRecord<"^.*$", alepha192.TAny>>;
42
42
  }>;
43
43
  type NotificationCreate = Static<typeof notificationCreateSchema>;
44
44
  //#endregion
45
45
  //#region ../../src/api-notifications/schemas/notificationQuerySchema.d.ts
46
- declare const notificationQuerySchema: alepha45.TObject<{
47
- page: alepha45.TOptional<alepha45.TInteger>;
48
- size: alepha45.TOptional<alepha45.TInteger>;
49
- sort: alepha45.TOptional<alepha45.TString>;
50
- type: alepha45.TOptional<alepha45.TUnsafe<"email" | "sms">>;
51
- template: alepha45.TOptional<alepha45.TString>;
52
- contact: alepha45.TOptional<alepha45.TString>;
53
- category: alepha45.TOptional<alepha45.TString>;
54
- status: alepha45.TOptional<alepha45.TUnsafe<"pending" | "sent" | "failed">>;
46
+ declare const notificationQuerySchema: alepha192.TObject<{
47
+ page: alepha192.TOptional<alepha192.TInteger>;
48
+ size: alepha192.TOptional<alepha192.TInteger>;
49
+ sort: alepha192.TOptional<alepha192.TString>;
50
+ type: alepha192.TOptional<alepha192.TUnsafe<"email" | "sms">>;
51
+ template: alepha192.TOptional<alepha192.TString>;
52
+ contact: alepha192.TOptional<alepha192.TString>;
53
+ category: alepha192.TOptional<alepha192.TString>;
54
+ status: alepha192.TOptional<alepha192.TUnsafe<"pending" | "sent" | "failed">>;
55
55
  }>;
56
56
  type NotificationQuery = Static<typeof notificationQuerySchema>;
57
57
  //#endregion
@@ -123,24 +123,24 @@ interface NotificationMessage<T extends TObject> {
123
123
  declare class NotificationSenderService {
124
124
  protected readonly alepha: Alepha;
125
125
  protected readonly log: alepha_logger0.Logger;
126
- protected readonly notificationRepository: alepha_orm15.Repository<alepha45.TObject<{
127
- id: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_PRIMARY_KEY>, typeof alepha_orm15.PG_DEFAULT>;
128
- version: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TInteger, typeof alepha_orm15.PG_VERSION>, typeof alepha_orm15.PG_DEFAULT>;
129
- createdAt: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_CREATED_AT>, typeof alepha_orm15.PG_DEFAULT>;
130
- updatedAt: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_UPDATED_AT>, typeof alepha_orm15.PG_DEFAULT>;
131
- type: alepha45.TUnsafe<"email" | "sms">;
132
- template: alepha45.TString;
133
- category: alepha45.TOptional<alepha45.TString>;
134
- critical: alepha45.TOptional<alepha45.TBoolean>;
135
- sensitive: alepha45.TOptional<alepha45.TBoolean>;
136
- contact: alepha45.TString;
137
- variables: alepha45.TOptional<alepha45.TRecord<"^.*$", alepha45.TAny>>;
138
- scheduledAt: alepha45.TOptional<alepha45.TString>;
139
- sentAt: alepha45.TOptional<alepha45.TString>;
140
- error: alepha45.TOptional<alepha45.TObject<{
141
- at: alepha45.TString;
142
- name: alepha45.TString;
143
- message: alepha45.TString;
126
+ protected readonly notificationRepository: alepha_orm83.Repository<alepha192.TObject<{
127
+ id: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_PRIMARY_KEY>, typeof alepha_orm83.PG_DEFAULT>;
128
+ version: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TInteger, typeof alepha_orm83.PG_VERSION>, typeof alepha_orm83.PG_DEFAULT>;
129
+ createdAt: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_CREATED_AT>, typeof alepha_orm83.PG_DEFAULT>;
130
+ updatedAt: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_UPDATED_AT>, typeof alepha_orm83.PG_DEFAULT>;
131
+ type: alepha192.TUnsafe<"email" | "sms">;
132
+ template: alepha192.TString;
133
+ category: alepha192.TOptional<alepha192.TString>;
134
+ critical: alepha192.TOptional<alepha192.TBoolean>;
135
+ sensitive: alepha192.TOptional<alepha192.TBoolean>;
136
+ contact: alepha192.TString;
137
+ variables: alepha192.TOptional<alepha192.TRecord<"^.*$", alepha192.TAny>>;
138
+ scheduledAt: alepha192.TOptional<alepha192.TString>;
139
+ sentAt: alepha192.TOptional<alepha192.TString>;
140
+ error: alepha192.TOptional<alepha192.TObject<{
141
+ at: alepha192.TString;
142
+ name: alepha192.TString;
143
+ message: alepha192.TString;
144
144
  }>>;
145
145
  }>>;
146
146
  protected readonly dateTimeProvider: DateTimeProvider;
@@ -157,15 +157,15 @@ declare class NotificationSenderService {
157
157
  body: string;
158
158
  };
159
159
  protected load(notification: NotificationEntity): {
160
- template: NotificationPrimitive<alepha45.TObject<alepha45.TProperties>>;
160
+ template: NotificationPrimitive<alepha192.TObject<alepha192.TProperties>>;
161
161
  variables: Record<string, any>;
162
162
  contact: string;
163
163
  };
164
164
  }
165
165
  //#endregion
166
166
  //#region ../../src/api-notifications/services/NotificationService.d.ts
167
- declare const notificationServiceEnvSchema: alepha45.TObject<{
168
- NOTIFICATION_QUEUE: alepha45.TOptional<alepha45.TBoolean>;
167
+ declare const notificationServiceEnvSchema: alepha192.TObject<{
168
+ NOTIFICATION_QUEUE: alepha192.TOptional<alepha192.TBoolean>;
169
169
  }>;
170
170
  declare module "alepha" {
171
171
  interface Env extends Partial<Static<typeof notificationServiceEnvSchema>> {}
@@ -176,71 +176,71 @@ declare class NotificationService {
176
176
  protected readonly env: {
177
177
  NOTIFICATION_QUEUE?: boolean | undefined;
178
178
  };
179
- protected readonly notificationRepository: alepha_orm15.Repository<alepha45.TObject<{
180
- id: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_PRIMARY_KEY>, typeof alepha_orm15.PG_DEFAULT>;
181
- version: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TInteger, typeof alepha_orm15.PG_VERSION>, typeof alepha_orm15.PG_DEFAULT>;
182
- createdAt: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_CREATED_AT>, typeof alepha_orm15.PG_DEFAULT>;
183
- updatedAt: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_UPDATED_AT>, typeof alepha_orm15.PG_DEFAULT>;
184
- type: alepha45.TUnsafe<"email" | "sms">;
185
- template: alepha45.TString;
186
- category: alepha45.TOptional<alepha45.TString>;
187
- critical: alepha45.TOptional<alepha45.TBoolean>;
188
- sensitive: alepha45.TOptional<alepha45.TBoolean>;
189
- contact: alepha45.TString;
190
- variables: alepha45.TOptional<alepha45.TRecord<"^.*$", alepha45.TAny>>;
191
- scheduledAt: alepha45.TOptional<alepha45.TString>;
192
- sentAt: alepha45.TOptional<alepha45.TString>;
193
- error: alepha45.TOptional<alepha45.TObject<{
194
- at: alepha45.TString;
195
- name: alepha45.TString;
196
- message: alepha45.TString;
179
+ protected readonly notificationRepository: alepha_orm83.Repository<alepha192.TObject<{
180
+ id: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_PRIMARY_KEY>, typeof alepha_orm83.PG_DEFAULT>;
181
+ version: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TInteger, typeof alepha_orm83.PG_VERSION>, typeof alepha_orm83.PG_DEFAULT>;
182
+ createdAt: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_CREATED_AT>, typeof alepha_orm83.PG_DEFAULT>;
183
+ updatedAt: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_UPDATED_AT>, typeof alepha_orm83.PG_DEFAULT>;
184
+ type: alepha192.TUnsafe<"email" | "sms">;
185
+ template: alepha192.TString;
186
+ category: alepha192.TOptional<alepha192.TString>;
187
+ critical: alepha192.TOptional<alepha192.TBoolean>;
188
+ sensitive: alepha192.TOptional<alepha192.TBoolean>;
189
+ contact: alepha192.TString;
190
+ variables: alepha192.TOptional<alepha192.TRecord<"^.*$", alepha192.TAny>>;
191
+ scheduledAt: alepha192.TOptional<alepha192.TString>;
192
+ sentAt: alepha192.TOptional<alepha192.TString>;
193
+ error: alepha192.TOptional<alepha192.TObject<{
194
+ at: alepha192.TString;
195
+ name: alepha192.TString;
196
+ message: alepha192.TString;
197
197
  }>>;
198
198
  }>>;
199
199
  protected readonly dateTimeProvider: DateTimeProvider;
200
200
  protected readonly notificationSenderService: NotificationSenderService;
201
- readonly notificationBatch: alepha_batch0.BatchPrimitive<alepha45.TObject<{
202
- type: alepha45.TUnsafe<"email" | "sms">;
203
- template: alepha45.TString;
204
- contact: alepha45.TString;
205
- variables: alepha45.TOptional<alepha45.TRecord<"^.*$", alepha45.TAny>>;
201
+ readonly notificationBatch: alepha_batch0.BatchPrimitive<alepha192.TObject<{
202
+ type: alepha192.TUnsafe<"email" | "sms">;
203
+ template: alepha192.TString;
204
+ contact: alepha192.TString;
205
+ variables: alepha192.TOptional<alepha192.TRecord<"^.*$", alepha192.TAny>>;
206
206
  }>, Promise<void>>;
207
- findNotificationById(id: string): Promise<alepha_orm15.PgStatic<alepha45.TObject<{
208
- id: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_PRIMARY_KEY>, typeof alepha_orm15.PG_DEFAULT>;
209
- version: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TInteger, typeof alepha_orm15.PG_VERSION>, typeof alepha_orm15.PG_DEFAULT>;
210
- createdAt: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_CREATED_AT>, typeof alepha_orm15.PG_DEFAULT>;
211
- updatedAt: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_UPDATED_AT>, typeof alepha_orm15.PG_DEFAULT>;
212
- type: alepha45.TUnsafe<"email" | "sms">;
213
- template: alepha45.TString;
214
- category: alepha45.TOptional<alepha45.TString>;
215
- critical: alepha45.TOptional<alepha45.TBoolean>;
216
- sensitive: alepha45.TOptional<alepha45.TBoolean>;
217
- contact: alepha45.TString;
218
- variables: alepha45.TOptional<alepha45.TRecord<"^.*$", alepha45.TAny>>;
219
- scheduledAt: alepha45.TOptional<alepha45.TString>;
220
- sentAt: alepha45.TOptional<alepha45.TString>;
221
- error: alepha45.TOptional<alepha45.TObject<{
222
- at: alepha45.TString;
223
- name: alepha45.TString;
224
- message: alepha45.TString;
207
+ findNotificationById(id: string): Promise<alepha_orm83.PgStatic<alepha192.TObject<{
208
+ id: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_PRIMARY_KEY>, typeof alepha_orm83.PG_DEFAULT>;
209
+ version: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TInteger, typeof alepha_orm83.PG_VERSION>, typeof alepha_orm83.PG_DEFAULT>;
210
+ createdAt: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_CREATED_AT>, typeof alepha_orm83.PG_DEFAULT>;
211
+ updatedAt: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_UPDATED_AT>, typeof alepha_orm83.PG_DEFAULT>;
212
+ type: alepha192.TUnsafe<"email" | "sms">;
213
+ template: alepha192.TString;
214
+ category: alepha192.TOptional<alepha192.TString>;
215
+ critical: alepha192.TOptional<alepha192.TBoolean>;
216
+ sensitive: alepha192.TOptional<alepha192.TBoolean>;
217
+ contact: alepha192.TString;
218
+ variables: alepha192.TOptional<alepha192.TRecord<"^.*$", alepha192.TAny>>;
219
+ scheduledAt: alepha192.TOptional<alepha192.TString>;
220
+ sentAt: alepha192.TOptional<alepha192.TString>;
221
+ error: alepha192.TOptional<alepha192.TObject<{
222
+ at: alepha192.TString;
223
+ name: alepha192.TString;
224
+ message: alepha192.TString;
225
225
  }>>;
226
- }>, alepha_orm15.PgRelationMap<alepha45.TObject<{
227
- id: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_PRIMARY_KEY>, typeof alepha_orm15.PG_DEFAULT>;
228
- version: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TInteger, typeof alepha_orm15.PG_VERSION>, typeof alepha_orm15.PG_DEFAULT>;
229
- createdAt: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_CREATED_AT>, typeof alepha_orm15.PG_DEFAULT>;
230
- updatedAt: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_UPDATED_AT>, typeof alepha_orm15.PG_DEFAULT>;
231
- type: alepha45.TUnsafe<"email" | "sms">;
232
- template: alepha45.TString;
233
- category: alepha45.TOptional<alepha45.TString>;
234
- critical: alepha45.TOptional<alepha45.TBoolean>;
235
- sensitive: alepha45.TOptional<alepha45.TBoolean>;
236
- contact: alepha45.TString;
237
- variables: alepha45.TOptional<alepha45.TRecord<"^.*$", alepha45.TAny>>;
238
- scheduledAt: alepha45.TOptional<alepha45.TString>;
239
- sentAt: alepha45.TOptional<alepha45.TString>;
240
- error: alepha45.TOptional<alepha45.TObject<{
241
- at: alepha45.TString;
242
- name: alepha45.TString;
243
- message: alepha45.TString;
226
+ }>, alepha_orm83.PgRelationMap<alepha192.TObject<{
227
+ id: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_PRIMARY_KEY>, typeof alepha_orm83.PG_DEFAULT>;
228
+ version: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TInteger, typeof alepha_orm83.PG_VERSION>, typeof alepha_orm83.PG_DEFAULT>;
229
+ createdAt: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_CREATED_AT>, typeof alepha_orm83.PG_DEFAULT>;
230
+ updatedAt: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_UPDATED_AT>, typeof alepha_orm83.PG_DEFAULT>;
231
+ type: alepha192.TUnsafe<"email" | "sms">;
232
+ template: alepha192.TString;
233
+ category: alepha192.TOptional<alepha192.TString>;
234
+ critical: alepha192.TOptional<alepha192.TBoolean>;
235
+ sensitive: alepha192.TOptional<alepha192.TBoolean>;
236
+ contact: alepha192.TString;
237
+ variables: alepha192.TOptional<alepha192.TRecord<"^.*$", alepha192.TAny>>;
238
+ scheduledAt: alepha192.TOptional<alepha192.TString>;
239
+ sentAt: alepha192.TOptional<alepha192.TString>;
240
+ error: alepha192.TOptional<alepha192.TObject<{
241
+ at: alepha192.TString;
242
+ name: alepha192.TString;
243
+ message: alepha192.TString;
244
244
  }>>;
245
245
  }>>>>;
246
246
  findNotifications(q?: NotificationQuery): Promise<Page<NotificationEntity>>;
@@ -259,34 +259,34 @@ declare class NotificationController {
259
259
  * Find notifications with pagination and filtering.
260
260
  */
261
261
  readonly findNotifications: alepha_server0.ActionPrimitiveFn<{
262
- query: alepha45.TObject<{
263
- page: alepha45.TOptional<alepha45.TInteger>;
264
- size: alepha45.TOptional<alepha45.TInteger>;
265
- sort: alepha45.TOptional<alepha45.TString>;
266
- type: alepha45.TOptional<alepha45.TUnsafe<"email" | "sms">>;
267
- template: alepha45.TOptional<alepha45.TString>;
268
- contact: alepha45.TOptional<alepha45.TString>;
269
- category: alepha45.TOptional<alepha45.TString>;
270
- status: alepha45.TOptional<alepha45.TUnsafe<"pending" | "sent" | "failed">>;
262
+ query: alepha192.TObject<{
263
+ page: alepha192.TOptional<alepha192.TInteger>;
264
+ size: alepha192.TOptional<alepha192.TInteger>;
265
+ sort: alepha192.TOptional<alepha192.TString>;
266
+ type: alepha192.TOptional<alepha192.TUnsafe<"email" | "sms">>;
267
+ template: alepha192.TOptional<alepha192.TString>;
268
+ contact: alepha192.TOptional<alepha192.TString>;
269
+ category: alepha192.TOptional<alepha192.TString>;
270
+ status: alepha192.TOptional<alepha192.TUnsafe<"pending" | "sent" | "failed">>;
271
271
  }>;
272
- response: alepha45.TPage<alepha45.TObject<{
273
- id: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_PRIMARY_KEY>, typeof alepha_orm15.PG_DEFAULT>;
274
- version: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TInteger, typeof alepha_orm15.PG_VERSION>, typeof alepha_orm15.PG_DEFAULT>;
275
- createdAt: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_CREATED_AT>, typeof alepha_orm15.PG_DEFAULT>;
276
- updatedAt: alepha_orm15.PgAttr<alepha_orm15.PgAttr<alepha45.TString, typeof alepha_orm15.PG_UPDATED_AT>, typeof alepha_orm15.PG_DEFAULT>;
277
- type: alepha45.TUnsafe<"email" | "sms">;
278
- template: alepha45.TString;
279
- category: alepha45.TOptional<alepha45.TString>;
280
- critical: alepha45.TOptional<alepha45.TBoolean>;
281
- sensitive: alepha45.TOptional<alepha45.TBoolean>;
282
- contact: alepha45.TString;
283
- variables: alepha45.TOptional<alepha45.TRecord<"^.*$", alepha45.TAny>>;
284
- scheduledAt: alepha45.TOptional<alepha45.TString>;
285
- sentAt: alepha45.TOptional<alepha45.TString>;
286
- error: alepha45.TOptional<alepha45.TObject<{
287
- at: alepha45.TString;
288
- name: alepha45.TString;
289
- message: alepha45.TString;
272
+ response: alepha192.TPage<alepha192.TObject<{
273
+ id: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_PRIMARY_KEY>, typeof alepha_orm83.PG_DEFAULT>;
274
+ version: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TInteger, typeof alepha_orm83.PG_VERSION>, typeof alepha_orm83.PG_DEFAULT>;
275
+ createdAt: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_CREATED_AT>, typeof alepha_orm83.PG_DEFAULT>;
276
+ updatedAt: alepha_orm83.PgAttr<alepha_orm83.PgAttr<alepha192.TString, typeof alepha_orm83.PG_UPDATED_AT>, typeof alepha_orm83.PG_DEFAULT>;
277
+ type: alepha192.TUnsafe<"email" | "sms">;
278
+ template: alepha192.TString;
279
+ category: alepha192.TOptional<alepha192.TString>;
280
+ critical: alepha192.TOptional<alepha192.TBoolean>;
281
+ sensitive: alepha192.TOptional<alepha192.TBoolean>;
282
+ contact: alepha192.TString;
283
+ variables: alepha192.TOptional<alepha192.TRecord<"^.*$", alepha192.TAny>>;
284
+ scheduledAt: alepha192.TOptional<alepha192.TString>;
285
+ sentAt: alepha192.TOptional<alepha192.TString>;
286
+ error: alepha192.TOptional<alepha192.TObject<{
287
+ at: alepha192.TString;
288
+ name: alepha192.TString;
289
+ message: alepha192.TString;
290
290
  }>>;
291
291
  }>>;
292
292
  }>;
@@ -298,15 +298,15 @@ declare class NotificationJobs {}
298
298
  //#region ../../src/api-notifications/queues/NotificationQueues.d.ts
299
299
  declare class NotificationQueues {
300
300
  protected readonly notificationSenderService: NotificationSenderService;
301
- readonly processNotification: alepha_queue0.QueuePrimitive<alepha45.TObject<{
302
- notificationId: alepha45.TString;
301
+ readonly processNotification: alepha_queue0.QueuePrimitive<alepha192.TObject<{
302
+ notificationId: alepha192.TString;
303
303
  }>>;
304
304
  }
305
305
  //#endregion
306
306
  //#region ../../src/api-notifications/schemas/notificationContactPreferencesSchema.d.ts
307
- declare const notificationContactPreferencesSchema: alepha45.TObject<{
308
- language: alepha45.TOptional<alepha45.TString>;
309
- exclude: alepha45.TArray<alepha45.TString>;
307
+ declare const notificationContactPreferencesSchema: alepha192.TObject<{
308
+ language: alepha192.TOptional<alepha192.TString>;
309
+ exclude: alepha192.TArray<alepha192.TString>;
310
310
  }>;
311
311
  type NotificationContactPreferences = Static<typeof notificationContactPreferencesSchema>;
312
312
  //#endregion
@@ -321,7 +321,7 @@ type NotificationContactPreferences = Static<typeof notificationContactPreferenc
321
321
  *
322
322
  * @module alepha.api.notifications
323
323
  */
324
- declare const AlephaApiNotifications: alepha45.Service<alepha45.Module>;
324
+ declare const AlephaApiNotifications: alepha192.Service<alepha192.Module>;
325
325
  //#endregion
326
326
  export { $notification, AlephaApiNotifications, NotificationContactPreferences, NotificationController, NotificationCreate, NotificationEntity, NotificationJobs, NotificationMessage, NotificationPrimitive, NotificationPrimitiveOptions, NotificationPushOptions, NotificationQuery, NotificationQueues, NotificationSenderService, NotificationService, notificationContactPreferencesSchema, notificationCreateSchema, notificationQuerySchema, notificationServiceEnvSchema, notifications };
327
327
  //# sourceMappingURL=index.d.ts.map
@@ -2,19 +2,50 @@ import { $module, t } from "alepha";
2
2
  import { $entity, pg } from "alepha/orm";
3
3
 
4
4
  //#region ../../src/api-parameters/entities/parameters.ts
5
+ /**
6
+ * Configuration parameter entity for versioned configuration management.
7
+ *
8
+ * Stores all versions of configuration parameters with:
9
+ * - Automatic status management (expired, current, next, future)
10
+ * - Schema versioning for migrations
11
+ * - Activation scheduling
12
+ * - Audit trail (creator info)
13
+ */
5
14
  const parameters = $entity({
6
15
  name: "parameters",
7
16
  schema: t.object({
8
17
  id: pg.primaryKey(t.uuid()),
9
18
  createdAt: pg.createdAt(),
10
19
  updatedAt: pg.updatedAt(),
11
- name: t.string(),
20
+ name: t.text(),
12
21
  content: t.json(),
13
- tags: t.optional(t.array(t.string())),
22
+ schemaHash: t.text(),
23
+ status: pg.default(t.enum([
24
+ "expired",
25
+ "current",
26
+ "next",
27
+ "future"
28
+ ]), "future"),
29
+ activationDate: t.datetime(),
30
+ expiredAt: t.optional(t.datetime()),
31
+ version: t.integer(),
32
+ changeDescription: t.optional(t.text()),
33
+ tags: t.optional(t.array(t.text())),
14
34
  creatorId: t.optional(t.uuid()),
15
- creatorName: t.optional(t.string()),
16
- activationDate: t.datetime({ description: "Optional activation date. Default to now. Must be now or later." })
17
- })
35
+ creatorName: t.optional(t.text()),
36
+ previousContent: t.optional(t.json()),
37
+ migrationLog: t.optional(t.text())
38
+ }),
39
+ indexes: [
40
+ { columns: ["name", "status"] },
41
+ { columns: ["name", "activationDate"] },
42
+ {
43
+ columns: ["name", "version"],
44
+ unique: true
45
+ },
46
+ { columns: ["status"] },
47
+ { columns: ["activationDate"] }
48
+ ]
18
49
  });
19
50
 
20
51
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.browser.js","names":[],"sources":["../../src/api-parameters/entities/parameters.ts","../../src/api-parameters/index.browser.ts"],"sourcesContent":["import { type Static, t } from \"alepha\";\nimport { $entity, pg } from \"alepha/orm\";\n\nexport const parameters = $entity({\n name: \"parameters\",\n schema: t.object({\n id: pg.primaryKey(t.uuid()),\n\n createdAt: pg.createdAt(),\n\n updatedAt: pg.updatedAt(),\n\n name: t.string(),\n\n content: t.json(),\n\n tags: t.optional(t.array(t.string())),\n\n creatorId: t.optional(t.uuid()),\n\n creatorName: t.optional(t.string()),\n\n activationDate: t.datetime({\n description:\n \"Optional activation date. Default to now. Must be now or later.\",\n }),\n }),\n});\n\nexport type ParameterEntity = Static<typeof parameters.schema>;\n","import { $module } from \"alepha\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./entities/parameters.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport const AlephaApiParameters = $module({\n name: \"alepha.api.parameters\",\n services: [],\n});\n"],"mappings":";;;;AAGA,MAAa,aAAa,QAAQ;CAChC,MAAM;CACN,QAAQ,EAAE,OAAO;EACf,IAAI,GAAG,WAAW,EAAE,MAAM,CAAC;EAE3B,WAAW,GAAG,WAAW;EAEzB,WAAW,GAAG,WAAW;EAEzB,MAAM,EAAE,QAAQ;EAEhB,SAAS,EAAE,MAAM;EAEjB,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;EAErC,WAAW,EAAE,SAAS,EAAE,MAAM,CAAC;EAE/B,aAAa,EAAE,SAAS,EAAE,QAAQ,CAAC;EAEnC,gBAAgB,EAAE,SAAS,EACzB,aACE,mEACH,CAAC;EACH,CAAC;CACH,CAAC;;;;ACnBF,MAAa,sBAAsB,QAAQ;CACzC,MAAM;CACN,UAAU,EAAE;CACb,CAAC"}
1
+ {"version":3,"file":"index.browser.js","names":[],"sources":["../../src/api-parameters/entities/parameters.ts","../../src/api-parameters/index.browser.ts"],"sourcesContent":["import { type Static, t } from \"alepha\";\nimport { $entity, pg } from \"alepha/orm\";\n\n/**\n * Parameter status values.\n *\n * - EXPIRED: Past version, no longer active\n * - CURRENT: Currently active version\n * - NEXT: Scheduled to become active (closest future date)\n * - FUTURE: Scheduled for activation after NEXT\n */\nexport type ParameterStatus = \"expired\" | \"current\" | \"next\" | \"future\";\n\n/**\n * Configuration parameter entity for versioned configuration management.\n *\n * Stores all versions of configuration parameters with:\n * - Automatic status management (expired, current, next, future)\n * - Schema versioning for migrations\n * - Activation scheduling\n * - Audit trail (creator info)\n */\nexport const parameters = $entity({\n name: \"parameters\",\n schema: t.object({\n id: pg.primaryKey(t.uuid()),\n createdAt: pg.createdAt(),\n updatedAt: pg.updatedAt(),\n\n /**\n * Configuration name using dot notation for tree hierarchy.\n * Examples: \"app.features\", \"app.pricing.tiers\", \"system.limits\"\n */\n name: t.text(),\n\n /**\n * The configuration content as JSON.\n */\n content: t.json(),\n\n /**\n * Schema version hash for detecting schema changes.\n * Used for auto-migration when schema evolves.\n */\n schemaHash: t.text(),\n\n /**\n * Current status of this parameter version.\n */\n status: pg.default(\n t.enum([\"expired\", \"current\", \"next\", \"future\"]),\n \"future\",\n ),\n\n /**\n * When this version should become active.\n * Default is immediate (now).\n */\n activationDate: t.datetime(),\n\n /**\n * When this version was deactivated (became expired).\n * Null if still active or scheduled.\n */\n expiredAt: t.optional(t.datetime()),\n\n /**\n * Version number for this configuration.\n * Auto-incremented per config name.\n */\n version: t.integer(),\n\n /**\n * Optional description of changes in this version.\n */\n changeDescription: t.optional(t.text()),\n\n /**\n * Optional tags for filtering/categorization.\n */\n tags: t.optional(t.array(t.text())),\n\n /**\n * Creator user ID (if available).\n */\n creatorId: t.optional(t.uuid()),\n\n /**\n * Creator display name for audit trail.\n */\n creatorName: t.optional(t.text()),\n\n /**\n * Previous content before this change (for rollback reference).\n */\n previousContent: t.optional(t.json()),\n\n /**\n * Migration log if schema changed.\n */\n migrationLog: t.optional(t.text()),\n }),\n indexes: [\n { columns: [\"name\", \"status\"] },\n { columns: [\"name\", \"activationDate\"] },\n { columns: [\"name\", \"version\"], unique: true },\n { columns: [\"status\"] },\n { columns: [\"activationDate\"] },\n ],\n});\n\nexport type Parameter = Static<typeof parameters.schema>;\nexport type ParameterInsert = Omit<Parameter, \"id\" | \"createdAt\" | \"updatedAt\">;\n","import { $module } from \"alepha\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./entities/parameters.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport const AlephaApiParameters = $module({\n name: \"alepha.api.parameters\",\n services: [],\n});\n"],"mappings":";;;;;;;;;;;;;AAsBA,MAAa,aAAa,QAAQ;CAChC,MAAM;CACN,QAAQ,EAAE,OAAO;EACf,IAAI,GAAG,WAAW,EAAE,MAAM,CAAC;EAC3B,WAAW,GAAG,WAAW;EACzB,WAAW,GAAG,WAAW;EAMzB,MAAM,EAAE,MAAM;EAKd,SAAS,EAAE,MAAM;EAMjB,YAAY,EAAE,MAAM;EAKpB,QAAQ,GAAG,QACT,EAAE,KAAK;GAAC;GAAW;GAAW;GAAQ;GAAS,CAAC,EAChD,SACD;EAMD,gBAAgB,EAAE,UAAU;EAM5B,WAAW,EAAE,SAAS,EAAE,UAAU,CAAC;EAMnC,SAAS,EAAE,SAAS;EAKpB,mBAAmB,EAAE,SAAS,EAAE,MAAM,CAAC;EAKvC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;EAKnC,WAAW,EAAE,SAAS,EAAE,MAAM,CAAC;EAK/B,aAAa,EAAE,SAAS,EAAE,MAAM,CAAC;EAKjC,iBAAiB,EAAE,SAAS,EAAE,MAAM,CAAC;EAKrC,cAAc,EAAE,SAAS,EAAE,MAAM,CAAC;EACnC,CAAC;CACF,SAAS;EACP,EAAE,SAAS,CAAC,QAAQ,SAAS,EAAE;EAC/B,EAAE,SAAS,CAAC,QAAQ,iBAAiB,EAAE;EACvC;GAAE,SAAS,CAAC,QAAQ,UAAU;GAAE,QAAQ;GAAM;EAC9C,EAAE,SAAS,CAAC,SAAS,EAAE;EACvB,EAAE,SAAS,CAAC,iBAAiB,EAAE;EAChC;CACF,CAAC;;;;ACrGF,MAAa,sBAAsB,QAAQ;CACzC,MAAM;CACN,UAAU,EAAE;CACb,CAAC"}