@fragno-dev/db 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +206 -140
- package/CHANGELOG.md +67 -0
- package/README.md +30 -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 +27 -9
- package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -1
- package/dist/adapters/generic-sql/generic-sql-adapter.js +55 -16
- package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -1
- package/dist/adapters/generic-sql/generic-sql-uow-executor.js +129 -3
- package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -1
- package/dist/adapters/generic-sql/migration/dialect/mysql.js +24 -5
- package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -1
- package/dist/adapters/generic-sql/migration/dialect/postgres.js +6 -5
- package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -1
- package/dist/adapters/generic-sql/migration/dialect/sqlite.js +21 -10
- package/dist/adapters/generic-sql/migration/dialect/sqlite.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 +8 -8
- package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -1
- package/dist/adapters/generic-sql/migration/sql-generator.js +74 -51
- package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -1
- package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +6 -5
- 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/generic-sql-uow-operation-compiler.js +25 -17
- 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 +15 -12
- package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -1
- package/dist/adapters/generic-sql/query/where-builder.js +38 -28
- 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 +7 -3
- package/dist/adapters/generic-sql/uow-decoder.js.map +1 -1
- package/dist/adapters/generic-sql/uow-encoder.js +28 -8
- package/dist/adapters/generic-sql/uow-encoder.js.map +1 -1
- package/dist/adapters/in-memory/condition-evaluator.js +131 -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 +176 -0
- package/dist/adapters/in-memory/in-memory-adapter.js.map +1 -0
- package/dist/adapters/in-memory/in-memory-uow.js +648 -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 +28 -0
- package/dist/adapters/in-memory/options.d.ts.map +1 -0
- package/dist/adapters/in-memory/options.js +61 -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.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/db-fragment-definition-builder.d.ts +45 -96
- package/dist/db-fragment-definition-builder.d.ts.map +1 -1
- package/dist/db-fragment-definition-builder.js +121 -99
- package/dist/db-fragment-definition-builder.js.map +1 -1
- package/dist/dispatchers/cloudflare-do/index.d.ts +26 -0
- package/dist/dispatchers/cloudflare-do/index.d.ts.map +1 -0
- package/dist/dispatchers/cloudflare-do/index.js +63 -0
- package/dist/dispatchers/cloudflare-do/index.js.map +1 -0
- package/dist/dispatchers/node/index.d.ts +17 -0
- package/dist/dispatchers/node/index.d.ts.map +1 -0
- package/dist/dispatchers/node/index.js +59 -0
- package/dist/dispatchers/node/index.js.map +1 -0
- package/dist/fragments/internal-fragment.d.ts +172 -9
- package/dist/fragments/internal-fragment.d.ts.map +1 -1
- package/dist/fragments/internal-fragment.js +193 -74
- package/dist/fragments/internal-fragment.js.map +1 -1
- package/dist/fragments/internal-fragment.routes.js +29 -0
- package/dist/fragments/internal-fragment.routes.js.map +1 -0
- package/dist/fragments/internal-fragment.schema.d.ts +9 -0
- package/dist/fragments/internal-fragment.schema.d.ts.map +1 -0
- package/dist/fragments/internal-fragment.schema.js +22 -0
- package/dist/fragments/internal-fragment.schema.js.map +1 -0
- package/dist/hooks/durable-hooks-processor.d.ts +14 -0
- package/dist/hooks/durable-hooks-processor.d.ts.map +1 -0
- package/dist/hooks/durable-hooks-processor.js +32 -0
- package/dist/hooks/durable-hooks-processor.js.map +1 -0
- package/dist/hooks/hooks.d.ts +47 -4
- package/dist/hooks/hooks.d.ts.map +1 -1
- package/dist/hooks/hooks.js +106 -39
- package/dist/hooks/hooks.js.map +1 -1
- package/dist/migration-engine/auto-from-schema.js +14 -11
- 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 +72 -33
- package/dist/migration-engine/generation-engine.js.map +1 -1
- package/dist/migration-engine/shared.js.map +1 -1
- package/dist/mod.d.ts +17 -10
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +14 -8
- 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/node_modules/.pnpm/{rou3@0.7.10 → rou3@0.7.12}/node_modules/rou3/dist/index.js +8 -5
- package/dist/node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.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 +52 -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/packages/fragno/dist/api/fragment-definition-builder.js +3 -2
- package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +1 -1
- package/dist/packages/fragno/dist/api/fragment-instantiator.js +164 -20
- package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +1 -1
- package/dist/packages/fragno/dist/api/request-input-context.js +67 -0
- package/dist/packages/fragno/dist/api/request-input-context.js.map +1 -1
- package/dist/packages/fragno/dist/api/route.js +14 -1
- package/dist/packages/fragno/dist/api/route.js.map +1 -1
- package/dist/packages/fragno/dist/internal/trace-context.js +12 -0
- package/dist/packages/fragno/dist/internal/trace-context.js.map +1 -0
- package/dist/query/column-defaults.js +20 -4
- package/dist/query/column-defaults.js.map +1 -1
- package/dist/query/cursor.d.ts +3 -1
- package/dist/query/cursor.d.ts.map +1 -1
- package/dist/query/cursor.js +45 -14
- package/dist/query/cursor.js.map +1 -1
- package/dist/query/db-now.d.ts +8 -0
- package/dist/query/db-now.d.ts.map +1 -0
- package/dist/query/db-now.js +7 -0
- package/dist/query/db-now.js.map +1 -0
- package/dist/query/serialize/create-sql-serializer.js +3 -2
- 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 +55 -11
- 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 +6 -1
- package/dist/query/simple-query-interface.d.ts.map +1 -1
- package/dist/query/unit-of-work/execute-unit-of-work.d.ts +351 -100
- 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 +440 -267
- 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 +67 -22
- package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
- package/dist/query/unit-of-work/unit-of-work.js +110 -13
- package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
- package/dist/query/value-decoding.js +8 -5
- 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 +40 -14
- package/dist/schema/create.d.ts.map +1 -1
- package/dist/schema/create.js +82 -42
- package/dist/schema/create.js.map +1 -1
- package/dist/schema/generate-id.d.ts +20 -0
- package/dist/schema/generate-id.d.ts.map +1 -0
- package/dist/schema/generate-id.js +28 -0
- package/dist/schema/generate-id.js.map +1 -0
- package/dist/schema/type-conversion/create-sql-type-mapper.js +3 -2
- 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} +82 -56
- 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 +296 -0
- package/dist/schema-output/prisma.js.map +1 -0
- package/dist/util/default-database-adapter.js +61 -0
- package/dist/util/default-database-adapter.js.map +1 -0
- package/dist/with-database.d.ts +1 -1
- package/dist/with-database.d.ts.map +1 -1
- package/dist/with-database.js +12 -3
- package/dist/with-database.js.map +1 -1
- package/package.json +43 -28
- package/src/adapters/adapters.ts +30 -24
- package/src/adapters/drizzle/migrate-drizzle.test.ts +54 -33
- package/src/adapters/drizzle/migration-parity-drizzle-kit.test.ts +599 -0
- package/src/adapters/drizzle/test-utils.ts +12 -8
- package/src/adapters/generic-sql/driver-config.ts +38 -0
- package/src/adapters/generic-sql/generic-sql-adapter.test.ts +5 -5
- package/src/adapters/generic-sql/generic-sql-adapter.ts +110 -24
- package/src/adapters/generic-sql/generic-sql-uow-executor.test.ts +54 -0
- package/src/adapters/generic-sql/generic-sql-uow-executor.ts +231 -3
- package/src/adapters/generic-sql/migration/adapter-migration-parity.test.ts +118 -0
- package/src/adapters/generic-sql/migration/dialect/mysql.test.ts +26 -8
- package/src/adapters/generic-sql/migration/dialect/mysql.ts +46 -8
- package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +25 -7
- package/src/adapters/generic-sql/migration/dialect/postgres.ts +8 -4
- package/src/adapters/generic-sql/migration/dialect/sqlite.test.ts +47 -8
- package/src/adapters/generic-sql/migration/dialect/sqlite.ts +27 -12
- package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +128 -39
- package/src/adapters/generic-sql/migration/prepared-migrations.ts +15 -8
- package/src/adapters/generic-sql/migration/sql-generator.ts +142 -65
- package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +9 -6
- package/src/adapters/generic-sql/query/cursor-utils.test.ts +271 -0
- package/src/adapters/generic-sql/query/cursor-utils.ts +41 -6
- package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +27 -27
- package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +38 -24
- package/src/adapters/generic-sql/query/select-builder.test.ts +15 -11
- package/src/adapters/generic-sql/query/select-builder.ts +6 -2
- package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +52 -2
- package/src/adapters/generic-sql/query/sql-query-compiler.ts +50 -15
- package/src/adapters/generic-sql/query/where-builder.test.ts +91 -17
- package/src/adapters/generic-sql/query/where-builder.ts +90 -38
- package/src/adapters/{kysely/kysely-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-migrations.test.ts} +6 -6
- package/src/adapters/generic-sql/sql-adapter-pglite-pagination.test.ts +806 -0
- package/src/adapters/{drizzle/drizzle-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-queries.test.ts} +11 -11
- package/src/adapters/generic-sql/{test/generic-drizzle-adapter-sqlite3.test.ts → sql-adapter-sqlite3-driver.test.ts} +49 -35
- package/src/adapters/{drizzle/drizzle-adapter-sqlite3.test.ts → generic-sql/sql-adapter-sqlite3-uow.test.ts} +48 -32
- package/src/adapters/{kysely/kysely-adapter-sqlocal.test.ts → generic-sql/sql-adapter-sqlocal.test.ts} +6 -6
- package/src/adapters/generic-sql/sqlite-storage.ts +20 -0
- package/src/adapters/generic-sql/uow-decoder.test.ts +1 -1
- package/src/adapters/generic-sql/uow-decoder.ts +21 -3
- package/src/adapters/generic-sql/uow-encoder.test.ts +33 -2
- package/src/adapters/generic-sql/uow-encoder.ts +50 -11
- package/src/adapters/in-memory/condition-evaluator.test.ts +193 -0
- package/src/adapters/in-memory/condition-evaluator.ts +275 -0
- package/src/adapters/in-memory/errors.ts +20 -0
- package/src/adapters/in-memory/in-memory-adapter.ts +277 -0
- package/src/adapters/in-memory/in-memory-uow.mutations.test.ts +296 -0
- package/src/adapters/in-memory/in-memory-uow.retrieval.test.ts +100 -0
- package/src/adapters/in-memory/in-memory-uow.ts +1348 -0
- package/src/adapters/in-memory/index.ts +3 -0
- package/src/adapters/in-memory/options.test.ts +41 -0
- package/src/adapters/in-memory/options.ts +87 -0
- package/src/adapters/in-memory/reference-resolution.test.ts +50 -0
- package/src/adapters/in-memory/reference-resolution.ts +67 -0
- package/src/adapters/in-memory/sorted-array-index.test.ts +123 -0
- package/src/adapters/in-memory/sorted-array-index.ts +228 -0
- package/src/adapters/in-memory/store.test.ts +68 -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 +57 -0
- package/src/adapters/prisma/prisma-adapter-sqlite3.test.ts +1163 -0
- package/src/adapters/shared/from-unit-of-work-compiler.ts +3 -1
- package/src/adapters/shared/uow-operation-compiler.ts +26 -16
- package/src/adapters/sql/index.ts +12 -0
- package/src/db-fragment-definition-builder.test.ts +88 -54
- package/src/db-fragment-definition-builder.ts +201 -322
- package/src/db-fragment-instantiator.test.ts +169 -101
- package/src/db-fragment-integration.test.ts +301 -149
- package/src/dispatchers/cloudflare-do/index.test.ts +73 -0
- package/src/dispatchers/cloudflare-do/index.ts +104 -0
- package/src/dispatchers/node/index.test.ts +91 -0
- package/src/dispatchers/node/index.ts +87 -0
- package/src/fragments/internal-fragment.routes.ts +42 -0
- package/src/fragments/internal-fragment.schema.ts +51 -0
- package/src/fragments/internal-fragment.test.ts +730 -274
- package/src/fragments/internal-fragment.ts +447 -154
- package/src/hooks/durable-hooks-processor.test.ts +117 -0
- package/src/hooks/durable-hooks-processor.ts +67 -0
- package/src/hooks/hooks.test.ts +411 -259
- package/src/hooks/hooks.ts +265 -66
- package/src/migration-engine/auto-from-schema.test.ts +14 -14
- package/src/migration-engine/auto-from-schema.ts +5 -2
- package/src/migration-engine/create.test.ts +2 -2
- package/src/migration-engine/generation-engine.test.ts +229 -104
- package/src/migration-engine/generation-engine.ts +94 -64
- package/src/migration-engine/shared.ts +1 -0
- package/src/mod.ts +78 -30
- package/src/naming/sql-naming.ts +180 -0
- package/src/outbox/outbox-builder.ts +241 -0
- package/src/outbox/outbox.test.ts +253 -0
- package/src/outbox/outbox.ts +137 -0
- package/src/query/column-defaults.ts +41 -3
- package/src/query/condition-builder.test.ts +3 -3
- package/src/query/cursor.test.ts +116 -18
- package/src/query/cursor.ts +75 -26
- package/src/query/db-now.ts +6 -0
- package/src/query/query-type.test.ts +2 -2
- package/src/query/serialize/create-sql-serializer.ts +7 -2
- package/src/query/serialize/dialect/mysql-serializer.ts +12 -4
- package/src/query/serialize/dialect/postgres-serializer.ts +34 -4
- package/src/query/serialize/dialect/sqlite-serializer.test.ts +51 -1
- package/src/query/serialize/dialect/sqlite-serializer.ts +92 -9
- package/src/query/serialize/sql-serializer.ts +4 -4
- package/src/query/simple-query-interface.ts +5 -0
- package/src/query/unit-of-work/execute-unit-of-work.test.ts +1512 -1458
- package/src/query/unit-of-work/execute-unit-of-work.ts +1708 -596
- package/src/query/unit-of-work/tx-builder.test.ts +1041 -0
- package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +32 -32
- package/src/query/unit-of-work/unit-of-work-types.test.ts +1 -1
- package/src/query/unit-of-work/unit-of-work.test.ts +231 -36
- package/src/query/unit-of-work/unit-of-work.ts +229 -31
- package/src/query/value-decoding.test.ts +13 -2
- package/src/query/value-decoding.ts +17 -4
- package/src/query/value-encoding.test.ts +85 -2
- package/src/query/value-encoding.ts +56 -6
- package/src/schema/create.test.ts +129 -42
- package/src/schema/create.ts +187 -47
- package/src/schema/generate-id.test.ts +57 -0
- package/src/schema/generate-id.ts +38 -0
- package/src/schema/serialize.test.ts +14 -2
- package/src/schema/type-conversion/create-sql-type-mapper.ts +7 -2
- package/src/schema/type-conversion/dialect/sqlite.ts +18 -0
- package/src/schema/type-conversion/type-mapping.test.ts +25 -1
- package/src/schema/validator.test.ts +197 -0
- package/src/schema/validator.ts +231 -0
- package/src/{adapters/drizzle/generate.test.ts → schema-output/drizzle.test.ts} +179 -129
- package/src/{adapters/drizzle/generate.ts → schema-output/drizzle.ts} +143 -93
- package/src/schema-output/prisma.test.ts +536 -0
- package/src/schema-output/prisma.ts +573 -0
- package/src/util/default-database-adapter.ts +106 -0
- package/src/with-database.ts +22 -3
- package/tsdown.config.ts +6 -4
- 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.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/shared/config.ts +0 -10
- package/src/shared/connection-pool.ts +0 -24
- package/src/shared/prisma.ts +0 -45
package/src/schema/create.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
1
2
|
import { createId } from "../id";
|
|
3
|
+
import type { DbNow } from "../query/db-now";
|
|
4
|
+
import type { Prettify } from "../util/types";
|
|
5
|
+
import { createTableStandardSchemaProps, createTableValidator } from "./validator";
|
|
6
|
+
|
|
7
|
+
export { generateId } from "./generate-id";
|
|
8
|
+
export { FragnoDbValidationError } from "./validator";
|
|
2
9
|
|
|
3
10
|
export type AnySchema = Schema<Record<string, AnyTable>>;
|
|
4
11
|
|
|
@@ -93,13 +100,13 @@ export class ExplicitRelationInit<
|
|
|
93
100
|
TTables extends Record<string, AnyTable>,
|
|
94
101
|
TTableName extends keyof TTables,
|
|
95
102
|
> extends RelationInit<TRelationType, TTables, TTableName> {
|
|
96
|
-
init(
|
|
97
|
-
const id = `${this.referencer.
|
|
103
|
+
init(name: string): Relation<TRelationType, TTables[TTableName]> {
|
|
104
|
+
const id = `${this.referencer.name}_${this.referencedTable.name}`;
|
|
98
105
|
|
|
99
106
|
return {
|
|
100
107
|
id,
|
|
101
108
|
on: this.on,
|
|
102
|
-
name
|
|
109
|
+
name,
|
|
103
110
|
referencer: this.referencer,
|
|
104
111
|
table: this.referencedTable,
|
|
105
112
|
type: this.type,
|
|
@@ -121,18 +128,57 @@ export interface Relation<
|
|
|
121
128
|
on: [string, string][];
|
|
122
129
|
}
|
|
123
130
|
|
|
131
|
+
type PickNullable<T> = {
|
|
132
|
+
[P in keyof T as null extends T[P] ? P : never]: T[P];
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
type PickNotNullable<T> = {
|
|
136
|
+
[P in keyof T as null extends T[P] ? never : P]: T[P];
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
type RawInsertValuesFromColumns<TColumns extends Record<string, AnyColumn>> = {
|
|
140
|
+
[K in keyof TColumns as string extends K ? never : K]: TColumns[K]["$in"];
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
type TableInsertValuesFromColumns<TColumns extends Record<string, AnyColumn>> = Prettify<
|
|
144
|
+
Partial<PickNullable<RawInsertValuesFromColumns<TColumns>>> &
|
|
145
|
+
PickNotNullable<RawInsertValuesFromColumns<TColumns>>
|
|
146
|
+
>;
|
|
147
|
+
|
|
148
|
+
export type TableInsertValues<T extends AnyTable> = TableInsertValuesFromColumns<T["columns"]>;
|
|
149
|
+
|
|
150
|
+
export type TableUnknownKeysMode = "strip" | "strict";
|
|
151
|
+
|
|
152
|
+
export type TableValidationOptions = {
|
|
153
|
+
unknownKeys?: TableUnknownKeysMode;
|
|
154
|
+
};
|
|
155
|
+
|
|
124
156
|
export interface Table<
|
|
125
157
|
TColumns extends Record<string, AnyColumn> = Record<string, AnyColumn>,
|
|
126
158
|
TRelations extends Record<string, AnyRelation> = Record<string, AnyRelation>,
|
|
127
159
|
TIndexes extends Record<string, Index> = Record<string, Index>,
|
|
128
160
|
> {
|
|
161
|
+
/**
|
|
162
|
+
* Standard Schema-compatible validator for insert values.
|
|
163
|
+
*/
|
|
164
|
+
"~standard": StandardSchemaV1.Props<
|
|
165
|
+
TableInsertValuesFromColumns<TColumns>,
|
|
166
|
+
TableInsertValuesFromColumns<TColumns>
|
|
167
|
+
>;
|
|
129
168
|
name: string;
|
|
130
|
-
ormName: string;
|
|
131
169
|
|
|
132
170
|
columns: TColumns;
|
|
133
171
|
relations: TRelations;
|
|
134
172
|
indexes: TIndexes;
|
|
135
173
|
|
|
174
|
+
/**
|
|
175
|
+
* Validate insert values at runtime.
|
|
176
|
+
*/
|
|
177
|
+
validate: (
|
|
178
|
+
value: unknown,
|
|
179
|
+
options?: TableValidationOptions,
|
|
180
|
+
) => TableInsertValuesFromColumns<TColumns>;
|
|
181
|
+
|
|
136
182
|
/**
|
|
137
183
|
* Get column by name
|
|
138
184
|
*/
|
|
@@ -201,7 +247,6 @@ export type TypeMap = {
|
|
|
201
247
|
export class Column<TType extends keyof TypeMap, TIn = unknown, TOut = unknown> {
|
|
202
248
|
type: TType;
|
|
203
249
|
name: string = "";
|
|
204
|
-
ormName: string = "";
|
|
205
250
|
isNullable: boolean = false;
|
|
206
251
|
role: "external-id" | "internal-id" | "version" | "reference" | "regular" = "regular";
|
|
207
252
|
isHidden: boolean = false;
|
|
@@ -419,9 +464,13 @@ export class VersionColumn<TIn = unknown, TOut = unknown> extends Column<"intege
|
|
|
419
464
|
}
|
|
420
465
|
}
|
|
421
466
|
|
|
467
|
+
type ColumnInput<TType extends keyof TypeMap> =
|
|
468
|
+
| TypeMap[TType]
|
|
469
|
+
| (TType extends "timestamp" | "date" ? DbNow : never);
|
|
470
|
+
|
|
422
471
|
export function column<TType extends keyof TypeMap>(
|
|
423
472
|
type: TType,
|
|
424
|
-
): Column<TType,
|
|
473
|
+
): Column<TType, ColumnInput<TType>, TypeMap[TType]> {
|
|
425
474
|
return new Column(type);
|
|
426
475
|
}
|
|
427
476
|
|
|
@@ -577,6 +626,8 @@ export class FragnoReference {
|
|
|
577
626
|
}
|
|
578
627
|
}
|
|
579
628
|
|
|
629
|
+
const validationClasses = { FragnoId, FragnoReference };
|
|
630
|
+
|
|
580
631
|
type RelationType = "one" | "many";
|
|
581
632
|
|
|
582
633
|
export class TableBuilder<
|
|
@@ -588,7 +639,6 @@ export class TableBuilder<
|
|
|
588
639
|
#columns: TColumns;
|
|
589
640
|
#relations: TRelations;
|
|
590
641
|
#indexes: TIndexes;
|
|
591
|
-
#ormName: string = "";
|
|
592
642
|
#columnOrder: string[] = [];
|
|
593
643
|
|
|
594
644
|
constructor(name: string) {
|
|
@@ -624,7 +674,7 @@ export class TableBuilder<
|
|
|
624
674
|
* Add a column to the table.
|
|
625
675
|
*/
|
|
626
676
|
addColumn<TColumnName extends string, TColumn extends AnyColumn>(
|
|
627
|
-
|
|
677
|
+
name: TColumnName,
|
|
628
678
|
col: TColumn,
|
|
629
679
|
): TableBuilder<TColumns & Record<TColumnName, TColumn>, TRelations, TIndexes>;
|
|
630
680
|
|
|
@@ -632,28 +682,27 @@ export class TableBuilder<
|
|
|
632
682
|
* Add a column to the table with simplified syntax.
|
|
633
683
|
*/
|
|
634
684
|
addColumn<TColumnName extends string, TType extends keyof TypeMap>(
|
|
635
|
-
|
|
685
|
+
name: TColumnName,
|
|
636
686
|
type: TType,
|
|
637
687
|
): TableBuilder<
|
|
638
|
-
TColumns & Record<TColumnName, Column<TType,
|
|
688
|
+
TColumns & Record<TColumnName, Column<TType, ColumnInput<TType>, TypeMap[TType]>>,
|
|
639
689
|
TRelations,
|
|
640
690
|
TIndexes
|
|
641
691
|
>;
|
|
642
692
|
|
|
643
693
|
addColumn<TColumnName extends string, TColumn extends AnyColumn, TType extends keyof TypeMap>(
|
|
644
|
-
|
|
694
|
+
name: TColumnName,
|
|
645
695
|
colOrType: TColumn | TType,
|
|
646
696
|
): TableBuilder<TColumns & Record<TColumnName, TColumn>, TRelations, TIndexes> {
|
|
647
697
|
// Create the column if a type string was provided
|
|
648
698
|
const col = typeof colOrType === "string" ? column(colOrType) : colOrType;
|
|
649
699
|
|
|
650
700
|
// Set column metadata
|
|
651
|
-
col.
|
|
652
|
-
col.name = ormName;
|
|
701
|
+
col.name = name;
|
|
653
702
|
|
|
654
703
|
// Add column directly to this builder
|
|
655
|
-
this.#columns[
|
|
656
|
-
this.#columnOrder.push(
|
|
704
|
+
this.#columns[name] = col as unknown as TColumns[TColumnName];
|
|
705
|
+
this.#columnOrder.push(name);
|
|
657
706
|
|
|
658
707
|
return this as unknown as TableBuilder<
|
|
659
708
|
TColumns & Record<TColumnName, TColumn>,
|
|
@@ -714,7 +763,6 @@ export class TableBuilder<
|
|
|
714
763
|
// Auto-add _internalId and _version columns if not already present
|
|
715
764
|
if (!this.#columns["_internalId"]) {
|
|
716
765
|
const col = internalIdColumn();
|
|
717
|
-
col.ormName = "_internalId";
|
|
718
766
|
col.name = "_internalId";
|
|
719
767
|
// Safe: we're adding system columns to the internal columns object
|
|
720
768
|
(this.#columns as Record<string, AnyColumn>)["_internalId"] = col;
|
|
@@ -722,18 +770,13 @@ export class TableBuilder<
|
|
|
722
770
|
|
|
723
771
|
if (!this.#columns["_version"]) {
|
|
724
772
|
const col = versionColumn();
|
|
725
|
-
col.ormName = "_version";
|
|
726
773
|
col.name = "_version";
|
|
727
774
|
// Safe: we're adding system columns to the internal columns object
|
|
728
775
|
(this.#columns as Record<string, AnyColumn>)["_version"] = col;
|
|
729
776
|
}
|
|
730
777
|
|
|
731
|
-
|
|
732
|
-
const ormName = this.#ormName || this.#name;
|
|
733
|
-
|
|
734
|
-
const table: Table<TColumns, TRelations, TIndexes> = {
|
|
778
|
+
const table = {
|
|
735
779
|
name: this.#name,
|
|
736
|
-
ormName,
|
|
737
780
|
columns: this.#columns,
|
|
738
781
|
relations: this.#relations,
|
|
739
782
|
indexes: this.#indexes,
|
|
@@ -749,7 +792,10 @@ export class TableBuilder<
|
|
|
749
792
|
getVersionColumn: () => {
|
|
750
793
|
return versionCol!;
|
|
751
794
|
},
|
|
752
|
-
}
|
|
795
|
+
} as Table<TColumns, TRelations, TIndexes>;
|
|
796
|
+
|
|
797
|
+
table["~standard"] = createTableStandardSchemaProps(table, validationClasses);
|
|
798
|
+
table.validate = createTableValidator(table, validationClasses);
|
|
753
799
|
|
|
754
800
|
// Set table reference and find special columns
|
|
755
801
|
for (const k in this.#columns) {
|
|
@@ -785,6 +831,10 @@ export class TableBuilder<
|
|
|
785
831
|
}
|
|
786
832
|
|
|
787
833
|
export interface Schema<TTables extends Record<string, AnyTable> = Record<string, AnyTable>> {
|
|
834
|
+
/**
|
|
835
|
+
* @description The name of the schema (required).
|
|
836
|
+
*/
|
|
837
|
+
name: string;
|
|
788
838
|
/**
|
|
789
839
|
* @description The version of the schema, automatically incremented on each change.
|
|
790
840
|
*/
|
|
@@ -849,11 +899,15 @@ type ColumnsToTuple<
|
|
|
849
899
|
} & AnyColumn[];
|
|
850
900
|
|
|
851
901
|
export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
902
|
+
#name: string;
|
|
852
903
|
#tables: TTables;
|
|
853
904
|
#version: number = 0;
|
|
854
905
|
#operations: SchemaOperation[] = [];
|
|
906
|
+
#tableNames: Set<string> = new Set();
|
|
907
|
+
#indexNames: Set<string> = new Set();
|
|
855
908
|
|
|
856
|
-
constructor(existingSchema?: Schema<TTables>) {
|
|
909
|
+
constructor(name: string, existingSchema?: Schema<TTables>) {
|
|
910
|
+
this.#name = name;
|
|
857
911
|
if (existingSchema) {
|
|
858
912
|
this.#tables = existingSchema.tables;
|
|
859
913
|
this.#version = existingSchema.version;
|
|
@@ -861,6 +915,29 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
861
915
|
} else {
|
|
862
916
|
this.#tables = {} as TTables;
|
|
863
917
|
}
|
|
918
|
+
|
|
919
|
+
for (const table of Object.values(this.#tables)) {
|
|
920
|
+
this.#registerTableName(table.name);
|
|
921
|
+
for (const index of Object.values(table.indexes)) {
|
|
922
|
+
this.#registerIndexName(index.name, table.name);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
#registerTableName(name: string): void {
|
|
928
|
+
if (this.#tableNames.has(name)) {
|
|
929
|
+
throw new Error(`Duplicate table name "${name}" in schema "${this.#name}".`);
|
|
930
|
+
}
|
|
931
|
+
this.#tableNames.add(name);
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
#registerIndexName(name: string, tableName: string): void {
|
|
935
|
+
if (this.#indexNames.has(name)) {
|
|
936
|
+
throw new Error(
|
|
937
|
+
`Duplicate index name "${name}" in schema "${this.#name}". Index names must be unique across tables (conflict on "${tableName}").`,
|
|
938
|
+
);
|
|
939
|
+
}
|
|
940
|
+
this.#indexNames.add(name);
|
|
864
941
|
}
|
|
865
942
|
|
|
866
943
|
/**
|
|
@@ -869,7 +946,7 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
869
946
|
*
|
|
870
947
|
* @example
|
|
871
948
|
* ```ts
|
|
872
|
-
* const builder = new SchemaBuilder()
|
|
949
|
+
* const builder = new SchemaBuilder("combined")
|
|
873
950
|
* .add(userSchema)
|
|
874
951
|
* .add(postSchema)
|
|
875
952
|
* .addTable("comments", ...);
|
|
@@ -878,10 +955,32 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
878
955
|
mergeWithExistingSchema<TNewTables extends Record<string, AnyTable>>(
|
|
879
956
|
schema: Schema<TNewTables>,
|
|
880
957
|
): SchemaBuilder<TTables & TNewTables> {
|
|
958
|
+
for (const table of Object.values(schema.tables)) {
|
|
959
|
+
if (this.#tableNames.has(table.name)) {
|
|
960
|
+
throw new Error(
|
|
961
|
+
`Duplicate table name "${table.name}" in schema "${this.#name}" when merging.`,
|
|
962
|
+
);
|
|
963
|
+
}
|
|
964
|
+
for (const index of Object.values(table.indexes)) {
|
|
965
|
+
if (this.#indexNames.has(index.name)) {
|
|
966
|
+
throw new Error(
|
|
967
|
+
`Duplicate index name "${index.name}" in schema "${this.#name}" when merging (conflict on "${table.name}").`,
|
|
968
|
+
);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
|
|
881
973
|
this.#tables = { ...this.#tables, ...schema.tables } as TTables & TNewTables;
|
|
882
974
|
this.#operations = [...this.#operations, ...schema.operations];
|
|
883
975
|
this.#version += schema.version;
|
|
884
976
|
|
|
977
|
+
for (const table of Object.values(schema.tables)) {
|
|
978
|
+
this.#tableNames.add(table.name);
|
|
979
|
+
for (const index of Object.values(table.indexes)) {
|
|
980
|
+
this.#indexNames.add(index.name);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
|
|
885
984
|
return this as unknown as SchemaBuilder<TTables & TNewTables>;
|
|
886
985
|
}
|
|
887
986
|
|
|
@@ -894,7 +993,7 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
894
993
|
TRelations extends Record<string, AnyRelation>,
|
|
895
994
|
TIndexes extends Record<string, Index> = Record<string, Index>,
|
|
896
995
|
>(
|
|
897
|
-
|
|
996
|
+
name: TTableName,
|
|
898
997
|
callback: (
|
|
899
998
|
builder: TableBuilder<
|
|
900
999
|
Record<string, AnyColumn>,
|
|
@@ -905,10 +1004,22 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
905
1004
|
): SchemaBuilder<TTables & Record<TTableName, Table<TColumns, TRelations, TIndexes>>> {
|
|
906
1005
|
this.#version++;
|
|
907
1006
|
|
|
908
|
-
|
|
1007
|
+
if (this.#tableNames.has(name)) {
|
|
1008
|
+
throw new Error(`Duplicate table name "${name}" in schema "${this.#name}".`);
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
const tableBuilder = new TableBuilder(name);
|
|
909
1012
|
const result = callback(tableBuilder);
|
|
910
1013
|
const builtTable = result.build();
|
|
911
|
-
|
|
1014
|
+
const indexNames = result.getIndexes().map((idx) => idx.name);
|
|
1015
|
+
|
|
1016
|
+
for (const indexName of indexNames) {
|
|
1017
|
+
if (this.#indexNames.has(indexName)) {
|
|
1018
|
+
throw new Error(
|
|
1019
|
+
`Duplicate index name "${indexName}" in schema "${this.#name}". Index names must be unique across tables (conflict on "${name}").`,
|
|
1020
|
+
);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
912
1023
|
|
|
913
1024
|
// Collect sub-operations in order
|
|
914
1025
|
const subOperations: TableSubOperation[] = [];
|
|
@@ -945,7 +1056,7 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
945
1056
|
subOperations.push({
|
|
946
1057
|
type: "add-index",
|
|
947
1058
|
name: idx.name,
|
|
948
|
-
columns: idx.columns.map((c) => c.
|
|
1059
|
+
columns: idx.columns.map((c) => c.name),
|
|
949
1060
|
unique: idx.unique,
|
|
950
1061
|
});
|
|
951
1062
|
}
|
|
@@ -953,13 +1064,17 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
953
1064
|
// Add the add-table operation
|
|
954
1065
|
this.#operations.push({
|
|
955
1066
|
type: "add-table",
|
|
956
|
-
tableName:
|
|
1067
|
+
tableName: name,
|
|
957
1068
|
operations: subOperations,
|
|
958
1069
|
});
|
|
959
1070
|
|
|
960
1071
|
// Update tables map
|
|
961
|
-
this.#tables = { ...this.#tables, [
|
|
1072
|
+
this.#tables = { ...this.#tables, [name]: builtTable } as TTables &
|
|
962
1073
|
Record<TTableName, Table<TColumns, TRelations, TIndexes>>;
|
|
1074
|
+
this.#tableNames.add(name);
|
|
1075
|
+
for (const indexName of indexNames) {
|
|
1076
|
+
this.#indexNames.add(indexName);
|
|
1077
|
+
}
|
|
963
1078
|
|
|
964
1079
|
return this as unknown as SchemaBuilder<
|
|
965
1080
|
TTables & Record<TTableName, Table<TColumns, TRelations, TIndexes>>
|
|
@@ -975,7 +1090,7 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
975
1090
|
* @example
|
|
976
1091
|
* ```ts
|
|
977
1092
|
* // One-to-one or many-to-one: post -> user
|
|
978
|
-
* schema(s => s
|
|
1093
|
+
* schema("blog", s => s
|
|
979
1094
|
* .addTable("users", t => t.addColumn("id", idColumn()))
|
|
980
1095
|
* .addTable("posts", t => t
|
|
981
1096
|
* .addColumn("id", idColumn())
|
|
@@ -1028,6 +1143,10 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1028
1143
|
const table = this.#tables[config.from.table];
|
|
1029
1144
|
const referencedTable = this.#tables[config.to.table];
|
|
1030
1145
|
|
|
1146
|
+
if (!referenceName || referenceName.trim().length === 0) {
|
|
1147
|
+
throw new Error(`referenceName is required for addReference on ${config.from.table}`);
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1031
1150
|
if (!table) {
|
|
1032
1151
|
throw new Error(`Table ${config.from.table} not found in schema`);
|
|
1033
1152
|
}
|
|
@@ -1052,6 +1171,10 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1052
1171
|
throw new Error(`Column ${actualTargetColumnName} not found in table ${config.to.table}`);
|
|
1053
1172
|
}
|
|
1054
1173
|
|
|
1174
|
+
if (table.relations[referenceName]) {
|
|
1175
|
+
throw new Error(`Reference ${referenceName} already exists on table ${config.from.table}`);
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1055
1178
|
// Verify that reference columns are bigint (matching internal ID type)
|
|
1056
1179
|
if (column.role === "reference" && column.type !== "bigint") {
|
|
1057
1180
|
throw new Error(
|
|
@@ -1096,7 +1219,7 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1096
1219
|
* @example
|
|
1097
1220
|
* ```ts
|
|
1098
1221
|
* // Add a new column to an existing table
|
|
1099
|
-
* schema(s => s
|
|
1222
|
+
* schema("blog", s => s
|
|
1100
1223
|
* .addTable("users", t => t
|
|
1101
1224
|
* .addColumn("id", idColumn())
|
|
1102
1225
|
* .addColumn("name", column("string")))
|
|
@@ -1166,10 +1289,15 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1166
1289
|
// Add only new indexes
|
|
1167
1290
|
for (const idx of resultBuilder.getIndexes()) {
|
|
1168
1291
|
if (!existingIndexes.has(idx.name)) {
|
|
1292
|
+
if (this.#indexNames.has(idx.name)) {
|
|
1293
|
+
throw new Error(
|
|
1294
|
+
`Duplicate index name "${idx.name}" in schema "${this.#name}". Index names must be unique across tables (conflict on "${tableName}").`,
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1169
1297
|
subOperations.push({
|
|
1170
1298
|
type: "add-index",
|
|
1171
1299
|
name: idx.name,
|
|
1172
|
-
columns: idx.columns.map((c) => c.
|
|
1300
|
+
columns: idx.columns.map((c) => c.name),
|
|
1173
1301
|
unique: idx.unique,
|
|
1174
1302
|
});
|
|
1175
1303
|
}
|
|
@@ -1186,6 +1314,11 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1186
1314
|
|
|
1187
1315
|
// Update table reference in schema
|
|
1188
1316
|
this.#tables[tableName] = newTable as unknown as TTables[TTableName];
|
|
1317
|
+
for (const idx of resultBuilder.getIndexes()) {
|
|
1318
|
+
if (!existingIndexes.has(idx.name)) {
|
|
1319
|
+
this.#indexNames.add(idx.name);
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1189
1322
|
|
|
1190
1323
|
// Set table name for all columns
|
|
1191
1324
|
for (const col of Object.values(newTable.columns)) {
|
|
@@ -1206,6 +1339,7 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1206
1339
|
const tables = this.#tables;
|
|
1207
1340
|
|
|
1208
1341
|
const schema: Schema<TTables> = {
|
|
1342
|
+
name: this.#name,
|
|
1209
1343
|
version,
|
|
1210
1344
|
tables,
|
|
1211
1345
|
operations,
|
|
@@ -1229,7 +1363,6 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1229
1363
|
}
|
|
1230
1364
|
|
|
1231
1365
|
clonedCol.name = col.name;
|
|
1232
|
-
clonedCol.ormName = col.ormName;
|
|
1233
1366
|
clonedCol.isNullable = col.isNullable;
|
|
1234
1367
|
clonedCol.role = col.role;
|
|
1235
1368
|
clonedCol.isHidden = col.isHidden;
|
|
@@ -1238,20 +1371,28 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1238
1371
|
clonedColumns[colName] = clonedCol;
|
|
1239
1372
|
}
|
|
1240
1373
|
|
|
1241
|
-
|
|
1374
|
+
const clonedTable = {
|
|
1242
1375
|
...v,
|
|
1243
1376
|
columns: clonedColumns,
|
|
1244
|
-
};
|
|
1377
|
+
} as AnyTable;
|
|
1378
|
+
|
|
1379
|
+
clonedTable["~standard"] = createTableStandardSchemaProps(clonedTable, validationClasses);
|
|
1380
|
+
clonedTable.validate = createTableValidator(clonedTable, validationClasses);
|
|
1381
|
+
|
|
1382
|
+
cloneTables[k] = clonedTable;
|
|
1245
1383
|
}
|
|
1246
1384
|
|
|
1247
|
-
|
|
1385
|
+
const clonedSchema: Schema<TTables> = {
|
|
1386
|
+
name: this.#name,
|
|
1248
1387
|
version,
|
|
1249
1388
|
tables: cloneTables as TTables,
|
|
1250
1389
|
operations: [...operations],
|
|
1251
1390
|
clone: () => {
|
|
1252
1391
|
throw new Error("Cannot clone during clone");
|
|
1253
1392
|
},
|
|
1254
|
-
}
|
|
1393
|
+
};
|
|
1394
|
+
|
|
1395
|
+
return new SchemaBuilder<TTables>(this.#name, clonedSchema).build();
|
|
1255
1396
|
},
|
|
1256
1397
|
};
|
|
1257
1398
|
|
|
@@ -1270,19 +1411,18 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
|
|
|
1270
1411
|
* Create a new schema with callback pattern.
|
|
1271
1412
|
*/
|
|
1272
1413
|
export function schema<const TTables extends Record<string, AnyTable> = {}>(
|
|
1414
|
+
name: string,
|
|
1273
1415
|
callback: (builder: SchemaBuilder<{}>) => SchemaBuilder<TTables>,
|
|
1274
1416
|
): Schema<TTables> {
|
|
1275
|
-
return callback(new SchemaBuilder()).build();
|
|
1417
|
+
return callback(new SchemaBuilder(name)).build();
|
|
1276
1418
|
}
|
|
1277
1419
|
|
|
1278
|
-
export function compileForeignKey(key: ForeignKey
|
|
1420
|
+
export function compileForeignKey(key: ForeignKey) {
|
|
1279
1421
|
return {
|
|
1280
1422
|
name: key.name,
|
|
1281
|
-
table:
|
|
1282
|
-
referencedTable:
|
|
1283
|
-
referencedColumns: key.referencedColumns.map((col) =>
|
|
1284
|
-
|
|
1285
|
-
),
|
|
1286
|
-
columns: key.columns.map((col) => (nameType === "sql" ? col.name : col.ormName)),
|
|
1423
|
+
table: key.table.name,
|
|
1424
|
+
referencedTable: key.referencedTable.name,
|
|
1425
|
+
referencedColumns: key.referencedColumns.map((col) => col.name),
|
|
1426
|
+
columns: key.columns.map((col) => col.name),
|
|
1287
1427
|
};
|
|
1288
1428
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { schema, idColumn, FragnoId } from "./create";
|
|
3
|
+
import { generateId } from "./generate-id";
|
|
4
|
+
|
|
5
|
+
describe("generateId", () => {
|
|
6
|
+
const testSchema = schema("test", (s) =>
|
|
7
|
+
s.addTable("users", (t) =>
|
|
8
|
+
t.addColumn("id", idColumn()).addColumn("email", "string").addColumn("name", "string"),
|
|
9
|
+
),
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
it("should generate a new FragnoId", () => {
|
|
13
|
+
const id = generateId(testSchema, "users");
|
|
14
|
+
|
|
15
|
+
expect(id).toBeInstanceOf(FragnoId);
|
|
16
|
+
expect(id.externalId).toBeDefined();
|
|
17
|
+
expect(typeof id.externalId).toBe("string");
|
|
18
|
+
expect(id.externalId.length).toBeGreaterThan(0);
|
|
19
|
+
expect(id.version).toBe(0);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("should generate unique IDs on each call", () => {
|
|
23
|
+
const id1 = generateId(testSchema, "users");
|
|
24
|
+
const id2 = generateId(testSchema, "users");
|
|
25
|
+
|
|
26
|
+
expect(id1.externalId).not.toBe(id2.externalId);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("should throw for non-existent table", () => {
|
|
30
|
+
expect(() => {
|
|
31
|
+
// @ts-expect-error - testing runtime error for non-existent table
|
|
32
|
+
generateId(testSchema, "nonexistent");
|
|
33
|
+
}).toThrow("Table nonexistent not found in schema");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should work with multiple tables", () => {
|
|
37
|
+
const multiTableSchema = schema("multitable", (s) =>
|
|
38
|
+
s
|
|
39
|
+
.addTable("users", (t) =>
|
|
40
|
+
t.addColumn("id", idColumn()).addColumn("email", "string").addColumn("name", "string"),
|
|
41
|
+
)
|
|
42
|
+
.addTable("posts", (t) =>
|
|
43
|
+
t
|
|
44
|
+
.addColumn("id", idColumn())
|
|
45
|
+
.addColumn("title", "string")
|
|
46
|
+
.addColumn("authorId", "string"),
|
|
47
|
+
),
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const userId = generateId(multiTableSchema, "users");
|
|
51
|
+
const postId = generateId(multiTableSchema, "posts");
|
|
52
|
+
|
|
53
|
+
expect(userId).toBeInstanceOf(FragnoId);
|
|
54
|
+
expect(postId).toBeInstanceOf(FragnoId);
|
|
55
|
+
expect(userId.externalId).not.toBe(postId.externalId);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { AnySchema } from "./create";
|
|
2
|
+
import { FragnoId } from "./create";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Generate a new ID for a table without creating a record.
|
|
6
|
+
* This is useful when you need to reference an ID before actually creating the record,
|
|
7
|
+
* or when you need to pass the ID to external services.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const userId = generateId(mySchema, "users");
|
|
12
|
+
* // Use userId in related records or pass to external services
|
|
13
|
+
* uow.create("users", { id: userId, name: "John" });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export function generateId<
|
|
17
|
+
TSchema extends AnySchema,
|
|
18
|
+
TableName extends keyof TSchema["tables"] & string,
|
|
19
|
+
>(schema: TSchema, tableName: TableName): FragnoId {
|
|
20
|
+
const tableSchema = schema.tables[tableName];
|
|
21
|
+
if (!tableSchema) {
|
|
22
|
+
throw new Error(`Table ${tableName} not found in schema`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const idColumn = tableSchema.getIdColumn();
|
|
26
|
+
const generated = idColumn.generateDefaultValue();
|
|
27
|
+
if (generated === undefined) {
|
|
28
|
+
throw new Error(`ID column ${idColumn.name} on table ${tableName} has no default generator`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (typeof generated !== "string") {
|
|
32
|
+
throw new Error(
|
|
33
|
+
`ID column ${idColumn.name} on table ${tableName} has no default generator that generates a string.`,
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return FragnoId.fromExternal(generated, 0);
|
|
38
|
+
}
|
|
@@ -131,7 +131,17 @@ describe("serialize", () => {
|
|
|
131
131
|
it("should convert string timestamps to Date", () => {
|
|
132
132
|
const timestampCol = column("timestamp");
|
|
133
133
|
const time = "2024-01-01 12:30:45.123";
|
|
134
|
-
|
|
134
|
+
const result = deserialize(time, timestampCol, "postgresql");
|
|
135
|
+
assert.instanceOf(result, Date);
|
|
136
|
+
expect(result.toISOString()).toBe("2024-01-01T12:30:45.123Z");
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("should treat timezone-less ISO timestamps as UTC", () => {
|
|
140
|
+
const timestampCol = column("timestamp");
|
|
141
|
+
const time = "2024-01-01T12:30:45.123";
|
|
142
|
+
const result = deserialize(time, timestampCol, "postgresql");
|
|
143
|
+
assert.instanceOf(result, Date);
|
|
144
|
+
expect(result.toISOString()).toBe("2024-01-01T12:30:45.123Z");
|
|
135
145
|
});
|
|
136
146
|
|
|
137
147
|
it("should convert ISO string timestamps to Date", () => {
|
|
@@ -262,7 +272,9 @@ describe("serialize", () => {
|
|
|
262
272
|
it("should convert string timestamps to Date", () => {
|
|
263
273
|
const timestampCol = column("timestamp");
|
|
264
274
|
const time = "2024-01-01 12:30:45.123";
|
|
265
|
-
|
|
275
|
+
const result = deserialize(time, timestampCol, "cockroachdb");
|
|
276
|
+
assert.instanceOf(result, Date);
|
|
277
|
+
expect(result.toISOString()).toBe("2024-01-01T12:30:45.123Z");
|
|
266
278
|
});
|
|
267
279
|
|
|
268
280
|
it("should convert date strings to Date", () => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SupportedDatabase } from "../../adapters/generic-sql/driver-config";
|
|
2
|
+
import type { SQLiteStorageMode } from "../../adapters/generic-sql/sqlite-storage";
|
|
2
3
|
import { PostgreSQLTypeMapper } from "./dialect/postgres";
|
|
3
4
|
import { MySQLTypeMapper } from "./dialect/mysql";
|
|
4
5
|
import { SQLiteTypeMapper } from "./dialect/sqlite";
|
|
@@ -10,16 +11,20 @@ import { SQLiteTypeMapper } from "./dialect/sqlite";
|
|
|
10
11
|
* (PostgreSQL, MySQL, or SQLite).
|
|
11
12
|
*
|
|
12
13
|
* @param database - The database type (sqlite, postgresql, or mysql)
|
|
14
|
+
* @param sqliteStorageMode - Optional SQLite storage mode override
|
|
13
15
|
* @returns Dialect-specific SQLTypeMapper instance
|
|
14
16
|
*/
|
|
15
|
-
export function createSQLTypeMapper(
|
|
17
|
+
export function createSQLTypeMapper(
|
|
18
|
+
database: SupportedDatabase,
|
|
19
|
+
sqliteStorageMode?: SQLiteStorageMode,
|
|
20
|
+
) {
|
|
16
21
|
switch (database) {
|
|
17
22
|
case "postgresql":
|
|
18
23
|
return new PostgreSQLTypeMapper(database);
|
|
19
24
|
case "mysql":
|
|
20
25
|
return new MySQLTypeMapper(database);
|
|
21
26
|
case "sqlite":
|
|
22
|
-
return new SQLiteTypeMapper(database);
|
|
27
|
+
return new SQLiteTypeMapper(database, sqliteStorageMode);
|
|
23
28
|
default: {
|
|
24
29
|
const exhaustiveCheck: never = database;
|
|
25
30
|
throw new Error(`Unsupported database type: ${exhaustiveCheck}`);
|