@fragno-dev/db 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/.turbo/turbo-build.log +137 -13
  2. package/.turbo/turbo-test.log +36 -0
  3. package/CHANGELOG.md +7 -0
  4. package/dist/adapters/adapters.d.ts +18 -0
  5. package/dist/adapters/adapters.d.ts.map +1 -0
  6. package/dist/adapters/drizzle/drizzle-adapter.d.ts +21 -0
  7. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -0
  8. package/dist/adapters/drizzle/drizzle-adapter.js +62 -0
  9. package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -0
  10. package/dist/adapters/drizzle/drizzle-query.d.ts +17 -0
  11. package/dist/adapters/drizzle/drizzle-query.d.ts.map +1 -0
  12. package/dist/adapters/drizzle/drizzle-query.js +139 -0
  13. package/dist/adapters/drizzle/drizzle-query.js.map +1 -0
  14. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts +9 -0
  15. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts.map +1 -0
  16. package/dist/adapters/drizzle/drizzle-uow-compiler.js +300 -0
  17. package/dist/adapters/drizzle/drizzle-uow-compiler.js.map +1 -0
  18. package/dist/adapters/drizzle/drizzle-uow-decoder.js +82 -0
  19. package/dist/adapters/drizzle/drizzle-uow-decoder.js.map +1 -0
  20. package/dist/adapters/drizzle/drizzle-uow-executor.js +125 -0
  21. package/dist/adapters/drizzle/drizzle-uow-executor.js.map +1 -0
  22. package/dist/adapters/drizzle/generate.js +273 -0
  23. package/dist/adapters/drizzle/generate.js.map +1 -0
  24. package/dist/adapters/drizzle/join-column-utils.js +28 -0
  25. package/dist/adapters/drizzle/join-column-utils.js.map +1 -0
  26. package/dist/adapters/drizzle/shared.js +11 -0
  27. package/dist/adapters/drizzle/shared.js.map +1 -0
  28. package/dist/adapters/kysely/kysely-adapter.d.ts +23 -0
  29. package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -0
  30. package/dist/adapters/kysely/kysely-adapter.js +119 -0
  31. package/dist/adapters/kysely/kysely-adapter.js.map +1 -0
  32. package/dist/adapters/kysely/kysely-query-builder.js +306 -0
  33. package/dist/adapters/kysely/kysely-query-builder.js.map +1 -0
  34. package/dist/adapters/kysely/kysely-query-compiler.js +67 -0
  35. package/dist/adapters/kysely/kysely-query-compiler.js.map +1 -0
  36. package/dist/adapters/kysely/kysely-query.js +158 -0
  37. package/dist/adapters/kysely/kysely-query.js.map +1 -0
  38. package/dist/adapters/kysely/kysely-uow-compiler.js +139 -0
  39. package/dist/adapters/kysely/kysely-uow-compiler.js.map +1 -0
  40. package/dist/adapters/kysely/kysely-uow-executor.js +89 -0
  41. package/dist/adapters/kysely/kysely-uow-executor.js.map +1 -0
  42. package/dist/adapters/kysely/migration/execute.js +176 -0
  43. package/dist/adapters/kysely/migration/execute.js.map +1 -0
  44. package/dist/fragment.d.ts +54 -0
  45. package/dist/fragment.d.ts.map +1 -0
  46. package/dist/fragment.js +92 -0
  47. package/dist/fragment.js.map +1 -0
  48. package/dist/id.d.ts +2 -0
  49. package/dist/migration-engine/auto-from-schema.js +116 -0
  50. package/dist/migration-engine/auto-from-schema.js.map +1 -0
  51. package/dist/migration-engine/create.d.ts +41 -0
  52. package/dist/migration-engine/create.d.ts.map +1 -0
  53. package/dist/migration-engine/create.js +58 -0
  54. package/dist/migration-engine/create.js.map +1 -0
  55. package/dist/migration-engine/shared.d.ts +90 -0
  56. package/dist/migration-engine/shared.d.ts.map +1 -0
  57. package/dist/migration-engine/shared.js +8 -0
  58. package/dist/migration-engine/shared.js.map +1 -0
  59. package/dist/mod.d.ts +55 -2
  60. package/dist/mod.d.ts.map +1 -1
  61. package/dist/mod.js +111 -2
  62. package/dist/mod.js.map +1 -1
  63. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column-builder.js +108 -0
  64. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column-builder.js.map +1 -0
  65. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column.js +55 -0
  66. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column.js.map +1 -0
  67. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/entity.js +18 -0
  68. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/entity.js.map +1 -0
  69. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/common.js +183 -0
  70. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/common.js.map +1 -0
  71. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/enum.js +58 -0
  72. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/enum.js.map +1 -0
  73. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/foreign-keys.js +68 -0
  74. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/foreign-keys.js.map +1 -0
  75. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/unique-constraint.js +56 -0
  76. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/unique-constraint.js.map +1 -0
  77. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/utils/array.js +65 -0
  78. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/utils/array.js.map +1 -0
  79. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/conditions.js +81 -0
  80. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/conditions.js.map +1 -0
  81. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/select.js +13 -0
  82. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/select.js.map +1 -0
  83. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/functions/aggregate.js +10 -0
  84. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/functions/aggregate.js.map +1 -0
  85. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/sql.js +372 -0
  86. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/sql.js.map +1 -0
  87. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/subquery.js +23 -0
  88. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/subquery.js.map +1 -0
  89. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.js +62 -0
  90. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.js.map +1 -0
  91. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.utils.js +6 -0
  92. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.utils.js.map +1 -0
  93. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing-utils.js +8 -0
  94. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing-utils.js.map +1 -0
  95. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing.js +8 -0
  96. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing.js.map +1 -0
  97. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/view-common.js +6 -0
  98. package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/view-common.js.map +1 -0
  99. package/dist/query/condition-builder.d.ts +41 -0
  100. package/dist/query/condition-builder.d.ts.map +1 -0
  101. package/dist/query/condition-builder.js +93 -0
  102. package/dist/query/condition-builder.js.map +1 -0
  103. package/dist/query/cursor.d.ts +88 -0
  104. package/dist/query/cursor.d.ts.map +1 -0
  105. package/dist/query/cursor.js +103 -0
  106. package/dist/query/cursor.js.map +1 -0
  107. package/dist/query/orm/orm.d.ts +18 -0
  108. package/dist/query/orm/orm.d.ts.map +1 -0
  109. package/dist/query/orm/orm.js +48 -0
  110. package/dist/query/orm/orm.js.map +1 -0
  111. package/dist/query/query.d.ts +79 -0
  112. package/dist/query/query.d.ts.map +1 -0
  113. package/dist/query/query.js +1 -0
  114. package/dist/query/result-transform.js +155 -0
  115. package/dist/query/result-transform.js.map +1 -0
  116. package/dist/query/unit-of-work.d.ts +435 -0
  117. package/dist/query/unit-of-work.d.ts.map +1 -0
  118. package/dist/query/unit-of-work.js +549 -0
  119. package/dist/query/unit-of-work.js.map +1 -0
  120. package/dist/schema/create.d.ts +273 -116
  121. package/dist/schema/create.d.ts.map +1 -1
  122. package/dist/schema/create.js +410 -222
  123. package/dist/schema/create.js.map +1 -1
  124. package/dist/schema/serialize.js +101 -0
  125. package/dist/schema/serialize.js.map +1 -0
  126. package/dist/schema-generator/schema-generator.d.ts +15 -0
  127. package/dist/schema-generator/schema-generator.d.ts.map +1 -0
  128. package/dist/shared/providers.d.ts +6 -0
  129. package/dist/shared/providers.d.ts.map +1 -0
  130. package/dist/util/import-generator.js +26 -0
  131. package/dist/util/import-generator.js.map +1 -0
  132. package/dist/util/parse.js +15 -0
  133. package/dist/util/parse.js.map +1 -0
  134. package/dist/util/types.d.ts +8 -0
  135. package/dist/util/types.d.ts.map +1 -0
  136. package/package.json +63 -2
  137. package/src/adapters/adapters.ts +22 -0
  138. package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +433 -0
  139. package/src/adapters/drizzle/drizzle-adapter.test.ts +122 -0
  140. package/src/adapters/drizzle/drizzle-adapter.ts +118 -0
  141. package/src/adapters/drizzle/drizzle-query.ts +234 -0
  142. package/src/adapters/drizzle/drizzle-uow-compiler.test.ts +1084 -0
  143. package/src/adapters/drizzle/drizzle-uow-compiler.ts +546 -0
  144. package/src/adapters/drizzle/drizzle-uow-decoder.ts +165 -0
  145. package/src/adapters/drizzle/drizzle-uow-executor.ts +213 -0
  146. package/src/adapters/drizzle/generate.test.ts +643 -0
  147. package/src/adapters/drizzle/generate.ts +481 -0
  148. package/src/adapters/drizzle/join-column-utils.test.ts +79 -0
  149. package/src/adapters/drizzle/join-column-utils.ts +39 -0
  150. package/src/adapters/drizzle/migrate-drizzle.test.ts +226 -0
  151. package/src/adapters/drizzle/shared.ts +22 -0
  152. package/src/adapters/drizzle/test-utils.ts +56 -0
  153. package/src/adapters/kysely/kysely-adapter-pglite.test.ts +789 -0
  154. package/src/adapters/kysely/kysely-adapter.ts +196 -0
  155. package/src/adapters/kysely/kysely-query-builder.test.ts +1344 -0
  156. package/src/adapters/kysely/kysely-query-builder.ts +611 -0
  157. package/src/adapters/kysely/kysely-query-compiler.ts +124 -0
  158. package/src/adapters/kysely/kysely-query.ts +254 -0
  159. package/src/adapters/kysely/kysely-uow-compiler.test.ts +916 -0
  160. package/src/adapters/kysely/kysely-uow-compiler.ts +271 -0
  161. package/src/adapters/kysely/kysely-uow-executor.ts +149 -0
  162. package/src/adapters/kysely/kysely-uow-joins.test.ts +811 -0
  163. package/src/adapters/kysely/migration/execute-mysql.test.ts +1173 -0
  164. package/src/adapters/kysely/migration/execute-postgres.test.ts +2657 -0
  165. package/src/adapters/kysely/migration/execute.ts +382 -0
  166. package/src/adapters/kysely/migration/kysely-migrator.test.ts +197 -0
  167. package/src/fragment.test.ts +287 -0
  168. package/src/fragment.ts +198 -0
  169. package/src/migration-engine/auto-from-schema.test.ts +118 -58
  170. package/src/migration-engine/auto-from-schema.ts +103 -32
  171. package/src/migration-engine/create.test.ts +34 -46
  172. package/src/migration-engine/create.ts +41 -26
  173. package/src/migration-engine/shared.ts +26 -6
  174. package/src/mod.ts +197 -1
  175. package/src/query/condition-builder.test.ts +379 -0
  176. package/src/query/condition-builder.ts +294 -0
  177. package/src/query/cursor.test.ts +296 -0
  178. package/src/query/cursor.ts +147 -0
  179. package/src/query/orm/orm.ts +92 -0
  180. package/src/query/query-type.test.ts +429 -0
  181. package/src/query/query.ts +200 -0
  182. package/src/query/result-transform.test.ts +795 -0
  183. package/src/query/result-transform.ts +247 -0
  184. package/src/query/unit-of-work-types.test.ts +192 -0
  185. package/src/query/unit-of-work.test.ts +947 -0
  186. package/src/query/unit-of-work.ts +1199 -0
  187. package/src/schema/create.test.ts +653 -110
  188. package/src/schema/create.ts +708 -337
  189. package/src/schema/serialize.test.ts +559 -0
  190. package/src/schema/serialize.ts +359 -0
  191. package/src/schema-generator/schema-generator.ts +12 -0
  192. package/src/shared/config.ts +0 -8
  193. package/src/util/import-generator.ts +28 -0
  194. package/src/util/parse.ts +16 -0
  195. package/src/util/types.ts +4 -0
  196. package/tsconfig.json +1 -1
  197. package/tsdown.config.ts +11 -1
  198. package/vitest.config.ts +3 -0
  199. /package/dist/{cuid.js → id.js} +0 -0
  200. /package/src/{cuid.ts → id.ts} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fragment.js","names":["#name","#schema","#namespace","#dependencies","#services","#createDatabaseContext"],"sources":["../src/fragment.ts"],"sourcesContent":["import type { AnySchema } from \"./schema/create\";\nimport type { AbstractQuery } from \"./query/query\";\nimport type { DatabaseAdapter } from \"./adapters/adapters\";\nimport type { FragnoPublicConfig, FragmentDefinition } from \"@fragno-dev/core\";\n\n/**\n * Extended FragnoPublicConfig that includes a database adapter.\n * Use this type when creating fragments with database support.\n */\nexport type FragnoPublicConfigWithDatabase = FragnoPublicConfig & {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n databaseAdapter: DatabaseAdapter<any>;\n};\n\n/**\n * Additional context provided to database fragments containing the database adapter and ORM instance.\n */\nexport type DatabaseFragmentContext<TSchema extends AnySchema> = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n databaseAdapter: DatabaseAdapter<any>;\n orm: AbstractQuery<TSchema>;\n};\n\nexport class DatabaseFragmentBuilder<\n const TSchema extends AnySchema,\n const TConfig,\n const TDeps = {},\n const TServices extends Record<string, unknown> = {},\n> {\n #name: string;\n #schema?: TSchema;\n #namespace?: string;\n #dependencies?: (\n context: {\n config: TConfig;\n fragnoConfig: FragnoPublicConfig;\n } & DatabaseFragmentContext<TSchema>,\n ) => TDeps;\n #services?: (\n context: {\n config: TConfig;\n fragnoConfig: FragnoPublicConfig;\n deps: TDeps;\n } & DatabaseFragmentContext<TSchema>,\n ) => TServices;\n\n constructor(options: {\n name: string;\n schema?: TSchema;\n namespace?: string;\n dependencies?: (\n context: {\n config: TConfig;\n fragnoConfig: FragnoPublicConfig;\n } & DatabaseFragmentContext<TSchema>,\n ) => TDeps;\n services?: (\n context: {\n config: TConfig;\n fragnoConfig: FragnoPublicConfig;\n deps: TDeps;\n } & DatabaseFragmentContext<TSchema>,\n ) => TServices;\n }) {\n this.#name = options.name;\n this.#schema = options.schema;\n this.#namespace = options.namespace;\n this.#dependencies = options.dependencies;\n this.#services = options.services;\n }\n\n get $requiredOptions(): FragnoPublicConfigWithDatabase {\n throw new Error(\"Type only method. Do not call.\");\n }\n\n get definition(): FragmentDefinition<TConfig, TDeps, TServices> {\n const schema = this.#schema;\n const namespace = this.#namespace ?? \"\";\n const name = this.#name;\n const dependencies = this.#dependencies;\n const services = this.#services;\n\n return {\n name,\n dependencies: (config: TConfig, options: FragnoPublicConfig) => {\n const dbContext = this.#createDatabaseContext(options, schema, namespace, name);\n return dependencies?.({ config, fragnoConfig: options, ...dbContext }) ?? ({} as TDeps);\n },\n services: (config: TConfig, options: FragnoPublicConfig, deps: TDeps) => {\n const dbContext = this.#createDatabaseContext(options, schema, namespace, name);\n return (\n services?.({ config, fragnoConfig: options, deps, ...dbContext }) ?? ({} as TServices)\n );\n },\n additionalContext: {\n databaseSchema: schema,\n databaseNamespace: namespace,\n },\n };\n }\n\n #createDatabaseContext(\n options: FragnoPublicConfig,\n schema: TSchema | undefined,\n namespace: string,\n name: string,\n ): DatabaseFragmentContext<TSchema> {\n // Safe cast: FragnoPublicConfig is extended with databaseAdapter by the user\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const databaseAdapter = (options as any).databaseAdapter as DatabaseAdapter<any> | undefined;\n\n if (!databaseAdapter) {\n throw new Error(`Fragment '${name}' requires a database adapter in options.databaseAdapter`);\n }\n if (!schema) {\n throw new Error(`Fragment '${name}' requires a schema. Use withDatabase() to provide one.`);\n }\n\n // Safe cast: we create a query engine for TSchema and know it will be AbstractQuery<TSchema>\n const orm = databaseAdapter.createQueryEngine(\n schema,\n namespace,\n ) as unknown as AbstractQuery<TSchema>;\n\n return { databaseAdapter, orm };\n }\n\n withDatabase<TNewSchema extends AnySchema>(\n schema: TNewSchema,\n namespace?: string,\n ): DatabaseFragmentBuilder<TNewSchema, TConfig, TDeps, TServices> {\n return new DatabaseFragmentBuilder<TNewSchema, TConfig, TDeps, TServices>({\n name: this.#name,\n schema,\n namespace: namespace ?? this.#name + \"-db\",\n dependencies: this.#dependencies as\n | ((\n context: {\n config: TConfig;\n fragnoConfig: FragnoPublicConfig;\n } & DatabaseFragmentContext<TNewSchema>,\n ) => TDeps)\n | undefined,\n services: this.#services as\n | ((\n context: {\n config: TConfig;\n fragnoConfig: FragnoPublicConfig;\n deps: TDeps;\n } & DatabaseFragmentContext<TNewSchema>,\n ) => TServices)\n | undefined,\n });\n }\n\n withDependencies<TNewDeps>(\n fn: (\n context: {\n config: TConfig;\n fragnoConfig: FragnoPublicConfig;\n } & DatabaseFragmentContext<TSchema>,\n ) => TNewDeps,\n ): DatabaseFragmentBuilder<TSchema, TConfig, TNewDeps, {}> {\n return new DatabaseFragmentBuilder<TSchema, TConfig, TNewDeps, {}>({\n name: this.#name,\n schema: this.#schema,\n namespace: this.#namespace,\n dependencies: fn,\n services: undefined,\n });\n }\n\n withServices<TNewServices extends Record<string, unknown>>(\n fn: (\n context: {\n config: TConfig;\n fragnoConfig: FragnoPublicConfig;\n deps: TDeps;\n } & DatabaseFragmentContext<TSchema>,\n ) => TNewServices,\n ): DatabaseFragmentBuilder<TSchema, TConfig, TDeps, TNewServices> {\n return new DatabaseFragmentBuilder<TSchema, TConfig, TDeps, TNewServices>({\n name: this.#name,\n schema: this.#schema,\n namespace: this.#namespace,\n dependencies: this.#dependencies,\n services: fn,\n });\n }\n}\n\nexport function defineFragmentWithDatabase<TConfig = {}>(\n name: string,\n): DatabaseFragmentBuilder<never, TConfig, {}, {}> {\n return new DatabaseFragmentBuilder<never, TConfig, {}, {}>({\n name,\n });\n}\n"],"mappings":";AAuBA,IAAa,0BAAb,MAAa,wBAKX;CACA;CACA;CACA;CACA;CAMA;CAQA,YAAY,SAiBT;AACD,QAAKA,OAAQ,QAAQ;AACrB,QAAKC,SAAU,QAAQ;AACvB,QAAKC,YAAa,QAAQ;AAC1B,QAAKC,eAAgB,QAAQ;AAC7B,QAAKC,WAAY,QAAQ;;CAG3B,IAAI,mBAAmD;AACrD,QAAM,IAAI,MAAM,iCAAiC;;CAGnD,IAAI,aAA4D;EAC9D,MAAM,SAAS,MAAKH;EACpB,MAAM,YAAY,MAAKC,aAAc;EACrC,MAAM,OAAO,MAAKF;EAClB,MAAM,eAAe,MAAKG;EAC1B,MAAM,WAAW,MAAKC;AAEtB,SAAO;GACL;GACA,eAAe,QAAiB,YAAgC;IAC9D,MAAM,YAAY,MAAKC,sBAAuB,SAAS,QAAQ,WAAW,KAAK;AAC/E,WAAO,eAAe;KAAE;KAAQ,cAAc;KAAS,GAAG;KAAW,CAAC,IAAK,EAAE;;GAE/E,WAAW,QAAiB,SAA6B,SAAgB;IACvE,MAAM,YAAY,MAAKA,sBAAuB,SAAS,QAAQ,WAAW,KAAK;AAC/E,WACE,WAAW;KAAE;KAAQ,cAAc;KAAS;KAAM,GAAG;KAAW,CAAC,IAAK,EAAE;;GAG5E,mBAAmB;IACjB,gBAAgB;IAChB,mBAAmB;IACpB;GACF;;CAGH,uBACE,SACA,QACA,WACA,MACkC;EAGlC,MAAM,kBAAmB,QAAgB;AAEzC,MAAI,CAAC,gBACH,OAAM,IAAI,MAAM,aAAa,KAAK,0DAA0D;AAE9F,MAAI,CAAC,OACH,OAAM,IAAI,MAAM,aAAa,KAAK,yDAAyD;AAS7F,SAAO;GAAE;GAAiB,KALd,gBAAgB,kBAC1B,QACA,UACD;GAE8B;;CAGjC,aACE,QACA,WACgE;AAChE,SAAO,IAAI,wBAA+D;GACxE,MAAM,MAAKL;GACX;GACA,WAAW,aAAa,MAAKA,OAAQ;GACrC,cAAc,MAAKG;GAQnB,UAAU,MAAKC;GAShB,CAAC;;CAGJ,iBACE,IAMyD;AACzD,SAAO,IAAI,wBAAwD;GACjE,MAAM,MAAKJ;GACX,QAAQ,MAAKC;GACb,WAAW,MAAKC;GAChB,cAAc;GACd,UAAU;GACX,CAAC;;CAGJ,aACE,IAOgE;AAChE,SAAO,IAAI,wBAA+D;GACxE,MAAM,MAAKF;GACX,QAAQ,MAAKC;GACb,WAAW,MAAKC;GAChB,cAAc,MAAKC;GACnB,UAAU;GACX,CAAC;;;AAIN,SAAgB,2BACd,MACiD;AACjD,QAAO,IAAI,wBAAgD,EACzD,MACD,CAAC"}
package/dist/id.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import { createId } from "@paralleldrive/cuid2";
2
+ export { createId };
@@ -0,0 +1,116 @@
1
+ import "../schema/create.js";
2
+
3
+ //#region src/migration-engine/auto-from-schema.ts
4
+ /**
5
+ * Generate migration operations from a schema's operation history
6
+ *
7
+ * The schema version number represents the cumulative number of operations applied.
8
+ * This function takes operations from the schema between fromVersion and toVersion,
9
+ * and converts them into migration operations.
10
+ *
11
+ * @param targetSchema - The schema containing the operations history
12
+ * @param fromVersion - The current database version (e.g., 0)
13
+ * @param toVersion - The target version to migrate to (e.g., 5)
14
+ * @param options - Migration generation options
15
+ * @returns Array of migration operations to apply
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const mySchema = schema(s => s
20
+ * .addTable("users", t => t.addColumn("id", idColumn())) // version 1
21
+ * .addTable("posts", t => t.addColumn("id", idColumn())) // version 2
22
+ * );
23
+ *
24
+ * // Generate operations from version 0 to 1 (only creates users table)
25
+ * const operations = generateMigrationFromSchema(mySchema, 0, 1);
26
+ * ```
27
+ */
28
+ function generateMigrationFromSchema(targetSchema, fromVersion, toVersion) {
29
+ if (fromVersion < 0) throw new Error(`fromVersion cannot be negative: ${fromVersion}`);
30
+ if (fromVersion > targetSchema.version) throw new Error(`fromVersion (${fromVersion}) exceeds schema version (${targetSchema.version})`);
31
+ if (toVersion > targetSchema.version) throw new Error(`toVersion (${toVersion}) exceeds schema version (${targetSchema.version})`);
32
+ if (toVersion < fromVersion) throw new Error(`Cannot migrate backwards: toVersion (${toVersion}) < fromVersion (${fromVersion})`);
33
+ const relevantOperations = targetSchema.operations.slice(fromVersion, toVersion);
34
+ const migrationOperations = [];
35
+ for (const op of relevantOperations) if (op.type === "add-table") {
36
+ const columns = [];
37
+ for (const subOp of op.operations) if (subOp.type === "add-column") {
38
+ const col = subOp.column;
39
+ columns.push({
40
+ name: subOp.columnName,
41
+ type: col.type,
42
+ isNullable: col.isNullable,
43
+ role: col.role,
44
+ default: col.default ? {
45
+ value: "value" in col.default ? col.default.value : void 0,
46
+ runtime: "runtime" in col.default ? typeof col.default.runtime === "string" ? col.default.runtime : void 0 : void 0
47
+ } : void 0
48
+ });
49
+ }
50
+ migrationOperations.push({
51
+ type: "create-table",
52
+ name: op.tableName,
53
+ columns
54
+ });
55
+ for (const subOp of op.operations) if (subOp.type === "add-index") migrationOperations.push({
56
+ type: "add-index",
57
+ table: op.tableName,
58
+ name: subOp.name,
59
+ columns: subOp.columns,
60
+ unique: subOp.unique
61
+ });
62
+ else if (subOp.type === "add-foreign-key") migrationOperations.push({
63
+ type: "add-foreign-key",
64
+ table: op.tableName,
65
+ value: {
66
+ name: subOp.name,
67
+ columns: subOp.columns,
68
+ referencedTable: subOp.referencedTable,
69
+ referencedColumns: subOp.referencedColumns
70
+ }
71
+ });
72
+ } else if (op.type === "alter-table") {
73
+ const columnOps = op.operations.filter((o) => o.type === "add-column");
74
+ if (columnOps.length > 0) migrationOperations.push({
75
+ type: "alter-table",
76
+ name: op.tableName,
77
+ value: columnOps.map((o) => {
78
+ const col = o.column;
79
+ return {
80
+ type: "create-column",
81
+ value: {
82
+ name: o.columnName,
83
+ type: col.type,
84
+ isNullable: col.isNullable,
85
+ role: col.role,
86
+ default: col.default ? {
87
+ value: "value" in col.default ? col.default.value : void 0,
88
+ runtime: "runtime" in col.default ? typeof col.default.runtime === "string" ? col.default.runtime : void 0 : void 0
89
+ } : void 0
90
+ }
91
+ };
92
+ })
93
+ });
94
+ for (const subOp of op.operations) if (subOp.type === "add-index") migrationOperations.push({
95
+ type: "add-index",
96
+ table: op.tableName,
97
+ name: subOp.name,
98
+ columns: subOp.columns,
99
+ unique: subOp.unique
100
+ });
101
+ } else if (op.type === "add-reference") migrationOperations.push({
102
+ type: "add-foreign-key",
103
+ table: op.tableName,
104
+ value: {
105
+ name: `${op.tableName}_${op.config.to.table}_${op.referenceName}_fk`,
106
+ columns: [op.config.from.column],
107
+ referencedTable: op.config.to.table,
108
+ referencedColumns: [op.config.to.column]
109
+ }
110
+ });
111
+ return migrationOperations;
112
+ }
113
+
114
+ //#endregion
115
+ export { generateMigrationFromSchema };
116
+ //# sourceMappingURL=auto-from-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-from-schema.js","names":["migrationOperations: MigrationOperation[]","columns: ColumnInfo[]"],"sources":["../../src/migration-engine/auto-from-schema.ts"],"sourcesContent":["import { type AnySchema } from \"../schema/create\";\nimport type { MigrationOperation, ColumnInfo } from \"./shared\";\n\n/**\n * Generate migration operations from a schema's operation history\n *\n * The schema version number represents the cumulative number of operations applied.\n * This function takes operations from the schema between fromVersion and toVersion,\n * and converts them into migration operations.\n *\n * @param targetSchema - The schema containing the operations history\n * @param fromVersion - The current database version (e.g., 0)\n * @param toVersion - The target version to migrate to (e.g., 5)\n * @param options - Migration generation options\n * @returns Array of migration operations to apply\n *\n * @example\n * ```ts\n * const mySchema = schema(s => s\n * .addTable(\"users\", t => t.addColumn(\"id\", idColumn())) // version 1\n * .addTable(\"posts\", t => t.addColumn(\"id\", idColumn())) // version 2\n * );\n *\n * // Generate operations from version 0 to 1 (only creates users table)\n * const operations = generateMigrationFromSchema(mySchema, 0, 1);\n * ```\n */\nexport function generateMigrationFromSchema(\n targetSchema: AnySchema,\n fromVersion: number,\n toVersion: number,\n): MigrationOperation[] {\n if (fromVersion < 0) {\n throw new Error(`fromVersion cannot be negative: ${fromVersion}`);\n }\n\n if (fromVersion > targetSchema.version) {\n throw new Error(\n `fromVersion (${fromVersion}) exceeds schema version (${targetSchema.version})`,\n );\n }\n\n if (toVersion > targetSchema.version) {\n throw new Error(`toVersion (${toVersion}) exceeds schema version (${targetSchema.version})`);\n }\n\n if (toVersion < fromVersion) {\n throw new Error(\n `Cannot migrate backwards: toVersion (${toVersion}) < fromVersion (${fromVersion})`,\n );\n }\n\n // Get operations between fromVersion and toVersion\n // Operations are 1-indexed (operation 0 is version 0→1)\n const relevantOperations = targetSchema.operations.slice(fromVersion, toVersion);\n\n // Convert schema operations to migration operations\n const migrationOperations: MigrationOperation[] = [];\n\n for (const op of relevantOperations) {\n if (op.type === \"add-table\") {\n // Collect columns for create-table operation\n const columns: ColumnInfo[] = [];\n\n for (const subOp of op.operations) {\n if (subOp.type === \"add-column\") {\n const col = subOp.column;\n columns.push({\n name: subOp.columnName,\n type: col.type,\n isNullable: col.isNullable,\n role: col.role,\n default: col.default\n ? {\n value: \"value\" in col.default ? col.default.value : undefined,\n runtime:\n \"runtime\" in col.default\n ? typeof col.default.runtime === \"string\"\n ? col.default.runtime\n : undefined\n : undefined,\n }\n : undefined,\n });\n }\n }\n\n migrationOperations.push({\n type: \"create-table\",\n name: op.tableName,\n columns,\n });\n\n // Add indexes and foreign keys as separate operations\n for (const subOp of op.operations) {\n if (subOp.type === \"add-index\") {\n migrationOperations.push({\n type: \"add-index\",\n table: op.tableName,\n name: subOp.name,\n columns: subOp.columns,\n unique: subOp.unique,\n });\n } else if (subOp.type === \"add-foreign-key\") {\n migrationOperations.push({\n type: \"add-foreign-key\",\n table: op.tableName,\n value: {\n name: subOp.name,\n columns: subOp.columns,\n referencedTable: subOp.referencedTable,\n referencedColumns: subOp.referencedColumns,\n },\n });\n }\n }\n } else if (op.type === \"alter-table\") {\n const columnOps = op.operations.filter((o) => o.type === \"add-column\");\n\n if (columnOps.length > 0) {\n migrationOperations.push({\n type: \"alter-table\",\n name: op.tableName,\n value: columnOps.map((o) => {\n const col = o.column;\n return {\n type: \"create-column\" as const,\n value: {\n name: o.columnName,\n type: col.type,\n isNullable: col.isNullable,\n role: col.role,\n default: col.default\n ? {\n value: \"value\" in col.default ? col.default.value : undefined,\n runtime:\n \"runtime\" in col.default\n ? typeof col.default.runtime === \"string\"\n ? col.default.runtime\n : undefined\n : undefined,\n }\n : undefined,\n },\n };\n }),\n });\n }\n\n // Add indexes as separate operations\n for (const subOp of op.operations) {\n if (subOp.type === \"add-index\") {\n migrationOperations.push({\n type: \"add-index\",\n table: op.tableName,\n name: subOp.name,\n columns: subOp.columns,\n unique: subOp.unique,\n });\n }\n }\n } else if (op.type === \"add-reference\") {\n migrationOperations.push({\n type: \"add-foreign-key\",\n table: op.tableName,\n value: {\n name: `${op.tableName}_${op.config.to.table}_${op.referenceName}_fk`,\n columns: [op.config.from.column],\n referencedTable: op.config.to.table,\n referencedColumns: [op.config.to.column],\n },\n });\n }\n }\n\n return migrationOperations;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,SAAgB,4BACd,cACA,aACA,WACsB;AACtB,KAAI,cAAc,EAChB,OAAM,IAAI,MAAM,mCAAmC,cAAc;AAGnE,KAAI,cAAc,aAAa,QAC7B,OAAM,IAAI,MACR,gBAAgB,YAAY,4BAA4B,aAAa,QAAQ,GAC9E;AAGH,KAAI,YAAY,aAAa,QAC3B,OAAM,IAAI,MAAM,cAAc,UAAU,4BAA4B,aAAa,QAAQ,GAAG;AAG9F,KAAI,YAAY,YACd,OAAM,IAAI,MACR,wCAAwC,UAAU,mBAAmB,YAAY,GAClF;CAKH,MAAM,qBAAqB,aAAa,WAAW,MAAM,aAAa,UAAU;CAGhF,MAAMA,sBAA4C,EAAE;AAEpD,MAAK,MAAM,MAAM,mBACf,KAAI,GAAG,SAAS,aAAa;EAE3B,MAAMC,UAAwB,EAAE;AAEhC,OAAK,MAAM,SAAS,GAAG,WACrB,KAAI,MAAM,SAAS,cAAc;GAC/B,MAAM,MAAM,MAAM;AAClB,WAAQ,KAAK;IACX,MAAM,MAAM;IACZ,MAAM,IAAI;IACV,YAAY,IAAI;IAChB,MAAM,IAAI;IACV,SAAS,IAAI,UACT;KACE,OAAO,WAAW,IAAI,UAAU,IAAI,QAAQ,QAAQ;KACpD,SACE,aAAa,IAAI,UACb,OAAO,IAAI,QAAQ,YAAY,WAC7B,IAAI,QAAQ,UACZ,SACF;KACP,GACD;IACL,CAAC;;AAIN,sBAAoB,KAAK;GACvB,MAAM;GACN,MAAM,GAAG;GACT;GACD,CAAC;AAGF,OAAK,MAAM,SAAS,GAAG,WACrB,KAAI,MAAM,SAAS,YACjB,qBAAoB,KAAK;GACvB,MAAM;GACN,OAAO,GAAG;GACV,MAAM,MAAM;GACZ,SAAS,MAAM;GACf,QAAQ,MAAM;GACf,CAAC;WACO,MAAM,SAAS,kBACxB,qBAAoB,KAAK;GACvB,MAAM;GACN,OAAO,GAAG;GACV,OAAO;IACL,MAAM,MAAM;IACZ,SAAS,MAAM;IACf,iBAAiB,MAAM;IACvB,mBAAmB,MAAM;IAC1B;GACF,CAAC;YAGG,GAAG,SAAS,eAAe;EACpC,MAAM,YAAY,GAAG,WAAW,QAAQ,MAAM,EAAE,SAAS,aAAa;AAEtE,MAAI,UAAU,SAAS,EACrB,qBAAoB,KAAK;GACvB,MAAM;GACN,MAAM,GAAG;GACT,OAAO,UAAU,KAAK,MAAM;IAC1B,MAAM,MAAM,EAAE;AACd,WAAO;KACL,MAAM;KACN,OAAO;MACL,MAAM,EAAE;MACR,MAAM,IAAI;MACV,YAAY,IAAI;MAChB,MAAM,IAAI;MACV,SAAS,IAAI,UACT;OACE,OAAO,WAAW,IAAI,UAAU,IAAI,QAAQ,QAAQ;OACpD,SACE,aAAa,IAAI,UACb,OAAO,IAAI,QAAQ,YAAY,WAC7B,IAAI,QAAQ,UACZ,SACF;OACP,GACD;MACL;KACF;KACD;GACH,CAAC;AAIJ,OAAK,MAAM,SAAS,GAAG,WACrB,KAAI,MAAM,SAAS,YACjB,qBAAoB,KAAK;GACvB,MAAM;GACN,OAAO,GAAG;GACV,MAAM,MAAM;GACZ,SAAS,MAAM;GACf,QAAQ,MAAM;GACf,CAAC;YAGG,GAAG,SAAS,gBACrB,qBAAoB,KAAK;EACvB,MAAM;EACN,OAAO,GAAG;EACV,OAAO;GACL,MAAM,GAAG,GAAG,UAAU,GAAG,GAAG,OAAO,GAAG,MAAM,GAAG,GAAG,cAAc;GAChE,SAAS,CAAC,GAAG,OAAO,KAAK,OAAO;GAChC,iBAAiB,GAAG,OAAO,GAAG;GAC9B,mBAAmB,CAAC,GAAG,OAAO,GAAG,OAAO;GACzC;EACF,CAAC;AAIN,QAAO"}
@@ -0,0 +1,41 @@
1
+ import { MigrationOperation } from "./shared.js";
2
+
3
+ //#region src/migration-engine/create.d.ts
4
+
5
+ interface MigrateOptions {
6
+ /**
7
+ * Update internal settings, it's true by default.
8
+ * We don't recommend to disable it other than testing purposes.
9
+ */
10
+ updateSettings?: boolean;
11
+ }
12
+ interface PreparedMigration {
13
+ operations: MigrationOperation[];
14
+ getSQL?: () => string;
15
+ execute: () => Promise<void>;
16
+ }
17
+ interface Migrator {
18
+ /**
19
+ * Get current version (returns 0 if not initialized)
20
+ */
21
+ getVersion: () => Promise<number>;
22
+ /**
23
+ * Migrate to the latest schema version
24
+ */
25
+ prepareMigration: (options?: MigrateOptions) => Promise<PreparedMigration>;
26
+ /**
27
+ * Migrate to a specific version (only forward migrations allowed)
28
+ * @param toVersion - Target version to migrate to
29
+ * @param options - Migration options including optional fromVersion
30
+ */
31
+ prepareMigrationTo: (toVersion: number, options?: MigrateOptions & {
32
+ fromVersion?: number;
33
+ }) => Promise<PreparedMigration>;
34
+ /**
35
+ * Get default file name for migration SQL
36
+ */
37
+ getDefaultFileName?: (namespace: string, fromVersion: number, toVersion: number) => string;
38
+ }
39
+ //#endregion
40
+ export { Migrator };
41
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","names":[],"sources":["../../src/migration-engine/create.ts"],"sourcesContent":[],"mappings":";;;;AAmC0D,UAvBzC,cAAA,CAuByC;EAAR;;;;EAUpC,cAAA,CAAA,EAAA,OAAA;;UAzBG,iBAAA;cACH;;iBAEG;;UAGA,QAAA;;;;oBAIG;;;;+BAKW,mBAAmB,QAAQ;;;;;;oDAS5C;;QACP,QAAQ"}
@@ -0,0 +1,58 @@
1
+ import { generateMigrationFromSchema } from "./auto-from-schema.js";
2
+
3
+ //#region src/migration-engine/create.ts
4
+ function createMigrator({ settings, generateMigrationFromSchema: generateMigrationFromSchema$1 = generateMigrationFromSchema, schema: targetSchema, executor, sql: sqlConfig, transformers = [] }) {
5
+ return {
6
+ getVersion() {
7
+ return settings.getVersion();
8
+ },
9
+ async prepareMigration(options = {}) {
10
+ return this.prepareMigrationTo(targetSchema.version, options);
11
+ },
12
+ async prepareMigrationTo(toVersion, options = {}) {
13
+ const { updateSettings: updateVersion = true, fromVersion: providedFromVersion } = options;
14
+ const fromVersion = providedFromVersion ?? await settings.getVersion();
15
+ if (toVersion < 0) throw new Error(`Cannot migrate to negative version: ${toVersion}`);
16
+ if (fromVersion < 0) throw new Error(`Cannot migrate from negative version: ${fromVersion}`);
17
+ if (toVersion < fromVersion) throw new Error(`Cannot migrate backwards: current version is ${fromVersion}, target is ${toVersion}. Only forward migrations are supported.`);
18
+ if (toVersion > targetSchema.version) throw new Error(`Cannot migrate to version ${toVersion}: schema only has version ${targetSchema.version}`);
19
+ if (fromVersion > targetSchema.version) throw new Error(`Cannot migrate from version ${fromVersion}: schema only has version ${targetSchema.version}`);
20
+ if (toVersion === fromVersion) return {
21
+ operations: [],
22
+ getSQL: sqlConfig ? () => sqlConfig.toSql([]) : void 0,
23
+ execute: async () => {}
24
+ };
25
+ const context = { async auto() {
26
+ let generated = generateMigrationFromSchema$1(targetSchema, fromVersion, toVersion);
27
+ for (const transformer of transformers) {
28
+ if (!transformer.afterAuto) continue;
29
+ generated = transformer.afterAuto(generated, {
30
+ fromVersion,
31
+ toVersion,
32
+ schema: targetSchema,
33
+ options
34
+ });
35
+ }
36
+ return generated;
37
+ } };
38
+ let operations = updateVersion ? [...await settings.updateSettingsInMigration(fromVersion, toVersion), ...await context.auto()] : await context.auto();
39
+ for (const transformer of transformers) {
40
+ if (!transformer.afterAll) continue;
41
+ operations = transformer.afterAll(operations, {
42
+ fromVersion,
43
+ toVersion,
44
+ schema: targetSchema
45
+ });
46
+ }
47
+ return {
48
+ operations,
49
+ getSQL: sqlConfig ? () => sqlConfig.toSql(operations) : void 0,
50
+ execute: () => executor(operations)
51
+ };
52
+ }
53
+ };
54
+ }
55
+
56
+ //#endregion
57
+ export { createMigrator };
58
+ //# sourceMappingURL=create.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.js","names":["defaultGenerateMigrationFromSchema","context: MigrationContext","generateMigrationFromSchema"],"sources":["../../src/migration-engine/create.ts"],"sourcesContent":["import { type MigrationOperation } from \"./shared\";\nimport type { AnySchema } from \"../schema/create\";\nimport { generateMigrationFromSchema as defaultGenerateMigrationFromSchema } from \"./auto-from-schema\";\n\ntype Awaitable<T> = T | Promise<T>;\n\ninterface MigrationContext {\n auto: () => Promise<MigrationOperation[]>;\n}\n\nexport type CustomMigrationFn = (context: MigrationContext) => Awaitable<MigrationOperation[]>;\n\nexport interface MigrateOptions {\n /**\n * Update internal settings, it's true by default.\n * We don't recommend to disable it other than testing purposes.\n */\n updateSettings?: boolean;\n}\n\nexport interface PreparedMigration {\n operations: MigrationOperation[];\n getSQL?: () => string;\n execute: () => Promise<void>;\n}\n\nexport interface Migrator {\n /**\n * Get current version (returns 0 if not initialized)\n */\n getVersion: () => Promise<number>;\n\n /**\n * Migrate to the latest schema version\n */\n prepareMigration: (options?: MigrateOptions) => Promise<PreparedMigration>;\n\n /**\n * Migrate to a specific version (only forward migrations allowed)\n * @param toVersion - Target version to migrate to\n * @param options - Migration options including optional fromVersion\n */\n prepareMigrationTo: (\n toVersion: number,\n options?: MigrateOptions & { fromVersion?: number },\n ) => Promise<PreparedMigration>;\n\n /**\n * Get default file name for migration SQL\n */\n getDefaultFileName?: (namespace: string, fromVersion: number, toVersion: number) => string;\n}\n\nexport interface MigrationEngineOptions {\n /**\n * The target schema to migrate to\n */\n schema: AnySchema;\n\n executor: (operations: MigrationOperation[]) => Promise<void>;\n\n generateMigrationFromSchema?: typeof defaultGenerateMigrationFromSchema;\n\n settings: {\n /**\n * Get current version from database (0 if not initialized)\n */\n getVersion: () => Promise<number>;\n\n updateSettingsInMigration: (\n fromVersion: number,\n toVersion: number,\n ) => Awaitable<MigrationOperation[]>;\n };\n\n sql?: {\n toSql: (operations: MigrationOperation[]) => string;\n };\n\n transformers?: MigrationTransformer[];\n}\n\nexport interface MigrationTransformer {\n /**\n * Run after auto-generating migration operations\n */\n afterAuto?: (\n operations: MigrationOperation[],\n context: {\n options: MigrateOptions;\n fromVersion: number;\n toVersion: number;\n schema: AnySchema;\n },\n ) => MigrationOperation[];\n\n /**\n * Run on all migration operations\n */\n afterAll?: (\n operations: MigrationOperation[],\n context: {\n fromVersion: number;\n toVersion: number;\n schema: AnySchema;\n },\n ) => MigrationOperation[];\n}\n\nexport function createMigrator({\n settings,\n generateMigrationFromSchema = defaultGenerateMigrationFromSchema,\n schema: targetSchema,\n executor,\n sql: sqlConfig,\n transformers = [],\n}: MigrationEngineOptions): Migrator {\n const instance: Migrator = {\n getVersion() {\n return settings.getVersion();\n },\n async prepareMigration(options = {}) {\n return this.prepareMigrationTo(targetSchema.version, options);\n },\n async prepareMigrationTo(toVersion, options = {}) {\n const { updateSettings: updateVersion = true, fromVersion: providedFromVersion } = options;\n\n // Use provided fromVersion if available, otherwise query the database\n const fromVersion = providedFromVersion ?? (await settings.getVersion());\n\n if (toVersion < 0) {\n throw new Error(`Cannot migrate to negative version: ${toVersion}`);\n }\n\n if (fromVersion < 0) {\n throw new Error(`Cannot migrate from negative version: ${fromVersion}`);\n }\n\n if (toVersion < fromVersion) {\n throw new Error(\n `Cannot migrate backwards: current version is ${fromVersion}, target is ${toVersion}. Only forward migrations are supported.`,\n );\n }\n\n if (toVersion > targetSchema.version) {\n throw new Error(\n `Cannot migrate to version ${toVersion}: schema only has version ${targetSchema.version}`,\n );\n }\n\n if (fromVersion > targetSchema.version) {\n throw new Error(\n `Cannot migrate from version ${fromVersion}: schema only has version ${targetSchema.version}`,\n );\n }\n\n if (toVersion === fromVersion) {\n // Already at target version, return empty migration\n return {\n operations: [],\n getSQL: sqlConfig ? () => sqlConfig.toSql([]) : undefined,\n execute: async () => {},\n };\n }\n\n const context: MigrationContext = {\n async auto() {\n let generated = generateMigrationFromSchema(targetSchema, fromVersion, toVersion);\n\n for (const transformer of transformers) {\n if (!transformer.afterAuto) {\n continue;\n }\n\n generated = transformer.afterAuto(generated, {\n fromVersion,\n toVersion,\n schema: targetSchema,\n options,\n });\n }\n\n return generated;\n },\n };\n\n let operations = updateVersion\n ? [\n ...(await settings.updateSettingsInMigration(fromVersion, toVersion)),\n ...(await context.auto()),\n ]\n : await context.auto();\n\n for (const transformer of transformers) {\n if (!transformer.afterAll) {\n continue;\n }\n operations = transformer.afterAll(operations, {\n fromVersion,\n toVersion,\n schema: targetSchema,\n });\n }\n\n return {\n operations,\n getSQL: sqlConfig ? () => sqlConfig.toSql(operations) : undefined,\n execute: () => executor(operations),\n };\n },\n };\n\n return instance;\n}\n"],"mappings":";;;AA6GA,SAAgB,eAAe,EAC7B,UACA,6DAA8BA,6BAC9B,QAAQ,cACR,UACA,KAAK,WACL,eAAe,EAAE,IACkB;AAgGnC,QA/F2B;EACzB,aAAa;AACX,UAAO,SAAS,YAAY;;EAE9B,MAAM,iBAAiB,UAAU,EAAE,EAAE;AACnC,UAAO,KAAK,mBAAmB,aAAa,SAAS,QAAQ;;EAE/D,MAAM,mBAAmB,WAAW,UAAU,EAAE,EAAE;GAChD,MAAM,EAAE,gBAAgB,gBAAgB,MAAM,aAAa,wBAAwB;GAGnF,MAAM,cAAc,uBAAwB,MAAM,SAAS,YAAY;AAEvE,OAAI,YAAY,EACd,OAAM,IAAI,MAAM,uCAAuC,YAAY;AAGrE,OAAI,cAAc,EAChB,OAAM,IAAI,MAAM,yCAAyC,cAAc;AAGzE,OAAI,YAAY,YACd,OAAM,IAAI,MACR,gDAAgD,YAAY,cAAc,UAAU,0CACrF;AAGH,OAAI,YAAY,aAAa,QAC3B,OAAM,IAAI,MACR,6BAA6B,UAAU,4BAA4B,aAAa,UACjF;AAGH,OAAI,cAAc,aAAa,QAC7B,OAAM,IAAI,MACR,+BAA+B,YAAY,4BAA4B,aAAa,UACrF;AAGH,OAAI,cAAc,YAEhB,QAAO;IACL,YAAY,EAAE;IACd,QAAQ,kBAAkB,UAAU,MAAM,EAAE,CAAC,GAAG;IAChD,SAAS,YAAY;IACtB;GAGH,MAAMC,UAA4B,EAChC,MAAM,OAAO;IACX,IAAI,YAAYC,8BAA4B,cAAc,aAAa,UAAU;AAEjF,SAAK,MAAM,eAAe,cAAc;AACtC,SAAI,CAAC,YAAY,UACf;AAGF,iBAAY,YAAY,UAAU,WAAW;MAC3C;MACA;MACA,QAAQ;MACR;MACD,CAAC;;AAGJ,WAAO;MAEV;GAED,IAAI,aAAa,gBACb,CACE,GAAI,MAAM,SAAS,0BAA0B,aAAa,UAAU,EACpE,GAAI,MAAM,QAAQ,MAAM,CACzB,GACD,MAAM,QAAQ,MAAM;AAExB,QAAK,MAAM,eAAe,cAAc;AACtC,QAAI,CAAC,YAAY,SACf;AAEF,iBAAa,YAAY,SAAS,YAAY;KAC5C;KACA;KACA,QAAQ;KACT,CAAC;;AAGJ,UAAO;IACL;IACA,QAAQ,kBAAkB,UAAU,MAAM,WAAW,GAAG;IACxD,eAAe,SAAS,WAAW;IACpC;;EAEJ"}
@@ -0,0 +1,90 @@
1
+ //#region src/migration-engine/shared.d.ts
2
+ interface ForeignKeyInfo {
3
+ name: string;
4
+ columns: string[];
5
+ referencedTable: string;
6
+ referencedColumns: string[];
7
+ }
8
+ interface ColumnInfo {
9
+ name: string;
10
+ type: "string" | "integer" | "bigint" | "decimal" | "bool" | "date" | "timestamp" | "json" | "binary" | `varchar(${number})`;
11
+ isNullable: boolean;
12
+ role: "external-id" | "internal-id" | "version" | "reference" | "regular";
13
+ default?: {
14
+ value?: unknown;
15
+ runtime?: "now" | "auto";
16
+ };
17
+ }
18
+ type MigrationOperation = TableOperation | {
19
+ type: "add-foreign-key";
20
+ table: string;
21
+ value: ForeignKeyInfo;
22
+ } | {
23
+ type: "drop-foreign-key";
24
+ table: string;
25
+ name: string;
26
+ } | {
27
+ type: "drop-index";
28
+ table: string;
29
+ name: string;
30
+ } | {
31
+ type: "add-index";
32
+ table: string;
33
+ columns: string[];
34
+ name: string;
35
+ unique: boolean;
36
+ } | CustomOperation;
37
+ type CustomOperation = {
38
+ type: "custom";
39
+ } & Record<string, unknown>;
40
+ type TableOperation = {
41
+ type: "create-table";
42
+ name: string;
43
+ columns: ColumnInfo[];
44
+ } | {
45
+ type: "drop-table";
46
+ name: string;
47
+ } | {
48
+ type: "alter-table";
49
+ name: string;
50
+ value: ColumnOperation[];
51
+ } | {
52
+ type: "rename-table";
53
+ from: string;
54
+ to: string;
55
+ };
56
+ type ColumnOperation = {
57
+ type: "rename-column";
58
+ from: string;
59
+ to: string;
60
+ } | {
61
+ type: "drop-column";
62
+ name: string;
63
+ } | {
64
+ /**
65
+ * Note: unique constraints are not created, please use dedicated operations like `add-index` instead
66
+ */
67
+ type: "create-column";
68
+ value: ColumnInfo;
69
+ } | {
70
+ /**
71
+ * warning: Not supported by SQLite
72
+ */
73
+ type: "update-column";
74
+ name: string;
75
+ /**
76
+ * For databases like MySQL, it requires the full definition for any modify column statement.
77
+ * Hence, you need to specify the full information of your column here.
78
+ *
79
+ * Then, opt-in for in-detail modification for other databases that supports changing data type/nullable/default separately, such as PostgreSQL.
80
+ *
81
+ * Note: unique constraints are not updated, please use dedicated operations like `add-index` instead
82
+ */
83
+ value: ColumnInfo;
84
+ updateNullable: boolean;
85
+ updateDefault: boolean;
86
+ updateDataType: boolean;
87
+ };
88
+ //#endregion
89
+ export { MigrationOperation };
90
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.ts","names":[],"sources":["../../src/migration-engine/shared.ts"],"sourcesContent":[],"mappings":";UAAiB,cAAA;EAAA,IAAA,EAAA,MAAA;EAOA,OAAA,EAAA,MAAU,EAAA;EAqBf,eAAA,EAAA,MAAkB;EAC1B,iBAAA,EAAA,MAAA,EAAA;;AAyBA,UA/Ca,UAAA,CA+Cb;EAAe,IAAA,EAAA,MAAA;EAEP,IAAA,EAAA,QAAA,GAAA,SAAe,GAAA,QAEvB,GAAM,SAAA,GAAA,MAAA,GAAA,MAAA,GAAA,WAAA,GAAA,MAAA,GAAA,QAAA,GAAA,WAAA,MAAA,GAAA;EAEE,UAAA,EAAA,OAAc;EAqBd,IAAA,EAAA,aAAe,GAAA,aAed,GAAA,SAgBA,GAAA,WAAU,GAAA,SAAA;;;;;;KApFX,kBAAA,GACR;;;SAKS;;;;;;;;;;;;;;;IAoBT;KAEQ,eAAA;;IAER;KAEQ,cAAA;;;WAIG;;;;;;;SASF;;;;;;KAQD,eAAA;;;;;;;;;;;;SAeC;;;;;;;;;;;;;;;SAgBA"}
@@ -0,0 +1,8 @@
1
+ //#region src/migration-engine/shared.ts
2
+ function isUpdated(op) {
3
+ return op.updateDataType || op.updateDefault || op.updateNullable;
4
+ }
5
+
6
+ //#endregion
7
+ export { isUpdated };
8
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","names":[],"sources":["../../src/migration-engine/shared.ts"],"sourcesContent":["export interface ForeignKeyInfo {\n name: string;\n columns: string[];\n referencedTable: string;\n referencedColumns: string[];\n}\n\nexport interface ColumnInfo {\n name: string;\n type:\n | \"string\"\n | \"integer\"\n | \"bigint\"\n | \"decimal\"\n | \"bool\"\n | \"date\"\n | \"timestamp\"\n | \"json\"\n | \"binary\"\n | `varchar(${number})`;\n isNullable: boolean;\n role: \"external-id\" | \"internal-id\" | \"version\" | \"reference\" | \"regular\";\n default?: {\n value?: unknown;\n runtime?: \"now\" | \"auto\";\n };\n}\n\nexport type MigrationOperation =\n | TableOperation\n | {\n // warning: not supported by SQLite\n type: \"add-foreign-key\";\n table: string;\n value: ForeignKeyInfo;\n }\n | {\n // warning: not supported by SQLite\n type: \"drop-foreign-key\";\n table: string;\n name: string;\n }\n | {\n type: \"drop-index\";\n table: string;\n name: string;\n }\n | {\n type: \"add-index\";\n table: string;\n columns: string[];\n name: string;\n unique: boolean;\n }\n | CustomOperation;\n\nexport type CustomOperation = {\n type: \"custom\";\n} & Record<string, unknown>;\n\nexport type TableOperation =\n | {\n type: \"create-table\";\n name: string;\n columns: ColumnInfo[];\n }\n | {\n type: \"drop-table\";\n name: string;\n }\n | {\n type: \"alter-table\";\n name: string;\n value: ColumnOperation[];\n }\n | {\n type: \"rename-table\";\n from: string;\n to: string;\n };\n\nexport type ColumnOperation =\n | {\n type: \"rename-column\";\n from: string;\n to: string;\n }\n | {\n type: \"drop-column\";\n name: string;\n }\n | {\n /**\n * Note: unique constraints are not created, please use dedicated operations like `add-index` instead\n */\n type: \"create-column\";\n value: ColumnInfo;\n }\n | {\n /**\n * warning: Not supported by SQLite\n */\n type: \"update-column\";\n name: string;\n /**\n * For databases like MySQL, it requires the full definition for any modify column statement.\n * Hence, you need to specify the full information of your column here.\n *\n * Then, opt-in for in-detail modification for other databases that supports changing data type/nullable/default separately, such as PostgreSQL.\n *\n * Note: unique constraints are not updated, please use dedicated operations like `add-index` instead\n */\n value: ColumnInfo;\n\n updateNullable: boolean;\n updateDefault: boolean;\n updateDataType: boolean;\n };\n\nexport function isUpdated(op: Extract<ColumnOperation, { type: \"update-column\" }>): boolean {\n return op.updateDataType || op.updateDefault || op.updateNullable;\n}\n"],"mappings":";AAuHA,SAAgB,UAAU,IAAkE;AAC1F,QAAO,GAAG,kBAAkB,GAAG,iBAAiB,GAAG"}
package/dist/mod.d.ts CHANGED
@@ -1,5 +1,58 @@
1
+ import { AnySchema } from "./schema/create.js";
2
+ import { AbstractQuery } from "./query/query.js";
3
+ import { DatabaseAdapter } from "./adapters/adapters.js";
4
+ import { DatabaseFragmentBuilder, DatabaseFragmentContext, FragnoPublicConfigWithDatabase, defineFragmentWithDatabase } from "./fragment.js";
5
+
1
6
  //#region src/mod.d.ts
2
- declare const hello = "world";
7
+ declare const fragnoDatabaseFakeSymbol: "$fragno-database";
8
+ declare const fragnoDatabaseLibraryVersion: "0.1";
9
+ interface CreateFragnoDatabaseDefinitionOptions<T extends AnySchema> {
10
+ namespace: string;
11
+ schema: T;
12
+ }
13
+ declare function isFragnoDatabase(value: unknown): value is FragnoDatabase<AnySchema>;
14
+ /**
15
+ * Definition of a Fragno database schema and namespace.
16
+ * Created by library authors using defineFragnoDatabase().
17
+ * Apps instantiate it by calling .create(adapter).
18
+ */
19
+ declare class FragnoDatabaseDefinition<const T extends AnySchema> {
20
+ #private;
21
+ constructor(options: CreateFragnoDatabaseDefinitionOptions<T>);
22
+ get namespace(): string;
23
+ get schema(): T;
24
+ /**
25
+ * Creates a FragnoDatabase instance by binding an adapter to this definition.
26
+ */
27
+ create(adapter: DatabaseAdapter): FragnoDatabase<T>;
28
+ }
29
+ /**
30
+ * A Fragno database instance with a bound adapter.
31
+ * Created from a FragnoDatabaseDefinition by calling .create(adapter).
32
+ */
33
+ declare class FragnoDatabase<const T extends AnySchema> {
34
+ #private;
35
+ constructor(options: {
36
+ namespace: string;
37
+ schema: T;
38
+ adapter: DatabaseAdapter;
39
+ });
40
+ get [fragnoDatabaseFakeSymbol](): typeof fragnoDatabaseFakeSymbol;
41
+ createClient(): Promise<AbstractQuery<T>>;
42
+ runMigrations(): Promise<boolean>;
43
+ get namespace(): string;
44
+ get schema(): T;
45
+ get adapter(): DatabaseAdapter<void>;
46
+ generateSchema(options?: {
47
+ path?: string;
48
+ toVersion?: number;
49
+ fromVersion?: number;
50
+ }): Promise<{
51
+ schema: string;
52
+ path: string;
53
+ }>;
54
+ }
55
+ declare function defineFragnoDatabase<const TSchema extends AnySchema>(options: CreateFragnoDatabaseDefinitionOptions<TSchema>): FragnoDatabaseDefinition<TSchema>;
3
56
  //#endregion
4
- export { hello };
57
+ export { CreateFragnoDatabaseDefinitionOptions, type DatabaseAdapter, DatabaseFragmentBuilder, type DatabaseFragmentContext, FragnoDatabase, FragnoDatabaseDefinition, type FragnoPublicConfigWithDatabase, defineFragmentWithDatabase, defineFragnoDatabase, fragnoDatabaseFakeSymbol, fragnoDatabaseLibraryVersion, isFragnoDatabase };
5
58
  //# sourceMappingURL=mod.d.ts.map
package/dist/mod.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mod.d.ts","names":[],"sources":["../src/mod.ts"],"sourcesContent":[],"mappings":";cAAa,KAAA"}
1
+ {"version":3,"file":"mod.d.ts","names":[],"sources":["../src/mod.ts"],"sourcesContent":[],"mappings":";;;;;;cAMa;cACA;AADA,UAGI,qCAHkD,CAAA,UAGF,SAHE,CAAA,CAAA;EACtD,SAAA,EAAA,MAAA;EAEI,MAAA,EAEP,CAFO;AAKjB;AAoBa,iBApBG,gBAAA,CAoBqB,KAAA,EAAA,OAAA,CAAA,EAAA,KAAA,IApBsB,cAoBtB,CApBqC,SAoBrC,CAAA;;;;;;AAoBc,cApBtC,wBAoBsC,CAAA,gBApBG,SAoBH,CAAA,CAAA;EAAf,CAAA,OAAA;EAAc,WAAA,CAAA,OAAA,EAhB3B,qCAgB2B,CAhBW,CAgBX,CAAA;EAarC,IAAA,SAAA,CAAA,CAAA,EAAc,MAAA;EAAiB,IAAA,MAAA,CAAA,CAAA,EApBhC,CAoBgC;EAKQ;;;EAM7C,MAAA,CAAA,OAAA,EAxBW,eAwBX,CAAA,EAxB6B,cAwB7B,CAxB4C,CAwB5C,CAAA;;;;;;AAoCM,cA/CA,cA+CA,CAAA,gBA/C+B,SA+C/B,CAAA,CAAA;EAQP,CAAA,OAAA;EAAO,WAAA,CAAA,OAAA,EAAA;IA+DG,SAAA,EAAA,MAAA;IAA2C,MAAA,EAjHP,CAiHO;IACV,OAAA,EAlHe,eAkHf;EAAtC,CAAA;EACiB,KA7GrB,wBAAA,GA6GqB,EAAA,OA7Ge,wBA6Gf;EAAzB,YAAA,CAAA,CAAA,EAzGqB,OAyGrB,CAzG6B,aAyG7B,CAzG2C,CAyG3C,CAAA,CAAA;EAAwB,aAAA,CAAA,CAAA,EA7FF,OA6FE,CAAA,OAAA,CAAA;;gBA7Ef;iBAIC;;;;;MAQP;;;;;iBA+DU,2CAA2C,oBAChD,sCAAsC,WAC9C,yBAAyB"}
package/dist/mod.js CHANGED
@@ -1,6 +1,115 @@
1
+ import { DatabaseFragmentBuilder, defineFragmentWithDatabase } from "./fragment.js";
2
+
1
3
  //#region src/mod.ts
2
- const hello = "world";
4
+ const fragnoDatabaseFakeSymbol = "$fragno-database";
5
+ const fragnoDatabaseLibraryVersion = "0.1";
6
+ function isFragnoDatabase(value) {
7
+ if (value instanceof FragnoDatabase) return true;
8
+ if (typeof value !== "object" || value === null) return false;
9
+ return fragnoDatabaseFakeSymbol in value && value[fragnoDatabaseFakeSymbol] === fragnoDatabaseFakeSymbol;
10
+ }
11
+ /**
12
+ * Definition of a Fragno database schema and namespace.
13
+ * Created by library authors using defineFragnoDatabase().
14
+ * Apps instantiate it by calling .create(adapter).
15
+ */
16
+ var FragnoDatabaseDefinition = class {
17
+ #namespace;
18
+ #schema;
19
+ constructor(options) {
20
+ this.#namespace = options.namespace;
21
+ this.#schema = options.schema;
22
+ }
23
+ get namespace() {
24
+ return this.#namespace;
25
+ }
26
+ get schema() {
27
+ return this.#schema;
28
+ }
29
+ /**
30
+ * Creates a FragnoDatabase instance by binding an adapter to this definition.
31
+ */
32
+ create(adapter) {
33
+ return new FragnoDatabase({
34
+ namespace: this.#namespace,
35
+ schema: this.#schema,
36
+ adapter
37
+ });
38
+ }
39
+ };
40
+ /**
41
+ * A Fragno database instance with a bound adapter.
42
+ * Created from a FragnoDatabaseDefinition by calling .create(adapter).
43
+ */
44
+ var FragnoDatabase = class {
45
+ #namespace;
46
+ #schema;
47
+ #adapter;
48
+ constructor(options) {
49
+ this.#namespace = options.namespace;
50
+ this.#schema = options.schema;
51
+ this.#adapter = options.adapter;
52
+ }
53
+ get [fragnoDatabaseFakeSymbol]() {
54
+ return fragnoDatabaseFakeSymbol;
55
+ }
56
+ async createClient() {
57
+ const dbVersion = await this.#adapter.getSchemaVersion(this.#namespace);
58
+ if (dbVersion !== this.#schema.version.toString()) throw new Error(`Database is not at expected version. Did you forget to run migrations? Current version: ${dbVersion}, Expected version: ${this.#schema.version}`);
59
+ return this.#adapter.createQueryEngine(this.#schema, this.#namespace);
60
+ }
61
+ async runMigrations() {
62
+ if (!this.#adapter.createMigrationEngine) throw new Error("Migration engine not supported for this adapter.");
63
+ const preparedMigration = await this.#adapter.createMigrationEngine(this.#schema, this.#namespace).prepareMigration();
64
+ await preparedMigration.execute();
65
+ return preparedMigration.operations.length > 0;
66
+ }
67
+ get namespace() {
68
+ return this.#namespace;
69
+ }
70
+ get schema() {
71
+ return this.#schema;
72
+ }
73
+ get adapter() {
74
+ return this.#adapter;
75
+ }
76
+ async generateSchema(options) {
77
+ const adapter = this.#adapter;
78
+ if (adapter.createSchemaGenerator) {
79
+ if (options?.toVersion !== void 0 || options?.fromVersion !== void 0) console.warn("⚠️ toVersion and fromVersion are not supported for schema generation.");
80
+ const generator = adapter.createSchemaGenerator(this.#schema, this.#namespace);
81
+ const defaultPath = options?.path ?? "schema.ts";
82
+ return generator.generateSchema({
83
+ path: defaultPath,
84
+ toVersion: options?.toVersion,
85
+ fromVersion: options?.fromVersion
86
+ });
87
+ }
88
+ if (adapter.createMigrationEngine) {
89
+ const migrator = adapter.createMigrationEngine(this.#schema, this.#namespace);
90
+ const targetVersion = options?.toVersion ?? this.#schema.version;
91
+ const sourceVersion = options?.fromVersion;
92
+ const currentVersion = sourceVersion ?? await migrator.getVersion();
93
+ const defaultPath = options?.path ?? (migrator.getDefaultFileName ? migrator.getDefaultFileName(this.#namespace, currentVersion, targetVersion) : "schema.sql");
94
+ const preparedMigration = await migrator.prepareMigrationTo(targetVersion, {
95
+ updateSettings: true,
96
+ fromVersion: sourceVersion
97
+ });
98
+ if (!preparedMigration.getSQL) throw new Error("Migration engine does not support SQL generation. Ensure your adapter's migration engine provides getSQL().");
99
+ const sql = preparedMigration.getSQL();
100
+ if (!sql.trim()) throw new Error("No migrations needed. Database is already at the target version.");
101
+ return {
102
+ schema: sql,
103
+ path: defaultPath
104
+ };
105
+ }
106
+ throw new Error("Adapter does not support schema generation. Ensure your adapter implements either createSchemaGenerator or createMigrationEngine.");
107
+ }
108
+ };
109
+ function defineFragnoDatabase(options) {
110
+ return new FragnoDatabaseDefinition(options);
111
+ }
3
112
 
4
113
  //#endregion
5
- export { hello };
114
+ export { DatabaseFragmentBuilder, FragnoDatabase, FragnoDatabaseDefinition, defineFragmentWithDatabase, defineFragnoDatabase, fragnoDatabaseFakeSymbol, fragnoDatabaseLibraryVersion, isFragnoDatabase };
6
115
  //# sourceMappingURL=mod.js.map
package/dist/mod.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mod.js","names":[],"sources":["../src/mod.ts"],"sourcesContent":["export const hello = \"world\";\n"],"mappings":";AAAA,MAAa,QAAQ"}
1
+ {"version":3,"file":"mod.js","names":["#namespace","#schema","#adapter"],"sources":["../src/mod.ts"],"sourcesContent":["import type { DatabaseAdapter } from \"./adapters/adapters\";\nimport type { AnySchema } from \"./schema/create\";\nimport type { AbstractQuery } from \"./query/query\";\n\nexport type { DatabaseAdapter };\n\nexport const fragnoDatabaseFakeSymbol = \"$fragno-database\" as const;\nexport const fragnoDatabaseLibraryVersion = \"0.1\" as const;\n\nexport interface CreateFragnoDatabaseDefinitionOptions<T extends AnySchema> {\n namespace: string;\n schema: T;\n}\n\nexport function isFragnoDatabase(value: unknown): value is FragnoDatabase<AnySchema> {\n if (value instanceof FragnoDatabase) {\n return true;\n }\n\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n return (\n fragnoDatabaseFakeSymbol in value &&\n value[fragnoDatabaseFakeSymbol] === fragnoDatabaseFakeSymbol\n );\n}\n\n/**\n * Definition of a Fragno database schema and namespace.\n * Created by library authors using defineFragnoDatabase().\n * Apps instantiate it by calling .create(adapter).\n */\nexport class FragnoDatabaseDefinition<const T extends AnySchema> {\n #namespace: string;\n #schema: T;\n\n constructor(options: CreateFragnoDatabaseDefinitionOptions<T>) {\n this.#namespace = options.namespace;\n this.#schema = options.schema;\n }\n\n get namespace() {\n return this.#namespace;\n }\n\n get schema() {\n return this.#schema;\n }\n\n /**\n * Creates a FragnoDatabase instance by binding an adapter to this definition.\n */\n create(adapter: DatabaseAdapter): FragnoDatabase<T> {\n return new FragnoDatabase({\n namespace: this.#namespace,\n schema: this.#schema,\n adapter,\n });\n }\n}\n\n/**\n * A Fragno database instance with a bound adapter.\n * Created from a FragnoDatabaseDefinition by calling .create(adapter).\n */\nexport class FragnoDatabase<const T extends AnySchema> {\n #namespace: string;\n #schema: T;\n #adapter: DatabaseAdapter;\n\n constructor(options: { namespace: string; schema: T; adapter: DatabaseAdapter }) {\n this.#namespace = options.namespace;\n this.#schema = options.schema;\n this.#adapter = options.adapter;\n }\n\n get [fragnoDatabaseFakeSymbol](): typeof fragnoDatabaseFakeSymbol {\n return fragnoDatabaseFakeSymbol;\n }\n\n async createClient(): Promise<AbstractQuery<T>> {\n const dbVersion = await this.#adapter.getSchemaVersion(this.#namespace);\n if (dbVersion !== this.#schema.version.toString()) {\n throw new Error(\n `Database is not at expected version. Did you forget to run migrations?` +\n ` Current version: ${dbVersion}, Expected version: ${this.#schema.version}`,\n );\n }\n\n return this.#adapter.createQueryEngine(this.#schema, this.#namespace);\n }\n\n async runMigrations(): Promise<boolean> {\n if (!this.#adapter.createMigrationEngine) {\n throw new Error(\"Migration engine not supported for this adapter.\");\n }\n\n const migrator = this.#adapter.createMigrationEngine(this.#schema, this.#namespace);\n const preparedMigration = await migrator.prepareMigration();\n await preparedMigration.execute();\n\n return preparedMigration.operations.length > 0;\n }\n\n get namespace() {\n return this.#namespace;\n }\n\n get schema() {\n return this.#schema;\n }\n\n get adapter() {\n return this.#adapter;\n }\n\n async generateSchema(options?: {\n path?: string;\n toVersion?: number;\n fromVersion?: number;\n }): Promise<{ schema: string; path: string }> {\n const adapter = this.#adapter;\n\n if (adapter.createSchemaGenerator) {\n if (options?.toVersion !== undefined || options?.fromVersion !== undefined) {\n console.warn(\"⚠️ toVersion and fromVersion are not supported for schema generation.\");\n }\n\n const generator = adapter.createSchemaGenerator(this.#schema, this.#namespace);\n const defaultPath = options?.path ?? \"schema.ts\";\n return generator.generateSchema({\n path: defaultPath,\n toVersion: options?.toVersion,\n fromVersion: options?.fromVersion,\n });\n }\n\n if (adapter.createMigrationEngine) {\n const migrator = adapter.createMigrationEngine(this.#schema, this.#namespace);\n const targetVersion = options?.toVersion ?? this.#schema.version;\n const sourceVersion = options?.fromVersion;\n\n // Get current version for file naming if not provided\n const currentVersion = sourceVersion ?? (await migrator.getVersion());\n\n // Determine the default path using the migrator's getDefaultFileName if available\n const defaultPath =\n options?.path ??\n (migrator.getDefaultFileName\n ? migrator.getDefaultFileName(this.#namespace, currentVersion, targetVersion)\n : \"schema.sql\");\n\n // Generate migration from source to target version\n const preparedMigration = await migrator.prepareMigrationTo(targetVersion, {\n updateSettings: true,\n fromVersion: sourceVersion,\n });\n\n if (!preparedMigration.getSQL) {\n throw new Error(\n \"Migration engine does not support SQL generation. Ensure your adapter's migration engine provides getSQL().\",\n );\n }\n\n const sql = preparedMigration.getSQL();\n\n // If no migrations needed, return informative message\n if (!sql.trim()) {\n throw new Error(\"No migrations needed. Database is already at the target version.\");\n }\n\n return {\n schema: sql,\n path: defaultPath,\n };\n }\n\n throw new Error(\n \"Adapter does not support schema generation. Ensure your adapter implements either createSchemaGenerator or createMigrationEngine.\",\n );\n }\n}\n\nexport function defineFragnoDatabase<const TSchema extends AnySchema>(\n options: CreateFragnoDatabaseDefinitionOptions<TSchema>,\n): FragnoDatabaseDefinition<TSchema> {\n return new FragnoDatabaseDefinition(options);\n}\n\nexport {\n defineFragmentWithDatabase,\n DatabaseFragmentBuilder,\n type FragnoPublicConfigWithDatabase,\n type DatabaseFragmentContext,\n} from \"./fragment\";\n"],"mappings":";;;AAMA,MAAa,2BAA2B;AACxC,MAAa,+BAA+B;AAO5C,SAAgB,iBAAiB,OAAoD;AACnF,KAAI,iBAAiB,eACnB,QAAO;AAGT,KAAI,OAAO,UAAU,YAAY,UAAU,KACzC,QAAO;AAGT,QACE,4BAA4B,SAC5B,MAAM,8BAA8B;;;;;;;AASxC,IAAa,2BAAb,MAAiE;CAC/D;CACA;CAEA,YAAY,SAAmD;AAC7D,QAAKA,YAAa,QAAQ;AAC1B,QAAKC,SAAU,QAAQ;;CAGzB,IAAI,YAAY;AACd,SAAO,MAAKD;;CAGd,IAAI,SAAS;AACX,SAAO,MAAKC;;;;;CAMd,OAAO,SAA6C;AAClD,SAAO,IAAI,eAAe;GACxB,WAAW,MAAKD;GAChB,QAAQ,MAAKC;GACb;GACD,CAAC;;;;;;;AAQN,IAAa,iBAAb,MAAuD;CACrD;CACA;CACA;CAEA,YAAY,SAAqE;AAC/E,QAAKD,YAAa,QAAQ;AAC1B,QAAKC,SAAU,QAAQ;AACvB,QAAKC,UAAW,QAAQ;;CAG1B,KAAK,4BAA6D;AAChE,SAAO;;CAGT,MAAM,eAA0C;EAC9C,MAAM,YAAY,MAAM,MAAKA,QAAS,iBAAiB,MAAKF,UAAW;AACvE,MAAI,cAAc,MAAKC,OAAQ,QAAQ,UAAU,CAC/C,OAAM,IAAI,MACR,2FACuB,UAAU,sBAAsB,MAAKA,OAAQ,UACrE;AAGH,SAAO,MAAKC,QAAS,kBAAkB,MAAKD,QAAS,MAAKD,UAAW;;CAGvE,MAAM,gBAAkC;AACtC,MAAI,CAAC,MAAKE,QAAS,sBACjB,OAAM,IAAI,MAAM,mDAAmD;EAIrE,MAAM,oBAAoB,MADT,MAAKA,QAAS,sBAAsB,MAAKD,QAAS,MAAKD,UAAW,CAC1C,kBAAkB;AAC3D,QAAM,kBAAkB,SAAS;AAEjC,SAAO,kBAAkB,WAAW,SAAS;;CAG/C,IAAI,YAAY;AACd,SAAO,MAAKA;;CAGd,IAAI,SAAS;AACX,SAAO,MAAKC;;CAGd,IAAI,UAAU;AACZ,SAAO,MAAKC;;CAGd,MAAM,eAAe,SAIyB;EAC5C,MAAM,UAAU,MAAKA;AAErB,MAAI,QAAQ,uBAAuB;AACjC,OAAI,SAAS,cAAc,UAAa,SAAS,gBAAgB,OAC/D,SAAQ,KAAK,wEAAwE;GAGvF,MAAM,YAAY,QAAQ,sBAAsB,MAAKD,QAAS,MAAKD,UAAW;GAC9E,MAAM,cAAc,SAAS,QAAQ;AACrC,UAAO,UAAU,eAAe;IAC9B,MAAM;IACN,WAAW,SAAS;IACpB,aAAa,SAAS;IACvB,CAAC;;AAGJ,MAAI,QAAQ,uBAAuB;GACjC,MAAM,WAAW,QAAQ,sBAAsB,MAAKC,QAAS,MAAKD,UAAW;GAC7E,MAAM,gBAAgB,SAAS,aAAa,MAAKC,OAAQ;GACzD,MAAM,gBAAgB,SAAS;GAG/B,MAAM,iBAAiB,iBAAkB,MAAM,SAAS,YAAY;GAGpE,MAAM,cACJ,SAAS,SACR,SAAS,qBACN,SAAS,mBAAmB,MAAKD,WAAY,gBAAgB,cAAc,GAC3E;GAGN,MAAM,oBAAoB,MAAM,SAAS,mBAAmB,eAAe;IACzE,gBAAgB;IAChB,aAAa;IACd,CAAC;AAEF,OAAI,CAAC,kBAAkB,OACrB,OAAM,IAAI,MACR,8GACD;GAGH,MAAM,MAAM,kBAAkB,QAAQ;AAGtC,OAAI,CAAC,IAAI,MAAM,CACb,OAAM,IAAI,MAAM,mEAAmE;AAGrF,UAAO;IACL,QAAQ;IACR,MAAM;IACP;;AAGH,QAAM,IAAI,MACR,oIACD;;;AAIL,SAAgB,qBACd,SACmC;AACnC,QAAO,IAAI,yBAAyB,QAAQ"}