@fragno-dev/db 0.2.2 → 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 +404 -175
- package/CHANGELOG.md +109 -0
- package/README.md +54 -9
- package/dist/adapters/adapters.d.ts +23 -21
- package/dist/adapters/adapters.d.ts.map +1 -1
- package/dist/adapters/adapters.js.map +1 -1
- package/dist/adapters/generic-sql/driver-config.d.ts +16 -1
- package/dist/adapters/generic-sql/driver-config.d.ts.map +1 -1
- package/dist/adapters/generic-sql/driver-config.js +23 -1
- package/dist/adapters/generic-sql/driver-config.js.map +1 -1
- package/dist/adapters/generic-sql/generic-sql-adapter.d.ts +24 -9
- package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -1
- package/dist/adapters/generic-sql/generic-sql-adapter.js +60 -22
- package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -1
- package/dist/adapters/generic-sql/generic-sql-uow-executor.js +169 -3
- 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 +25 -6
- package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -1
- package/dist/adapters/generic-sql/migration/dialect/postgres.js +7 -6
- package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -1
- package/dist/adapters/generic-sql/migration/dialect/sqlite.js +193 -16
- 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 +9 -9
- package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -1
- package/dist/adapters/generic-sql/migration/sql-generator.js +75 -52
- package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -1
- package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +7 -6
- package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -1
- package/dist/adapters/generic-sql/query/cursor-utils.js +42 -4
- 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 +32 -21
- package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -1
- package/dist/adapters/generic-sql/query/select-builder.js +5 -3
- package/dist/adapters/generic-sql/query/select-builder.js.map +1 -1
- package/dist/adapters/generic-sql/query/sql-query-compiler.js +49 -18
- package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -1
- package/dist/adapters/generic-sql/query/where-builder.js +43 -29
- package/dist/adapters/generic-sql/query/where-builder.js.map +1 -1
- package/dist/adapters/generic-sql/sqlite-storage.d.ts +13 -0
- package/dist/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
- package/dist/adapters/generic-sql/sqlite-storage.js +15 -0
- package/dist/adapters/generic-sql/sqlite-storage.js.map +1 -0
- package/dist/adapters/generic-sql/uow-decoder.js +6 -2
- package/dist/adapters/generic-sql/uow-decoder.js.map +1 -1
- package/dist/adapters/generic-sql/uow-encoder.js +27 -8
- package/dist/adapters/generic-sql/uow-encoder.js.map +1 -1
- package/dist/adapters/in-memory/condition-evaluator.js +135 -0
- package/dist/adapters/in-memory/condition-evaluator.js.map +1 -0
- package/dist/adapters/in-memory/errors.d.ts +13 -0
- package/dist/adapters/in-memory/errors.d.ts.map +1 -0
- package/dist/adapters/in-memory/errors.js +23 -0
- package/dist/adapters/in-memory/errors.js.map +1 -0
- package/dist/adapters/in-memory/in-memory-adapter.d.ts +27 -0
- package/dist/adapters/in-memory/in-memory-adapter.d.ts.map +1 -0
- package/dist/adapters/in-memory/in-memory-adapter.js +196 -0
- package/dist/adapters/in-memory/in-memory-adapter.js.map +1 -0
- package/dist/adapters/in-memory/in-memory-uow.js +871 -0
- package/dist/adapters/in-memory/in-memory-uow.js.map +1 -0
- package/dist/adapters/in-memory/index.d.ts +4 -0
- package/dist/adapters/in-memory/index.js +4 -0
- package/dist/adapters/in-memory/options.d.ts +30 -0
- package/dist/adapters/in-memory/options.d.ts.map +1 -0
- package/dist/adapters/in-memory/options.js +62 -0
- package/dist/adapters/in-memory/options.js.map +1 -0
- package/dist/adapters/in-memory/reference-resolution.js +26 -0
- package/dist/adapters/in-memory/reference-resolution.js.map +1 -0
- package/dist/adapters/in-memory/sorted-array-index.js +129 -0
- package/dist/adapters/in-memory/sorted-array-index.js.map +1 -0
- package/dist/adapters/in-memory/store.js +71 -0
- package/dist/adapters/in-memory/store.js.map +1 -0
- package/dist/adapters/in-memory/value-comparison.js +28 -0
- package/dist/adapters/in-memory/value-comparison.js.map +1 -0
- 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 +11 -11
- package/dist/adapters/shared/uow-operation-compiler.js.map +1 -1
- package/dist/adapters/sql/index.d.ts +5 -0
- package/dist/adapters/sql/index.js +4 -0
- 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 +101 -33
- package/dist/db-fragment-definition-builder.d.ts.map +1 -1
- package/dist/db-fragment-definition-builder.js +450 -60
- 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 +11 -0
- package/dist/dispatchers/cloudflare-do/index.d.ts.map +1 -0
- package/dist/dispatchers/cloudflare-do/index.js +31 -0
- package/dist/dispatchers/cloudflare-do/index.js.map +1 -0
- 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 +12 -0
- package/dist/dispatchers/node/index.d.ts.map +1 -0
- package/dist/dispatchers/node/index.js +27 -0
- package/dist/dispatchers/node/index.js.map +1 -0
- 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 +186 -8
- package/dist/fragments/internal-fragment.d.ts.map +1 -1
- package/dist/fragments/internal-fragment.js +203 -38
- package/dist/fragments/internal-fragment.js.map +1 -1
- package/dist/fragments/internal-fragment.routes.js +164 -0
- package/dist/fragments/internal-fragment.routes.js.map +1 -0
- package/dist/fragments/internal-fragment.schema.d.ts +15 -0
- package/dist/fragments/internal-fragment.schema.d.ts.map +1 -0
- package/dist/fragments/internal-fragment.schema.js +39 -0
- package/dist/fragments/internal-fragment.schema.js.map +1 -0
- 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 -0
- package/dist/hooks/durable-hooks-processor.js +80 -0
- package/dist/hooks/durable-hooks-processor.js.map +1 -0
- 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 +100 -1
- package/dist/hooks/hooks.d.ts.map +1 -1
- package/dist/hooks/hooks.js +254 -27
- 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 +223 -37
- package/dist/migration-engine/auto-from-schema.js.map +1 -1
- package/dist/migration-engine/generation-engine.d.ts +16 -10
- package/dist/migration-engine/generation-engine.d.ts.map +1 -1
- package/dist/migration-engine/generation-engine.js +86 -35
- 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 +20 -12
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +18 -12
- package/dist/mod.js.map +1 -1
- package/dist/naming/sql-naming.d.ts +19 -0
- package/dist/naming/sql-naming.d.ts.map +1 -0
- package/dist/naming/sql-naming.js +116 -0
- package/dist/naming/sql-naming.js.map +1 -0
- package/dist/outbox/outbox-builder.js +156 -0
- package/dist/outbox/outbox-builder.js.map +1 -0
- package/dist/outbox/outbox.d.ts +54 -0
- package/dist/outbox/outbox.d.ts.map +1 -0
- package/dist/outbox/outbox.js +37 -0
- package/dist/outbox/outbox.js.map +1 -0
- package/dist/query/column-defaults.js +20 -4
- 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 +3 -1
- package/dist/query/cursor.d.ts.map +1 -1
- package/dist/query/cursor.js +51 -14
- package/dist/query/cursor.js.map +1 -1
- package/dist/query/db-now.d.ts +22 -0
- package/dist/query/db-now.d.ts.map +1 -0
- package/dist/query/db-now.js +35 -0
- package/dist/query/db-now.js.map +1 -0
- package/dist/query/orm/orm.js.map +1 -1
- package/dist/query/serialize/create-sql-serializer.js +5 -4
- package/dist/query/serialize/create-sql-serializer.js.map +1 -1
- package/dist/query/serialize/dialect/mysql-serializer.js +12 -6
- package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -1
- package/dist/query/serialize/dialect/postgres-serializer.js +25 -7
- package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -1
- package/dist/query/serialize/dialect/sqlite-serializer.js +60 -12
- package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -1
- package/dist/query/serialize/sql-serializer.js +2 -2
- package/dist/query/serialize/sql-serializer.js.map +1 -1
- package/dist/query/simple-query-interface.d.ts +13 -4
- 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 +50 -24
- 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 +92 -30
- package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
- package/dist/query/unit-of-work/unit-of-work.js +136 -11
- package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
- package/dist/query/value-decoding.js +16 -6
- package/dist/query/value-decoding.js.map +1 -1
- package/dist/query/value-encoding.js +29 -9
- package/dist/query/value-encoding.js.map +1 -1
- package/dist/schema/create.d.ts +103 -35
- package/dist/schema/create.d.ts.map +1 -1
- package/dist/schema/create.js +172 -58
- package/dist/schema/create.js.map +1 -1
- package/dist/schema/generate-id.js +2 -2
- package/dist/schema/generate-id.js.map +1 -1
- package/dist/schema/type-conversion/create-sql-type-mapper.js +4 -3
- package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -1
- package/dist/schema/type-conversion/dialect/sqlite.js +9 -0
- package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -1
- package/dist/schema/validator.d.ts +10 -0
- package/dist/schema/validator.d.ts.map +1 -0
- package/dist/schema/validator.js +123 -0
- package/dist/schema/validator.js.map +1 -0
- package/dist/schema-output/drizzle.d.ts +30 -0
- package/dist/schema-output/drizzle.d.ts.map +1 -0
- package/dist/{adapters/drizzle/generate.js → schema-output/drizzle.js} +88 -60
- package/dist/schema-output/drizzle.js.map +1 -0
- package/dist/schema-output/prisma.d.ts +17 -0
- package/dist/schema-output/prisma.d.ts.map +1 -0
- package/dist/schema-output/prisma.js +307 -0
- package/dist/schema-output/prisma.js.map +1 -0
- 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 +66 -0
- package/dist/util/default-database-adapter.js.map +1 -0
- package/dist/with-database.d.ts +3 -6
- package/dist/with-database.d.ts.map +1 -1
- package/dist/with-database.js +8 -7
- package/dist/with-database.js.map +1 -1
- package/package.json +62 -55
- package/src/adapters/adapters.ts +33 -26
- package/src/adapters/drizzle/migrate-drizzle.test.ts +99 -41
- package/src/adapters/drizzle/migration-parity-drizzle-kit.test.ts +601 -0
- package/src/adapters/drizzle/test-utils.ts +13 -8
- package/src/adapters/generic-sql/driver-config.ts +38 -0
- package/src/adapters/generic-sql/generic-sql-adapter.test.ts +10 -8
- package/src/adapters/generic-sql/generic-sql-adapter.ts +117 -34
- package/src/adapters/generic-sql/generic-sql-uow-executor.test.ts +55 -0
- package/src/adapters/generic-sql/generic-sql-uow-executor.ts +297 -3
- package/src/adapters/generic-sql/migration/adapter-migration-parity.test.ts +120 -0
- package/src/adapters/generic-sql/migration/cold-kysely.ts +1 -0
- package/src/adapters/generic-sql/migration/dialect/mysql.test.ts +27 -8
- package/src/adapters/generic-sql/migration/dialect/mysql.ts +47 -8
- package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +28 -9
- package/src/adapters/generic-sql/migration/dialect/postgres.ts +9 -4
- package/src/adapters/generic-sql/migration/dialect/sqlite.test.ts +839 -8
- package/src/adapters/generic-sql/migration/dialect/sqlite.ts +396 -53
- 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 +238 -46
- package/src/adapters/generic-sql/migration/prepared-migrations.ts +21 -13
- package/src/adapters/generic-sql/migration/sql-generator.ts +145 -66
- package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +11 -8
- package/src/adapters/generic-sql/query/cursor-utils.test.ts +272 -0
- package/src/adapters/generic-sql/query/cursor-utils.ts +42 -7
- 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 +171 -35
- package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +53 -40
- package/src/adapters/generic-sql/query/select-builder.test.ts +16 -11
- package/src/adapters/generic-sql/query/select-builder.ts +7 -3
- package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +75 -6
- package/src/adapters/generic-sql/query/sql-query-compiler.ts +129 -24
- package/src/adapters/generic-sql/query/where-builder.test.ts +96 -20
- package/src/adapters/generic-sql/query/where-builder.ts +112 -41
- package/src/adapters/{kysely/kysely-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-migrations.test.ts} +11 -20
- package/src/adapters/generic-sql/sql-adapter-pglite-pagination.test.ts +851 -0
- package/src/adapters/{drizzle/drizzle-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-queries.test.ts} +18 -15
- package/src/adapters/generic-sql/{test/generic-drizzle-adapter-sqlite3.test.ts → sql-adapter-sqlite3-driver.test.ts} +282 -14
- package/src/adapters/{drizzle/drizzle-adapter-sqlite3.test.ts → generic-sql/sql-adapter-sqlite3-uow.test.ts} +129 -12
- package/src/adapters/{kysely/kysely-adapter-sqlocal.test.ts → generic-sql/sql-adapter-sqlocal.test.ts} +9 -7
- package/src/adapters/generic-sql/sqlite-storage.ts +20 -0
- package/src/adapters/generic-sql/uow-decoder.test.ts +5 -4
- package/src/adapters/generic-sql/uow-decoder.ts +23 -5
- package/src/adapters/generic-sql/uow-encoder.test.ts +36 -3
- package/src/adapters/generic-sql/uow-encoder.ts +48 -13
- package/src/adapters/in-memory/condition-evaluator.test.ts +194 -0
- package/src/adapters/in-memory/condition-evaluator.ts +280 -0
- package/src/adapters/in-memory/errors.ts +20 -0
- package/src/adapters/in-memory/in-memory-adapter.ts +388 -0
- package/src/adapters/in-memory/in-memory-uow.mutations.test.ts +344 -0
- package/src/adapters/in-memory/in-memory-uow.retrieval.test.ts +255 -0
- package/src/adapters/in-memory/in-memory-uow.ts +1724 -0
- package/src/adapters/in-memory/index.ts +3 -0
- package/src/adapters/in-memory/options.test.ts +42 -0
- package/src/adapters/in-memory/options.ts +91 -0
- package/src/adapters/in-memory/outbox.test.ts +361 -0
- package/src/adapters/in-memory/reference-resolution.test.ts +51 -0
- package/src/adapters/in-memory/reference-resolution.ts +67 -0
- package/src/adapters/in-memory/sorted-array-index.test.ts +124 -0
- package/src/adapters/in-memory/sorted-array-index.ts +228 -0
- package/src/adapters/in-memory/store.test.ts +69 -0
- package/src/adapters/in-memory/store.ts +145 -0
- package/src/adapters/in-memory/value-comparison.ts +53 -0
- package/src/adapters/in-memory/value-normalization.test.ts +58 -0
- package/src/adapters/prisma/prisma-adapter-sqlite3.test.ts +1207 -0
- package/src/adapters/shared/from-unit-of-work-compiler.ts +159 -47
- package/src/adapters/shared/uow-operation-compiler.ts +28 -18
- package/src/adapters/sql/index.ts +12 -0
- package/src/browser/mod.ts +64 -0
- package/src/client.ts +19 -0
- package/src/db-fragment-definition-builder.test.ts +845 -53
- package/src/db-fragment-definition-builder.ts +911 -95
- package/src/db-fragment-instantiator.test.ts +210 -94
- package/src/db-fragment-integration.test.ts +17 -12
- package/src/dispatchers/cloudflare-do/dispatcher.ts +204 -0
- package/src/dispatchers/cloudflare-do/index.test.ts +206 -0
- package/src/dispatchers/cloudflare-do/index.ts +63 -0
- package/src/dispatchers/node/dispatcher.ts +112 -0
- package/src/dispatchers/node/index.test.ts +120 -0
- package/src/dispatchers/node/index.ts +50 -0
- 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 +334 -0
- package/src/fragments/internal-fragment.schema.ts +95 -0
- package/src/fragments/internal-fragment.test.ts +505 -83
- package/src/fragments/internal-fragment.ts +453 -70
- 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 +282 -0
- package/src/hooks/durable-hooks-processor.ts +173 -0
- 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 +455 -34
- package/src/hooks/hooks.ts +501 -34
- 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 +107 -14
- package/src/migration-engine/auto-from-schema.ts +365 -44
- package/src/migration-engine/create.test.ts +4 -3
- package/src/migration-engine/create.ts +1 -1
- package/src/migration-engine/generation-engine.test.ts +292 -110
- package/src/migration-engine/generation-engine.ts +117 -66
- package/src/migration-engine/shared.ts +14 -0
- package/src/mod.ts +95 -39
- package/src/naming/sql-naming.ts +181 -0
- package/src/outbox/outbox-builder.ts +241 -0
- package/src/outbox/outbox.test.ts +424 -0
- package/src/outbox/outbox.ts +139 -0
- package/src/query/column-defaults.ts +42 -4
- package/src/query/condition-builder.test.ts +18 -3
- 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 +119 -20
- package/src/query/cursor.ts +88 -27
- package/src/query/db-now.ts +73 -0
- package/src/query/orm/orm.ts +2 -2
- package/src/query/query-type.test.ts +4 -3
- package/src/query/serialize/create-sql-serializer.ts +10 -5
- package/src/query/serialize/dialect/mysql-serializer.ts +13 -5
- package/src/query/serialize/dialect/postgres-serializer.ts +35 -5
- package/src/query/serialize/dialect/sqlite-serializer.test.ts +90 -3
- package/src/query/serialize/dialect/sqlite-serializer.ts +108 -12
- package/src/query/serialize/sql-serializer.ts +4 -4
- package/src/query/simple-query-interface.ts +15 -4
- package/src/query/unit-of-work/execute-unit-of-work.test.ts +372 -10
- package/src/query/unit-of-work/execute-unit-of-work.ts +87 -27
- 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 +17 -16
- package/src/query/unit-of-work/unit-of-work-types.test.ts +42 -12
- package/src/query/unit-of-work/unit-of-work.test.ts +196 -39
- package/src/query/unit-of-work/unit-of-work.ts +309 -38
- package/src/query/value-decoding.test.ts +63 -4
- package/src/query/value-decoding.ts +32 -6
- package/src/query/value-encoding.test.ts +86 -2
- package/src/query/value-encoding.ts +56 -6
- package/src/schema/create.test.ts +293 -47
- package/src/schema/create.ts +406 -70
- package/src/schema/generate-id.test.ts +3 -2
- package/src/schema/generate-id.ts +2 -2
- package/src/schema/serialize.test.ts +18 -5
- package/src/schema/type-conversion/create-sql-type-mapper.ts +8 -3
- package/src/schema/type-conversion/dialect/sqlite.ts +18 -0
- package/src/schema/type-conversion/type-mapping.test.ts +26 -1
- package/src/schema/validator.test.ts +199 -0
- package/src/schema/validator.ts +232 -0
- package/src/{adapters/drizzle/generate.test.ts → schema-output/drizzle.test.ts} +232 -129
- package/src/{adapters/drizzle/generate.ts → schema-output/drizzle.ts} +155 -99
- package/src/schema-output/prisma.test.ts +694 -0
- package/src/schema-output/prisma.ts +593 -0
- 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 +119 -0
- package/src/with-database.ts +20 -31
- package/tsconfig.json +1 -1
- package/tsdown.config.ts +38 -24
- package/vitest.config.ts +1 -0
- package/dist/adapters/drizzle/drizzle-adapter.d.ts +0 -20
- package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +0 -1
- package/dist/adapters/drizzle/drizzle-adapter.js +0 -27
- package/dist/adapters/drizzle/drizzle-adapter.js.map +0 -1
- package/dist/adapters/drizzle/generate.d.ts +0 -30
- package/dist/adapters/drizzle/generate.d.ts.map +0 -1
- package/dist/adapters/drizzle/generate.js.map +0 -1
- package/dist/adapters/kysely/kysely-adapter.d.ts +0 -19
- package/dist/adapters/kysely/kysely-adapter.d.ts.map +0 -1
- package/dist/adapters/kysely/kysely-adapter.js +0 -17
- package/dist/adapters/kysely/kysely-adapter.js.map +0 -1
- package/dist/adapters/shared/table-name-mapper.d.ts +0 -12
- package/dist/adapters/shared/table-name-mapper.d.ts.map +0 -1
- package/dist/adapters/shared/table-name-mapper.js +0 -43
- package/dist/adapters/shared/table-name-mapper.js.map +0 -1
- package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js +0 -165
- package/dist/node_modules/.pnpm/rou3@0.7.10/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 -320
- package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +0 -1
- package/dist/packages/fragno/dist/api/fragment-instantiator.js +0 -525
- 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 -118
- 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 -17
- 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/schema-generator/schema-generator.d.ts +0 -15
- package/dist/schema-generator/schema-generator.d.ts.map +0 -1
- package/src/adapters/drizzle/drizzle-adapter.ts +0 -39
- package/src/adapters/kysely/kysely-adapter.ts +0 -27
- package/src/adapters/shared/table-name-mapper.ts +0 -50
- package/src/schema-generator/schema-generator.ts +0 -12
package/src/schema/create.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
+
|
|
1
3
|
import { createId } from "../id";
|
|
4
|
+
import type { DbNow } from "../query/db-now";
|
|
5
|
+
import type { Prettify } from "../util/types";
|
|
6
|
+
import { createTableStandardSchemaProps, createTableValidator } from "./validator";
|
|
2
7
|
|
|
3
8
|
export { generateId } from "./generate-id";
|
|
9
|
+
export { FragnoDbValidationError } from "./validator";
|
|
4
10
|
|
|
5
11
|
export type AnySchema = Schema<Record<string, AnyTable>>;
|
|
6
12
|
|
|
@@ -20,6 +26,16 @@ export type AnyColumn =
|
|
|
20
26
|
export type TableSubOperation =
|
|
21
27
|
| { type: "add-column"; columnName: string; column: AnyColumn }
|
|
22
28
|
| { type: "add-index"; name: string; columns: string[]; unique: boolean }
|
|
29
|
+
| { type: "rename-column"; from: string; to: string }
|
|
30
|
+
| { type: "drop-column"; name: string }
|
|
31
|
+
| {
|
|
32
|
+
type: "update-column";
|
|
33
|
+
columnName: string;
|
|
34
|
+
column: AnyColumn;
|
|
35
|
+
updateNullable: boolean;
|
|
36
|
+
updateDefault: boolean;
|
|
37
|
+
updateDataType: boolean;
|
|
38
|
+
}
|
|
23
39
|
| {
|
|
24
40
|
type: "add-foreign-key";
|
|
25
41
|
name: string;
|
|
@@ -51,6 +67,7 @@ export type SchemaOperation =
|
|
|
51
67
|
type: "one" | "many";
|
|
52
68
|
from: { table: string; column: string };
|
|
53
69
|
to: { table: string; column: string };
|
|
70
|
+
foreignKey?: boolean;
|
|
54
71
|
};
|
|
55
72
|
};
|
|
56
73
|
|
|
@@ -72,11 +89,18 @@ class RelationInit<
|
|
|
72
89
|
referencedTable: TTables[TTableName];
|
|
73
90
|
referencer: AnyTable;
|
|
74
91
|
on: [string, string][] = [];
|
|
92
|
+
foreignKey: boolean;
|
|
75
93
|
|
|
76
|
-
constructor(
|
|
94
|
+
constructor(
|
|
95
|
+
type: TRelationType,
|
|
96
|
+
referencedTable: TTables[TTableName],
|
|
97
|
+
referencer: AnyTable,
|
|
98
|
+
options?: { foreignKey?: boolean },
|
|
99
|
+
) {
|
|
77
100
|
this.type = type;
|
|
78
101
|
this.referencedTable = referencedTable;
|
|
79
102
|
this.referencer = referencer;
|
|
103
|
+
this.foreignKey = options?.foreignKey ?? true;
|
|
80
104
|
}
|
|
81
105
|
}
|
|
82
106
|
|
|
@@ -95,16 +119,17 @@ export class ExplicitRelationInit<
|
|
|
95
119
|
TTables extends Record<string, AnyTable>,
|
|
96
120
|
TTableName extends keyof TTables,
|
|
97
121
|
> extends RelationInit<TRelationType, TTables, TTableName> {
|
|
98
|
-
init(
|
|
99
|
-
const id = `${this.referencer.
|
|
122
|
+
init(name: string): Relation<TRelationType, TTables[TTableName]> {
|
|
123
|
+
const id = `${this.referencer.name}_${this.referencedTable.name}`;
|
|
100
124
|
|
|
101
125
|
return {
|
|
102
126
|
id,
|
|
103
127
|
on: this.on,
|
|
104
|
-
name
|
|
128
|
+
name,
|
|
105
129
|
referencer: this.referencer,
|
|
106
130
|
table: this.referencedTable,
|
|
107
131
|
type: this.type,
|
|
132
|
+
foreignKey: this.foreignKey,
|
|
108
133
|
};
|
|
109
134
|
}
|
|
110
135
|
}
|
|
@@ -116,6 +141,7 @@ export interface Relation<
|
|
|
116
141
|
id: string;
|
|
117
142
|
name: string;
|
|
118
143
|
type: TRelationType;
|
|
144
|
+
foreignKey?: boolean;
|
|
119
145
|
|
|
120
146
|
table: TTable;
|
|
121
147
|
referencer: AnyTable;
|
|
@@ -123,18 +149,57 @@ export interface Relation<
|
|
|
123
149
|
on: [string, string][];
|
|
124
150
|
}
|
|
125
151
|
|
|
152
|
+
type PickNullable<T> = {
|
|
153
|
+
[P in keyof T as null extends T[P] ? P : never]: T[P];
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
type PickNotNullable<T> = {
|
|
157
|
+
[P in keyof T as null extends T[P] ? never : P]: T[P];
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
type RawInsertValuesFromColumns<TColumns extends Record<string, AnyColumn>> = {
|
|
161
|
+
[K in keyof TColumns as string extends K ? never : K]: TColumns[K]["$in"];
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
type TableInsertValuesFromColumns<TColumns extends Record<string, AnyColumn>> = Prettify<
|
|
165
|
+
Partial<PickNullable<RawInsertValuesFromColumns<TColumns>>> &
|
|
166
|
+
PickNotNullable<RawInsertValuesFromColumns<TColumns>>
|
|
167
|
+
>;
|
|
168
|
+
|
|
169
|
+
export type TableInsertValues<T extends AnyTable> = TableInsertValuesFromColumns<T["columns"]>;
|
|
170
|
+
|
|
171
|
+
export type TableUnknownKeysMode = "strip" | "strict";
|
|
172
|
+
|
|
173
|
+
export type TableValidationOptions = {
|
|
174
|
+
unknownKeys?: TableUnknownKeysMode;
|
|
175
|
+
};
|
|
176
|
+
|
|
126
177
|
export interface Table<
|
|
127
178
|
TColumns extends Record<string, AnyColumn> = Record<string, AnyColumn>,
|
|
128
179
|
TRelations extends Record<string, AnyRelation> = Record<string, AnyRelation>,
|
|
129
180
|
TIndexes extends Record<string, Index> = Record<string, Index>,
|
|
130
181
|
> {
|
|
182
|
+
/**
|
|
183
|
+
* Standard Schema-compatible validator for insert values.
|
|
184
|
+
*/
|
|
185
|
+
"~standard": StandardSchemaV1.Props<
|
|
186
|
+
TableInsertValuesFromColumns<TColumns>,
|
|
187
|
+
TableInsertValuesFromColumns<TColumns>
|
|
188
|
+
>;
|
|
131
189
|
name: string;
|
|
132
|
-
ormName: string;
|
|
133
190
|
|
|
134
191
|
columns: TColumns;
|
|
135
192
|
relations: TRelations;
|
|
136
193
|
indexes: TIndexes;
|
|
137
194
|
|
|
195
|
+
/**
|
|
196
|
+
* Validate insert values at runtime.
|
|
197
|
+
*/
|
|
198
|
+
validate: (
|
|
199
|
+
value: unknown,
|
|
200
|
+
options?: TableValidationOptions,
|
|
201
|
+
) => TableInsertValuesFromColumns<TColumns>;
|
|
202
|
+
|
|
138
203
|
/**
|
|
139
204
|
* Get column by name
|
|
140
205
|
*/
|
|
@@ -203,7 +268,6 @@ export type TypeMap = {
|
|
|
203
268
|
export class Column<TType extends keyof TypeMap, TIn = unknown, TOut = unknown> {
|
|
204
269
|
type: TType;
|
|
205
270
|
name: string = "";
|
|
206
|
-
ormName: string = "";
|
|
207
271
|
isNullable: boolean = false;
|
|
208
272
|
role: "external-id" | "internal-id" | "version" | "reference" | "regular" = "regular";
|
|
209
273
|
isHidden: boolean = false;
|
|
@@ -421,9 +485,36 @@ export class VersionColumn<TIn = unknown, TOut = unknown> extends Column<"intege
|
|
|
421
485
|
}
|
|
422
486
|
}
|
|
423
487
|
|
|
488
|
+
function cloneColumn<TColumn extends AnyColumn>(col: TColumn): TColumn {
|
|
489
|
+
let clonedCol: AnyColumn;
|
|
490
|
+
|
|
491
|
+
if (col instanceof InternalIdColumn) {
|
|
492
|
+
clonedCol = new InternalIdColumn();
|
|
493
|
+
} else if (col instanceof VersionColumn) {
|
|
494
|
+
clonedCol = new VersionColumn();
|
|
495
|
+
} else if (col instanceof IdColumn) {
|
|
496
|
+
clonedCol = new IdColumn(col.type);
|
|
497
|
+
} else {
|
|
498
|
+
clonedCol = new Column(col.type);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
clonedCol.name = col.name;
|
|
502
|
+
clonedCol.isNullable = col.isNullable;
|
|
503
|
+
clonedCol.role = col.role;
|
|
504
|
+
clonedCol.isHidden = col.isHidden;
|
|
505
|
+
clonedCol.default = col.default;
|
|
506
|
+
clonedCol.tableName = col.tableName;
|
|
507
|
+
|
|
508
|
+
return clonedCol as TColumn;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
type ColumnInput<TType extends keyof TypeMap> =
|
|
512
|
+
| TypeMap[TType]
|
|
513
|
+
| (TType extends "timestamp" | "date" ? DbNow : never);
|
|
514
|
+
|
|
424
515
|
export function column<TType extends keyof TypeMap>(
|
|
425
516
|
type: TType,
|
|
426
|
-
): Column<TType,
|
|
517
|
+
): Column<TType, ColumnInput<TType>, TypeMap[TType]> {
|
|
427
518
|
return new Column(type);
|
|
428
519
|
}
|
|
429
520
|
|
|
@@ -449,8 +540,8 @@ export function referenceColumn(): Column<
|
|
|
449
540
|
* This is a CUID string that can be auto-generated or user-provided.
|
|
450
541
|
* Input accepts string | FragnoId | null, output returns FragnoId.
|
|
451
542
|
*/
|
|
452
|
-
export function idColumn(): IdColumn<"varchar(
|
|
453
|
-
const col = new IdColumn<"varchar(
|
|
543
|
+
export function idColumn(): IdColumn<"varchar(128)", string | FragnoId | null, FragnoId> {
|
|
544
|
+
const col = new IdColumn<"varchar(128)", string | FragnoId | null, FragnoId>("varchar(128)");
|
|
454
545
|
col.role = "external-id";
|
|
455
546
|
col.defaultTo$((b) => b.cuid());
|
|
456
547
|
return col;
|
|
@@ -579,6 +670,8 @@ export class FragnoReference {
|
|
|
579
670
|
}
|
|
580
671
|
}
|
|
581
672
|
|
|
673
|
+
const validationClasses = { FragnoId, FragnoReference };
|
|
674
|
+
|
|
582
675
|
type RelationType = "one" | "many";
|
|
583
676
|
|
|
584
677
|
export class TableBuilder<
|
|
@@ -590,7 +683,6 @@ export class TableBuilder<
|
|
|
590
683
|
#columns: TColumns;
|
|
591
684
|
#relations: TRelations;
|
|
592
685
|
#indexes: TIndexes;
|
|
593
|
-
#ormName: string = "";
|
|
594
686
|
#columnOrder: string[] = [];
|
|
595
687
|
|
|
596
688
|
constructor(name: string) {
|
|
@@ -626,7 +718,7 @@ export class TableBuilder<
|
|
|
626
718
|
* Add a column to the table.
|
|
627
719
|
*/
|
|
628
720
|
addColumn<TColumnName extends string, TColumn extends AnyColumn>(
|
|
629
|
-
|
|
721
|
+
name: TColumnName,
|
|
630
722
|
col: TColumn,
|
|
631
723
|
): TableBuilder<TColumns & Record<TColumnName, TColumn>, TRelations, TIndexes>;
|
|
632
724
|
|
|
@@ -634,28 +726,27 @@ export class TableBuilder<
|
|
|
634
726
|
* Add a column to the table with simplified syntax.
|
|
635
727
|
*/
|
|
636
728
|
addColumn<TColumnName extends string, TType extends keyof TypeMap>(
|
|
637
|
-
|
|
729
|
+
name: TColumnName,
|
|
638
730
|
type: TType,
|
|
639
731
|
): TableBuilder<
|
|
640
|
-
TColumns & Record<TColumnName, Column<TType,
|
|
732
|
+
TColumns & Record<TColumnName, Column<TType, ColumnInput<TType>, TypeMap[TType]>>,
|
|
641
733
|
TRelations,
|
|
642
734
|
TIndexes
|
|
643
735
|
>;
|
|
644
736
|
|
|
645
737
|
addColumn<TColumnName extends string, TColumn extends AnyColumn, TType extends keyof TypeMap>(
|
|
646
|
-
|
|
738
|
+
name: TColumnName,
|
|
647
739
|
colOrType: TColumn | TType,
|
|
648
740
|
): TableBuilder<TColumns & Record<TColumnName, TColumn>, TRelations, TIndexes> {
|
|
649
741
|
// Create the column if a type string was provided
|
|
650
742
|
const col = typeof colOrType === "string" ? column(colOrType) : colOrType;
|
|
651
743
|
|
|
652
744
|
// Set column metadata
|
|
653
|
-
col.
|
|
654
|
-
col.name = ormName;
|
|
745
|
+
col.name = name;
|
|
655
746
|
|
|
656
747
|
// Add column directly to this builder
|
|
657
|
-
this.#columns[
|
|
658
|
-
this.#columnOrder.push(
|
|
748
|
+
this.#columns[name] = col as unknown as TColumns[TColumnName];
|
|
749
|
+
this.#columnOrder.push(name);
|
|
659
750
|
|
|
660
751
|
return this as unknown as TableBuilder<
|
|
661
752
|
TColumns & Record<TColumnName, TColumn>,
|
|
@@ -664,6 +755,32 @@ export class TableBuilder<
|
|
|
664
755
|
>;
|
|
665
756
|
}
|
|
666
757
|
|
|
758
|
+
/**
|
|
759
|
+
* Alter an existing column.
|
|
760
|
+
*/
|
|
761
|
+
alterColumn<TColumnName extends NonIdColumnName<TColumns>>(
|
|
762
|
+
name: TColumnName,
|
|
763
|
+
): ColumnAlterer<TColumns, TRelations, TIndexes, TColumnName> {
|
|
764
|
+
return {
|
|
765
|
+
nullable: <TNullable extends boolean = true>(nullable?: TNullable) => {
|
|
766
|
+
const column = this.#columns[name];
|
|
767
|
+
if (!column) {
|
|
768
|
+
throw new Error(`Unknown column name ${String(name)}`);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
const cloned = cloneColumn(column) as Column<keyof TypeMap>;
|
|
772
|
+
const updated = cloned.nullable(nullable ?? true);
|
|
773
|
+
this.#columns[name] = updated as unknown as TColumns[TColumnName];
|
|
774
|
+
|
|
775
|
+
return this as unknown as TableBuilder<
|
|
776
|
+
UpdateColumn<TColumns, TColumnName, NullableColumn<TColumns[TColumnName], TNullable>>,
|
|
777
|
+
TRelations,
|
|
778
|
+
TIndexes
|
|
779
|
+
>;
|
|
780
|
+
},
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
|
|
667
784
|
/**
|
|
668
785
|
* Create an index on the specified columns.
|
|
669
786
|
*/
|
|
@@ -716,7 +833,6 @@ export class TableBuilder<
|
|
|
716
833
|
// Auto-add _internalId and _version columns if not already present
|
|
717
834
|
if (!this.#columns["_internalId"]) {
|
|
718
835
|
const col = internalIdColumn();
|
|
719
|
-
col.ormName = "_internalId";
|
|
720
836
|
col.name = "_internalId";
|
|
721
837
|
// Safe: we're adding system columns to the internal columns object
|
|
722
838
|
(this.#columns as Record<string, AnyColumn>)["_internalId"] = col;
|
|
@@ -724,18 +840,13 @@ export class TableBuilder<
|
|
|
724
840
|
|
|
725
841
|
if (!this.#columns["_version"]) {
|
|
726
842
|
const col = versionColumn();
|
|
727
|
-
col.ormName = "_version";
|
|
728
843
|
col.name = "_version";
|
|
729
844
|
// Safe: we're adding system columns to the internal columns object
|
|
730
845
|
(this.#columns as Record<string, AnyColumn>)["_version"] = col;
|
|
731
846
|
}
|
|
732
847
|
|
|
733
|
-
|
|
734
|
-
const ormName = this.#ormName || this.#name;
|
|
735
|
-
|
|
736
|
-
const table: Table<TColumns, TRelations, TIndexes> = {
|
|
848
|
+
const table = {
|
|
737
849
|
name: this.#name,
|
|
738
|
-
ormName,
|
|
739
850
|
columns: this.#columns,
|
|
740
851
|
relations: this.#relations,
|
|
741
852
|
indexes: this.#indexes,
|
|
@@ -751,7 +862,10 @@ export class TableBuilder<
|
|
|
751
862
|
getVersionColumn: () => {
|
|
752
863
|
return versionCol!;
|
|
753
864
|
},
|
|
754
|
-
}
|
|
865
|
+
} as Table<TColumns, TRelations, TIndexes>;
|
|
866
|
+
|
|
867
|
+
table["~standard"] = createTableStandardSchemaProps(table, validationClasses);
|
|
868
|
+
table.validate = createTableValidator(table, validationClasses);
|
|
755
869
|
|
|
756
870
|
// Set table reference and find special columns
|
|
757
871
|
for (const k in this.#columns) {
|
|
@@ -787,6 +901,10 @@ export class TableBuilder<
|
|
|
787
901
|
}
|
|
788
902
|
|
|
789
903
|
export interface Schema<TTables extends Record<string, AnyTable> = Record<string, AnyTable>> {
|
|
904
|
+
/**
|
|
905
|
+
* @description The name of the schema (required).
|
|
906
|
+
*/
|
|
907
|
+
name: string;
|
|
790
908
|
/**
|
|
791
909
|
* @description The version of the schema, automatically incremented on each change.
|
|
792
910
|
*/
|
|
@@ -850,12 +968,55 @@ type ColumnsToTuple<
|
|
|
850
968
|
: never;
|
|
851
969
|
} & AnyColumn[];
|
|
852
970
|
|
|
971
|
+
type UpdateColumn<
|
|
972
|
+
TColumns extends Record<string, AnyColumn>,
|
|
973
|
+
TColumnName extends keyof TColumns,
|
|
974
|
+
TUpdatedColumn extends AnyColumn,
|
|
975
|
+
> = Prettify<Omit<TColumns, TColumnName> & Record<TColumnName, TUpdatedColumn>>;
|
|
976
|
+
|
|
977
|
+
type NonIdColumnName<TColumns extends Record<string, AnyColumn>> = {
|
|
978
|
+
[K in keyof TColumns]: TColumns[K] extends
|
|
979
|
+
| IdColumn<IdColumnType, unknown, unknown>
|
|
980
|
+
| InternalIdColumn<unknown, unknown>
|
|
981
|
+
| VersionColumn<unknown, unknown>
|
|
982
|
+
? never
|
|
983
|
+
: K;
|
|
984
|
+
}[keyof TColumns];
|
|
985
|
+
|
|
986
|
+
type NullableColumn<TColumn extends AnyColumn, TNullable extends boolean> =
|
|
987
|
+
TColumn extends Column<infer TType, infer TIn, infer TOut>
|
|
988
|
+
? Column<
|
|
989
|
+
TType,
|
|
990
|
+
TNullable extends true ? TIn | null : Exclude<TIn, null>,
|
|
991
|
+
TNullable extends true ? TOut | null : Exclude<TOut, null>
|
|
992
|
+
>
|
|
993
|
+
: TColumn;
|
|
994
|
+
|
|
995
|
+
type ColumnAlterer<
|
|
996
|
+
TColumns extends Record<string, AnyColumn>,
|
|
997
|
+
TRelations extends Record<string, AnyRelation>,
|
|
998
|
+
TIndexes extends Record<string, Index>,
|
|
999
|
+
TColumnName extends keyof TColumns,
|
|
1000
|
+
> = {
|
|
1001
|
+
nullable<TNullable extends boolean = true>(
|
|
1002
|
+
nullable?: TNullable,
|
|
1003
|
+
): TableBuilder<
|
|
1004
|
+
UpdateColumn<TColumns, TColumnName, NullableColumn<TColumns[TColumnName], TNullable>>,
|
|
1005
|
+
TRelations,
|
|
1006
|
+
TIndexes
|
|
1007
|
+
>;
|
|
1008
|
+
};
|
|
1009
|
+
|
|
853
1010
|
export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
1011
|
+
#name: string;
|
|
854
1012
|
#tables: TTables;
|
|
855
1013
|
#version: number = 0;
|
|
856
1014
|
#operations: SchemaOperation[] = [];
|
|
1015
|
+
#tableNames: Set<string> = new Set();
|
|
1016
|
+
#indexNames: Set<string> = new Set();
|
|
857
1017
|
|
|
858
|
-
constructor(existingSchema?: Schema<TTables>) {
|
|
1018
|
+
constructor(name: string, existingSchema?: Schema<TTables>) {
|
|
1019
|
+
this.#name = name;
|
|
859
1020
|
if (existingSchema) {
|
|
860
1021
|
this.#tables = existingSchema.tables;
|
|
861
1022
|
this.#version = existingSchema.version;
|
|
@@ -863,6 +1024,54 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
863
1024
|
} else {
|
|
864
1025
|
this.#tables = {} as TTables;
|
|
865
1026
|
}
|
|
1027
|
+
|
|
1028
|
+
for (const table of Object.values(this.#tables)) {
|
|
1029
|
+
this.#registerTableName(table.name);
|
|
1030
|
+
for (const index of Object.values(table.indexes)) {
|
|
1031
|
+
this.#registerIndexName(index.name, table.name);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
#registerTableName(name: string): void {
|
|
1037
|
+
if (this.#tableNames.has(name)) {
|
|
1038
|
+
throw new Error(`Duplicate table name "${name}" in schema "${this.#name}".`);
|
|
1039
|
+
}
|
|
1040
|
+
this.#tableNames.add(name);
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
#registerIndexName(name: string, tableName: string): void {
|
|
1044
|
+
if (this.#indexNames.has(name)) {
|
|
1045
|
+
throw new Error(
|
|
1046
|
+
`Duplicate index name "${name}" in schema "${this.#name}". Index names must be unique across tables (conflict on "${tableName}").`,
|
|
1047
|
+
);
|
|
1048
|
+
}
|
|
1049
|
+
this.#indexNames.add(name);
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
#rebindRelations(tableName: string, newTable: AnyTable): void {
|
|
1053
|
+
for (const table of Object.values(this.#tables)) {
|
|
1054
|
+
for (const relation of Object.values(table.relations)) {
|
|
1055
|
+
if (relation.table.name === tableName) {
|
|
1056
|
+
relation.table = newTable;
|
|
1057
|
+
}
|
|
1058
|
+
if (relation.referencer.name === tableName) {
|
|
1059
|
+
relation.referencer = newTable;
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
#isJoinColumnIndexed(table: AnyTable, columnName: string): boolean {
|
|
1066
|
+
const idColumnName = table.getIdColumn().name;
|
|
1067
|
+
const internalIdColumnName = table.getInternalIdColumn().name;
|
|
1068
|
+
if (columnName === idColumnName || columnName === internalIdColumnName) {
|
|
1069
|
+
return true;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
return Object.values(table.indexes).some((index) =>
|
|
1073
|
+
index.columnNames.some((name) => name === columnName),
|
|
1074
|
+
);
|
|
866
1075
|
}
|
|
867
1076
|
|
|
868
1077
|
/**
|
|
@@ -871,7 +1080,7 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
871
1080
|
*
|
|
872
1081
|
* @example
|
|
873
1082
|
* ```ts
|
|
874
|
-
* const builder = new SchemaBuilder()
|
|
1083
|
+
* const builder = new SchemaBuilder("combined")
|
|
875
1084
|
* .add(userSchema)
|
|
876
1085
|
* .add(postSchema)
|
|
877
1086
|
* .addTable("comments", ...);
|
|
@@ -880,10 +1089,32 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
880
1089
|
mergeWithExistingSchema<TNewTables extends Record<string, AnyTable>>(
|
|
881
1090
|
schema: Schema<TNewTables>,
|
|
882
1091
|
): SchemaBuilder<TTables & TNewTables> {
|
|
1092
|
+
for (const table of Object.values(schema.tables)) {
|
|
1093
|
+
if (this.#tableNames.has(table.name)) {
|
|
1094
|
+
throw new Error(
|
|
1095
|
+
`Duplicate table name "${table.name}" in schema "${this.#name}" when merging.`,
|
|
1096
|
+
);
|
|
1097
|
+
}
|
|
1098
|
+
for (const index of Object.values(table.indexes)) {
|
|
1099
|
+
if (this.#indexNames.has(index.name)) {
|
|
1100
|
+
throw new Error(
|
|
1101
|
+
`Duplicate index name "${index.name}" in schema "${this.#name}" when merging (conflict on "${table.name}").`,
|
|
1102
|
+
);
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
|
|
883
1107
|
this.#tables = { ...this.#tables, ...schema.tables } as TTables & TNewTables;
|
|
884
1108
|
this.#operations = [...this.#operations, ...schema.operations];
|
|
885
1109
|
this.#version += schema.version;
|
|
886
1110
|
|
|
1111
|
+
for (const table of Object.values(schema.tables)) {
|
|
1112
|
+
this.#tableNames.add(table.name);
|
|
1113
|
+
for (const index of Object.values(table.indexes)) {
|
|
1114
|
+
this.#indexNames.add(index.name);
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
|
|
887
1118
|
return this as unknown as SchemaBuilder<TTables & TNewTables>;
|
|
888
1119
|
}
|
|
889
1120
|
|
|
@@ -896,21 +1127,31 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
896
1127
|
TRelations extends Record<string, AnyRelation>,
|
|
897
1128
|
TIndexes extends Record<string, Index> = Record<string, Index>,
|
|
898
1129
|
>(
|
|
899
|
-
|
|
1130
|
+
name: TTableName,
|
|
900
1131
|
callback: (
|
|
901
|
-
builder: TableBuilder<
|
|
902
|
-
Record<string, AnyColumn>,
|
|
903
|
-
Record<string, AnyRelation>,
|
|
904
|
-
Record<string, Index>
|
|
905
|
-
>,
|
|
1132
|
+
builder: TableBuilder<{}, Record<string, AnyRelation>, Record<string, Index>>,
|
|
906
1133
|
) => TableBuilder<TColumns, TRelations, TIndexes>,
|
|
907
1134
|
): SchemaBuilder<TTables & Record<TTableName, Table<TColumns, TRelations, TIndexes>>> {
|
|
908
1135
|
this.#version++;
|
|
909
1136
|
|
|
910
|
-
|
|
1137
|
+
if (this.#tableNames.has(name)) {
|
|
1138
|
+
throw new Error(`Duplicate table name "${name}" in schema "${this.#name}".`);
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
const tableBuilder = new TableBuilder<{}, Record<string, AnyRelation>, Record<string, Index>>(
|
|
1142
|
+
name,
|
|
1143
|
+
);
|
|
911
1144
|
const result = callback(tableBuilder);
|
|
912
1145
|
const builtTable = result.build();
|
|
913
|
-
|
|
1146
|
+
const indexNames = result.getIndexes().map((idx) => idx.name);
|
|
1147
|
+
|
|
1148
|
+
for (const indexName of indexNames) {
|
|
1149
|
+
if (this.#indexNames.has(indexName)) {
|
|
1150
|
+
throw new Error(
|
|
1151
|
+
`Duplicate index name "${indexName}" in schema "${this.#name}". Index names must be unique across tables (conflict on "${name}").`,
|
|
1152
|
+
);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
914
1155
|
|
|
915
1156
|
// Collect sub-operations in order
|
|
916
1157
|
const subOperations: TableSubOperation[] = [];
|
|
@@ -922,7 +1163,7 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
922
1163
|
subOperations.push({
|
|
923
1164
|
type: "add-column",
|
|
924
1165
|
columnName: colName,
|
|
925
|
-
column: col,
|
|
1166
|
+
column: cloneColumn(col),
|
|
926
1167
|
});
|
|
927
1168
|
}
|
|
928
1169
|
|
|
@@ -931,14 +1172,14 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
931
1172
|
subOperations.push({
|
|
932
1173
|
type: "add-column",
|
|
933
1174
|
columnName: "_internalId",
|
|
934
|
-
column: builtTable.columns["_internalId"],
|
|
1175
|
+
column: cloneColumn(builtTable.columns["_internalId"]),
|
|
935
1176
|
});
|
|
936
1177
|
}
|
|
937
1178
|
if (builtTable.columns["_version"]) {
|
|
938
1179
|
subOperations.push({
|
|
939
1180
|
type: "add-column",
|
|
940
1181
|
columnName: "_version",
|
|
941
|
-
column: builtTable.columns["_version"],
|
|
1182
|
+
column: cloneColumn(builtTable.columns["_version"]),
|
|
942
1183
|
});
|
|
943
1184
|
}
|
|
944
1185
|
|
|
@@ -947,7 +1188,7 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
947
1188
|
subOperations.push({
|
|
948
1189
|
type: "add-index",
|
|
949
1190
|
name: idx.name,
|
|
950
|
-
columns: idx.columns.map((c) => c.
|
|
1191
|
+
columns: idx.columns.map((c) => c.name),
|
|
951
1192
|
unique: idx.unique,
|
|
952
1193
|
});
|
|
953
1194
|
}
|
|
@@ -955,13 +1196,17 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
955
1196
|
// Add the add-table operation
|
|
956
1197
|
this.#operations.push({
|
|
957
1198
|
type: "add-table",
|
|
958
|
-
tableName:
|
|
1199
|
+
tableName: name,
|
|
959
1200
|
operations: subOperations,
|
|
960
1201
|
});
|
|
961
1202
|
|
|
962
1203
|
// Update tables map
|
|
963
|
-
this.#tables = { ...this.#tables, [
|
|
1204
|
+
this.#tables = { ...this.#tables, [name]: builtTable } as TTables &
|
|
964
1205
|
Record<TTableName, Table<TColumns, TRelations, TIndexes>>;
|
|
1206
|
+
this.#tableNames.add(name);
|
|
1207
|
+
for (const indexName of indexNames) {
|
|
1208
|
+
this.#indexNames.add(indexName);
|
|
1209
|
+
}
|
|
965
1210
|
|
|
966
1211
|
return this as unknown as SchemaBuilder<
|
|
967
1212
|
TTables & Record<TTableName, Table<TColumns, TRelations, TIndexes>>
|
|
@@ -977,7 +1222,7 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
977
1222
|
* @example
|
|
978
1223
|
* ```ts
|
|
979
1224
|
* // One-to-one or many-to-one: post -> user
|
|
980
|
-
* schema(s => s
|
|
1225
|
+
* schema("blog", s => s
|
|
981
1226
|
* .addTable("users", t => t.addColumn("id", idColumn()))
|
|
982
1227
|
* .addTable("posts", t => t
|
|
983
1228
|
* .addColumn("id", idColumn())
|
|
@@ -1002,6 +1247,14 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1002
1247
|
* from: { table: "users", column: "invitedBy" },
|
|
1003
1248
|
* to: { table: "users", column: "id" },
|
|
1004
1249
|
* })
|
|
1250
|
+
*
|
|
1251
|
+
* // Join-only relation (no foreign key)
|
|
1252
|
+
* .addReference("invitedUser", {
|
|
1253
|
+
* type: "one",
|
|
1254
|
+
* from: { table: "invitations", column: "email" },
|
|
1255
|
+
* to: { table: "users", column: "email" },
|
|
1256
|
+
* foreignKey: false,
|
|
1257
|
+
* })
|
|
1005
1258
|
* ```
|
|
1006
1259
|
*/
|
|
1007
1260
|
addReference<
|
|
@@ -1021,6 +1274,12 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1021
1274
|
table: TToTableName;
|
|
1022
1275
|
column: keyof TTables[TToTableName]["columns"];
|
|
1023
1276
|
};
|
|
1277
|
+
/**
|
|
1278
|
+
* When false, defines a join-only relation without foreign key migrations.
|
|
1279
|
+
* References to external-id columns still coerce to `_internalId`
|
|
1280
|
+
* (including left-side external IDs for join-only).
|
|
1281
|
+
*/
|
|
1282
|
+
foreignKey?: boolean;
|
|
1024
1283
|
},
|
|
1025
1284
|
): SchemaBuilder<
|
|
1026
1285
|
UpdateTableRelations<TTables, TFromTableName, TReferenceName, TToTableName, TRelationType>
|
|
@@ -1030,6 +1289,10 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1030
1289
|
const table = this.#tables[config.from.table];
|
|
1031
1290
|
const referencedTable = this.#tables[config.to.table];
|
|
1032
1291
|
|
|
1292
|
+
if (!referenceName || referenceName.trim().length === 0) {
|
|
1293
|
+
throw new Error(`referenceName is required for addReference on ${config.from.table}`);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1033
1296
|
if (!table) {
|
|
1034
1297
|
throw new Error(`Table ${config.from.table} not found in schema`);
|
|
1035
1298
|
}
|
|
@@ -1039,21 +1302,33 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1039
1302
|
|
|
1040
1303
|
const columnName = config.from.column as string;
|
|
1041
1304
|
const targetColumnName = config.to.column as string;
|
|
1042
|
-
|
|
1043
|
-
// Foreign keys always reference internal IDs, not external IDs
|
|
1044
|
-
// If user specifies "id", translate to "_internalId" for the actual FK
|
|
1045
|
-
const actualTargetColumnName = targetColumnName === "id" ? "_internalId" : targetColumnName;
|
|
1305
|
+
const foreignKey = config.foreignKey !== false;
|
|
1046
1306
|
|
|
1047
1307
|
const column = table.columns[columnName];
|
|
1048
|
-
const
|
|
1308
|
+
const targetColumn = referencedTable.columns[targetColumnName];
|
|
1049
1309
|
|
|
1050
1310
|
if (!column) {
|
|
1051
1311
|
throw new Error(`Column ${columnName} not found in table ${config.from.table}`);
|
|
1052
1312
|
}
|
|
1313
|
+
if (!targetColumn) {
|
|
1314
|
+
throw new Error(`Column ${targetColumnName} not found in table ${config.to.table}`);
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
// External-id columns always target the internal ID column.
|
|
1318
|
+
const actualTargetColumnName =
|
|
1319
|
+
targetColumn.role === "external-id"
|
|
1320
|
+
? referencedTable.getInternalIdColumn().name
|
|
1321
|
+
: targetColumnName;
|
|
1322
|
+
|
|
1323
|
+
const referencedColumn = referencedTable.columns[actualTargetColumnName];
|
|
1053
1324
|
if (!referencedColumn) {
|
|
1054
1325
|
throw new Error(`Column ${actualTargetColumnName} not found in table ${config.to.table}`);
|
|
1055
1326
|
}
|
|
1056
1327
|
|
|
1328
|
+
if (table.relations[referenceName]) {
|
|
1329
|
+
throw new Error(`Reference ${referenceName} already exists on table ${config.from.table}`);
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1057
1332
|
// Verify that reference columns are bigint (matching internal ID type)
|
|
1058
1333
|
if (column.role === "reference" && column.type !== "bigint") {
|
|
1059
1334
|
throw new Error(
|
|
@@ -1061,9 +1336,28 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1061
1336
|
);
|
|
1062
1337
|
}
|
|
1063
1338
|
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1339
|
+
if (!foreignKey) {
|
|
1340
|
+
const missingIndexes: string[] = [];
|
|
1341
|
+
if (!this.#isJoinColumnIndexed(table, columnName)) {
|
|
1342
|
+
missingIndexes.push(`${table.name}.${columnName}`);
|
|
1343
|
+
}
|
|
1344
|
+
if (!this.#isJoinColumnIndexed(referencedTable, actualTargetColumnName)) {
|
|
1345
|
+
missingIndexes.push(`${referencedTable.name}.${actualTargetColumnName}`);
|
|
1346
|
+
}
|
|
1347
|
+
if (missingIndexes.length > 0) {
|
|
1348
|
+
throw new Error(
|
|
1349
|
+
`Join-only relation "${referenceName}" requires indexed join columns: ${missingIndexes.join(", ")}.`,
|
|
1350
|
+
);
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
// Join-only relations treat external IDs as internal IDs on the left side.
|
|
1355
|
+
const actualFromColumnName =
|
|
1356
|
+
!foreignKey && column.role === "external-id" ? table.getInternalIdColumn().name : columnName;
|
|
1357
|
+
|
|
1358
|
+
// Create the relation (use user-facing right-side column name)
|
|
1359
|
+
const init = new ExplicitRelationInit(config.type, referencedTable, table, { foreignKey });
|
|
1360
|
+
init.on.push([actualFromColumnName, targetColumnName]);
|
|
1067
1361
|
const relation = init.init(referenceName);
|
|
1068
1362
|
|
|
1069
1363
|
// Add relation to the table
|
|
@@ -1076,8 +1370,9 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1076
1370
|
referenceName,
|
|
1077
1371
|
config: {
|
|
1078
1372
|
type: config.type,
|
|
1079
|
-
from: { table: config.from.table, column:
|
|
1373
|
+
from: { table: config.from.table, column: actualFromColumnName },
|
|
1080
1374
|
to: { table: config.to.table, column: actualTargetColumnName },
|
|
1375
|
+
foreignKey,
|
|
1081
1376
|
},
|
|
1082
1377
|
});
|
|
1083
1378
|
|
|
@@ -1089,8 +1384,8 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1089
1384
|
}
|
|
1090
1385
|
|
|
1091
1386
|
/**
|
|
1092
|
-
* Alter an existing table by adding columns or indexes.
|
|
1093
|
-
* This is used for
|
|
1387
|
+
* Alter an existing table by adding columns, altering columns, or adding indexes.
|
|
1388
|
+
* This is used for forward-only schema modifications.
|
|
1094
1389
|
*
|
|
1095
1390
|
* @param tableName - The name of the table to modify
|
|
1096
1391
|
* @param callback - A callback that receives a table builder for adding columns/indexes
|
|
@@ -1098,11 +1393,12 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1098
1393
|
* @example
|
|
1099
1394
|
* ```ts
|
|
1100
1395
|
* // Add a new column to an existing table
|
|
1101
|
-
* schema(s => s
|
|
1396
|
+
* schema("blog", s => s
|
|
1102
1397
|
* .addTable("users", t => t
|
|
1103
1398
|
* .addColumn("id", idColumn())
|
|
1104
1399
|
* .addColumn("name", column("string")))
|
|
1105
1400
|
* .alterTable("users", t => t
|
|
1401
|
+
* .alterColumn("name").nullable()
|
|
1106
1402
|
* .addColumn("email", column("string"))
|
|
1107
1403
|
* .addColumn("age", column("integer").nullable())
|
|
1108
1404
|
* .createIndex("idx_email", ["email"]))
|
|
@@ -1139,6 +1435,10 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1139
1435
|
// Track existing columns and indexes
|
|
1140
1436
|
const existingColumns = new Set(Object.keys(table.columns));
|
|
1141
1437
|
const existingIndexes = new Set(Object.keys(table.indexes));
|
|
1438
|
+
const existingColumnState = new Map<string, { isNullable: boolean }>();
|
|
1439
|
+
for (const [colName, col] of Object.entries(table.columns)) {
|
|
1440
|
+
existingColumnState.set(colName, { isNullable: col.isNullable });
|
|
1441
|
+
}
|
|
1142
1442
|
|
|
1143
1443
|
// Apply modifications
|
|
1144
1444
|
const resultBuilder = callback(
|
|
@@ -1160,7 +1460,25 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1160
1460
|
subOperations.push({
|
|
1161
1461
|
type: "add-column",
|
|
1162
1462
|
columnName: colName,
|
|
1163
|
-
column: newTable.columns[colName],
|
|
1463
|
+
column: cloneColumn(newTable.columns[colName]),
|
|
1464
|
+
});
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
// Track updates to existing columns
|
|
1469
|
+
for (const [colName, previousState] of existingColumnState.entries()) {
|
|
1470
|
+
const updatedColumn = newTable.columns[colName];
|
|
1471
|
+
if (!updatedColumn) {
|
|
1472
|
+
continue;
|
|
1473
|
+
}
|
|
1474
|
+
if (previousState.isNullable !== updatedColumn.isNullable) {
|
|
1475
|
+
subOperations.push({
|
|
1476
|
+
type: "update-column",
|
|
1477
|
+
columnName: colName,
|
|
1478
|
+
column: cloneColumn(updatedColumn),
|
|
1479
|
+
updateNullable: true,
|
|
1480
|
+
updateDefault: false,
|
|
1481
|
+
updateDataType: false,
|
|
1164
1482
|
});
|
|
1165
1483
|
}
|
|
1166
1484
|
}
|
|
@@ -1168,10 +1486,15 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1168
1486
|
// Add only new indexes
|
|
1169
1487
|
for (const idx of resultBuilder.getIndexes()) {
|
|
1170
1488
|
if (!existingIndexes.has(idx.name)) {
|
|
1489
|
+
if (this.#indexNames.has(idx.name)) {
|
|
1490
|
+
throw new Error(
|
|
1491
|
+
`Duplicate index name "${idx.name}" in schema "${this.#name}". Index names must be unique across tables (conflict on "${tableName}").`,
|
|
1492
|
+
);
|
|
1493
|
+
}
|
|
1171
1494
|
subOperations.push({
|
|
1172
1495
|
type: "add-index",
|
|
1173
1496
|
name: idx.name,
|
|
1174
|
-
columns: idx.columns.map((c) => c.
|
|
1497
|
+
columns: idx.columns.map((c) => c.name),
|
|
1175
1498
|
unique: idx.unique,
|
|
1176
1499
|
});
|
|
1177
1500
|
}
|
|
@@ -1188,6 +1511,12 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1188
1511
|
|
|
1189
1512
|
// Update table reference in schema
|
|
1190
1513
|
this.#tables[tableName] = newTable as unknown as TTables[TTableName];
|
|
1514
|
+
this.#rebindRelations(tableName, newTable as unknown as AnyTable);
|
|
1515
|
+
for (const idx of resultBuilder.getIndexes()) {
|
|
1516
|
+
if (!existingIndexes.has(idx.name)) {
|
|
1517
|
+
this.#indexNames.add(idx.name);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1191
1520
|
|
|
1192
1521
|
// Set table name for all columns
|
|
1193
1522
|
for (const col of Object.values(newTable.columns)) {
|
|
@@ -1208,6 +1537,7 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1208
1537
|
const tables = this.#tables;
|
|
1209
1538
|
|
|
1210
1539
|
const schema: Schema<TTables> = {
|
|
1540
|
+
name: this.#name,
|
|
1211
1541
|
version,
|
|
1212
1542
|
tables,
|
|
1213
1543
|
operations,
|
|
@@ -1231,7 +1561,6 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1231
1561
|
}
|
|
1232
1562
|
|
|
1233
1563
|
clonedCol.name = col.name;
|
|
1234
|
-
clonedCol.ormName = col.ormName;
|
|
1235
1564
|
clonedCol.isNullable = col.isNullable;
|
|
1236
1565
|
clonedCol.role = col.role;
|
|
1237
1566
|
clonedCol.isHidden = col.isHidden;
|
|
@@ -1240,20 +1569,28 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1240
1569
|
clonedColumns[colName] = clonedCol;
|
|
1241
1570
|
}
|
|
1242
1571
|
|
|
1243
|
-
|
|
1572
|
+
const clonedTable = {
|
|
1244
1573
|
...v,
|
|
1245
1574
|
columns: clonedColumns,
|
|
1246
|
-
};
|
|
1575
|
+
} as AnyTable;
|
|
1576
|
+
|
|
1577
|
+
clonedTable["~standard"] = createTableStandardSchemaProps(clonedTable, validationClasses);
|
|
1578
|
+
clonedTable.validate = createTableValidator(clonedTable, validationClasses);
|
|
1579
|
+
|
|
1580
|
+
cloneTables[k] = clonedTable;
|
|
1247
1581
|
}
|
|
1248
1582
|
|
|
1249
|
-
|
|
1583
|
+
const clonedSchema: Schema<TTables> = {
|
|
1584
|
+
name: this.#name,
|
|
1250
1585
|
version,
|
|
1251
1586
|
tables: cloneTables as TTables,
|
|
1252
1587
|
operations: [...operations],
|
|
1253
1588
|
clone: () => {
|
|
1254
1589
|
throw new Error("Cannot clone during clone");
|
|
1255
1590
|
},
|
|
1256
|
-
}
|
|
1591
|
+
};
|
|
1592
|
+
|
|
1593
|
+
return new SchemaBuilder<TTables>(this.#name, clonedSchema).build();
|
|
1257
1594
|
},
|
|
1258
1595
|
};
|
|
1259
1596
|
|
|
@@ -1272,19 +1609,18 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1272
1609
|
* Create a new schema with callback pattern.
|
|
1273
1610
|
*/
|
|
1274
1611
|
export function schema<const TTables extends Record<string, AnyTable> = {}>(
|
|
1612
|
+
name: string,
|
|
1275
1613
|
callback: (builder: SchemaBuilder<{}>) => SchemaBuilder<TTables>,
|
|
1276
1614
|
): Schema<TTables> {
|
|
1277
|
-
return callback(new SchemaBuilder()).build();
|
|
1615
|
+
return callback(new SchemaBuilder(name)).build();
|
|
1278
1616
|
}
|
|
1279
1617
|
|
|
1280
|
-
export function compileForeignKey(key: ForeignKey
|
|
1618
|
+
export function compileForeignKey(key: ForeignKey) {
|
|
1281
1619
|
return {
|
|
1282
1620
|
name: key.name,
|
|
1283
|
-
table:
|
|
1284
|
-
referencedTable:
|
|
1285
|
-
referencedColumns: key.referencedColumns.map((col) =>
|
|
1286
|
-
|
|
1287
|
-
),
|
|
1288
|
-
columns: key.columns.map((col) => (nameType === "sql" ? col.name : col.ormName)),
|
|
1621
|
+
table: key.table.name,
|
|
1622
|
+
referencedTable: key.referencedTable.name,
|
|
1623
|
+
referencedColumns: key.referencedColumns.map((col) => col.name),
|
|
1624
|
+
columns: key.columns.map((col) => col.name),
|
|
1289
1625
|
};
|
|
1290
1626
|
}
|