@fragno-dev/db 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +327 -160
- package/CHANGELOG.md +74 -0
- package/README.md +24 -0
- package/dist/adapters/adapters.d.ts +1 -1
- package/dist/adapters/adapters.d.ts.map +1 -1
- package/dist/adapters/adapters.js.map +1 -1
- package/dist/adapters/generic-sql/generic-sql-adapter.d.ts +0 -3
- package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -1
- package/dist/adapters/generic-sql/generic-sql-adapter.js +11 -12
- package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -1
- package/dist/adapters/generic-sql/generic-sql-uow-executor.js +46 -6
- package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -1
- package/dist/adapters/generic-sql/migration/cold-kysely.js.map +1 -1
- package/dist/adapters/generic-sql/migration/dialect/mysql.js +1 -1
- package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -1
- package/dist/adapters/generic-sql/migration/dialect/postgres.js +1 -1
- package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -1
- package/dist/adapters/generic-sql/migration/dialect/sqlite.js +185 -19
- package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -1
- package/dist/adapters/generic-sql/migration/executor.d.ts.map +1 -1
- package/dist/adapters/generic-sql/migration/executor.js +30 -3
- package/dist/adapters/generic-sql/migration/executor.js.map +1 -1
- package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -1
- package/dist/adapters/generic-sql/migration/prepared-migrations.js +3 -3
- package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -1
- package/dist/adapters/generic-sql/migration/sql-generator.js +1 -1
- package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -1
- package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +1 -1
- package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -1
- package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -1
- package/dist/adapters/generic-sql/query/db-now-sql.js +27 -0
- package/dist/adapters/generic-sql/query/db-now-sql.js.map +1 -0
- package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +9 -6
- package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -1
- package/dist/adapters/generic-sql/query/select-builder.js.map +1 -1
- package/dist/adapters/generic-sql/query/sql-query-compiler.js +37 -9
- package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -1
- package/dist/adapters/generic-sql/query/where-builder.js +24 -20
- package/dist/adapters/generic-sql/query/where-builder.js.map +1 -1
- package/dist/adapters/generic-sql/uow-decoder.js +1 -1
- package/dist/adapters/generic-sql/uow-decoder.js.map +1 -1
- package/dist/adapters/generic-sql/uow-encoder.js +8 -9
- package/dist/adapters/generic-sql/uow-encoder.js.map +1 -1
- package/dist/adapters/in-memory/condition-evaluator.js +10 -6
- package/dist/adapters/in-memory/condition-evaluator.js.map +1 -1
- package/dist/adapters/in-memory/in-memory-adapter.d.ts.map +1 -1
- package/dist/adapters/in-memory/in-memory-adapter.js +45 -25
- package/dist/adapters/in-memory/in-memory-adapter.js.map +1 -1
- package/dist/adapters/in-memory/in-memory-uow.js +236 -13
- package/dist/adapters/in-memory/in-memory-uow.js.map +1 -1
- package/dist/adapters/in-memory/options.d.ts +2 -0
- package/dist/adapters/in-memory/options.d.ts.map +1 -1
- package/dist/adapters/in-memory/options.js +3 -2
- package/dist/adapters/in-memory/options.js.map +1 -1
- package/dist/adapters/in-memory/reference-resolution.js.map +1 -1
- package/dist/adapters/in-memory/store.js +1 -1
- package/dist/adapters/in-memory/store.js.map +1 -1
- package/dist/adapters/shared/from-unit-of-work-compiler.js +51 -24
- package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -1
- package/dist/adapters/shared/uow-operation-compiler.js.map +1 -1
- package/dist/browser/adapters/adapters.d.ts +61 -0
- package/dist/browser/adapters/adapters.d.ts.map +1 -0
- package/dist/browser/adapters/generic-sql/migration/executor.d.ts +15 -0
- package/dist/browser/adapters/generic-sql/migration/executor.d.ts.map +1 -0
- package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts +66 -0
- package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -0
- package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts +11 -0
- package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
- package/dist/browser/adapters/in-memory/in-memory-adapter.d.ts +5 -0
- package/dist/browser/adapters/in-memory/index.d.ts +2 -0
- package/dist/browser/adapters/in-memory/options.d.ts +1 -0
- package/dist/browser/db-fragment-definition-builder.d.ts +237 -0
- package/dist/browser/db-fragment-definition-builder.d.ts.map +1 -0
- package/dist/browser/durable-hooks.d.ts +3 -0
- package/dist/browser/fragments/internal-fragment.d.ts +317 -0
- package/dist/browser/fragments/internal-fragment.d.ts.map +1 -0
- package/dist/browser/fragments/internal-fragment.schema.d.ts +1 -0
- package/dist/browser/hooks/durable-hooks-logger.d.ts +10 -0
- package/dist/browser/hooks/durable-hooks-logger.d.ts.map +1 -0
- package/dist/browser/hooks/hooks.d.ts +146 -0
- package/dist/browser/hooks/hooks.d.ts.map +1 -0
- package/dist/browser/id.js +1 -0
- package/dist/browser/internal/adapter-registry.d.ts +4 -0
- package/dist/browser/internal/outbox-state.d.ts +2 -0
- package/dist/browser/mod.d.ts +15 -0
- package/dist/browser/mod.d.ts.map +1 -0
- package/dist/browser/mod.js +17 -0
- package/dist/browser/mod.js.map +1 -0
- package/dist/browser/mod2.d.ts +48 -0
- package/dist/browser/mod2.d.ts.map +1 -0
- package/dist/browser/naming/sql-naming.d.ts +19 -0
- package/dist/browser/naming/sql-naming.d.ts.map +1 -0
- package/dist/browser/outbox/outbox.d.ts +21 -0
- package/dist/browser/outbox/outbox.d.ts.map +1 -0
- package/dist/browser/query/column-defaults.js +1 -0
- package/dist/browser/query/condition-builder.d.ts +44 -0
- package/dist/browser/query/condition-builder.d.ts.map +1 -0
- package/dist/browser/query/condition-builder.js +97 -0
- package/dist/browser/query/condition-builder.js.map +1 -0
- package/dist/browser/query/cursor.d.ts +105 -0
- package/dist/browser/query/cursor.d.ts.map +1 -0
- package/dist/browser/query/cursor.js +150 -0
- package/dist/browser/query/cursor.js.map +1 -0
- package/dist/browser/query/db-now.d.ts +22 -0
- package/dist/browser/query/db-now.d.ts.map +1 -0
- package/dist/browser/query/db-now.js +33 -0
- package/dist/browser/query/db-now.js.map +1 -0
- package/dist/browser/query/orm/orm.d.ts +18 -0
- package/dist/browser/query/orm/orm.d.ts.map +1 -0
- package/dist/browser/query/simple-query-interface.d.ts +108 -0
- package/dist/browser/query/simple-query-interface.d.ts.map +1 -0
- package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts +423 -0
- package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -0
- package/dist/browser/query/unit-of-work/execute-unit-of-work.js +507 -0
- package/dist/browser/query/unit-of-work/execute-unit-of-work.js.map +1 -0
- package/dist/browser/query/unit-of-work/retry-policy.d.ts +23 -0
- package/dist/browser/query/unit-of-work/retry-policy.d.ts.map +1 -0
- package/dist/browser/query/unit-of-work/retry-policy.js +40 -0
- package/dist/browser/query/unit-of-work/retry-policy.js.map +1 -0
- package/dist/browser/query/unit-of-work/unit-of-work.d.ts +703 -0
- package/dist/browser/query/unit-of-work/unit-of-work.d.ts.map +1 -0
- package/dist/browser/query/unit-of-work/unit-of-work.js +1206 -0
- package/dist/browser/query/unit-of-work/unit-of-work.js.map +1 -0
- package/dist/browser/query/value-encoding.js +38 -0
- package/dist/browser/query/value-encoding.js.map +1 -0
- package/dist/browser/schema/create.d.ts +326 -0
- package/dist/browser/schema/create.d.ts.map +1 -0
- package/dist/browser/schema/create.js +89 -0
- package/dist/browser/schema/create.js.map +1 -0
- package/dist/browser/schema/generate-id.js +28 -0
- package/dist/browser/schema/generate-id.js.map +1 -0
- package/dist/browser/shared/providers.d.ts +6 -0
- package/dist/browser/shared/providers.d.ts.map +1 -0
- package/dist/browser/sql-driver/connection/connection-provider.d.ts +13 -0
- package/dist/browser/sql-driver/connection/connection-provider.d.ts.map +1 -0
- package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts +7 -0
- package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts.map +1 -0
- package/dist/browser/sql-driver/driver/runtime-driver.d.ts +23 -0
- package/dist/browser/sql-driver/driver/runtime-driver.d.ts.map +1 -0
- package/dist/browser/sql-driver/query-executor/plugin.d.ts +17 -0
- package/dist/browser/sql-driver/query-executor/plugin.d.ts.map +1 -0
- package/dist/browser/sql-driver/query-executor/query-executor.d.ts +36 -0
- package/dist/browser/sql-driver/query-executor/query-executor.d.ts.map +1 -0
- package/dist/browser/sql-driver/sql-driver-adapter.d.ts +29 -0
- package/dist/browser/sql-driver/sql-driver-adapter.d.ts.map +1 -0
- package/dist/browser/sql-driver/sql-driver.d.ts +38 -0
- package/dist/browser/sql-driver/sql-driver.d.ts.map +1 -0
- package/dist/browser/sync/commands.d.ts +15 -0
- package/dist/browser/sync/commands.d.ts.map +1 -0
- package/dist/browser/sync/commands.js +27 -0
- package/dist/browser/sync/commands.js.map +1 -0
- package/dist/browser/sync/types.d.ts +63 -0
- package/dist/browser/sync/types.d.ts.map +1 -0
- package/dist/browser/util/types.d.ts +8 -0
- package/dist/browser/util/types.d.ts.map +1 -0
- package/dist/browser/with-database.d.ts +29 -0
- package/dist/browser/with-database.d.ts.map +1 -0
- package/dist/client.d.ts +4 -0
- package/dist/client.js +5 -0
- package/dist/db-fragment-definition-builder.d.ts +85 -28
- package/dist/db-fragment-definition-builder.d.ts.map +1 -1
- package/dist/db-fragment-definition-builder.js +374 -46
- package/dist/db-fragment-definition-builder.js.map +1 -1
- package/dist/dispatchers/cloudflare-do/dispatcher.d.ts +20 -0
- package/dist/dispatchers/cloudflare-do/dispatcher.d.ts.map +1 -0
- package/dist/dispatchers/cloudflare-do/dispatcher.js +147 -0
- package/dist/dispatchers/cloudflare-do/dispatcher.js.map +1 -0
- package/dist/dispatchers/cloudflare-do/index.d.ts +5 -20
- package/dist/dispatchers/cloudflare-do/index.d.ts.map +1 -1
- package/dist/dispatchers/cloudflare-do/index.js +23 -55
- package/dist/dispatchers/cloudflare-do/index.js.map +1 -1
- package/dist/dispatchers/node/dispatcher.d.ts +14 -0
- package/dist/dispatchers/node/dispatcher.d.ts.map +1 -0
- package/dist/dispatchers/node/dispatcher.js +80 -0
- package/dist/dispatchers/node/dispatcher.js.map +1 -0
- package/dist/dispatchers/node/index.d.ts +5 -10
- package/dist/dispatchers/node/index.d.ts.map +1 -1
- package/dist/dispatchers/node/index.js +21 -53
- package/dist/dispatchers/node/index.js.map +1 -1
- package/dist/durable-hooks.d.ts +31 -0
- package/dist/durable-hooks.d.ts.map +1 -0
- package/dist/durable-hooks.js +23 -0
- package/dist/durable-hooks.js.map +1 -0
- package/dist/fragments/internal-fragment.d.ts +128 -27
- package/dist/fragments/internal-fragment.d.ts.map +1 -1
- package/dist/fragments/internal-fragment.js +125 -78
- package/dist/fragments/internal-fragment.js.map +1 -1
- package/dist/fragments/internal-fragment.routes.js +138 -3
- package/dist/fragments/internal-fragment.routes.js.map +1 -1
- package/dist/fragments/internal-fragment.schema.d.ts +7 -1
- package/dist/fragments/internal-fragment.schema.d.ts.map +1 -1
- package/dist/fragments/internal-fragment.schema.js +18 -1
- package/dist/fragments/internal-fragment.schema.js.map +1 -1
- package/dist/hooks/durable-hooks-logger.d.ts +10 -0
- package/dist/hooks/durable-hooks-logger.d.ts.map +1 -0
- package/dist/hooks/durable-hooks-logger.js +75 -0
- package/dist/hooks/durable-hooks-logger.js.map +1 -0
- package/dist/hooks/durable-hooks-processor.d.ts +1 -14
- package/dist/hooks/durable-hooks-processor.js +58 -10
- package/dist/hooks/durable-hooks-processor.js.map +1 -1
- package/dist/hooks/durable-hooks-runtime.js +44 -0
- package/dist/hooks/durable-hooks-runtime.js.map +1 -0
- package/dist/hooks/hooks.d.ts +60 -2
- package/dist/hooks/hooks.d.ts.map +1 -1
- package/dist/hooks/hooks.js +214 -53
- package/dist/hooks/hooks.js.map +1 -1
- package/dist/id.d.ts +2 -2
- package/dist/id.js +2 -2
- package/dist/internal/adapter-registry.d.ts +11 -0
- package/dist/internal/adapter-registry.d.ts.map +1 -0
- package/dist/internal/adapter-registry.js +135 -0
- package/dist/internal/adapter-registry.js.map +1 -0
- package/dist/internal/outbox-state.d.ts +2 -0
- package/dist/internal/outbox-state.js +26 -0
- package/dist/internal/outbox-state.js.map +1 -0
- package/dist/migration-engine/auto-from-schema.d.ts +33 -0
- package/dist/migration-engine/auto-from-schema.d.ts.map +1 -0
- package/dist/migration-engine/auto-from-schema.js +210 -27
- package/dist/migration-engine/auto-from-schema.js.map +1 -1
- package/dist/migration-engine/generation-engine.d.ts.map +1 -1
- package/dist/migration-engine/generation-engine.js +17 -5
- package/dist/migration-engine/generation-engine.js.map +1 -1
- package/dist/migration-engine/shared.d.ts +113 -0
- package/dist/migration-engine/shared.d.ts.map +1 -0
- package/dist/migration-engine/shared.js.map +1 -1
- package/dist/mod.d.ts +12 -11
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +10 -10
- package/dist/mod.js.map +1 -1
- package/dist/naming/sql-naming.d.ts.map +1 -1
- package/dist/naming/sql-naming.js.map +1 -1
- package/dist/outbox/outbox-builder.js.map +1 -1
- package/dist/outbox/outbox.d.ts +3 -1
- package/dist/outbox/outbox.d.ts.map +1 -1
- package/dist/outbox/outbox.js.map +1 -1
- package/dist/query/column-defaults.js.map +1 -1
- package/dist/query/condition-builder.d.ts +7 -1
- package/dist/query/condition-builder.d.ts.map +1 -1
- package/dist/query/condition-builder.js +5 -1
- package/dist/query/condition-builder.js.map +1 -1
- package/dist/query/cursor-client.d.ts +105 -0
- package/dist/query/cursor-client.d.ts.map +1 -0
- package/dist/query/cursor-client.js +165 -0
- package/dist/query/cursor-client.js.map +1 -0
- package/dist/query/cursor.d.ts.map +1 -1
- package/dist/query/cursor.js +7 -1
- package/dist/query/cursor.js.map +1 -1
- package/dist/query/db-now.d.ts +15 -1
- package/dist/query/db-now.d.ts.map +1 -1
- package/dist/query/db-now.js +30 -2
- package/dist/query/db-now.js.map +1 -1
- package/dist/query/orm/orm.js.map +1 -1
- package/dist/query/serialize/create-sql-serializer.js +2 -2
- package/dist/query/serialize/create-sql-serializer.js.map +1 -1
- package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -1
- package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -1
- package/dist/query/serialize/dialect/sqlite-serializer.js +6 -2
- package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -1
- package/dist/query/simple-query-interface.d.ts +7 -3
- package/dist/query/simple-query-interface.d.ts.map +1 -1
- package/dist/query/unit-of-work/execute-unit-of-work.d.ts +37 -2
- package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -1
- package/dist/query/unit-of-work/execute-unit-of-work.js +39 -18
- package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -1
- package/dist/query/unit-of-work/unit-of-work.d.ts +42 -16
- package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
- package/dist/query/unit-of-work/unit-of-work.js +50 -6
- package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
- package/dist/query/value-decoding.js +8 -1
- package/dist/query/value-decoding.js.map +1 -1
- package/dist/query/value-encoding.js.map +1 -1
- package/dist/schema/create.d.ts +69 -25
- package/dist/schema/create.d.ts.map +1 -1
- package/dist/schema/create.js +91 -16
- package/dist/schema/create.js.map +1 -1
- package/dist/schema/type-conversion/create-sql-type-mapper.js +1 -1
- package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -1
- package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -1
- package/dist/schema/validator.d.ts.map +1 -1
- package/dist/schema/validator.js.map +1 -1
- package/dist/schema-output/drizzle.d.ts.map +1 -1
- package/dist/schema-output/drizzle.js +8 -6
- package/dist/schema-output/drizzle.js.map +1 -1
- package/dist/schema-output/prisma.d.ts.map +1 -1
- package/dist/schema-output/prisma.js +21 -10
- package/dist/schema-output/prisma.js.map +1 -1
- package/dist/sql-driver/dialects/durable-object-dialect.js +3 -9
- package/dist/sql-driver/dialects/durable-object-dialect.js.map +1 -1
- package/dist/sql-driver/query-executor/default-query-executor.js.map +1 -1
- package/dist/sql-driver/query-executor/query-executor-base.js.map +1 -1
- package/dist/sql-driver/sql-driver-adapter.js.map +1 -1
- package/dist/sql-driver/sql.js.map +1 -1
- package/dist/sync/commands.d.ts +15 -0
- package/dist/sync/commands.d.ts.map +1 -0
- package/dist/sync/commands.js +27 -0
- package/dist/sync/commands.js.map +1 -0
- package/dist/sync/index.d.ts +4 -0
- package/dist/sync/index.js +4 -0
- package/dist/sync/read-tracking.d.ts +25 -0
- package/dist/sync/read-tracking.d.ts.map +1 -0
- package/dist/sync/read-tracking.js +148 -0
- package/dist/sync/read-tracking.js.map +1 -0
- package/dist/sync/submit.js +213 -0
- package/dist/sync/submit.js.map +1 -0
- package/dist/sync/types.d.ts +63 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/util/default-database-adapter.js +6 -1
- package/dist/util/default-database-adapter.js.map +1 -1
- package/dist/with-database.d.ts +3 -6
- package/dist/with-database.d.ts.map +1 -1
- package/dist/with-database.js +7 -15
- package/dist/with-database.js.map +1 -1
- package/package.json +33 -41
- package/src/adapters/adapters.ts +5 -4
- package/src/adapters/drizzle/migrate-drizzle.test.ts +46 -9
- package/src/adapters/drizzle/migration-parity-drizzle-kit.test.ts +5 -3
- package/src/adapters/drizzle/test-utils.ts +2 -1
- package/src/adapters/generic-sql/generic-sql-adapter.test.ts +5 -3
- package/src/adapters/generic-sql/generic-sql-adapter.ts +21 -24
- package/src/adapters/generic-sql/generic-sql-uow-executor.test.ts +1 -0
- package/src/adapters/generic-sql/generic-sql-uow-executor.ts +81 -15
- package/src/adapters/generic-sql/migration/adapter-migration-parity.test.ts +4 -2
- package/src/adapters/generic-sql/migration/cold-kysely.ts +1 -0
- package/src/adapters/generic-sql/migration/dialect/mysql.test.ts +3 -2
- package/src/adapters/generic-sql/migration/dialect/mysql.ts +1 -0
- package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +5 -4
- package/src/adapters/generic-sql/migration/dialect/postgres.ts +2 -1
- package/src/adapters/generic-sql/migration/dialect/sqlite.test.ts +795 -3
- package/src/adapters/generic-sql/migration/dialect/sqlite.ts +385 -57
- package/src/adapters/generic-sql/migration/executor.test.ts +52 -0
- package/src/adapters/generic-sql/migration/executor.ts +47 -4
- package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +117 -14
- package/src/adapters/generic-sql/migration/prepared-migrations.ts +9 -8
- package/src/adapters/generic-sql/migration/sql-generator.ts +5 -3
- package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +3 -3
- package/src/adapters/generic-sql/query/cursor-utils.test.ts +3 -2
- package/src/adapters/generic-sql/query/cursor-utils.ts +1 -1
- package/src/adapters/generic-sql/query/db-now-sql.ts +49 -0
- package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +144 -8
- package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +16 -17
- package/src/adapters/generic-sql/query/select-builder.test.ts +1 -0
- package/src/adapters/generic-sql/query/select-builder.ts +2 -2
- package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +24 -5
- package/src/adapters/generic-sql/query/sql-query-compiler.ts +83 -13
- package/src/adapters/generic-sql/query/where-builder.test.ts +7 -5
- package/src/adapters/generic-sql/query/where-builder.ts +48 -29
- package/src/adapters/generic-sql/sql-adapter-pglite-migrations.test.ts +6 -15
- package/src/adapters/generic-sql/sql-adapter-pglite-pagination.test.ts +52 -7
- package/src/adapters/generic-sql/sql-adapter-pglite-queries.test.ts +9 -6
- package/src/adapters/generic-sql/sql-adapter-sqlite3-driver.test.ts +273 -5
- package/src/adapters/generic-sql/sql-adapter-sqlite3-uow.test.ts +123 -6
- package/src/adapters/generic-sql/sql-adapter-sqlocal.test.ts +4 -2
- package/src/adapters/generic-sql/uow-decoder.test.ts +4 -3
- package/src/adapters/generic-sql/uow-decoder.ts +3 -3
- package/src/adapters/generic-sql/uow-encoder.test.ts +4 -2
- package/src/adapters/generic-sql/uow-encoder.ts +14 -18
- package/src/adapters/in-memory/condition-evaluator.test.ts +2 -1
- package/src/adapters/in-memory/condition-evaluator.ts +9 -4
- package/src/adapters/in-memory/in-memory-adapter.ts +155 -44
- package/src/adapters/in-memory/in-memory-uow.mutations.test.ts +50 -2
- package/src/adapters/in-memory/in-memory-uow.retrieval.test.ts +158 -3
- package/src/adapters/in-memory/in-memory-uow.ts +402 -26
- package/src/adapters/in-memory/options.test.ts +1 -0
- package/src/adapters/in-memory/options.ts +5 -1
- package/src/adapters/in-memory/outbox.test.ts +361 -0
- package/src/adapters/in-memory/reference-resolution.test.ts +3 -2
- package/src/adapters/in-memory/reference-resolution.ts +2 -2
- package/src/adapters/in-memory/sorted-array-index.test.ts +1 -0
- package/src/adapters/in-memory/store.test.ts +1 -0
- package/src/adapters/in-memory/store.ts +3 -3
- package/src/adapters/in-memory/value-normalization.test.ts +1 -0
- package/src/adapters/prisma/prisma-adapter-sqlite3.test.ts +51 -7
- package/src/adapters/shared/from-unit-of-work-compiler.ts +156 -46
- package/src/adapters/shared/uow-operation-compiler.ts +3 -3
- package/src/browser/mod.ts +64 -0
- package/src/client.ts +19 -0
- package/src/db-fragment-definition-builder.test.ts +821 -47
- package/src/db-fragment-definition-builder.ts +857 -110
- package/src/db-fragment-instantiator.test.ts +114 -90
- package/src/db-fragment-integration.test.ts +9 -6
- package/src/dispatchers/cloudflare-do/dispatcher.ts +204 -0
- package/src/dispatchers/cloudflare-do/index.test.ts +145 -12
- package/src/dispatchers/cloudflare-do/index.ts +49 -90
- package/src/dispatchers/node/dispatcher.ts +112 -0
- package/src/dispatchers/node/index.test.ts +43 -14
- package/src/dispatchers/node/index.ts +38 -75
- package/src/durable-hooks.test.ts +80 -0
- package/src/durable-hooks.ts +67 -0
- package/src/fragments/internal-fragment.routes.test.ts +570 -0
- package/src/fragments/internal-fragment.routes.ts +297 -5
- package/src/fragments/internal-fragment.schema.ts +45 -1
- package/src/fragments/internal-fragment.test.ts +223 -251
- package/src/fragments/internal-fragment.ts +278 -154
- package/src/hooks/durable-hooks-logger.ts +126 -0
- package/src/hooks/durable-hooks-processor.pglite.test.ts +87 -0
- package/src/hooks/durable-hooks-processor.test.ts +179 -14
- package/src/hooks/durable-hooks-processor.ts +120 -14
- package/src/hooks/durable-hooks-runtime.test.ts +65 -0
- package/src/hooks/durable-hooks-runtime.ts +81 -0
- package/src/hooks/hooks.test.ts +314 -53
- package/src/hooks/hooks.ts +360 -81
- package/src/id.test.ts +34 -0
- package/src/id.ts +1 -3
- package/src/internal/adapter-registry.test.ts +93 -0
- package/src/internal/adapter-registry.ts +239 -0
- package/src/internal/outbox-state.ts +43 -0
- package/src/migration-engine/auto-from-schema.test.ts +93 -0
- package/src/migration-engine/auto-from-schema.ts +360 -42
- package/src/migration-engine/create.test.ts +2 -1
- package/src/migration-engine/create.ts +1 -1
- package/src/migration-engine/generation-engine.test.ts +66 -9
- package/src/migration-engine/generation-engine.ts +31 -10
- package/src/migration-engine/shared.ts +13 -0
- package/src/mod.ts +45 -27
- package/src/naming/sql-naming.ts +1 -0
- package/src/outbox/outbox-builder.ts +2 -2
- package/src/outbox/outbox.test.ts +216 -45
- package/src/outbox/outbox.ts +3 -1
- package/src/query/column-defaults.ts +1 -1
- package/src/query/condition-builder.test.ts +15 -0
- package/src/query/condition-builder.ts +7 -0
- package/src/query/cursor-client.test.ts +70 -0
- package/src/query/cursor-client.ts +263 -0
- package/src/query/cursor.test.ts +3 -2
- package/src/query/cursor.ts +15 -3
- package/src/query/db-now.ts +69 -2
- package/src/query/orm/orm.ts +2 -2
- package/src/query/query-type.test.ts +2 -1
- package/src/query/serialize/create-sql-serializer.ts +3 -3
- package/src/query/serialize/dialect/mysql-serializer.ts +1 -1
- package/src/query/serialize/dialect/postgres-serializer.ts +1 -1
- package/src/query/serialize/dialect/sqlite-serializer.test.ts +39 -2
- package/src/query/serialize/dialect/sqlite-serializer.ts +18 -5
- package/src/query/simple-query-interface.ts +10 -4
- package/src/query/unit-of-work/execute-unit-of-work.test.ts +347 -9
- package/src/query/unit-of-work/execute-unit-of-work.ts +63 -20
- package/src/query/unit-of-work/retry-policy.test.ts +1 -0
- package/src/query/unit-of-work/tx-builder.test.ts +73 -1
- package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +5 -4
- package/src/query/unit-of-work/unit-of-work-types.test.ts +41 -11
- package/src/query/unit-of-work/unit-of-work.test.ts +28 -2
- package/src/query/unit-of-work/unit-of-work.ts +105 -19
- package/src/query/value-decoding.test.ts +50 -2
- package/src/query/value-decoding.ts +17 -4
- package/src/query/value-encoding.test.ts +1 -0
- package/src/query/value-encoding.ts +1 -1
- package/src/schema/create.test.ts +164 -5
- package/src/schema/create.ts +222 -24
- package/src/schema/generate-id.test.ts +1 -0
- package/src/schema/serialize.test.ts +4 -3
- package/src/schema/type-conversion/create-sql-type-mapper.ts +1 -1
- package/src/schema/type-conversion/dialect/sqlite.ts +2 -2
- package/src/schema/type-conversion/type-mapping.test.ts +2 -1
- package/src/schema/validator.test.ts +4 -2
- package/src/schema/validator.ts +1 -0
- package/src/schema-output/drizzle.test.ts +72 -19
- package/src/schema-output/drizzle.ts +24 -18
- package/src/schema-output/prisma.test.ts +172 -14
- package/src/schema-output/prisma.ts +34 -14
- package/src/sql-driver/better-sqlite3.test.ts +5 -3
- package/src/sql-driver/dialects/durable-object-dialect.ts +3 -8
- package/src/sql-driver/query-executor/default-query-executor.ts +1 -1
- package/src/sql-driver/query-executor/query-executor-base.ts +1 -1
- package/src/sql-driver/query-executor/query-executor.ts +1 -1
- package/src/sql-driver/sql-driver-adapter.ts +2 -2
- package/src/sql-driver/sql.ts +2 -1
- package/src/sql-driver/sqlocal.test.ts +4 -2
- package/src/sync/commands.test.ts +39 -0
- package/src/sync/commands.ts +51 -0
- package/src/sync/conflict-checker.test.ts +450 -0
- package/src/sync/conflict-checker.ts +248 -0
- package/src/sync/index.ts +14 -0
- package/src/sync/plan.ts +9 -0
- package/src/sync/read-tracking.test.ts +177 -0
- package/src/sync/read-tracking.ts +287 -0
- package/src/sync/submit.test.ts +205 -0
- package/src/sync/submit.ts +328 -0
- package/src/sync/types.ts +80 -0
- package/src/util/default-database-adapter.ts +15 -2
- package/src/with-database.ts +20 -50
- package/tsconfig.json +1 -1
- package/tsdown.config.ts +38 -26
- package/vitest.config.ts +1 -0
- package/dist/hooks/durable-hooks-processor.d.ts.map +0 -1
- package/dist/node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.js +0 -168
- package/dist/node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.js.map +0 -1
- package/dist/packages/fragno/dist/api/bind-services.js +0 -20
- package/dist/packages/fragno/dist/api/bind-services.js.map +0 -1
- package/dist/packages/fragno/dist/api/error.js +0 -48
- package/dist/packages/fragno/dist/api/error.js.map +0 -1
- package/dist/packages/fragno/dist/api/fragment-definition-builder.js +0 -321
- package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +0 -1
- package/dist/packages/fragno/dist/api/fragment-instantiator.js +0 -669
- package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +0 -1
- package/dist/packages/fragno/dist/api/fragno-response.js +0 -73
- package/dist/packages/fragno/dist/api/fragno-response.js.map +0 -1
- package/dist/packages/fragno/dist/api/internal/response-stream.js +0 -81
- package/dist/packages/fragno/dist/api/internal/response-stream.js.map +0 -1
- package/dist/packages/fragno/dist/api/internal/route.js +0 -10
- package/dist/packages/fragno/dist/api/internal/route.js.map +0 -1
- package/dist/packages/fragno/dist/api/mutable-request-state.js +0 -97
- package/dist/packages/fragno/dist/api/mutable-request-state.js.map +0 -1
- package/dist/packages/fragno/dist/api/request-context-storage.js +0 -43
- package/dist/packages/fragno/dist/api/request-context-storage.js.map +0 -1
- package/dist/packages/fragno/dist/api/request-input-context.js +0 -185
- package/dist/packages/fragno/dist/api/request-input-context.js.map +0 -1
- package/dist/packages/fragno/dist/api/request-middleware.js +0 -83
- package/dist/packages/fragno/dist/api/request-middleware.js.map +0 -1
- package/dist/packages/fragno/dist/api/request-output-context.js +0 -119
- package/dist/packages/fragno/dist/api/request-output-context.js.map +0 -1
- package/dist/packages/fragno/dist/api/route.js +0 -30
- package/dist/packages/fragno/dist/api/route.js.map +0 -1
- package/dist/packages/fragno/dist/internal/symbols.js +0 -10
- package/dist/packages/fragno/dist/internal/symbols.js.map +0 -1
- package/dist/packages/fragno/dist/internal/trace-context.js +0 -12
- package/dist/packages/fragno/dist/internal/trace-context.js.map +0 -1
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region src/internal/outbox-state.ts
|
|
2
|
+
const outboxStateByAdapter = /* @__PURE__ */ new WeakMap();
|
|
3
|
+
const getOperationNamespaceKey = (operation) => operation.namespace ?? operation.schema.name;
|
|
4
|
+
const createOutboxState = () => {
|
|
5
|
+
const enabledSchemaKeys = /* @__PURE__ */ new Set();
|
|
6
|
+
return {
|
|
7
|
+
config: {
|
|
8
|
+
enabled: false,
|
|
9
|
+
shouldInclude: (operation) => enabledSchemaKeys.has(getOperationNamespaceKey(operation))
|
|
10
|
+
},
|
|
11
|
+
enabledSchemaKeys,
|
|
12
|
+
enabledFragments: /* @__PURE__ */ new Set()
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
const getOutboxStateForAdapter = (adapter) => {
|
|
16
|
+
const existing = outboxStateByAdapter.get(adapter);
|
|
17
|
+
if (existing) return existing;
|
|
18
|
+
const state = createOutboxState();
|
|
19
|
+
outboxStateByAdapter.set(adapter, state);
|
|
20
|
+
return state;
|
|
21
|
+
};
|
|
22
|
+
const getOutboxConfigForAdapter = (adapter) => getOutboxStateForAdapter(adapter).config;
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { getOutboxConfigForAdapter, getOutboxStateForAdapter };
|
|
26
|
+
//# sourceMappingURL=outbox-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbox-state.js","names":[],"sources":["../../src/internal/outbox-state.ts"],"sourcesContent":["import type { DatabaseAdapter } from \"../adapters/adapters\";\nimport type { OutboxConfig } from \"../outbox/outbox\";\nimport type { MutationOperation } from \"../query/unit-of-work/unit-of-work\";\nimport type { AnySchema } from \"../schema/create\";\n\nexport type OutboxState = {\n config: OutboxConfig;\n enabledSchemaKeys: Set<string>;\n enabledFragments: Set<string>;\n};\n\ntype AdapterKey = DatabaseAdapter<unknown>;\n\nconst outboxStateByAdapter = new WeakMap<AdapterKey, OutboxState>();\n\nconst getOperationNamespaceKey = (operation: MutationOperation<AnySchema>): string =>\n operation.namespace ?? operation.schema.name;\n\nconst createOutboxState = (): OutboxState => {\n const enabledSchemaKeys = new Set<string>();\n const enabledFragments = new Set<string>();\n const config: OutboxConfig = {\n enabled: false,\n shouldInclude: (operation) => enabledSchemaKeys.has(getOperationNamespaceKey(operation)),\n };\n\n return { config, enabledSchemaKeys, enabledFragments };\n};\n\nexport const getOutboxStateForAdapter = (adapter: AdapterKey): OutboxState => {\n const existing = outboxStateByAdapter.get(adapter);\n if (existing) {\n return existing;\n }\n\n const state = createOutboxState();\n outboxStateByAdapter.set(adapter, state);\n return state;\n};\n\nexport const getOutboxConfigForAdapter = <TUOWConfig>(\n adapter: DatabaseAdapter<TUOWConfig>,\n): OutboxConfig => getOutboxStateForAdapter(adapter as AdapterKey).config;\n"],"mappings":";AAaA,MAAM,uCAAuB,IAAI,SAAkC;AAEnE,MAAM,4BAA4B,cAChC,UAAU,aAAa,UAAU,OAAO;AAE1C,MAAM,0BAAuC;CAC3C,MAAM,oCAAoB,IAAI,KAAa;AAO3C,QAAO;EAAE,QALoB;GAC3B,SAAS;GACT,gBAAgB,cAAc,kBAAkB,IAAI,yBAAyB,UAAU,CAAC;GACzF;EAEgB;EAAmB,kCANX,IAAI,KAAa;EAMY;;AAGxD,MAAa,4BAA4B,YAAqC;CAC5E,MAAM,WAAW,qBAAqB,IAAI,QAAQ;AAClD,KAAI,SACF,QAAO;CAGT,MAAM,QAAQ,mBAAmB;AACjC,sBAAqB,IAAI,SAAS,MAAM;AACxC,QAAO;;AAGT,MAAa,6BACX,YACiB,yBAAyB,QAAsB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AnySchema } from "../schema/create.js";
|
|
2
|
+
import { MigrationOperation } from "./shared.js";
|
|
3
|
+
|
|
4
|
+
//#region src/migration-engine/auto-from-schema.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Generate migration operations from a schema's operation history
|
|
8
|
+
*
|
|
9
|
+
* The schema version number represents the cumulative number of operations applied.
|
|
10
|
+
* This function takes operations from the schema between fromVersion and toVersion,
|
|
11
|
+
* and converts them into migration operations.
|
|
12
|
+
*
|
|
13
|
+
* @param targetSchema - The schema containing the operations history
|
|
14
|
+
* @param fromVersion - The current database version (e.g., 0)
|
|
15
|
+
* @param toVersion - The target version to migrate to (e.g., 5)
|
|
16
|
+
* @param options - Migration generation options
|
|
17
|
+
* @returns Array of migration operations to apply
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* const mySchema = schema("my", s => s
|
|
22
|
+
* .addTable("users", t => t.addColumn("id", idColumn())) // version 1
|
|
23
|
+
* .addTable("posts", t => t.addColumn("id", idColumn())) // version 2
|
|
24
|
+
* );
|
|
25
|
+
*
|
|
26
|
+
* // Generate operations from version 0 to 1 (only creates users table)
|
|
27
|
+
* const operations = generateMigrationFromSchema(mySchema, 0, 1);
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
declare function generateMigrationFromSchema(targetSchema: AnySchema, fromVersion: number, toVersion: number): MigrationOperation[];
|
|
31
|
+
//#endregion
|
|
32
|
+
export { generateMigrationFromSchema };
|
|
33
|
+
//# sourceMappingURL=auto-from-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-from-schema.d.ts","names":[],"sources":["../../src/migration-engine/auto-from-schema.ts"],"sourcesContent":[],"mappings":";;;;;;;AAyQA;;;;;;;;;;;;;;;;;;;;;;iBAAgB,2BAAA,eACA,oDAGb"}
|
|
@@ -1,6 +1,137 @@
|
|
|
1
1
|
import "../schema/create.js";
|
|
2
2
|
|
|
3
3
|
//#region src/migration-engine/auto-from-schema.ts
|
|
4
|
+
function cloneTableState(state) {
|
|
5
|
+
return {
|
|
6
|
+
columns: { ...state.columns },
|
|
7
|
+
columnOrder: [...state.columnOrder],
|
|
8
|
+
indexes: { ...state.indexes },
|
|
9
|
+
foreignKeys: [...state.foreignKeys]
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function createTableState(operations) {
|
|
13
|
+
const state = {
|
|
14
|
+
columns: {},
|
|
15
|
+
columnOrder: [],
|
|
16
|
+
indexes: {},
|
|
17
|
+
foreignKeys: []
|
|
18
|
+
};
|
|
19
|
+
for (const subOp of operations) if (subOp.type === "add-column") {
|
|
20
|
+
state.columns[subOp.columnName] = subOp.column;
|
|
21
|
+
state.columnOrder.push(subOp.columnName);
|
|
22
|
+
} else if (subOp.type === "add-index") state.indexes[subOp.name] = {
|
|
23
|
+
name: subOp.name,
|
|
24
|
+
columns: [...subOp.columns],
|
|
25
|
+
unique: subOp.unique
|
|
26
|
+
};
|
|
27
|
+
return state;
|
|
28
|
+
}
|
|
29
|
+
function applyTableSubOperations(state, operations) {
|
|
30
|
+
for (const subOp of operations) if (subOp.type === "add-column") {
|
|
31
|
+
if (!state.columns[subOp.columnName]) state.columnOrder.push(subOp.columnName);
|
|
32
|
+
state.columns[subOp.columnName] = subOp.column;
|
|
33
|
+
} else if (subOp.type === "update-column") state.columns[subOp.columnName] = subOp.column;
|
|
34
|
+
else if (subOp.type === "rename-column") {
|
|
35
|
+
if (state.columns[subOp.from]) {
|
|
36
|
+
state.columns[subOp.to] = state.columns[subOp.from];
|
|
37
|
+
delete state.columns[subOp.from];
|
|
38
|
+
}
|
|
39
|
+
const orderIndex = state.columnOrder.indexOf(subOp.from);
|
|
40
|
+
if (orderIndex !== -1) state.columnOrder[orderIndex] = subOp.to;
|
|
41
|
+
state.indexes = renameColumnInIndexes(state.indexes, subOp.from, subOp.to);
|
|
42
|
+
state.foreignKeys = renameColumnInForeignKeys(state.foreignKeys, subOp.from, subOp.to);
|
|
43
|
+
} else if (subOp.type === "drop-column") {
|
|
44
|
+
if (state.columns[subOp.name]) delete state.columns[subOp.name];
|
|
45
|
+
state.columnOrder = state.columnOrder.filter((colName) => colName !== subOp.name);
|
|
46
|
+
state.indexes = dropColumnFromIndexes(state.indexes, subOp.name);
|
|
47
|
+
state.foreignKeys = dropColumnFromForeignKeys(state.foreignKeys, subOp.name);
|
|
48
|
+
} else if (subOp.type === "add-index") state.indexes[subOp.name] = {
|
|
49
|
+
name: subOp.name,
|
|
50
|
+
columns: [...subOp.columns],
|
|
51
|
+
unique: subOp.unique
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function renameColumnInIndexes(indexes, from, to) {
|
|
55
|
+
const next = {};
|
|
56
|
+
for (const [name, index] of Object.entries(indexes)) {
|
|
57
|
+
if (!index.columns.includes(from)) {
|
|
58
|
+
next[name] = index;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
next[name] = {
|
|
62
|
+
...index,
|
|
63
|
+
columns: index.columns.map((column) => column === from ? to : column)
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return next;
|
|
67
|
+
}
|
|
68
|
+
function dropColumnFromIndexes(indexes, columnName) {
|
|
69
|
+
const next = {};
|
|
70
|
+
for (const [name, index] of Object.entries(indexes)) {
|
|
71
|
+
if (index.columns.includes(columnName)) continue;
|
|
72
|
+
next[name] = index;
|
|
73
|
+
}
|
|
74
|
+
return next;
|
|
75
|
+
}
|
|
76
|
+
function renameColumnInForeignKeys(foreignKeys, from, to) {
|
|
77
|
+
return foreignKeys.map((foreignKey) => {
|
|
78
|
+
if (!foreignKey.columns.includes(from)) return foreignKey;
|
|
79
|
+
return {
|
|
80
|
+
...foreignKey,
|
|
81
|
+
columns: foreignKey.columns.map((column) => column === from ? to : column)
|
|
82
|
+
};
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
function dropColumnFromForeignKeys(foreignKeys, columnName) {
|
|
86
|
+
return foreignKeys.filter((foreignKey) => !foreignKey.columns.includes(columnName));
|
|
87
|
+
}
|
|
88
|
+
function buildCopyColumns(columnOrder, operations) {
|
|
89
|
+
const mappings = columnOrder.map((columnName) => ({
|
|
90
|
+
from: columnName,
|
|
91
|
+
to: columnName
|
|
92
|
+
}));
|
|
93
|
+
for (const op of operations) if (op.type === "rename-column") {
|
|
94
|
+
for (const mapping of mappings) if (mapping.to === op.from) mapping.to = op.to;
|
|
95
|
+
} else if (op.type === "drop-column") {
|
|
96
|
+
for (let i = mappings.length - 1; i >= 0; i -= 1) if (mappings[i]?.to === op.name) mappings.splice(i, 1);
|
|
97
|
+
}
|
|
98
|
+
return mappings;
|
|
99
|
+
}
|
|
100
|
+
function applyRenameDropToColumnList(columns, operations) {
|
|
101
|
+
let next = [...columns];
|
|
102
|
+
for (const op of operations) {
|
|
103
|
+
if (op.type === "rename-column") {
|
|
104
|
+
next = next.map((column) => column === op.from ? op.to : column);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (op.type === "drop-column" && next.includes(op.name)) return null;
|
|
108
|
+
}
|
|
109
|
+
return next;
|
|
110
|
+
}
|
|
111
|
+
function applyReferenceOperation(state, operation) {
|
|
112
|
+
if (operation.config.foreignKey === false) return;
|
|
113
|
+
state.foreignKeys.push({
|
|
114
|
+
name: operation.referenceName,
|
|
115
|
+
columns: [operation.config.from.column],
|
|
116
|
+
referencedTable: operation.config.to.table,
|
|
117
|
+
referencedColumns: [operation.config.to.column]
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
function buildTableStates(schema, version) {
|
|
121
|
+
const tableStates = /* @__PURE__ */ new Map();
|
|
122
|
+
const operations = schema.operations.slice(0, version);
|
|
123
|
+
for (const op of operations) if (op.type === "add-table") tableStates.set(op.tableName, createTableState(op.operations));
|
|
124
|
+
else if (op.type === "alter-table") {
|
|
125
|
+
const state = tableStates.get(op.tableName);
|
|
126
|
+
if (!state) continue;
|
|
127
|
+
applyTableSubOperations(state, op.operations);
|
|
128
|
+
} else if (op.type === "add-reference") {
|
|
129
|
+
const state = tableStates.get(op.tableName);
|
|
130
|
+
if (!state) continue;
|
|
131
|
+
applyReferenceOperation(state, op);
|
|
132
|
+
}
|
|
133
|
+
return tableStates;
|
|
134
|
+
}
|
|
4
135
|
/**
|
|
5
136
|
* Generate migration operations from a schema's operation history
|
|
6
137
|
*
|
|
@@ -32,18 +163,19 @@ function generateMigrationFromSchema(targetSchema, fromVersion, toVersion) {
|
|
|
32
163
|
if (toVersion < fromVersion) throw new Error(`Cannot migrate backwards: toVersion (${toVersion}) < fromVersion (${fromVersion})`);
|
|
33
164
|
const relevantOperations = targetSchema.operations.slice(fromVersion, toVersion);
|
|
34
165
|
const migrationOperations = [];
|
|
166
|
+
const tableStates = buildTableStates(targetSchema, fromVersion);
|
|
167
|
+
const toColumnInfo = (columnName, col) => {
|
|
168
|
+
return {
|
|
169
|
+
name: columnName,
|
|
170
|
+
type: col.type,
|
|
171
|
+
isNullable: col.isNullable,
|
|
172
|
+
role: col.role,
|
|
173
|
+
default: col.default ? "value" in col.default ? { value: col.default.value } : "dbSpecial" in col.default ? { dbSpecial: col.default.dbSpecial } : "runtime" in col.default && typeof col.default.runtime === "string" ? { runtime: col.default.runtime } : void 0 : void 0
|
|
174
|
+
};
|
|
175
|
+
};
|
|
35
176
|
for (const op of relevantOperations) if (op.type === "add-table") {
|
|
36
177
|
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 ? "value" in col.default ? { value: col.default.value } : "dbSpecial" in col.default ? { dbSpecial: col.default.dbSpecial } : "runtime" in col.default && typeof col.default.runtime === "string" ? { runtime: col.default.runtime } : void 0 : void 0
|
|
45
|
-
});
|
|
46
|
-
}
|
|
178
|
+
for (const subOp of op.operations) if (subOp.type === "add-column") columns.push(toColumnInfo(subOp.columnName, subOp.column));
|
|
47
179
|
migrationOperations.push({
|
|
48
180
|
type: "create-table",
|
|
49
181
|
name: op.tableName,
|
|
@@ -66,25 +198,68 @@ function generateMigrationFromSchema(targetSchema, fromVersion, toVersion) {
|
|
|
66
198
|
referencedColumns: subOp.referencedColumns
|
|
67
199
|
}
|
|
68
200
|
});
|
|
201
|
+
tableStates.set(op.tableName, createTableState(op.operations));
|
|
69
202
|
} else if (op.type === "alter-table") {
|
|
70
|
-
const columnOps =
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
value:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
203
|
+
const columnOps = [];
|
|
204
|
+
const tableState = tableStates.get(op.tableName);
|
|
205
|
+
for (const subOp of op.operations) if (subOp.type === "add-column") columnOps.push({
|
|
206
|
+
type: "create-column",
|
|
207
|
+
value: toColumnInfo(subOp.columnName, subOp.column)
|
|
208
|
+
});
|
|
209
|
+
else if (subOp.type === "update-column") columnOps.push({
|
|
210
|
+
type: "update-column",
|
|
211
|
+
name: subOp.columnName,
|
|
212
|
+
value: toColumnInfo(subOp.columnName, subOp.column),
|
|
213
|
+
updateNullable: subOp.updateNullable,
|
|
214
|
+
updateDefault: subOp.updateDefault,
|
|
215
|
+
updateDataType: subOp.updateDataType
|
|
216
|
+
});
|
|
217
|
+
else if (subOp.type === "rename-column") columnOps.push({
|
|
218
|
+
type: "rename-column",
|
|
219
|
+
from: subOp.from,
|
|
220
|
+
to: subOp.to
|
|
221
|
+
});
|
|
222
|
+
else if (subOp.type === "drop-column") columnOps.push({
|
|
223
|
+
type: "drop-column",
|
|
224
|
+
name: subOp.name
|
|
87
225
|
});
|
|
226
|
+
if (columnOps.length > 0) {
|
|
227
|
+
const hasUpdateColumn = columnOps.some((colOp) => colOp.type === "update-column");
|
|
228
|
+
const alterTableOperation = {
|
|
229
|
+
type: "alter-table",
|
|
230
|
+
name: op.tableName,
|
|
231
|
+
value: columnOps
|
|
232
|
+
};
|
|
233
|
+
if (hasUpdateColumn) {
|
|
234
|
+
if (!tableState) throw new Error(`Table ${op.tableName} not found in schema state`);
|
|
235
|
+
const nextState = cloneTableState(tableState);
|
|
236
|
+
applyTableSubOperations(nextState, op.operations);
|
|
237
|
+
alterTableOperation.metadata = { recreateTable: {
|
|
238
|
+
columns: nextState.columnOrder.map((colName) => toColumnInfo(colName, nextState.columns[colName])),
|
|
239
|
+
copyColumns: buildCopyColumns(tableState.columnOrder, op.operations),
|
|
240
|
+
indexes: Object.values(tableState.indexes).flatMap((idx) => {
|
|
241
|
+
const columns = applyRenameDropToColumnList(idx.columns, op.operations);
|
|
242
|
+
if (!columns) return [];
|
|
243
|
+
return [{
|
|
244
|
+
name: idx.name,
|
|
245
|
+
columns,
|
|
246
|
+
unique: idx.unique
|
|
247
|
+
}];
|
|
248
|
+
}),
|
|
249
|
+
foreignKeys: tableState.foreignKeys.flatMap((fk) => {
|
|
250
|
+
const columns = applyRenameDropToColumnList(fk.columns, op.operations);
|
|
251
|
+
if (!columns) return [];
|
|
252
|
+
return [{
|
|
253
|
+
name: fk.name,
|
|
254
|
+
columns,
|
|
255
|
+
referencedTable: fk.referencedTable,
|
|
256
|
+
referencedColumns: [...fk.referencedColumns]
|
|
257
|
+
}];
|
|
258
|
+
})
|
|
259
|
+
} };
|
|
260
|
+
}
|
|
261
|
+
migrationOperations.push(alterTableOperation);
|
|
262
|
+
}
|
|
88
263
|
for (const subOp of op.operations) if (subOp.type === "add-index") migrationOperations.push({
|
|
89
264
|
type: "add-index",
|
|
90
265
|
table: op.tableName,
|
|
@@ -92,8 +267,14 @@ function generateMigrationFromSchema(targetSchema, fromVersion, toVersion) {
|
|
|
92
267
|
columns: subOp.columns,
|
|
93
268
|
unique: subOp.unique
|
|
94
269
|
});
|
|
270
|
+
if (tableState) {
|
|
271
|
+
const nextState = cloneTableState(tableState);
|
|
272
|
+
applyTableSubOperations(nextState, op.operations);
|
|
273
|
+
tableStates.set(op.tableName, nextState);
|
|
274
|
+
}
|
|
95
275
|
} else if (op.type === "add-reference") {
|
|
96
276
|
if (!op.referenceName || op.referenceName.trim().length === 0) throw new Error(`referenceName is required for add-reference on ${op.tableName}`);
|
|
277
|
+
if (op.config.foreignKey === false) continue;
|
|
97
278
|
migrationOperations.push({
|
|
98
279
|
type: "add-foreign-key",
|
|
99
280
|
table: op.tableName,
|
|
@@ -104,6 +285,8 @@ function generateMigrationFromSchema(targetSchema, fromVersion, toVersion) {
|
|
|
104
285
|
referencedColumns: [op.config.to.column]
|
|
105
286
|
}
|
|
106
287
|
});
|
|
288
|
+
const tableState = tableStates.get(op.tableName);
|
|
289
|
+
if (tableState) applyReferenceOperation(tableState, op);
|
|
107
290
|
}
|
|
108
291
|
return migrationOperations;
|
|
109
292
|
}
|
|
@@ -1 +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(\"my\", 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 ? \"value\" in col.default\n ? { value: col.default.value }\n : \"dbSpecial\" in col.default\n ? { dbSpecial: col.default.dbSpecial }\n : \"runtime\" in col.default && typeof col.default.runtime === \"string\"\n ? { runtime: col.default.runtime }\n : undefined\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 ? \"value\" in col.default\n ? { value: col.default.value }\n : \"dbSpecial\" in col.default\n ? { dbSpecial: col.default.dbSpecial }\n : \"runtime\" in col.default && typeof col.default.runtime === \"string\"\n ? { runtime: col.default.runtime }\n : undefined\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 if (!op.referenceName || op.referenceName.trim().length === 0) {\n throw new Error(`referenceName is required for add-reference on ${op.tableName}`);\n }\n migrationOperations.push({\n type: \"add-foreign-key\",\n table: op.tableName,\n value: {\n name: op.referenceName,\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":"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"}
|
|
1
|
+
{"version":3,"file":"auto-from-schema.js","names":["state: TableState","next: Record<string, IndexInfo>","migrationOperations: MigrationOperation[]","columns: ColumnInfo[]","columnOps: ColumnOperation[]","alterTableOperation: MigrationOperation"],"sources":["../../src/migration-engine/auto-from-schema.ts"],"sourcesContent":["import {\n type AnySchema,\n type AnyColumn,\n type TableSubOperation,\n type SchemaOperation,\n} from \"../schema/create\";\nimport type {\n MigrationOperation,\n ColumnInfo,\n ColumnOperation,\n ForeignKeyInfo,\n SqliteAlterTableMetadata,\n SqliteCopyColumn,\n} from \"./shared\";\n\ntype IndexInfo = { name: string; columns: string[]; unique: boolean };\n\ntype TableState = {\n columns: Record<string, AnyColumn>;\n columnOrder: string[];\n indexes: Record<string, IndexInfo>;\n foreignKeys: ForeignKeyInfo[];\n};\n\nfunction cloneTableState(state: TableState): TableState {\n return {\n columns: { ...state.columns },\n columnOrder: [...state.columnOrder],\n indexes: { ...state.indexes },\n foreignKeys: [...state.foreignKeys],\n };\n}\n\nfunction createTableState(operations: TableSubOperation[]): TableState {\n const state: TableState = {\n columns: {},\n columnOrder: [],\n indexes: {},\n foreignKeys: [],\n };\n\n for (const subOp of operations) {\n if (subOp.type === \"add-column\") {\n state.columns[subOp.columnName] = subOp.column;\n state.columnOrder.push(subOp.columnName);\n } else if (subOp.type === \"add-index\") {\n state.indexes[subOp.name] = {\n name: subOp.name,\n columns: [...subOp.columns],\n unique: subOp.unique,\n };\n }\n }\n\n return state;\n}\n\nfunction applyTableSubOperations(state: TableState, operations: TableSubOperation[]): void {\n for (const subOp of operations) {\n if (subOp.type === \"add-column\") {\n if (!state.columns[subOp.columnName]) {\n state.columnOrder.push(subOp.columnName);\n }\n state.columns[subOp.columnName] = subOp.column;\n } else if (subOp.type === \"update-column\") {\n state.columns[subOp.columnName] = subOp.column;\n } else if (subOp.type === \"rename-column\") {\n if (state.columns[subOp.from]) {\n state.columns[subOp.to] = state.columns[subOp.from]!;\n delete state.columns[subOp.from];\n }\n const orderIndex = state.columnOrder.indexOf(subOp.from);\n if (orderIndex !== -1) {\n state.columnOrder[orderIndex] = subOp.to;\n }\n state.indexes = renameColumnInIndexes(state.indexes, subOp.from, subOp.to);\n state.foreignKeys = renameColumnInForeignKeys(state.foreignKeys, subOp.from, subOp.to);\n } else if (subOp.type === \"drop-column\") {\n if (state.columns[subOp.name]) {\n delete state.columns[subOp.name];\n }\n state.columnOrder = state.columnOrder.filter((colName) => colName !== subOp.name);\n state.indexes = dropColumnFromIndexes(state.indexes, subOp.name);\n state.foreignKeys = dropColumnFromForeignKeys(state.foreignKeys, subOp.name);\n } else if (subOp.type === \"add-index\") {\n state.indexes[subOp.name] = {\n name: subOp.name,\n columns: [...subOp.columns],\n unique: subOp.unique,\n };\n }\n }\n}\n\nfunction renameColumnInIndexes(\n indexes: Record<string, IndexInfo>,\n from: string,\n to: string,\n): Record<string, IndexInfo> {\n const next: Record<string, IndexInfo> = {};\n\n for (const [name, index] of Object.entries(indexes)) {\n if (!index.columns.includes(from)) {\n next[name] = index;\n continue;\n }\n\n next[name] = {\n ...index,\n columns: index.columns.map((column) => (column === from ? to : column)),\n };\n }\n\n return next;\n}\n\nfunction dropColumnFromIndexes(\n indexes: Record<string, IndexInfo>,\n columnName: string,\n): Record<string, IndexInfo> {\n const next: Record<string, IndexInfo> = {};\n\n for (const [name, index] of Object.entries(indexes)) {\n if (index.columns.includes(columnName)) {\n continue;\n }\n next[name] = index;\n }\n\n return next;\n}\n\nfunction renameColumnInForeignKeys(\n foreignKeys: ForeignKeyInfo[],\n from: string,\n to: string,\n): ForeignKeyInfo[] {\n return foreignKeys.map((foreignKey) => {\n if (!foreignKey.columns.includes(from)) {\n return foreignKey;\n }\n\n return {\n ...foreignKey,\n columns: foreignKey.columns.map((column) => (column === from ? to : column)),\n };\n });\n}\n\nfunction dropColumnFromForeignKeys(\n foreignKeys: ForeignKeyInfo[],\n columnName: string,\n): ForeignKeyInfo[] {\n return foreignKeys.filter((foreignKey) => !foreignKey.columns.includes(columnName));\n}\n\nfunction buildCopyColumns(\n columnOrder: string[],\n operations: TableSubOperation[],\n): SqliteCopyColumn[] {\n const mappings = columnOrder.map((columnName) => ({ from: columnName, to: columnName }));\n\n for (const op of operations) {\n if (op.type === \"rename-column\") {\n for (const mapping of mappings) {\n if (mapping.to === op.from) {\n mapping.to = op.to;\n }\n }\n } else if (op.type === \"drop-column\") {\n for (let i = mappings.length - 1; i >= 0; i -= 1) {\n if (mappings[i]?.to === op.name) {\n mappings.splice(i, 1);\n }\n }\n }\n }\n\n return mappings;\n}\n\nfunction applyRenameDropToColumnList(\n columns: string[],\n operations: TableSubOperation[],\n): string[] | null {\n let next = [...columns];\n\n for (const op of operations) {\n if (op.type === \"rename-column\") {\n next = next.map((column) => (column === op.from ? op.to : column));\n continue;\n }\n\n if (op.type === \"drop-column\" && next.includes(op.name)) {\n return null;\n }\n }\n\n return next;\n}\n\nfunction applyReferenceOperation(\n state: TableState,\n operation: Extract<SchemaOperation, { type: \"add-reference\" }>,\n): void {\n if (operation.config.foreignKey === false) {\n return;\n }\n state.foreignKeys.push({\n name: operation.referenceName,\n columns: [operation.config.from.column],\n referencedTable: operation.config.to.table,\n referencedColumns: [operation.config.to.column],\n });\n}\n\nfunction buildTableStates(schema: AnySchema, version: number): Map<string, TableState> {\n const tableStates = new Map<string, TableState>();\n const operations = schema.operations.slice(0, version);\n\n for (const op of operations) {\n if (op.type === \"add-table\") {\n tableStates.set(op.tableName, createTableState(op.operations));\n } else if (op.type === \"alter-table\") {\n const state = tableStates.get(op.tableName);\n if (!state) {\n continue;\n }\n applyTableSubOperations(state, op.operations);\n } else if (op.type === \"add-reference\") {\n const state = tableStates.get(op.tableName);\n if (!state) {\n continue;\n }\n applyReferenceOperation(state, op);\n }\n }\n\n return tableStates;\n}\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(\"my\", 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 const tableStates = buildTableStates(targetSchema, fromVersion);\n\n const toColumnInfo = (columnName: string, col: AnyColumn): ColumnInfo => {\n return {\n name: columnName,\n type: col.type,\n isNullable: col.isNullable,\n role: col.role,\n default: col.default\n ? \"value\" in col.default\n ? { value: col.default.value }\n : \"dbSpecial\" in col.default\n ? { dbSpecial: col.default.dbSpecial }\n : \"runtime\" in col.default && typeof col.default.runtime === \"string\"\n ? { runtime: col.default.runtime }\n : undefined\n : undefined,\n };\n };\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 columns.push(toColumnInfo(subOp.columnName, subOp.column));\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\n tableStates.set(op.tableName, createTableState(op.operations));\n } else if (op.type === \"alter-table\") {\n const columnOps: ColumnOperation[] = [];\n const tableState = tableStates.get(op.tableName);\n\n for (const subOp of op.operations) {\n if (subOp.type === \"add-column\") {\n columnOps.push({\n type: \"create-column\",\n value: toColumnInfo(subOp.columnName, subOp.column),\n });\n } else if (subOp.type === \"update-column\") {\n columnOps.push({\n type: \"update-column\",\n name: subOp.columnName,\n value: toColumnInfo(subOp.columnName, subOp.column),\n updateNullable: subOp.updateNullable,\n updateDefault: subOp.updateDefault,\n updateDataType: subOp.updateDataType,\n });\n } else if (subOp.type === \"rename-column\") {\n columnOps.push({\n type: \"rename-column\",\n from: subOp.from,\n to: subOp.to,\n });\n } else if (subOp.type === \"drop-column\") {\n columnOps.push({\n type: \"drop-column\",\n name: subOp.name,\n });\n }\n }\n\n if (columnOps.length > 0) {\n const hasUpdateColumn = columnOps.some((colOp) => colOp.type === \"update-column\");\n const alterTableOperation: MigrationOperation = {\n type: \"alter-table\",\n name: op.tableName,\n value: columnOps,\n };\n\n if (hasUpdateColumn) {\n if (!tableState) {\n throw new Error(`Table ${op.tableName} not found in schema state`);\n }\n\n const nextState = cloneTableState(tableState);\n applyTableSubOperations(nextState, op.operations);\n\n const metadata: SqliteAlterTableMetadata = {\n recreateTable: {\n columns: nextState.columnOrder.map((colName) =>\n toColumnInfo(colName, nextState.columns[colName]!),\n ),\n copyColumns: buildCopyColumns(tableState.columnOrder, op.operations),\n indexes: Object.values(tableState.indexes).flatMap((idx) => {\n const columns = applyRenameDropToColumnList(idx.columns, op.operations);\n if (!columns) {\n return [];\n }\n return [\n {\n name: idx.name,\n columns,\n unique: idx.unique,\n },\n ];\n }),\n foreignKeys: tableState.foreignKeys.flatMap((fk) => {\n const columns = applyRenameDropToColumnList(fk.columns, op.operations);\n if (!columns) {\n return [];\n }\n return [\n {\n name: fk.name,\n columns,\n referencedTable: fk.referencedTable,\n referencedColumns: [...fk.referencedColumns],\n },\n ];\n }),\n },\n };\n\n alterTableOperation.metadata = metadata;\n }\n\n migrationOperations.push(alterTableOperation);\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\n if (tableState) {\n const nextState = cloneTableState(tableState);\n applyTableSubOperations(nextState, op.operations);\n tableStates.set(op.tableName, nextState);\n }\n } else if (op.type === \"add-reference\") {\n if (!op.referenceName || op.referenceName.trim().length === 0) {\n throw new Error(`referenceName is required for add-reference on ${op.tableName}`);\n }\n if (op.config.foreignKey === false) {\n continue;\n }\n migrationOperations.push({\n type: \"add-foreign-key\",\n table: op.tableName,\n value: {\n name: op.referenceName,\n columns: [op.config.from.column],\n referencedTable: op.config.to.table,\n referencedColumns: [op.config.to.column],\n },\n });\n\n const tableState = tableStates.get(op.tableName);\n if (tableState) {\n applyReferenceOperation(tableState, op);\n }\n }\n }\n\n return migrationOperations;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generation-engine.d.ts","names":[],"sources":["../../src/migration-engine/generation-engine.ts"],"sourcesContent":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"generation-engine.d.ts","names":[],"sources":["../../src/migration-engine/generation-engine.ts"],"sourcesContent":[],"mappings":";;;;UAmBiB,sBAAA;;EAAA,IAAA,EAAA,MAAA;EAML,SAAA,EAAA,MAAA,GAAA,IAAkB;AAE9B;AAOiB,KATL,kBAAA,GAS6B,KAAA,GAAA,SAAA,GAAA,QAAA;AAWxB,UAlBA,qBAAA,CAkBsB;EAajB,MAAA,CAAA,EA9BX,kBA8BkC;EAEH,IAAA,CAAA,EAAA,MAAA;EAAf,SAAA,CAAA,EAAA,MAAA;EACd,WAAA,CAAA,EAAA,MAAA;;AAAsD,UA3BlD,wBAAA,CA2BkD;EAAR,MAAA,EAAA,MAAA;EAAO,IAAA,EAAA,MAAA;EA2K5C,SAAA,EAAA,MAAA,GAAiB,IAAA;EAAyC,YAAA,EAAA,MAAA;EAAf,UAAA,EAAA,MAAA;EACpD,UAAA,EAAA,OAAA;EACF,WAAA,EAAA,MAAA;EAAR,SAAA,EAAA,MAAA;;AAwJa,UArVC,sBAAA,CAqV4B;;;;;;iBAxUvB,iDAEK,eAAe,8BAC7B,sBAAsB,wBAAwB,QAAQ;;;;;;;;iBA2K7C,2CAA2C,eAAe,yBACnE,aACV,QAAQ;;;;;;;;;;;iBAwJK,6BAAA,QACP,6BACN"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { supportedDatabases } from "../adapters/generic-sql/driver-config.js";
|
|
2
2
|
import { fragnoDatabaseAdapterNameFakeSymbol, fragnoDatabaseAdapterVersionFakeSymbol } from "../adapters/adapters.js";
|
|
3
3
|
import { SETTINGS_TABLE_NAME, internalSchema } from "../fragments/internal-fragment.schema.js";
|
|
4
|
-
import { supportedDatabases } from "../adapters/generic-sql/driver-config.js";
|
|
5
4
|
import { getSchemaVersionFromDatabase, internalFragmentDef } from "../fragments/internal-fragment.js";
|
|
5
|
+
import { getRegistryForAdapterSync } from "../internal/adapter-registry.js";
|
|
6
6
|
import { generateDrizzleSchema } from "../schema-output/drizzle.js";
|
|
7
7
|
import { generatePrismaSchema } from "../schema-output/prisma.js";
|
|
8
|
+
import { instantiate } from "@fragno-dev/core";
|
|
8
9
|
|
|
9
10
|
//#region src/migration-engine/generation-engine.ts
|
|
10
11
|
const DEFAULT_DRIZZLE_PATH = "fragno-schema.ts";
|
|
@@ -31,7 +32,18 @@ async function generateSchemaArtifacts(databases, options) {
|
|
|
31
32
|
namespace: db.namespace
|
|
32
33
|
});
|
|
33
34
|
}
|
|
34
|
-
const allFragments = Array.from(fragmentsMap.
|
|
35
|
+
const allFragments = Array.from(fragmentsMap.entries()).map(([namespaceKey, fragment]) => ({
|
|
36
|
+
...fragment,
|
|
37
|
+
namespaceKey,
|
|
38
|
+
isInternal: fragment.schema === internalSchema
|
|
39
|
+
})).sort((a, b) => {
|
|
40
|
+
if (a.isInternal) return -1;
|
|
41
|
+
if (b.isInternal) return 1;
|
|
42
|
+
return a.schema.name.localeCompare(b.schema.name);
|
|
43
|
+
}).map(({ schema, namespace }) => ({
|
|
44
|
+
schema,
|
|
45
|
+
namespace
|
|
46
|
+
}));
|
|
35
47
|
const defaultPath = format === "drizzle" ? DEFAULT_DRIZZLE_PATH : DEFAULT_PRISMA_PATH;
|
|
36
48
|
return [{
|
|
37
49
|
schema: format === "drizzle" ? generateDrizzleSchema(allFragments, databaseType, { namingStrategy: adapter.namingStrategy }) : generatePrismaSchema(allFragments, databaseType, {
|
|
@@ -44,7 +56,7 @@ async function generateSchemaArtifacts(databases, options) {
|
|
|
44
56
|
}
|
|
45
57
|
if (!adapter.prepareMigrations) throw new Error("Adapter does not support migration generation. Ensure your adapter implements prepareMigrations.");
|
|
46
58
|
if (!await adapter.isConnectionHealthy()) throw new Error("Database connection is not healthy. Please check your database connection and try again.");
|
|
47
|
-
const settingsSourceVersion = await getSchemaVersionFromDatabase(instantiate(internalFragmentDef).withConfig({}).withOptions({
|
|
59
|
+
const settingsSourceVersion = await getSchemaVersionFromDatabase(instantiate(internalFragmentDef).withConfig({ registry: getRegistryForAdapterSync(adapter) }).withOptions({
|
|
48
60
|
databaseAdapter: adapter,
|
|
49
61
|
databaseNamespace: null
|
|
50
62
|
}).build(), "");
|
|
@@ -103,7 +115,7 @@ async function executeMigrations(databases) {
|
|
|
103
115
|
if (!await adapter.isConnectionHealthy()) throw new Error("Database connection is not healthy. Please check your database connection and try again.");
|
|
104
116
|
const results = [];
|
|
105
117
|
const migrationsToExecute = [];
|
|
106
|
-
const internalFragment = instantiate(internalFragmentDef).withConfig({}).withOptions({
|
|
118
|
+
const internalFragment = instantiate(internalFragmentDef).withConfig({ registry: getRegistryForAdapterSync(adapter) }).withOptions({
|
|
107
119
|
databaseAdapter: adapter,
|
|
108
120
|
databaseNamespace: null
|
|
109
121
|
}).build();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generation-engine.js","names":["generatedFiles: GenerationInternalResult[]","results: ExecuteMigrationResult[]","migrationsToExecute: Array<{\n namespace: string | null;\n namespaceKey: string;\n fromVersion: number;\n toVersion: number;\n execute: () => Promise<void>;\n }>"],"sources":["../../src/migration-engine/generation-engine.ts"],"sourcesContent":["import type { FragnoDatabase } from \"../mod\";\nimport type { AnySchema } from \"../schema/create\";\nimport {\n fragnoDatabaseAdapterNameFakeSymbol,\n fragnoDatabaseAdapterVersionFakeSymbol,\n} from \"../adapters/adapters\";\nimport { generateDrizzleSchema } from \"../schema-output/drizzle\";\nimport { generatePrismaSchema } from \"../schema-output/prisma\";\nimport { internalFragmentDef, getSchemaVersionFromDatabase } from \"../fragments/internal-fragment\";\nimport { internalSchema, SETTINGS_TABLE_NAME } from \"../fragments/internal-fragment.schema\";\nimport { instantiate } from \"@fragno-dev/core\";\nimport { supportedDatabases, type SupportedDatabase } from \"../adapters/generic-sql/driver-config\";\n\nexport interface GenerationEngineResult {\n schema: string;\n path: string;\n namespace: string | null;\n}\n\nexport type SchemaOutputFormat = \"sql\" | \"drizzle\" | \"prisma\";\n\nexport interface GenerateSchemaOptions {\n format?: SchemaOutputFormat;\n path?: string;\n toVersion?: number;\n fromVersion?: number;\n}\n\nexport interface GenerationInternalResult {\n schema: string;\n path: string;\n namespace: string | null;\n namespaceKey: string;\n schemaName: string;\n isSettings: boolean;\n fromVersion: number;\n toVersion: number;\n}\n\nexport interface ExecuteMigrationResult {\n namespace: string | null;\n didMigrate: boolean;\n fromVersion: number;\n toVersion: number;\n}\n\nconst DEFAULT_DRIZZLE_PATH = \"fragno-schema.ts\";\nconst DEFAULT_PRISMA_PATH = \"fragno.prisma\";\n\nconst isSupportedDatabase = (value: string): value is SupportedDatabase =>\n supportedDatabases.includes(value as SupportedDatabase);\n\nexport async function generateSchemaArtifacts<\n // oxlint-disable-next-line no-explicit-any\n const TDatabases extends FragnoDatabase<AnySchema, any>[],\n>(databases: TDatabases, options?: GenerateSchemaOptions): Promise<GenerationEngineResult[]> {\n if (databases.length === 0) {\n throw new Error(\"No databases provided for schema generation\");\n }\n\n const firstDb = databases[0];\n const adapter = firstDb.adapter;\n const format = options?.format ?? \"sql\";\n\n if (format !== \"sql\") {\n if (options?.toVersion !== undefined || options?.fromVersion !== undefined) {\n throw new Error(\"--from and --to are only supported when generating SQL migrations.\");\n }\n\n const databaseType = adapter.adapterMetadata?.databaseType;\n if (!databaseType || !isSupportedDatabase(databaseType)) {\n throw new Error(\n \"Adapter does not expose databaseType metadata required for schema output generation.\",\n );\n }\n\n // Collect all schemas, de-duplicating by namespace.\n // The internal fragment (settings schema) is always included first since all database\n // fragments automatically link to it via withDatabase().\n const fragmentsMap = new Map<string, { schema: AnySchema; namespace: string | null }>();\n\n // Include internal fragment first with empty namespace (settings table has no prefix)\n fragmentsMap.set(internalSchema.name, {\n schema: internalSchema,\n namespace: null,\n });\n\n // Add user fragments, de-duplicating by namespace\n // Each FragnoDatabase has a unique namespace, so this prevents duplicate schema generation\n for (const db of databases) {\n const namespaceKey = db.namespace ?? db.schema.name;\n if (!fragmentsMap.has(namespaceKey)) {\n fragmentsMap.set(namespaceKey, {\n schema: db.schema,\n namespace: db.namespace,\n });\n }\n }\n\n const allFragments = Array.from(fragmentsMap.values());\n const defaultPath = format === \"drizzle\" ? DEFAULT_DRIZZLE_PATH : DEFAULT_PRISMA_PATH;\n const schema =\n format === \"drizzle\"\n ? generateDrizzleSchema(allFragments, databaseType, {\n namingStrategy: adapter.namingStrategy,\n })\n : generatePrismaSchema(allFragments, databaseType, {\n sqliteStorageMode: adapter.adapterMetadata?.sqliteStorageMode,\n namingStrategy: adapter.namingStrategy,\n });\n\n return [\n {\n schema,\n path: options?.path ?? defaultPath,\n namespace: firstDb.namespace,\n },\n ];\n }\n\n // Otherwise, use migration engine for SQL migration generation.\n if (!adapter.prepareMigrations) {\n throw new Error(\n \"Adapter does not support migration generation. Ensure your adapter implements prepareMigrations.\",\n );\n }\n\n if (!(await adapter.isConnectionHealthy())) {\n throw new Error(\n \"Database connection is not healthy. Please check your database connection and try again.\",\n );\n }\n\n // Use the internal fragment for settings management\n const internalFragment = instantiate(internalFragmentDef)\n .withConfig({})\n .withOptions({ databaseAdapter: adapter, databaseNamespace: null })\n .build();\n\n const settingsSourceVersion = await getSchemaVersionFromDatabase(internalFragment, \"\");\n\n const generatedFiles: GenerationInternalResult[] = [];\n\n // Internal fragment uses empty-string namespace: no table suffix, version key is \".schema_version\"\n const settingsPreparedMigrations = adapter.prepareMigrations(internalSchema, \"\");\n const settingsTargetVersion = internalSchema.version;\n\n // Generate settings table migration\n const settingsSql = settingsPreparedMigrations.getSQL(\n settingsSourceVersion,\n settingsTargetVersion,\n );\n\n if (settingsSql.trim()) {\n generatedFiles.push({\n schema: settingsSql,\n path: \"settings-migration.sql\", // Placeholder, will be renamed in post-processing\n namespace: null,\n namespaceKey: SETTINGS_TABLE_NAME,\n schemaName: internalSchema.name,\n isSettings: true,\n fromVersion: settingsSourceVersion,\n toVersion: settingsTargetVersion,\n });\n }\n\n // Generate migration for each fragment\n for (const db of databases) {\n const dbAdapter = db.adapter;\n\n // Use migration engine\n if (!dbAdapter.prepareMigrations) {\n throw new Error(\n `Adapter for ${db.namespace ?? db.schema.name} does not support migration generation. ` +\n `Ensure your adapter implements prepareMigrations.`,\n );\n }\n\n const preparedMigrations = dbAdapter.prepareMigrations(db.schema, db.namespace);\n const targetVersion = options?.toVersion ?? db.schema.version;\n const sourceVersion = options?.fromVersion ?? 0;\n\n // Generate migration from source to target version\n const sql = preparedMigrations.getSQL(sourceVersion, targetVersion);\n\n // If no migrations needed, skip this fragment\n if (sql.trim()) {\n generatedFiles.push({\n schema: sql,\n path: \"schema.sql\", // Placeholder, will be renamed in post-processing\n namespace: db.namespace,\n namespaceKey: db.namespace ?? db.schema.name,\n schemaName: db.schema.name,\n isSettings: false,\n fromVersion: sourceVersion,\n toVersion: targetVersion,\n });\n }\n }\n\n // Post-process filenames with ordering\n return postProcessMigrationFilenames(generatedFiles);\n}\n\n/**\n * Execute migrations for all fragments in the correct order.\n * Migrates settings table first, then fragments alphabetically.\n *\n * @param databases - Array of FragnoDatabase instances to migrate\n * @returns Array of execution results for each migration\n */\nexport async function executeMigrations<const TDatabases extends FragnoDatabase<AnySchema>[]>(\n databases: TDatabases,\n): Promise<ExecuteMigrationResult[]> {\n if (databases.length === 0) {\n throw new Error(\"No databases provided for migration\");\n }\n\n const firstDb = databases[0];\n const adapter = firstDb.adapter;\n\n // Validate adapter supports migrations\n if (!adapter.prepareMigrations) {\n throw new Error(\n \"Adapter does not support running migrations. The adapter only supports schema generation.\\n\" +\n \"Try using 'generateSchemaArtifacts' instead to generate schema files.\",\n );\n }\n\n // Validate all use same adapter name and version\n const firstAdapterName = adapter[fragnoDatabaseAdapterNameFakeSymbol];\n const firstAdapterVersion = adapter[fragnoDatabaseAdapterVersionFakeSymbol];\n\n for (const db of databases) {\n const dbAdapterName = db.adapter[fragnoDatabaseAdapterNameFakeSymbol];\n const dbAdapterVersion = db.adapter[fragnoDatabaseAdapterVersionFakeSymbol];\n\n if (dbAdapterName !== firstAdapterName || dbAdapterVersion !== firstAdapterVersion) {\n throw new Error(\n `All fragments must use the same database adapter. ` +\n `Found: ${firstAdapterName}@${firstAdapterVersion} and ${dbAdapterName}@${dbAdapterVersion}`,\n );\n }\n }\n\n if (!(await adapter.isConnectionHealthy())) {\n throw new Error(\n \"Database connection is not healthy. Please check your database connection and try again.\",\n );\n }\n\n const results: ExecuteMigrationResult[] = [];\n const migrationsToExecute: Array<{\n namespace: string | null;\n namespaceKey: string;\n fromVersion: number;\n toVersion: number;\n execute: () => Promise<void>;\n }> = [];\n\n // 1. Prepare settings table migration\n // Use the internal fragment for settings management\n const internalFragment = instantiate(internalFragmentDef)\n .withConfig({})\n .withOptions({ databaseAdapter: adapter, databaseNamespace: null })\n .build();\n\n const settingsSourceVersion = await getSchemaVersionFromDatabase(internalFragment, \"\");\n\n // Internal fragment uses empty-string namespace: no table suffix, version key is \".schema_version\"\n const settingsPreparedMigrations = adapter.prepareMigrations(internalSchema, \"\");\n const settingsTargetVersion = internalSchema.version;\n\n if (settingsSourceVersion < settingsTargetVersion) {\n const compiledMigration = settingsPreparedMigrations.compile(\n settingsSourceVersion,\n settingsTargetVersion,\n { updateVersionInMigration: true },\n );\n\n if (compiledMigration.statements.length > 0) {\n migrationsToExecute.push({\n namespace: null,\n namespaceKey: SETTINGS_TABLE_NAME,\n fromVersion: settingsSourceVersion,\n toVersion: settingsTargetVersion,\n execute: () =>\n settingsPreparedMigrations.execute(settingsSourceVersion, settingsTargetVersion, {\n updateVersionInMigration: true,\n }),\n });\n }\n }\n\n // 2. Prepare fragment migrations (sorted alphabetically)\n const getNamespaceKey = (db: FragnoDatabase<AnySchema>) => db.namespace ?? db.schema.name;\n const sortedDatabases = [...databases].sort((a, b) =>\n getNamespaceKey(a).localeCompare(getNamespaceKey(b)),\n );\n\n for (const fragnoDb of sortedDatabases) {\n const namespaceKey = getNamespaceKey(fragnoDb);\n const preparedMigrations = adapter.prepareMigrations(fragnoDb.schema, fragnoDb.namespace);\n const currentVersion = await getSchemaVersionFromDatabase(internalFragment, namespaceKey);\n const targetVersion = fragnoDb.schema.version;\n\n if (currentVersion < targetVersion) {\n const compiledMigration = preparedMigrations.compile(currentVersion, targetVersion, {\n updateVersionInMigration: true,\n });\n\n if (compiledMigration.statements.length > 0) {\n migrationsToExecute.push({\n namespace: fragnoDb.namespace,\n namespaceKey,\n fromVersion: currentVersion,\n toVersion: targetVersion,\n execute: () =>\n preparedMigrations.execute(currentVersion, targetVersion, {\n updateVersionInMigration: true,\n }),\n });\n }\n }\n }\n\n // 3. Execute all migrations in order\n const executedNamespaceKeys = new Set<string>();\n for (const migration of migrationsToExecute) {\n await migration.execute();\n results.push({\n namespace: migration.namespace,\n didMigrate: true,\n fromVersion: migration.fromVersion,\n toVersion: migration.toVersion,\n });\n executedNamespaceKeys.add(migration.namespaceKey);\n }\n\n // 4. Add skipped migrations (already up-to-date)\n for (const fragnoDb of databases) {\n const namespaceKey = getNamespaceKey(fragnoDb);\n if (!executedNamespaceKeys.has(namespaceKey)) {\n results.push({\n namespace: fragnoDb.namespace,\n didMigrate: false,\n fromVersion: fragnoDb.schema.version,\n toVersion: fragnoDb.schema.version,\n });\n }\n }\n\n return results;\n}\n\n/**\n * Post-processes migration files to add ordering and standardize naming.\n *\n * Sorts files with settings namespace first, then alphabetically by namespace key,\n * and assigns ordering numbers. Transforms filenames to format:\n * `<date>_<n>_f<from>_t<to>_<namespace>.sql`\n *\n * @param files - Array of generated migration files with version information\n * @returns Array of files with standardized paths and ordering\n */\nexport function postProcessMigrationFilenames(\n files: GenerationInternalResult[],\n): GenerationEngineResult[] {\n if (files.length === 0) {\n return [];\n }\n\n // Sort files: settings first, then alphabetically by namespace key\n const sortedFiles = [...files].sort((a, b) => {\n if (a.isSettings) {\n return -1;\n }\n if (b.isSettings) {\n return 1;\n }\n return a.namespaceKey.localeCompare(b.namespaceKey);\n });\n\n // Generate date prefix for filenames\n const date = new Date().toISOString().split(\"T\")[0].replace(/-/g, \"\");\n\n // Rename files with ordering\n return sortedFiles.map((file, index) => {\n const fromVersion = file.fromVersion ?? 0;\n const toVersion = file.toVersion ?? 0;\n\n // Create new filename with ordering\n const orderNum = (index + 1).toString().padStart(3, \"0\");\n const fromPadded = fromVersion.toString().padStart(3, \"0\");\n const toPadded = toVersion.toString().padStart(3, \"0\");\n\n const safeName = file.namespaceKey.replace(/[^a-z0-9-]/gi, \"_\");\n const newPath = `${date}_${orderNum}_f${fromPadded}_t${toPadded}_${safeName}.sql`;\n\n return {\n schema: file.schema,\n path: newPath,\n namespace: file.namespace,\n };\n });\n}\n"],"mappings":";;;;;;;;;AA8CA,MAAM,uBAAuB;AAC7B,MAAM,sBAAsB;AAE5B,MAAM,uBAAuB,UAC3B,mBAAmB,SAAS,MAA2B;AAEzD,eAAsB,wBAGpB,WAAuB,SAAoE;AAC3F,KAAI,UAAU,WAAW,EACvB,OAAM,IAAI,MAAM,8CAA8C;CAGhE,MAAM,UAAU,UAAU;CAC1B,MAAM,UAAU,QAAQ;CACxB,MAAM,SAAS,SAAS,UAAU;AAElC,KAAI,WAAW,OAAO;AACpB,MAAI,SAAS,cAAc,UAAa,SAAS,gBAAgB,OAC/D,OAAM,IAAI,MAAM,qEAAqE;EAGvF,MAAM,eAAe,QAAQ,iBAAiB;AAC9C,MAAI,CAAC,gBAAgB,CAAC,oBAAoB,aAAa,CACrD,OAAM,IAAI,MACR,uFACD;EAMH,MAAM,+BAAe,IAAI,KAA8D;AAGvF,eAAa,IAAI,eAAe,MAAM;GACpC,QAAQ;GACR,WAAW;GACZ,CAAC;AAIF,OAAK,MAAM,MAAM,WAAW;GAC1B,MAAM,eAAe,GAAG,aAAa,GAAG,OAAO;AAC/C,OAAI,CAAC,aAAa,IAAI,aAAa,CACjC,cAAa,IAAI,cAAc;IAC7B,QAAQ,GAAG;IACX,WAAW,GAAG;IACf,CAAC;;EAIN,MAAM,eAAe,MAAM,KAAK,aAAa,QAAQ,CAAC;EACtD,MAAM,cAAc,WAAW,YAAY,uBAAuB;AAWlE,SAAO,CACL;GACE,QAXF,WAAW,YACP,sBAAsB,cAAc,cAAc,EAChD,gBAAgB,QAAQ,gBACzB,CAAC,GACF,qBAAqB,cAAc,cAAc;IAC/C,mBAAmB,QAAQ,iBAAiB;IAC5C,gBAAgB,QAAQ;IACzB,CAAC;GAKJ,MAAM,SAAS,QAAQ;GACvB,WAAW,QAAQ;GACpB,CACF;;AAIH,KAAI,CAAC,QAAQ,kBACX,OAAM,IAAI,MACR,mGACD;AAGH,KAAI,CAAE,MAAM,QAAQ,qBAAqB,CACvC,OAAM,IAAI,MACR,2FACD;CASH,MAAM,wBAAwB,MAAM,6BALX,YAAY,oBAAoB,CACtD,WAAW,EAAE,CAAC,CACd,YAAY;EAAE,iBAAiB;EAAS,mBAAmB;EAAM,CAAC,CAClE,OAAO,EAEyE,GAAG;CAEtF,MAAMA,iBAA6C,EAAE;CAGrD,MAAM,6BAA6B,QAAQ,kBAAkB,gBAAgB,GAAG;CAChF,MAAM,wBAAwB,eAAe;CAG7C,MAAM,cAAc,2BAA2B,OAC7C,uBACA,sBACD;AAED,KAAI,YAAY,MAAM,CACpB,gBAAe,KAAK;EAClB,QAAQ;EACR,MAAM;EACN,WAAW;EACX,cAAc;EACd,YAAY,eAAe;EAC3B,YAAY;EACZ,aAAa;EACb,WAAW;EACZ,CAAC;AAIJ,MAAK,MAAM,MAAM,WAAW;EAC1B,MAAM,YAAY,GAAG;AAGrB,MAAI,CAAC,UAAU,kBACb,OAAM,IAAI,MACR,eAAe,GAAG,aAAa,GAAG,OAAO,KAAK,2FAE/C;EAGH,MAAM,qBAAqB,UAAU,kBAAkB,GAAG,QAAQ,GAAG,UAAU;EAC/E,MAAM,gBAAgB,SAAS,aAAa,GAAG,OAAO;EACtD,MAAM,gBAAgB,SAAS,eAAe;EAG9C,MAAM,MAAM,mBAAmB,OAAO,eAAe,cAAc;AAGnE,MAAI,IAAI,MAAM,CACZ,gBAAe,KAAK;GAClB,QAAQ;GACR,MAAM;GACN,WAAW,GAAG;GACd,cAAc,GAAG,aAAa,GAAG,OAAO;GACxC,YAAY,GAAG,OAAO;GACtB,YAAY;GACZ,aAAa;GACb,WAAW;GACZ,CAAC;;AAKN,QAAO,8BAA8B,eAAe;;;;;;;;;AAUtD,eAAsB,kBACpB,WACmC;AACnC,KAAI,UAAU,WAAW,EACvB,OAAM,IAAI,MAAM,sCAAsC;CAIxD,MAAM,UADU,UAAU,GACF;AAGxB,KAAI,CAAC,QAAQ,kBACX,OAAM,IAAI,MACR,mKAED;CAIH,MAAM,mBAAmB,QAAQ;CACjC,MAAM,sBAAsB,QAAQ;AAEpC,MAAK,MAAM,MAAM,WAAW;EAC1B,MAAM,gBAAgB,GAAG,QAAQ;EACjC,MAAM,mBAAmB,GAAG,QAAQ;AAEpC,MAAI,kBAAkB,oBAAoB,qBAAqB,oBAC7D,OAAM,IAAI,MACR,4DACY,iBAAiB,GAAG,oBAAoB,OAAO,cAAc,GAAG,mBAC7E;;AAIL,KAAI,CAAE,MAAM,QAAQ,qBAAqB,CACvC,OAAM,IAAI,MACR,2FACD;CAGH,MAAMC,UAAoC,EAAE;CAC5C,MAAMC,sBAMD,EAAE;CAIP,MAAM,mBAAmB,YAAY,oBAAoB,CACtD,WAAW,EAAE,CAAC,CACd,YAAY;EAAE,iBAAiB;EAAS,mBAAmB;EAAM,CAAC,CAClE,OAAO;CAEV,MAAM,wBAAwB,MAAM,6BAA6B,kBAAkB,GAAG;CAGtF,MAAM,6BAA6B,QAAQ,kBAAkB,gBAAgB,GAAG;CAChF,MAAM,wBAAwB,eAAe;AAE7C,KAAI,wBAAwB,uBAO1B;MAN0B,2BAA2B,QACnD,uBACA,uBACA,EAAE,0BAA0B,MAAM,CACnC,CAEqB,WAAW,SAAS,EACxC,qBAAoB,KAAK;GACvB,WAAW;GACX,cAAc;GACd,aAAa;GACb,WAAW;GACX,eACE,2BAA2B,QAAQ,uBAAuB,uBAAuB,EAC/E,0BAA0B,MAC3B,CAAC;GACL,CAAC;;CAKN,MAAM,mBAAmB,OAAkC,GAAG,aAAa,GAAG,OAAO;CACrF,MAAM,kBAAkB,CAAC,GAAG,UAAU,CAAC,MAAM,GAAG,MAC9C,gBAAgB,EAAE,CAAC,cAAc,gBAAgB,EAAE,CAAC,CACrD;AAED,MAAK,MAAM,YAAY,iBAAiB;EACtC,MAAM,eAAe,gBAAgB,SAAS;EAC9C,MAAM,qBAAqB,QAAQ,kBAAkB,SAAS,QAAQ,SAAS,UAAU;EACzF,MAAM,iBAAiB,MAAM,6BAA6B,kBAAkB,aAAa;EACzF,MAAM,gBAAgB,SAAS,OAAO;AAEtC,MAAI,iBAAiB,eAKnB;OAJ0B,mBAAmB,QAAQ,gBAAgB,eAAe,EAClF,0BAA0B,MAC3B,CAAC,CAEoB,WAAW,SAAS,EACxC,qBAAoB,KAAK;IACvB,WAAW,SAAS;IACpB;IACA,aAAa;IACb,WAAW;IACX,eACE,mBAAmB,QAAQ,gBAAgB,eAAe,EACxD,0BAA0B,MAC3B,CAAC;IACL,CAAC;;;CAMR,MAAM,wCAAwB,IAAI,KAAa;AAC/C,MAAK,MAAM,aAAa,qBAAqB;AAC3C,QAAM,UAAU,SAAS;AACzB,UAAQ,KAAK;GACX,WAAW,UAAU;GACrB,YAAY;GACZ,aAAa,UAAU;GACvB,WAAW,UAAU;GACtB,CAAC;AACF,wBAAsB,IAAI,UAAU,aAAa;;AAInD,MAAK,MAAM,YAAY,WAAW;EAChC,MAAM,eAAe,gBAAgB,SAAS;AAC9C,MAAI,CAAC,sBAAsB,IAAI,aAAa,CAC1C,SAAQ,KAAK;GACX,WAAW,SAAS;GACpB,YAAY;GACZ,aAAa,SAAS,OAAO;GAC7B,WAAW,SAAS,OAAO;GAC5B,CAAC;;AAIN,QAAO;;;;;;;;;;;;AAaT,SAAgB,8BACd,OAC0B;AAC1B,KAAI,MAAM,WAAW,EACnB,QAAO,EAAE;CAIX,MAAM,cAAc,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM;AAC5C,MAAI,EAAE,WACJ,QAAO;AAET,MAAI,EAAE,WACJ,QAAO;AAET,SAAO,EAAE,aAAa,cAAc,EAAE,aAAa;GACnD;CAGF,MAAM,wBAAO,IAAI,MAAM,EAAC,aAAa,CAAC,MAAM,IAAI,CAAC,GAAG,QAAQ,MAAM,GAAG;AAGrE,QAAO,YAAY,KAAK,MAAM,UAAU;EACtC,MAAM,cAAc,KAAK,eAAe;EACxC,MAAM,YAAY,KAAK,aAAa;EAQpC,MAAM,UAAU,GAAG,KAAK,IALN,QAAQ,GAAG,UAAU,CAAC,SAAS,GAAG,IAAI,CAKpB,IAJjB,YAAY,UAAU,CAAC,SAAS,GAAG,IAAI,CAIP,IAHlC,UAAU,UAAU,CAAC,SAAS,GAAG,IAAI,CAGU,GAD/C,KAAK,aAAa,QAAQ,gBAAgB,IAAI,CACa;AAE5E,SAAO;GACL,QAAQ,KAAK;GACb,MAAM;GACN,WAAW,KAAK;GACjB;GACD"}
|
|
1
|
+
{"version":3,"file":"generation-engine.js","names":["generatedFiles: GenerationInternalResult[]","results: ExecuteMigrationResult[]","migrationsToExecute: Array<{\n namespace: string | null;\n namespaceKey: string;\n fromVersion: number;\n toVersion: number;\n execute: () => Promise<void>;\n }>"],"sources":["../../src/migration-engine/generation-engine.ts"],"sourcesContent":["import { instantiate } from \"@fragno-dev/core\";\n\nimport {\n fragnoDatabaseAdapterNameFakeSymbol,\n fragnoDatabaseAdapterVersionFakeSymbol,\n} from \"../adapters/adapters\";\nimport { supportedDatabases, type SupportedDatabase } from \"../adapters/generic-sql/driver-config\";\nimport {\n internalFragmentDef,\n internalSchema,\n SETTINGS_TABLE_NAME,\n getSchemaVersionFromDatabase,\n} from \"../fragments/internal-fragment\";\nimport { getRegistryForAdapterSync } from \"../internal/adapter-registry\";\nimport type { FragnoDatabase } from \"../mod\";\nimport { generateDrizzleSchema } from \"../schema-output/drizzle\";\nimport { generatePrismaSchema } from \"../schema-output/prisma\";\nimport type { AnySchema } from \"../schema/create\";\n\nexport interface GenerationEngineResult {\n schema: string;\n path: string;\n namespace: string | null;\n}\n\nexport type SchemaOutputFormat = \"sql\" | \"drizzle\" | \"prisma\";\n\nexport interface GenerateSchemaOptions {\n format?: SchemaOutputFormat;\n path?: string;\n toVersion?: number;\n fromVersion?: number;\n}\n\nexport interface GenerationInternalResult {\n schema: string;\n path: string;\n namespace: string | null;\n namespaceKey: string;\n schemaName: string;\n isSettings: boolean;\n fromVersion: number;\n toVersion: number;\n}\n\nexport interface ExecuteMigrationResult {\n namespace: string | null;\n didMigrate: boolean;\n fromVersion: number;\n toVersion: number;\n}\n\nconst DEFAULT_DRIZZLE_PATH = \"fragno-schema.ts\";\nconst DEFAULT_PRISMA_PATH = \"fragno.prisma\";\n\nconst isSupportedDatabase = (value: string): value is SupportedDatabase =>\n supportedDatabases.includes(value as SupportedDatabase);\n\nexport async function generateSchemaArtifacts<\n // oxlint-disable-next-line no-explicit-any\n const TDatabases extends FragnoDatabase<AnySchema, any>[],\n>(databases: TDatabases, options?: GenerateSchemaOptions): Promise<GenerationEngineResult[]> {\n if (databases.length === 0) {\n throw new Error(\"No databases provided for schema generation\");\n }\n\n const firstDb = databases[0];\n const adapter = firstDb.adapter;\n const format = options?.format ?? \"sql\";\n\n if (format !== \"sql\") {\n if (options?.toVersion !== undefined || options?.fromVersion !== undefined) {\n throw new Error(\"--from and --to are only supported when generating SQL migrations.\");\n }\n\n const databaseType = adapter.adapterMetadata?.databaseType;\n if (!databaseType || !isSupportedDatabase(databaseType)) {\n throw new Error(\n \"Adapter does not expose databaseType metadata required for schema output generation.\",\n );\n }\n\n // Collect all schemas, de-duplicating by namespace.\n // The internal fragment (settings schema) is always included first since all database\n // fragments share it via the adapter registry.\n const fragmentsMap = new Map<string, { schema: AnySchema; namespace: string | null }>();\n\n // Include internal fragment first with empty namespace (settings table has no prefix)\n fragmentsMap.set(internalSchema.name, {\n schema: internalSchema,\n namespace: null,\n });\n\n // Add user fragments, de-duplicating by namespace\n // Each FragnoDatabase has a unique namespace, so this prevents duplicate schema generation\n for (const db of databases) {\n const namespaceKey = db.namespace ?? db.schema.name;\n if (!fragmentsMap.has(namespaceKey)) {\n fragmentsMap.set(namespaceKey, {\n schema: db.schema,\n namespace: db.namespace,\n });\n }\n }\n\n const allFragments = Array.from(fragmentsMap.entries())\n .map(([namespaceKey, fragment]) => ({\n ...fragment,\n namespaceKey,\n isInternal: fragment.schema === internalSchema,\n }))\n .sort((a, b) => {\n if (a.isInternal) {\n return -1;\n }\n if (b.isInternal) {\n return 1;\n }\n return a.schema.name.localeCompare(b.schema.name);\n })\n .map(({ schema, namespace }) => ({ schema, namespace }));\n const defaultPath = format === \"drizzle\" ? DEFAULT_DRIZZLE_PATH : DEFAULT_PRISMA_PATH;\n const schema =\n format === \"drizzle\"\n ? generateDrizzleSchema(allFragments, databaseType, {\n namingStrategy: adapter.namingStrategy,\n })\n : generatePrismaSchema(allFragments, databaseType, {\n sqliteStorageMode: adapter.adapterMetadata?.sqliteStorageMode,\n namingStrategy: adapter.namingStrategy,\n });\n\n return [\n {\n schema,\n path: options?.path ?? defaultPath,\n namespace: firstDb.namespace,\n },\n ];\n }\n\n // Otherwise, use migration engine for SQL migration generation.\n if (!adapter.prepareMigrations) {\n throw new Error(\n \"Adapter does not support migration generation. Ensure your adapter implements prepareMigrations.\",\n );\n }\n\n if (!(await adapter.isConnectionHealthy())) {\n throw new Error(\n \"Database connection is not healthy. Please check your database connection and try again.\",\n );\n }\n\n // Use the internal fragment for settings management\n const internalFragment = instantiate(internalFragmentDef)\n .withConfig({ registry: getRegistryForAdapterSync(adapter) })\n .withOptions({ databaseAdapter: adapter, databaseNamespace: null })\n .build();\n\n const settingsSourceVersion = await getSchemaVersionFromDatabase(internalFragment, \"\");\n\n const generatedFiles: GenerationInternalResult[] = [];\n\n // Internal fragment uses empty-string namespace: no table suffix, version key is \".schema_version\"\n const settingsPreparedMigrations = adapter.prepareMigrations(internalSchema, \"\");\n const settingsTargetVersion = internalSchema.version;\n\n // Generate settings table migration\n const settingsSql = settingsPreparedMigrations.getSQL(\n settingsSourceVersion,\n settingsTargetVersion,\n );\n\n if (settingsSql.trim()) {\n generatedFiles.push({\n schema: settingsSql,\n path: \"settings-migration.sql\", // Placeholder, will be renamed in post-processing\n namespace: null,\n namespaceKey: SETTINGS_TABLE_NAME,\n schemaName: internalSchema.name,\n isSettings: true,\n fromVersion: settingsSourceVersion,\n toVersion: settingsTargetVersion,\n });\n }\n\n // Generate migration for each fragment\n for (const db of databases) {\n const dbAdapter = db.adapter;\n\n // Use migration engine\n if (!dbAdapter.prepareMigrations) {\n throw new Error(\n `Adapter for ${db.namespace ?? db.schema.name} does not support migration generation. ` +\n `Ensure your adapter implements prepareMigrations.`,\n );\n }\n\n const preparedMigrations = dbAdapter.prepareMigrations(db.schema, db.namespace);\n const targetVersion = options?.toVersion ?? db.schema.version;\n const sourceVersion = options?.fromVersion ?? 0;\n\n // Generate migration from source to target version\n const sql = preparedMigrations.getSQL(sourceVersion, targetVersion);\n\n // If no migrations needed, skip this fragment\n if (sql.trim()) {\n generatedFiles.push({\n schema: sql,\n path: \"schema.sql\", // Placeholder, will be renamed in post-processing\n namespace: db.namespace,\n namespaceKey: db.namespace ?? db.schema.name,\n schemaName: db.schema.name,\n isSettings: false,\n fromVersion: sourceVersion,\n toVersion: targetVersion,\n });\n }\n }\n\n // Post-process filenames with ordering\n return postProcessMigrationFilenames(generatedFiles);\n}\n\n/**\n * Execute migrations for all fragments in the correct order.\n * Migrates settings table first, then fragments alphabetically.\n *\n * @param databases - Array of FragnoDatabase instances to migrate\n * @returns Array of execution results for each migration\n */\nexport async function executeMigrations<const TDatabases extends FragnoDatabase<AnySchema>[]>(\n databases: TDatabases,\n): Promise<ExecuteMigrationResult[]> {\n if (databases.length === 0) {\n throw new Error(\"No databases provided for migration\");\n }\n\n const firstDb = databases[0];\n const adapter = firstDb.adapter;\n\n // Validate adapter supports migrations\n if (!adapter.prepareMigrations) {\n throw new Error(\n \"Adapter does not support running migrations. The adapter only supports schema generation.\\n\" +\n \"Try using 'generateSchemaArtifacts' instead to generate schema files.\",\n );\n }\n\n // Validate all use same adapter name and version\n const firstAdapterName = adapter[fragnoDatabaseAdapterNameFakeSymbol];\n const firstAdapterVersion = adapter[fragnoDatabaseAdapterVersionFakeSymbol];\n\n for (const db of databases) {\n const dbAdapterName = db.adapter[fragnoDatabaseAdapterNameFakeSymbol];\n const dbAdapterVersion = db.adapter[fragnoDatabaseAdapterVersionFakeSymbol];\n\n if (dbAdapterName !== firstAdapterName || dbAdapterVersion !== firstAdapterVersion) {\n throw new Error(\n `All fragments must use the same database adapter. ` +\n `Found: ${firstAdapterName}@${firstAdapterVersion} and ${dbAdapterName}@${dbAdapterVersion}`,\n );\n }\n }\n\n if (!(await adapter.isConnectionHealthy())) {\n throw new Error(\n \"Database connection is not healthy. Please check your database connection and try again.\",\n );\n }\n\n const results: ExecuteMigrationResult[] = [];\n const migrationsToExecute: Array<{\n namespace: string | null;\n namespaceKey: string;\n fromVersion: number;\n toVersion: number;\n execute: () => Promise<void>;\n }> = [];\n\n // 1. Prepare settings table migration\n // Use the internal fragment for settings management\n const internalFragment = instantiate(internalFragmentDef)\n .withConfig({ registry: getRegistryForAdapterSync(adapter) })\n .withOptions({ databaseAdapter: adapter, databaseNamespace: null })\n .build();\n\n const settingsSourceVersion = await getSchemaVersionFromDatabase(internalFragment, \"\");\n\n // Internal fragment uses empty-string namespace: no table suffix, version key is \".schema_version\"\n const settingsPreparedMigrations = adapter.prepareMigrations(internalSchema, \"\");\n const settingsTargetVersion = internalSchema.version;\n\n if (settingsSourceVersion < settingsTargetVersion) {\n const compiledMigration = settingsPreparedMigrations.compile(\n settingsSourceVersion,\n settingsTargetVersion,\n { updateVersionInMigration: true },\n );\n\n if (compiledMigration.statements.length > 0) {\n migrationsToExecute.push({\n namespace: null,\n namespaceKey: SETTINGS_TABLE_NAME,\n fromVersion: settingsSourceVersion,\n toVersion: settingsTargetVersion,\n execute: () =>\n settingsPreparedMigrations.execute(settingsSourceVersion, settingsTargetVersion, {\n updateVersionInMigration: true,\n }),\n });\n }\n }\n\n // 2. Prepare fragment migrations (sorted alphabetically)\n const getNamespaceKey = (db: FragnoDatabase<AnySchema>) => db.namespace ?? db.schema.name;\n const sortedDatabases = [...databases].sort((a, b) =>\n getNamespaceKey(a).localeCompare(getNamespaceKey(b)),\n );\n\n for (const fragnoDb of sortedDatabases) {\n const namespaceKey = getNamespaceKey(fragnoDb);\n const preparedMigrations = adapter.prepareMigrations(fragnoDb.schema, fragnoDb.namespace);\n const currentVersion = await getSchemaVersionFromDatabase(internalFragment, namespaceKey);\n const targetVersion = fragnoDb.schema.version;\n\n if (currentVersion < targetVersion) {\n const compiledMigration = preparedMigrations.compile(currentVersion, targetVersion, {\n updateVersionInMigration: true,\n });\n\n if (compiledMigration.statements.length > 0) {\n migrationsToExecute.push({\n namespace: fragnoDb.namespace,\n namespaceKey,\n fromVersion: currentVersion,\n toVersion: targetVersion,\n execute: () =>\n preparedMigrations.execute(currentVersion, targetVersion, {\n updateVersionInMigration: true,\n }),\n });\n }\n }\n }\n\n // 3. Execute all migrations in order\n const executedNamespaceKeys = new Set<string>();\n for (const migration of migrationsToExecute) {\n await migration.execute();\n results.push({\n namespace: migration.namespace,\n didMigrate: true,\n fromVersion: migration.fromVersion,\n toVersion: migration.toVersion,\n });\n executedNamespaceKeys.add(migration.namespaceKey);\n }\n\n // 4. Add skipped migrations (already up-to-date)\n for (const fragnoDb of databases) {\n const namespaceKey = getNamespaceKey(fragnoDb);\n if (!executedNamespaceKeys.has(namespaceKey)) {\n results.push({\n namespace: fragnoDb.namespace,\n didMigrate: false,\n fromVersion: fragnoDb.schema.version,\n toVersion: fragnoDb.schema.version,\n });\n }\n }\n\n return results;\n}\n\n/**\n * Post-processes migration files to add ordering and standardize naming.\n *\n * Sorts files with settings namespace first, then alphabetically by namespace key,\n * and assigns ordering numbers. Transforms filenames to format:\n * `<date>_<n>_f<from>_t<to>_<namespace>.sql`\n *\n * @param files - Array of generated migration files with version information\n * @returns Array of files with standardized paths and ordering\n */\nexport function postProcessMigrationFilenames(\n files: GenerationInternalResult[],\n): GenerationEngineResult[] {\n if (files.length === 0) {\n return [];\n }\n\n // Sort files: settings first, then alphabetically by namespace key\n const sortedFiles = [...files].sort((a, b) => {\n if (a.isSettings) {\n return -1;\n }\n if (b.isSettings) {\n return 1;\n }\n return a.namespaceKey.localeCompare(b.namespaceKey);\n });\n\n // Generate date prefix for filenames\n const date = new Date().toISOString().split(\"T\")[0].replace(/-/g, \"\");\n\n // Rename files with ordering\n return sortedFiles.map((file, index) => {\n const fromVersion = file.fromVersion ?? 0;\n const toVersion = file.toVersion ?? 0;\n\n // Create new filename with ordering\n const orderNum = (index + 1).toString().padStart(3, \"0\");\n const fromPadded = fromVersion.toString().padStart(3, \"0\");\n const toPadded = toVersion.toString().padStart(3, \"0\");\n\n const safeName = file.namespaceKey.replace(/[^a-z0-9-]/gi, \"_\");\n const newPath = `${date}_${orderNum}_f${fromPadded}_t${toPadded}_${safeName}.sql`;\n\n return {\n schema: file.schema,\n path: newPath,\n namespace: file.namespace,\n };\n });\n}\n"],"mappings":"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"}
|