alepha 0.20.2 → 0.20.3

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 (208) hide show
  1. package/README.md +0 -1
  2. package/assets/swagger-ui/swagger-ui-bundle.js +1 -1
  3. package/assets/swagger-ui/swagger-ui.css +1 -1
  4. package/dist/api/audits/index.browser.js +49 -0
  5. package/dist/api/audits/index.browser.js.map +1 -1
  6. package/dist/api/audits/index.d.ts.map +1 -1
  7. package/dist/api/audits/index.js +49 -0
  8. package/dist/api/audits/index.js.map +1 -1
  9. package/dist/api/files/index.d.ts.map +1 -1
  10. package/dist/api/files/index.js.map +1 -1
  11. package/dist/api/jobs/index.d.ts +16 -75
  12. package/dist/api/jobs/index.d.ts.map +1 -1
  13. package/dist/api/jobs/index.js.map +1 -1
  14. package/dist/api/keys/index.js.map +1 -1
  15. package/dist/api/notifications/index.d.ts +1 -10
  16. package/dist/api/notifications/index.d.ts.map +1 -1
  17. package/dist/api/organizations/index.d.ts.map +1 -1
  18. package/dist/api/parameters/index.browser.js +37 -0
  19. package/dist/api/parameters/index.browser.js.map +1 -1
  20. package/dist/api/parameters/index.d.ts +4 -65
  21. package/dist/api/parameters/index.d.ts.map +1 -1
  22. package/dist/api/parameters/index.js +37 -0
  23. package/dist/api/parameters/index.js.map +1 -1
  24. package/dist/api/payments/index.d.ts.map +1 -1
  25. package/dist/api/payments/index.js.map +1 -1
  26. package/dist/api/users/index.d.ts +207 -5184
  27. package/dist/api/users/index.d.ts.map +1 -1
  28. package/dist/api/users/index.js +2 -4
  29. package/dist/api/users/index.js.map +1 -1
  30. package/dist/api/verifications/index.d.ts.map +1 -1
  31. package/dist/api/verifications/index.js +2 -1
  32. package/dist/api/verifications/index.js.map +1 -1
  33. package/dist/bucket/index.js +5 -1
  34. package/dist/bucket/index.js.map +1 -1
  35. package/dist/bucket/index.workerd.js +5 -1
  36. package/dist/bucket/index.workerd.js.map +1 -1
  37. package/dist/cache/core/index.js.map +1 -1
  38. package/dist/cache/core/index.workerd.js.map +1 -1
  39. package/dist/captcha/index.js.map +1 -1
  40. package/dist/cli/core/index.d.ts +217 -11647
  41. package/dist/cli/core/index.d.ts.map +1 -1
  42. package/dist/cli/core/index.js +706 -42
  43. package/dist/cli/core/index.js.map +1 -1
  44. package/dist/cli/devtools/index.js +7 -1
  45. package/dist/cli/devtools/index.js.map +1 -1
  46. package/dist/cli/platform/index.d.ts +41 -64
  47. package/dist/cli/platform/index.d.ts.map +1 -1
  48. package/dist/cli/platform/index.js +47 -0
  49. package/dist/cli/platform/index.js.map +1 -1
  50. package/dist/cli/vendor/index.js +15 -0
  51. package/dist/cli/vendor/index.js.map +1 -1
  52. package/dist/command/index.js +1 -1
  53. package/dist/command/index.js.map +1 -1
  54. package/dist/core/index.browser.js.map +1 -1
  55. package/dist/core/index.d.ts +2 -8
  56. package/dist/core/index.d.ts.map +1 -1
  57. package/dist/core/index.js.map +1 -1
  58. package/dist/core/index.native.js.map +1 -1
  59. package/dist/core/index.workerd.js.map +1 -1
  60. package/dist/crypto/index.js.map +1 -1
  61. package/dist/datetime/index.js.map +1 -1
  62. package/dist/email/core/index.js.map +1 -1
  63. package/dist/email/smtp/index.js +2 -10522
  64. package/dist/email/smtp/index.js.map +1 -1
  65. package/dist/fake/index.d.ts +4 -8085
  66. package/dist/fake/index.d.ts.map +1 -1
  67. package/dist/fake/index.js +3 -33554
  68. package/dist/fake/index.js.map +1 -1
  69. package/dist/lock/core/index.js.map +1 -1
  70. package/dist/lock/redis/index.js.map +1 -1
  71. package/dist/logger/index.js +32 -1
  72. package/dist/logger/index.js.map +1 -1
  73. package/dist/mcp/index.js +5 -1
  74. package/dist/mcp/index.js.map +1 -1
  75. package/dist/orm/core/index.browser.js +1 -361
  76. package/dist/orm/core/index.browser.js.map +1 -1
  77. package/dist/orm/core/index.bun.js +14 -406
  78. package/dist/orm/core/index.bun.js.map +1 -1
  79. package/dist/orm/core/index.d.ts +96 -5117
  80. package/dist/orm/core/index.d.ts.map +1 -1
  81. package/dist/orm/core/index.js +23 -419
  82. package/dist/orm/core/index.js.map +1 -1
  83. package/dist/orm/postgres/index.bun.js +17 -20
  84. package/dist/orm/postgres/index.bun.js.map +1 -1
  85. package/dist/orm/postgres/index.d.ts +2 -613
  86. package/dist/orm/postgres/index.d.ts.map +1 -1
  87. package/dist/orm/postgres/index.js +17 -20
  88. package/dist/orm/postgres/index.js.map +1 -1
  89. package/dist/react/core/index.js.map +1 -1
  90. package/dist/react/i18n/index.js.map +1 -1
  91. package/dist/react/intro/index.js +22 -17
  92. package/dist/react/intro/index.js.map +1 -1
  93. package/dist/react/router/index.browser.js +78 -2
  94. package/dist/react/router/index.browser.js.map +1 -1
  95. package/dist/react/router/index.d.ts +22 -1
  96. package/dist/react/router/index.d.ts.map +1 -1
  97. package/dist/react/router/index.js +102 -4
  98. package/dist/react/router/index.js.map +1 -1
  99. package/dist/react/testing/index.d.ts +1 -411
  100. package/dist/react/testing/index.d.ts.map +1 -1
  101. package/dist/react/testing/index.js +13 -12293
  102. package/dist/react/testing/index.js.map +1 -1
  103. package/dist/react/ui/index.js +3 -0
  104. package/dist/react/ui/index.js.map +1 -1
  105. package/dist/react/websocket/index.js.map +1 -1
  106. package/dist/redis/index.js.map +1 -1
  107. package/dist/scheduler/index.d.ts +1 -83
  108. package/dist/scheduler/index.d.ts.map +1 -1
  109. package/dist/scheduler/index.js +2 -391
  110. package/dist/scheduler/index.js.map +1 -1
  111. package/dist/scheduler/index.workerd.js +2 -391
  112. package/dist/scheduler/index.workerd.js.map +1 -1
  113. package/dist/security/index.browser.js.map +1 -1
  114. package/dist/security/index.d.ts +2 -325
  115. package/dist/security/index.d.ts.map +1 -1
  116. package/dist/security/index.js +3 -1362
  117. package/dist/security/index.js.map +1 -1
  118. package/dist/server/auth/index.d.ts +1 -1054
  119. package/dist/server/auth/index.d.ts.map +1 -1
  120. package/dist/server/auth/index.js +16 -1224
  121. package/dist/server/auth/index.js.map +1 -1
  122. package/dist/server/cookies/index.js.map +1 -1
  123. package/dist/server/core/index.browser.js.map +1 -1
  124. package/dist/server/core/index.d.ts +1 -4
  125. package/dist/server/core/index.d.ts.map +1 -1
  126. package/dist/server/core/index.js +19 -4
  127. package/dist/server/core/index.js.map +1 -1
  128. package/dist/server/links/index.browser.js.map +1 -1
  129. package/dist/server/links/index.js.map +1 -1
  130. package/dist/server/metrics/index.d.ts +1 -514
  131. package/dist/server/metrics/index.d.ts.map +1 -1
  132. package/dist/server/metrics/index.js +4 -4356
  133. package/dist/server/metrics/index.js.map +1 -1
  134. package/dist/server/rate-limit/index.js.map +1 -1
  135. package/dist/server/static/index.js.map +1 -1
  136. package/dist/server/swagger/index.js +1 -1
  137. package/dist/server/swagger/index.js.map +1 -1
  138. package/dist/sms/index.js.map +1 -1
  139. package/dist/system/index.browser.js.map +1 -1
  140. package/dist/system/index.js.map +1 -1
  141. package/dist/system/index.workerd.js.map +1 -1
  142. package/dist/topic/core/index.js.map +1 -1
  143. package/dist/websocket/index.browser.js +21 -0
  144. package/dist/websocket/index.browser.js.map +1 -1
  145. package/dist/websocket/index.js +21 -0
  146. package/dist/websocket/index.js.map +1 -1
  147. package/package.json +18 -15
  148. package/src/api/files/__tests__/FileController.spec.ts +1 -1
  149. package/src/api/jobs/__tests__/$job.spec.ts +5 -1
  150. package/src/api/users/schemas/userQuerySchema.ts +0 -1
  151. package/src/api/users/services/UserService.ts +1 -5
  152. package/src/api/verifications/__tests__/CodeVerification.spec.ts +14 -0
  153. package/src/api/verifications/__tests__/LinkVerification.spec.ts +14 -0
  154. package/src/api/verifications/services/VerificationService.ts +1 -0
  155. package/src/cli/core/__tests__/init.spec.ts +208 -0
  156. package/src/cli/core/commands/init.ts +12 -0
  157. package/src/cli/core/services/PackageManagerUtils.ts +23 -6
  158. package/src/cli/core/services/ProjectScaffolder.ts +298 -20
  159. package/src/cli/core/tasks/BuildDockerTask.ts +9 -10
  160. package/src/cli/core/tasks/BuildServerTask.ts +8 -0
  161. package/src/cli/core/templates/apiIndexTs.ts +23 -1
  162. package/src/cli/core/templates/componentsJsonTs.ts +39 -0
  163. package/src/cli/core/templates/mainCss.ts +1 -0
  164. package/src/cli/core/templates/saasAdminLayoutTsx.ts +77 -0
  165. package/src/cli/core/templates/saasAdminPagesTsx.ts +26 -0
  166. package/src/cli/core/templates/saasAuthLayoutTsx.ts +20 -0
  167. package/src/cli/core/templates/saasAuthPagesTsx.ts +62 -0
  168. package/src/cli/core/templates/saasRealmProviderTs.ts +46 -0
  169. package/src/cli/core/templates/webAppRouterTs.ts +104 -1
  170. package/src/cli/core/templates/webIndexTs.ts +23 -1
  171. package/src/cli/platform/__tests__/SecretsCommand.spec.ts +2 -0
  172. package/src/command/providers/CliProvider.ts +1 -1
  173. package/src/core/interfaces/Service.ts +3 -1
  174. package/src/core/providers/TypeProvider.ts +1 -1
  175. package/src/logger/services/Logger.ts +1 -1
  176. package/src/mcp/__tests__/$resource.spec.ts +1 -1
  177. package/src/mcp/__tests__/$tool.spec.ts +1 -1
  178. package/src/mcp/__tests__/McpServerProvider.spec.ts +1 -1
  179. package/src/orm/__tests__/$repository-tests.ts +1 -0
  180. package/src/orm/__tests__/orm-next-tests.ts +2 -67
  181. package/src/orm/__tests__/orm-next.spec.ts +0 -21
  182. package/src/orm/core/index.shared.ts +0 -2
  183. package/src/orm/core/index.ts +1 -2
  184. package/src/orm/core/primitives/$repository.ts +3 -6
  185. package/src/orm/core/providers/drivers/DatabaseProvider.ts +0 -5
  186. package/src/orm/core/providers/drivers/NodeSqliteProvider.ts +11 -13
  187. package/src/orm/core/services/ModelBuilder.ts +1 -13
  188. package/src/orm/core/services/Repository.ts +1 -42
  189. package/src/orm/core/services/SqliteModelBuilder.ts +2 -33
  190. package/src/orm/postgres/services/PostgresModelBuilder.ts +10 -45
  191. package/src/react/intro/components/GettingStartedAuthSlide.tsx +11 -4
  192. package/src/react/router/__tests__/ReactBrowserProvider.browser.spec.ts +213 -2
  193. package/src/react/router/providers/ReactBrowserProvider.ts +73 -0
  194. package/src/react/router/providers/ReactBrowserRouterProvider.ts +1 -1
  195. package/src/react/router/providers/ReactPreloadProvider.ts +1 -1
  196. package/src/react/router/providers/ReactServerProvider.ts +1 -0
  197. package/src/scheduler/providers/CronProvider.ts +1 -1
  198. package/src/security/primitives/$basicAuth.ts +1 -1
  199. package/src/server/auth/providers/ServerAuthProvider.ts +5 -1
  200. package/src/server/core/interfaces/ServerRequest.ts +1 -0
  201. package/src/server/core/providers/ServerProvider.ts +1 -1
  202. package/src/server/core/providers/ServerRouterProvider.ts +2 -2
  203. package/src/server/core/services/HttpClient.ts +1 -1
  204. package/src/server/swagger/providers/ServerSwaggerProvider.ts +1 -1
  205. package/dist/react/testing/chunk-DBEY4PJZ.js +0 -16
  206. package/src/orm/core/__tests__/parseQueryString.spec.ts +0 -196
  207. package/src/orm/core/helpers/parseQueryString.ts +0 -502
  208. package/src/orm/core/primitives/$view.ts +0 -88
@@ -1 +1 @@
1
- {"version":3,"file":"index.bun.js","names":["sql","sql","sql","isSQLWrapper","drizzleEq","drizzleAnd","pageSchema"],"sources":["../../../src/orm/core/constants/PG_SYMBOLS.ts","../../../src/orm/core/schemas/insertSchema.ts","../../../src/orm/core/schemas/updateSchema.ts","../../../src/orm/core/primitives/$entity.ts","../../../src/orm/core/errors/DbError.ts","../../../src/orm/core/schemas/databaseEnvSchema.ts","../../../src/orm/core/providers/DrizzleKitProvider.ts","../../../src/orm/core/providers/drivers/DatabaseProvider.ts","../../../src/orm/core/primitives/$sequence.ts","../../../src/orm/core/services/ModelBuilder.ts","../../../src/orm/core/services/SqliteModelBuilder.ts","../../../src/orm/core/providers/drivers/BunSqliteProvider.ts","../../../src/orm/core/providers/drivers/CloudflareD1Provider.ts","../../../src/orm/core/errors/DbColumnNotFoundError.ts","../../../src/orm/core/errors/DbConflictError.ts","../../../src/orm/core/errors/DbDeadlockError.ts","../../../src/orm/core/errors/DbEntityNotFoundError.ts","../../../src/orm/core/errors/DbForeignKeyError.ts","../../../src/orm/core/errors/DbNotNullError.ts","../../../src/orm/core/errors/DbTableNotFoundError.ts","../../../src/orm/core/errors/DbVersionMismatchError.ts","../../../src/orm/core/helpers/pgAttr.ts","../../../src/orm/core/providers/DbCacheProvider.ts","../../../src/orm/core/services/PgRelationManager.ts","../../../src/orm/core/services/QueryManager.ts","../../../src/orm/core/services/Repository.ts","../../../src/orm/core/providers/RepositoryProvider.ts","../../../src/orm/core/errors/DbMigrationError.ts","../../../src/orm/core/errors/DbConnectionError.ts","../../../src/orm/core/helpers/parseQueryString.ts","../../../src/orm/core/primitives/$view.ts","../../../src/orm/core/providers/DatabaseTypeProvider.ts","../../../src/orm/core/schemas/legacyIdSchema.ts","../../../src/orm/core/primitives/$repository.ts","../../../src/orm/core/primitives/$seed.ts","../../../src/orm/core/primitives/$transactional.ts","../../../src/orm/core/types/schema.ts","../../../src/orm/core/index.bun.ts"],"sourcesContent":["import type { SQL } from \"drizzle-orm\";\nimport type {\n PgSequenceOptions,\n UpdateDeleteAction,\n} from \"drizzle-orm/pg-core\";\nimport type { EntityPrimitive } from \"../primitives/$entity.ts\";\n\nexport const PG_DEFAULT = Symbol.for(\"Alepha.Postgres.Default\");\nexport const PG_PRIMARY_KEY = Symbol.for(\"Alepha.Postgres.PrimaryKey\");\nexport const PG_CREATED_AT = Symbol.for(\"Alepha.Postgres.CreatedAt\");\nexport const PG_UPDATED_AT = Symbol.for(\"Alepha.Postgres.UpdatedAt\");\nexport const PG_DELETED_AT = Symbol.for(\"Alepha.Postgres.DeletedAt\");\nexport const PG_VERSION = Symbol.for(\"Alepha.Postgres.Version\");\nexport const PG_IDENTITY = Symbol.for(\"Alepha.Postgres.Identity\");\nexport const PG_ENUM = Symbol.for(\"Alepha.Postgres.Enum\");\nexport const PG_REF = Symbol.for(\"Alepha.Postgres.Ref\");\nexport const PG_GENERATED = Symbol.for(\"Alepha.Postgres.Generated\");\nexport const PG_ORGANIZATION = Symbol.for(\"Alepha.Postgres.Organization\");\n\n/**\n * @deprecated Use `PG_IDENTITY` instead.\n */\nexport const PG_SERIAL = Symbol.for(\"Alepha.Postgres.Serial\");\n\nexport type PgDefault = typeof PG_DEFAULT;\nexport type PgRef = typeof PG_REF;\nexport type PgPrimaryKey = typeof PG_PRIMARY_KEY;\n\nexport type PgSymbols = {\n [PG_DEFAULT]: {};\n [PG_PRIMARY_KEY]: {};\n [PG_CREATED_AT]: {};\n [PG_UPDATED_AT]: {};\n [PG_DELETED_AT]: {};\n [PG_VERSION]: {};\n [PG_IDENTITY]: PgIdentityOptions;\n [PG_REF]: PgRefOptions;\n [PG_ENUM]: PgEnumOptions;\n [PG_GENERATED]: PgGeneratedOptions;\n [PG_ORGANIZATION]: {};\n\n /**\n * @deprecated Use `PG_IDENTITY` instead.\n */\n [PG_SERIAL]: {};\n};\n\nexport type PgSymbolKeys = keyof PgSymbols;\n\nexport type PgIdentityOptions = {\n mode: \"always\" | \"byDefault\";\n} & PgSequenceOptions & {\n name?: string;\n };\n\nexport interface PgEnumOptions {\n name?: string;\n description?: string;\n}\n\nexport interface PgGeneratedOptions {\n /**\n * SQL expression for the generated column.\n */\n expression: SQL;\n\n /**\n * Storage mode for the generated column.\n * - `\"stored\"` — value is computed on write and stored on disk (default for PostgreSQL).\n * - `\"virtual\"` — value is computed on read (default for SQLite).\n */\n mode?: \"stored\" | \"virtual\";\n}\n\nexport interface PgRefOptions {\n ref: () => {\n name: string;\n entity: EntityPrimitive;\n };\n actions?: {\n onUpdate?: UpdateDeleteAction;\n onDelete?: UpdateDeleteAction;\n };\n}\n","import type { TObject, TOptional } from \"alepha\";\nimport { t } from \"alepha\";\nimport { PG_DEFAULT, PG_GENERATED } from \"../constants/PG_SYMBOLS.ts\";\n\n/**\n * Transforms a TObject schema for insert operations.\n * All default properties at the root level are made optional.\n * Generated columns are excluded entirely.\n *\n * @example\n * Before: { name: string; age: number(default=0); fullName: generated }\n * After: { name: string; age?: number; }\n */\nexport type TObjectInsert<T extends TObject> = TObject<{\n [K in keyof T[\"properties\"] as T[\"properties\"][K] extends {\n [PG_GENERATED]: any;\n }\n ? never\n : K]: T[\"properties\"][K] extends\n | { [PG_DEFAULT]: any }\n | { \"~optional\": true }\n ? TOptional<T[\"properties\"][K]>\n : T[\"properties\"][K];\n}>;\n\nexport const insertSchema = <T extends TObject>(obj: T): TObjectInsert<T> => {\n const newProperties: Record<string, any> = {};\n\n for (const key in obj.properties) {\n const prop = obj.properties[key];\n\n // Skip generated columns — they are computed by the database\n if (PG_GENERATED in prop) {\n continue;\n }\n\n if (PG_DEFAULT in prop) {\n newProperties[key] = t.optional(prop);\n } else {\n newProperties[key] = prop;\n }\n }\n\n return t.object(\n newProperties,\n \"options\" in obj && typeof obj.options === \"object\"\n ? { ...obj.options }\n : {},\n ) as TObjectInsert<T>;\n};\n","import {\n type TNull,\n type TObject,\n type TOptional,\n type TUnion,\n t,\n} from \"alepha\";\nimport { PG_GENERATED } from \"../constants/PG_SYMBOLS.ts\";\n\n/**\n * Transforms a TObject schema for update operations.\n * All optional properties at the root level are made nullable (i.e., `T | null`).\n * Generated columns are excluded entirely.\n *\n * @example\n * Before: { name?: string; age: number; fullName: generated }\n * After: { name?: string | null; age: number; }\n */\nexport type TObjectUpdate<T extends TObject> = TObject<{\n [K in keyof T[\"properties\"] as T[\"properties\"][K] extends {\n [PG_GENERATED]: any;\n }\n ? never\n : K]: T[\"properties\"][K] extends TOptional<infer U>\n ? TOptional<TUnion<[U, TNull]>>\n : T[\"properties\"][K];\n}>;\n\nexport const updateSchema = <T extends TObject>(\n schema: T,\n): TObjectUpdate<T> => {\n const newProperties: Record<string, any> = {};\n\n for (const key in schema.properties) {\n const prop = schema.properties[key];\n\n // Skip generated columns — they are computed by the database\n if (PG_GENERATED in prop) {\n continue;\n }\n\n if (t.schema.isOptional(prop)) {\n newProperties[key] = t.optional(t.union([prop, t.raw.Null()]));\n } else {\n newProperties[key] = prop;\n }\n }\n\n return t.object(\n newProperties,\n \"options\" in schema && typeof schema.options === \"object\"\n ? { ...schema.options }\n : {},\n ) as TObjectUpdate<T>;\n};\n","import { KIND, type Static, type TObject } from \"alepha\";\nimport type { BuildExtraConfigColumns, SQL } from \"drizzle-orm\";\nimport type {\n PgColumn,\n PgColumnBuilderBase,\n PgTableExtraConfigValue,\n} from \"drizzle-orm/pg-core\";\nimport { insertSchema, type TObjectInsert } from \"../schemas/insertSchema.ts\";\nimport { type TObjectUpdate, updateSchema } from \"../schemas/updateSchema.ts\";\n\n/**\n * Creates a database entity primitive that defines table structure using TypeBox schemas.\n *\n * @example\n * ```ts\n * import { t } from \"alepha\";\n * import { $entity } from \"alepha/orm\";\n *\n * const userEntity = $entity({\n * name: \"users\",\n * schema: t.object({\n * id: pg.primaryKey(),\n * name: t.text(),\n * email: t.email(),\n * }),\n * });\n * ```\n */\nexport const $entity = <TSchema extends TObject>(\n options: EntityPrimitiveOptions<TSchema>,\n): EntityPrimitive<TSchema> => {\n return new EntityPrimitive<TSchema>(options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface EntityPrimitiveOptions<\n T extends TObject,\n Keys = keyof Static<T>,\n> {\n /**\n * The database table name that will be created for this entity.\n * If not provided, name will be inferred from the $repository variable name.\n */\n name: string;\n\n /**\n * TypeBox schema defining the table structure and column types.\n */\n schema: T;\n\n /**\n * Database indexes to create for query optimization.\n */\n indexes?: (\n | Keys\n | {\n /**\n * Single column to index.\n */\n column: Keys;\n /**\n * Whether this should be a unique index (enforces uniqueness constraint).\n */\n unique?: boolean;\n /**\n * Custom name for the index. If not provided, generates name automatically.\n */\n name?: string;\n /**\n * Partial index condition. Only rows matching this SQL expression are indexed.\n */\n where?: SQL;\n }\n | {\n /**\n * Multiple columns for composite index (order matters for query optimization).\n */\n columns: Keys[];\n /**\n * Whether this should be a unique index (enforces uniqueness constraint).\n */\n unique?: boolean;\n /**\n * Custom name for the index. If not provided, generates name automatically.\n */\n name?: string;\n /**\n * Partial index condition. Only rows matching this SQL expression are indexed.\n */\n where?: SQL;\n }\n | {\n /**\n * SQL expressions for expression-based indexes.\n *\n * Can include column references and SQL functions like `LOWER()`, `UPPER()`, etc.\n * Columns and expressions can be mixed together.\n *\n * @example\n * ```ts\n * // Case-insensitive unique username per realm\n * indexes: [{\n * expressions: (self) => [self.realm, sql`LOWER(${self.username})`],\n * unique: true,\n * name: \"users_realm_username_lower_idx\",\n * }]\n * ```\n */\n expressions: (self: Record<Keys & string, any>) => (SQL | any)[];\n /**\n * Whether this should be a unique index (enforces uniqueness constraint).\n */\n unique?: boolean;\n /**\n * Custom name for the index. If not provided, generates name automatically.\n */\n name: string;\n /**\n * Partial index condition. Only rows matching this SQL expression are indexed.\n */\n where?: SQL;\n }\n )[];\n\n /**\n * Foreign key constraints to maintain referential integrity.\n */\n foreignKeys?: Array<{\n /**\n * Optional name for the foreign key constraint.\n */\n name?: string;\n /**\n * Local columns that reference the foreign table.\n */\n columns: Array<keyof Static<T>>;\n /**\n * Referenced columns in the foreign table.\n * Must be EntityColumn references from other entities.\n */\n foreignColumns: Array<() => EntityColumn<any>>;\n }>;\n\n /**\n * Additional table constraints for data validation.\n *\n * Constraints enforce business rules at the database level, providing\n * an additional layer of data integrity beyond application validation.\n *\n * **Constraint Types**:\n * - **Unique constraints**: Prevent duplicate values across columns\n * - **Check constraints**: Enforce custom validation rules with SQL expressions\n *\n * @example\n * ```ts\n * constraints: [\n * {\n * name: \"unique_user_email\",\n * columns: [\"email\"],\n * unique: true\n * },\n * {\n * name: \"valid_age_range\",\n * columns: [\"age\"],\n * check: sql`age >= 0 AND age <= 150`\n * },\n * {\n * name: \"unique_user_username_per_tenant\",\n * columns: [\"tenantId\", \"username\"],\n * unique: true\n * }\n * ]\n * ```\n */\n constraints?: Array<{\n /**\n * Columns involved in this constraint.\n */\n columns: Array<keyof Static<T>>;\n /**\n * Optional name for the constraint.\n */\n name?: string;\n /**\n * Whether this is a unique constraint.\n */\n unique?: boolean | {} /* options */;\n /**\n * SQL expression for check constraint validation.\n */\n check?: SQL;\n }>;\n\n /**\n * Advanced Drizzle ORM configuration for complex table setups.\n */\n config?: (\n self: BuildExtraConfigColumns<string, FromSchema<T>, \"pg\">,\n ) => PgTableExtraConfigValue[];\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class EntityPrimitive<T extends TObject = TObject> {\n public readonly options: EntityPrimitiveOptions<T>;\n\n constructor(options: EntityPrimitiveOptions<T>) {\n this.options = options;\n }\n\n alias(alias: string): this {\n const aliased = new EntityPrimitive<T>(this.options);\n return new Proxy(aliased, {\n get(target, prop, receiver) {\n if (prop === \"$alias\") {\n return alias;\n }\n return Reflect.get(target, prop, receiver);\n },\n }) as this;\n }\n\n get cols(): EntityColumns<T> {\n const cols: Partial<EntityColumns<T>> = {};\n for (const key of Object.keys(this.schema.properties) as Array<\n keyof T[\"properties\"]\n >) {\n cols[key] = {\n name: key as string,\n entity: this,\n };\n }\n\n return cols as EntityColumns<T>;\n }\n\n get name(): string {\n return this.options.name;\n }\n\n get schema(): T {\n return this.options.schema;\n }\n\n get insertSchema(): TObjectInsert<T> {\n return insertSchema(this.options.schema);\n }\n\n get updateSchema(): TObjectUpdate<T> {\n return updateSchema(this.options.schema);\n }\n}\n\n$entity[KIND] = EntityPrimitive;\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Convert a schema to columns.\n */\nexport type FromSchema<T extends TObject> = {\n [key in keyof T[\"properties\"]]: PgColumnBuilderBase;\n};\n\nexport type SchemaToTableConfig<T extends TObject> = {\n name: string;\n schema: string | undefined;\n columns: {\n [key in keyof T[\"properties\"]]: PgColumn;\n };\n dialect: string;\n};\n\nexport type EntityColumn<T extends TObject> = {\n name: string;\n entity: EntityPrimitive<T>;\n};\n\nexport type EntityColumns<T extends TObject> = {\n [key in keyof T[\"properties\"]]: EntityColumn<T>;\n};\n","import { AlephaError } from \"alepha\";\n\nexport class DbError extends AlephaError {\n name = \"DbError\";\n\n constructor(message: string, cause?: unknown) {\n super(message, { cause });\n }\n}\n","import { type Static, t } from \"alepha\";\n\n/**\n * Base database environment schema.\n *\n * Defines the `DATABASE_URL` connection string used by all ORM providers\n * to determine the database driver and connection target.\n *\n * Supported URL formats:\n * - `sqlite://:memory:` or `sqlite://./path/to/db` — SQLite (Node.js or Bun)\n * - `postgres://user:password@host:port/database` — PostgreSQL (Node.js or Bun)\n * - `pglite://:memory:` or `pglite://./path` — PGlite (embedded Postgres)\n * - `d1://BINDING_NAME` — Cloudflare D1\n * - `hyperdrive://BINDING_NAME` — Cloudflare Hyperdrive\n */\nexport const databaseEnvSchema = t.object({\n DATABASE_URL: t.optional(t.text()),\n\n /**\n * Enable or disable push-based schema synchronization (drizzle-kit push).\n *\n * Defaults to `true` in development and test, `false` in production.\n * Set to `false` in development to skip automatic schema sync\n * (e.g. when managing migrations manually).\n */\n DATABASE_SYNC: t.optional(t.boolean()),\n});\n\ndeclare module \"alepha\" {\n interface Env extends Partial<Static<typeof databaseEnvSchema>> {}\n}\n","import { createRequire } from \"node:module\";\nimport { $inject, Alepha, AlephaError } from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport type * as DrizzleKit from \"drizzle-kit/api\";\nimport { sql } from \"drizzle-orm\";\nimport type { DatabaseProvider } from \"./drivers/DatabaseProvider.ts\";\n\nexport class DrizzleKitProvider {\n protected readonly log = $logger();\n protected readonly dateTime = $inject(DateTimeProvider);\n protected readonly alepha = $inject(Alepha);\n\n /**\n * Push-based synchronization using Drizzle Kit's introspection API.\n *\n * Reads the actual database state, diffs against current entity definitions,\n * and applies changes. No stored snapshots — no drift, no corruption.\n *\n * - SQLite: uses `pushSQLiteSchema` (requires sync driver — node:sqlite shim or bun-sqlite)\n * - PostgreSQL: uses `pushSchema` with schema filters\n *\n * Does nothing in production mode — use file-based migrations instead.\n */\n public async synchronize(provider: DatabaseProvider): Promise<void> {\n if (this.alepha.isProduction()) {\n this.log.warn(\"Synchronization skipped in production mode.\");\n return;\n }\n\n if (this.alepha.isTest()) {\n const { statements } = await this.generateMigration(provider);\n await this.executeStatements(\n statements.map((s) =>\n s.replace(/^CREATE SCHEMA /i, \"CREATE SCHEMA IF NOT EXISTS \"),\n ),\n provider,\n );\n return;\n }\n\n const now = this.dateTime.nowMillis();\n const kit = this.importDrizzleKit();\n const models = this.getModels(provider);\n\n if (Object.keys(models).length === 0) {\n this.log.info(`No models to synchronize for '${provider.name}'`);\n return;\n }\n\n try {\n if (provider.dialect === \"sqlite\") {\n await this.pushSqlite(kit, models, provider);\n } else {\n await this.pushPostgres(kit, models, provider);\n }\n } catch (error) {\n // Fallback: generate migrations from scratch (no snapshots).\n // Covers drivers that don't support introspection (e.g. PgLite, sqlite-proxy).\n //\n // If push partially executed (e.g. interactive rename applied then errored),\n // the fallback would re-create tables that already exist. Guard against this\n // by attempting the statements individually and ignoring \"already exists\" errors.\n this.log.debug(\n \"Push sync not available, falling back to migration generation\",\n { error },\n );\n const { statements } = await this.generateMigration(provider);\n await this.executeStatementsLenient(statements, provider);\n }\n\n this.log.info(\n `Synchronization of '${provider.name}' OK [${this.dateTime.nowMillis() - now}ms]`,\n );\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Generate SQL migration statements by diffing two schema states.\n *\n * Used by tests (schema validation) and CLI (`alepha db migrations generate`).\n * Not part of the push sync flow.\n *\n * When `withoutSchema` is true, models are rebuilt without schema qualifiers\n * so the generated SQL is portable across different PostgreSQL schemas.\n */\n public async generateMigration(\n provider: DatabaseProvider,\n prevSnapshot?: any,\n options?: { withoutSchema?: boolean },\n ): Promise<{\n statements: string[];\n models: Record<string, unknown>;\n snapshot?: any;\n }> {\n const kit = this.importDrizzleKit();\n const models = options?.withoutSchema\n ? this.getModelsWithoutSchema(provider)\n : this.getModels(provider);\n\n if (Object.keys(models).length > 0) {\n if (provider.dialect === \"sqlite\") {\n const prev = prevSnapshot ?? (await kit.generateSQLiteDrizzleJson({}));\n const curr = await kit.generateSQLiteDrizzleJson(models);\n return {\n models,\n statements: await kit.generateSQLiteMigration(prev, curr),\n snapshot: curr,\n };\n }\n\n const prev = prevSnapshot ?? kit.generateDrizzleJson({});\n const curr = kit.generateDrizzleJson(models);\n return {\n models,\n statements: await kit.generateMigration(prev, curr),\n snapshot: curr,\n };\n }\n\n return {\n models,\n statements: [],\n snapshot: {},\n };\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Load all tables, enums, sequences, etc. from the provider's repositories.\n */\n public getModels(provider: DatabaseProvider): Record<string, unknown> {\n const models: Record<string, unknown> = {};\n\n for (const [key, value] of provider.schemas.entries()) {\n models[`__schema_${key}`] = value;\n }\n\n for (const [key, value] of provider.tables.entries()) {\n if (models[key]) {\n throw new AlephaError(\n `Model name conflict: '${key}' is already defined.`,\n );\n }\n models[key] = value;\n }\n\n for (const [key, value] of provider.enums.entries()) {\n if (models[key]) {\n throw new AlephaError(\n `Model name conflict: '${key}' is already defined.`,\n );\n }\n models[key] = value;\n }\n\n for (const [key, value] of provider.sequences.entries()) {\n if (models[key]) {\n throw new AlephaError(\n `Model name conflict: '${key}' is already defined.`,\n );\n }\n models[key] = value;\n }\n\n return models;\n }\n\n /**\n * Build schema-free models for migration generation.\n *\n * Rebuilds all entities with `schema = \"public\"` so Drizzle produces\n * SQL without schema qualifiers (e.g. `CREATE TABLE \"users\"` instead\n * of `CREATE TABLE \"myschema\".\"users\"`).\n *\n * The actual schema is applied at migration execution time via `search_path`.\n */\n public getModelsWithoutSchema(\n provider: DatabaseProvider,\n ): Record<string, unknown> {\n const maps = provider.rebuildModels(\"public\");\n const models: Record<string, unknown> = {};\n\n for (const [key, value] of maps.tables.entries()) {\n if (models[key]) {\n throw new AlephaError(\n `Model name conflict: '${key}' is already defined.`,\n );\n }\n models[key] = value;\n }\n\n for (const [key, value] of maps.enums.entries()) {\n if (models[key]) {\n throw new AlephaError(\n `Model name conflict: '${key}' is already defined.`,\n );\n }\n models[key] = value;\n }\n\n for (const [key, value] of maps.sequences.entries()) {\n if (models[key]) {\n throw new AlephaError(\n `Model name conflict: '${key}' is already defined.`,\n );\n }\n models[key] = value;\n }\n\n return models;\n }\n\n /**\n * Preview schema push without executing any statements.\n *\n * Returns the SQL statements that would be executed, warnings, and\n * whether data loss would occur. Does NOT execute any SQL.\n */\n public async dryRunPush(provider: DatabaseProvider): Promise<{\n statements: string[];\n warnings: string[];\n hasDataLoss: boolean;\n }> {\n const kit = this.importDrizzleKit();\n const models = this.getModels(provider);\n\n if (Object.keys(models).length === 0) {\n return { statements: [], warnings: [], hasDataLoss: false };\n }\n\n let result: {\n statementsToExecute: string[];\n warnings: string[];\n hasDataLoss: boolean;\n };\n\n if (provider.dialect === \"sqlite\") {\n result = await kit.pushSQLiteSchema(models, provider.db as any);\n } else {\n const wrappedDb = this.wrapDbForDrizzleKit(provider.db);\n result = await kit.pushSchema(models, wrappedDb, [provider.schema]);\n }\n\n return {\n statements: result.statementsToExecute,\n warnings: result.warnings,\n hasDataLoss: result.hasDataLoss,\n };\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n protected async pushSqlite(\n kit: typeof DrizzleKit,\n models: Record<string, unknown>,\n provider: DatabaseProvider,\n ): Promise<void> {\n const { statementsToExecute } = await kit.pushSQLiteSchema(\n models,\n provider.db as any,\n );\n await this.executeStatements(statementsToExecute, provider);\n }\n\n /**\n * Push schema changes to PostgreSQL using Drizzle Kit's pushSchema with schema filters.\n */\n protected async pushPostgres(\n kit: typeof DrizzleKit,\n models: Record<string, unknown>,\n provider: DatabaseProvider,\n ): Promise<void> {\n if (provider.schema !== \"public\") {\n await this.createSchemaIfNotExists(provider, provider.schema);\n }\n\n // Drizzle Kit's pushSchema expects execute() to return { rows: T[] }\n // (node-postgres/pg format), but postgres.js returns a Result that\n // extends Array directly — no .rows property.\n const wrappedDb = this.wrapDbForDrizzleKit(provider.db);\n\n const { statementsToExecute } = await kit.pushSchema(models, wrappedDb, [\n provider.schema,\n ]);\n await this.executeStatements(statementsToExecute, provider);\n }\n\n /**\n * Execute a list of SQL statements against the provider.\n */\n protected async executeStatements(\n statements: string[],\n provider: DatabaseProvider,\n ): Promise<void> {\n if (statements.length > 0) {\n this.log.debug(`Executing ${statements.length} statements ...`, {\n statements,\n });\n }\n for (const statement of statements) {\n await provider.execute(sql.raw(statement));\n }\n }\n\n /**\n * Execute SQL statements, ignoring \"already exists\" errors.\n *\n * Used by the fallback migration path where push may have partially\n * applied changes before erroring, leaving some objects already created.\n */\n protected async executeStatementsLenient(\n statements: string[],\n provider: DatabaseProvider,\n ): Promise<void> {\n if (statements.length > 0) {\n this.log.debug(\n `Executing ${statements.length} statements (lenient) ...`,\n { statements },\n );\n }\n for (const statement of statements) {\n try {\n await provider.execute(sql.raw(statement));\n } catch (error: any) {\n const message = error?.message ?? \"\";\n if (message.includes(\"already exists\")) {\n this.log.debug(`Skipped (already exists): ${statement.slice(0, 80)}`);\n continue;\n }\n throw error;\n }\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n protected async createSchemaIfNotExists(\n provider: DatabaseProvider,\n schemaName: string,\n ) {\n if (!/^[a-z0-9_]+$/i.test(schemaName)) {\n throw new AlephaError(\n `Invalid schema name: ${schemaName}. Must only contain alphanumeric characters and underscores.`,\n );\n }\n\n const sqlSchema = sql.raw(schemaName);\n\n if (schemaName.startsWith(\"test_\")) {\n this.log.info(`Drop test schema '${schemaName}' ...`, schemaName);\n await provider.execute(sql`DROP SCHEMA IF EXISTS ${sqlSchema} CASCADE`);\n }\n\n this.log.debug(`Ensuring schema '${schemaName}' exists`);\n await provider.execute(sql`CREATE SCHEMA IF NOT EXISTS ${sqlSchema}`);\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n // TODO: remove when Drizzle Kit fixes postgres.js compatibility\n\n /**\n * Wrap a Drizzle PgDatabase instance for compatibility with Drizzle Kit.\n *\n * Drizzle Kit's pushSchema expects execute() to return { rows: T[] }\n * (node-postgres/pg format), but postgres.js returns a Result that\n * extends Array directly — no .rows property.\n */\n protected wrapDbForDrizzleKit(db: any): any {\n return new Proxy(db, {\n get(target, prop, receiver) {\n if (prop === \"execute\") {\n return async (...args: any[]) => {\n const res = await target.execute(...args);\n if (Array.isArray(res) && !(\"rows\" in res)) {\n return Object.assign(res, { rows: [...res] });\n }\n return res;\n };\n }\n return Reflect.get(target, prop, receiver);\n },\n });\n }\n\n /**\n * Try to load the official Drizzle Kit API.\n */\n public importDrizzleKit(): typeof DrizzleKit {\n try {\n return createRequire(import.meta.url)(\"drizzle-kit/api\");\n } catch (_) {\n throw new AlephaError(\n \"Drizzle Kit is not installed. Please install it with `npm install -D drizzle-kit`.\",\n );\n }\n }\n}\n","import { stat } from \"node:fs/promises\";\nimport {\n $inject,\n Alepha,\n AlephaError,\n type Static,\n type TObject,\n} from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { type SQLWrapper, sql } from \"drizzle-orm\";\nimport {\n alias,\n type PgDatabase,\n type PgTableWithColumns,\n type PgTransaction,\n} from \"drizzle-orm/pg-core\";\nimport type { PgTransactionConfig } from \"drizzle-orm/pg-core/session\";\nimport { DbError } from \"../../errors/DbError.ts\";\nimport type {\n EntityPrimitive,\n SchemaToTableConfig,\n} from \"../../primitives/$entity.ts\";\nimport type { SequencePrimitive } from \"../../primitives/$sequence.ts\";\nimport type { ViewPrimitive } from \"../../primitives/$view.ts\";\nimport { databaseEnvSchema } from \"../../schemas/databaseEnvSchema.ts\";\nimport type { ModelBuilder } from \"../../services/ModelBuilder.ts\";\nimport { DrizzleKitProvider } from \"../DrizzleKitProvider.ts\";\n\nexport type SQLLike = SQLWrapper | string;\n\nexport abstract class DatabaseProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly dateTime = $inject(DateTimeProvider);\n protected readonly log = $logger();\n protected abstract readonly builder: ModelBuilder;\n protected readonly kit = $inject(DrizzleKitProvider);\n public abstract readonly db: PgDatabase<any>;\n public abstract readonly dialect: \"postgresql\" | \"sqlite\";\n public abstract readonly url: string;\n\n public readonly enums = new Map<string, unknown>();\n public readonly tables = new Map<string, unknown>();\n public readonly sequences = new Map<string, unknown>();\n public readonly schemas = new Map<string, unknown>();\n\n protected readonly entityPrimitives: EntityPrimitive[] = [];\n protected readonly sequencePrimitives: SequencePrimitive[] = [];\n\n public get name() {\n return \"default\";\n }\n\n public get driver(): string {\n return this.dialect;\n }\n\n /**\n * Whether this driver supports SQL-level transactions (BEGIN/COMMIT/ROLLBACK).\n *\n * Drivers that do not (e.g. PGlite, Cloudflare D1) should override to `false`.\n */\n public get supportsTransactions(): boolean {\n return true;\n }\n\n /**\n * Raw database connection handle (e.g. DatabaseSync, bun:sqlite Database).\n * Override in providers that expose native connections for introspection.\n */\n public get nativeConnection(): unknown {\n return undefined;\n }\n\n public get schema() {\n return \"public\";\n }\n\n /**\n * Migration tracking table name, scoped by schema.\n *\n * Returns `migrations_{schema}` so that multiple schemas sharing the same\n * database each get their own migration history (e.g. `migrations_roadmap`,\n * `migrations_public`).\n */\n public get migrationsTable(): string {\n return `migrations_${this.schema}`;\n }\n\n /**\n * Log a database query with structured metadata for devtools inspection.\n */\n protected logQuery(\n sql: string,\n params: unknown[],\n duration: number,\n rowCount: number,\n error?: string,\n ): void {\n const operation = this.parseOperation(sql);\n const data = {\n type: \"db:query\",\n sql,\n params,\n operation,\n duration: Math.round(duration * 100) / 100,\n rowCount,\n success: !error,\n error,\n };\n\n if (error) {\n this.log.warn(`Query failed (${operation})`, data);\n } else {\n this.log.debug(\n `Query OK (${operation}, ${Math.round(duration)}ms)`,\n data,\n );\n }\n }\n\n protected parseOperation(sql: string): string {\n const trimmed = sql.trimStart().toUpperCase();\n if (trimmed.startsWith(\"SELECT\")) return \"SELECT\";\n if (trimmed.startsWith(\"INSERT\")) return \"INSERT\";\n if (trimmed.startsWith(\"UPDATE\")) return \"UPDATE\";\n if (trimmed.startsWith(\"DELETE\")) return \"DELETE\";\n if (trimmed.startsWith(\"CREATE\")) return \"CREATE\";\n if (trimmed.startsWith(\"ALTER\")) return \"ALTER\";\n if (trimmed.startsWith(\"DROP\")) return \"DROP\";\n return \"OTHER\";\n }\n\n public table<T extends TObject>(\n entity: EntityPrimitive<T>,\n ): PgTableWithColumns<SchemaToTableConfig<T>> {\n const table = this.tables.get(entity.name);\n if (!table) {\n throw new AlephaError(`Table '${entity.name}' is not registered`);\n }\n\n const hasAlias = (entity as any).$alias;\n\n if (hasAlias) {\n return alias(\n table as PgTableWithColumns<SchemaToTableConfig<T>>,\n hasAlias,\n ) as PgTableWithColumns<SchemaToTableConfig<T>>;\n }\n\n return table as PgTableWithColumns<SchemaToTableConfig<T>>;\n }\n\n public registerEntity(entity: EntityPrimitive) {\n this.entityPrimitives.push(entity);\n this.builder.buildTable(entity, this);\n }\n\n public registerView(view: ViewPrimitive) {\n this.builder.buildView(view, this);\n }\n\n public registerSequence(sequence: SequencePrimitive) {\n this.sequencePrimitives.push(sequence);\n this.builder.buildSequence(sequence, this);\n }\n\n /**\n * Rebuild all models into fresh maps using a different schema.\n *\n * When called with `\"public\"`, produces schema-free models suitable for\n * migration generation (no schema qualifiers in the SQL output).\n */\n public rebuildModels(targetSchema: string): {\n tables: Map<string, unknown>;\n enums: Map<string, unknown>;\n sequences: Map<string, unknown>;\n schemas: Map<string, unknown>;\n } {\n const result = {\n tables: new Map<string, unknown>(),\n enums: new Map<string, unknown>(),\n sequences: new Map<string, unknown>(),\n schemas: new Map<string, unknown>(),\n schema: targetSchema,\n };\n\n for (const entity of this.entityPrimitives) {\n this.builder.buildTable(entity, result);\n }\n for (const seq of this.sequencePrimitives) {\n this.builder.buildSequence(seq, result);\n }\n\n return result;\n }\n\n /**\n * Run a function inside a database transaction with implicit tx propagation.\n *\n * The transaction object is stored in `alepha.store` so that all Repository\n * operations within `fn` automatically participate in the transaction without\n * explicit `{ tx }` drilling.\n *\n * Nesting is safe — if already inside a `transactional()` block, the inner\n * call reuses the outer transaction (no nested PG transactions / savepoints).\n */\n public async transactional<R>(\n fn: () => Promise<R>,\n config?: PgTransactionConfig,\n ): Promise<R> {\n const existing = this.alepha.get(\"alepha.orm.tx\");\n if (existing) {\n return fn();\n }\n\n if (!this.supportsTransactions) {\n return fn();\n }\n\n return this.db.transaction(async (tx) => {\n this.alepha.store.set(\"alepha.orm.tx\", tx as PgTransaction<any>, {\n skipEvents: true,\n });\n try {\n return await fn();\n } finally {\n this.alepha.store.set(\"alepha.orm.tx\", undefined, { skipEvents: true });\n }\n }, config);\n }\n\n public abstract execute(\n statement: SQLLike,\n ): Promise<Record<string, unknown>[]>;\n\n public async run<T extends TObject>(\n statement: SQLLike,\n schema: T,\n ): Promise<Array<Static<T>>> {\n const result = await this.execute(statement);\n\n if (result == null) {\n return [];\n }\n\n if (!Array.isArray(result)) {\n this.log.error(\"Unexpected query result format\", { result });\n throw new DbError(\n \"Unexpected query result format, expected array of rows\",\n );\n }\n\n return result.map((row) => this.alepha.codec.decode(schema, row));\n }\n\n /**\n * Get migrations folder path - can be overridden\n */\n protected getMigrationsFolder(): string {\n return `migrations/${this.name}`;\n }\n\n /**\n * Migration orchestration.\n *\n * - Production: file-based migrations from the migrations folder\n * - Dev / Test: push-based sync (introspects actual DB, no snapshots)\n * - Serverless: skipped (migrations should be applied during deployment)\n */\n public async migrate(): Promise<void> {\n if (this.alepha.isServerless()) {\n return;\n }\n\n if (this.alepha.isProduction()) {\n const migrationsFolder = this.getMigrationsFolder();\n const exists = await stat(migrationsFolder).catch(() => false);\n\n if (!exists) {\n this.log.warn(\"Migration SKIPPED - no migrations found\");\n return;\n }\n\n // For schema-free migrations, ensure the target schema exists\n // before running migration files. The schema is applied via\n // search_path set at the provider's connection level.\n if (this.dialect === \"postgresql\" && this.schema !== \"public\") {\n this.log.debug(`Ensuring schema '${this.schema}' exists ...`);\n await this.execute(\n sql`CREATE SCHEMA IF NOT EXISTS ${sql.raw(this.schema)}`,\n );\n }\n\n this.log.debug(`Migrate from '${migrationsFolder}' directory ...`);\n await this.executeMigrations(migrationsFolder);\n this.log.info(\"Migration OK\");\n } else {\n const { DATABASE_SYNC } = this.alepha.parseEnv(databaseEnvSchema);\n if (DATABASE_SYNC === false) {\n this.log.info(\n \"Database synchronization disabled (DATABASE_SYNC=false)\",\n );\n return;\n }\n\n try {\n await this.kit.synchronize(this);\n } catch (error) {\n throw new DbError(\n `Failed to synchronize ${this.dialect} database schema`,\n error as Error,\n );\n }\n }\n }\n\n /**\n * Provider-specific migration execution\n * MUST be implemented by each provider\n */\n protected abstract executeMigrations(migrationsFolder: string): Promise<void>;\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * For testing purposes, generate a unique schema name.\n *\n * Format: `test_alepha_{epoch_seconds}_{random8}`\n * Example: `test_alepha_1739871618_k3m9x2p1`\n */\n protected generateTestSchemaName(): string {\n const epoch = Math.floor(this.dateTime.nowMillis() / 1000);\n const random = Math.random().toString(36).slice(2, 10).padEnd(8, \"0\");\n\n return `test_alepha_${epoch}_${random}`;\n }\n}\n","import { createPrimitive, KIND, Primitive } from \"alepha\";\nimport { sql } from \"drizzle-orm\";\nimport type { PgSequenceOptions } from \"drizzle-orm/pg-core\";\nimport { DatabaseProvider } from \"../providers/drivers/DatabaseProvider.ts\";\n\n/**\n * Creates a PostgreSQL sequence primitive for generating unique numeric values.\n */\nexport const $sequence = (\n options: SequencePrimitiveOptions = {},\n): SequencePrimitive => {\n return createPrimitive(SequencePrimitive, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface SequencePrimitiveOptions extends PgSequenceOptions {\n /**\n * The name of the sequence. If not provided, the property key will be used.\n */\n name?: string;\n\n provider?: DatabaseProvider;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class SequencePrimitive extends Primitive<SequencePrimitiveOptions> {\n public readonly provider = this.$provider();\n\n public onInit() {\n this.provider.registerSequence(this);\n }\n\n public get name(): string {\n return this.options.name ?? this.config.propertyKey;\n }\n\n public async next(): Promise<number> {\n return this.provider\n .execute(\n sql`SELECT nextval('${sql.raw(this.provider.schema)}.\"${sql.raw(this.name)}\"')`,\n )\n .then((rows) => Number(rows[0]?.nextval));\n }\n\n public async current(): Promise<number> {\n return this.provider\n .execute(\n sql`SELECT last_value FROM ${sql.raw(this.provider.schema)}.\"${sql.raw(this.name)}\"`,\n )\n .then((rows) => Number(rows[0]?.last_value));\n }\n\n protected $provider() {\n return this.options.provider ?? this.alepha.inject(DatabaseProvider);\n }\n}\n\n$sequence[KIND] = SequencePrimitive;\n","import { AlephaError } from \"alepha\";\nimport type { SQL } from \"drizzle-orm\";\nimport type { EntityPrimitive } from \"../primitives/$entity.ts\";\nimport type { SequencePrimitive } from \"../primitives/$sequence.ts\";\nimport type { ViewPrimitive } from \"../primitives/$view.ts\";\n\n/**\n * Database-specific table configuration functions\n */\nexport interface TableConfigBuilders<TConfig> {\n index: (name: string) => {\n on: (...columns: any[]) => TConfig;\n };\n uniqueIndex: (name: string) => {\n on: (...columns: any[]) => TConfig;\n };\n unique: (name: string) => {\n on: (...columns: any[]) => TConfig;\n };\n check: (name: string, sql: SQL) => TConfig;\n foreignKey: (config: {\n name: string;\n columns: any[];\n foreignColumns: any[];\n }) => TConfig;\n}\n\n/**\n * Abstract base class for transforming Alepha Primitives (Entity, Sequence, etc...)\n * into drizzle models (tables, enums, sequences, etc...).\n */\nexport abstract class ModelBuilder {\n /**\n * Build a table from an entity primitive.\n */\n abstract buildTable(\n entity: EntityPrimitive,\n options: {\n tables: Map<string, unknown>;\n enums: Map<string, unknown>;\n schemas: Map<string, unknown>;\n schema: string;\n },\n ): void;\n\n /**\n * Build a view from a view primitive.\n */\n abstract buildView(\n view: ViewPrimitive,\n options: {\n tables: Map<string, unknown>;\n schema: string;\n },\n ): void;\n\n /**\n * Build a sequence from a sequence primitive.\n */\n abstract buildSequence(\n sequence: SequencePrimitive,\n options: {\n sequences: Map<string, unknown>;\n schema: string;\n },\n ): void;\n\n /**\n * Convert camelCase to snake_case for column names.\n */\n protected toColumnName(str: string): string {\n return (\n str[0].toLowerCase() +\n str.slice(1).replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`)\n );\n }\n\n /**\n * Build the table configuration function for any database.\n * This includes indexes, foreign keys, constraints, and custom config.\n *\n * @param entity - The entity primitive\n * @param builders - Database-specific builder functions\n * @param tableResolver - Function to resolve entity references to table columns\n * @param customConfigHandler - Optional handler for custom config\n */\n protected buildTableConfig<TConfig, TSelf>(\n entity: EntityPrimitive,\n builders: TableConfigBuilders<TConfig>,\n tableResolver?: (entityName: string) => any,\n customConfigHandler?: (config: any, self: TSelf) => TConfig[],\n ): ((self: TSelf) => TConfig[]) | undefined {\n // If no extra config is needed, return undefined\n if (\n !entity.options.indexes &&\n !entity.options.foreignKeys &&\n !entity.options.constraints &&\n !entity.options.config\n ) {\n return undefined;\n }\n\n return (self: TSelf) => {\n const configs: TConfig[] = [];\n\n // Build indexes\n if (entity.options.indexes) {\n for (const indexDef of entity.options.indexes) {\n if (typeof indexDef === \"string\") {\n const columnName = this.toColumnName(indexDef);\n const indexName = `${entity.name}_${columnName}_idx`;\n\n // Use original camelCase property name for lookup\n if ((self as any)[indexDef]) {\n configs.push(\n builders.index(indexName).on((self as any)[indexDef]),\n );\n }\n } else if (typeof indexDef === \"object\" && indexDef !== null) {\n if (\"column\" in indexDef) {\n const columnName = this.toColumnName(indexDef.column as string);\n const indexName =\n indexDef.name || `${entity.name}_${columnName}_idx`;\n\n // Use original camelCase property name for lookup\n if ((self as any)[indexDef.column]) {\n let idx = indexDef.unique\n ? builders\n .uniqueIndex(indexName)\n .on((self as any)[indexDef.column])\n : builders\n .index(indexName)\n .on((self as any)[indexDef.column]);\n if (\"where\" in indexDef && indexDef.where) {\n idx = (idx as any).where(indexDef.where);\n }\n configs.push(idx);\n }\n } else if (\"expressions\" in indexDef) {\n const parts = indexDef.expressions(self as any);\n if (parts.length > 0) {\n let idx = indexDef.unique\n ? builders.uniqueIndex(indexDef.name).on(...parts)\n : builders.index(indexDef.name).on(...parts);\n if (\"where\" in indexDef && indexDef.where) {\n idx = (idx as any).where(indexDef.where);\n }\n configs.push(idx);\n }\n } else if (\"columns\" in indexDef) {\n const columnNames = indexDef.columns.map((col: any) =>\n this.toColumnName(col as string),\n );\n const indexName =\n indexDef.name || `${entity.name}_${columnNames.join(\"_\")}_idx`;\n\n // Use original camelCase property names for lookup\n const cols = indexDef.columns\n .map((col: any) => (self as any)[col])\n .filter(Boolean);\n\n if (cols.length === indexDef.columns.length) {\n let idx = indexDef.unique\n ? builders.uniqueIndex(indexName).on(...cols)\n : builders.index(indexName).on(...cols);\n if (\"where\" in indexDef && indexDef.where) {\n idx = (idx as any).where(indexDef.where);\n }\n configs.push(idx);\n }\n }\n }\n }\n }\n\n // Build foreign keys\n if (entity.options.foreignKeys) {\n for (const fkDef of entity.options.foreignKeys) {\n const columnNames = fkDef.columns.map((col) =>\n this.toColumnName(col as string),\n );\n\n // Use original camelCase property names for lookup\n const cols = fkDef.columns\n .map((col) => (self as any)[col])\n .filter(Boolean);\n\n if (cols.length === fkDef.columns.length) {\n const fkName =\n fkDef.name || `${entity.name}_${columnNames.join(\"_\")}_fk`;\n\n // Resolve foreign column references\n const foreignColumns = fkDef.foreignColumns.map((colRef) => {\n const entityCol = colRef();\n if (!entityCol || !entityCol.entity || !entityCol.name) {\n throw new AlephaError(\n `Invalid foreign column reference in ${entity.name}`,\n );\n }\n\n // If we have a table resolver, use it to get the actual table column\n if (tableResolver) {\n const foreignTable = tableResolver(entityCol.entity.name);\n if (!foreignTable) {\n throw new AlephaError(\n `Foreign table ${entityCol.entity.name} not found for ${entity.name}`,\n );\n }\n // Use original camelCase property name for lookup in foreign table\n return foreignTable[entityCol.name];\n }\n\n // Fallback: return the entity column reference (will be resolved later)\n return entityCol;\n });\n\n configs.push(\n builders.foreignKey({\n name: fkName,\n columns: cols,\n foreignColumns,\n }),\n );\n }\n }\n }\n\n // Build constraints\n if (entity.options.constraints) {\n for (const constraintDef of entity.options.constraints) {\n const columnNames = constraintDef.columns.map((col) =>\n this.toColumnName(col as string),\n );\n\n // Use original camelCase property names for lookup\n const cols = constraintDef.columns\n .map((col) => (self as any)[col])\n .filter(Boolean);\n\n if (cols.length === constraintDef.columns.length) {\n if (constraintDef.unique) {\n const constraintName =\n constraintDef.name ||\n `${entity.name}_${columnNames.join(\"_\")}_unique`;\n\n configs.push(builders.unique(constraintName).on(...cols));\n }\n\n if (constraintDef.check) {\n const constraintName =\n constraintDef.name ||\n `${entity.name}_${columnNames.join(\"_\")}_check`;\n\n configs.push(builders.check(constraintName, constraintDef.check));\n }\n }\n }\n }\n\n // Add custom config if provided\n if (entity.options.config && customConfigHandler) {\n configs.push(...customConfigHandler(entity.options.config, self));\n } else if (entity.options.config) {\n // Default behavior: call the config function directly\n const customConfigs = entity.options.config(self as any);\n if (Array.isArray(customConfigs)) {\n configs.push(...(customConfigs as any));\n }\n }\n\n return configs;\n };\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport {\n AlephaError,\n type Static,\n type TObject,\n type TSchema,\n type TString,\n t,\n} from \"alepha\";\nimport { type BuildColumns, sql } from \"drizzle-orm\";\nimport * as pg from \"drizzle-orm/sqlite-core\";\nimport {\n check,\n foreignKey,\n index,\n type SQLiteColumnBuilderBase,\n type SQLiteTableWithColumns,\n sqliteTable,\n sqliteView,\n unique,\n uniqueIndex,\n} from \"drizzle-orm/sqlite-core\";\nimport {\n PG_CREATED_AT,\n PG_GENERATED,\n PG_IDENTITY,\n PG_PRIMARY_KEY,\n PG_REF,\n PG_SERIAL,\n PG_UPDATED_AT,\n type PgGeneratedOptions,\n type PgRefOptions,\n} from \"../constants/PG_SYMBOLS.ts\";\nimport type { EntityPrimitive } from \"../primitives/$entity.ts\";\nimport type { SequencePrimitive } from \"../primitives/$sequence.ts\";\nimport type { ViewPrimitive } from \"../primitives/$view.ts\";\nimport { ModelBuilder } from \"./ModelBuilder.ts\";\n\nexport class SqliteModelBuilder extends ModelBuilder {\n public buildTable(\n entity: EntityPrimitive<any>,\n options: {\n tables: Map<string, unknown>;\n enums: Map<string, unknown>;\n schemas: Map<string, unknown>;\n schema: string;\n },\n ) {\n const tableName = entity.name;\n if (options.tables.has(tableName)) {\n return;\n }\n\n const columns = this.schemaToSqliteColumns(\n tableName,\n entity.schema,\n options.enums,\n options.tables,\n );\n\n // Build the config function for SQLite\n const configFn = this.getTableConfig(entity, options.tables);\n\n const table = sqliteTable(tableName, columns, configFn);\n\n options.tables.set(tableName, table);\n }\n\n public buildView(\n view: ViewPrimitive,\n options: {\n tables: Map<string, unknown>;\n schema: string;\n },\n ) {\n const viewName = view.name;\n if (options.tables.has(viewName)) {\n return;\n }\n\n if (view.materialized) {\n throw new AlephaError(\"SQLite does not support materialized views\");\n }\n\n const columns = this.schemaToSqliteColumns(\n viewName,\n view.schema,\n new Map(),\n options.tables,\n );\n\n const drizzleView = sqliteView(viewName, columns).existing();\n options.tables.set(viewName, drizzleView);\n }\n\n public buildSequence(\n sequence: SequencePrimitive,\n options: {\n sequences: Map<string, unknown>;\n schema: string;\n },\n ) {\n throw new AlephaError(\"SQLite does not support sequences\");\n }\n\n /**\n * Get SQLite-specific config builder for the table.\n */\n protected getTableConfig(\n entity: EntityPrimitive,\n tables: Map<string, unknown>,\n ): ((self: BuildColumns<string, any, \"sqlite\">) => any) | undefined {\n // SQLite-specific builders\n const sqliteBuilders = {\n index,\n uniqueIndex,\n unique,\n check,\n foreignKey,\n };\n\n // Table resolver function\n const tableResolver = (entityName: string) => {\n return tables.get(entityName) as any;\n };\n\n return this.buildTableConfig<any, BuildColumns<string, any, \"sqlite\">>(\n entity,\n sqliteBuilders,\n tableResolver,\n (config, self) => {\n // SQLite custom config handler\n const customConfigs = (config as any)(self);\n return Array.isArray(customConfigs) ? customConfigs : [];\n },\n );\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n schemaToSqliteColumns = <T extends TObject>(\n tableName: string,\n schema: T,\n enums: Map<string, unknown>,\n tables: Map<string, unknown>,\n ): SchemaToSqliteBuilder<T> => {\n return Object.entries(schema.properties).reduce<\n Partial<SchemaToSqliteBuilder<T>>\n >((columns, [key, value]) => {\n let col = this.mapFieldToSqliteColumn(tableName, key, value, enums);\n\n if (\"default\" in value && value.default != null) {\n col = col.default(value.default as any);\n }\n\n if (PG_PRIMARY_KEY in value) {\n col = col.primaryKey();\n }\n\n if (PG_REF in value) {\n const config = value[PG_REF] as PgRefOptions;\n col = col.references(() => {\n const ref = config.ref();\n const table = tables.get(\n ref.entity.name,\n ) as SQLiteTableWithColumns<any>;\n\n if (!table) {\n throw new AlephaError(\n `Referenced table ${ref.entity.name} not found for ${tableName}.${key}`,\n );\n }\n\n const target = table[ref.name];\n if (!target) {\n throw new AlephaError(\n `Referenced column ${ref.name} not found in table ${ref.entity.name} for ${tableName}.${key}`,\n );\n }\n\n return target;\n }, config.actions);\n }\n\n if (PG_GENERATED in value) {\n const gen = value[PG_GENERATED] as PgGeneratedOptions;\n col = col.generatedAlwaysAs(gen.expression, {\n mode: gen.mode ?? \"virtual\",\n });\n }\n\n if (schema.required?.includes(key)) {\n col = col.notNull();\n }\n\n return {\n ...columns,\n [key]: col,\n };\n }, {}) as SchemaToSqliteBuilder<T>;\n };\n\n mapFieldToSqliteColumn = (\n tableName: string,\n fieldName: string,\n value: TSchema,\n enums: Map<string, any>,\n ) => {\n const key = this.toColumnName(fieldName);\n\n if (\n // is nullish ?\n \"anyOf\" in value &&\n Array.isArray(value.anyOf) &&\n value.anyOf.length === 2 &&\n value.anyOf.some((it: TSchema) => t.schema.isNull(it))\n ) {\n // then, remove nullish\n value = value.anyOf.find((it: TSchema) => !t.schema.isNull(it))!;\n }\n\n if (t.schema.isInteger(value)) {\n if (PG_SERIAL in value || PG_IDENTITY in value) {\n return pg\n .integer(key, { mode: \"number\" })\n .primaryKey({ autoIncrement: true });\n }\n\n return pg.integer(key);\n }\n\n if (t.schema.isBigInt(value)) {\n if (PG_PRIMARY_KEY in value || PG_IDENTITY in value) {\n return pg\n .integer(key, { mode: \"number\" })\n .primaryKey({ autoIncrement: true });\n }\n\n return pg.integer(key, { mode: \"number\" });\n }\n\n if (t.schema.isNumber(value)) {\n if (PG_IDENTITY in value) {\n return pg\n .integer(key, { mode: \"number\" })\n .primaryKey({ autoIncrement: true });\n }\n\n return pg.numeric(key);\n }\n\n if (t.schema.isString(value)) {\n return this.mapStringToSqliteColumn(key, value);\n }\n\n if (t.schema.isBoolean(value)) {\n return this.sqliteBool(key, value);\n }\n\n if (t.schema.isObject(value)) {\n return this.sqliteJson(key, value);\n }\n\n if (t.schema.isRecord(value)) {\n return this.sqliteJson(key, value);\n }\n\n if (t.schema.isAny(value)) {\n return this.sqliteJson(key, value);\n }\n\n if (t.schema.isArray(value)) {\n if (t.schema.isObject(value.items)) {\n return this.sqliteJson(key, value);\n }\n if (t.schema.isRecord(value.items)) {\n return this.sqliteJson(key, value);\n }\n if (t.schema.isAny(value.items)) {\n return this.sqliteJson(key, value);\n }\n if (t.schema.isString(value.items)) {\n return this.sqliteJson(key, value);\n }\n if (t.schema.isInteger(value.items)) {\n return this.sqliteJson(key, value);\n }\n if (t.schema.isNumber(value.items)) {\n return this.sqliteJson(key, value);\n }\n if (t.schema.isBoolean(value.items)) {\n return this.sqliteJson(key, value);\n }\n }\n\n if (\n t.schema.isUnsafe(value) &&\n \"type\" in value &&\n value.type === \"string\"\n ) {\n return this.mapStringToSqliteColumn(key, value as any);\n }\n\n throw new AlephaError(\n `Unsupported schema for field '${tableName}.${fieldName}' (schema: ${JSON.stringify(value)})`,\n );\n };\n\n mapStringToSqliteColumn = (key: string, value: TString) => {\n if (value.format === \"uuid\") {\n if (PG_PRIMARY_KEY in value) {\n return pg\n .text(key)\n .primaryKey()\n .$defaultFn(() => randomUUID());\n }\n\n return pg.text(key);\n }\n\n if (value.format === \"byte\") {\n return this.sqliteJson(key, value);\n }\n\n if (value.format === \"date-time\") {\n if (PG_CREATED_AT in value) {\n return this.sqliteDateTime(key, {}).default(\n sql`(unixepoch('subsec') * 1000)`,\n );\n }\n if (PG_UPDATED_AT in value) {\n return this.sqliteDateTime(key, {}).default(\n sql`(unixepoch('subsec') * 1000)`,\n );\n }\n return this.sqliteDateTime(key, {});\n }\n\n if (value.format === \"date\") {\n return this.sqliteDate(key, {});\n }\n\n return pg.text(key);\n };\n\n sqliteJson = <TDocument extends TSchema>(name: string, document: TDocument) =>\n pg\n .customType<{\n data: Static<TDocument>;\n driverData: string;\n config: { document: TDocument };\n configRequired: true;\n }>({\n dataType: () => \"text\",\n toDriver: (value) => JSON.stringify(value),\n fromDriver: (value: TDocument | string) => {\n return value && typeof value === \"string\" ? JSON.parse(value) : value;\n },\n })(name, { document })\n .$type<Static<TDocument>>();\n\n sqliteDateTime = pg.customType<{\n data: string;\n driverData: number;\n configRequired: true;\n }>({\n dataType: () => \"integer\",\n toDriver: (value) => new Date(value).getTime(),\n fromDriver: (value) => {\n return new Date(value).toISOString();\n },\n });\n\n sqliteBool = pg.customType<{\n data: boolean;\n driverData: number;\n configRequired: true;\n }>({\n dataType: () => \"integer\",\n toDriver: (value) => (value ? 1 : 0),\n fromDriver: (value) => value === 1,\n });\n\n sqliteDate = pg.customType<{\n data: string;\n driverData: number;\n configRequired: true;\n }>({\n dataType: () => \"integer\",\n toDriver: (value) => new Date(value).getTime(),\n fromDriver: (value) => {\n return new Date(value).toISOString().split(\"T\")[0];\n },\n });\n}\n\nexport type SchemaToSqliteBuilder<T extends TObject> = {\n [key in keyof T[\"properties\"]]: SQLiteColumnBuilderBase;\n};\n","import type { Database } from \"bun:sqlite\";\nimport { mkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport {\n $atom,\n $env,\n $hook,\n $inject,\n $state,\n AlephaError,\n type Static,\n t,\n} from \"alepha\";\nimport type { BunSQLiteDatabase } from \"drizzle-orm/bun-sqlite\";\nimport type { PgDatabase } from \"drizzle-orm/pg-core\";\nimport { databaseEnvSchema } from \"../../schemas/databaseEnvSchema.ts\";\nimport { SqliteModelBuilder } from \"../../services/SqliteModelBuilder.ts\";\nimport { DatabaseProvider, type SQLLike } from \"./DatabaseProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst envSchema = databaseEnvSchema;\n\n/**\n * Configuration options for the Bun SQLite database provider.\n */\nexport const bunSqliteOptions = $atom({\n name: \"alepha.postgres.bun-sqlite.options\",\n schema: t.object({\n path: t.optional(\n t.string({\n description:\n \"Filepath or :memory:. If empty, provider will use DATABASE_URL from env.\",\n }),\n ),\n }),\n default: {},\n});\n\nexport type BunSqliteProviderOptions = Static<typeof bunSqliteOptions.schema>;\n\ndeclare module \"alepha\" {\n interface State {\n [bunSqliteOptions.key]: BunSqliteProviderOptions;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Bun SQLite provider using Drizzle ORM with Bun's native SQLite client.\n *\n * This provider uses Bun's built-in `bun:sqlite` for SQLite connections,\n * which provides excellent performance on the Bun runtime.\n *\n * @example\n * ```ts\n * // Set DATABASE_URL environment variable\n * // DATABASE_URL=sqlite://./my-database.db\n *\n * // Or configure programmatically\n * alepha.with({\n * provide: DatabaseProvider,\n * use: BunSqliteProvider,\n * });\n *\n * // Or use options atom\n * alepha.store.mut(bunSqliteOptions, (old) => ({\n * ...old,\n * path: \":memory:\",\n * }));\n * ```\n */\nexport class BunSqliteProvider extends DatabaseProvider {\n protected readonly env = $env(envSchema);\n protected readonly builder = $inject(SqliteModelBuilder);\n protected readonly options = $state(bunSqliteOptions);\n\n protected sqlite?: Database;\n protected bunDb?: BunSQLiteDatabase;\n\n public get name() {\n return \"sqlite\";\n }\n\n public override readonly dialect = \"sqlite\";\n\n public override get url(): string {\n const path = this.options.path ?? this.env.DATABASE_URL;\n if (path) {\n if (path.startsWith(\"postgres://\")) {\n throw new AlephaError(\n \"Postgres URL is not supported for SQLite provider.\",\n );\n }\n return path;\n }\n\n if (this.alepha.isTest() || this.alepha.isServerless()) {\n return \":memory:\";\n } else {\n return \"node_modules/.alepha/bun-sqlite.db\";\n }\n }\n\n public override get db(): PgDatabase<any> {\n if (!this.bunDb) {\n throw new AlephaError(\"Database not initialized\");\n }\n\n return this.bunDb as unknown as PgDatabase<any>;\n }\n\n public override get nativeConnection(): unknown {\n return this.sqlite;\n }\n\n public override async execute(\n query: SQLLike,\n ): Promise<Array<Record<string, unknown>>> {\n return (this.bunDb as BunSQLiteDatabase).all(query);\n }\n\n protected readonly onStart = $hook({\n on: \"start\",\n handler: async () => {\n // Check if we're running in Bun\n if (typeof Bun === \"undefined\") {\n throw new AlephaError(\n \"BunSqliteProvider requires the Bun runtime. Use NodeSqliteProvider for Node.js.\",\n );\n }\n\n const { Database } = await import(\"bun:sqlite\");\n const { drizzle } = await import(\"drizzle-orm/bun-sqlite\");\n\n const filepath = this.url.replace(\"sqlite://\", \"\").replace(\"sqlite:\", \"\");\n\n if (filepath !== \":memory:\" && filepath !== \"\") {\n const dir = dirname(filepath);\n if (dir) {\n await mkdir(dir, { recursive: true }).catch(() => null);\n }\n }\n\n this.sqlite = new Database(filepath);\n\n this.bunDb = drizzle({\n client: this.sqlite,\n logger: {\n logQuery: (query: string, params: unknown[]) => {\n this.log.trace(query, { params });\n },\n },\n });\n\n // Never migrate in serverless mode - migrations should be applied during deployment\n if (!this.alepha.isServerless()) {\n await this.migrate();\n }\n\n this.log.info(`Using Bun SQLite database at ${filepath}`);\n },\n });\n\n protected readonly onStop = $hook({\n on: \"stop\",\n priority: \"last\",\n handler: async () => {\n if (this.sqlite) {\n this.log.debug(\"Closing Bun SQLite connection...\");\n this.sqlite.close();\n this.sqlite = undefined;\n this.bunDb = undefined;\n this.log.info(\"Bun SQLite connection closed\");\n }\n },\n });\n\n protected async executeMigrations(migrationsFolder: string): Promise<void> {\n const { migrate } = await import(\"drizzle-orm/bun-sqlite/migrator\");\n await migrate(this.bunDb!, { migrationsFolder });\n }\n}\n","import { $env, $hook, $inject, AlephaError, t } from \"alepha\";\nimport type { DrizzleD1Database } from \"drizzle-orm/d1\";\nimport type { PgDatabase } from \"drizzle-orm/pg-core\";\nimport { SqliteModelBuilder } from \"../../services/SqliteModelBuilder.ts\";\nimport { DatabaseProvider, type SQLLike } from \"./DatabaseProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * D1Database interface matching Cloudflare's D1 API.\n */\nexport interface D1Database {\n prepare(query: string): D1PreparedStatement;\n batch<T = unknown>(statements: D1PreparedStatement[]): Promise<T[]>;\n exec(query: string): Promise<D1ExecResult>;\n dump(): Promise<ArrayBuffer>;\n}\n\nexport interface D1PreparedStatement {\n bind(...values: unknown[]): D1PreparedStatement;\n first<T = unknown>(colName?: string): Promise<T | null>;\n run(): Promise<D1Result>;\n all<T = unknown>(): Promise<D1Result<T>>;\n raw<T = unknown>(): Promise<T[]>;\n}\n\nexport interface D1Result<T = unknown> {\n results: T[];\n success: boolean;\n meta: {\n duration: number;\n changes: number;\n last_row_id: number;\n served_by: string;\n internal_stats: unknown;\n };\n}\n\nexport interface D1ExecResult {\n count: number;\n duration: number;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Cloudflare D1 SQLite provider using Drizzle ORM.\n */\nexport class CloudflareD1Provider extends DatabaseProvider {\n protected readonly builder = $inject(SqliteModelBuilder);\n protected readonly env = $env(\n t.object({\n DATABASE_URL: t.string({\n description: \"Expect to be 'd1://binding'\",\n }),\n }),\n );\n\n protected d1?: D1Database;\n protected drizzleDb?: DrizzleD1Database;\n\n public get name() {\n return \"sqlite\";\n }\n\n public get driver() {\n return \"d1\";\n }\n\n public override readonly dialect = \"sqlite\";\n\n public override get url(): string {\n return this.env.DATABASE_URL;\n }\n\n public override get db(): PgDatabase<any> {\n if (!this.drizzleDb) {\n throw new AlephaError(\"D1 database not initialized\");\n }\n\n return this.drizzleDb as unknown as PgDatabase<any>;\n }\n\n public override async execute(\n query: SQLLike,\n ): Promise<Array<Record<string, unknown>>> {\n const { rows } = await (this.db as any).run(query);\n return rows;\n }\n\n /**\n * D1 does not support SQL-level transactions (BEGIN/COMMIT/ROLLBACK).\n * It rejects these statements and requires the JS `batch()` API for atomic\n * multi-statement operations instead.\n *\n * @see https://developers.cloudflare.com/d1/worker-api/d1-database/#batch-statements\n * @see https://github.com/drizzle-team/drizzle-orm/issues/2463\n */\n public override get supportsTransactions(): boolean {\n return false;\n }\n\n protected readonly onStart = $hook({\n on: \"start\",\n handler: async () => {\n try {\n const [bindingName] = this.env.DATABASE_URL.replace(\"d1://\", \"\").split(\n \":\",\n );\n const cloudflareEnv = this.alepha.get(\"cloudflare.env\") as\n | Record<string, unknown>\n | undefined;\n if (!cloudflareEnv) {\n throw new AlephaError(\n \"Cloudflare Workers environment not found in Alepha store under 'cloudflare.env'.\",\n );\n }\n\n const binding = cloudflareEnv[bindingName] as D1Database;\n if (!binding) {\n throw new AlephaError(\n `D1 binding '${bindingName}' not found in Cloudflare Workers environment.`,\n );\n }\n\n this.d1 = binding;\n\n // Dynamic import to avoid crashes when not on Cloudflare\n const { drizzle } = await import(\"drizzle-orm/d1\");\n\n this.drizzleDb = drizzle(this.d1) as DrizzleD1Database;\n\n // Never migrate in serverless mode - D1 migrations must be applied\n // via `wrangler d1 migrations apply` before deployment\n if (!this.alepha.isServerless()) {\n await this.migrate();\n }\n\n this.log.info(\"Using Cloudflare D1 database\");\n } catch (error) {\n // Log the full error for debugging since Cloudflare Workers\n // doesn't properly display error causes\n const errorMessage =\n error instanceof Error\n ? `${error.message}${error.stack ? `\\n${error.stack}` : \"\"}`\n : String(error);\n this.log.error(`D1 initialization failed: ${errorMessage}`);\n throw error;\n }\n },\n });\n\n protected async executeMigrations(migrationsFolder: string): Promise<void> {\n this.log.debug(`Running D1 migrations from '${migrationsFolder}'...`);\n try {\n // Dynamic import for D1 migrator\n const { migrate } = await import(\"drizzle-orm/d1/migrator\");\n await migrate(this.db as any, { migrationsFolder });\n this.log.debug(\"D1 migrations completed successfully\");\n } catch (error) {\n const errorMessage =\n error instanceof Error\n ? `${error.name}: ${error.message}`\n : String(error);\n throw new AlephaError(\n `D1 migration failed from '${migrationsFolder}': ${errorMessage}`,\n { cause: error },\n );\n }\n }\n\n /**\n * D1 doesn't support push-based schema sync.\n * Always use file-based migrations regardless of environment.\n */\n public override async migrate(): Promise<void> {\n const migrationsFolder = this.getMigrationsFolder();\n try {\n await this.executeMigrations(migrationsFolder);\n } catch (error) {\n if (this.alepha.isTest()) {\n this.log.warn(\n \"D1 migrations failed in test environment - ensure migrations exist\",\n );\n } else {\n throw error;\n }\n }\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\n/**\n * Error thrown when a column does not exist.\n *\n * This typically happens when:\n * - Column name is misspelled\n * - Migrations haven't been run\n * - Using wrong schema version\n */\nexport class DbColumnNotFoundError extends DbError {\n readonly name = \"DbColumnNotFoundError\";\n readonly status = 500;\n\n /**\n * The column that was not found.\n */\n readonly column?: string;\n\n /**\n * The table where the column was expected.\n */\n readonly table?: string;\n\n constructor(\n message: string,\n cause?: unknown,\n options?: { column?: string; table?: string },\n ) {\n super(message, cause);\n this.column = options?.column;\n this.table = options?.table;\n }\n\n /**\n * Parse a database column not found error and create a DbColumnNotFoundError.\n * Supports both PostgreSQL and SQLite error formats.\n */\n static fromDatabaseError(error: Error): DbColumnNotFoundError {\n const message = error.message;\n\n // PostgreSQL format:\n // 'column \"foo\" does not exist'\n // 'column \"foo\" of relation \"users\" does not exist'\n const pgMatch = message.match(\n /column \"([^\"]+)\"(?: of relation \"([^\"]+)\")? does not exist/,\n );\n\n if (pgMatch) {\n const column = pgMatch[1];\n const table = pgMatch[2];\n const msg = table\n ? `Column '${column}' does not exist in table '${table}'`\n : `Column '${column}' does not exist`;\n return new DbColumnNotFoundError(msg, error, { column, table });\n }\n\n // SQLite format:\n // 'no such column: foo'\n // 'no such column: users.foo'\n const sqliteMatch = message.match(/no such column: (?:(\\S+)\\.)?(\\S+)/);\n\n if (sqliteMatch) {\n const table = sqliteMatch[1];\n const column = sqliteMatch[2];\n const msg = table\n ? `Column '${column}' does not exist in table '${table}'`\n : `Column '${column}' does not exist`;\n return new DbColumnNotFoundError(msg, error, { column, table });\n }\n\n return new DbColumnNotFoundError(\"Column does not exist\", error);\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\nexport class DbConflictError extends DbError {\n readonly name = \"DbConflictError\";\n readonly status = 409;\n}\n","import { DbError } from \"./DbError.ts\";\n\n/**\n * Error thrown when a deadlock is detected.\n *\n * This happens when two or more transactions are waiting for each other\n * to release locks. The database automatically aborts one transaction\n * to resolve the deadlock.\n *\n * This error is useful for implementing retry logic.\n */\nexport class DbDeadlockError extends DbError {\n readonly name = \"DbDeadlockError\";\n readonly status = 409;\n\n /**\n * Whether this error is retryable.\n * Deadlocks are typically safe to retry.\n */\n readonly retryable = true;\n\n /**\n * Parse a database deadlock error message and create a DbDeadlockError.\n * Supports PostgreSQL. SQLite doesn't have true deadlocks (uses SQLITE_BUSY instead).\n */\n static fromDatabaseError(error: Error): DbDeadlockError {\n return new DbDeadlockError(\n \"Transaction deadlock detected. Please retry the operation.\",\n error,\n );\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\nexport class DbEntityNotFoundError extends DbError {\n readonly name = \"DbEntityNotFoundError\";\n readonly status = 404;\n\n constructor(entityName: string) {\n super(`Entity from '${entityName}' was not found`);\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\n/**\n * Error thrown when a foreign key constraint is violated.\n *\n * This typically happens when trying to delete an entity that is\n * referenced by another entity.\n */\nexport class DbForeignKeyError extends DbError {\n readonly name = \"DbForeignKeyError\";\n readonly status = 409;\n\n /**\n * The table that references the entity being deleted.\n */\n readonly referencingTable?: string;\n\n /**\n * The constraint name that was violated.\n */\n readonly constraintName?: string;\n\n constructor(\n message: string,\n cause?: unknown,\n options?: { referencingTable?: string; constraintName?: string },\n ) {\n super(message, cause);\n this.referencingTable = options?.referencingTable;\n this.constraintName = options?.constraintName;\n }\n\n /**\n * Parse a database foreign key error message and create a DbForeignKeyError.\n * Supports both PostgreSQL and SQLite error formats.\n */\n static fromDatabaseError(error: Error, tableName: string): DbForeignKeyError {\n const message = error.message;\n\n // PostgreSQL format:\n // 'violates foreign key constraint \"reporting_alert_query_id_fk\" on table \"reporting_alert\"'\n const pgMatch = message.match(\n /violates foreign key constraint \"([^\"]+)\" on table \"([^\"]+)\"/,\n );\n\n if (pgMatch) {\n const constraintName = pgMatch[1];\n const referencingTable = pgMatch[2];\n\n return new DbForeignKeyError(\n `Cannot delete ${tableName}: it is referenced by ${referencingTable}`,\n error,\n { referencingTable, constraintName },\n );\n }\n\n // SQLite format:\n // 'FOREIGN KEY constraint failed' (no table name available)\n return new DbForeignKeyError(\n `Cannot delete ${tableName}: it is referenced by another entity`,\n error,\n );\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\n/**\n * Error thrown when a NOT NULL constraint is violated.\n *\n * This happens when inserting or updating a NULL value into a column\n * that has a NOT NULL constraint.\n */\nexport class DbNotNullError extends DbError {\n readonly name = \"DbNotNullError\";\n readonly status = 400;\n\n /**\n * The column that violated the NOT NULL constraint.\n */\n readonly column?: string;\n\n /**\n * The table containing the column.\n */\n readonly table?: string;\n\n constructor(\n message: string,\n cause?: unknown,\n options?: { column?: string; table?: string },\n ) {\n super(message, cause);\n this.column = options?.column;\n this.table = options?.table;\n }\n\n /**\n * Parse a database NOT NULL error message and create a DbNotNullError.\n * Supports both PostgreSQL and SQLite error formats.\n */\n static fromDatabaseError(error: Error, tableName: string): DbNotNullError {\n const message = error.message;\n\n // PostgreSQL format:\n // 'null value in column \"email\" of relation \"users\" violates not-null constraint'\n const pgMatch = message.match(\n /null value in column \"([^\"]+)\" of relation \"([^\"]+)\" violates not-null constraint/,\n );\n\n if (pgMatch) {\n const column = pgMatch[1];\n const table = pgMatch[2];\n return new DbNotNullError(\n `Column '${column}' in '${table}' cannot be null`,\n error,\n { column, table },\n );\n }\n\n // SQLite format:\n // 'NOT NULL constraint failed: users.email'\n const sqliteMatch = message.match(\n /NOT NULL constraint failed: ([^.]+)\\.(\\S+)/,\n );\n\n if (sqliteMatch) {\n const table = sqliteMatch[1];\n const column = sqliteMatch[2];\n return new DbNotNullError(\n `Column '${column}' in '${table}' cannot be null`,\n error,\n { column, table },\n );\n }\n\n return new DbNotNullError(\n `A required field in '${tableName}' cannot be null`,\n error,\n );\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\n/**\n * Error thrown when a table does not exist.\n *\n * This typically happens when:\n * - Migrations haven't been run\n * - Table name is misspelled\n * - Wrong database/schema is being used\n */\nexport class DbTableNotFoundError extends DbError {\n readonly name = \"DbTableNotFoundError\";\n readonly status = 500;\n\n /**\n * The table that was not found.\n */\n readonly table?: string;\n\n constructor(message: string, cause?: unknown, options?: { table?: string }) {\n super(message, cause);\n this.table = options?.table;\n }\n\n /**\n * Parse a database table not found error and create a DbTableNotFoundError.\n * Supports both PostgreSQL and SQLite error formats.\n */\n static fromDatabaseError(error: Error): DbTableNotFoundError {\n const message = error.message;\n\n // PostgreSQL format:\n // 'relation \"users\" does not exist'\n const pgMatch = message.match(/relation \"([^\"]+)\" does not exist/);\n\n if (pgMatch) {\n const table = pgMatch[1];\n return new DbTableNotFoundError(\n `Table '${table}' does not exist. Have you run migrations?`,\n error,\n { table },\n );\n }\n\n // SQLite format:\n // 'no such table: users'\n const sqliteMatch = message.match(/no such table: (\\S+)/);\n\n if (sqliteMatch) {\n const table = sqliteMatch[1];\n return new DbTableNotFoundError(\n `Table '${table}' does not exist. Have you run migrations?`,\n error,\n { table },\n );\n }\n\n return new DbTableNotFoundError(\n \"Table does not exist. Have you run migrations?\",\n error,\n );\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\n/**\n * Error thrown when there is a version mismatch.\n * It's thrown by {@link Repository#save} when the updated entity version does not match the one in the database.\n * This is used for optimistic concurrency control.\n */\nexport class DbVersionMismatchError extends DbError {\n readonly name = \"DbVersionMismatchError\";\n\n constructor(table: string, id: any) {\n super(`Version mismatch for table '${table}' and id '${id}'`);\n }\n}\n","import type { TObject, TSchema } from \"alepha\";\nimport type { PgSymbolKeys, PgSymbols } from \"../constants/PG_SYMBOLS.ts\";\n\n/**\n * Decorates a typebox schema with a Postgres attribute.\n *\n * > It's just a fancy way to add Symbols to a field.\n *\n * @example\n * ```ts\n * import { t } from \"alepha\";\n * import { PG_UPDATED_AT } from \"../constants/PG_SYMBOLS\";\n *\n * export const updatedAtSchema = pgAttr(\n * t.datetime(), PG_UPDATED_AT,\n * );\n * ```\n */\nexport const pgAttr = <T extends TSchema, Attr extends PgSymbolKeys>(\n type: T,\n attr: Attr,\n value?: PgSymbols[Attr],\n): PgAttr<T, Attr> => {\n Object.assign(type, { [attr]: value ?? {} });\n return type as PgAttr<T, Attr>;\n};\n\n/**\n * Retrieves the fields of a schema that have a specific attribute.\n */\nexport const getAttrFields = (\n schema: TObject,\n name: PgSymbolKeys,\n): PgAttrField[] => {\n const fields: Array<PgAttrField> = [];\n\n for (const key of Object.keys(schema.properties)) {\n const value = schema.properties[key];\n if (name in value) {\n fields.push({\n type: value as TSchema,\n key: key,\n data: (value as any)[name],\n });\n }\n }\n\n return fields;\n};\n\n/**\n * Type representation.\n */\nexport type PgAttr<T extends TSchema, TAttr extends PgSymbolKeys> = T & {\n [K in TAttr]: PgSymbols[K];\n};\n\nexport interface PgAttrField {\n key: string;\n type: TSchema;\n data: any;\n nested?: any[];\n one?: boolean;\n}\n","import { $inject } from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\n\n/**\n * Database query cache using a simple in-memory Map.\n *\n * Uses `{tableName}:{cacheKey}` as the storage key.\n * Provides per-table invalidation for write-through cache busting.\n *\n * This is intentionally self-contained (no external cache dependencies)\n * so the ORM module does not force `AlephaCache` on all consumers.\n */\nexport class DbCacheProvider {\n protected readonly dateTime = $inject(DateTimeProvider);\n protected readonly store = new Map<\n string,\n { value: unknown; expiresAt?: number }\n >();\n\n protected storeKey(tableName: string, cacheKey: string): string {\n return `${tableName}:${cacheKey}`;\n }\n\n /**\n * Get a cached query result.\n */\n public async get<T>(\n tableName: string,\n cacheKey: string,\n ): Promise<T | undefined> {\n const key = this.storeKey(tableName, cacheKey);\n const entry = this.store.get(key);\n\n if (!entry) return undefined;\n if (entry.expiresAt && this.dateTime.nowMillis() > entry.expiresAt) {\n this.store.delete(key);\n return undefined;\n }\n\n return entry.value as T;\n }\n\n /**\n * Store a query result in the cache.\n */\n public async set<T>(\n tableName: string,\n cacheKey: string,\n value: T,\n ttl?: number,\n ): Promise<void> {\n const key = this.storeKey(tableName, cacheKey);\n this.store.set(key, {\n value,\n expiresAt: ttl ? this.dateTime.nowMillis() + ttl : undefined,\n });\n }\n\n /**\n * Invalidate all cached queries for a table.\n */\n public async invalidateTable(tableName: string): Promise<void> {\n const prefix = `${tableName}:`;\n for (const key of this.store.keys()) {\n if (key.startsWith(prefix)) {\n this.store.delete(key);\n }\n }\n }\n}\n","import { type TObject, t, Value } from \"alepha\";\nimport { getTableName, type SQL, sql } from \"drizzle-orm\";\nimport type { PgSelectBase, PgTableWithColumns } from \"drizzle-orm/pg-core\";\nimport { isSQLWrapper } from \"drizzle-orm/sql/sql\";\nimport type { PgRelationMap } from \"../interfaces/PgQuery.ts\";\nimport type { EntityPrimitive } from \"../primitives/$entity.ts\";\nimport type { DatabaseProvider } from \"../providers/drivers/DatabaseProvider.ts\";\nimport type { PgJoin } from \"./QueryManager.ts\";\n\nexport class PgRelationManager {\n /**\n * Recursively build joins for the query builder based on the relations map\n */\n public buildJoins(\n provider: DatabaseProvider,\n builder: PgSelectBase<any, any, any>,\n joins: Array<PgJoin>,\n withRelations: PgRelationMap<TObject>,\n table: PgTableWithColumns<any>,\n parentKey?: string,\n ) {\n for (const [key, join] of Object.entries(withRelations)) {\n const from = provider.table(join.join as EntityPrimitive);\n const on = isSQLWrapper(join.on)\n ? (join.on as SQL)\n : sql`${table[join.on[0] as string]} = ${from[join.on[1].name]}`;\n\n if (join.type === \"right\") {\n builder.rightJoin(from, on);\n } else if (join.type === \"inner\") {\n builder.innerJoin(from, on);\n } else {\n builder.leftJoin(from, on);\n }\n\n joins.push({\n key,\n table: getTableName(from),\n schema: join.join.schema,\n col: (name: string) => from[name],\n parent: parentKey,\n });\n\n if (join.with) {\n this.buildJoins(\n provider,\n builder,\n joins,\n join.with,\n from,\n parentKey ? `${parentKey}.${key}` : key,\n );\n }\n }\n }\n\n /**\n * Map a row with its joined relations based on the joins definition\n */\n public mapRowWithJoins(\n record: Record<string, unknown>,\n row: Record<string, unknown>,\n schema: TObject,\n joins: PgJoin[],\n parentKey?: string,\n ) {\n for (const join of joins) {\n if (join.parent === parentKey) {\n const joinedData = row[join.table];\n // Set to undefined if all values in the joined table are null (left join with no match)\n if (this.isAllNull(joinedData)) {\n record[join.key] = undefined;\n } else {\n record[join.key] = joinedData;\n // Only process nested joins if the parent join has data\n this.mapRowWithJoins(\n record[join.key] as Record<string, unknown>,\n row,\n schema, // Don't need to pass modified schema, just for recursion\n joins,\n parentKey ? `${parentKey}.${join.key}` : join.key,\n );\n }\n }\n }\n return record;\n }\n\n /**\n * Check if all values in an object are null (indicates a left join with no match)\n */\n protected isAllNull(obj: unknown): boolean {\n if (obj === null || obj === undefined) return true;\n if (typeof obj !== \"object\") return false;\n return Object.values(obj).every((val) => val === null);\n }\n\n /**\n * Build a schema that includes all join properties recursively\n */\n public buildSchemaWithJoins(\n baseSchema: TObject,\n joins: PgJoin[],\n parentPath?: string,\n ): TObject {\n const schema = Value.Clone(baseSchema) as TObject;\n\n // Group joins by parent\n const joinsAtThisLevel = joins.filter((j) => j.parent === parentPath);\n\n for (const join of joinsAtThisLevel) {\n // Build the path for this join\n const joinPath = parentPath ? `${parentPath}.${join.key}` : join.key;\n\n // Find child joins\n const childJoins = joins.filter((j) => j.parent === joinPath);\n\n // If there are child joins, recursively build the schema\n let joinSchema = join.schema;\n if (childJoins.length > 0) {\n joinSchema = this.buildSchemaWithJoins(join.schema, joins, joinPath);\n }\n\n // Make the join optional (left joins may return null)\n schema.properties[join.key] = t.optional(joinSchema);\n }\n\n return schema;\n }\n}\n","import {\n $inject,\n Alepha,\n AlephaError,\n createPagination,\n type TObject,\n} from \"alepha\";\nimport {\n and,\n arrayContained,\n arrayContains,\n arrayOverlaps,\n between,\n eq,\n exists,\n gt,\n gte,\n ilike,\n inArray,\n isNotNull,\n isNull,\n isSQLWrapper,\n like,\n lt,\n lte,\n ne,\n not,\n notBetween,\n notExists,\n notIlike,\n notInArray,\n notLike,\n or,\n type SQL,\n type SQLWrapper,\n sql,\n} from \"drizzle-orm\";\nimport type { PgColumn } from \"drizzle-orm/pg-core\";\nimport type { FilterOperators } from \"../interfaces/FilterOperators.ts\";\nimport type {\n PgQueryWhere,\n PgQueryWhereOrSQL,\n} from \"../interfaces/PgQueryWhere.ts\";\n\nexport class QueryManager {\n protected readonly alepha = $inject(Alepha);\n\n /**\n * Convert a query object to a SQL query.\n */\n public toSQL(\n query: PgQueryWhereOrSQL<TObject>,\n options: {\n schema: TObject;\n col: (key: string) => PgColumn;\n joins?: PgJoin[];\n dialect: \"postgresql\" | \"sqlite\";\n },\n ): SQL | undefined {\n const { schema, col, joins } = options;\n const conditions: SQL[] = [];\n\n if (isSQLWrapper(query)) {\n conditions.push(query as SQL);\n } else {\n const keys = Object.keys(query) as Array<\n keyof PgQueryWhere<TObject> & string\n >;\n\n for (const key of keys) {\n const operator = query[key] as SQL;\n\n // Handle joins - check if this key matches a join at the current level\n if (\n typeof query[key] === \"object\" &&\n query[key] != null &&\n !Array.isArray(query[key]) &&\n joins?.length\n ) {\n // Find the join that matches this key (at the current level, without parent filtering)\n const matchingJoins = joins.filter((j) => j.key === key);\n if (matchingJoins.length > 0) {\n // Use the first matching join (they should all have the same schema)\n const join = matchingJoins[0];\n\n // Build the full path to this join\n const joinPath = join.parent ? `${join.parent}.${key}` : key;\n\n // Find child joins: those whose parent starts with this join's path\n const childJoins = joins.filter((j) => {\n if (!j.parent) return false;\n // Child's parent should be exactly our path, or start with our path + \".\"\n return (\n j.parent === joinPath || j.parent.startsWith(`${joinPath}.`)\n );\n });\n\n // For recursion, we need to restructure child joins\n // Remove the current path prefix from parent keys\n const recursiveJoins = childJoins.map((j) => {\n const newParent =\n j.parent === joinPath\n ? undefined\n : j.parent!.substring(joinPath.length + 1);\n return {\n ...j,\n parent: newParent,\n };\n });\n\n const sql = this.toSQL(query[key], {\n schema: join.schema,\n col: join.col,\n joins: recursiveJoins.length > 0 ? recursiveJoins : undefined,\n dialect: options.dialect,\n });\n if (sql) {\n conditions.push(sql);\n }\n continue;\n }\n }\n\n if (Array.isArray(operator)) {\n const operations: SQL[] = operator\n .map((it) => {\n if (isSQLWrapper(it)) {\n return it as SQL;\n }\n return this.toSQL(it as PgQueryWhere<TObject>, {\n schema,\n col,\n joins, // Pass joins through recursively\n dialect: options.dialect,\n });\n })\n .filter((it) => it != null);\n\n if (key === \"and\") {\n return and(...operations);\n }\n\n if (key === \"or\") {\n return or(...operations);\n }\n }\n\n if (key === \"not\") {\n const where = this.toSQL(operator as PgQueryWhereOrSQL<TObject>, {\n schema,\n col,\n joins, // Pass joins through recursively\n dialect: options.dialect,\n });\n if (where) {\n conditions.push(not(where));\n }\n continue;\n }\n\n if (key === \"exists\") {\n conditions.push(exists(operator as SQLWrapper));\n continue;\n }\n\n if (key === \"notExists\") {\n conditions.push(notExists(operator as SQLWrapper));\n continue;\n }\n\n if (operator != null) {\n const column = col(key);\n const sql = this.mapOperatorToSql(\n operator,\n column,\n schema,\n key,\n options.dialect,\n );\n if (sql) {\n conditions.push(sql);\n }\n }\n }\n }\n\n if (conditions.length === 1) {\n return conditions[0];\n }\n\n return and(...conditions);\n }\n\n /**\n * Check if an object has any filter operator properties.\n */\n protected hasFilterOperatorProperties(obj: any): boolean {\n if (!obj || typeof obj !== \"object\") return false;\n\n const filterOperatorKeys = [\n \"eq\",\n \"ne\",\n \"gt\",\n \"gte\",\n \"lt\",\n \"lte\",\n \"inArray\",\n \"notInArray\",\n \"isNull\",\n \"isNotNull\",\n \"like\",\n \"notLike\",\n \"ilike\",\n \"notIlike\",\n \"contains\",\n \"startsWith\",\n \"endsWith\",\n \"between\",\n \"notBetween\",\n \"arrayContains\",\n \"arrayContained\",\n \"arrayOverlaps\",\n ];\n\n return filterOperatorKeys.some((key) => key in obj);\n }\n\n /**\n * Map a filter operator to a SQL query.\n */\n public mapOperatorToSql(\n operator: FilterOperators<any> | any,\n column: PgColumn,\n columnSchema?: TObject,\n columnName?: string,\n dialect: \"postgresql\" | \"sqlite\" = \"postgresql\",\n ): SQL | undefined {\n // Helper function to encode a value for the specific column\n const encodeValue = (value: any): any => {\n if (value == null) {\n return value;\n }\n\n // If we have schema information, encode the value properly\n if (columnSchema && columnName) {\n try {\n const fieldSchema = columnSchema.properties[columnName];\n if (fieldSchema) {\n // Encode the value using the drizzle codec\n // This converts application values (like Dayjs) to database values (like ISO strings)\n return this.alepha.codec.encode(fieldSchema, value, {\n encoder: \"drizzle\",\n });\n }\n } catch (error) {\n // If encoding fails, fall back to the original value\n // This ensures backward compatibility\n }\n }\n\n return value;\n };\n\n // Helper function to encode array values\n const encodeArray = (values: any[]): any[] => {\n return values.map((v) => encodeValue(v));\n };\n\n // If operator is not an object, OR it's an object but doesn't have any filter operator properties,\n // treat it as a direct value (e.g., string, number, Date, Dayjs, etc.)\n if (\n typeof operator !== \"object\" ||\n operator == null ||\n !this.hasFilterOperatorProperties(operator)\n ) {\n return eq(column, encodeValue(operator));\n }\n\n const conditions: SQL[] = [];\n\n if (operator?.eq != null) {\n conditions.push(eq(column, encodeValue(operator.eq)));\n }\n\n if (operator?.ne != null) {\n conditions.push(ne(column, encodeValue(operator.ne)));\n }\n\n if (operator?.gt != null) {\n conditions.push(gt(column, encodeValue(operator.gt)));\n }\n\n if (operator?.gte != null) {\n conditions.push(gte(column, encodeValue(operator.gte)));\n }\n\n if (operator?.lt != null) {\n conditions.push(lt(column, encodeValue(operator.lt)));\n }\n\n if (operator?.lte != null) {\n conditions.push(lte(column, encodeValue(operator.lte)));\n }\n\n if (operator?.inArray != null) {\n if (!Array.isArray(operator.inArray) || operator.inArray.length === 0) {\n throw new AlephaError(\"inArray operator requires at least one value\");\n }\n conditions.push(inArray(column, encodeArray(operator.inArray)));\n }\n\n if (operator?.notInArray != null) {\n if (\n !Array.isArray(operator.notInArray) ||\n operator.notInArray.length === 0\n ) {\n throw new AlephaError(\n \"notInArray operator requires at least one value\",\n );\n }\n conditions.push(notInArray(column, encodeArray(operator.notInArray)));\n }\n\n if (operator?.isNull != null) {\n conditions.push(isNull(column));\n }\n\n if (operator?.isNotNull != null) {\n conditions.push(isNotNull(column));\n }\n\n if (operator?.like != null) {\n conditions.push(like(column, encodeValue(operator.like)));\n }\n\n if (operator?.notLike != null) {\n conditions.push(notLike(column, encodeValue(operator.notLike)));\n }\n\n if (operator?.ilike != null) {\n if (dialect === \"sqlite\") {\n // SQLite doesn't have ilike, use LOWER() for case-insensitive matching\n conditions.push(\n sql`LOWER(${column}) LIKE LOWER(${encodeValue(operator.ilike)})`,\n );\n } else {\n conditions.push(ilike(column, encodeValue(operator.ilike)));\n }\n }\n\n if (operator?.notIlike != null) {\n if (dialect === \"sqlite\") {\n // SQLite doesn't have ilike, use LOWER() for case-insensitive matching\n conditions.push(\n sql`LOWER(${column}) NOT LIKE LOWER(${encodeValue(operator.notIlike)})`,\n );\n } else {\n conditions.push(notIlike(column, encodeValue(operator.notIlike)));\n }\n }\n\n if (operator?.contains != null) {\n // Escape LIKE special characters to prevent wildcard injection\n const escapedValue = String(operator.contains)\n .replace(/\\\\/g, \"\\\\\\\\\") // Escape backslash first\n .replace(/%/g, \"\\\\%\") // Escape %\n .replace(/_/g, \"\\\\_\"); // Escape _\n\n if (dialect === \"sqlite\") {\n // SQLite doesn't have ilike, use LOWER() for case-insensitive matching\n // ESCAPE '\\\\' is required for SQLite to recognize backslash as escape character\n conditions.push(\n sql`LOWER(${column}) LIKE LOWER(${encodeValue(`%${escapedValue}%`)}) ESCAPE '\\\\'`,\n );\n } else {\n conditions.push(ilike(column, encodeValue(`%${escapedValue}%`)));\n }\n }\n\n if (operator?.startsWith != null) {\n // Escape LIKE special characters to prevent wildcard injection\n const escapedValue = String(operator.startsWith)\n .replace(/\\\\/g, \"\\\\\\\\\") // Escape backslash first\n .replace(/%/g, \"\\\\%\") // Escape %\n .replace(/_/g, \"\\\\_\"); // Escape _\n\n if (dialect === \"sqlite\") {\n // SQLite doesn't have ilike, use LOWER() for case-insensitive matching\n conditions.push(\n sql`LOWER(${column}) LIKE LOWER(${encodeValue(`${escapedValue}%`)}) ESCAPE '\\\\'`,\n );\n } else {\n conditions.push(ilike(column, encodeValue(`${escapedValue}%`)));\n }\n }\n\n if (operator?.endsWith != null) {\n // Escape LIKE special characters to prevent wildcard injection\n const escapedValue = String(operator.endsWith)\n .replace(/\\\\/g, \"\\\\\\\\\") // Escape backslash first\n .replace(/%/g, \"\\\\%\") // Escape %\n .replace(/_/g, \"\\\\_\"); // Escape _\n\n if (dialect === \"sqlite\") {\n // SQLite doesn't have ilike, use LOWER() for case-insensitive matching\n conditions.push(\n sql`LOWER(${column}) LIKE LOWER(${encodeValue(`%${escapedValue}`)}) ESCAPE '\\\\'`,\n );\n } else {\n conditions.push(ilike(column, encodeValue(`%${escapedValue}`)));\n }\n }\n\n if (operator?.between != null) {\n if (!Array.isArray(operator.between) || operator.between.length !== 2) {\n throw new AlephaError(\n \"between operator requires exactly 2 values [min, max]\",\n );\n }\n conditions.push(\n between(\n column,\n encodeValue(operator.between[0]),\n encodeValue(operator.between[1]),\n ),\n );\n }\n\n if (operator?.notBetween != null) {\n if (\n !Array.isArray(operator.notBetween) ||\n operator.notBetween.length !== 2\n ) {\n throw new AlephaError(\n \"notBetween operator requires exactly 2 values [min, max]\",\n );\n }\n conditions.push(\n notBetween(\n column,\n encodeValue(operator.notBetween[0]),\n encodeValue(operator.notBetween[1]),\n ),\n );\n }\n\n if (operator?.arrayContains != null) {\n conditions.push(\n arrayContains(column, encodeValue(operator.arrayContains)),\n );\n }\n\n if (operator?.arrayContained != null) {\n conditions.push(\n arrayContained(column, encodeValue(operator.arrayContained)),\n );\n }\n\n if (operator?.arrayOverlaps != null) {\n conditions.push(\n arrayOverlaps(column, encodeValue(operator.arrayOverlaps)),\n );\n }\n\n if (conditions.length === 0) {\n return undefined;\n }\n\n if (conditions.length === 1) {\n return conditions[0];\n }\n\n return and(...conditions);\n }\n\n /**\n * Parse pagination sort string to orderBy format.\n * Format: \"firstName,-lastName\" -> [{ column: \"firstName\", direction: \"asc\" }, { column: \"lastName\", direction: \"desc\" }]\n * - Columns separated by comma\n * - Prefix with '-' for DESC direction\n *\n * @param sort Pagination sort string\n * @returns OrderBy array or single object\n */\n public parsePaginationSort(\n sort: string,\n ):\n | Array<{ column: string; direction: \"asc\" | \"desc\" }>\n | { column: string; direction: \"asc\" | \"desc\" } {\n const fields = sort.split(\",\").map((field) => field.trim());\n\n const orderByClauses = fields.map((field) => {\n if (field.startsWith(\"-\")) {\n return {\n column: field.substring(1),\n direction: \"desc\" as const,\n };\n }\n return {\n column: field,\n direction: \"asc\" as const,\n };\n });\n\n // Return single object if only one field, array if multiple\n return orderByClauses.length === 1 ? orderByClauses[0] : orderByClauses;\n }\n\n /**\n * Normalize orderBy parameter to array format.\n * Supports 3 modes:\n * 1. String: \"name\" -> [{ column: \"name\", direction: \"asc\" }]\n * 2. Object: { column: \"name\", direction: \"desc\" } -> [{ column: \"name\", direction: \"desc\" }]\n * 3. Array: [{ column: \"name\" }, { column: \"age\", direction: \"desc\" }] -> normalized array\n *\n * @param orderBy The orderBy parameter\n * @returns Normalized array of order by clauses\n */\n public normalizeOrderBy(\n orderBy: any,\n ): Array<{ column: string; direction: \"asc\" | \"desc\" }> {\n // Mode 1: String -> single column, ASC by default\n if (typeof orderBy === \"string\") {\n return [{ column: orderBy, direction: \"asc\" }];\n }\n\n // Mode 2: Single object -> convert to array\n if (!Array.isArray(orderBy) && typeof orderBy === \"object\") {\n return [\n {\n column: orderBy.column,\n direction: orderBy.direction ?? \"asc\",\n },\n ];\n }\n\n // Mode 3: Array -> normalize each item with default direction\n if (Array.isArray(orderBy)) {\n return orderBy.map((item) => ({\n column: item.column,\n direction: item.direction ?? \"asc\",\n }));\n }\n\n return [];\n }\n\n /**\n * Create a pagination object.\n *\n * @deprecated Use `createPagination` from alepha instead.\n * This method now delegates to the framework-level helper.\n *\n * @param entities The entities to paginate.\n * @param limit The limit of the pagination.\n * @param offset The offset of the pagination.\n * @param sort Optional sort metadata to include in response.\n */\n public createPagination<T>(\n entities: T[],\n limit = 10,\n offset = 0,\n sort?: Array<{ column: string; direction: \"asc\" | \"desc\" }>,\n ) {\n return createPagination(entities, limit, offset, sort);\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface PgJoin {\n table: string;\n schema: TObject;\n key: string;\n col: (key: string) => PgColumn;\n parent?: string;\n}\n","import {\n $inject,\n Alepha,\n AlephaError,\n type Page,\n type PageQuery,\n type Static,\n type StaticEncode,\n type TObject,\n type TSchema,\n t,\n} from \"alepha\";\nimport { type DateTime, DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { currentUserAtom } from \"alepha/security\";\nimport {\n asc,\n avg,\n count,\n desc,\n and as drizzleAnd,\n eq as drizzleEq,\n gt,\n gte,\n lt,\n lte,\n max,\n min,\n ne,\n type SQL,\n sum,\n} from \"drizzle-orm\";\nimport type {\n LockConfig,\n LockStrength,\n PgColumn,\n PgDatabase,\n PgInsertValue,\n PgTable,\n PgTableWithColumns,\n PgTransaction,\n PgUpdateSetSource,\n} from \"drizzle-orm/pg-core\";\nimport type { PgTransactionConfig } from \"drizzle-orm/pg-core/session\";\nimport {\n PG_DELETED_AT,\n PG_ORGANIZATION,\n PG_PRIMARY_KEY,\n PG_UPDATED_AT,\n PG_VERSION,\n} from \"../constants/PG_SYMBOLS.ts\";\nimport { DbColumnNotFoundError } from \"../errors/DbColumnNotFoundError.ts\";\nimport { DbConflictError } from \"../errors/DbConflictError.ts\";\nimport { DbDeadlockError } from \"../errors/DbDeadlockError.ts\";\nimport { DbEntityNotFoundError } from \"../errors/DbEntityNotFoundError.ts\";\nimport { DbError } from \"../errors/DbError.ts\";\nimport { DbForeignKeyError } from \"../errors/DbForeignKeyError.ts\";\nimport { DbNotNullError } from \"../errors/DbNotNullError.ts\";\nimport { DbTableNotFoundError } from \"../errors/DbTableNotFoundError.ts\";\nimport { DbVersionMismatchError } from \"../errors/DbVersionMismatchError.ts\";\nimport { getAttrFields, type PgAttrField } from \"../helpers/pgAttr.ts\";\nimport type {\n AggregateOp,\n AggregateQuery,\n AggregateResult,\n AggregateSelect,\n} from \"../interfaces/AggregateQuery.ts\";\nimport type {\n PgQuery,\n PgQueryRelations,\n PgRelationMap,\n PgStatic,\n} from \"../interfaces/PgQuery.ts\";\nimport type {\n PgQueryWhere,\n PgQueryWhereOrSQL,\n} from \"../interfaces/PgQueryWhere.ts\";\nimport type {\n EntityPrimitive,\n SchemaToTableConfig,\n} from \"../primitives/$entity.ts\";\nimport { DbCacheProvider } from \"../providers/DbCacheProvider.ts\";\nimport {\n DatabaseProvider,\n type SQLLike,\n} from \"../providers/drivers/DatabaseProvider.ts\";\nimport type { TObjectInsert } from \"../schemas/insertSchema.ts\";\nimport type { TObjectUpdate } from \"../schemas/updateSchema.ts\";\nimport { PgRelationManager } from \"./PgRelationManager.ts\";\nimport { type PgJoin, QueryManager } from \"./QueryManager.ts\";\n\nexport abstract class Repository<T extends TObject> {\n public readonly entity: EntityPrimitive<T>;\n public readonly provider: DatabaseProvider;\n\n protected readonly log = $logger();\n protected readonly relationManager = $inject(PgRelationManager);\n protected readonly queryManager = $inject(QueryManager);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly dbCache = new DbCacheProvider();\n protected readonly alepha = $inject(Alepha);\n\n static of<T extends TObject>(\n entity: EntityPrimitive<T>,\n provider = DatabaseProvider,\n ): new () => Repository<T> {\n return class InlineRepository extends Repository<T> {\n constructor() {\n super(entity, provider);\n }\n };\n }\n\n constructor(entity: EntityPrimitive<T>, provider = DatabaseProvider) {\n this.entity = entity;\n this.provider = this.alepha.inject(provider);\n if ((entity as any).isView) {\n this.provider.registerView(entity as any);\n } else {\n this.provider.registerEntity(entity as EntityPrimitive);\n }\n }\n\n /**\n * Represents the primary key of the table.\n * - Key is the name of the primary key column.\n * - Type is the type (TypeBox) of the primary key column.\n *\n * ID is mandatory. If the table does not have a primary key, it will throw an error.\n */\n public get id(): {\n type: TSchema;\n key: keyof T[\"properties\"];\n col: PgColumn;\n } {\n return this.getPrimaryKey(this.entity.schema);\n }\n\n /**\n * Get Drizzle table object.\n */\n public get table(): PgTableWithColumns<SchemaToTableConfig<T>> {\n return this.provider.table(this.entity);\n }\n\n /**\n * Get SQL table name. (from Drizzle table object)\n */\n public get tableName(): string {\n return this.entity.name;\n }\n\n /**\n * Whether this repository is backed by a view (read-only).\n */\n public get isReadOnly(): boolean {\n return (this.entity as any).isView === true;\n }\n\n /**\n * Getter for the database connection from the database provider.\n *\n * Automatically picks up a transaction from `alepha.store` if one was set\n * by `DatabaseProvider.transactional()`, so that all repository operations\n * inside a `transactional()` block participate in the same transaction.\n */\n protected get db(): PgDatabase<any> {\n const tx = this.alepha.get(\"alepha.orm.tx\");\n return tx ?? this.provider.db;\n }\n\n /**\n * Execute a SQL query.\n *\n * This method allows executing raw SQL queries against the database.\n * This is by far the easiest way to run custom queries that are not covered by the repository's built-in methods!\n *\n * You must use the `sql` tagged template function from Drizzle ORM to create the query. https://orm.drizzle.team/docs/sql\n *\n * @example\n * ```ts\n * class App {\n * repository = $repository({ ... });\n * async getAdults() {\n * const users = repository.table; // Drizzle table object\n * await repository.query(sql`SELECT * FROM ${users} WHERE ${users.age} > ${18}`);\n * // or better\n * await repository.query((users) => sql`SELECT * FROM ${users} WHERE ${users.age} > ${18}`);\n * }\n * }\n * ```\n */\n public async query<R extends TObject = T>(\n query:\n | SQLLike\n | ((\n table: PgTableWithColumns<SchemaToTableConfig<T>>,\n db: PgDatabase<any>,\n ) => SQLLike),\n schema?: R,\n ): Promise<Static<R>[]> {\n const raw =\n typeof query === \"function\" ? query(this.table, this.db) : query;\n\n if (typeof raw === \"string\" && raw.includes(\"[object Object]\")) {\n throw new AlephaError(\n \"Invalid SQL query. Did you forget to call the 'sql' function?\",\n );\n }\n\n // Only wrap database execution errors, not post-processing errors (e.g., TypeBoxError)\n let rows: Array<Record<string, unknown>>;\n try {\n rows = await this.provider.execute(raw);\n } catch (error) {\n throw this.handleError(error, \"Custom query has failed\");\n }\n\n if (rows == null) {\n return [];\n }\n\n if (!Array.isArray(rows)) {\n throw new DbError(\n \"Invalid query result. Expected an array of rows, but got: \" +\n JSON.stringify(rows),\n );\n }\n\n return rows.map((it) => {\n return this.clean(\n this.mapRawFieldsToEntity(it),\n schema ?? this.entity.schema,\n ) as Static<R>;\n });\n }\n\n protected columnNameMap?: Map<string, string>;\n\n /**\n * Map raw database fields to entity fields. (handles column name differences)\n */\n protected mapRawFieldsToEntity(row: Record<string, unknown>) {\n if (!this.columnNameMap) {\n this.columnNameMap = new Map();\n for (const colKey of Object.keys(this.table)) {\n this.columnNameMap.set(this.table[colKey].name, colKey);\n }\n }\n\n const entity: any = {};\n\n for (const key of Object.keys(row)) {\n entity[key] = row[key];\n const fieldKey = this.columnNameMap.get(key);\n if (fieldKey) {\n entity[fieldKey] = row[key];\n }\n }\n\n return entity;\n }\n\n /**\n * Get a Drizzle column from the table by his name.\n */\n protected col(name: keyof StaticEncode<T>): PgColumn {\n const column = (this.table as any)[name];\n if (!column) {\n throw new AlephaError(\n `Invalid access. Column '${String(name)}' not found in table '${this.tableName}'`,\n );\n }\n\n return column;\n }\n\n /**\n * Run a transaction.\n */\n public async transaction<T>(\n transaction: (\n tx: PgTransaction<any, Record<string, any>, any>,\n ) => Promise<T>,\n config?: PgTransactionConfig,\n ): Promise<T> {\n if (!this.provider.supportsTransactions) {\n throw new AlephaError(\n `Transactions are not supported with ${this.provider.driver} driver. Use $transactional() middleware instead, which gracefully degrades on unsupported drivers.`,\n );\n }\n\n this.log.debug(`Starting transaction on table ${this.tableName}`);\n return await this.db.transaction(transaction, config);\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Start a SELECT query on the table.\n */\n protected rawSelect(opts: StatementOptions = {}) {\n const db = opts.tx === null ? this.provider.db : (opts.tx ?? this.db);\n return db.select().from(this.table as PgTable);\n }\n\n /**\n * Start a SELECT DISTINCT query on the table.\n */\n protected rawSelectDistinct(\n opts: StatementOptions = {},\n columns: (keyof Static<T>)[] = [],\n ) {\n const db = opts.tx === null ? this.provider.db : (opts.tx ?? this.db);\n const table = this.table as PgTable;\n\n const fields: Record<string, any> = {};\n for (const column of columns) {\n if (typeof column === \"string\") {\n fields[column] = this.col(column);\n }\n }\n\n return db.selectDistinct(fields).from(table);\n }\n\n /**\n * Start an INSERT query on the table.\n */\n protected rawInsert(opts: StatementOptions = {}) {\n const db = opts.tx === null ? this.provider.db : (opts.tx ?? this.db);\n return db.insert(this.table);\n }\n\n /**\n * Start an UPDATE query on the table.\n */\n protected rawUpdate(opts: StatementOptions = {}) {\n const db = opts.tx === null ? this.provider.db : (opts.tx ?? this.db);\n return db.update(this.table);\n }\n\n /**\n * Start a DELETE query on the table.\n */\n protected rawDelete(opts: StatementOptions = {}) {\n const db = opts.tx === null ? this.provider.db : (opts.tx ?? this.db);\n return db.delete(this.table);\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Create a Drizzle `select` query based on a JSON query object.\n *\n * > This method is the base for `find`, `findOne`, `findById`, and `paginate`.\n */\n public async findMany<R extends PgRelationMap<T>>(\n query: PgQueryRelations<T, R> = {},\n opts: StatementOptions = {},\n ): Promise<PgStatic<T, R>[]> {\n // Check cache\n if (opts.cache) {\n const cacheKey = opts.cache.key ?? this.buildCacheKey(\"findMany\", query);\n const cached = await this.dbCache.get<PgStatic<T, R>[]>(\n this.tableName,\n cacheKey,\n );\n if (cached) return cached;\n }\n\n await this.alepha.events.emit(\"repository:read:before\", {\n tableName: this.tableName,\n query,\n });\n\n const columns = query.columns ?? query.distinct;\n const builder = query.distinct\n ? this.rawSelectDistinct(opts, query.distinct)\n : this.rawSelect(opts);\n\n const joins: Array<PgJoin> = [];\n if (query.with) {\n this.relationManager.buildJoins(\n this.provider,\n builder,\n joins,\n query.with,\n this.table,\n );\n }\n\n const where = this.withOrganization(\n this.withDeletedAt((query.where ?? {}) as PgQueryWhere<T>, opts),\n );\n\n builder.where(() => this.toSQL(where, joins));\n\n if (query.offset) {\n builder.offset(query.offset);\n\n // SQLite requires LIMIT when OFFSET is used\n if (this.provider.dialect === \"sqlite\" && !query.limit) {\n query.limit = 1000;\n }\n }\n\n if (query.limit) {\n builder.limit(query.limit);\n }\n\n if (query.orderBy) {\n const orderByClauses = this.queryManager.normalizeOrderBy(query.orderBy);\n builder.orderBy(\n ...orderByClauses.map((clause) =>\n clause.direction === \"desc\"\n ? desc(this.col(clause.column as string))\n : asc(this.col(clause.column as string)),\n ),\n );\n }\n\n if (query.groupBy) {\n builder.groupBy(...query.groupBy.map((key) => this.col(key as string)));\n }\n\n if (opts.for) {\n if (typeof opts.for === \"string\") {\n builder.for(opts.for);\n } else if (opts.for) {\n builder.for(opts.for.strength, opts.for.config);\n }\n }\n\n try {\n let rows = await builder.execute();\n\n let schema: TObject = this.entity.schema;\n if (columns) {\n schema = t.pick(schema, columns);\n }\n\n if (joins.length) {\n rows = rows.map((row: any) => {\n // Clone schema for each row to avoid mutation\n const rowSchema = { ...schema, properties: { ...schema.properties } };\n return this.relationManager.mapRowWithJoins(\n row[this.tableName],\n row,\n rowSchema,\n joins,\n );\n });\n }\n\n rows = rows.map((row) => {\n // For joined queries, build a schema that includes all nested joins\n if (joins.length) {\n const joinedSchema = this.relationManager.buildSchemaWithJoins(\n schema,\n joins,\n );\n // Clean the row with the full joined schema (including nested relations)\n return this.cleanWithJoins(row, joinedSchema, joins);\n }\n return this.clean(row, schema);\n });\n\n await this.alepha.events.emit(\"repository:read:after\", {\n tableName: this.tableName,\n query,\n entities: rows,\n });\n\n const result = rows as PgStatic<T, R>[];\n\n // Store in cache\n if (opts.cache) {\n const cacheKey =\n opts.cache.key ?? this.buildCacheKey(\"findMany\", query);\n await this.dbCache.set(\n this.tableName,\n cacheKey,\n result,\n opts.cache.ttl,\n );\n }\n\n return result;\n } catch (error) {\n throw this.handleError(error, \"Query select has failed\");\n }\n }\n\n /**\n * Find a single entity. Returns `undefined` if not found.\n */\n public async findOne<R extends PgRelationMap<T>>(\n query: Pick<PgQueryRelations<T, R>, \"with\" | \"where\">,\n opts: StatementOptions = {},\n ): Promise<PgStatic<T, R> | undefined> {\n const [entity] = await this.findMany({ limit: 1, ...query }, opts);\n return entity as PgStatic<T, R> | undefined;\n }\n\n /**\n * Find a single entity. Throws `DbEntityNotFoundError` if not found.\n */\n public async getOne<R extends PgRelationMap<T>>(\n query: Pick<PgQueryRelations<T, R>, \"with\" | \"where\">,\n opts: StatementOptions = {},\n ): Promise<PgStatic<T, R>> {\n const entity = await this.findOne(query, opts);\n\n if (!entity) {\n throw new DbEntityNotFoundError(this.tableName);\n }\n\n return entity;\n }\n\n /**\n * Find entities with pagination.\n *\n * It uses the same parameters as `find()`, but adds pagination metadata to the response.\n *\n * > Pagination CAN also do a count query to get the total number of elements.\n */\n public async paginate<R extends PgRelationMap<T>>(\n pagination: PageQuery = {},\n query: Omit<PgQueryRelations<T, R>, \"where\"> & {\n where?: PgQueryWhere<T>;\n } = {},\n opts: StatementOptions & { count?: boolean } = {},\n ): Promise<Page<PgStatic<T, R>>> {\n // Overflow-safe: pageQuerySchema constrains size to [1, 100] and page to >= 0.\n // With max size=100, page would need to exceed 2^45 to overflow Number.MAX_SAFE_INTEGER.\n const limit = query.limit ?? pagination.size ?? 10;\n const page = pagination.page ?? 0;\n const offset = query.offset ?? page * limit;\n\n let orderBy = query.orderBy;\n if (!query.orderBy && pagination.sort) {\n orderBy = this.queryManager.parsePaginationSort(pagination.sort) as any;\n }\n\n const now = this.dateTimeProvider.nowMillis();\n const timers = {\n query: now,\n count: now,\n };\n\n const tasks: Promise<any>[] = [];\n\n tasks.push(\n this.findMany(\n {\n offset,\n limit: limit + 1,\n orderBy,\n ...query,\n },\n opts,\n ).then((it) => {\n timers.query = this.dateTimeProvider.nowMillis() - timers.query;\n return it;\n }),\n );\n\n if (opts.count) {\n const countWhere = this.withOrganization(\n this.withDeletedAt((query.where ?? {}) as PgQueryWhere<T>, opts),\n );\n\n tasks.push(\n this.db.$count(this.table, this.toSQL(countWhere)).then((it) => {\n timers.count = this.dateTimeProvider.nowMillis() - timers.count;\n return it;\n }),\n );\n }\n\n const [entities, countResult] = await Promise.all(tasks);\n\n // Normalize orderBy to get sort metadata\n let sortMetadata:\n | Array<{ column: string; direction: \"asc\" | \"desc\" }>\n | undefined;\n if (orderBy) {\n sortMetadata = this.queryManager.normalizeOrderBy(orderBy);\n }\n\n const response = this.queryManager.createPagination<T>(\n entities,\n limit,\n offset,\n sortMetadata,\n );\n\n response.page.totalElements = countResult;\n if (countResult != null) {\n response.page.totalPages = Math.ceil(countResult / limit);\n }\n\n return response as Page<PgStatic<T, R>>;\n }\n\n /**\n * Find an entity by ID. Returns `undefined` if not found.\n */\n public async findById(\n id: string | number,\n opts: StatementOptions = {},\n ): Promise<Static<T> | undefined> {\n return await this.findOne(\n {\n where: this.getWhereId(id),\n },\n opts,\n );\n }\n\n /**\n * Find an entity by ID. Throws `DbEntityNotFoundError` if not found.\n */\n public async getById(\n id: string | number,\n opts: StatementOptions = {},\n ): Promise<Static<T>> {\n const entity = await this.findById(id, opts);\n\n if (!entity) {\n throw new DbEntityNotFoundError(this.tableName);\n }\n\n return entity;\n }\n\n /**\n * Helper to create a type-safe query object.\n */\n public createQuery(): PgQuery<T> {\n return {};\n }\n\n /**\n * Helper to create a type-safe where clause.\n */\n public createQueryWhere(): PgQueryWhere<T> {\n return {};\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Create an entity.\n *\n * @param data The entity to create.\n * @param opts The options for creating the entity.\n * @returns The ID of the created entity.\n */\n public async create(\n data: Static<TObjectInsert<T>>,\n opts: StatementOptions = {},\n ): Promise<Static<T>> {\n this.assertWritable();\n this.stampOrganization(data);\n await this.alepha.events.emit(\"repository:create:before\", {\n tableName: this.tableName,\n data,\n });\n\n try {\n const entity = await this.rawInsert(opts)\n .values(this.cast(data ?? {}, true))\n .returning(this.table)\n .then(([it]) => this.clean(it, this.entity.schema));\n\n this.dbCache\n .invalidateTable(this.tableName)\n .catch((err) => this.log.warn(\"Cache invalidation failed\", err));\n\n await this.alepha.events.emit(\"repository:create:after\", {\n tableName: this.tableName,\n data,\n entity,\n });\n\n return entity;\n } catch (error) {\n throw this.handleError(error, \"Insert query has failed\");\n }\n }\n\n /**\n * Create many entities.\n *\n * Inserts are batched in chunks of 1000 to avoid hitting database limits.\n *\n * @param values The entities to create.\n * @param opts The statement options.\n * @returns The created entities.\n */\n public async createMany(\n values: Array<Static<TObjectInsert<T>>>,\n opts: StatementOptions & { batchSize?: number } = {},\n ): Promise<Static<T>[]> {\n this.assertWritable();\n if (values.length === 0) {\n return [];\n }\n\n for (const value of values) {\n this.stampOrganization(value);\n }\n\n await this.alepha.events.emit(\"repository:create:before\", {\n tableName: this.tableName,\n data: values,\n });\n\n const batchSize = opts.batchSize ?? 1000;\n const allEntities: Static<T>[] = [];\n\n try {\n for (let i = 0; i < values.length; i += batchSize) {\n const batch = values.slice(i, i + batchSize);\n const entities = await this.rawInsert(opts)\n .values(batch.map((data) => this.cast(data, true)))\n .returning(this.table)\n .then((rows) => rows.map((it) => this.clean(it, this.entity.schema)));\n allEntities.push(...entities);\n }\n\n this.dbCache\n .invalidateTable(this.tableName)\n .catch((err) => this.log.warn(\"Cache invalidation failed\", err));\n\n await this.alepha.events.emit(\"repository:create:after\", {\n tableName: this.tableName,\n data: values,\n entity: allEntities,\n });\n\n return allEntities;\n } catch (error) {\n throw this.handleError(error, \"Insert query has failed\");\n }\n }\n\n /**\n * Insert or update an entity.\n *\n * If a row with the same conflict target already exists, it updates that row.\n * Otherwise, it inserts a new row.\n *\n * @param data The entity data to insert.\n * @param opts.target The column(s) to detect conflicts on. Defaults to the primary key.\n * @param opts.set The fields to update on conflict. Defaults to the insert data (minus conflict target columns).\n * @returns The created or updated entity.\n *\n * @example\n * ```ts\n * // Simple upsert on primary key\n * await repo.upsert({ id: \"abc\", name: \"Alice\", role: \"admin\" });\n *\n * // Upsert on a unique column\n * await repo.upsert(\n * { email: \"alice@example.com\", name: \"Alice\" },\n * { target: [\"email\"] },\n * );\n *\n * // Upsert with custom update fields\n * await repo.upsert(\n * { id: \"abc\", name: \"Alice\", role: \"admin\" },\n * { set: { role: \"admin\" } },\n * );\n * ```\n */\n public async upsert(\n data: Static<TObjectInsert<T>>,\n opts: StatementOptions & {\n target?: Array<keyof Static<T>>;\n set?: WithSQL<Static<TObjectUpdate<T>>>;\n } = {},\n ): Promise<Static<T>> {\n this.assertWritable();\n this.stampOrganization(data);\n await this.alepha.events.emit(\"repository:create:before\", {\n tableName: this.tableName,\n data,\n });\n\n const targetKeys = opts.target ?? [this.id.key];\n const targetColumns = targetKeys.map((key) => this.col(key as string));\n\n let setData: any;\n if (opts.set) {\n setData = opts.set;\n } else {\n // Default: update all fields from the insert data except the conflict target and primary key columns\n setData = { ...data };\n for (const key of targetKeys) {\n delete setData[key];\n }\n delete setData[this.id.key];\n }\n\n // Always inject updatedAt into the conflict SET clause. This ensures that even\n // with `set: {}`, the ON CONFLICT path touches the row — making it possible to\n // distinguish inserts from no-ops by comparing createdAt vs updatedAt.\n const updatedAtField = getAttrFields(\n this.entity.schema,\n PG_UPDATED_AT,\n )?.[0];\n\n if (updatedAtField) {\n setData[updatedAtField.key] =\n opts.now ?? this.dateTimeProvider.nowISOString();\n }\n\n //setData = this.cast(setData, false) as any;\n\n try {\n const entity = await this.rawInsert(opts)\n .values(this.cast(data ?? {}, true))\n .onConflictDoUpdate({\n target: targetColumns,\n set: setData,\n })\n .returning(this.table)\n .then(([it]) => this.clean(it, this.entity.schema));\n\n this.dbCache\n .invalidateTable(this.tableName)\n .catch((err) => this.log.warn(\"Cache invalidation failed\", err));\n\n await this.alepha.events.emit(\"repository:create:after\", {\n tableName: this.tableName,\n data,\n entity,\n });\n\n return entity;\n } catch (error) {\n throw this.handleError(error, \"Upsert query has failed\");\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Find an entity and update it.\n */\n public async updateOne(\n where: PgQueryWhereOrSQL<T>,\n data: WithSQL<Static<TObjectUpdate<T>>>,\n opts: StatementOptions = {},\n ): Promise<Static<T>> {\n this.assertWritable();\n await this.alepha.events.emit(\"repository:update:before\", {\n tableName: this.tableName,\n where,\n data,\n });\n\n let row = data as any;\n\n const updatedAtField = getAttrFields(\n this.entity.schema,\n PG_UPDATED_AT,\n )?.[0];\n\n if (updatedAtField) {\n row[updatedAtField.key] =\n opts.now ?? this.dateTimeProvider.nowISOString();\n }\n\n where = this.withOrganization(this.withDeletedAt(where, opts));\n row = this.cast(row, false) as any;\n\n // do not update the ID field\n delete row[this.id.key];\n\n const response = await this.rawUpdate(opts)\n .set(row)\n .where(this.toSQL(where))\n .returning(this.table)\n .catch((error) => {\n throw this.handleError(error, \"Update query has failed\");\n });\n\n if (!response[0]) {\n throw new DbEntityNotFoundError(this.tableName);\n }\n\n try {\n const entity = this.clean(response[0], this.entity.schema);\n\n this.dbCache\n .invalidateTable(this.tableName)\n .catch((err) => this.log.warn(\"Cache invalidation failed\", err));\n\n await this.alepha.events.emit(\"repository:update:after\", {\n tableName: this.tableName,\n where,\n data,\n entities: [entity],\n });\n\n return entity;\n } catch (error) {\n throw this.handleError(error, \"Update query has failed\");\n }\n }\n\n /**\n * Save a given entity.\n *\n * @example\n * ```ts\n * const entity = await repository.findById(1);\n * entity.name = \"New Name\"; // update a field\n * delete entity.description; // delete a field\n * await repository.save(entity);\n * ```\n *\n * Difference with `updateById/updateOne`:\n *\n * - requires the entity to be fetched first (whole object is expected)\n * - check pg.version() if present -> optimistic locking\n * - validate entity against schema\n * - undefined values will be set to null, not ignored!\n *\n * @see {@link DbVersionMismatchError}\n */\n public async save(\n entity: Static<T>,\n opts: StatementOptions = {},\n ): Promise<void> {\n this.assertWritable();\n const row = entity as any;\n\n const id = row[this.id.key];\n if (id == null) {\n throw new AlephaError(\n \"Cannot save entity without ID - missing primary key in value\",\n );\n }\n\n // in save mode, we do not ignore undefined values, but set them to null\n for (const key of Object.keys(this.entity.schema.properties)) {\n if (row[key] === undefined) {\n row[key] = null;\n }\n }\n\n let where: any = this.createQueryWhere();\n\n where[this.id.key] = { eq: id };\n\n const versionField = getAttrFields(this.entity.schema, PG_VERSION)?.[0];\n if (versionField && typeof row[versionField.key] === \"number\") {\n where = {\n and: [\n where,\n {\n [versionField.key]: {\n eq: row[versionField.key],\n },\n },\n ],\n } as PgQueryWhere<T>;\n\n row[versionField.key] += 1;\n }\n\n try {\n const newValue = await this.updateOne(where, row, opts);\n for (const key of Object.keys(this.entity.schema.properties)) {\n row[key] = undefined;\n }\n Object.assign(row, newValue);\n } catch (error) {\n if (error instanceof DbEntityNotFoundError && versionField) {\n // Verify entity still exists to differentiate between not-found vs version mismatch\n try {\n // If getById succeeds, entity exists and this was a version mismatch\n await this.getById(id);\n throw new DbVersionMismatchError(this.tableName, id);\n } catch (lookupError) {\n // If it's still not found, propagate the original not found error\n if (lookupError instanceof DbEntityNotFoundError) {\n throw error; // Original error\n }\n // If it's a version mismatch error, propagate it\n if (lookupError instanceof DbVersionMismatchError) {\n throw lookupError;\n }\n // Other errors (network, timeout, etc.) should be re-thrown\n throw lookupError;\n }\n }\n throw error;\n }\n }\n\n /**\n * Find an entity by ID and update it.\n */\n public async updateById(\n id: string | number,\n data: WithSQL<Static<TObjectUpdate<T>>>,\n opts: StatementOptions = {},\n ): Promise<Static<T>> {\n return await this.updateOne(this.getWhereId(id), data, opts);\n }\n\n /**\n * Find many entities and update all of them.\n */\n public async updateMany(\n where: PgQueryWhereOrSQL<T>,\n data: WithSQL<Static<TObjectUpdate<T>>>,\n opts: StatementOptions = {},\n ): Promise<Array<number | string>> {\n this.assertWritable();\n await this.alepha.events.emit(\"repository:update:before\", {\n tableName: this.tableName,\n where,\n data,\n });\n\n const updatedAtField = getAttrFields(\n this.entity.schema,\n PG_UPDATED_AT,\n )?.[0];\n\n if (updatedAtField) {\n (data as any)[updatedAtField.key] =\n opts.now ?? this.dateTimeProvider.nowISOString();\n }\n\n where = this.withOrganization(this.withDeletedAt(where, opts));\n data = this.cast(data, false) as any;\n try {\n const entities = await this.rawUpdate(opts)\n .set(\n data as PgUpdateSetSource<PgTableWithColumns<SchemaToTableConfig<T>>>,\n )\n .where(this.toSQL(where))\n .returning();\n\n this.dbCache\n .invalidateTable(this.tableName)\n .catch((err) => this.log.warn(\"Cache invalidation failed\", err));\n\n await this.alepha.events.emit(\"repository:update:after\", {\n tableName: this.tableName,\n where,\n data,\n entities,\n });\n\n return entities.map((it: any) => it[this.id.key]);\n } catch (error) {\n throw this.handleError(error, \"Update query has failed\");\n }\n }\n\n /**\n * Find many and delete all of them.\n * @returns Array of deleted entity IDs\n */\n public async deleteMany(\n where: PgQueryWhereOrSQL<T> = {},\n opts: StatementOptions = {},\n ): Promise<Array<number | string>> {\n this.assertWritable();\n const deletedAt = this.deletedAt();\n if (deletedAt && !opts.force) {\n return await this.updateMany(\n where,\n {\n [deletedAt.key]: opts.now ?? this.dateTimeProvider.nowISOString(),\n } as any,\n opts,\n );\n }\n\n where = this.withOrganization(where);\n\n await this.alepha.events.emit(\"repository:delete:before\", {\n tableName: this.tableName,\n where,\n });\n\n try {\n const result = await this.rawDelete(opts)\n .where(this.toSQL(where))\n .returning({ id: (this.table as any)[this.id.key] });\n const ids = result.map((row) => row.id);\n\n this.dbCache\n .invalidateTable(this.tableName)\n .catch((err) => this.log.warn(\"Cache invalidation failed\", err));\n\n await this.alepha.events.emit(\"repository:delete:after\", {\n tableName: this.tableName,\n where,\n ids,\n });\n\n return ids;\n } catch (error) {\n throw this.handleError(error, \"Delete query has failed\");\n }\n }\n\n /**\n * Delete all entities.\n * @returns Array of deleted entity IDs\n */\n public clear(opts: StatementOptions = {}): Promise<Array<number | string>> {\n return this.deleteMany({}, opts);\n }\n\n /**\n * Delete the given entity.\n *\n * You must fetch the entity first in order to delete it.\n * @returns Array containing the deleted entity ID\n */\n public async destroy(\n entity: Static<T>,\n opts: StatementOptions = {},\n ): Promise<Array<number | string>> {\n const id = (entity as any)[this.id.key];\n if (id == null) {\n throw new AlephaError(\"Cannot destroy entity without ID\");\n }\n\n const deletedAt = this.deletedAt();\n if (deletedAt && !opts.force) {\n opts.now ??= this.dateTimeProvider.nowISOString();\n (entity as any)[deletedAt.key] = opts.now;\n }\n\n return await this.deleteById(id, opts);\n }\n\n /**\n * Find an entity and delete it.\n * @returns Array of deleted entity IDs (should contain at most one ID)\n */\n public async deleteOne(\n where: PgQueryWhereOrSQL<T> = {},\n opts: StatementOptions = {},\n ): Promise<Array<number | string>> {\n const entity = await this.findOne({ where }, opts);\n if (!entity) {\n return [];\n }\n return await this.deleteMany(\n this.getWhereId((entity as any)[this.id.key]),\n opts,\n );\n }\n\n /**\n * Find an entity by ID and delete it.\n * @returns Array containing the deleted entity ID\n * @throws DbEntityNotFoundError if the entity is not found\n */\n public async deleteById(\n id: string | number,\n opts: StatementOptions = {},\n ): Promise<Array<number | string>> {\n const result = await this.deleteMany(this.getWhereId(id), opts);\n if (result.length === 0) {\n throw new DbEntityNotFoundError(\n `Entity with ID ${id} not found in ${this.tableName}`,\n );\n }\n return result;\n }\n\n /**\n * Count entities.\n */\n public async count(\n where: PgQueryWhereOrSQL<T> = {},\n opts: StatementOptions = {},\n ): Promise<number> {\n where = this.withOrganization(this.withDeletedAt(where, opts));\n const db = opts.tx === null ? this.provider.db : (opts.tx ?? this.db);\n return db.$count(this.table, this.toSQL(where));\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Execute an aggregate query with type-safe select, groupBy, and having.\n *\n * @example\n * ```ts\n * const result = await repo.aggregate({\n * select: { category: true, amount: { sum: true, avg: true } },\n * groupBy: [\"category\"],\n * having: { amount: { sum: { gt: 100 } } },\n * orderBy: { column: \"amount.sum\", direction: \"desc\" },\n * });\n * // result: Array<{ category: string; amount: { sum: number; avg: number } }>\n * ```\n */\n public async aggregate<S extends AggregateSelect<T>>(\n query: AggregateQuery<T, S>,\n opts: StatementOptions = {},\n ): Promise<AggregateResult<T, S>[]> {\n const AGG_SEPARATOR = \"___\";\n\n // Build flat select fields\n const flatFields: Record<string, any> = {};\n const aggFn = (op: AggregateOp, column: any) => {\n switch (op) {\n case \"count\":\n return count(column);\n case \"sum\":\n return sum(column);\n case \"avg\":\n return avg(column);\n case \"min\":\n return min(column);\n case \"max\":\n return max(column);\n }\n };\n\n for (const [key, select] of Object.entries(query.select)) {\n if (select === true) {\n flatFields[key] = this.col(key);\n } else if (typeof select === \"object\" && select !== null) {\n for (const op of Object.keys(select) as AggregateOp[]) {\n if ((select as Record<string, boolean>)[op]) {\n flatFields[`${key}${AGG_SEPARATOR}${op}`] = aggFn(\n op,\n this.col(key),\n );\n }\n }\n }\n }\n\n const db = opts.tx === null ? this.provider.db : (opts.tx ?? this.db);\n let builder = db.select(flatFields).from(this.table as PgTable);\n\n // WHERE\n if (query.where) {\n const where = this.withOrganization(\n this.withDeletedAt(query.where as any, opts),\n );\n builder = builder.where(this.toSQL(where)) as any;\n }\n\n // GROUP BY\n if (query.groupBy) {\n builder = builder.groupBy(\n ...query.groupBy.map((key) => this.col(key as string)),\n ) as any;\n }\n\n // HAVING\n if (query.having) {\n const havingConditions: SQL[] = [];\n for (const [key, ops] of Object.entries(query.having)) {\n if (!ops || typeof ops !== \"object\") continue;\n for (const [op, comparisons] of Object.entries(ops)) {\n if (!comparisons || typeof comparisons !== \"object\") continue;\n const aggExpr = aggFn(op as AggregateOp, this.col(key));\n for (const [cmp, val] of Object.entries(\n comparisons as Record<string, number>,\n )) {\n switch (cmp) {\n case \"gt\":\n havingConditions.push(gt(aggExpr, val));\n break;\n case \"gte\":\n havingConditions.push(gte(aggExpr, val));\n break;\n case \"lt\":\n havingConditions.push(lt(aggExpr, val));\n break;\n case \"lte\":\n havingConditions.push(lte(aggExpr, val));\n break;\n case \"eq\":\n havingConditions.push(drizzleEq(aggExpr, val));\n break;\n case \"ne\":\n havingConditions.push(ne(aggExpr, val));\n break;\n }\n }\n }\n }\n if (havingConditions.length > 0) {\n builder = builder.having(drizzleAnd(...havingConditions)!) as any;\n }\n }\n\n // ORDER BY\n if (query.orderBy) {\n const clauses = this.queryManager.normalizeOrderBy(query.orderBy);\n builder = builder.orderBy(\n ...clauses.map((clause) => {\n // Support dot notation: \"amount.sum\" → \"amount___sum\"\n const colName = clause.column.includes(\".\")\n ? clause.column.replace(\".\", AGG_SEPARATOR)\n : clause.column;\n const col = flatFields[colName];\n if (!col) {\n throw new AlephaError(\n `Invalid orderBy column '${clause.column}' in aggregate query`,\n );\n }\n return clause.direction === \"desc\" ? desc(col) : asc(col);\n }),\n ) as any;\n }\n\n // LIMIT / OFFSET\n if (query.limit) {\n builder = builder.limit(query.limit) as any;\n }\n if (query.offset) {\n builder = builder.offset(query.offset) as any;\n }\n\n try {\n const rows = await builder.execute();\n\n // Re-nest flat results: { amount___sum: 500 } → { amount: { sum: 500 } }\n return rows.map((row: any) => {\n const result: Record<string, any> = {};\n for (const [flatKey, value] of Object.entries(row)) {\n if (flatKey.includes(AGG_SEPARATOR)) {\n const [col, op] = flatKey.split(AGG_SEPARATOR);\n if (!result[col]) result[col] = {};\n result[col][op] = value != null ? Number(value) : 0;\n } else {\n result[flatKey] = value;\n }\n }\n return result as AggregateResult<T, S>;\n });\n } catch (error) {\n throw this.handleError(error, \"Aggregate query has failed\");\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n // Error message patterns for different database errors\n protected errorPatterns = {\n // Unique constraint violations\n conflict: [\n \"duplicate key value violates unique constraint\", // PostgreSQL\n \"UNIQUE constraint failed\", // SQLite\n ],\n // Foreign key violations\n foreignKey: [\n \"violates foreign key constraint\", // PostgreSQL\n \"FOREIGN KEY constraint failed\", // SQLite\n ],\n // NOT NULL violations\n notNull: [\n \"violates not-null constraint\", // PostgreSQL\n \"NOT NULL constraint failed\", // SQLite\n ],\n // Deadlock\n deadlock: [\n \"deadlock detected\", // PostgreSQL\n // SQLite doesn't have true deadlocks\n ],\n // Table not found\n tableNotFound: [\n \"does not exist\", // PostgreSQL: relation \"x\" does not exist\n \"no such table\", // SQLite\n ],\n // Column not found\n columnNotFound: [\n 'column \"', // PostgreSQL: column \"x\" does not exist\n \"no such column\", // SQLite\n ],\n };\n\n protected handleError(error: unknown, message: string): DbError {\n if (!(error instanceof Error)) {\n return new DbError(message);\n }\n\n const fullMessage =\n `${error.message} ${(error.cause as Error)?.message ?? \"\"}`.toLowerCase();\n\n const hasPattern = (patterns: string[]) =>\n patterns.some((pattern) => fullMessage.includes(pattern.toLowerCase()));\n\n const getSourceError = () =>\n error.cause instanceof Error ? error.cause : error;\n\n // Check for unique constraint violation (conflict)\n if (hasPattern(this.errorPatterns.conflict)) {\n return new DbConflictError(message, error);\n }\n\n // Check for foreign key violation\n if (hasPattern(this.errorPatterns.foreignKey)) {\n return DbForeignKeyError.fromDatabaseError(\n getSourceError(),\n this.tableName,\n );\n }\n\n // Check for NOT NULL violation\n if (hasPattern(this.errorPatterns.notNull)) {\n return DbNotNullError.fromDatabaseError(getSourceError(), this.tableName);\n }\n\n // Check for deadlock\n if (hasPattern(this.errorPatterns.deadlock)) {\n return DbDeadlockError.fromDatabaseError(getSourceError());\n }\n\n // Check for table not found (must check before column not found)\n if (\n hasPattern(this.errorPatterns.tableNotFound) &&\n (fullMessage.includes(\"relation\") || fullMessage.includes(\"table\"))\n ) {\n return DbTableNotFoundError.fromDatabaseError(getSourceError());\n }\n\n // Check for column not found\n if (hasPattern(this.errorPatterns.columnNotFound)) {\n return DbColumnNotFoundError.fromDatabaseError(getSourceError());\n }\n\n return new DbError(message, error);\n }\n\n protected withDeletedAt(\n where: PgQueryWhereOrSQL<T>,\n opts: {\n force?: boolean;\n } = {},\n ): PgQueryWhereOrSQL<T> {\n if (opts.force) {\n return where;\n }\n\n const deletedAt = this.deletedAt();\n if (!deletedAt) {\n return where;\n }\n\n return {\n and: [\n where,\n {\n [deletedAt.key]: {\n isNull: true,\n },\n } as any,\n ],\n } as PgQueryWhereOrSQL<T>;\n }\n\n protected deletedAt(): PgAttrField | undefined {\n const deletedAtFields = getAttrFields(this.entity.schema, PG_DELETED_AT);\n if (deletedAtFields.length > 0) {\n return deletedAtFields[0];\n }\n return undefined;\n }\n\n protected withOrganization(\n where: PgQueryWhereOrSQL<T>,\n ): PgQueryWhereOrSQL<T> {\n const orgField = this.organizationField();\n if (!orgField) {\n return where;\n }\n\n const user = this.alepha.store.get(currentUserAtom);\n if (!user?.organization) {\n return where;\n }\n\n return {\n and: [\n where,\n {\n or: [\n { [orgField.key]: { eq: user.organization } },\n { [orgField.key]: { isNull: true } },\n ],\n } as any,\n ],\n } as PgQueryWhereOrSQL<T>;\n }\n\n protected stampOrganization(data: any): void {\n const orgField = this.organizationField();\n if (!orgField) {\n return;\n }\n\n if (data[orgField.key] != null) {\n return;\n }\n\n const user = this.alepha.store.get(currentUserAtom);\n if (user?.organization) {\n data[orgField.key] = user.organization;\n }\n }\n\n protected organizationField(): PgAttrField | undefined {\n const fields = getAttrFields(this.entity.schema, PG_ORGANIZATION);\n if (fields.length > 0) {\n return fields[0];\n }\n return undefined;\n }\n\n /**\n * Convert something to valid Pg Insert Value.\n */\n protected cast(\n data: any,\n insert: boolean,\n ): PgInsertValue<PgTableWithColumns<SchemaToTableConfig<T>>> {\n const schema = insert\n ? this.entity.insertSchema // insert\n : (t.partial(this.entity.updateSchema) as TObject); // update\n\n return this.alepha.codec.encode(schema, data) as PgInsertValue<\n PgTableWithColumns<SchemaToTableConfig<T>>\n >;\n }\n\n /**\n * Transform a row from the database into a clean entity.\n */\n protected clean<T extends TObject>(\n row: Record<string, unknown>,\n schema: T,\n ): Static<T> {\n for (const key of Object.keys(schema.properties)) {\n const value = schema.properties[key];\n\n // convert PG date-time and date to ISO strings\n if (typeof row[key] === \"string\") {\n if (t.schema.isDateTime(value)) {\n row[key] = this.dateTimeProvider.of(row[key]).toISOString();\n } else if (t.schema.isDate(value)) {\n row[key] = this.dateTimeProvider\n .of(`${row[key]}T00:00:00Z`)\n .toISOString()\n .split(\"T\")[0];\n }\n }\n\n // convert BigInt to string\n if (typeof row[key] === \"bigint\" && t.schema.isBigInt(value)) {\n row[key] = row[key].toString();\n }\n }\n\n return this.alepha.codec.decode(schema, row) as Static<T>;\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n // INTERNAL METHODS\n\n /**\n * Clean a row with joins recursively\n */\n protected cleanWithJoins<T extends TObject>(\n row: Record<string, unknown>,\n schema: T,\n joins: PgJoin[],\n parentPath?: string,\n ): Static<T> {\n // Get joins at this level\n const joinsAtThisLevel = joins.filter((j) => j.parent === parentPath);\n\n // Create a copy of the row for cleaning, removing joined data temporarily\n const cleanRow: Record<string, unknown> = { ...row };\n const joinedData: Record<string, unknown> = {};\n\n for (const join of joinsAtThisLevel) {\n joinedData[join.key] = cleanRow[join.key];\n delete cleanRow[join.key];\n }\n\n // Clean the base entity without joined properties\n const entity = this.clean(cleanRow, schema);\n\n // Then recursively clean joined entities\n for (const join of joinsAtThisLevel) {\n const joinedValue = joinedData[join.key];\n // Only process if the joined value exists\n if (joinedValue != null) {\n // Build path for this join\n const joinPath = parentPath ? `${parentPath}.${join.key}` : join.key;\n // Find child joins\n const childJoins = joins.filter((j) => j.parent === joinPath);\n // Recursively clean if there are child joins\n if (childJoins.length > 0) {\n (entity as any)[join.key] = this.cleanWithJoins(\n joinedValue as Record<string, unknown>,\n join.schema,\n joins,\n joinPath,\n );\n } else {\n // No child joins, just clean this join\n (entity as any)[join.key] = this.clean(\n joinedValue as Record<string, unknown>,\n join.schema,\n );\n }\n } else {\n // Set to undefined if no data\n (entity as any)[join.key] = undefined;\n }\n }\n\n return entity as Static<T>;\n }\n\n /**\n * Throw if this repository is read-only (backed by a view).\n */\n protected assertWritable(): void {\n if (this.isReadOnly) {\n throw new AlephaError(\n `Cannot write to view '${this.tableName}'. Views are read-only.`,\n );\n }\n }\n\n /**\n * Refresh a materialized view. PostgreSQL only.\n */\n public async refresh(): Promise<void> {\n if (!(this.entity as any).materialized) {\n throw new AlephaError(\n `Cannot refresh '${this.tableName}'. Only materialized views support refresh.`,\n );\n }\n await this.provider.execute(`REFRESH MATERIALIZED VIEW ${this.tableName}`);\n }\n\n /**\n * Build a cache key from method name and query parameters.\n */\n protected buildCacheKey(method: string, query: any): string {\n return `${method}:${JSON.stringify(query)}`;\n }\n\n /**\n * Convert a where clause to SQL.\n */\n protected toSQL(\n where: PgQueryWhereOrSQL<T>,\n joins?: PgJoin[],\n ): SQL | undefined {\n return this.queryManager.toSQL(where as PgQueryWhereOrSQL<T>, {\n schema: this.entity.schema,\n col: (name) => {\n return this.col(name);\n },\n joins,\n dialect: this.provider.dialect,\n });\n }\n\n /**\n * Get the where clause for an ID.\n *\n * @param id The ID to get the where clause for.\n * @returns The where clause for the ID.\n */\n protected getWhereId(id: string | number): PgQueryWhere<T> {\n return {\n [this.id.key]: {\n eq: t.schema.isString(this.id.type) ? String(id) : Number(id),\n },\n } as PgQueryWhere<T>;\n }\n\n /**\n * Find a primary key in the schema.\n */\n protected getPrimaryKey(schema: TObject) {\n const primaryKeys = getAttrFields(schema, PG_PRIMARY_KEY);\n if (primaryKeys.length === 0) {\n throw new AlephaError(\"Primary key not found in schema\");\n }\n\n if (primaryKeys.length > 1) {\n throw new AlephaError(\n `Multiple primary keys (${primaryKeys.length}) are not supported`,\n );\n }\n\n return {\n key: primaryKeys[0].key,\n col: this.col(primaryKeys[0].key),\n type: primaryKeys[0].type,\n };\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * The options for a statement.\n */\nexport interface StatementOptions {\n /**\n * Transaction to use.\n *\n * - `undefined` — auto-detect from `alepha.store` (implicit transactional context)\n * - `PgTransaction` — use this specific transaction (explicit)\n * - `null` — force no transaction, bypass implicit context\n */\n tx?: PgTransaction<any, Record<string, any>> | null;\n\n /**\n * Lock strength.\n */\n for?: LockStrength | { config: LockConfig; strength: LockStrength };\n\n /**\n * If true, ignore soft delete.\n */\n force?: boolean;\n\n /**\n * Force the current time.\n */\n now?: DateTime | string;\n\n /**\n * Cache configuration for query results.\n *\n * When set, results are stored in an in-memory cache keyed by query parameters.\n * Any write to this table automatically invalidates all cached queries.\n *\n * @example\n * ```ts\n * await repo.findMany(query, { cache: { ttl: 60_000 } });\n * ```\n */\n cache?: {\n /**\n * Time-to-live in milliseconds.\n */\n ttl?: number;\n /**\n * Custom cache key. If not provided, a key is derived from the query.\n */\n key?: string;\n };\n}\n\ntype WithSQL<T> = {\n [P in keyof T]?: T[P] | SQL;\n};\n","import { $inject, Alepha, type Service, type TObject } from \"alepha\";\nimport type { EntityPrimitive } from \"../primitives/$entity.ts\";\nimport { Repository } from \"../services/Repository.ts\";\nimport type { DatabaseProvider } from \"./drivers/DatabaseProvider.ts\";\n\nexport class RepositoryProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly registry = new Map<\n EntityPrimitive<any>,\n Service<Repository<any>>\n >();\n\n public getRepositories(provider?: DatabaseProvider) {\n const repositories = this.alepha.services(Repository);\n\n if (provider) {\n return repositories.filter((it) => it.provider === provider);\n }\n\n return repositories;\n }\n\n public getRepository<T extends TObject>(\n entity: EntityPrimitive<T>,\n ): Repository<T> {\n const RepositoryClass = this.createClassRepository(entity);\n return this.alepha.inject(RepositoryClass);\n }\n\n public createClassRepository<T extends TObject>(\n entity: EntityPrimitive<T>,\n ): Service<Repository<T>> {\n let name = entity.name.charAt(0).toUpperCase() + entity.name.slice(1);\n if (name.endsWith(\"s\")) {\n name = name.slice(0, -1);\n }\n name = `${name}Repository`;\n\n if (this.registry.has(entity)) {\n return this.registry.get(entity) as Service<Repository<T>>;\n }\n\n class GenericRepository extends Repository<T> {\n constructor() {\n super(entity);\n }\n }\n\n // for class name to entity.name + \"Repository\"\n Object.defineProperty(GenericRepository, \"name\", { value: name });\n\n this.registry.set(entity, GenericRepository as Service<Repository<T>>);\n\n return GenericRepository;\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\nexport class DbMigrationError extends DbError {\n readonly name = \"DbMigrationError\";\n\n constructor(cause?: unknown) {\n super(\"Failed to migrate database\", cause);\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\n/**\n * Error thrown when a database connection fails.\n *\n * This can happen due to:\n * - Connection refused (server not running)\n * - Connection timeout\n * - Authentication failure\n * - Network issues\n * - Database file not found (SQLite)\n */\nexport class DbConnectionError extends DbError {\n readonly name = \"DbConnectionError\";\n readonly status = 503;\n\n /**\n * The type of connection error.\n */\n readonly errorType?:\n | \"refused\"\n | \"timeout\"\n | \"auth\"\n | \"not_found\"\n | \"locked\"\n | \"unknown\";\n\n /**\n * Whether this error is retryable.\n * Connection errors are often transient and can be retried.\n */\n readonly retryable: boolean;\n\n constructor(\n message: string,\n cause?: unknown,\n options?: {\n errorType?: DbConnectionError[\"errorType\"];\n retryable?: boolean;\n },\n ) {\n super(message, cause);\n this.errorType = options?.errorType;\n this.retryable = options?.retryable ?? true;\n }\n\n /**\n * Parse a database connection error message and create a DbConnectionError.\n * Supports both PostgreSQL and SQLite error formats.\n */\n static fromDatabaseError(error: Error): DbConnectionError {\n const message = error.message.toLowerCase();\n\n // Connection refused\n if (\n message.includes(\"connection refused\") ||\n message.includes(\"econnrefused\") ||\n message.includes(\"could not connect\")\n ) {\n return new DbConnectionError(\n \"Database connection refused. Is the server running?\",\n error,\n { errorType: \"refused\", retryable: true },\n );\n }\n\n // Timeout\n if (\n message.includes(\"timeout\") ||\n message.includes(\"timed out\") ||\n message.includes(\"etimedout\")\n ) {\n return new DbConnectionError(\"Database connection timed out\", error, {\n errorType: \"timeout\",\n retryable: true,\n });\n }\n\n // Authentication\n if (\n message.includes(\"password authentication failed\") ||\n message.includes(\"authentication failed\") ||\n message.includes(\"access denied\")\n ) {\n return new DbConnectionError(\n \"Database authentication failed. Check credentials.\",\n error,\n { errorType: \"auth\", retryable: false },\n );\n }\n\n // SQLite file not found\n if (\n message.includes(\"unable to open database\") ||\n message.includes(\"no such file\") ||\n message.includes(\"enoent\")\n ) {\n return new DbConnectionError(\"Database file not found\", error, {\n errorType: \"not_found\",\n retryable: false,\n });\n }\n\n // SQLite database locked\n if (message.includes(\"database is locked\")) {\n return new DbConnectionError(\n \"Database is locked by another process\",\n error,\n { errorType: \"locked\", retryable: true },\n );\n }\n\n return new DbConnectionError(\"Failed to connect to database\", error, {\n errorType: \"unknown\",\n retryable: true,\n });\n }\n}\n","import { AlephaError, type TObject } from \"alepha\";\nimport type { PgQueryWhere } from \"../interfaces/PgQueryWhere.ts\";\n\n/**\n * Parse a string query into a PgQueryWhere object.\n *\n * Supported syntax:\n * - Simple equality: \"name=John\"\n * - Wildcard patterns: \"name=John*\" (startsWith), \"name=*John\" (endsWith), \"name=*John*\" (contains)\n * - Operators: \"age>18\", \"age>=18\", \"age<65\", \"age<=65\", \"status!=active\"\n * - NULL checks: \"deletedAt=null\", \"email!=null\"\n * - IN arrays: \"status=[pending,active]\"\n * - AND conditions: \"name=John&age>18\"\n * - OR conditions: \"name=John|email=john@example.com\"\n * - Nested AND/OR: \"(name=John|name=Jane)&age>18\"\n * - JSONB nested: \"profile.city=Paris\"\n *\n * @example\n * ```ts\n * // Simple equality\n * parseQueryString(\"name=John\")\n * // => { name: { eq: \"John\" } }\n *\n * // Wildcard patterns\n * parseQueryString(\"name=John*\") // startsWith\n * // => { name: { startsWith: \"John\" } }\n * parseQueryString(\"name=*Smith\") // endsWith\n * // => { name: { endsWith: \"Smith\" } }\n * parseQueryString(\"name=*oh*\") // contains\n * // => { name: { contains: \"oh\" } }\n *\n * // Multiple conditions\n * parseQueryString(\"name=John&age>18\")\n * // => { and: [{ name: { eq: \"John\" } }, { age: { gt: 18 } }] }\n *\n * // OR conditions\n * parseQueryString(\"status=active|status=pending\")\n * // => { or: [{ status: { eq: \"active\" } }, { status: { eq: \"pending\" } }] }\n *\n * // Complex nested\n * parseQueryString(\"(name=John|name=Jane)&age>18&status!=archived\")\n * // => { and: [\n * // { or: [{ name: { eq: \"John\" } }, { name: { eq: \"Jane\" } }] },\n * // { age: { gt: 18 } },\n * // { status: { ne: \"archived\" } }\n * // ] }\n *\n * // JSONB nested query\n * parseQueryString(\"profile.city=Paris&profile.age>25\")\n * // => { profile: { city: { eq: \"Paris\" }, age: { gt: 25 } } }\n * ```\n */\nexport function parseQueryString<T extends TObject>(\n query: string,\n): PgQueryWhere<T> {\n if (!query || query.trim() === \"\") {\n return {};\n }\n\n const parser = new QueryStringParser(query);\n return parser.parse() as PgQueryWhere<T>;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nclass QueryStringParser {\n protected pos = 0;\n protected readonly query: string;\n\n constructor(query: string) {\n this.query = query.trim();\n }\n\n parse(): PgQueryWhere<any> {\n return this.parseExpression();\n }\n\n protected parseExpression(): PgQueryWhere<any> {\n return this.parseOr();\n }\n\n protected parseOr(): any {\n const left = this.parseAnd();\n\n // Check for OR operator (|)\n if (this.peek() === \"|\") {\n const conditions = [left];\n\n while (this.peek() === \"|\") {\n this.consume(\"|\");\n conditions.push(this.parseAnd());\n }\n\n return { or: conditions };\n }\n\n return left;\n }\n\n protected parseAnd(): any {\n const left = this.parsePrimary();\n\n // Check for AND operator (&)\n if (this.peek() === \"&\") {\n const conditions = [left];\n\n while (this.peek() === \"&\") {\n this.consume(\"&\");\n conditions.push(this.parsePrimary());\n }\n\n return { and: conditions };\n }\n\n return left;\n }\n\n protected parsePrimary(): any {\n this.skipWhitespace();\n\n // Handle parentheses\n if (this.peek() === \"(\") {\n this.consume(\"(\");\n const expr = this.parseExpression();\n this.consume(\")\");\n return expr;\n }\n\n // Parse field condition\n return this.parseCondition();\n }\n\n protected parseCondition(): any {\n const field = this.parseFieldPath();\n this.skipWhitespace();\n\n // Get operator\n const operator = this.parseOperator();\n this.skipWhitespace();\n\n // Get value\n const value = this.parseValue();\n\n if (value === \"\") {\n throw new AlephaError(`Expected value for field '${field.join(\".\")}'`);\n }\n\n // Build the condition object\n return this.buildCondition(field, operator, value);\n }\n\n protected parseFieldPath(): string[] {\n const path: string[] = [];\n let current = \"\";\n\n while (this.pos < this.query.length) {\n const ch = this.query[this.pos];\n\n if (ch === \".\" && current) {\n path.push(current);\n current = \"\";\n this.pos++;\n continue;\n }\n\n if (ch === \"=\" || ch === \"!\" || ch === \">\" || ch === \"<\" || ch === \" \") {\n break;\n }\n\n current += ch;\n this.pos++;\n }\n\n if (current) {\n path.push(current);\n }\n\n return path;\n }\n\n protected parseOperator(): string {\n this.skipWhitespace();\n\n const remaining = this.query.slice(this.pos);\n\n // Two-character operators\n if (remaining.startsWith(\">=\")) {\n this.pos += 2;\n return \">=\";\n }\n if (remaining.startsWith(\"<=\")) {\n this.pos += 2;\n return \"<=\";\n }\n if (remaining.startsWith(\"!=\")) {\n this.pos += 2;\n return \"!=\";\n }\n\n // Single-character operators\n const ch = this.query[this.pos];\n if (ch === \"=\" || ch === \">\" || ch === \"<\") {\n this.pos++;\n return ch;\n }\n\n throw new AlephaError(`Expected operator at position ${this.pos}`);\n }\n\n protected parseValue(): any {\n this.skipWhitespace();\n\n // Handle null\n if (this.query.slice(this.pos, this.pos + 4).toLowerCase() === \"null\") {\n this.pos += 4;\n return null;\n }\n\n // Handle arrays [value1,value2,...]\n if (this.query[this.pos] === \"[\") {\n return this.parseArray();\n }\n\n // Handle quoted strings\n if (this.query[this.pos] === '\"' || this.query[this.pos] === \"'\") {\n return this.parseQuotedString();\n }\n\n // Parse unquoted value (until &, |, or ))\n let value = \"\";\n while (this.pos < this.query.length) {\n const ch = this.query[this.pos];\n if (ch === \"&\" || ch === \"|\" || ch === \")\") {\n break;\n }\n value += ch;\n this.pos++;\n }\n\n return this.coerceValue(value.trim());\n }\n\n protected parseArray(): any[] {\n this.consume(\"[\");\n const values: any[] = [];\n\n while (this.pos < this.query.length && this.query[this.pos] !== \"]\") {\n this.skipWhitespace();\n\n // Handle quoted values\n if (this.query[this.pos] === '\"' || this.query[this.pos] === \"'\") {\n values.push(this.parseQuotedString());\n } else {\n // Parse until comma or ]\n let value = \"\";\n while (\n this.pos < this.query.length &&\n this.query[this.pos] !== \",\" &&\n this.query[this.pos] !== \"]\"\n ) {\n value += this.query[this.pos];\n this.pos++;\n }\n values.push(this.coerceValue(value.trim()));\n }\n\n this.skipWhitespace();\n if (this.query[this.pos] === \",\") {\n this.pos++;\n }\n }\n\n this.consume(\"]\");\n return values;\n }\n\n protected parseQuotedString(): string {\n const quote = this.query[this.pos];\n this.pos++; // Skip opening quote\n\n let value = \"\";\n let escaped = false;\n\n while (this.pos < this.query.length) {\n const ch = this.query[this.pos];\n\n if (escaped) {\n value += ch;\n escaped = false;\n this.pos++;\n continue;\n }\n\n if (ch === \"\\\\\") {\n escaped = true;\n this.pos++;\n continue;\n }\n\n if (ch === quote) {\n this.pos++; // Skip closing quote\n break;\n }\n\n value += ch;\n this.pos++;\n }\n\n return value;\n }\n\n protected coerceValue(value: string): any {\n // Try to parse as number\n if (/^-?\\d+$/.test(value)) {\n return parseInt(value, 10);\n }\n\n if (/^-?\\d+\\.\\d+$/.test(value)) {\n return parseFloat(value);\n }\n\n // Try to parse as boolean\n if (value.toLowerCase() === \"true\") {\n return true;\n }\n if (value.toLowerCase() === \"false\") {\n return false;\n }\n\n return value;\n }\n\n protected buildCondition(path: string[], operator: string, value: any): any {\n // Map operator to filter operator\n let filterOp: any;\n\n if (operator === \"=\") {\n if (value === null) {\n filterOp = { isNull: true };\n } else if (Array.isArray(value)) {\n // Arrays should be treated as inArray regardless of content\n filterOp = { inArray: value };\n } else if (typeof value === \"string\" && value.includes(\"*\")) {\n // Handle wildcard patterns\n const startsWithAsterisk = value.startsWith(\"*\");\n const endsWithAsterisk = value.endsWith(\"*\");\n const cleanValue = value.replace(/^\\*|\\*$/g, \"\"); // Remove leading/trailing asterisks\n\n if (startsWithAsterisk && endsWithAsterisk) {\n // *text* -> contains\n filterOp = { contains: cleanValue };\n } else if (startsWithAsterisk) {\n // *text -> endsWith\n filterOp = { endsWith: cleanValue };\n } else if (endsWithAsterisk) {\n // text* -> startsWith\n filterOp = { startsWith: cleanValue };\n } else {\n // Has asterisk in the middle, treat as literal\n filterOp = { eq: value };\n }\n } else {\n filterOp = { eq: value };\n }\n } else if (operator === \"!=\") {\n if (value === null) {\n filterOp = { isNotNull: true };\n } else {\n filterOp = { ne: value };\n }\n } else if (operator === \">\") {\n filterOp = { gt: value };\n } else if (operator === \">=\") {\n filterOp = { gte: value };\n } else if (operator === \"<\") {\n filterOp = { lt: value };\n } else if (operator === \"<=\") {\n filterOp = { lte: value };\n } else {\n throw new AlephaError(`Unsupported operator: ${operator}`);\n }\n\n // Build nested object for path\n if (path.length === 1) {\n return { [path[0]]: filterOp };\n }\n\n // Handle nested paths (JSONB)\n let result: any = filterOp;\n for (let i = path.length - 1; i >= 0; i--) {\n result = { [path[i]]: result };\n }\n\n return result;\n }\n\n protected peek(): string {\n this.skipWhitespace();\n return this.query[this.pos] || \"\";\n }\n\n protected consume(expected: string): void {\n this.skipWhitespace();\n if (this.query[this.pos] !== expected) {\n throw new AlephaError(\n `Expected '${expected}' at position ${this.pos}, got '${this.query[this.pos]}'`,\n );\n }\n this.pos++;\n }\n\n protected skipWhitespace(): void {\n while (this.pos < this.query.length && /\\s/.test(this.query[this.pos])) {\n this.pos++;\n }\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Helper function to build query strings programmatically\n *\n * @example\n * ```ts\n * buildQueryString({\n * and: [\n * { name: \"eq:John\" },\n * { age: \"gt:18\" }\n * ]\n * })\n * // => \"name=John&age>18\"\n * ```\n */\nexport function buildQueryString(where: any): string {\n if (!where || typeof where !== \"object\") {\n return \"\";\n }\n\n // Handle logical operators\n if (\"and\" in where && Array.isArray(where.and)) {\n return where.and.map((w: any) => buildQueryString(w)).join(\"&\");\n }\n\n if (\"or\" in where && Array.isArray(where.or)) {\n const parts = where.or.map((w: any) => buildQueryString(w));\n return parts.length > 1 ? `(${parts.join(\"|\")})` : parts[0];\n }\n\n if (\"not\" in where) {\n // Not operator is harder to represent in string form\n // For now, we'll skip it or you could add a syntax like \"!field=value\"\n return \"\";\n }\n\n // Handle field conditions\n const parts: string[] = [];\n\n for (const [field, condition] of Object.entries(where)) {\n if (typeof condition !== \"object\" || condition === null) {\n parts.push(`${field}=${condition}`);\n continue;\n }\n\n if (\"eq\" in condition) {\n parts.push(`${field}=${condition.eq}`);\n } else if (\"ne\" in condition) {\n parts.push(`${field}!=${condition.ne}`);\n } else if (\"gt\" in condition) {\n parts.push(`${field}>${condition.gt}`);\n } else if (\"gte\" in condition) {\n parts.push(`${field}>=${condition.gte}`);\n } else if (\"lt\" in condition) {\n parts.push(`${field}<${condition.lt}`);\n } else if (\"lte\" in condition) {\n parts.push(`${field}<=${condition.lte}`);\n } else if (\"contains\" in condition) {\n parts.push(`${field}=*${condition.contains}*`);\n } else if (\"startsWith\" in condition) {\n parts.push(`${field}=${condition.startsWith}*`);\n } else if (\"endsWith\" in condition) {\n parts.push(`${field}=*${condition.endsWith}`);\n } else if (\"isNull\" in condition && condition.isNull) {\n parts.push(`${field}=null`);\n } else if (\"isNotNull\" in condition && condition.isNotNull) {\n parts.push(`${field}!=null`);\n } else if (\"inArray\" in condition && Array.isArray(condition.inArray)) {\n const values = condition.inArray.map((v: any) =>\n typeof v === \"string\" ? `\"${v}\"` : v,\n );\n parts.push(`${field}=[${values.join(\",\")}]`);\n } else {\n // Nested object (JSONB)\n const nested = buildQueryString(condition);\n if (nested) {\n parts.push(`${field}.${nested}`);\n }\n }\n }\n\n return parts.join(\"&\");\n}\n","import { KIND, type TObject } from \"alepha\";\nimport type { SQL } from \"drizzle-orm\";\n\n/**\n * Creates a database view primitive from a TypeBox schema and SQL query.\n *\n * Views are read-only: Repository blocks all write operations.\n *\n * @example\n * ```ts\n * import { t } from \"alepha\";\n * import { $view } from \"alepha/orm\";\n * import { sql } from \"drizzle-orm\";\n *\n * const userSummary = $view({\n * name: \"user_summary\",\n * schema: t.object({\n * id: t.uuid(),\n * fullName: t.text(),\n * orderCount: t.integer(),\n * }),\n * query: sql`SELECT u.id, u.first_name || ' ' || u.last_name AS full_name, COUNT(o.id) AS order_count FROM users u LEFT JOIN orders o ON o.user_id = u.id GROUP BY u.id`,\n * });\n *\n * // Materialized view (PostgreSQL only)\n * const monthlyStats = $view({\n * name: \"monthly_stats\",\n * schema: t.object({ ... }),\n * query: sql`...`,\n * materialized: true,\n * });\n * ```\n */\nexport const $view = <TSchema extends TObject>(\n options: ViewPrimitiveOptions<TSchema>,\n): ViewPrimitive<TSchema> => {\n return new ViewPrimitive<TSchema>(options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface ViewPrimitiveOptions<T extends TObject> {\n /**\n * The database view name.\n */\n name: string;\n\n /**\n * TypeBox schema defining the view's columns.\n */\n schema: T;\n\n /**\n * SQL query that defines the view.\n */\n query: SQL;\n\n /**\n * Whether this is a materialized view (PostgreSQL only).\n * Materialized views store results on disk and can be refreshed.\n */\n materialized?: boolean;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class ViewPrimitive<T extends TObject = TObject> {\n public readonly options: ViewPrimitiveOptions<T>;\n public readonly isView = true;\n\n constructor(options: ViewPrimitiveOptions<T>) {\n this.options = options;\n }\n\n get name(): string {\n return this.options.name;\n }\n\n get schema(): T {\n return this.options.schema;\n }\n\n get materialized(): boolean {\n return this.options.materialized ?? false;\n }\n}\n\n$view[KIND] = ViewPrimitive;\n","import {\n AlephaError,\n pageSchema,\n type Static,\n type TBigInt,\n type TInteger,\n type TNumber,\n type TNumberOptions,\n type TObject,\n type TObjectOptions,\n type TPage,\n type TSchema,\n type TString,\n type TStringOptions,\n t,\n} from \"alepha\";\nimport type { UpdateDeleteAction } from \"drizzle-orm/pg-core/foreign-keys\";\nimport {\n PG_CREATED_AT,\n PG_DEFAULT,\n PG_DELETED_AT,\n PG_IDENTITY,\n PG_ORGANIZATION,\n PG_PRIMARY_KEY,\n PG_REF,\n PG_UPDATED_AT,\n PG_VERSION,\n type PgDefault,\n type PgIdentityOptions,\n type PgPrimaryKey,\n type PgRef,\n} from \"../constants/PG_SYMBOLS.ts\";\nimport type { PgAttr } from \"../helpers/pgAttr.ts\";\nimport { pgAttr } from \"../helpers/pgAttr.ts\";\n\nexport class DatabaseTypeProvider {\n public readonly attr = pgAttr;\n\n /**\n * Creates a primary key with an identity column.\n */\n public readonly identityPrimaryKey = (\n identity?: PgIdentityOptions,\n options?: TNumberOptions,\n ) =>\n pgAttr(\n pgAttr(pgAttr(t.integer(options), PG_PRIMARY_KEY), PG_IDENTITY, identity),\n PG_DEFAULT,\n );\n\n /**\n * Creates a primary key with a big identity column. (default)\n */\n public readonly bigIdentityPrimaryKey = (\n identity?: PgIdentityOptions,\n options?: TNumberOptions,\n ) =>\n pgAttr(\n pgAttr(pgAttr(t.int64(options), PG_PRIMARY_KEY), PG_IDENTITY, identity),\n PG_DEFAULT,\n );\n\n /**\n * Creates a primary key with a UUID column.\n */\n public readonly uuidPrimaryKey = () =>\n pgAttr(pgAttr(t.uuid(), PG_PRIMARY_KEY), PG_DEFAULT);\n\n /**\n * Creates a primary key for a given type. Supports:\n * - `t.integer()` -> PG INT (default)\n * - `t.bigint()` -> PG BIGINT\n * - `t.uuid()` -> PG UUID\n */\n public primaryKey(): PgAttr<PgAttr<TInteger, PgPrimaryKey>, PgDefault>;\n public primaryKey(\n type: TString,\n options?: TStringOptions,\n ): PgAttr<PgAttr<TString, PgPrimaryKey>, PgDefault>;\n public primaryKey(\n type: TInteger,\n options?: TNumberOptions,\n identity?: PgIdentityOptions,\n ): PgAttr<PgAttr<TInteger, PgPrimaryKey>, PgDefault>;\n public primaryKey(\n type: TNumber,\n options?: TNumberOptions,\n identity?: PgIdentityOptions,\n ): PgAttr<PgAttr<TNumber, PgPrimaryKey>, PgDefault>;\n public primaryKey(\n type: TBigInt,\n options?: TNumberOptions,\n identity?: PgIdentityOptions,\n ): PgAttr<PgAttr<TBigInt, PgPrimaryKey>, PgDefault>;\n public primaryKey(\n type?: TSchema,\n options?: TNumberOptions | TStringOptions,\n identity?: PgIdentityOptions,\n ): PgAttr<PgAttr<TSchema, PgPrimaryKey>, PgDefault> {\n if (!type || t.schema.isInteger(type)) {\n return pgAttr(\n pgAttr(\n pgAttr(t.integer(options), PG_PRIMARY_KEY),\n PG_IDENTITY,\n identity,\n ),\n PG_DEFAULT,\n );\n }\n\n if (t.schema.isString(type) && type.format === \"uuid\") {\n return pgAttr(pgAttr(t.uuid(), PG_PRIMARY_KEY), PG_DEFAULT);\n }\n\n if (t.schema.isNumber(type) && type.format === \"int64\") {\n return pgAttr(\n pgAttr(\n pgAttr(t.number(options), PG_PRIMARY_KEY),\n PG_IDENTITY,\n identity,\n ),\n PG_DEFAULT,\n );\n }\n\n if (t.schema.isBigInt(type)) {\n return pgAttr(\n pgAttr(\n pgAttr(t.bigint(options), PG_PRIMARY_KEY),\n PG_IDENTITY,\n identity,\n ),\n PG_DEFAULT,\n );\n }\n\n throw new AlephaError(`Unsupported type for primary key: ${type}`);\n }\n\n /**\n * Wrap a schema with \"default\" attribute.\n * This is used to set a default value for a column in the database.\n */\n public readonly default = <T extends TSchema>(\n type: T,\n value?: Static<T>,\n ): PgAttr<T, PgDefault> => {\n if (value != null) {\n Object.assign(type, { default: value });\n }\n\n return this.attr(type, PG_DEFAULT);\n };\n\n /**\n * Creates a column 'version'.\n *\n * This is used to track the version of a row in the database.\n *\n * You can use it for optimistic concurrency control (OCC) with {@link RepositoryPrimitive#save}.\n *\n * @see {@link RepositoryPrimitive#save}\n * @see {@link PgVersionMismatchError}\n */\n public readonly version = (options: TNumberOptions = {}) =>\n this.default(pgAttr(t.integer(options), PG_VERSION), 0);\n\n /**\n * Creates a column Created At. So just a datetime column with a default value of the current timestamp.\n */\n public readonly createdAt = (options?: TStringOptions) =>\n pgAttr(pgAttr(t.datetime(options), PG_CREATED_AT), PG_DEFAULT);\n\n /**\n * Creates a column Updated At. Like createdAt, but it is updated on every update of the row.\n */\n public readonly updatedAt = (options?: TStringOptions) =>\n pgAttr(pgAttr(t.datetime(options), PG_UPDATED_AT), PG_DEFAULT);\n\n /**\n * Creates a column Deleted At for soft delete functionality.\n * This is used to mark rows as deleted without actually removing them from the database.\n * The column is nullable - NULL means not deleted, timestamp means deleted.\n */\n public readonly deletedAt = (options?: TStringOptions) =>\n pgAttr(t.optional(t.datetime(options)), PG_DELETED_AT);\n\n /**\n * Creates an organization column for multi-tenant row scoping.\n *\n * When present, queries are automatically filtered by the current user's organization.\n * Rows with `null` organization are considered global and visible to everyone.\n * On create, the column is auto-stamped with the current user's organization.\n */\n public readonly organization = () =>\n pgAttr(t.optional(t.uuid()), PG_ORGANIZATION);\n\n /**\n * Creates a reference to another table or schema. Basically a foreign key.\n */\n public readonly ref = <T extends TSchema>(\n type: T,\n ref: () => any,\n actions?: {\n onUpdate?: UpdateDeleteAction;\n onDelete?: UpdateDeleteAction;\n },\n ): PgAttr<T, PgRef> => {\n // If actions are not provided, set default onDelete based on type\n const finalActions = actions ?? {\n onDelete: t.schema.isOptional(type) ? \"set null\" : \"cascade\",\n };\n\n return this.attr(type, PG_REF, {\n ref,\n actions: finalActions,\n });\n };\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Creates a page schema for a given object schema.\n * It's used by {@link Repository#paginate} method.\n */\n public readonly page = <T extends TObject>(\n resource: T,\n options?: TObjectOptions,\n ): TPage<T> => {\n return pageSchema(resource, options);\n };\n}\n\n/**\n * Wrapper of TypeProvider (`t`) for database types.\n *\n * Use `db` for improve TypeBox schema definitions with database-specific attributes.\n *\n * @example\n * ```ts\n * import { t } from \"alepha\";\n * import { db } from \"alepha/orm\";\n *\n * const userSchema = t.object({\n * id: db.primaryKey(t.uuid()),\n * email: t.email(),\n * createdAt: db.createdAt(),\n * });\n * ```\n */\nexport const db = new DatabaseTypeProvider();\n","import { t } from \"alepha\";\nimport {\n PG_DEFAULT,\n PG_PRIMARY_KEY,\n PG_SERIAL,\n} from \"../constants/PG_SYMBOLS.ts\";\nimport { pgAttr } from \"../helpers/pgAttr.ts\";\n\n/**\n * @deprecated Use `pg.primaryKey()` instead.\n */\nexport const legacyIdSchema = pgAttr(\n pgAttr(pgAttr(t.integer(), PG_PRIMARY_KEY), PG_SERIAL),\n PG_DEFAULT,\n);\n","import { $context, $inject, type TObject } from \"alepha\";\nimport { RepositoryProvider } from \"../providers/RepositoryProvider.ts\";\nimport type { Repository } from \"../services/Repository.ts\";\nimport type { EntityPrimitive } from \"./$entity.ts\";\nimport type { ViewPrimitive } from \"./$view.ts\";\n\n/**\n * Get the repository for the given entity or view.\n */\nexport const $repository = <T extends TObject>(\n entity: EntityPrimitive<T> | ViewPrimitive<T>,\n): Repository<T> => {\n const { alepha } = $context();\n const repositoryProvider = alepha.inject(RepositoryProvider);\n return $inject(\n repositoryProvider.createClassRepository(entity as EntityPrimitive<T>),\n );\n};\n","import { $context, $mode, type Alepha } from \"alepha\";\nimport { DatabaseProvider } from \"../providers/drivers/DatabaseProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface SeedOptions {\n /**\n * Seed handler, executed inside a database transaction.\n *\n * If the handler throws, the transaction is rolled back automatically.\n */\n handler: (ctx: { alepha: Alepha; db: DatabaseProvider }) => any;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Activate seed mode: a convenience wrapper around `$mode` that runs the handler\n * inside a database transaction.\n *\n * When `SEED=true` (or `MODE=SEED`) is set, the owning class becomes `alepha.target`,\n * the graph is pruned, and the handler runs inside `db.transactional()`.\n * After completion (or error), the app stops automatically.\n *\n * Returns `true` if seed mode is active, `false` otherwise.\n *\n * @example\n * ```ts\n * import { $seed } from \"alepha/orm\";\n * import { $repository } from \"alepha/orm\";\n *\n * class AppSeed {\n * users = $repository(userEntity);\n *\n * seed = $seed({\n * handler: async () => {\n * await this.users.create({ name: \"John Doe\" });\n * },\n * });\n * }\n * ```\n *\n * ```bash\n * SEED=true node app.js\n * ```\n */\nexport const $seed = (args: SeedOptions): boolean => {\n const { alepha } = $context();\n const db = alepha.inject(DatabaseProvider);\n\n return $mode({\n env: \"SEED\",\n ready: async () => {\n await db.transactional(async () => {\n await args.handler({ alepha, db });\n });\n },\n });\n};\n","import { createMiddleware, type Middleware } from \"alepha\";\nimport type { PgTransactionConfig } from \"drizzle-orm/pg-core/session\";\nimport { DatabaseProvider } from \"../providers/drivers/DatabaseProvider.ts\";\n\nexport interface TransactionalOptions {\n /**\n * PostgreSQL transaction configuration (isolation level, access mode, etc.).\n */\n config?: PgTransactionConfig;\n}\n\n/**\n * Middleware that wraps handler execution in a database transaction.\n *\n * All Repository operations inside the handler automatically participate in\n * the transaction — no explicit `{ tx }` drilling required.\n *\n * Nesting is safe: if the handler is already inside a `transactional()` block,\n * the outer transaction is reused.\n *\n * ```typescript\n * class OrderService {\n * createOrder = $action({\n * use: [$transactional()],\n * handler: async ({ body }) => {\n * await this.orders.create(body); // auto-uses tx\n * await this.audit.create({ ... }); // auto-uses tx\n * // throw → auto rollback, return → auto commit\n * },\n * });\n * }\n * ```\n */\nexport const $transactional = (options?: TransactionalOptions): Middleware => {\n return createMiddleware({\n name: \"$transactional\",\n options,\n handler: ({ alepha, next }) => {\n const provider = alepha.inject(DatabaseProvider);\n return async (...args: any[]) => {\n return provider.transactional(() => next(...args), options?.config);\n };\n },\n });\n};\n","import type { Static, TSchema } from \"alepha\";\nimport { customType } from \"drizzle-orm/pg-core\";\n\n/**\n * Postgres schema type.\n */\nexport const schema = <TDocument extends TSchema>(\n name: string,\n document: TDocument,\n) =>\n customType<{\n data: Static<TDocument>;\n driverData: string;\n config: { document: TDocument };\n configRequired: true;\n }>({\n dataType: () => \"jsonb\",\n toDriver: (value) => JSON.stringify(value),\n fromDriver: (value: TDocument | string) =>\n value && typeof value === \"string\" ? JSON.parse(value) : value,\n })(name, { document }).$type<Static<TDocument>>();\n","import { $module, type Alepha } from \"alepha\";\nimport { AlephaDateTime } from \"alepha/datetime\";\nimport { $entity } from \"./primitives/$entity.ts\";\nimport { $sequence } from \"./primitives/$sequence.ts\";\nimport { DrizzleKitProvider } from \"./providers/DrizzleKitProvider.ts\";\nimport { BunSqliteProvider } from \"./providers/drivers/BunSqliteProvider.ts\";\nimport { CloudflareD1Provider } from \"./providers/drivers/CloudflareD1Provider.ts\";\nimport { DatabaseProvider } from \"./providers/drivers/DatabaseProvider.ts\";\nimport { RepositoryProvider } from \"./providers/RepositoryProvider.ts\";\nimport { databaseEnvSchema } from \"./schemas/databaseEnvSchema.ts\";\nimport { PgRelationManager } from \"./services/PgRelationManager.ts\";\nimport { QueryManager } from \"./services/QueryManager.ts\";\nimport { Repository } from \"./services/Repository.ts\";\nimport { SqliteModelBuilder } from \"./services/SqliteModelBuilder.ts\";\n\nexport const SqliteProvider = BunSqliteProvider;\n\nexport * from \"./index.shared-server.ts\";\nexport * from \"./providers/drivers/BunSqliteProvider.ts\";\n\nexport const AlephaOrm = $module({\n name: \"alepha.orm\",\n primitives: [$sequence, $entity],\n services: [\n AlephaDateTime,\n DatabaseProvider,\n BunSqliteProvider,\n CloudflareD1Provider,\n SqliteModelBuilder,\n DrizzleKitProvider,\n RepositoryProvider,\n Repository,\n PgRelationManager,\n QueryManager,\n ],\n register: (alepha: Alepha) => {\n const env = alepha.parseEnv(databaseEnvSchema);\n\n alepha.with(DrizzleKitProvider);\n alepha.with(RepositoryProvider);\n\n const url = env.DATABASE_URL;\n\n if (url?.startsWith(\"d1:\")) {\n alepha.with({\n optional: true,\n provide: DatabaseProvider,\n use: CloudflareD1Provider,\n });\n return;\n }\n\n // PostgreSQL URLs are handled by AlephaOrmPostgres — skip here\n if (url?.startsWith(\"postgres:\") || url?.startsWith(\"pglite:\")) {\n return;\n }\n\n alepha.with({\n optional: true,\n provide: DatabaseProvider,\n use: BunSqliteProvider,\n });\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.bun.js","names":["sql","sql","sql","isSQLWrapper","drizzleEq","drizzleAnd","pageSchema"],"sources":["../../../src/orm/core/constants/PG_SYMBOLS.ts","../../../src/orm/core/schemas/insertSchema.ts","../../../src/orm/core/schemas/updateSchema.ts","../../../src/orm/core/primitives/$entity.ts","../../../src/orm/core/errors/DbError.ts","../../../src/orm/core/schemas/databaseEnvSchema.ts","../../../src/orm/core/providers/DrizzleKitProvider.ts","../../../src/orm/core/providers/drivers/DatabaseProvider.ts","../../../src/orm/core/primitives/$sequence.ts","../../../src/orm/core/services/ModelBuilder.ts","../../../src/orm/core/services/SqliteModelBuilder.ts","../../../src/orm/core/providers/drivers/BunSqliteProvider.ts","../../../src/orm/core/providers/drivers/CloudflareD1Provider.ts","../../../src/orm/core/errors/DbColumnNotFoundError.ts","../../../src/orm/core/errors/DbConflictError.ts","../../../src/orm/core/errors/DbDeadlockError.ts","../../../src/orm/core/errors/DbEntityNotFoundError.ts","../../../src/orm/core/errors/DbForeignKeyError.ts","../../../src/orm/core/errors/DbNotNullError.ts","../../../src/orm/core/errors/DbTableNotFoundError.ts","../../../src/orm/core/errors/DbVersionMismatchError.ts","../../../src/orm/core/helpers/pgAttr.ts","../../../src/orm/core/providers/DbCacheProvider.ts","../../../src/orm/core/services/PgRelationManager.ts","../../../src/orm/core/services/QueryManager.ts","../../../src/orm/core/services/Repository.ts","../../../src/orm/core/providers/RepositoryProvider.ts","../../../src/orm/core/errors/DbMigrationError.ts","../../../src/orm/core/errors/DbConnectionError.ts","../../../src/orm/core/providers/DatabaseTypeProvider.ts","../../../src/orm/core/schemas/legacyIdSchema.ts","../../../src/orm/core/primitives/$repository.ts","../../../src/orm/core/primitives/$seed.ts","../../../src/orm/core/primitives/$transactional.ts","../../../src/orm/core/types/schema.ts","../../../src/orm/core/index.bun.ts"],"sourcesContent":["import type { SQL } from \"drizzle-orm\";\nimport type {\n PgSequenceOptions,\n UpdateDeleteAction,\n} from \"drizzle-orm/pg-core\";\nimport type { EntityPrimitive } from \"../primitives/$entity.ts\";\n\nexport const PG_DEFAULT = Symbol.for(\"Alepha.Postgres.Default\");\nexport const PG_PRIMARY_KEY = Symbol.for(\"Alepha.Postgres.PrimaryKey\");\nexport const PG_CREATED_AT = Symbol.for(\"Alepha.Postgres.CreatedAt\");\nexport const PG_UPDATED_AT = Symbol.for(\"Alepha.Postgres.UpdatedAt\");\nexport const PG_DELETED_AT = Symbol.for(\"Alepha.Postgres.DeletedAt\");\nexport const PG_VERSION = Symbol.for(\"Alepha.Postgres.Version\");\nexport const PG_IDENTITY = Symbol.for(\"Alepha.Postgres.Identity\");\nexport const PG_ENUM = Symbol.for(\"Alepha.Postgres.Enum\");\nexport const PG_REF = Symbol.for(\"Alepha.Postgres.Ref\");\nexport const PG_GENERATED = Symbol.for(\"Alepha.Postgres.Generated\");\nexport const PG_ORGANIZATION = Symbol.for(\"Alepha.Postgres.Organization\");\n\n/**\n * @deprecated Use `PG_IDENTITY` instead.\n */\nexport const PG_SERIAL = Symbol.for(\"Alepha.Postgres.Serial\");\n\nexport type PgDefault = typeof PG_DEFAULT;\nexport type PgRef = typeof PG_REF;\nexport type PgPrimaryKey = typeof PG_PRIMARY_KEY;\n\nexport type PgSymbols = {\n [PG_DEFAULT]: {};\n [PG_PRIMARY_KEY]: {};\n [PG_CREATED_AT]: {};\n [PG_UPDATED_AT]: {};\n [PG_DELETED_AT]: {};\n [PG_VERSION]: {};\n [PG_IDENTITY]: PgIdentityOptions;\n [PG_REF]: PgRefOptions;\n [PG_ENUM]: PgEnumOptions;\n [PG_GENERATED]: PgGeneratedOptions;\n [PG_ORGANIZATION]: {};\n\n /**\n * @deprecated Use `PG_IDENTITY` instead.\n */\n [PG_SERIAL]: {};\n};\n\nexport type PgSymbolKeys = keyof PgSymbols;\n\nexport type PgIdentityOptions = {\n mode: \"always\" | \"byDefault\";\n} & PgSequenceOptions & {\n name?: string;\n };\n\nexport interface PgEnumOptions {\n name?: string;\n description?: string;\n}\n\nexport interface PgGeneratedOptions {\n /**\n * SQL expression for the generated column.\n */\n expression: SQL;\n\n /**\n * Storage mode for the generated column.\n * - `\"stored\"` — value is computed on write and stored on disk (default for PostgreSQL).\n * - `\"virtual\"` — value is computed on read (default for SQLite).\n */\n mode?: \"stored\" | \"virtual\";\n}\n\nexport interface PgRefOptions {\n ref: () => {\n name: string;\n entity: EntityPrimitive;\n };\n actions?: {\n onUpdate?: UpdateDeleteAction;\n onDelete?: UpdateDeleteAction;\n };\n}\n","import type { TObject, TOptional } from \"alepha\";\nimport { t } from \"alepha\";\nimport { PG_DEFAULT, PG_GENERATED } from \"../constants/PG_SYMBOLS.ts\";\n\n/**\n * Transforms a TObject schema for insert operations.\n * All default properties at the root level are made optional.\n * Generated columns are excluded entirely.\n *\n * @example\n * Before: { name: string; age: number(default=0); fullName: generated }\n * After: { name: string; age?: number; }\n */\nexport type TObjectInsert<T extends TObject> = TObject<{\n [K in keyof T[\"properties\"] as T[\"properties\"][K] extends {\n [PG_GENERATED]: any;\n }\n ? never\n : K]: T[\"properties\"][K] extends\n | { [PG_DEFAULT]: any }\n | { \"~optional\": true }\n ? TOptional<T[\"properties\"][K]>\n : T[\"properties\"][K];\n}>;\n\nexport const insertSchema = <T extends TObject>(obj: T): TObjectInsert<T> => {\n const newProperties: Record<string, any> = {};\n\n for (const key in obj.properties) {\n const prop = obj.properties[key];\n\n // Skip generated columns — they are computed by the database\n if (PG_GENERATED in prop) {\n continue;\n }\n\n if (PG_DEFAULT in prop) {\n newProperties[key] = t.optional(prop);\n } else {\n newProperties[key] = prop;\n }\n }\n\n return t.object(\n newProperties,\n \"options\" in obj && typeof obj.options === \"object\"\n ? { ...obj.options }\n : {},\n ) as TObjectInsert<T>;\n};\n","import {\n type TNull,\n type TObject,\n type TOptional,\n type TUnion,\n t,\n} from \"alepha\";\nimport { PG_GENERATED } from \"../constants/PG_SYMBOLS.ts\";\n\n/**\n * Transforms a TObject schema for update operations.\n * All optional properties at the root level are made nullable (i.e., `T | null`).\n * Generated columns are excluded entirely.\n *\n * @example\n * Before: { name?: string; age: number; fullName: generated }\n * After: { name?: string | null; age: number; }\n */\nexport type TObjectUpdate<T extends TObject> = TObject<{\n [K in keyof T[\"properties\"] as T[\"properties\"][K] extends {\n [PG_GENERATED]: any;\n }\n ? never\n : K]: T[\"properties\"][K] extends TOptional<infer U>\n ? TOptional<TUnion<[U, TNull]>>\n : T[\"properties\"][K];\n}>;\n\nexport const updateSchema = <T extends TObject>(\n schema: T,\n): TObjectUpdate<T> => {\n const newProperties: Record<string, any> = {};\n\n for (const key in schema.properties) {\n const prop = schema.properties[key];\n\n // Skip generated columns — they are computed by the database\n if (PG_GENERATED in prop) {\n continue;\n }\n\n if (t.schema.isOptional(prop)) {\n newProperties[key] = t.optional(t.union([prop, t.raw.Null()]));\n } else {\n newProperties[key] = prop;\n }\n }\n\n return t.object(\n newProperties,\n \"options\" in schema && typeof schema.options === \"object\"\n ? { ...schema.options }\n : {},\n ) as TObjectUpdate<T>;\n};\n","import { KIND, type Static, type TObject } from \"alepha\";\nimport type { BuildExtraConfigColumns, SQL } from \"drizzle-orm\";\nimport type {\n PgColumn,\n PgColumnBuilderBase,\n PgTableExtraConfigValue,\n} from \"drizzle-orm/pg-core\";\nimport { insertSchema, type TObjectInsert } from \"../schemas/insertSchema.ts\";\nimport { type TObjectUpdate, updateSchema } from \"../schemas/updateSchema.ts\";\n\n/**\n * Creates a database entity primitive that defines table structure using TypeBox schemas.\n *\n * @example\n * ```ts\n * import { t } from \"alepha\";\n * import { $entity } from \"alepha/orm\";\n *\n * const userEntity = $entity({\n * name: \"users\",\n * schema: t.object({\n * id: pg.primaryKey(),\n * name: t.text(),\n * email: t.email(),\n * }),\n * });\n * ```\n */\nexport const $entity = <TSchema extends TObject>(\n options: EntityPrimitiveOptions<TSchema>,\n): EntityPrimitive<TSchema> => {\n return new EntityPrimitive<TSchema>(options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface EntityPrimitiveOptions<\n T extends TObject,\n Keys = keyof Static<T>,\n> {\n /**\n * The database table name that will be created for this entity.\n * If not provided, name will be inferred from the $repository variable name.\n */\n name: string;\n\n /**\n * TypeBox schema defining the table structure and column types.\n */\n schema: T;\n\n /**\n * Database indexes to create for query optimization.\n */\n indexes?: (\n | Keys\n | {\n /**\n * Single column to index.\n */\n column: Keys;\n /**\n * Whether this should be a unique index (enforces uniqueness constraint).\n */\n unique?: boolean;\n /**\n * Custom name for the index. If not provided, generates name automatically.\n */\n name?: string;\n /**\n * Partial index condition. Only rows matching this SQL expression are indexed.\n */\n where?: SQL;\n }\n | {\n /**\n * Multiple columns for composite index (order matters for query optimization).\n */\n columns: Keys[];\n /**\n * Whether this should be a unique index (enforces uniqueness constraint).\n */\n unique?: boolean;\n /**\n * Custom name for the index. If not provided, generates name automatically.\n */\n name?: string;\n /**\n * Partial index condition. Only rows matching this SQL expression are indexed.\n */\n where?: SQL;\n }\n | {\n /**\n * SQL expressions for expression-based indexes.\n *\n * Can include column references and SQL functions like `LOWER()`, `UPPER()`, etc.\n * Columns and expressions can be mixed together.\n *\n * @example\n * ```ts\n * // Case-insensitive unique username per realm\n * indexes: [{\n * expressions: (self) => [self.realm, sql`LOWER(${self.username})`],\n * unique: true,\n * name: \"users_realm_username_lower_idx\",\n * }]\n * ```\n */\n expressions: (self: Record<Keys & string, any>) => (SQL | any)[];\n /**\n * Whether this should be a unique index (enforces uniqueness constraint).\n */\n unique?: boolean;\n /**\n * Custom name for the index. If not provided, generates name automatically.\n */\n name: string;\n /**\n * Partial index condition. Only rows matching this SQL expression are indexed.\n */\n where?: SQL;\n }\n )[];\n\n /**\n * Foreign key constraints to maintain referential integrity.\n */\n foreignKeys?: Array<{\n /**\n * Optional name for the foreign key constraint.\n */\n name?: string;\n /**\n * Local columns that reference the foreign table.\n */\n columns: Array<keyof Static<T>>;\n /**\n * Referenced columns in the foreign table.\n * Must be EntityColumn references from other entities.\n */\n foreignColumns: Array<() => EntityColumn<any>>;\n }>;\n\n /**\n * Additional table constraints for data validation.\n *\n * Constraints enforce business rules at the database level, providing\n * an additional layer of data integrity beyond application validation.\n *\n * **Constraint Types**:\n * - **Unique constraints**: Prevent duplicate values across columns\n * - **Check constraints**: Enforce custom validation rules with SQL expressions\n *\n * @example\n * ```ts\n * constraints: [\n * {\n * name: \"unique_user_email\",\n * columns: [\"email\"],\n * unique: true\n * },\n * {\n * name: \"valid_age_range\",\n * columns: [\"age\"],\n * check: sql`age >= 0 AND age <= 150`\n * },\n * {\n * name: \"unique_user_username_per_tenant\",\n * columns: [\"tenantId\", \"username\"],\n * unique: true\n * }\n * ]\n * ```\n */\n constraints?: Array<{\n /**\n * Columns involved in this constraint.\n */\n columns: Array<keyof Static<T>>;\n /**\n * Optional name for the constraint.\n */\n name?: string;\n /**\n * Whether this is a unique constraint.\n */\n unique?: boolean | {} /* options */;\n /**\n * SQL expression for check constraint validation.\n */\n check?: SQL;\n }>;\n\n /**\n * Advanced Drizzle ORM configuration for complex table setups.\n */\n config?: (\n self: BuildExtraConfigColumns<string, FromSchema<T>, \"pg\">,\n ) => PgTableExtraConfigValue[];\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class EntityPrimitive<T extends TObject = TObject> {\n public readonly options: EntityPrimitiveOptions<T>;\n\n constructor(options: EntityPrimitiveOptions<T>) {\n this.options = options;\n }\n\n alias(alias: string): this {\n const aliased = new EntityPrimitive<T>(this.options);\n return new Proxy(aliased, {\n get(target, prop, receiver) {\n if (prop === \"$alias\") {\n return alias;\n }\n return Reflect.get(target, prop, receiver);\n },\n }) as this;\n }\n\n get cols(): EntityColumns<T> {\n const cols: Partial<EntityColumns<T>> = {};\n for (const key of Object.keys(this.schema.properties) as Array<\n keyof T[\"properties\"]\n >) {\n cols[key] = {\n name: key as string,\n entity: this,\n };\n }\n\n return cols as EntityColumns<T>;\n }\n\n get name(): string {\n return this.options.name;\n }\n\n get schema(): T {\n return this.options.schema;\n }\n\n get insertSchema(): TObjectInsert<T> {\n return insertSchema(this.options.schema);\n }\n\n get updateSchema(): TObjectUpdate<T> {\n return updateSchema(this.options.schema);\n }\n}\n\n$entity[KIND] = EntityPrimitive;\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Convert a schema to columns.\n */\nexport type FromSchema<T extends TObject> = {\n [key in keyof T[\"properties\"]]: PgColumnBuilderBase;\n};\n\nexport type SchemaToTableConfig<T extends TObject> = {\n name: string;\n schema: string | undefined;\n columns: {\n [key in keyof T[\"properties\"]]: PgColumn;\n };\n dialect: string;\n};\n\nexport type EntityColumn<T extends TObject> = {\n name: string;\n entity: EntityPrimitive<T>;\n};\n\nexport type EntityColumns<T extends TObject> = {\n [key in keyof T[\"properties\"]]: EntityColumn<T>;\n};\n","import { AlephaError } from \"alepha\";\n\nexport class DbError extends AlephaError {\n name = \"DbError\";\n\n constructor(message: string, cause?: unknown) {\n super(message, { cause });\n }\n}\n","import { type Static, t } from \"alepha\";\n\n/**\n * Base database environment schema.\n *\n * Defines the `DATABASE_URL` connection string used by all ORM providers\n * to determine the database driver and connection target.\n *\n * Supported URL formats:\n * - `sqlite://:memory:` or `sqlite://./path/to/db` — SQLite (Node.js or Bun)\n * - `postgres://user:password@host:port/database` — PostgreSQL (Node.js or Bun)\n * - `pglite://:memory:` or `pglite://./path` — PGlite (embedded Postgres)\n * - `d1://BINDING_NAME` — Cloudflare D1\n * - `hyperdrive://BINDING_NAME` — Cloudflare Hyperdrive\n */\nexport const databaseEnvSchema = t.object({\n DATABASE_URL: t.optional(t.text()),\n\n /**\n * Enable or disable push-based schema synchronization (drizzle-kit push).\n *\n * Defaults to `true` in development and test, `false` in production.\n * Set to `false` in development to skip automatic schema sync\n * (e.g. when managing migrations manually).\n */\n DATABASE_SYNC: t.optional(t.boolean()),\n});\n\ndeclare module \"alepha\" {\n interface Env extends Partial<Static<typeof databaseEnvSchema>> {}\n}\n","import { createRequire } from \"node:module\";\nimport { $inject, Alepha, AlephaError } from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport type * as DrizzleKit from \"drizzle-kit/api\";\nimport { sql } from \"drizzle-orm\";\nimport type { DatabaseProvider } from \"./drivers/DatabaseProvider.ts\";\n\nexport class DrizzleKitProvider {\n protected readonly log = $logger();\n protected readonly dateTime = $inject(DateTimeProvider);\n protected readonly alepha = $inject(Alepha);\n\n /**\n * Push-based synchronization using Drizzle Kit's introspection API.\n *\n * Reads the actual database state, diffs against current entity definitions,\n * and applies changes. No stored snapshots — no drift, no corruption.\n *\n * - SQLite: uses `pushSQLiteSchema` (requires sync driver — node:sqlite shim or bun-sqlite)\n * - PostgreSQL: uses `pushSchema` with schema filters\n *\n * Does nothing in production mode — use file-based migrations instead.\n */\n public async synchronize(provider: DatabaseProvider): Promise<void> {\n if (this.alepha.isProduction()) {\n this.log.warn(\"Synchronization skipped in production mode.\");\n return;\n }\n\n if (this.alepha.isTest()) {\n const { statements } = await this.generateMigration(provider);\n await this.executeStatements(\n statements.map((s) =>\n s.replace(/^CREATE SCHEMA /i, \"CREATE SCHEMA IF NOT EXISTS \"),\n ),\n provider,\n );\n return;\n }\n\n const now = this.dateTime.nowMillis();\n const kit = this.importDrizzleKit();\n const models = this.getModels(provider);\n\n if (Object.keys(models).length === 0) {\n this.log.info(`No models to synchronize for '${provider.name}'`);\n return;\n }\n\n try {\n if (provider.dialect === \"sqlite\") {\n await this.pushSqlite(kit, models, provider);\n } else {\n await this.pushPostgres(kit, models, provider);\n }\n } catch (error) {\n // Fallback: generate migrations from scratch (no snapshots).\n // Covers drivers that don't support introspection (e.g. PgLite, sqlite-proxy).\n //\n // If push partially executed (e.g. interactive rename applied then errored),\n // the fallback would re-create tables that already exist. Guard against this\n // by attempting the statements individually and ignoring \"already exists\" errors.\n this.log.debug(\n \"Push sync not available, falling back to migration generation\",\n { error },\n );\n const { statements } = await this.generateMigration(provider);\n await this.executeStatementsLenient(statements, provider);\n }\n\n this.log.info(\n `Synchronization of '${provider.name}' OK [${this.dateTime.nowMillis() - now}ms]`,\n );\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Generate SQL migration statements by diffing two schema states.\n *\n * Used by tests (schema validation) and CLI (`alepha db migrations generate`).\n * Not part of the push sync flow.\n *\n * When `withoutSchema` is true, models are rebuilt without schema qualifiers\n * so the generated SQL is portable across different PostgreSQL schemas.\n */\n public async generateMigration(\n provider: DatabaseProvider,\n prevSnapshot?: any,\n options?: { withoutSchema?: boolean },\n ): Promise<{\n statements: string[];\n models: Record<string, unknown>;\n snapshot?: any;\n }> {\n const kit = this.importDrizzleKit();\n const models = options?.withoutSchema\n ? this.getModelsWithoutSchema(provider)\n : this.getModels(provider);\n\n if (Object.keys(models).length > 0) {\n if (provider.dialect === \"sqlite\") {\n const prev = prevSnapshot ?? (await kit.generateSQLiteDrizzleJson({}));\n const curr = await kit.generateSQLiteDrizzleJson(models);\n return {\n models,\n statements: await kit.generateSQLiteMigration(prev, curr),\n snapshot: curr,\n };\n }\n\n const prev = prevSnapshot ?? kit.generateDrizzleJson({});\n const curr = kit.generateDrizzleJson(models);\n return {\n models,\n statements: await kit.generateMigration(prev, curr),\n snapshot: curr,\n };\n }\n\n return {\n models,\n statements: [],\n snapshot: {},\n };\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Load all tables, enums, sequences, etc. from the provider's repositories.\n */\n public getModels(provider: DatabaseProvider): Record<string, unknown> {\n const models: Record<string, unknown> = {};\n\n for (const [key, value] of provider.schemas.entries()) {\n models[`__schema_${key}`] = value;\n }\n\n for (const [key, value] of provider.tables.entries()) {\n if (models[key]) {\n throw new AlephaError(\n `Model name conflict: '${key}' is already defined.`,\n );\n }\n models[key] = value;\n }\n\n for (const [key, value] of provider.enums.entries()) {\n if (models[key]) {\n throw new AlephaError(\n `Model name conflict: '${key}' is already defined.`,\n );\n }\n models[key] = value;\n }\n\n for (const [key, value] of provider.sequences.entries()) {\n if (models[key]) {\n throw new AlephaError(\n `Model name conflict: '${key}' is already defined.`,\n );\n }\n models[key] = value;\n }\n\n return models;\n }\n\n /**\n * Build schema-free models for migration generation.\n *\n * Rebuilds all entities with `schema = \"public\"` so Drizzle produces\n * SQL without schema qualifiers (e.g. `CREATE TABLE \"users\"` instead\n * of `CREATE TABLE \"myschema\".\"users\"`).\n *\n * The actual schema is applied at migration execution time via `search_path`.\n */\n public getModelsWithoutSchema(\n provider: DatabaseProvider,\n ): Record<string, unknown> {\n const maps = provider.rebuildModels(\"public\");\n const models: Record<string, unknown> = {};\n\n for (const [key, value] of maps.tables.entries()) {\n if (models[key]) {\n throw new AlephaError(\n `Model name conflict: '${key}' is already defined.`,\n );\n }\n models[key] = value;\n }\n\n for (const [key, value] of maps.enums.entries()) {\n if (models[key]) {\n throw new AlephaError(\n `Model name conflict: '${key}' is already defined.`,\n );\n }\n models[key] = value;\n }\n\n for (const [key, value] of maps.sequences.entries()) {\n if (models[key]) {\n throw new AlephaError(\n `Model name conflict: '${key}' is already defined.`,\n );\n }\n models[key] = value;\n }\n\n return models;\n }\n\n /**\n * Preview schema push without executing any statements.\n *\n * Returns the SQL statements that would be executed, warnings, and\n * whether data loss would occur. Does NOT execute any SQL.\n */\n public async dryRunPush(provider: DatabaseProvider): Promise<{\n statements: string[];\n warnings: string[];\n hasDataLoss: boolean;\n }> {\n const kit = this.importDrizzleKit();\n const models = this.getModels(provider);\n\n if (Object.keys(models).length === 0) {\n return { statements: [], warnings: [], hasDataLoss: false };\n }\n\n let result: {\n statementsToExecute: string[];\n warnings: string[];\n hasDataLoss: boolean;\n };\n\n if (provider.dialect === \"sqlite\") {\n result = await kit.pushSQLiteSchema(models, provider.db as any);\n } else {\n const wrappedDb = this.wrapDbForDrizzleKit(provider.db);\n result = await kit.pushSchema(models, wrappedDb, [provider.schema]);\n }\n\n return {\n statements: result.statementsToExecute,\n warnings: result.warnings,\n hasDataLoss: result.hasDataLoss,\n };\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n protected async pushSqlite(\n kit: typeof DrizzleKit,\n models: Record<string, unknown>,\n provider: DatabaseProvider,\n ): Promise<void> {\n const { statementsToExecute } = await kit.pushSQLiteSchema(\n models,\n provider.db as any,\n );\n await this.executeStatements(statementsToExecute, provider);\n }\n\n /**\n * Push schema changes to PostgreSQL using Drizzle Kit's pushSchema with schema filters.\n */\n protected async pushPostgres(\n kit: typeof DrizzleKit,\n models: Record<string, unknown>,\n provider: DatabaseProvider,\n ): Promise<void> {\n if (provider.schema !== \"public\") {\n await this.createSchemaIfNotExists(provider, provider.schema);\n }\n\n // Drizzle Kit's pushSchema expects execute() to return { rows: T[] }\n // (node-postgres/pg format), but postgres.js returns a Result that\n // extends Array directly — no .rows property.\n const wrappedDb = this.wrapDbForDrizzleKit(provider.db);\n\n const { statementsToExecute } = await kit.pushSchema(models, wrappedDb, [\n provider.schema,\n ]);\n await this.executeStatements(statementsToExecute, provider);\n }\n\n /**\n * Execute a list of SQL statements against the provider.\n */\n protected async executeStatements(\n statements: string[],\n provider: DatabaseProvider,\n ): Promise<void> {\n if (statements.length > 0) {\n this.log.debug(`Executing ${statements.length} statements ...`, {\n statements,\n });\n }\n for (const statement of statements) {\n await provider.execute(sql.raw(statement));\n }\n }\n\n /**\n * Execute SQL statements, ignoring \"already exists\" errors.\n *\n * Used by the fallback migration path where push may have partially\n * applied changes before erroring, leaving some objects already created.\n */\n protected async executeStatementsLenient(\n statements: string[],\n provider: DatabaseProvider,\n ): Promise<void> {\n if (statements.length > 0) {\n this.log.debug(\n `Executing ${statements.length} statements (lenient) ...`,\n { statements },\n );\n }\n for (const statement of statements) {\n try {\n await provider.execute(sql.raw(statement));\n } catch (error: any) {\n const message = error?.message ?? \"\";\n if (message.includes(\"already exists\")) {\n this.log.debug(`Skipped (already exists): ${statement.slice(0, 80)}`);\n continue;\n }\n throw error;\n }\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n protected async createSchemaIfNotExists(\n provider: DatabaseProvider,\n schemaName: string,\n ) {\n if (!/^[a-z0-9_]+$/i.test(schemaName)) {\n throw new AlephaError(\n `Invalid schema name: ${schemaName}. Must only contain alphanumeric characters and underscores.`,\n );\n }\n\n const sqlSchema = sql.raw(schemaName);\n\n if (schemaName.startsWith(\"test_\")) {\n this.log.info(`Drop test schema '${schemaName}' ...`, schemaName);\n await provider.execute(sql`DROP SCHEMA IF EXISTS ${sqlSchema} CASCADE`);\n }\n\n this.log.debug(`Ensuring schema '${schemaName}' exists`);\n await provider.execute(sql`CREATE SCHEMA IF NOT EXISTS ${sqlSchema}`);\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n // TODO: remove when Drizzle Kit fixes postgres.js compatibility\n\n /**\n * Wrap a Drizzle PgDatabase instance for compatibility with Drizzle Kit.\n *\n * Drizzle Kit's pushSchema expects execute() to return { rows: T[] }\n * (node-postgres/pg format), but postgres.js returns a Result that\n * extends Array directly — no .rows property.\n */\n protected wrapDbForDrizzleKit(db: any): any {\n return new Proxy(db, {\n get(target, prop, receiver) {\n if (prop === \"execute\") {\n return async (...args: any[]) => {\n const res = await target.execute(...args);\n if (Array.isArray(res) && !(\"rows\" in res)) {\n return Object.assign(res, { rows: [...res] });\n }\n return res;\n };\n }\n return Reflect.get(target, prop, receiver);\n },\n });\n }\n\n /**\n * Try to load the official Drizzle Kit API.\n */\n public importDrizzleKit(): typeof DrizzleKit {\n try {\n return createRequire(import.meta.url)(\"drizzle-kit/api\");\n } catch (_) {\n throw new AlephaError(\n \"Drizzle Kit is not installed. Please install it with `npm install -D drizzle-kit`.\",\n );\n }\n }\n}\n","import { stat } from \"node:fs/promises\";\nimport {\n $inject,\n Alepha,\n AlephaError,\n type Static,\n type TObject,\n} from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { type SQLWrapper, sql } from \"drizzle-orm\";\nimport {\n alias,\n type PgDatabase,\n type PgTableWithColumns,\n type PgTransaction,\n} from \"drizzle-orm/pg-core\";\nimport type { PgTransactionConfig } from \"drizzle-orm/pg-core/session\";\nimport { DbError } from \"../../errors/DbError.ts\";\nimport type {\n EntityPrimitive,\n SchemaToTableConfig,\n} from \"../../primitives/$entity.ts\";\nimport type { SequencePrimitive } from \"../../primitives/$sequence.ts\";\nimport { databaseEnvSchema } from \"../../schemas/databaseEnvSchema.ts\";\nimport type { ModelBuilder } from \"../../services/ModelBuilder.ts\";\nimport { DrizzleKitProvider } from \"../DrizzleKitProvider.ts\";\n\nexport type SQLLike = SQLWrapper | string;\n\nexport abstract class DatabaseProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly dateTime = $inject(DateTimeProvider);\n protected readonly log = $logger();\n protected abstract readonly builder: ModelBuilder;\n protected readonly kit = $inject(DrizzleKitProvider);\n public abstract readonly db: PgDatabase<any>;\n public abstract readonly dialect: \"postgresql\" | \"sqlite\";\n public abstract readonly url: string;\n\n public readonly enums = new Map<string, unknown>();\n public readonly tables = new Map<string, unknown>();\n public readonly sequences = new Map<string, unknown>();\n public readonly schemas = new Map<string, unknown>();\n\n protected readonly entityPrimitives: EntityPrimitive[] = [];\n protected readonly sequencePrimitives: SequencePrimitive[] = [];\n\n public get name() {\n return \"default\";\n }\n\n public get driver(): string {\n return this.dialect;\n }\n\n /**\n * Whether this driver supports SQL-level transactions (BEGIN/COMMIT/ROLLBACK).\n *\n * Drivers that do not (e.g. PGlite, Cloudflare D1) should override to `false`.\n */\n public get supportsTransactions(): boolean {\n return true;\n }\n\n /**\n * Raw database connection handle (e.g. DatabaseSync, bun:sqlite Database).\n * Override in providers that expose native connections for introspection.\n */\n public get nativeConnection(): unknown {\n return undefined;\n }\n\n public get schema() {\n return \"public\";\n }\n\n /**\n * Migration tracking table name, scoped by schema.\n *\n * Returns `migrations_{schema}` so that multiple schemas sharing the same\n * database each get their own migration history (e.g. `migrations_roadmap`,\n * `migrations_public`).\n */\n public get migrationsTable(): string {\n return `migrations_${this.schema}`;\n }\n\n /**\n * Log a database query with structured metadata for devtools inspection.\n */\n protected logQuery(\n sql: string,\n params: unknown[],\n duration: number,\n rowCount: number,\n error?: string,\n ): void {\n const operation = this.parseOperation(sql);\n const data = {\n type: \"db:query\",\n sql,\n params,\n operation,\n duration: Math.round(duration * 100) / 100,\n rowCount,\n success: !error,\n error,\n };\n\n if (error) {\n this.log.warn(`Query failed (${operation})`, data);\n } else {\n this.log.debug(\n `Query OK (${operation}, ${Math.round(duration)}ms)`,\n data,\n );\n }\n }\n\n protected parseOperation(sql: string): string {\n const trimmed = sql.trimStart().toUpperCase();\n if (trimmed.startsWith(\"SELECT\")) return \"SELECT\";\n if (trimmed.startsWith(\"INSERT\")) return \"INSERT\";\n if (trimmed.startsWith(\"UPDATE\")) return \"UPDATE\";\n if (trimmed.startsWith(\"DELETE\")) return \"DELETE\";\n if (trimmed.startsWith(\"CREATE\")) return \"CREATE\";\n if (trimmed.startsWith(\"ALTER\")) return \"ALTER\";\n if (trimmed.startsWith(\"DROP\")) return \"DROP\";\n return \"OTHER\";\n }\n\n public table<T extends TObject>(\n entity: EntityPrimitive<T>,\n ): PgTableWithColumns<SchemaToTableConfig<T>> {\n const table = this.tables.get(entity.name);\n if (!table) {\n throw new AlephaError(`Table '${entity.name}' is not registered`);\n }\n\n const hasAlias = (entity as any).$alias;\n\n if (hasAlias) {\n return alias(\n table as PgTableWithColumns<SchemaToTableConfig<T>>,\n hasAlias,\n ) as PgTableWithColumns<SchemaToTableConfig<T>>;\n }\n\n return table as PgTableWithColumns<SchemaToTableConfig<T>>;\n }\n\n public registerEntity(entity: EntityPrimitive) {\n this.entityPrimitives.push(entity);\n this.builder.buildTable(entity, this);\n }\n\n public registerSequence(sequence: SequencePrimitive) {\n this.sequencePrimitives.push(sequence);\n this.builder.buildSequence(sequence, this);\n }\n\n /**\n * Rebuild all models into fresh maps using a different schema.\n *\n * When called with `\"public\"`, produces schema-free models suitable for\n * migration generation (no schema qualifiers in the SQL output).\n */\n public rebuildModels(targetSchema: string): {\n tables: Map<string, unknown>;\n enums: Map<string, unknown>;\n sequences: Map<string, unknown>;\n schemas: Map<string, unknown>;\n } {\n const result = {\n tables: new Map<string, unknown>(),\n enums: new Map<string, unknown>(),\n sequences: new Map<string, unknown>(),\n schemas: new Map<string, unknown>(),\n schema: targetSchema,\n };\n\n for (const entity of this.entityPrimitives) {\n this.builder.buildTable(entity, result);\n }\n for (const seq of this.sequencePrimitives) {\n this.builder.buildSequence(seq, result);\n }\n\n return result;\n }\n\n /**\n * Run a function inside a database transaction with implicit tx propagation.\n *\n * The transaction object is stored in `alepha.store` so that all Repository\n * operations within `fn` automatically participate in the transaction without\n * explicit `{ tx }` drilling.\n *\n * Nesting is safe — if already inside a `transactional()` block, the inner\n * call reuses the outer transaction (no nested PG transactions / savepoints).\n */\n public async transactional<R>(\n fn: () => Promise<R>,\n config?: PgTransactionConfig,\n ): Promise<R> {\n const existing = this.alepha.get(\"alepha.orm.tx\");\n if (existing) {\n return fn();\n }\n\n if (!this.supportsTransactions) {\n return fn();\n }\n\n return this.db.transaction(async (tx) => {\n this.alepha.store.set(\"alepha.orm.tx\", tx as PgTransaction<any>, {\n skipEvents: true,\n });\n try {\n return await fn();\n } finally {\n this.alepha.store.set(\"alepha.orm.tx\", undefined, { skipEvents: true });\n }\n }, config);\n }\n\n public abstract execute(\n statement: SQLLike,\n ): Promise<Record<string, unknown>[]>;\n\n public async run<T extends TObject>(\n statement: SQLLike,\n schema: T,\n ): Promise<Array<Static<T>>> {\n const result = await this.execute(statement);\n\n if (result == null) {\n return [];\n }\n\n if (!Array.isArray(result)) {\n this.log.error(\"Unexpected query result format\", { result });\n throw new DbError(\n \"Unexpected query result format, expected array of rows\",\n );\n }\n\n return result.map((row) => this.alepha.codec.decode(schema, row));\n }\n\n /**\n * Get migrations folder path - can be overridden\n */\n protected getMigrationsFolder(): string {\n return `migrations/${this.name}`;\n }\n\n /**\n * Migration orchestration.\n *\n * - Production: file-based migrations from the migrations folder\n * - Dev / Test: push-based sync (introspects actual DB, no snapshots)\n * - Serverless: skipped (migrations should be applied during deployment)\n */\n public async migrate(): Promise<void> {\n if (this.alepha.isServerless()) {\n return;\n }\n\n if (this.alepha.isProduction()) {\n const migrationsFolder = this.getMigrationsFolder();\n const exists = await stat(migrationsFolder).catch(() => false);\n\n if (!exists) {\n this.log.warn(\"Migration SKIPPED - no migrations found\");\n return;\n }\n\n // For schema-free migrations, ensure the target schema exists\n // before running migration files. The schema is applied via\n // search_path set at the provider's connection level.\n if (this.dialect === \"postgresql\" && this.schema !== \"public\") {\n this.log.debug(`Ensuring schema '${this.schema}' exists ...`);\n await this.execute(\n sql`CREATE SCHEMA IF NOT EXISTS ${sql.raw(this.schema)}`,\n );\n }\n\n this.log.debug(`Migrate from '${migrationsFolder}' directory ...`);\n await this.executeMigrations(migrationsFolder);\n this.log.info(\"Migration OK\");\n } else {\n const { DATABASE_SYNC } = this.alepha.parseEnv(databaseEnvSchema);\n if (DATABASE_SYNC === false) {\n this.log.info(\n \"Database synchronization disabled (DATABASE_SYNC=false)\",\n );\n return;\n }\n\n try {\n await this.kit.synchronize(this);\n } catch (error) {\n throw new DbError(\n `Failed to synchronize ${this.dialect} database schema`,\n error as Error,\n );\n }\n }\n }\n\n /**\n * Provider-specific migration execution\n * MUST be implemented by each provider\n */\n protected abstract executeMigrations(migrationsFolder: string): Promise<void>;\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * For testing purposes, generate a unique schema name.\n *\n * Format: `test_alepha_{epoch_seconds}_{random8}`\n * Example: `test_alepha_1739871618_k3m9x2p1`\n */\n protected generateTestSchemaName(): string {\n const epoch = Math.floor(this.dateTime.nowMillis() / 1000);\n const random = Math.random().toString(36).slice(2, 10).padEnd(8, \"0\");\n\n return `test_alepha_${epoch}_${random}`;\n }\n}\n","import { createPrimitive, KIND, Primitive } from \"alepha\";\nimport { sql } from \"drizzle-orm\";\nimport type { PgSequenceOptions } from \"drizzle-orm/pg-core\";\nimport { DatabaseProvider } from \"../providers/drivers/DatabaseProvider.ts\";\n\n/**\n * Creates a PostgreSQL sequence primitive for generating unique numeric values.\n */\nexport const $sequence = (\n options: SequencePrimitiveOptions = {},\n): SequencePrimitive => {\n return createPrimitive(SequencePrimitive, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface SequencePrimitiveOptions extends PgSequenceOptions {\n /**\n * The name of the sequence. If not provided, the property key will be used.\n */\n name?: string;\n\n provider?: DatabaseProvider;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class SequencePrimitive extends Primitive<SequencePrimitiveOptions> {\n public readonly provider = this.$provider();\n\n public onInit() {\n this.provider.registerSequence(this);\n }\n\n public get name(): string {\n return this.options.name ?? this.config.propertyKey;\n }\n\n public async next(): Promise<number> {\n return this.provider\n .execute(\n sql`SELECT nextval('${sql.raw(this.provider.schema)}.\"${sql.raw(this.name)}\"')`,\n )\n .then((rows) => Number(rows[0]?.nextval));\n }\n\n public async current(): Promise<number> {\n return this.provider\n .execute(\n sql`SELECT last_value FROM ${sql.raw(this.provider.schema)}.\"${sql.raw(this.name)}\"`,\n )\n .then((rows) => Number(rows[0]?.last_value));\n }\n\n protected $provider() {\n return this.options.provider ?? this.alepha.inject(DatabaseProvider);\n }\n}\n\n$sequence[KIND] = SequencePrimitive;\n","import { AlephaError } from \"alepha\";\nimport type { SQL } from \"drizzle-orm\";\nimport type { EntityPrimitive } from \"../primitives/$entity.ts\";\nimport type { SequencePrimitive } from \"../primitives/$sequence.ts\";\n\n/**\n * Database-specific table configuration functions\n */\nexport interface TableConfigBuilders<TConfig> {\n index: (name: string) => {\n on: (...columns: any[]) => TConfig;\n };\n uniqueIndex: (name: string) => {\n on: (...columns: any[]) => TConfig;\n };\n unique: (name: string) => {\n on: (...columns: any[]) => TConfig;\n };\n check: (name: string, sql: SQL) => TConfig;\n foreignKey: (config: {\n name: string;\n columns: any[];\n foreignColumns: any[];\n }) => TConfig;\n}\n\n/**\n * Abstract base class for transforming Alepha Primitives (Entity, Sequence, etc...)\n * into drizzle models (tables, enums, sequences, etc...).\n */\nexport abstract class ModelBuilder {\n /**\n * Build a table from an entity primitive.\n */\n abstract buildTable(\n entity: EntityPrimitive,\n options: {\n tables: Map<string, unknown>;\n enums: Map<string, unknown>;\n schemas: Map<string, unknown>;\n schema: string;\n },\n ): void;\n\n /**\n * Build a sequence from a sequence primitive.\n */\n abstract buildSequence(\n sequence: SequencePrimitive,\n options: {\n sequences: Map<string, unknown>;\n schema: string;\n },\n ): void;\n\n /**\n * Convert camelCase to snake_case for column names.\n */\n protected toColumnName(str: string): string {\n return (\n str[0].toLowerCase() +\n str.slice(1).replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`)\n );\n }\n\n /**\n * Build the table configuration function for any database.\n * This includes indexes, foreign keys, constraints, and custom config.\n *\n * @param entity - The entity primitive\n * @param builders - Database-specific builder functions\n * @param tableResolver - Function to resolve entity references to table columns\n * @param customConfigHandler - Optional handler for custom config\n */\n protected buildTableConfig<TConfig, TSelf>(\n entity: EntityPrimitive,\n builders: TableConfigBuilders<TConfig>,\n tableResolver?: (entityName: string) => any,\n customConfigHandler?: (config: any, self: TSelf) => TConfig[],\n ): ((self: TSelf) => TConfig[]) | undefined {\n // If no extra config is needed, return undefined\n if (\n !entity.options.indexes &&\n !entity.options.foreignKeys &&\n !entity.options.constraints &&\n !entity.options.config\n ) {\n return undefined;\n }\n\n return (self: TSelf) => {\n const configs: TConfig[] = [];\n\n // Build indexes\n if (entity.options.indexes) {\n for (const indexDef of entity.options.indexes) {\n if (typeof indexDef === \"string\") {\n const columnName = this.toColumnName(indexDef);\n const indexName = `${entity.name}_${columnName}_idx`;\n\n // Use original camelCase property name for lookup\n if ((self as any)[indexDef]) {\n configs.push(\n builders.index(indexName).on((self as any)[indexDef]),\n );\n }\n } else if (typeof indexDef === \"object\" && indexDef !== null) {\n if (\"column\" in indexDef) {\n const columnName = this.toColumnName(indexDef.column as string);\n const indexName =\n indexDef.name || `${entity.name}_${columnName}_idx`;\n\n // Use original camelCase property name for lookup\n if ((self as any)[indexDef.column]) {\n let idx = indexDef.unique\n ? builders\n .uniqueIndex(indexName)\n .on((self as any)[indexDef.column])\n : builders\n .index(indexName)\n .on((self as any)[indexDef.column]);\n if (\"where\" in indexDef && indexDef.where) {\n idx = (idx as any).where(indexDef.where);\n }\n configs.push(idx);\n }\n } else if (\"expressions\" in indexDef) {\n const parts = indexDef.expressions(self as any);\n if (parts.length > 0) {\n let idx = indexDef.unique\n ? builders.uniqueIndex(indexDef.name).on(...parts)\n : builders.index(indexDef.name).on(...parts);\n if (\"where\" in indexDef && indexDef.where) {\n idx = (idx as any).where(indexDef.where);\n }\n configs.push(idx);\n }\n } else if (\"columns\" in indexDef) {\n const columnNames = indexDef.columns.map((col: any) =>\n this.toColumnName(col as string),\n );\n const indexName =\n indexDef.name || `${entity.name}_${columnNames.join(\"_\")}_idx`;\n\n // Use original camelCase property names for lookup\n const cols = indexDef.columns\n .map((col: any) => (self as any)[col])\n .filter(Boolean);\n\n if (cols.length === indexDef.columns.length) {\n let idx = indexDef.unique\n ? builders.uniqueIndex(indexName).on(...cols)\n : builders.index(indexName).on(...cols);\n if (\"where\" in indexDef && indexDef.where) {\n idx = (idx as any).where(indexDef.where);\n }\n configs.push(idx);\n }\n }\n }\n }\n }\n\n // Build foreign keys\n if (entity.options.foreignKeys) {\n for (const fkDef of entity.options.foreignKeys) {\n const columnNames = fkDef.columns.map((col) =>\n this.toColumnName(col as string),\n );\n\n // Use original camelCase property names for lookup\n const cols = fkDef.columns\n .map((col) => (self as any)[col])\n .filter(Boolean);\n\n if (cols.length === fkDef.columns.length) {\n const fkName =\n fkDef.name || `${entity.name}_${columnNames.join(\"_\")}_fk`;\n\n // Resolve foreign column references\n const foreignColumns = fkDef.foreignColumns.map((colRef) => {\n const entityCol = colRef();\n if (!entityCol?.entity || !entityCol.name) {\n throw new AlephaError(\n `Invalid foreign column reference in ${entity.name}`,\n );\n }\n\n // If we have a table resolver, use it to get the actual table column\n if (tableResolver) {\n const foreignTable = tableResolver(entityCol.entity.name);\n if (!foreignTable) {\n throw new AlephaError(\n `Foreign table ${entityCol.entity.name} not found for ${entity.name}`,\n );\n }\n // Use original camelCase property name for lookup in foreign table\n return foreignTable[entityCol.name];\n }\n\n // Fallback: return the entity column reference (will be resolved later)\n return entityCol;\n });\n\n configs.push(\n builders.foreignKey({\n name: fkName,\n columns: cols,\n foreignColumns,\n }),\n );\n }\n }\n }\n\n // Build constraints\n if (entity.options.constraints) {\n for (const constraintDef of entity.options.constraints) {\n const columnNames = constraintDef.columns.map((col) =>\n this.toColumnName(col as string),\n );\n\n // Use original camelCase property names for lookup\n const cols = constraintDef.columns\n .map((col) => (self as any)[col])\n .filter(Boolean);\n\n if (cols.length === constraintDef.columns.length) {\n if (constraintDef.unique) {\n const constraintName =\n constraintDef.name ||\n `${entity.name}_${columnNames.join(\"_\")}_unique`;\n\n configs.push(builders.unique(constraintName).on(...cols));\n }\n\n if (constraintDef.check) {\n const constraintName =\n constraintDef.name ||\n `${entity.name}_${columnNames.join(\"_\")}_check`;\n\n configs.push(builders.check(constraintName, constraintDef.check));\n }\n }\n }\n }\n\n // Add custom config if provided\n if (entity.options.config && customConfigHandler) {\n configs.push(...customConfigHandler(entity.options.config, self));\n } else if (entity.options.config) {\n // Default behavior: call the config function directly\n const customConfigs = entity.options.config(self as any);\n if (Array.isArray(customConfigs)) {\n configs.push(...(customConfigs as any));\n }\n }\n\n return configs;\n };\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport {\n AlephaError,\n type Static,\n type TObject,\n type TSchema,\n type TString,\n t,\n} from \"alepha\";\nimport { type BuildColumns, sql } from \"drizzle-orm\";\nimport * as pg from \"drizzle-orm/sqlite-core\";\nimport {\n check,\n foreignKey,\n index,\n type SQLiteColumnBuilderBase,\n type SQLiteTableWithColumns,\n sqliteTable,\n unique,\n uniqueIndex,\n} from \"drizzle-orm/sqlite-core\";\nimport {\n PG_CREATED_AT,\n PG_GENERATED,\n PG_IDENTITY,\n PG_PRIMARY_KEY,\n PG_REF,\n PG_SERIAL,\n PG_UPDATED_AT,\n type PgGeneratedOptions,\n type PgRefOptions,\n} from \"../constants/PG_SYMBOLS.ts\";\nimport type { EntityPrimitive } from \"../primitives/$entity.ts\";\nimport type { SequencePrimitive } from \"../primitives/$sequence.ts\";\nimport { ModelBuilder } from \"./ModelBuilder.ts\";\n\nexport class SqliteModelBuilder extends ModelBuilder {\n public buildTable(\n entity: EntityPrimitive<any>,\n options: {\n tables: Map<string, unknown>;\n enums: Map<string, unknown>;\n schemas: Map<string, unknown>;\n schema: string;\n },\n ) {\n const tableName = entity.name;\n if (options.tables.has(tableName)) {\n return;\n }\n\n const columns = this.schemaToSqliteColumns(\n tableName,\n entity.schema,\n options.enums,\n options.tables,\n );\n\n // Build the config function for SQLite\n const configFn = this.getTableConfig(entity, options.tables);\n\n const table = sqliteTable(tableName, columns, configFn);\n\n options.tables.set(tableName, table);\n }\n\n public buildSequence(\n sequence: SequencePrimitive,\n options: {\n sequences: Map<string, unknown>;\n schema: string;\n },\n ) {\n throw new AlephaError(\"SQLite does not support sequences\");\n }\n\n /**\n * Get SQLite-specific config builder for the table.\n */\n protected getTableConfig(\n entity: EntityPrimitive,\n tables: Map<string, unknown>,\n ): ((self: BuildColumns<string, any, \"sqlite\">) => any) | undefined {\n // SQLite-specific builders\n const sqliteBuilders = {\n index,\n uniqueIndex,\n unique,\n check,\n foreignKey,\n };\n\n // Table resolver function\n const tableResolver = (entityName: string) => {\n return tables.get(entityName) as any;\n };\n\n return this.buildTableConfig<any, BuildColumns<string, any, \"sqlite\">>(\n entity,\n sqliteBuilders,\n tableResolver,\n (config, self) => {\n // SQLite custom config handler\n const customConfigs = (config as any)(self);\n return Array.isArray(customConfigs) ? customConfigs : [];\n },\n );\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n schemaToSqliteColumns = <T extends TObject>(\n tableName: string,\n schema: T,\n enums: Map<string, unknown>,\n tables: Map<string, unknown>,\n ): SchemaToSqliteBuilder<T> => {\n return Object.entries(schema.properties).reduce<\n Partial<SchemaToSqliteBuilder<T>>\n >((columns, [key, value]) => {\n let col = this.mapFieldToSqliteColumn(tableName, key, value, enums);\n\n if (\"default\" in value && value.default != null) {\n col = col.default(value.default as any);\n }\n\n if (PG_PRIMARY_KEY in value) {\n col = col.primaryKey();\n }\n\n if (PG_REF in value) {\n const config = value[PG_REF] as PgRefOptions;\n col = col.references(() => {\n const ref = config.ref();\n const table = tables.get(\n ref.entity.name,\n ) as SQLiteTableWithColumns<any>;\n\n if (!table) {\n throw new AlephaError(\n `Referenced table ${ref.entity.name} not found for ${tableName}.${key}`,\n );\n }\n\n const target = table[ref.name];\n if (!target) {\n throw new AlephaError(\n `Referenced column ${ref.name} not found in table ${ref.entity.name} for ${tableName}.${key}`,\n );\n }\n\n return target;\n }, config.actions);\n }\n\n if (PG_GENERATED in value) {\n const gen = value[PG_GENERATED] as PgGeneratedOptions;\n col = col.generatedAlwaysAs(gen.expression, {\n mode: gen.mode ?? \"virtual\",\n });\n }\n\n if (schema.required?.includes(key)) {\n col = col.notNull();\n }\n\n (columns as Record<string, unknown>)[key] = col;\n return columns;\n }, {}) as SchemaToSqliteBuilder<T>;\n };\n\n mapFieldToSqliteColumn = (\n tableName: string,\n fieldName: string,\n value: TSchema,\n enums: Map<string, any>,\n ) => {\n const key = this.toColumnName(fieldName);\n\n if (\n // is nullish ?\n \"anyOf\" in value &&\n Array.isArray(value.anyOf) &&\n value.anyOf.length === 2 &&\n value.anyOf.some((it: TSchema) => t.schema.isNull(it))\n ) {\n // then, remove nullish\n value = value.anyOf.find((it: TSchema) => !t.schema.isNull(it))!;\n }\n\n if (t.schema.isInteger(value)) {\n if (PG_SERIAL in value || PG_IDENTITY in value) {\n return pg\n .integer(key, { mode: \"number\" })\n .primaryKey({ autoIncrement: true });\n }\n\n return pg.integer(key);\n }\n\n if (t.schema.isBigInt(value)) {\n if (PG_PRIMARY_KEY in value || PG_IDENTITY in value) {\n return pg\n .integer(key, { mode: \"number\" })\n .primaryKey({ autoIncrement: true });\n }\n\n return pg.integer(key, { mode: \"number\" });\n }\n\n if (t.schema.isNumber(value)) {\n if (PG_IDENTITY in value) {\n return pg\n .integer(key, { mode: \"number\" })\n .primaryKey({ autoIncrement: true });\n }\n\n return pg.numeric(key);\n }\n\n if (t.schema.isString(value)) {\n return this.mapStringToSqliteColumn(key, value);\n }\n\n if (t.schema.isBoolean(value)) {\n return this.sqliteBool(key, value);\n }\n\n if (t.schema.isObject(value)) {\n return this.sqliteJson(key, value);\n }\n\n if (t.schema.isRecord(value)) {\n return this.sqliteJson(key, value);\n }\n\n if (t.schema.isAny(value)) {\n return this.sqliteJson(key, value);\n }\n\n if (t.schema.isArray(value)) {\n if (t.schema.isObject(value.items)) {\n return this.sqliteJson(key, value);\n }\n if (t.schema.isRecord(value.items)) {\n return this.sqliteJson(key, value);\n }\n if (t.schema.isAny(value.items)) {\n return this.sqliteJson(key, value);\n }\n if (t.schema.isString(value.items)) {\n return this.sqliteJson(key, value);\n }\n if (t.schema.isInteger(value.items)) {\n return this.sqliteJson(key, value);\n }\n if (t.schema.isNumber(value.items)) {\n return this.sqliteJson(key, value);\n }\n if (t.schema.isBoolean(value.items)) {\n return this.sqliteJson(key, value);\n }\n }\n\n if (\n t.schema.isUnsafe(value) &&\n \"type\" in value &&\n value.type === \"string\"\n ) {\n return this.mapStringToSqliteColumn(key, value as any);\n }\n\n throw new AlephaError(\n `Unsupported schema for field '${tableName}.${fieldName}' (schema: ${JSON.stringify(value)})`,\n );\n };\n\n mapStringToSqliteColumn = (key: string, value: TString) => {\n if (value.format === \"uuid\") {\n if (PG_PRIMARY_KEY in value) {\n return pg\n .text(key)\n .primaryKey()\n .$defaultFn(() => randomUUID());\n }\n\n return pg.text(key);\n }\n\n if (value.format === \"byte\") {\n return this.sqliteJson(key, value);\n }\n\n if (value.format === \"date-time\") {\n if (PG_CREATED_AT in value) {\n return this.sqliteDateTime(key, {}).default(\n sql`(unixepoch('subsec') * 1000)`,\n );\n }\n if (PG_UPDATED_AT in value) {\n return this.sqliteDateTime(key, {}).default(\n sql`(unixepoch('subsec') * 1000)`,\n );\n }\n return this.sqliteDateTime(key, {});\n }\n\n if (value.format === \"date\") {\n return this.sqliteDate(key, {});\n }\n\n return pg.text(key);\n };\n\n sqliteJson = <TDocument extends TSchema>(name: string, document: TDocument) =>\n pg\n .customType<{\n data: Static<TDocument>;\n driverData: string;\n config: { document: TDocument };\n configRequired: true;\n }>({\n dataType: () => \"text\",\n toDriver: (value) => JSON.stringify(value),\n fromDriver: (value: TDocument | string) => {\n return value && typeof value === \"string\" ? JSON.parse(value) : value;\n },\n })(name, { document })\n .$type<Static<TDocument>>();\n\n sqliteDateTime = pg.customType<{\n data: string;\n driverData: number;\n configRequired: true;\n }>({\n dataType: () => \"integer\",\n toDriver: (value) => new Date(value).getTime(),\n fromDriver: (value) => {\n return new Date(value).toISOString();\n },\n });\n\n sqliteBool = pg.customType<{\n data: boolean;\n driverData: number;\n configRequired: true;\n }>({\n dataType: () => \"integer\",\n toDriver: (value) => (value ? 1 : 0),\n fromDriver: (value) => value === 1,\n });\n\n sqliteDate = pg.customType<{\n data: string;\n driverData: number;\n configRequired: true;\n }>({\n dataType: () => \"integer\",\n toDriver: (value) => new Date(value).getTime(),\n fromDriver: (value) => {\n return new Date(value).toISOString().split(\"T\")[0];\n },\n });\n}\n\nexport type SchemaToSqliteBuilder<T extends TObject> = {\n [key in keyof T[\"properties\"]]: SQLiteColumnBuilderBase;\n};\n","import type { Database } from \"bun:sqlite\";\nimport { mkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport {\n $atom,\n $env,\n $hook,\n $inject,\n $state,\n AlephaError,\n type Static,\n t,\n} from \"alepha\";\nimport type { BunSQLiteDatabase } from \"drizzle-orm/bun-sqlite\";\nimport type { PgDatabase } from \"drizzle-orm/pg-core\";\nimport { databaseEnvSchema } from \"../../schemas/databaseEnvSchema.ts\";\nimport { SqliteModelBuilder } from \"../../services/SqliteModelBuilder.ts\";\nimport { DatabaseProvider, type SQLLike } from \"./DatabaseProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst envSchema = databaseEnvSchema;\n\n/**\n * Configuration options for the Bun SQLite database provider.\n */\nexport const bunSqliteOptions = $atom({\n name: \"alepha.postgres.bun-sqlite.options\",\n schema: t.object({\n path: t.optional(\n t.string({\n description:\n \"Filepath or :memory:. If empty, provider will use DATABASE_URL from env.\",\n }),\n ),\n }),\n default: {},\n});\n\nexport type BunSqliteProviderOptions = Static<typeof bunSqliteOptions.schema>;\n\ndeclare module \"alepha\" {\n interface State {\n [bunSqliteOptions.key]: BunSqliteProviderOptions;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Bun SQLite provider using Drizzle ORM with Bun's native SQLite client.\n *\n * This provider uses Bun's built-in `bun:sqlite` for SQLite connections,\n * which provides excellent performance on the Bun runtime.\n *\n * @example\n * ```ts\n * // Set DATABASE_URL environment variable\n * // DATABASE_URL=sqlite://./my-database.db\n *\n * // Or configure programmatically\n * alepha.with({\n * provide: DatabaseProvider,\n * use: BunSqliteProvider,\n * });\n *\n * // Or use options atom\n * alepha.store.mut(bunSqliteOptions, (old) => ({\n * ...old,\n * path: \":memory:\",\n * }));\n * ```\n */\nexport class BunSqliteProvider extends DatabaseProvider {\n protected readonly env = $env(envSchema);\n protected readonly builder = $inject(SqliteModelBuilder);\n protected readonly options = $state(bunSqliteOptions);\n\n protected sqlite?: Database;\n protected bunDb?: BunSQLiteDatabase;\n\n public get name() {\n return \"sqlite\";\n }\n\n public override readonly dialect = \"sqlite\";\n\n public override get url(): string {\n const path = this.options.path ?? this.env.DATABASE_URL;\n if (path) {\n if (path.startsWith(\"postgres://\")) {\n throw new AlephaError(\n \"Postgres URL is not supported for SQLite provider.\",\n );\n }\n return path;\n }\n\n if (this.alepha.isTest() || this.alepha.isServerless()) {\n return \":memory:\";\n } else {\n return \"node_modules/.alepha/bun-sqlite.db\";\n }\n }\n\n public override get db(): PgDatabase<any> {\n if (!this.bunDb) {\n throw new AlephaError(\"Database not initialized\");\n }\n\n return this.bunDb as unknown as PgDatabase<any>;\n }\n\n public override get nativeConnection(): unknown {\n return this.sqlite;\n }\n\n public override async execute(\n query: SQLLike,\n ): Promise<Array<Record<string, unknown>>> {\n return (this.bunDb as BunSQLiteDatabase).all(query);\n }\n\n protected readonly onStart = $hook({\n on: \"start\",\n handler: async () => {\n // Check if we're running in Bun\n if (typeof Bun === \"undefined\") {\n throw new AlephaError(\n \"BunSqliteProvider requires the Bun runtime. Use NodeSqliteProvider for Node.js.\",\n );\n }\n\n const { Database } = await import(\"bun:sqlite\");\n const { drizzle } = await import(\"drizzle-orm/bun-sqlite\");\n\n const filepath = this.url.replace(\"sqlite://\", \"\").replace(\"sqlite:\", \"\");\n\n if (filepath !== \":memory:\" && filepath !== \"\") {\n const dir = dirname(filepath);\n if (dir) {\n await mkdir(dir, { recursive: true }).catch(() => null);\n }\n }\n\n this.sqlite = new Database(filepath);\n\n this.bunDb = drizzle({\n client: this.sqlite,\n logger: {\n logQuery: (query: string, params: unknown[]) => {\n this.log.trace(query, { params });\n },\n },\n });\n\n // Never migrate in serverless mode - migrations should be applied during deployment\n if (!this.alepha.isServerless()) {\n await this.migrate();\n }\n\n this.log.info(`Using Bun SQLite database at ${filepath}`);\n },\n });\n\n protected readonly onStop = $hook({\n on: \"stop\",\n priority: \"last\",\n handler: async () => {\n if (this.sqlite) {\n this.log.debug(\"Closing Bun SQLite connection...\");\n this.sqlite.close();\n this.sqlite = undefined;\n this.bunDb = undefined;\n this.log.info(\"Bun SQLite connection closed\");\n }\n },\n });\n\n protected async executeMigrations(migrationsFolder: string): Promise<void> {\n const { migrate } = await import(\"drizzle-orm/bun-sqlite/migrator\");\n await migrate(this.bunDb!, { migrationsFolder });\n }\n}\n","import { $env, $hook, $inject, AlephaError, t } from \"alepha\";\nimport type { DrizzleD1Database } from \"drizzle-orm/d1\";\nimport type { PgDatabase } from \"drizzle-orm/pg-core\";\nimport { SqliteModelBuilder } from \"../../services/SqliteModelBuilder.ts\";\nimport { DatabaseProvider, type SQLLike } from \"./DatabaseProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * D1Database interface matching Cloudflare's D1 API.\n */\nexport interface D1Database {\n prepare(query: string): D1PreparedStatement;\n batch<T = unknown>(statements: D1PreparedStatement[]): Promise<T[]>;\n exec(query: string): Promise<D1ExecResult>;\n dump(): Promise<ArrayBuffer>;\n}\n\nexport interface D1PreparedStatement {\n bind(...values: unknown[]): D1PreparedStatement;\n first<T = unknown>(colName?: string): Promise<T | null>;\n run(): Promise<D1Result>;\n all<T = unknown>(): Promise<D1Result<T>>;\n raw<T = unknown>(): Promise<T[]>;\n}\n\nexport interface D1Result<T = unknown> {\n results: T[];\n success: boolean;\n meta: {\n duration: number;\n changes: number;\n last_row_id: number;\n served_by: string;\n internal_stats: unknown;\n };\n}\n\nexport interface D1ExecResult {\n count: number;\n duration: number;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Cloudflare D1 SQLite provider using Drizzle ORM.\n */\nexport class CloudflareD1Provider extends DatabaseProvider {\n protected readonly builder = $inject(SqliteModelBuilder);\n protected readonly env = $env(\n t.object({\n DATABASE_URL: t.string({\n description: \"Expect to be 'd1://binding'\",\n }),\n }),\n );\n\n protected d1?: D1Database;\n protected drizzleDb?: DrizzleD1Database;\n\n public get name() {\n return \"sqlite\";\n }\n\n public get driver() {\n return \"d1\";\n }\n\n public override readonly dialect = \"sqlite\";\n\n public override get url(): string {\n return this.env.DATABASE_URL;\n }\n\n public override get db(): PgDatabase<any> {\n if (!this.drizzleDb) {\n throw new AlephaError(\"D1 database not initialized\");\n }\n\n return this.drizzleDb as unknown as PgDatabase<any>;\n }\n\n public override async execute(\n query: SQLLike,\n ): Promise<Array<Record<string, unknown>>> {\n const { rows } = await (this.db as any).run(query);\n return rows;\n }\n\n /**\n * D1 does not support SQL-level transactions (BEGIN/COMMIT/ROLLBACK).\n * It rejects these statements and requires the JS `batch()` API for atomic\n * multi-statement operations instead.\n *\n * @see https://developers.cloudflare.com/d1/worker-api/d1-database/#batch-statements\n * @see https://github.com/drizzle-team/drizzle-orm/issues/2463\n */\n public override get supportsTransactions(): boolean {\n return false;\n }\n\n protected readonly onStart = $hook({\n on: \"start\",\n handler: async () => {\n try {\n const [bindingName] = this.env.DATABASE_URL.replace(\"d1://\", \"\").split(\n \":\",\n );\n const cloudflareEnv = this.alepha.get(\"cloudflare.env\") as\n | Record<string, unknown>\n | undefined;\n if (!cloudflareEnv) {\n throw new AlephaError(\n \"Cloudflare Workers environment not found in Alepha store under 'cloudflare.env'.\",\n );\n }\n\n const binding = cloudflareEnv[bindingName] as D1Database;\n if (!binding) {\n throw new AlephaError(\n `D1 binding '${bindingName}' not found in Cloudflare Workers environment.`,\n );\n }\n\n this.d1 = binding;\n\n // Dynamic import to avoid crashes when not on Cloudflare\n const { drizzle } = await import(\"drizzle-orm/d1\");\n\n this.drizzleDb = drizzle(this.d1) as DrizzleD1Database;\n\n // Never migrate in serverless mode - D1 migrations must be applied\n // via `wrangler d1 migrations apply` before deployment\n if (!this.alepha.isServerless()) {\n await this.migrate();\n }\n\n this.log.info(\"Using Cloudflare D1 database\");\n } catch (error) {\n // Log the full error for debugging since Cloudflare Workers\n // doesn't properly display error causes\n const errorMessage =\n error instanceof Error\n ? `${error.message}${error.stack ? `\\n${error.stack}` : \"\"}`\n : String(error);\n this.log.error(`D1 initialization failed: ${errorMessage}`);\n throw error;\n }\n },\n });\n\n protected async executeMigrations(migrationsFolder: string): Promise<void> {\n this.log.debug(`Running D1 migrations from '${migrationsFolder}'...`);\n try {\n // Dynamic import for D1 migrator\n const { migrate } = await import(\"drizzle-orm/d1/migrator\");\n await migrate(this.db as any, { migrationsFolder });\n this.log.debug(\"D1 migrations completed successfully\");\n } catch (error) {\n const errorMessage =\n error instanceof Error\n ? `${error.name}: ${error.message}`\n : String(error);\n throw new AlephaError(\n `D1 migration failed from '${migrationsFolder}': ${errorMessage}`,\n { cause: error },\n );\n }\n }\n\n /**\n * D1 doesn't support push-based schema sync.\n * Always use file-based migrations regardless of environment.\n */\n public override async migrate(): Promise<void> {\n const migrationsFolder = this.getMigrationsFolder();\n try {\n await this.executeMigrations(migrationsFolder);\n } catch (error) {\n if (this.alepha.isTest()) {\n this.log.warn(\n \"D1 migrations failed in test environment - ensure migrations exist\",\n );\n } else {\n throw error;\n }\n }\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\n/**\n * Error thrown when a column does not exist.\n *\n * This typically happens when:\n * - Column name is misspelled\n * - Migrations haven't been run\n * - Using wrong schema version\n */\nexport class DbColumnNotFoundError extends DbError {\n readonly name = \"DbColumnNotFoundError\";\n readonly status = 500;\n\n /**\n * The column that was not found.\n */\n readonly column?: string;\n\n /**\n * The table where the column was expected.\n */\n readonly table?: string;\n\n constructor(\n message: string,\n cause?: unknown,\n options?: { column?: string; table?: string },\n ) {\n super(message, cause);\n this.column = options?.column;\n this.table = options?.table;\n }\n\n /**\n * Parse a database column not found error and create a DbColumnNotFoundError.\n * Supports both PostgreSQL and SQLite error formats.\n */\n static fromDatabaseError(error: Error): DbColumnNotFoundError {\n const message = error.message;\n\n // PostgreSQL format:\n // 'column \"foo\" does not exist'\n // 'column \"foo\" of relation \"users\" does not exist'\n const pgMatch = message.match(\n /column \"([^\"]+)\"(?: of relation \"([^\"]+)\")? does not exist/,\n );\n\n if (pgMatch) {\n const column = pgMatch[1];\n const table = pgMatch[2];\n const msg = table\n ? `Column '${column}' does not exist in table '${table}'`\n : `Column '${column}' does not exist`;\n return new DbColumnNotFoundError(msg, error, { column, table });\n }\n\n // SQLite format:\n // 'no such column: foo'\n // 'no such column: users.foo'\n const sqliteMatch = message.match(/no such column: (?:(\\S+)\\.)?(\\S+)/);\n\n if (sqliteMatch) {\n const table = sqliteMatch[1];\n const column = sqliteMatch[2];\n const msg = table\n ? `Column '${column}' does not exist in table '${table}'`\n : `Column '${column}' does not exist`;\n return new DbColumnNotFoundError(msg, error, { column, table });\n }\n\n return new DbColumnNotFoundError(\"Column does not exist\", error);\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\nexport class DbConflictError extends DbError {\n readonly name = \"DbConflictError\";\n readonly status = 409;\n}\n","import { DbError } from \"./DbError.ts\";\n\n/**\n * Error thrown when a deadlock is detected.\n *\n * This happens when two or more transactions are waiting for each other\n * to release locks. The database automatically aborts one transaction\n * to resolve the deadlock.\n *\n * This error is useful for implementing retry logic.\n */\nexport class DbDeadlockError extends DbError {\n readonly name = \"DbDeadlockError\";\n readonly status = 409;\n\n /**\n * Whether this error is retryable.\n * Deadlocks are typically safe to retry.\n */\n readonly retryable = true;\n\n /**\n * Parse a database deadlock error message and create a DbDeadlockError.\n * Supports PostgreSQL. SQLite doesn't have true deadlocks (uses SQLITE_BUSY instead).\n */\n static fromDatabaseError(error: Error): DbDeadlockError {\n return new DbDeadlockError(\n \"Transaction deadlock detected. Please retry the operation.\",\n error,\n );\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\nexport class DbEntityNotFoundError extends DbError {\n readonly name = \"DbEntityNotFoundError\";\n readonly status = 404;\n\n constructor(entityName: string) {\n super(`Entity from '${entityName}' was not found`);\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\n/**\n * Error thrown when a foreign key constraint is violated.\n *\n * This typically happens when trying to delete an entity that is\n * referenced by another entity.\n */\nexport class DbForeignKeyError extends DbError {\n readonly name = \"DbForeignKeyError\";\n readonly status = 409;\n\n /**\n * The table that references the entity being deleted.\n */\n readonly referencingTable?: string;\n\n /**\n * The constraint name that was violated.\n */\n readonly constraintName?: string;\n\n constructor(\n message: string,\n cause?: unknown,\n options?: { referencingTable?: string; constraintName?: string },\n ) {\n super(message, cause);\n this.referencingTable = options?.referencingTable;\n this.constraintName = options?.constraintName;\n }\n\n /**\n * Parse a database foreign key error message and create a DbForeignKeyError.\n * Supports both PostgreSQL and SQLite error formats.\n */\n static fromDatabaseError(error: Error, tableName: string): DbForeignKeyError {\n const message = error.message;\n\n // PostgreSQL format:\n // 'violates foreign key constraint \"reporting_alert_query_id_fk\" on table \"reporting_alert\"'\n const pgMatch = message.match(\n /violates foreign key constraint \"([^\"]+)\" on table \"([^\"]+)\"/,\n );\n\n if (pgMatch) {\n const constraintName = pgMatch[1];\n const referencingTable = pgMatch[2];\n\n return new DbForeignKeyError(\n `Cannot delete ${tableName}: it is referenced by ${referencingTable}`,\n error,\n { referencingTable, constraintName },\n );\n }\n\n // SQLite format:\n // 'FOREIGN KEY constraint failed' (no table name available)\n return new DbForeignKeyError(\n `Cannot delete ${tableName}: it is referenced by another entity`,\n error,\n );\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\n/**\n * Error thrown when a NOT NULL constraint is violated.\n *\n * This happens when inserting or updating a NULL value into a column\n * that has a NOT NULL constraint.\n */\nexport class DbNotNullError extends DbError {\n readonly name = \"DbNotNullError\";\n readonly status = 400;\n\n /**\n * The column that violated the NOT NULL constraint.\n */\n readonly column?: string;\n\n /**\n * The table containing the column.\n */\n readonly table?: string;\n\n constructor(\n message: string,\n cause?: unknown,\n options?: { column?: string; table?: string },\n ) {\n super(message, cause);\n this.column = options?.column;\n this.table = options?.table;\n }\n\n /**\n * Parse a database NOT NULL error message and create a DbNotNullError.\n * Supports both PostgreSQL and SQLite error formats.\n */\n static fromDatabaseError(error: Error, tableName: string): DbNotNullError {\n const message = error.message;\n\n // PostgreSQL format:\n // 'null value in column \"email\" of relation \"users\" violates not-null constraint'\n const pgMatch = message.match(\n /null value in column \"([^\"]+)\" of relation \"([^\"]+)\" violates not-null constraint/,\n );\n\n if (pgMatch) {\n const column = pgMatch[1];\n const table = pgMatch[2];\n return new DbNotNullError(\n `Column '${column}' in '${table}' cannot be null`,\n error,\n { column, table },\n );\n }\n\n // SQLite format:\n // 'NOT NULL constraint failed: users.email'\n const sqliteMatch = message.match(\n /NOT NULL constraint failed: ([^.]+)\\.(\\S+)/,\n );\n\n if (sqliteMatch) {\n const table = sqliteMatch[1];\n const column = sqliteMatch[2];\n return new DbNotNullError(\n `Column '${column}' in '${table}' cannot be null`,\n error,\n { column, table },\n );\n }\n\n return new DbNotNullError(\n `A required field in '${tableName}' cannot be null`,\n error,\n );\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\n/**\n * Error thrown when a table does not exist.\n *\n * This typically happens when:\n * - Migrations haven't been run\n * - Table name is misspelled\n * - Wrong database/schema is being used\n */\nexport class DbTableNotFoundError extends DbError {\n readonly name = \"DbTableNotFoundError\";\n readonly status = 500;\n\n /**\n * The table that was not found.\n */\n readonly table?: string;\n\n constructor(message: string, cause?: unknown, options?: { table?: string }) {\n super(message, cause);\n this.table = options?.table;\n }\n\n /**\n * Parse a database table not found error and create a DbTableNotFoundError.\n * Supports both PostgreSQL and SQLite error formats.\n */\n static fromDatabaseError(error: Error): DbTableNotFoundError {\n const message = error.message;\n\n // PostgreSQL format:\n // 'relation \"users\" does not exist'\n const pgMatch = message.match(/relation \"([^\"]+)\" does not exist/);\n\n if (pgMatch) {\n const table = pgMatch[1];\n return new DbTableNotFoundError(\n `Table '${table}' does not exist. Have you run migrations?`,\n error,\n { table },\n );\n }\n\n // SQLite format:\n // 'no such table: users'\n const sqliteMatch = message.match(/no such table: (\\S+)/);\n\n if (sqliteMatch) {\n const table = sqliteMatch[1];\n return new DbTableNotFoundError(\n `Table '${table}' does not exist. Have you run migrations?`,\n error,\n { table },\n );\n }\n\n return new DbTableNotFoundError(\n \"Table does not exist. Have you run migrations?\",\n error,\n );\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\n/**\n * Error thrown when there is a version mismatch.\n * It's thrown by {@link Repository#save} when the updated entity version does not match the one in the database.\n * This is used for optimistic concurrency control.\n */\nexport class DbVersionMismatchError extends DbError {\n readonly name = \"DbVersionMismatchError\";\n\n constructor(table: string, id: any) {\n super(`Version mismatch for table '${table}' and id '${id}'`);\n }\n}\n","import type { TObject, TSchema } from \"alepha\";\nimport type { PgSymbolKeys, PgSymbols } from \"../constants/PG_SYMBOLS.ts\";\n\n/**\n * Decorates a typebox schema with a Postgres attribute.\n *\n * > It's just a fancy way to add Symbols to a field.\n *\n * @example\n * ```ts\n * import { t } from \"alepha\";\n * import { PG_UPDATED_AT } from \"../constants/PG_SYMBOLS\";\n *\n * export const updatedAtSchema = pgAttr(\n * t.datetime(), PG_UPDATED_AT,\n * );\n * ```\n */\nexport const pgAttr = <T extends TSchema, Attr extends PgSymbolKeys>(\n type: T,\n attr: Attr,\n value?: PgSymbols[Attr],\n): PgAttr<T, Attr> => {\n Object.assign(type, { [attr]: value ?? {} });\n return type as PgAttr<T, Attr>;\n};\n\n/**\n * Retrieves the fields of a schema that have a specific attribute.\n */\nexport const getAttrFields = (\n schema: TObject,\n name: PgSymbolKeys,\n): PgAttrField[] => {\n const fields: Array<PgAttrField> = [];\n\n for (const key of Object.keys(schema.properties)) {\n const value = schema.properties[key];\n if (name in value) {\n fields.push({\n type: value as TSchema,\n key: key,\n data: (value as any)[name],\n });\n }\n }\n\n return fields;\n};\n\n/**\n * Type representation.\n */\nexport type PgAttr<T extends TSchema, TAttr extends PgSymbolKeys> = T & {\n [K in TAttr]: PgSymbols[K];\n};\n\nexport interface PgAttrField {\n key: string;\n type: TSchema;\n data: any;\n nested?: any[];\n one?: boolean;\n}\n","import { $inject } from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\n\n/**\n * Database query cache using a simple in-memory Map.\n *\n * Uses `{tableName}:{cacheKey}` as the storage key.\n * Provides per-table invalidation for write-through cache busting.\n *\n * This is intentionally self-contained (no external cache dependencies)\n * so the ORM module does not force `AlephaCache` on all consumers.\n */\nexport class DbCacheProvider {\n protected readonly dateTime = $inject(DateTimeProvider);\n protected readonly store = new Map<\n string,\n { value: unknown; expiresAt?: number }\n >();\n\n protected storeKey(tableName: string, cacheKey: string): string {\n return `${tableName}:${cacheKey}`;\n }\n\n /**\n * Get a cached query result.\n */\n public async get<T>(\n tableName: string,\n cacheKey: string,\n ): Promise<T | undefined> {\n const key = this.storeKey(tableName, cacheKey);\n const entry = this.store.get(key);\n\n if (!entry) return undefined;\n if (entry.expiresAt && this.dateTime.nowMillis() > entry.expiresAt) {\n this.store.delete(key);\n return undefined;\n }\n\n return entry.value as T;\n }\n\n /**\n * Store a query result in the cache.\n */\n public async set<T>(\n tableName: string,\n cacheKey: string,\n value: T,\n ttl?: number,\n ): Promise<void> {\n const key = this.storeKey(tableName, cacheKey);\n this.store.set(key, {\n value,\n expiresAt: ttl ? this.dateTime.nowMillis() + ttl : undefined,\n });\n }\n\n /**\n * Invalidate all cached queries for a table.\n */\n public async invalidateTable(tableName: string): Promise<void> {\n const prefix = `${tableName}:`;\n for (const key of this.store.keys()) {\n if (key.startsWith(prefix)) {\n this.store.delete(key);\n }\n }\n }\n}\n","import { type TObject, t, Value } from \"alepha\";\nimport { getTableName, type SQL, sql } from \"drizzle-orm\";\nimport type { PgSelectBase, PgTableWithColumns } from \"drizzle-orm/pg-core\";\nimport { isSQLWrapper } from \"drizzle-orm/sql/sql\";\nimport type { PgRelationMap } from \"../interfaces/PgQuery.ts\";\nimport type { EntityPrimitive } from \"../primitives/$entity.ts\";\nimport type { DatabaseProvider } from \"../providers/drivers/DatabaseProvider.ts\";\nimport type { PgJoin } from \"./QueryManager.ts\";\n\nexport class PgRelationManager {\n /**\n * Recursively build joins for the query builder based on the relations map\n */\n public buildJoins(\n provider: DatabaseProvider,\n builder: PgSelectBase<any, any, any>,\n joins: Array<PgJoin>,\n withRelations: PgRelationMap<TObject>,\n table: PgTableWithColumns<any>,\n parentKey?: string,\n ) {\n for (const [key, join] of Object.entries(withRelations)) {\n const from = provider.table(join.join as EntityPrimitive);\n const on = isSQLWrapper(join.on)\n ? (join.on as SQL)\n : sql`${table[join.on[0] as string]} = ${from[join.on[1].name]}`;\n\n if (join.type === \"right\") {\n builder.rightJoin(from, on);\n } else if (join.type === \"inner\") {\n builder.innerJoin(from, on);\n } else {\n builder.leftJoin(from, on);\n }\n\n joins.push({\n key,\n table: getTableName(from),\n schema: join.join.schema,\n col: (name: string) => from[name],\n parent: parentKey,\n });\n\n if (join.with) {\n this.buildJoins(\n provider,\n builder,\n joins,\n join.with,\n from,\n parentKey ? `${parentKey}.${key}` : key,\n );\n }\n }\n }\n\n /**\n * Map a row with its joined relations based on the joins definition\n */\n public mapRowWithJoins(\n record: Record<string, unknown>,\n row: Record<string, unknown>,\n schema: TObject,\n joins: PgJoin[],\n parentKey?: string,\n ) {\n for (const join of joins) {\n if (join.parent === parentKey) {\n const joinedData = row[join.table];\n // Set to undefined if all values in the joined table are null (left join with no match)\n if (this.isAllNull(joinedData)) {\n record[join.key] = undefined;\n } else {\n record[join.key] = joinedData;\n // Only process nested joins if the parent join has data\n this.mapRowWithJoins(\n record[join.key] as Record<string, unknown>,\n row,\n schema, // Don't need to pass modified schema, just for recursion\n joins,\n parentKey ? `${parentKey}.${join.key}` : join.key,\n );\n }\n }\n }\n return record;\n }\n\n /**\n * Check if all values in an object are null (indicates a left join with no match)\n */\n protected isAllNull(obj: unknown): boolean {\n if (obj === null || obj === undefined) return true;\n if (typeof obj !== \"object\") return false;\n return Object.values(obj).every((val) => val === null);\n }\n\n /**\n * Build a schema that includes all join properties recursively\n */\n public buildSchemaWithJoins(\n baseSchema: TObject,\n joins: PgJoin[],\n parentPath?: string,\n ): TObject {\n const schema = Value.Clone(baseSchema) as TObject;\n\n // Group joins by parent\n const joinsAtThisLevel = joins.filter((j) => j.parent === parentPath);\n\n for (const join of joinsAtThisLevel) {\n // Build the path for this join\n const joinPath = parentPath ? `${parentPath}.${join.key}` : join.key;\n\n // Find child joins\n const childJoins = joins.filter((j) => j.parent === joinPath);\n\n // If there are child joins, recursively build the schema\n let joinSchema = join.schema;\n if (childJoins.length > 0) {\n joinSchema = this.buildSchemaWithJoins(join.schema, joins, joinPath);\n }\n\n // Make the join optional (left joins may return null)\n schema.properties[join.key] = t.optional(joinSchema);\n }\n\n return schema;\n }\n}\n","import {\n $inject,\n Alepha,\n AlephaError,\n createPagination,\n type TObject,\n} from \"alepha\";\nimport {\n and,\n arrayContained,\n arrayContains,\n arrayOverlaps,\n between,\n eq,\n exists,\n gt,\n gte,\n ilike,\n inArray,\n isNotNull,\n isNull,\n isSQLWrapper,\n like,\n lt,\n lte,\n ne,\n not,\n notBetween,\n notExists,\n notIlike,\n notInArray,\n notLike,\n or,\n type SQL,\n type SQLWrapper,\n sql,\n} from \"drizzle-orm\";\nimport type { PgColumn } from \"drizzle-orm/pg-core\";\nimport type { FilterOperators } from \"../interfaces/FilterOperators.ts\";\nimport type {\n PgQueryWhere,\n PgQueryWhereOrSQL,\n} from \"../interfaces/PgQueryWhere.ts\";\n\nexport class QueryManager {\n protected readonly alepha = $inject(Alepha);\n\n /**\n * Convert a query object to a SQL query.\n */\n public toSQL(\n query: PgQueryWhereOrSQL<TObject>,\n options: {\n schema: TObject;\n col: (key: string) => PgColumn;\n joins?: PgJoin[];\n dialect: \"postgresql\" | \"sqlite\";\n },\n ): SQL | undefined {\n const { schema, col, joins } = options;\n const conditions: SQL[] = [];\n\n if (isSQLWrapper(query)) {\n conditions.push(query as SQL);\n } else {\n const keys = Object.keys(query) as Array<\n keyof PgQueryWhere<TObject> & string\n >;\n\n for (const key of keys) {\n const operator = query[key] as SQL;\n\n // Handle joins - check if this key matches a join at the current level\n if (\n typeof query[key] === \"object\" &&\n query[key] != null &&\n !Array.isArray(query[key]) &&\n joins?.length\n ) {\n // Find the join that matches this key (at the current level, without parent filtering)\n const matchingJoins = joins.filter((j) => j.key === key);\n if (matchingJoins.length > 0) {\n // Use the first matching join (they should all have the same schema)\n const join = matchingJoins[0];\n\n // Build the full path to this join\n const joinPath = join.parent ? `${join.parent}.${key}` : key;\n\n // Find child joins: those whose parent starts with this join's path\n const childJoins = joins.filter((j) => {\n if (!j.parent) return false;\n // Child's parent should be exactly our path, or start with our path + \".\"\n return (\n j.parent === joinPath || j.parent.startsWith(`${joinPath}.`)\n );\n });\n\n // For recursion, we need to restructure child joins\n // Remove the current path prefix from parent keys\n const recursiveJoins = childJoins.map((j) => {\n const newParent =\n j.parent === joinPath\n ? undefined\n : j.parent!.substring(joinPath.length + 1);\n return {\n ...j,\n parent: newParent,\n };\n });\n\n const sql = this.toSQL(query[key], {\n schema: join.schema,\n col: join.col,\n joins: recursiveJoins.length > 0 ? recursiveJoins : undefined,\n dialect: options.dialect,\n });\n if (sql) {\n conditions.push(sql);\n }\n continue;\n }\n }\n\n if (Array.isArray(operator)) {\n const operations: SQL[] = operator\n .map((it) => {\n if (isSQLWrapper(it)) {\n return it as SQL;\n }\n return this.toSQL(it as PgQueryWhere<TObject>, {\n schema,\n col,\n joins, // Pass joins through recursively\n dialect: options.dialect,\n });\n })\n .filter((it) => it != null);\n\n if (key === \"and\") {\n return and(...operations);\n }\n\n if (key === \"or\") {\n return or(...operations);\n }\n }\n\n if (key === \"not\") {\n const where = this.toSQL(operator as PgQueryWhereOrSQL<TObject>, {\n schema,\n col,\n joins, // Pass joins through recursively\n dialect: options.dialect,\n });\n if (where) {\n conditions.push(not(where));\n }\n continue;\n }\n\n if (key === \"exists\") {\n conditions.push(exists(operator as SQLWrapper));\n continue;\n }\n\n if (key === \"notExists\") {\n conditions.push(notExists(operator as SQLWrapper));\n continue;\n }\n\n if (operator != null) {\n const column = col(key);\n const sql = this.mapOperatorToSql(\n operator,\n column,\n schema,\n key,\n options.dialect,\n );\n if (sql) {\n conditions.push(sql);\n }\n }\n }\n }\n\n if (conditions.length === 1) {\n return conditions[0];\n }\n\n return and(...conditions);\n }\n\n /**\n * Check if an object has any filter operator properties.\n */\n protected hasFilterOperatorProperties(obj: any): boolean {\n if (!obj || typeof obj !== \"object\") return false;\n\n const filterOperatorKeys = [\n \"eq\",\n \"ne\",\n \"gt\",\n \"gte\",\n \"lt\",\n \"lte\",\n \"inArray\",\n \"notInArray\",\n \"isNull\",\n \"isNotNull\",\n \"like\",\n \"notLike\",\n \"ilike\",\n \"notIlike\",\n \"contains\",\n \"startsWith\",\n \"endsWith\",\n \"between\",\n \"notBetween\",\n \"arrayContains\",\n \"arrayContained\",\n \"arrayOverlaps\",\n ];\n\n return filterOperatorKeys.some((key) => key in obj);\n }\n\n /**\n * Map a filter operator to a SQL query.\n */\n public mapOperatorToSql(\n operator: FilterOperators<any> | any,\n column: PgColumn,\n columnSchema?: TObject,\n columnName?: string,\n dialect: \"postgresql\" | \"sqlite\" = \"postgresql\",\n ): SQL | undefined {\n // Helper function to encode a value for the specific column\n const encodeValue = (value: any): any => {\n if (value == null) {\n return value;\n }\n\n // If we have schema information, encode the value properly\n if (columnSchema && columnName) {\n try {\n const fieldSchema = columnSchema.properties[columnName];\n if (fieldSchema) {\n // Encode the value using the drizzle codec\n // This converts application values (like Dayjs) to database values (like ISO strings)\n return this.alepha.codec.encode(fieldSchema, value, {\n encoder: \"drizzle\",\n });\n }\n } catch (error) {\n // If encoding fails, fall back to the original value\n // This ensures backward compatibility\n }\n }\n\n return value;\n };\n\n // Helper function to encode array values\n const encodeArray = (values: any[]): any[] => {\n return values.map((v) => encodeValue(v));\n };\n\n // If operator is not an object, OR it's an object but doesn't have any filter operator properties,\n // treat it as a direct value (e.g., string, number, Date, Dayjs, etc.)\n if (\n typeof operator !== \"object\" ||\n operator == null ||\n !this.hasFilterOperatorProperties(operator)\n ) {\n return eq(column, encodeValue(operator));\n }\n\n const conditions: SQL[] = [];\n\n if (operator?.eq != null) {\n conditions.push(eq(column, encodeValue(operator.eq)));\n }\n\n if (operator?.ne != null) {\n conditions.push(ne(column, encodeValue(operator.ne)));\n }\n\n if (operator?.gt != null) {\n conditions.push(gt(column, encodeValue(operator.gt)));\n }\n\n if (operator?.gte != null) {\n conditions.push(gte(column, encodeValue(operator.gte)));\n }\n\n if (operator?.lt != null) {\n conditions.push(lt(column, encodeValue(operator.lt)));\n }\n\n if (operator?.lte != null) {\n conditions.push(lte(column, encodeValue(operator.lte)));\n }\n\n if (operator?.inArray != null) {\n if (!Array.isArray(operator.inArray) || operator.inArray.length === 0) {\n throw new AlephaError(\"inArray operator requires at least one value\");\n }\n conditions.push(inArray(column, encodeArray(operator.inArray)));\n }\n\n if (operator?.notInArray != null) {\n if (\n !Array.isArray(operator.notInArray) ||\n operator.notInArray.length === 0\n ) {\n throw new AlephaError(\n \"notInArray operator requires at least one value\",\n );\n }\n conditions.push(notInArray(column, encodeArray(operator.notInArray)));\n }\n\n if (operator?.isNull != null) {\n conditions.push(isNull(column));\n }\n\n if (operator?.isNotNull != null) {\n conditions.push(isNotNull(column));\n }\n\n if (operator?.like != null) {\n conditions.push(like(column, encodeValue(operator.like)));\n }\n\n if (operator?.notLike != null) {\n conditions.push(notLike(column, encodeValue(operator.notLike)));\n }\n\n if (operator?.ilike != null) {\n if (dialect === \"sqlite\") {\n // SQLite doesn't have ilike, use LOWER() for case-insensitive matching\n conditions.push(\n sql`LOWER(${column}) LIKE LOWER(${encodeValue(operator.ilike)})`,\n );\n } else {\n conditions.push(ilike(column, encodeValue(operator.ilike)));\n }\n }\n\n if (operator?.notIlike != null) {\n if (dialect === \"sqlite\") {\n // SQLite doesn't have ilike, use LOWER() for case-insensitive matching\n conditions.push(\n sql`LOWER(${column}) NOT LIKE LOWER(${encodeValue(operator.notIlike)})`,\n );\n } else {\n conditions.push(notIlike(column, encodeValue(operator.notIlike)));\n }\n }\n\n if (operator?.contains != null) {\n // Escape LIKE special characters to prevent wildcard injection\n const escapedValue = String(operator.contains)\n .replace(/\\\\/g, \"\\\\\\\\\") // Escape backslash first\n .replace(/%/g, \"\\\\%\") // Escape %\n .replace(/_/g, \"\\\\_\"); // Escape _\n\n if (dialect === \"sqlite\") {\n // SQLite doesn't have ilike, use LOWER() for case-insensitive matching\n // ESCAPE '\\\\' is required for SQLite to recognize backslash as escape character\n conditions.push(\n sql`LOWER(${column}) LIKE LOWER(${encodeValue(`%${escapedValue}%`)}) ESCAPE '\\\\'`,\n );\n } else {\n conditions.push(ilike(column, encodeValue(`%${escapedValue}%`)));\n }\n }\n\n if (operator?.startsWith != null) {\n // Escape LIKE special characters to prevent wildcard injection\n const escapedValue = String(operator.startsWith)\n .replace(/\\\\/g, \"\\\\\\\\\") // Escape backslash first\n .replace(/%/g, \"\\\\%\") // Escape %\n .replace(/_/g, \"\\\\_\"); // Escape _\n\n if (dialect === \"sqlite\") {\n // SQLite doesn't have ilike, use LOWER() for case-insensitive matching\n conditions.push(\n sql`LOWER(${column}) LIKE LOWER(${encodeValue(`${escapedValue}%`)}) ESCAPE '\\\\'`,\n );\n } else {\n conditions.push(ilike(column, encodeValue(`${escapedValue}%`)));\n }\n }\n\n if (operator?.endsWith != null) {\n // Escape LIKE special characters to prevent wildcard injection\n const escapedValue = String(operator.endsWith)\n .replace(/\\\\/g, \"\\\\\\\\\") // Escape backslash first\n .replace(/%/g, \"\\\\%\") // Escape %\n .replace(/_/g, \"\\\\_\"); // Escape _\n\n if (dialect === \"sqlite\") {\n // SQLite doesn't have ilike, use LOWER() for case-insensitive matching\n conditions.push(\n sql`LOWER(${column}) LIKE LOWER(${encodeValue(`%${escapedValue}`)}) ESCAPE '\\\\'`,\n );\n } else {\n conditions.push(ilike(column, encodeValue(`%${escapedValue}`)));\n }\n }\n\n if (operator?.between != null) {\n if (!Array.isArray(operator.between) || operator.between.length !== 2) {\n throw new AlephaError(\n \"between operator requires exactly 2 values [min, max]\",\n );\n }\n conditions.push(\n between(\n column,\n encodeValue(operator.between[0]),\n encodeValue(operator.between[1]),\n ),\n );\n }\n\n if (operator?.notBetween != null) {\n if (\n !Array.isArray(operator.notBetween) ||\n operator.notBetween.length !== 2\n ) {\n throw new AlephaError(\n \"notBetween operator requires exactly 2 values [min, max]\",\n );\n }\n conditions.push(\n notBetween(\n column,\n encodeValue(operator.notBetween[0]),\n encodeValue(operator.notBetween[1]),\n ),\n );\n }\n\n if (operator?.arrayContains != null) {\n conditions.push(\n arrayContains(column, encodeValue(operator.arrayContains)),\n );\n }\n\n if (operator?.arrayContained != null) {\n conditions.push(\n arrayContained(column, encodeValue(operator.arrayContained)),\n );\n }\n\n if (operator?.arrayOverlaps != null) {\n conditions.push(\n arrayOverlaps(column, encodeValue(operator.arrayOverlaps)),\n );\n }\n\n if (conditions.length === 0) {\n return undefined;\n }\n\n if (conditions.length === 1) {\n return conditions[0];\n }\n\n return and(...conditions);\n }\n\n /**\n * Parse pagination sort string to orderBy format.\n * Format: \"firstName,-lastName\" -> [{ column: \"firstName\", direction: \"asc\" }, { column: \"lastName\", direction: \"desc\" }]\n * - Columns separated by comma\n * - Prefix with '-' for DESC direction\n *\n * @param sort Pagination sort string\n * @returns OrderBy array or single object\n */\n public parsePaginationSort(\n sort: string,\n ):\n | Array<{ column: string; direction: \"asc\" | \"desc\" }>\n | { column: string; direction: \"asc\" | \"desc\" } {\n const fields = sort.split(\",\").map((field) => field.trim());\n\n const orderByClauses = fields.map((field) => {\n if (field.startsWith(\"-\")) {\n return {\n column: field.substring(1),\n direction: \"desc\" as const,\n };\n }\n return {\n column: field,\n direction: \"asc\" as const,\n };\n });\n\n // Return single object if only one field, array if multiple\n return orderByClauses.length === 1 ? orderByClauses[0] : orderByClauses;\n }\n\n /**\n * Normalize orderBy parameter to array format.\n * Supports 3 modes:\n * 1. String: \"name\" -> [{ column: \"name\", direction: \"asc\" }]\n * 2. Object: { column: \"name\", direction: \"desc\" } -> [{ column: \"name\", direction: \"desc\" }]\n * 3. Array: [{ column: \"name\" }, { column: \"age\", direction: \"desc\" }] -> normalized array\n *\n * @param orderBy The orderBy parameter\n * @returns Normalized array of order by clauses\n */\n public normalizeOrderBy(\n orderBy: any,\n ): Array<{ column: string; direction: \"asc\" | \"desc\" }> {\n // Mode 1: String -> single column, ASC by default\n if (typeof orderBy === \"string\") {\n return [{ column: orderBy, direction: \"asc\" }];\n }\n\n // Mode 2: Single object -> convert to array\n if (!Array.isArray(orderBy) && typeof orderBy === \"object\") {\n return [\n {\n column: orderBy.column,\n direction: orderBy.direction ?? \"asc\",\n },\n ];\n }\n\n // Mode 3: Array -> normalize each item with default direction\n if (Array.isArray(orderBy)) {\n return orderBy.map((item) => ({\n column: item.column,\n direction: item.direction ?? \"asc\",\n }));\n }\n\n return [];\n }\n\n /**\n * Create a pagination object.\n *\n * @deprecated Use `createPagination` from alepha instead.\n * This method now delegates to the framework-level helper.\n *\n * @param entities The entities to paginate.\n * @param limit The limit of the pagination.\n * @param offset The offset of the pagination.\n * @param sort Optional sort metadata to include in response.\n */\n public createPagination<T>(\n entities: T[],\n limit = 10,\n offset = 0,\n sort?: Array<{ column: string; direction: \"asc\" | \"desc\" }>,\n ) {\n return createPagination(entities, limit, offset, sort);\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface PgJoin {\n table: string;\n schema: TObject;\n key: string;\n col: (key: string) => PgColumn;\n parent?: string;\n}\n","import {\n $inject,\n Alepha,\n AlephaError,\n type Page,\n type PageQuery,\n type Static,\n type StaticEncode,\n type TObject,\n type TSchema,\n t,\n} from \"alepha\";\nimport { type DateTime, DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { currentUserAtom } from \"alepha/security\";\nimport {\n asc,\n avg,\n count,\n desc,\n and as drizzleAnd,\n eq as drizzleEq,\n gt,\n gte,\n lt,\n lte,\n max,\n min,\n ne,\n type SQL,\n sum,\n} from \"drizzle-orm\";\nimport type {\n LockConfig,\n LockStrength,\n PgColumn,\n PgDatabase,\n PgInsertValue,\n PgTable,\n PgTableWithColumns,\n PgTransaction,\n PgUpdateSetSource,\n} from \"drizzle-orm/pg-core\";\nimport type { PgTransactionConfig } from \"drizzle-orm/pg-core/session\";\nimport {\n PG_DELETED_AT,\n PG_ORGANIZATION,\n PG_PRIMARY_KEY,\n PG_UPDATED_AT,\n PG_VERSION,\n} from \"../constants/PG_SYMBOLS.ts\";\nimport { DbColumnNotFoundError } from \"../errors/DbColumnNotFoundError.ts\";\nimport { DbConflictError } from \"../errors/DbConflictError.ts\";\nimport { DbDeadlockError } from \"../errors/DbDeadlockError.ts\";\nimport { DbEntityNotFoundError } from \"../errors/DbEntityNotFoundError.ts\";\nimport { DbError } from \"../errors/DbError.ts\";\nimport { DbForeignKeyError } from \"../errors/DbForeignKeyError.ts\";\nimport { DbNotNullError } from \"../errors/DbNotNullError.ts\";\nimport { DbTableNotFoundError } from \"../errors/DbTableNotFoundError.ts\";\nimport { DbVersionMismatchError } from \"../errors/DbVersionMismatchError.ts\";\nimport { getAttrFields, type PgAttrField } from \"../helpers/pgAttr.ts\";\nimport type {\n AggregateOp,\n AggregateQuery,\n AggregateResult,\n AggregateSelect,\n} from \"../interfaces/AggregateQuery.ts\";\nimport type {\n PgQuery,\n PgQueryRelations,\n PgRelationMap,\n PgStatic,\n} from \"../interfaces/PgQuery.ts\";\nimport type {\n PgQueryWhere,\n PgQueryWhereOrSQL,\n} from \"../interfaces/PgQueryWhere.ts\";\nimport type {\n EntityPrimitive,\n SchemaToTableConfig,\n} from \"../primitives/$entity.ts\";\nimport { DbCacheProvider } from \"../providers/DbCacheProvider.ts\";\nimport {\n DatabaseProvider,\n type SQLLike,\n} from \"../providers/drivers/DatabaseProvider.ts\";\nimport type { TObjectInsert } from \"../schemas/insertSchema.ts\";\nimport type { TObjectUpdate } from \"../schemas/updateSchema.ts\";\nimport { PgRelationManager } from \"./PgRelationManager.ts\";\nimport { type PgJoin, QueryManager } from \"./QueryManager.ts\";\n\nexport abstract class Repository<T extends TObject> {\n public readonly entity: EntityPrimitive<T>;\n public readonly provider: DatabaseProvider;\n\n protected readonly log = $logger();\n protected readonly relationManager = $inject(PgRelationManager);\n protected readonly queryManager = $inject(QueryManager);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly dbCache = new DbCacheProvider();\n protected readonly alepha = $inject(Alepha);\n\n static of<T extends TObject>(\n entity: EntityPrimitive<T>,\n provider = DatabaseProvider,\n ): new () => Repository<T> {\n return class InlineRepository extends Repository<T> {\n constructor() {\n super(entity, provider);\n }\n };\n }\n\n constructor(entity: EntityPrimitive<T>, provider = DatabaseProvider) {\n this.entity = entity;\n this.provider = this.alepha.inject(provider);\n this.provider.registerEntity(entity as EntityPrimitive);\n }\n\n /**\n * Represents the primary key of the table.\n * - Key is the name of the primary key column.\n * - Type is the type (TypeBox) of the primary key column.\n *\n * ID is mandatory. If the table does not have a primary key, it will throw an error.\n */\n public get id(): {\n type: TSchema;\n key: keyof T[\"properties\"];\n col: PgColumn;\n } {\n return this.getPrimaryKey(this.entity.schema);\n }\n\n /**\n * Get Drizzle table object.\n */\n public get table(): PgTableWithColumns<SchemaToTableConfig<T>> {\n return this.provider.table(this.entity);\n }\n\n /**\n * Get SQL table name. (from Drizzle table object)\n */\n public get tableName(): string {\n return this.entity.name;\n }\n\n /**\n * Getter for the database connection from the database provider.\n *\n * Automatically picks up a transaction from `alepha.store` if one was set\n * by `DatabaseProvider.transactional()`, so that all repository operations\n * inside a `transactional()` block participate in the same transaction.\n */\n protected get db(): PgDatabase<any> {\n const tx = this.alepha.get(\"alepha.orm.tx\");\n return tx ?? this.provider.db;\n }\n\n /**\n * Execute a SQL query.\n *\n * This method allows executing raw SQL queries against the database.\n * This is by far the easiest way to run custom queries that are not covered by the repository's built-in methods!\n *\n * You must use the `sql` tagged template function from Drizzle ORM to create the query. https://orm.drizzle.team/docs/sql\n *\n * @example\n * ```ts\n * class App {\n * repository = $repository({ ... });\n * async getAdults() {\n * const users = repository.table; // Drizzle table object\n * await repository.query(sql`SELECT * FROM ${users} WHERE ${users.age} > ${18}`);\n * // or better\n * await repository.query((users) => sql`SELECT * FROM ${users} WHERE ${users.age} > ${18}`);\n * }\n * }\n * ```\n */\n public async query<R extends TObject = T>(\n query:\n | SQLLike\n | ((\n table: PgTableWithColumns<SchemaToTableConfig<T>>,\n db: PgDatabase<any>,\n ) => SQLLike),\n schema?: R,\n ): Promise<Static<R>[]> {\n const raw =\n typeof query === \"function\" ? query(this.table, this.db) : query;\n\n if (typeof raw === \"string\" && raw.includes(\"[object Object]\")) {\n throw new AlephaError(\n \"Invalid SQL query. Did you forget to call the 'sql' function?\",\n );\n }\n\n // Only wrap database execution errors, not post-processing errors (e.g., TypeBoxError)\n let rows: Array<Record<string, unknown>>;\n try {\n rows = await this.provider.execute(raw);\n } catch (error) {\n throw this.handleError(error, \"Custom query has failed\");\n }\n\n if (rows == null) {\n return [];\n }\n\n if (!Array.isArray(rows)) {\n throw new DbError(\n \"Invalid query result. Expected an array of rows, but got: \" +\n JSON.stringify(rows),\n );\n }\n\n return rows.map((it) => {\n return this.clean(\n this.mapRawFieldsToEntity(it),\n schema ?? this.entity.schema,\n ) as Static<R>;\n });\n }\n\n protected columnNameMap?: Map<string, string>;\n\n /**\n * Map raw database fields to entity fields. (handles column name differences)\n */\n protected mapRawFieldsToEntity(row: Record<string, unknown>) {\n if (!this.columnNameMap) {\n this.columnNameMap = new Map();\n for (const colKey of Object.keys(this.table)) {\n this.columnNameMap.set(this.table[colKey].name, colKey);\n }\n }\n\n const entity: any = {};\n\n for (const key of Object.keys(row)) {\n entity[key] = row[key];\n const fieldKey = this.columnNameMap.get(key);\n if (fieldKey) {\n entity[fieldKey] = row[key];\n }\n }\n\n return entity;\n }\n\n /**\n * Get a Drizzle column from the table by his name.\n */\n protected col(name: keyof StaticEncode<T>): PgColumn {\n const column = (this.table as any)[name];\n if (!column) {\n throw new AlephaError(\n `Invalid access. Column '${String(name)}' not found in table '${this.tableName}'`,\n );\n }\n\n return column;\n }\n\n /**\n * Run a transaction.\n */\n public async transaction<T>(\n transaction: (\n tx: PgTransaction<any, Record<string, any>, any>,\n ) => Promise<T>,\n config?: PgTransactionConfig,\n ): Promise<T> {\n if (!this.provider.supportsTransactions) {\n throw new AlephaError(\n `Transactions are not supported with ${this.provider.driver} driver. Use $transactional() middleware instead, which gracefully degrades on unsupported drivers.`,\n );\n }\n\n this.log.debug(`Starting transaction on table ${this.tableName}`);\n return await this.db.transaction(transaction, config);\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Start a SELECT query on the table.\n */\n protected rawSelect(opts: StatementOptions = {}) {\n const db = opts.tx === null ? this.provider.db : (opts.tx ?? this.db);\n return db.select().from(this.table as PgTable);\n }\n\n /**\n * Start a SELECT DISTINCT query on the table.\n */\n protected rawSelectDistinct(\n opts: StatementOptions = {},\n columns: (keyof Static<T>)[] = [],\n ) {\n const db = opts.tx === null ? this.provider.db : (opts.tx ?? this.db);\n const table = this.table as PgTable;\n\n const fields: Record<string, any> = {};\n for (const column of columns) {\n if (typeof column === \"string\") {\n fields[column] = this.col(column);\n }\n }\n\n return db.selectDistinct(fields).from(table);\n }\n\n /**\n * Start an INSERT query on the table.\n */\n protected rawInsert(opts: StatementOptions = {}) {\n const db = opts.tx === null ? this.provider.db : (opts.tx ?? this.db);\n return db.insert(this.table);\n }\n\n /**\n * Start an UPDATE query on the table.\n */\n protected rawUpdate(opts: StatementOptions = {}) {\n const db = opts.tx === null ? this.provider.db : (opts.tx ?? this.db);\n return db.update(this.table);\n }\n\n /**\n * Start a DELETE query on the table.\n */\n protected rawDelete(opts: StatementOptions = {}) {\n const db = opts.tx === null ? this.provider.db : (opts.tx ?? this.db);\n return db.delete(this.table);\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Create a Drizzle `select` query based on a JSON query object.\n *\n * > This method is the base for `find`, `findOne`, `findById`, and `paginate`.\n */\n public async findMany<R extends PgRelationMap<T>>(\n query: PgQueryRelations<T, R> = {},\n opts: StatementOptions = {},\n ): Promise<PgStatic<T, R>[]> {\n // Check cache\n if (opts.cache) {\n const cacheKey = opts.cache.key ?? this.buildCacheKey(\"findMany\", query);\n const cached = await this.dbCache.get<PgStatic<T, R>[]>(\n this.tableName,\n cacheKey,\n );\n if (cached) return cached;\n }\n\n await this.alepha.events.emit(\"repository:read:before\", {\n tableName: this.tableName,\n query,\n });\n\n const columns = query.columns ?? query.distinct;\n const builder = query.distinct\n ? this.rawSelectDistinct(opts, query.distinct)\n : this.rawSelect(opts);\n\n const joins: Array<PgJoin> = [];\n if (query.with) {\n this.relationManager.buildJoins(\n this.provider,\n builder,\n joins,\n query.with,\n this.table,\n );\n }\n\n const where = this.withOrganization(\n this.withDeletedAt((query.where ?? {}) as PgQueryWhere<T>, opts),\n );\n\n builder.where(() => this.toSQL(where, joins));\n\n if (query.offset) {\n builder.offset(query.offset);\n\n // SQLite requires LIMIT when OFFSET is used\n if (this.provider.dialect === \"sqlite\" && !query.limit) {\n query.limit = 1000;\n }\n }\n\n if (query.limit) {\n builder.limit(query.limit);\n }\n\n if (query.orderBy) {\n const orderByClauses = this.queryManager.normalizeOrderBy(query.orderBy);\n builder.orderBy(\n ...orderByClauses.map((clause) =>\n clause.direction === \"desc\"\n ? desc(this.col(clause.column as string))\n : asc(this.col(clause.column as string)),\n ),\n );\n }\n\n if (query.groupBy) {\n builder.groupBy(...query.groupBy.map((key) => this.col(key as string)));\n }\n\n if (opts.for) {\n if (typeof opts.for === \"string\") {\n builder.for(opts.for);\n } else if (opts.for) {\n builder.for(opts.for.strength, opts.for.config);\n }\n }\n\n try {\n let rows = await builder.execute();\n\n let schema: TObject = this.entity.schema;\n if (columns) {\n schema = t.pick(schema, columns);\n }\n\n if (joins.length) {\n rows = rows.map((row: any) => {\n // Clone schema for each row to avoid mutation\n const rowSchema = { ...schema, properties: { ...schema.properties } };\n return this.relationManager.mapRowWithJoins(\n row[this.tableName],\n row,\n rowSchema,\n joins,\n );\n });\n }\n\n rows = rows.map((row) => {\n // For joined queries, build a schema that includes all nested joins\n if (joins.length) {\n const joinedSchema = this.relationManager.buildSchemaWithJoins(\n schema,\n joins,\n );\n // Clean the row with the full joined schema (including nested relations)\n return this.cleanWithJoins(row, joinedSchema, joins);\n }\n return this.clean(row, schema);\n });\n\n await this.alepha.events.emit(\"repository:read:after\", {\n tableName: this.tableName,\n query,\n entities: rows,\n });\n\n const result = rows as PgStatic<T, R>[];\n\n // Store in cache\n if (opts.cache) {\n const cacheKey =\n opts.cache.key ?? this.buildCacheKey(\"findMany\", query);\n await this.dbCache.set(\n this.tableName,\n cacheKey,\n result,\n opts.cache.ttl,\n );\n }\n\n return result;\n } catch (error) {\n throw this.handleError(error, \"Query select has failed\");\n }\n }\n\n /**\n * Find a single entity. Returns `undefined` if not found.\n */\n public async findOne<R extends PgRelationMap<T>>(\n query: Pick<PgQueryRelations<T, R>, \"with\" | \"where\">,\n opts: StatementOptions = {},\n ): Promise<PgStatic<T, R> | undefined> {\n const [entity] = await this.findMany({ limit: 1, ...query }, opts);\n return entity as PgStatic<T, R> | undefined;\n }\n\n /**\n * Find a single entity. Throws `DbEntityNotFoundError` if not found.\n */\n public async getOne<R extends PgRelationMap<T>>(\n query: Pick<PgQueryRelations<T, R>, \"with\" | \"where\">,\n opts: StatementOptions = {},\n ): Promise<PgStatic<T, R>> {\n const entity = await this.findOne(query, opts);\n\n if (!entity) {\n throw new DbEntityNotFoundError(this.tableName);\n }\n\n return entity;\n }\n\n /**\n * Find entities with pagination.\n *\n * It uses the same parameters as `find()`, but adds pagination metadata to the response.\n *\n * > Pagination CAN also do a count query to get the total number of elements.\n */\n public async paginate<R extends PgRelationMap<T>>(\n pagination: PageQuery = {},\n query: Omit<PgQueryRelations<T, R>, \"where\"> & {\n where?: PgQueryWhere<T>;\n } = {},\n opts: StatementOptions & { count?: boolean } = {},\n ): Promise<Page<PgStatic<T, R>>> {\n // Overflow-safe: pageQuerySchema constrains size to [1, 100] and page to >= 0.\n // With max size=100, page would need to exceed 2^45 to overflow Number.MAX_SAFE_INTEGER.\n const limit = query.limit ?? pagination.size ?? 10;\n const page = pagination.page ?? 0;\n const offset = query.offset ?? page * limit;\n\n let orderBy = query.orderBy;\n if (!query.orderBy && pagination.sort) {\n orderBy = this.queryManager.parsePaginationSort(pagination.sort) as any;\n }\n\n const now = this.dateTimeProvider.nowMillis();\n const timers = {\n query: now,\n count: now,\n };\n\n const tasks: Promise<any>[] = [];\n\n tasks.push(\n this.findMany(\n {\n offset,\n limit: limit + 1,\n orderBy,\n ...query,\n },\n opts,\n ).then((it) => {\n timers.query = this.dateTimeProvider.nowMillis() - timers.query;\n return it;\n }),\n );\n\n if (opts.count) {\n const countWhere = this.withOrganization(\n this.withDeletedAt((query.where ?? {}) as PgQueryWhere<T>, opts),\n );\n\n tasks.push(\n this.db.$count(this.table, this.toSQL(countWhere)).then((it) => {\n timers.count = this.dateTimeProvider.nowMillis() - timers.count;\n return it;\n }),\n );\n }\n\n const [entities, countResult] = await Promise.all(tasks);\n\n // Normalize orderBy to get sort metadata\n let sortMetadata:\n | Array<{ column: string; direction: \"asc\" | \"desc\" }>\n | undefined;\n if (orderBy) {\n sortMetadata = this.queryManager.normalizeOrderBy(orderBy);\n }\n\n const response = this.queryManager.createPagination<T>(\n entities,\n limit,\n offset,\n sortMetadata,\n );\n\n response.page.totalElements = countResult;\n if (countResult != null) {\n response.page.totalPages = Math.ceil(countResult / limit);\n }\n\n return response as Page<PgStatic<T, R>>;\n }\n\n /**\n * Find an entity by ID. Returns `undefined` if not found.\n */\n public async findById(\n id: string | number,\n opts: StatementOptions = {},\n ): Promise<Static<T> | undefined> {\n return await this.findOne(\n {\n where: this.getWhereId(id),\n },\n opts,\n );\n }\n\n /**\n * Find an entity by ID. Throws `DbEntityNotFoundError` if not found.\n */\n public async getById(\n id: string | number,\n opts: StatementOptions = {},\n ): Promise<Static<T>> {\n const entity = await this.findById(id, opts);\n\n if (!entity) {\n throw new DbEntityNotFoundError(this.tableName);\n }\n\n return entity;\n }\n\n /**\n * Helper to create a type-safe query object.\n */\n public createQuery(): PgQuery<T> {\n return {};\n }\n\n /**\n * Helper to create a type-safe where clause.\n */\n public createQueryWhere(): PgQueryWhere<T> {\n return {};\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Create an entity.\n *\n * @param data The entity to create.\n * @param opts The options for creating the entity.\n * @returns The ID of the created entity.\n */\n public async create(\n data: Static<TObjectInsert<T>>,\n opts: StatementOptions = {},\n ): Promise<Static<T>> {\n this.stampOrganization(data);\n await this.alepha.events.emit(\"repository:create:before\", {\n tableName: this.tableName,\n data,\n });\n\n try {\n const entity = await this.rawInsert(opts)\n .values(this.cast(data ?? {}, true))\n .returning(this.table)\n .then(([it]) => this.clean(it, this.entity.schema));\n\n this.dbCache\n .invalidateTable(this.tableName)\n .catch((err) => this.log.warn(\"Cache invalidation failed\", err));\n\n await this.alepha.events.emit(\"repository:create:after\", {\n tableName: this.tableName,\n data,\n entity,\n });\n\n return entity;\n } catch (error) {\n throw this.handleError(error, \"Insert query has failed\");\n }\n }\n\n /**\n * Create many entities.\n *\n * Inserts are batched in chunks of 1000 to avoid hitting database limits.\n *\n * @param values The entities to create.\n * @param opts The statement options.\n * @returns The created entities.\n */\n public async createMany(\n values: Array<Static<TObjectInsert<T>>>,\n opts: StatementOptions & { batchSize?: number } = {},\n ): Promise<Static<T>[]> {\n if (values.length === 0) {\n return [];\n }\n\n for (const value of values) {\n this.stampOrganization(value);\n }\n\n await this.alepha.events.emit(\"repository:create:before\", {\n tableName: this.tableName,\n data: values,\n });\n\n const batchSize = opts.batchSize ?? 1000;\n const allEntities: Static<T>[] = [];\n\n try {\n for (let i = 0; i < values.length; i += batchSize) {\n const batch = values.slice(i, i + batchSize);\n const entities = await this.rawInsert(opts)\n .values(batch.map((data) => this.cast(data, true)))\n .returning(this.table)\n .then((rows) => rows.map((it) => this.clean(it, this.entity.schema)));\n allEntities.push(...entities);\n }\n\n this.dbCache\n .invalidateTable(this.tableName)\n .catch((err) => this.log.warn(\"Cache invalidation failed\", err));\n\n await this.alepha.events.emit(\"repository:create:after\", {\n tableName: this.tableName,\n data: values,\n entity: allEntities,\n });\n\n return allEntities;\n } catch (error) {\n throw this.handleError(error, \"Insert query has failed\");\n }\n }\n\n /**\n * Insert or update an entity.\n *\n * If a row with the same conflict target already exists, it updates that row.\n * Otherwise, it inserts a new row.\n *\n * @param data The entity data to insert.\n * @param opts.target The column(s) to detect conflicts on. Defaults to the primary key.\n * @param opts.set The fields to update on conflict. Defaults to the insert data (minus conflict target columns).\n * @returns The created or updated entity.\n *\n * @example\n * ```ts\n * // Simple upsert on primary key\n * await repo.upsert({ id: \"abc\", name: \"Alice\", role: \"admin\" });\n *\n * // Upsert on a unique column\n * await repo.upsert(\n * { email: \"alice@example.com\", name: \"Alice\" },\n * { target: [\"email\"] },\n * );\n *\n * // Upsert with custom update fields\n * await repo.upsert(\n * { id: \"abc\", name: \"Alice\", role: \"admin\" },\n * { set: { role: \"admin\" } },\n * );\n * ```\n */\n public async upsert(\n data: Static<TObjectInsert<T>>,\n opts: StatementOptions & {\n target?: Array<keyof Static<T>>;\n set?: WithSQL<Static<TObjectUpdate<T>>>;\n } = {},\n ): Promise<Static<T>> {\n this.stampOrganization(data);\n await this.alepha.events.emit(\"repository:create:before\", {\n tableName: this.tableName,\n data,\n });\n\n const targetKeys = opts.target ?? [this.id.key];\n const targetColumns = targetKeys.map((key) => this.col(key as string));\n\n let setData: any;\n if (opts.set) {\n setData = opts.set;\n } else {\n // Default: update all fields from the insert data except the conflict target and primary key columns\n setData = { ...data };\n for (const key of targetKeys) {\n delete setData[key];\n }\n delete setData[this.id.key];\n }\n\n // Always inject updatedAt into the conflict SET clause. This ensures that even\n // with `set: {}`, the ON CONFLICT path touches the row — making it possible to\n // distinguish inserts from no-ops by comparing createdAt vs updatedAt.\n const updatedAtField = getAttrFields(\n this.entity.schema,\n PG_UPDATED_AT,\n )?.[0];\n\n if (updatedAtField) {\n setData[updatedAtField.key] =\n opts.now ?? this.dateTimeProvider.nowISOString();\n }\n\n //setData = this.cast(setData, false) as any;\n\n try {\n const entity = await this.rawInsert(opts)\n .values(this.cast(data ?? {}, true))\n .onConflictDoUpdate({\n target: targetColumns,\n set: setData,\n })\n .returning(this.table)\n .then(([it]) => this.clean(it, this.entity.schema));\n\n this.dbCache\n .invalidateTable(this.tableName)\n .catch((err) => this.log.warn(\"Cache invalidation failed\", err));\n\n await this.alepha.events.emit(\"repository:create:after\", {\n tableName: this.tableName,\n data,\n entity,\n });\n\n return entity;\n } catch (error) {\n throw this.handleError(error, \"Upsert query has failed\");\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Find an entity and update it.\n */\n public async updateOne(\n where: PgQueryWhereOrSQL<T>,\n data: WithSQL<Static<TObjectUpdate<T>>>,\n opts: StatementOptions = {},\n ): Promise<Static<T>> {\n await this.alepha.events.emit(\"repository:update:before\", {\n tableName: this.tableName,\n where,\n data,\n });\n\n let row = data as any;\n\n const updatedAtField = getAttrFields(\n this.entity.schema,\n PG_UPDATED_AT,\n )?.[0];\n\n if (updatedAtField) {\n row[updatedAtField.key] =\n opts.now ?? this.dateTimeProvider.nowISOString();\n }\n\n where = this.withOrganization(this.withDeletedAt(where, opts));\n row = this.cast(row, false) as any;\n\n // do not update the ID field\n delete row[this.id.key];\n\n const response = await this.rawUpdate(opts)\n .set(row)\n .where(this.toSQL(where))\n .returning(this.table)\n .catch((error) => {\n throw this.handleError(error, \"Update query has failed\");\n });\n\n if (!response[0]) {\n throw new DbEntityNotFoundError(this.tableName);\n }\n\n try {\n const entity = this.clean(response[0], this.entity.schema);\n\n this.dbCache\n .invalidateTable(this.tableName)\n .catch((err) => this.log.warn(\"Cache invalidation failed\", err));\n\n await this.alepha.events.emit(\"repository:update:after\", {\n tableName: this.tableName,\n where,\n data,\n entities: [entity],\n });\n\n return entity;\n } catch (error) {\n throw this.handleError(error, \"Update query has failed\");\n }\n }\n\n /**\n * Save a given entity.\n *\n * @example\n * ```ts\n * const entity = await repository.findById(1);\n * entity.name = \"New Name\"; // update a field\n * delete entity.description; // delete a field\n * await repository.save(entity);\n * ```\n *\n * Difference with `updateById/updateOne`:\n *\n * - requires the entity to be fetched first (whole object is expected)\n * - check pg.version() if present -> optimistic locking\n * - validate entity against schema\n * - undefined values will be set to null, not ignored!\n *\n * @see {@link DbVersionMismatchError}\n */\n public async save(\n entity: Static<T>,\n opts: StatementOptions = {},\n ): Promise<void> {\n const row = entity as any;\n\n const id = row[this.id.key];\n if (id == null) {\n throw new AlephaError(\n \"Cannot save entity without ID - missing primary key in value\",\n );\n }\n\n // in save mode, we do not ignore undefined values, but set them to null\n for (const key of Object.keys(this.entity.schema.properties)) {\n if (row[key] === undefined) {\n row[key] = null;\n }\n }\n\n let where: any = this.createQueryWhere();\n\n where[this.id.key] = { eq: id };\n\n const versionField = getAttrFields(this.entity.schema, PG_VERSION)?.[0];\n if (versionField && typeof row[versionField.key] === \"number\") {\n where = {\n and: [\n where,\n {\n [versionField.key]: {\n eq: row[versionField.key],\n },\n },\n ],\n } as PgQueryWhere<T>;\n\n row[versionField.key] += 1;\n }\n\n try {\n const newValue = await this.updateOne(where, row, opts);\n for (const key of Object.keys(this.entity.schema.properties)) {\n row[key] = undefined;\n }\n Object.assign(row, newValue);\n } catch (error) {\n if (error instanceof DbEntityNotFoundError && versionField) {\n // Verify entity still exists to differentiate between not-found vs version mismatch\n try {\n // If getById succeeds, entity exists and this was a version mismatch\n await this.getById(id);\n throw new DbVersionMismatchError(this.tableName, id);\n } catch (lookupError) {\n // If it's still not found, propagate the original not found error\n if (lookupError instanceof DbEntityNotFoundError) {\n throw error; // Original error\n }\n // If it's a version mismatch error, propagate it\n if (lookupError instanceof DbVersionMismatchError) {\n throw lookupError;\n }\n // Other errors (network, timeout, etc.) should be re-thrown\n throw lookupError;\n }\n }\n throw error;\n }\n }\n\n /**\n * Find an entity by ID and update it.\n */\n public async updateById(\n id: string | number,\n data: WithSQL<Static<TObjectUpdate<T>>>,\n opts: StatementOptions = {},\n ): Promise<Static<T>> {\n return await this.updateOne(this.getWhereId(id), data, opts);\n }\n\n /**\n * Find many entities and update all of them.\n */\n public async updateMany(\n where: PgQueryWhereOrSQL<T>,\n data: WithSQL<Static<TObjectUpdate<T>>>,\n opts: StatementOptions = {},\n ): Promise<Array<number | string>> {\n await this.alepha.events.emit(\"repository:update:before\", {\n tableName: this.tableName,\n where,\n data,\n });\n\n const updatedAtField = getAttrFields(\n this.entity.schema,\n PG_UPDATED_AT,\n )?.[0];\n\n if (updatedAtField) {\n (data as any)[updatedAtField.key] =\n opts.now ?? this.dateTimeProvider.nowISOString();\n }\n\n where = this.withOrganization(this.withDeletedAt(where, opts));\n data = this.cast(data, false) as any;\n try {\n const entities = await this.rawUpdate(opts)\n .set(\n data as PgUpdateSetSource<PgTableWithColumns<SchemaToTableConfig<T>>>,\n )\n .where(this.toSQL(where))\n .returning();\n\n this.dbCache\n .invalidateTable(this.tableName)\n .catch((err) => this.log.warn(\"Cache invalidation failed\", err));\n\n await this.alepha.events.emit(\"repository:update:after\", {\n tableName: this.tableName,\n where,\n data,\n entities,\n });\n\n return entities.map((it: any) => it[this.id.key]);\n } catch (error) {\n throw this.handleError(error, \"Update query has failed\");\n }\n }\n\n /**\n * Find many and delete all of them.\n * @returns Array of deleted entity IDs\n */\n public async deleteMany(\n where: PgQueryWhereOrSQL<T> = {},\n opts: StatementOptions = {},\n ): Promise<Array<number | string>> {\n const deletedAt = this.deletedAt();\n if (deletedAt && !opts.force) {\n return await this.updateMany(\n where,\n {\n [deletedAt.key]: opts.now ?? this.dateTimeProvider.nowISOString(),\n } as any,\n opts,\n );\n }\n\n where = this.withOrganization(where);\n\n await this.alepha.events.emit(\"repository:delete:before\", {\n tableName: this.tableName,\n where,\n });\n\n try {\n const result = await this.rawDelete(opts)\n .where(this.toSQL(where))\n .returning({ id: (this.table as any)[this.id.key] });\n const ids = result.map((row) => row.id);\n\n this.dbCache\n .invalidateTable(this.tableName)\n .catch((err) => this.log.warn(\"Cache invalidation failed\", err));\n\n await this.alepha.events.emit(\"repository:delete:after\", {\n tableName: this.tableName,\n where,\n ids,\n });\n\n return ids;\n } catch (error) {\n throw this.handleError(error, \"Delete query has failed\");\n }\n }\n\n /**\n * Delete all entities.\n * @returns Array of deleted entity IDs\n */\n public clear(opts: StatementOptions = {}): Promise<Array<number | string>> {\n return this.deleteMany({}, opts);\n }\n\n /**\n * Delete the given entity.\n *\n * You must fetch the entity first in order to delete it.\n * @returns Array containing the deleted entity ID\n */\n public async destroy(\n entity: Static<T>,\n opts: StatementOptions = {},\n ): Promise<Array<number | string>> {\n const id = (entity as any)[this.id.key];\n if (id == null) {\n throw new AlephaError(\"Cannot destroy entity without ID\");\n }\n\n const deletedAt = this.deletedAt();\n if (deletedAt && !opts.force) {\n opts.now ??= this.dateTimeProvider.nowISOString();\n (entity as any)[deletedAt.key] = opts.now;\n }\n\n return await this.deleteById(id, opts);\n }\n\n /**\n * Find an entity and delete it.\n * @returns Array of deleted entity IDs (should contain at most one ID)\n */\n public async deleteOne(\n where: PgQueryWhereOrSQL<T> = {},\n opts: StatementOptions = {},\n ): Promise<Array<number | string>> {\n const entity = await this.findOne({ where }, opts);\n if (!entity) {\n return [];\n }\n return await this.deleteMany(\n this.getWhereId((entity as any)[this.id.key]),\n opts,\n );\n }\n\n /**\n * Find an entity by ID and delete it.\n * @returns Array containing the deleted entity ID\n * @throws DbEntityNotFoundError if the entity is not found\n */\n public async deleteById(\n id: string | number,\n opts: StatementOptions = {},\n ): Promise<Array<number | string>> {\n const result = await this.deleteMany(this.getWhereId(id), opts);\n if (result.length === 0) {\n throw new DbEntityNotFoundError(\n `Entity with ID ${id} not found in ${this.tableName}`,\n );\n }\n return result;\n }\n\n /**\n * Count entities.\n */\n public async count(\n where: PgQueryWhereOrSQL<T> = {},\n opts: StatementOptions = {},\n ): Promise<number> {\n where = this.withOrganization(this.withDeletedAt(where, opts));\n const db = opts.tx === null ? this.provider.db : (opts.tx ?? this.db);\n return db.$count(this.table, this.toSQL(where));\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Execute an aggregate query with type-safe select, groupBy, and having.\n *\n * @example\n * ```ts\n * const result = await repo.aggregate({\n * select: { category: true, amount: { sum: true, avg: true } },\n * groupBy: [\"category\"],\n * having: { amount: { sum: { gt: 100 } } },\n * orderBy: { column: \"amount.sum\", direction: \"desc\" },\n * });\n * // result: Array<{ category: string; amount: { sum: number; avg: number } }>\n * ```\n */\n public async aggregate<S extends AggregateSelect<T>>(\n query: AggregateQuery<T, S>,\n opts: StatementOptions = {},\n ): Promise<AggregateResult<T, S>[]> {\n const AGG_SEPARATOR = \"___\";\n\n // Build flat select fields\n const flatFields: Record<string, any> = {};\n const aggFn = (op: AggregateOp, column: any) => {\n switch (op) {\n case \"count\":\n return count(column);\n case \"sum\":\n return sum(column);\n case \"avg\":\n return avg(column);\n case \"min\":\n return min(column);\n case \"max\":\n return max(column);\n }\n };\n\n for (const [key, select] of Object.entries(query.select)) {\n if (select === true) {\n flatFields[key] = this.col(key);\n } else if (typeof select === \"object\" && select !== null) {\n for (const op of Object.keys(select) as AggregateOp[]) {\n if ((select as Record<string, boolean>)[op]) {\n flatFields[`${key}${AGG_SEPARATOR}${op}`] = aggFn(\n op,\n this.col(key),\n );\n }\n }\n }\n }\n\n const db = opts.tx === null ? this.provider.db : (opts.tx ?? this.db);\n let builder = db.select(flatFields).from(this.table as PgTable);\n\n // WHERE\n if (query.where) {\n const where = this.withOrganization(\n this.withDeletedAt(query.where as any, opts),\n );\n builder = builder.where(this.toSQL(where)) as any;\n }\n\n // GROUP BY\n if (query.groupBy) {\n builder = builder.groupBy(\n ...query.groupBy.map((key) => this.col(key as string)),\n ) as any;\n }\n\n // HAVING\n if (query.having) {\n const havingConditions: SQL[] = [];\n for (const [key, ops] of Object.entries(query.having)) {\n if (!ops || typeof ops !== \"object\") continue;\n for (const [op, comparisons] of Object.entries(ops)) {\n if (!comparisons || typeof comparisons !== \"object\") continue;\n const aggExpr = aggFn(op as AggregateOp, this.col(key));\n for (const [cmp, val] of Object.entries(\n comparisons as Record<string, number>,\n )) {\n switch (cmp) {\n case \"gt\":\n havingConditions.push(gt(aggExpr, val));\n break;\n case \"gte\":\n havingConditions.push(gte(aggExpr, val));\n break;\n case \"lt\":\n havingConditions.push(lt(aggExpr, val));\n break;\n case \"lte\":\n havingConditions.push(lte(aggExpr, val));\n break;\n case \"eq\":\n havingConditions.push(drizzleEq(aggExpr, val));\n break;\n case \"ne\":\n havingConditions.push(ne(aggExpr, val));\n break;\n }\n }\n }\n }\n if (havingConditions.length > 0) {\n builder = builder.having(drizzleAnd(...havingConditions)!) as any;\n }\n }\n\n // ORDER BY\n if (query.orderBy) {\n const clauses = this.queryManager.normalizeOrderBy(query.orderBy);\n builder = builder.orderBy(\n ...clauses.map((clause) => {\n // Support dot notation: \"amount.sum\" → \"amount___sum\"\n const colName = clause.column.includes(\".\")\n ? clause.column.replace(\".\", AGG_SEPARATOR)\n : clause.column;\n const col = flatFields[colName];\n if (!col) {\n throw new AlephaError(\n `Invalid orderBy column '${clause.column}' in aggregate query`,\n );\n }\n return clause.direction === \"desc\" ? desc(col) : asc(col);\n }),\n ) as any;\n }\n\n // LIMIT / OFFSET\n if (query.limit) {\n builder = builder.limit(query.limit) as any;\n }\n if (query.offset) {\n builder = builder.offset(query.offset) as any;\n }\n\n try {\n const rows = await builder.execute();\n\n // Re-nest flat results: { amount___sum: 500 } → { amount: { sum: 500 } }\n return rows.map((row: any) => {\n const result: Record<string, any> = {};\n for (const [flatKey, value] of Object.entries(row)) {\n if (flatKey.includes(AGG_SEPARATOR)) {\n const [col, op] = flatKey.split(AGG_SEPARATOR);\n if (!result[col]) result[col] = {};\n result[col][op] = value != null ? Number(value) : 0;\n } else {\n result[flatKey] = value;\n }\n }\n return result as AggregateResult<T, S>;\n });\n } catch (error) {\n throw this.handleError(error, \"Aggregate query has failed\");\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n // Error message patterns for different database errors\n protected errorPatterns = {\n // Unique constraint violations\n conflict: [\n \"duplicate key value violates unique constraint\", // PostgreSQL\n \"UNIQUE constraint failed\", // SQLite\n ],\n // Foreign key violations\n foreignKey: [\n \"violates foreign key constraint\", // PostgreSQL\n \"FOREIGN KEY constraint failed\", // SQLite\n ],\n // NOT NULL violations\n notNull: [\n \"violates not-null constraint\", // PostgreSQL\n \"NOT NULL constraint failed\", // SQLite\n ],\n // Deadlock\n deadlock: [\n \"deadlock detected\", // PostgreSQL\n // SQLite doesn't have true deadlocks\n ],\n // Table not found\n tableNotFound: [\n \"does not exist\", // PostgreSQL: relation \"x\" does not exist\n \"no such table\", // SQLite\n ],\n // Column not found\n columnNotFound: [\n 'column \"', // PostgreSQL: column \"x\" does not exist\n \"no such column\", // SQLite\n ],\n };\n\n protected handleError(error: unknown, message: string): DbError {\n if (!(error instanceof Error)) {\n return new DbError(message);\n }\n\n const fullMessage =\n `${error.message} ${(error.cause as Error)?.message ?? \"\"}`.toLowerCase();\n\n const hasPattern = (patterns: string[]) =>\n patterns.some((pattern) => fullMessage.includes(pattern.toLowerCase()));\n\n const getSourceError = () =>\n error.cause instanceof Error ? error.cause : error;\n\n // Check for unique constraint violation (conflict)\n if (hasPattern(this.errorPatterns.conflict)) {\n return new DbConflictError(message, error);\n }\n\n // Check for foreign key violation\n if (hasPattern(this.errorPatterns.foreignKey)) {\n return DbForeignKeyError.fromDatabaseError(\n getSourceError(),\n this.tableName,\n );\n }\n\n // Check for NOT NULL violation\n if (hasPattern(this.errorPatterns.notNull)) {\n return DbNotNullError.fromDatabaseError(getSourceError(), this.tableName);\n }\n\n // Check for deadlock\n if (hasPattern(this.errorPatterns.deadlock)) {\n return DbDeadlockError.fromDatabaseError(getSourceError());\n }\n\n // Check for table not found (must check before column not found)\n if (\n hasPattern(this.errorPatterns.tableNotFound) &&\n (fullMessage.includes(\"relation\") || fullMessage.includes(\"table\"))\n ) {\n return DbTableNotFoundError.fromDatabaseError(getSourceError());\n }\n\n // Check for column not found\n if (hasPattern(this.errorPatterns.columnNotFound)) {\n return DbColumnNotFoundError.fromDatabaseError(getSourceError());\n }\n\n return new DbError(message, error);\n }\n\n protected withDeletedAt(\n where: PgQueryWhereOrSQL<T>,\n opts: {\n force?: boolean;\n } = {},\n ): PgQueryWhereOrSQL<T> {\n if (opts.force) {\n return where;\n }\n\n const deletedAt = this.deletedAt();\n if (!deletedAt) {\n return where;\n }\n\n return {\n and: [\n where,\n {\n [deletedAt.key]: {\n isNull: true,\n },\n } as any,\n ],\n } as PgQueryWhereOrSQL<T>;\n }\n\n protected deletedAt(): PgAttrField | undefined {\n const deletedAtFields = getAttrFields(this.entity.schema, PG_DELETED_AT);\n if (deletedAtFields.length > 0) {\n return deletedAtFields[0];\n }\n return undefined;\n }\n\n protected withOrganization(\n where: PgQueryWhereOrSQL<T>,\n ): PgQueryWhereOrSQL<T> {\n const orgField = this.organizationField();\n if (!orgField) {\n return where;\n }\n\n const user = this.alepha.store.get(currentUserAtom);\n if (!user?.organization) {\n return where;\n }\n\n return {\n and: [\n where,\n {\n or: [\n { [orgField.key]: { eq: user.organization } },\n { [orgField.key]: { isNull: true } },\n ],\n } as any,\n ],\n } as PgQueryWhereOrSQL<T>;\n }\n\n protected stampOrganization(data: any): void {\n const orgField = this.organizationField();\n if (!orgField) {\n return;\n }\n\n if (data[orgField.key] != null) {\n return;\n }\n\n const user = this.alepha.store.get(currentUserAtom);\n if (user?.organization) {\n data[orgField.key] = user.organization;\n }\n }\n\n protected organizationField(): PgAttrField | undefined {\n const fields = getAttrFields(this.entity.schema, PG_ORGANIZATION);\n if (fields.length > 0) {\n return fields[0];\n }\n return undefined;\n }\n\n /**\n * Convert something to valid Pg Insert Value.\n */\n protected cast(\n data: any,\n insert: boolean,\n ): PgInsertValue<PgTableWithColumns<SchemaToTableConfig<T>>> {\n const schema = insert\n ? this.entity.insertSchema // insert\n : (t.partial(this.entity.updateSchema) as TObject); // update\n\n return this.alepha.codec.encode(schema, data) as PgInsertValue<\n PgTableWithColumns<SchemaToTableConfig<T>>\n >;\n }\n\n /**\n * Transform a row from the database into a clean entity.\n */\n protected clean<T extends TObject>(\n row: Record<string, unknown>,\n schema: T,\n ): Static<T> {\n for (const key of Object.keys(schema.properties)) {\n const value = schema.properties[key];\n\n // convert PG date-time and date to ISO strings\n if (typeof row[key] === \"string\") {\n if (t.schema.isDateTime(value)) {\n row[key] = this.dateTimeProvider.of(row[key]).toISOString();\n } else if (t.schema.isDate(value)) {\n row[key] = this.dateTimeProvider\n .of(`${row[key]}T00:00:00Z`)\n .toISOString()\n .split(\"T\")[0];\n }\n }\n\n // convert BigInt to string\n if (typeof row[key] === \"bigint\" && t.schema.isBigInt(value)) {\n row[key] = row[key].toString();\n }\n }\n\n return this.alepha.codec.decode(schema, row) as Static<T>;\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n // INTERNAL METHODS\n\n /**\n * Clean a row with joins recursively\n */\n protected cleanWithJoins<T extends TObject>(\n row: Record<string, unknown>,\n schema: T,\n joins: PgJoin[],\n parentPath?: string,\n ): Static<T> {\n // Get joins at this level\n const joinsAtThisLevel = joins.filter((j) => j.parent === parentPath);\n\n // Create a copy of the row for cleaning, removing joined data temporarily\n const cleanRow: Record<string, unknown> = { ...row };\n const joinedData: Record<string, unknown> = {};\n\n for (const join of joinsAtThisLevel) {\n joinedData[join.key] = cleanRow[join.key];\n delete cleanRow[join.key];\n }\n\n // Clean the base entity without joined properties\n const entity = this.clean(cleanRow, schema);\n\n // Then recursively clean joined entities\n for (const join of joinsAtThisLevel) {\n const joinedValue = joinedData[join.key];\n // Only process if the joined value exists\n if (joinedValue != null) {\n // Build path for this join\n const joinPath = parentPath ? `${parentPath}.${join.key}` : join.key;\n // Find child joins\n const childJoins = joins.filter((j) => j.parent === joinPath);\n // Recursively clean if there are child joins\n if (childJoins.length > 0) {\n (entity as any)[join.key] = this.cleanWithJoins(\n joinedValue as Record<string, unknown>,\n join.schema,\n joins,\n joinPath,\n );\n } else {\n // No child joins, just clean this join\n (entity as any)[join.key] = this.clean(\n joinedValue as Record<string, unknown>,\n join.schema,\n );\n }\n } else {\n // Set to undefined if no data\n (entity as any)[join.key] = undefined;\n }\n }\n\n return entity as Static<T>;\n }\n\n /**\n * Build a cache key from method name and query parameters.\n */\n protected buildCacheKey(method: string, query: any): string {\n return `${method}:${JSON.stringify(query)}`;\n }\n\n /**\n * Convert a where clause to SQL.\n */\n protected toSQL(\n where: PgQueryWhereOrSQL<T>,\n joins?: PgJoin[],\n ): SQL | undefined {\n return this.queryManager.toSQL(where as PgQueryWhereOrSQL<T>, {\n schema: this.entity.schema,\n col: (name) => {\n return this.col(name);\n },\n joins,\n dialect: this.provider.dialect,\n });\n }\n\n /**\n * Get the where clause for an ID.\n *\n * @param id The ID to get the where clause for.\n * @returns The where clause for the ID.\n */\n protected getWhereId(id: string | number): PgQueryWhere<T> {\n return {\n [this.id.key]: {\n eq: t.schema.isString(this.id.type) ? String(id) : Number(id),\n },\n } as PgQueryWhere<T>;\n }\n\n /**\n * Find a primary key in the schema.\n */\n protected getPrimaryKey(schema: TObject) {\n const primaryKeys = getAttrFields(schema, PG_PRIMARY_KEY);\n if (primaryKeys.length === 0) {\n throw new AlephaError(\"Primary key not found in schema\");\n }\n\n if (primaryKeys.length > 1) {\n throw new AlephaError(\n `Multiple primary keys (${primaryKeys.length}) are not supported`,\n );\n }\n\n return {\n key: primaryKeys[0].key,\n col: this.col(primaryKeys[0].key),\n type: primaryKeys[0].type,\n };\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * The options for a statement.\n */\nexport interface StatementOptions {\n /**\n * Transaction to use.\n *\n * - `undefined` — auto-detect from `alepha.store` (implicit transactional context)\n * - `PgTransaction` — use this specific transaction (explicit)\n * - `null` — force no transaction, bypass implicit context\n */\n tx?: PgTransaction<any, Record<string, any>> | null;\n\n /**\n * Lock strength.\n */\n for?: LockStrength | { config: LockConfig; strength: LockStrength };\n\n /**\n * If true, ignore soft delete.\n */\n force?: boolean;\n\n /**\n * Force the current time.\n */\n now?: DateTime | string;\n\n /**\n * Cache configuration for query results.\n *\n * When set, results are stored in an in-memory cache keyed by query parameters.\n * Any write to this table automatically invalidates all cached queries.\n *\n * @example\n * ```ts\n * await repo.findMany(query, { cache: { ttl: 60_000 } });\n * ```\n */\n cache?: {\n /**\n * Time-to-live in milliseconds.\n */\n ttl?: number;\n /**\n * Custom cache key. If not provided, a key is derived from the query.\n */\n key?: string;\n };\n}\n\ntype WithSQL<T> = {\n [P in keyof T]?: T[P] | SQL;\n};\n","import { $inject, Alepha, type Service, type TObject } from \"alepha\";\nimport type { EntityPrimitive } from \"../primitives/$entity.ts\";\nimport { Repository } from \"../services/Repository.ts\";\nimport type { DatabaseProvider } from \"./drivers/DatabaseProvider.ts\";\n\nexport class RepositoryProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly registry = new Map<\n EntityPrimitive<any>,\n Service<Repository<any>>\n >();\n\n public getRepositories(provider?: DatabaseProvider) {\n const repositories = this.alepha.services(Repository);\n\n if (provider) {\n return repositories.filter((it) => it.provider === provider);\n }\n\n return repositories;\n }\n\n public getRepository<T extends TObject>(\n entity: EntityPrimitive<T>,\n ): Repository<T> {\n const RepositoryClass = this.createClassRepository(entity);\n return this.alepha.inject(RepositoryClass);\n }\n\n public createClassRepository<T extends TObject>(\n entity: EntityPrimitive<T>,\n ): Service<Repository<T>> {\n let name = entity.name.charAt(0).toUpperCase() + entity.name.slice(1);\n if (name.endsWith(\"s\")) {\n name = name.slice(0, -1);\n }\n name = `${name}Repository`;\n\n if (this.registry.has(entity)) {\n return this.registry.get(entity) as Service<Repository<T>>;\n }\n\n class GenericRepository extends Repository<T> {\n constructor() {\n super(entity);\n }\n }\n\n // for class name to entity.name + \"Repository\"\n Object.defineProperty(GenericRepository, \"name\", { value: name });\n\n this.registry.set(entity, GenericRepository as Service<Repository<T>>);\n\n return GenericRepository;\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\nexport class DbMigrationError extends DbError {\n readonly name = \"DbMigrationError\";\n\n constructor(cause?: unknown) {\n super(\"Failed to migrate database\", cause);\n }\n}\n","import { DbError } from \"./DbError.ts\";\n\n/**\n * Error thrown when a database connection fails.\n *\n * This can happen due to:\n * - Connection refused (server not running)\n * - Connection timeout\n * - Authentication failure\n * - Network issues\n * - Database file not found (SQLite)\n */\nexport class DbConnectionError extends DbError {\n readonly name = \"DbConnectionError\";\n readonly status = 503;\n\n /**\n * The type of connection error.\n */\n readonly errorType?:\n | \"refused\"\n | \"timeout\"\n | \"auth\"\n | \"not_found\"\n | \"locked\"\n | \"unknown\";\n\n /**\n * Whether this error is retryable.\n * Connection errors are often transient and can be retried.\n */\n readonly retryable: boolean;\n\n constructor(\n message: string,\n cause?: unknown,\n options?: {\n errorType?: DbConnectionError[\"errorType\"];\n retryable?: boolean;\n },\n ) {\n super(message, cause);\n this.errorType = options?.errorType;\n this.retryable = options?.retryable ?? true;\n }\n\n /**\n * Parse a database connection error message and create a DbConnectionError.\n * Supports both PostgreSQL and SQLite error formats.\n */\n static fromDatabaseError(error: Error): DbConnectionError {\n const message = error.message.toLowerCase();\n\n // Connection refused\n if (\n message.includes(\"connection refused\") ||\n message.includes(\"econnrefused\") ||\n message.includes(\"could not connect\")\n ) {\n return new DbConnectionError(\n \"Database connection refused. Is the server running?\",\n error,\n { errorType: \"refused\", retryable: true },\n );\n }\n\n // Timeout\n if (\n message.includes(\"timeout\") ||\n message.includes(\"timed out\") ||\n message.includes(\"etimedout\")\n ) {\n return new DbConnectionError(\"Database connection timed out\", error, {\n errorType: \"timeout\",\n retryable: true,\n });\n }\n\n // Authentication\n if (\n message.includes(\"password authentication failed\") ||\n message.includes(\"authentication failed\") ||\n message.includes(\"access denied\")\n ) {\n return new DbConnectionError(\n \"Database authentication failed. Check credentials.\",\n error,\n { errorType: \"auth\", retryable: false },\n );\n }\n\n // SQLite file not found\n if (\n message.includes(\"unable to open database\") ||\n message.includes(\"no such file\") ||\n message.includes(\"enoent\")\n ) {\n return new DbConnectionError(\"Database file not found\", error, {\n errorType: \"not_found\",\n retryable: false,\n });\n }\n\n // SQLite database locked\n if (message.includes(\"database is locked\")) {\n return new DbConnectionError(\n \"Database is locked by another process\",\n error,\n { errorType: \"locked\", retryable: true },\n );\n }\n\n return new DbConnectionError(\"Failed to connect to database\", error, {\n errorType: \"unknown\",\n retryable: true,\n });\n }\n}\n","import {\n AlephaError,\n pageSchema,\n type Static,\n type TBigInt,\n type TInteger,\n type TNumber,\n type TNumberOptions,\n type TObject,\n type TObjectOptions,\n type TPage,\n type TSchema,\n type TString,\n type TStringOptions,\n t,\n} from \"alepha\";\nimport type { UpdateDeleteAction } from \"drizzle-orm/pg-core/foreign-keys\";\nimport {\n PG_CREATED_AT,\n PG_DEFAULT,\n PG_DELETED_AT,\n PG_IDENTITY,\n PG_ORGANIZATION,\n PG_PRIMARY_KEY,\n PG_REF,\n PG_UPDATED_AT,\n PG_VERSION,\n type PgDefault,\n type PgIdentityOptions,\n type PgPrimaryKey,\n type PgRef,\n} from \"../constants/PG_SYMBOLS.ts\";\nimport type { PgAttr } from \"../helpers/pgAttr.ts\";\nimport { pgAttr } from \"../helpers/pgAttr.ts\";\n\nexport class DatabaseTypeProvider {\n public readonly attr = pgAttr;\n\n /**\n * Creates a primary key with an identity column.\n */\n public readonly identityPrimaryKey = (\n identity?: PgIdentityOptions,\n options?: TNumberOptions,\n ) =>\n pgAttr(\n pgAttr(pgAttr(t.integer(options), PG_PRIMARY_KEY), PG_IDENTITY, identity),\n PG_DEFAULT,\n );\n\n /**\n * Creates a primary key with a big identity column. (default)\n */\n public readonly bigIdentityPrimaryKey = (\n identity?: PgIdentityOptions,\n options?: TNumberOptions,\n ) =>\n pgAttr(\n pgAttr(pgAttr(t.int64(options), PG_PRIMARY_KEY), PG_IDENTITY, identity),\n PG_DEFAULT,\n );\n\n /**\n * Creates a primary key with a UUID column.\n */\n public readonly uuidPrimaryKey = () =>\n pgAttr(pgAttr(t.uuid(), PG_PRIMARY_KEY), PG_DEFAULT);\n\n /**\n * Creates a primary key for a given type. Supports:\n * - `t.integer()` -> PG INT (default)\n * - `t.bigint()` -> PG BIGINT\n * - `t.uuid()` -> PG UUID\n */\n public primaryKey(): PgAttr<PgAttr<TInteger, PgPrimaryKey>, PgDefault>;\n public primaryKey(\n type: TString,\n options?: TStringOptions,\n ): PgAttr<PgAttr<TString, PgPrimaryKey>, PgDefault>;\n public primaryKey(\n type: TInteger,\n options?: TNumberOptions,\n identity?: PgIdentityOptions,\n ): PgAttr<PgAttr<TInteger, PgPrimaryKey>, PgDefault>;\n public primaryKey(\n type: TNumber,\n options?: TNumberOptions,\n identity?: PgIdentityOptions,\n ): PgAttr<PgAttr<TNumber, PgPrimaryKey>, PgDefault>;\n public primaryKey(\n type: TBigInt,\n options?: TNumberOptions,\n identity?: PgIdentityOptions,\n ): PgAttr<PgAttr<TBigInt, PgPrimaryKey>, PgDefault>;\n public primaryKey(\n type?: TSchema,\n options?: TNumberOptions | TStringOptions,\n identity?: PgIdentityOptions,\n ): PgAttr<PgAttr<TSchema, PgPrimaryKey>, PgDefault> {\n if (!type || t.schema.isInteger(type)) {\n return pgAttr(\n pgAttr(\n pgAttr(t.integer(options), PG_PRIMARY_KEY),\n PG_IDENTITY,\n identity,\n ),\n PG_DEFAULT,\n );\n }\n\n if (t.schema.isString(type) && type.format === \"uuid\") {\n return pgAttr(pgAttr(t.uuid(), PG_PRIMARY_KEY), PG_DEFAULT);\n }\n\n if (t.schema.isNumber(type) && type.format === \"int64\") {\n return pgAttr(\n pgAttr(\n pgAttr(t.number(options), PG_PRIMARY_KEY),\n PG_IDENTITY,\n identity,\n ),\n PG_DEFAULT,\n );\n }\n\n if (t.schema.isBigInt(type)) {\n return pgAttr(\n pgAttr(\n pgAttr(t.bigint(options), PG_PRIMARY_KEY),\n PG_IDENTITY,\n identity,\n ),\n PG_DEFAULT,\n );\n }\n\n throw new AlephaError(`Unsupported type for primary key: ${type}`);\n }\n\n /**\n * Wrap a schema with \"default\" attribute.\n * This is used to set a default value for a column in the database.\n */\n public readonly default = <T extends TSchema>(\n type: T,\n value?: Static<T>,\n ): PgAttr<T, PgDefault> => {\n if (value != null) {\n Object.assign(type, { default: value });\n }\n\n return this.attr(type, PG_DEFAULT);\n };\n\n /**\n * Creates a column 'version'.\n *\n * This is used to track the version of a row in the database.\n *\n * You can use it for optimistic concurrency control (OCC) with {@link RepositoryPrimitive#save}.\n *\n * @see {@link RepositoryPrimitive#save}\n * @see {@link PgVersionMismatchError}\n */\n public readonly version = (options: TNumberOptions = {}) =>\n this.default(pgAttr(t.integer(options), PG_VERSION), 0);\n\n /**\n * Creates a column Created At. So just a datetime column with a default value of the current timestamp.\n */\n public readonly createdAt = (options?: TStringOptions) =>\n pgAttr(pgAttr(t.datetime(options), PG_CREATED_AT), PG_DEFAULT);\n\n /**\n * Creates a column Updated At. Like createdAt, but it is updated on every update of the row.\n */\n public readonly updatedAt = (options?: TStringOptions) =>\n pgAttr(pgAttr(t.datetime(options), PG_UPDATED_AT), PG_DEFAULT);\n\n /**\n * Creates a column Deleted At for soft delete functionality.\n * This is used to mark rows as deleted without actually removing them from the database.\n * The column is nullable - NULL means not deleted, timestamp means deleted.\n */\n public readonly deletedAt = (options?: TStringOptions) =>\n pgAttr(t.optional(t.datetime(options)), PG_DELETED_AT);\n\n /**\n * Creates an organization column for multi-tenant row scoping.\n *\n * When present, queries are automatically filtered by the current user's organization.\n * Rows with `null` organization are considered global and visible to everyone.\n * On create, the column is auto-stamped with the current user's organization.\n */\n public readonly organization = () =>\n pgAttr(t.optional(t.uuid()), PG_ORGANIZATION);\n\n /**\n * Creates a reference to another table or schema. Basically a foreign key.\n */\n public readonly ref = <T extends TSchema>(\n type: T,\n ref: () => any,\n actions?: {\n onUpdate?: UpdateDeleteAction;\n onDelete?: UpdateDeleteAction;\n },\n ): PgAttr<T, PgRef> => {\n // If actions are not provided, set default onDelete based on type\n const finalActions = actions ?? {\n onDelete: t.schema.isOptional(type) ? \"set null\" : \"cascade\",\n };\n\n return this.attr(type, PG_REF, {\n ref,\n actions: finalActions,\n });\n };\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Creates a page schema for a given object schema.\n * It's used by {@link Repository#paginate} method.\n */\n public readonly page = <T extends TObject>(\n resource: T,\n options?: TObjectOptions,\n ): TPage<T> => {\n return pageSchema(resource, options);\n };\n}\n\n/**\n * Wrapper of TypeProvider (`t`) for database types.\n *\n * Use `db` for improve TypeBox schema definitions with database-specific attributes.\n *\n * @example\n * ```ts\n * import { t } from \"alepha\";\n * import { db } from \"alepha/orm\";\n *\n * const userSchema = t.object({\n * id: db.primaryKey(t.uuid()),\n * email: t.email(),\n * createdAt: db.createdAt(),\n * });\n * ```\n */\nexport const db = new DatabaseTypeProvider();\n","import { t } from \"alepha\";\nimport {\n PG_DEFAULT,\n PG_PRIMARY_KEY,\n PG_SERIAL,\n} from \"../constants/PG_SYMBOLS.ts\";\nimport { pgAttr } from \"../helpers/pgAttr.ts\";\n\n/**\n * @deprecated Use `pg.primaryKey()` instead.\n */\nexport const legacyIdSchema = pgAttr(\n pgAttr(pgAttr(t.integer(), PG_PRIMARY_KEY), PG_SERIAL),\n PG_DEFAULT,\n);\n","import { $context, $inject, type TObject } from \"alepha\";\nimport { RepositoryProvider } from \"../providers/RepositoryProvider.ts\";\nimport type { Repository } from \"../services/Repository.ts\";\nimport type { EntityPrimitive } from \"./$entity.ts\";\n\n/**\n * Get the repository for the given entity.\n */\nexport const $repository = <T extends TObject>(\n entity: EntityPrimitive<T>,\n): Repository<T> => {\n const { alepha } = $context();\n const repositoryProvider = alepha.inject(RepositoryProvider);\n return $inject(repositoryProvider.createClassRepository(entity));\n};\n","import { $context, $mode, type Alepha } from \"alepha\";\nimport { DatabaseProvider } from \"../providers/drivers/DatabaseProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface SeedOptions {\n /**\n * Seed handler, executed inside a database transaction.\n *\n * If the handler throws, the transaction is rolled back automatically.\n */\n handler: (ctx: { alepha: Alepha; db: DatabaseProvider }) => any;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Activate seed mode: a convenience wrapper around `$mode` that runs the handler\n * inside a database transaction.\n *\n * When `SEED=true` (or `MODE=SEED`) is set, the owning class becomes `alepha.target`,\n * the graph is pruned, and the handler runs inside `db.transactional()`.\n * After completion (or error), the app stops automatically.\n *\n * Returns `true` if seed mode is active, `false` otherwise.\n *\n * @example\n * ```ts\n * import { $seed } from \"alepha/orm\";\n * import { $repository } from \"alepha/orm\";\n *\n * class AppSeed {\n * users = $repository(userEntity);\n *\n * seed = $seed({\n * handler: async () => {\n * await this.users.create({ name: \"John Doe\" });\n * },\n * });\n * }\n * ```\n *\n * ```bash\n * SEED=true node app.js\n * ```\n */\nexport const $seed = (args: SeedOptions): boolean => {\n const { alepha } = $context();\n const db = alepha.inject(DatabaseProvider);\n\n return $mode({\n env: \"SEED\",\n ready: async () => {\n await db.transactional(async () => {\n await args.handler({ alepha, db });\n });\n },\n });\n};\n","import { createMiddleware, type Middleware } from \"alepha\";\nimport type { PgTransactionConfig } from \"drizzle-orm/pg-core/session\";\nimport { DatabaseProvider } from \"../providers/drivers/DatabaseProvider.ts\";\n\nexport interface TransactionalOptions {\n /**\n * PostgreSQL transaction configuration (isolation level, access mode, etc.).\n */\n config?: PgTransactionConfig;\n}\n\n/**\n * Middleware that wraps handler execution in a database transaction.\n *\n * All Repository operations inside the handler automatically participate in\n * the transaction — no explicit `{ tx }` drilling required.\n *\n * Nesting is safe: if the handler is already inside a `transactional()` block,\n * the outer transaction is reused.\n *\n * ```typescript\n * class OrderService {\n * createOrder = $action({\n * use: [$transactional()],\n * handler: async ({ body }) => {\n * await this.orders.create(body); // auto-uses tx\n * await this.audit.create({ ... }); // auto-uses tx\n * // throw → auto rollback, return → auto commit\n * },\n * });\n * }\n * ```\n */\nexport const $transactional = (options?: TransactionalOptions): Middleware => {\n return createMiddleware({\n name: \"$transactional\",\n options,\n handler: ({ alepha, next }) => {\n const provider = alepha.inject(DatabaseProvider);\n return async (...args: any[]) => {\n return provider.transactional(() => next(...args), options?.config);\n };\n },\n });\n};\n","import type { Static, TSchema } from \"alepha\";\nimport { customType } from \"drizzle-orm/pg-core\";\n\n/**\n * Postgres schema type.\n */\nexport const schema = <TDocument extends TSchema>(\n name: string,\n document: TDocument,\n) =>\n customType<{\n data: Static<TDocument>;\n driverData: string;\n config: { document: TDocument };\n configRequired: true;\n }>({\n dataType: () => \"jsonb\",\n toDriver: (value) => JSON.stringify(value),\n fromDriver: (value: TDocument | string) =>\n value && typeof value === \"string\" ? JSON.parse(value) : value,\n })(name, { document }).$type<Static<TDocument>>();\n","import { $module, type Alepha } from \"alepha\";\nimport { AlephaDateTime } from \"alepha/datetime\";\nimport { $entity } from \"./primitives/$entity.ts\";\nimport { $sequence } from \"./primitives/$sequence.ts\";\nimport { DrizzleKitProvider } from \"./providers/DrizzleKitProvider.ts\";\nimport { BunSqliteProvider } from \"./providers/drivers/BunSqliteProvider.ts\";\nimport { CloudflareD1Provider } from \"./providers/drivers/CloudflareD1Provider.ts\";\nimport { DatabaseProvider } from \"./providers/drivers/DatabaseProvider.ts\";\nimport { RepositoryProvider } from \"./providers/RepositoryProvider.ts\";\nimport { databaseEnvSchema } from \"./schemas/databaseEnvSchema.ts\";\nimport { PgRelationManager } from \"./services/PgRelationManager.ts\";\nimport { QueryManager } from \"./services/QueryManager.ts\";\nimport { Repository } from \"./services/Repository.ts\";\nimport { SqliteModelBuilder } from \"./services/SqliteModelBuilder.ts\";\n\nexport const SqliteProvider = BunSqliteProvider;\n\nexport * from \"./index.shared-server.ts\";\nexport * from \"./providers/drivers/BunSqliteProvider.ts\";\n\nexport const AlephaOrm = $module({\n name: \"alepha.orm\",\n primitives: [$sequence, $entity],\n services: [\n AlephaDateTime,\n DatabaseProvider,\n BunSqliteProvider,\n CloudflareD1Provider,\n SqliteModelBuilder,\n DrizzleKitProvider,\n RepositoryProvider,\n Repository,\n PgRelationManager,\n QueryManager,\n ],\n register: (alepha: Alepha) => {\n const env = alepha.parseEnv(databaseEnvSchema);\n\n alepha.with(DrizzleKitProvider);\n alepha.with(RepositoryProvider);\n\n const url = env.DATABASE_URL;\n\n if (url?.startsWith(\"d1:\")) {\n alepha.with({\n optional: true,\n provide: DatabaseProvider,\n use: CloudflareD1Provider,\n });\n return;\n }\n\n // PostgreSQL URLs are handled by AlephaOrmPostgres — skip here\n if (url?.startsWith(\"postgres:\") || url?.startsWith(\"pglite:\")) {\n return;\n }\n\n alepha.with({\n optional: true,\n provide: DatabaseProvider,\n use: BunSqliteProvider,\n });\n },\n});\n"],"mappings":"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"}