@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
|
@@ -0,0 +1,648 @@
|
|
|
1
|
+
import { FragnoId, FragnoReference } from "../../schema/create.js";
|
|
2
|
+
import { createSQLSerializer } from "../../query/serialize/create-sql-serializer.js";
|
|
3
|
+
import { ReferenceSubquery, encodeValues, encodeValuesWithDbDefaults } from "../../query/value-encoding.js";
|
|
4
|
+
import { createCursorFromRecord, decodeCursor } from "../../query/cursor.js";
|
|
5
|
+
import { buildCondition } from "../../query/condition-builder.js";
|
|
6
|
+
import { isDbNow } from "../../query/db-now.js";
|
|
7
|
+
import { SQLocalDriverConfig } from "../generic-sql/driver-config.js";
|
|
8
|
+
import { compareNormalizedValues } from "./value-comparison.js";
|
|
9
|
+
import { buildIndexKey, ensureNamespaceStore, normalizeIndexValue } from "./store.js";
|
|
10
|
+
import { resolveReferenceSubqueries } from "./reference-resolution.js";
|
|
11
|
+
import { evaluateCondition } from "./condition-evaluator.js";
|
|
12
|
+
|
|
13
|
+
//#region src/adapters/in-memory/in-memory-uow.ts
|
|
14
|
+
const getResolver = (schema, namespace, resolverFactory) => resolverFactory ? resolverFactory(schema, namespace ?? null) : void 0;
|
|
15
|
+
const getPhysicalTableName = (table, resolver) => resolver ? resolver.getTableName(table.name) : table.name;
|
|
16
|
+
const getPhysicalColumnName = (table, columnName, resolver) => resolver ? resolver.getColumnName(table.name, columnName) : columnName;
|
|
17
|
+
const cursorSerializer = createSQLSerializer(new SQLocalDriverConfig());
|
|
18
|
+
var VersionConflictError = class extends Error {
|
|
19
|
+
constructor(message) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = "VersionConflictError";
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const getNamespaceStore = (store, schema, namespace, resolver) => {
|
|
25
|
+
return ensureNamespaceStore(store, namespace ?? schema.name, schema, resolver);
|
|
26
|
+
};
|
|
27
|
+
const getTableStore = (namespaceStore, table, resolver) => {
|
|
28
|
+
const physicalTableName = getPhysicalTableName(table, resolver);
|
|
29
|
+
const tableStore = namespaceStore.tables.get(physicalTableName);
|
|
30
|
+
if (!tableStore) throw new Error(`Missing in-memory table store for "${physicalTableName}".`);
|
|
31
|
+
return tableStore;
|
|
32
|
+
};
|
|
33
|
+
const buildSelection = (table, select, _resolver) => {
|
|
34
|
+
const selection = /* @__PURE__ */ new Set();
|
|
35
|
+
if (!select || select === true) for (const columnName of Object.keys(table.columns)) selection.add(columnName);
|
|
36
|
+
else for (const columnName of select) selection.add(columnName);
|
|
37
|
+
selection.add("_internalId");
|
|
38
|
+
selection.add("_version");
|
|
39
|
+
return selection;
|
|
40
|
+
};
|
|
41
|
+
const selectRow = (row, table, select, resolver) => {
|
|
42
|
+
const selection = buildSelection(table, select, resolver);
|
|
43
|
+
const selected = {};
|
|
44
|
+
for (const columnName of selection) {
|
|
45
|
+
const physicalColumnName = getPhysicalColumnName(table, columnName, resolver);
|
|
46
|
+
if (Object.prototype.hasOwnProperty.call(row, physicalColumnName)) selected[columnName] = row[physicalColumnName];
|
|
47
|
+
}
|
|
48
|
+
return selected;
|
|
49
|
+
};
|
|
50
|
+
const isNullish = (value) => value === null || value === void 0;
|
|
51
|
+
const prefixSelection = (row, table, select, prefix, resolver) => {
|
|
52
|
+
const selected = selectRow(row, table, select, resolver);
|
|
53
|
+
const prefixed = {};
|
|
54
|
+
for (const key in selected) prefixed[`${prefix}:${key}`] = selected[key];
|
|
55
|
+
return prefixed;
|
|
56
|
+
};
|
|
57
|
+
const orderRows = (rows, orderBy, resolver) => {
|
|
58
|
+
if (!orderBy || orderBy.length === 0) return rows;
|
|
59
|
+
return rows.slice().sort((left, right) => {
|
|
60
|
+
for (const [column, direction] of orderBy) {
|
|
61
|
+
const columnName = resolver ? resolver.getColumnName(column.tableName, column.name) : column.name;
|
|
62
|
+
const comparison = compareNormalizedValues(normalizeIndexValue(left[columnName], column), normalizeIndexValue(right[columnName], column));
|
|
63
|
+
if (comparison !== 0) return direction === "asc" ? comparison : -comparison;
|
|
64
|
+
}
|
|
65
|
+
return 0;
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
const assertOrderByIndexOnly = (table, orderBy, resolver) => {
|
|
69
|
+
if (!orderBy || orderBy.length === 0) return;
|
|
70
|
+
const direction = orderBy[0][1];
|
|
71
|
+
if (!orderBy.every(([, dir]) => dir === direction)) throw new Error(`In-memory adapter only supports orderByIndex; mixed orderBy directions found on table "${table.name}".`);
|
|
72
|
+
const orderColumnNames = orderBy.map(([column]) => resolver ? resolver.getColumnName(table.name, column.name) : column.name);
|
|
73
|
+
const idColumnName = resolver ? resolver.getColumnName(table.name, table.getIdColumn().name) : table.getIdColumn().name;
|
|
74
|
+
if (orderColumnNames.length === 1 && orderColumnNames[0] === idColumnName) return;
|
|
75
|
+
for (const index of Object.values(table.indexes)) {
|
|
76
|
+
const indexColumnNames = index.columnNames.map((columnName) => resolver ? resolver.getColumnName(table.name, columnName) : columnName);
|
|
77
|
+
if (indexColumnNames.length !== orderColumnNames.length) continue;
|
|
78
|
+
let matches = true;
|
|
79
|
+
for (let i = 0; i < indexColumnNames.length; i += 1) if (indexColumnNames[i] !== orderColumnNames[i]) {
|
|
80
|
+
matches = false;
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
if (matches) return;
|
|
84
|
+
}
|
|
85
|
+
throw new Error(`In-memory adapter only supports orderByIndex; received orderBy on table "${table.name}".`);
|
|
86
|
+
};
|
|
87
|
+
const findJoinMatches = (parentRow, parentTable, join, namespaceStore, resolver, now = () => /* @__PURE__ */ new Date()) => {
|
|
88
|
+
const { relation, options } = join;
|
|
89
|
+
if (options === false) return [];
|
|
90
|
+
const targetTable = relation.table;
|
|
91
|
+
const targetStore = getTableStore(namespaceStore, targetTable, resolver);
|
|
92
|
+
const matches = [];
|
|
93
|
+
assertOrderByIndexOnly(targetTable, options.orderBy, resolver);
|
|
94
|
+
for (const row of targetStore.rows.values()) {
|
|
95
|
+
let matchesJoin = true;
|
|
96
|
+
for (const [left, right] of relation.on) {
|
|
97
|
+
const leftColumn = parentTable.columns[left];
|
|
98
|
+
if (!leftColumn) throw new Error(`Column "${left}" not found on table "${parentTable.name}".`);
|
|
99
|
+
const rightColumn = targetTable.columns[right];
|
|
100
|
+
if (!rightColumn) throw new Error(`Column "${right}" not found on table "${targetTable.name}".`);
|
|
101
|
+
const actualRight = rightColumn.role === "external-id" ? "_internalId" : right;
|
|
102
|
+
const actualRightColumn = targetTable.columns[actualRight];
|
|
103
|
+
if (!actualRightColumn) throw new Error(`Column "${actualRight}" not found on table "${targetTable.name}".`);
|
|
104
|
+
const leftValue = parentRow[getPhysicalColumnName(parentTable, left, resolver)];
|
|
105
|
+
const rightValue = row[getPhysicalColumnName(targetTable, actualRight, resolver)];
|
|
106
|
+
if (isNullish(leftValue) || isNullish(rightValue)) {
|
|
107
|
+
matchesJoin = false;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
if (compareNormalizedValues(normalizeIndexValue(leftValue, leftColumn), normalizeIndexValue(rightValue, actualRightColumn)) !== 0) {
|
|
111
|
+
matchesJoin = false;
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (!matchesJoin) continue;
|
|
116
|
+
if (options.where && !evaluateCondition(options.where, targetTable, row, namespaceStore, resolver, now)) continue;
|
|
117
|
+
matches.push(row);
|
|
118
|
+
}
|
|
119
|
+
const ordered = orderRows(matches, options.orderBy, resolver);
|
|
120
|
+
if (options.limit !== void 0) return ordered.slice(0, Math.max(0, options.limit));
|
|
121
|
+
return ordered;
|
|
122
|
+
};
|
|
123
|
+
const applyJoins = (baseOutput, parentRow, parentTable, joins, namespaceStore, resolver, now = () => /* @__PURE__ */ new Date(), parentPath = "") => {
|
|
124
|
+
if (!joins || joins.length === 0) return [baseOutput];
|
|
125
|
+
let outputs = [baseOutput];
|
|
126
|
+
for (const join of joins) {
|
|
127
|
+
if (join.options === false) continue;
|
|
128
|
+
const relationPath = parentPath ? `${parentPath}:${join.relation.name}` : join.relation.name;
|
|
129
|
+
const nextOutputs = [];
|
|
130
|
+
for (const currentOutput of outputs) {
|
|
131
|
+
const matches = findJoinMatches(parentRow, parentTable, join, namespaceStore, resolver, now);
|
|
132
|
+
if (matches.length === 0) {
|
|
133
|
+
nextOutputs.push(currentOutput);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
for (const matchRow of matches) {
|
|
137
|
+
const prefixed = prefixSelection(matchRow, join.relation.table, join.options.select, relationPath, resolver);
|
|
138
|
+
const merged = {
|
|
139
|
+
...currentOutput,
|
|
140
|
+
...prefixed
|
|
141
|
+
};
|
|
142
|
+
if (join.options.join && join.options.join.length > 0) nextOutputs.push(...applyJoins(merged, matchRow, join.relation.table, join.options.join, namespaceStore, resolver, now, relationPath));
|
|
143
|
+
else nextOutputs.push(merged);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
outputs = nextOutputs;
|
|
147
|
+
}
|
|
148
|
+
return outputs;
|
|
149
|
+
};
|
|
150
|
+
const getExternalId = (id) => typeof id === "string" ? id : id.externalId;
|
|
151
|
+
const getVersionToCheck = (id, checkVersion) => {
|
|
152
|
+
if (!checkVersion) return;
|
|
153
|
+
if (typeof id === "string") throw new Error("Cannot use checkVersion with a string ID. Version checking requires a FragnoId.");
|
|
154
|
+
return id.version;
|
|
155
|
+
};
|
|
156
|
+
const resolveReferenceSubqueriesOrThrow = (namespaceStore, table, encodedValues, resolver) => {
|
|
157
|
+
const resolved = resolveReferenceSubqueries(namespaceStore, encodedValues, resolver);
|
|
158
|
+
for (const [key, value] of Object.entries(encodedValues)) {
|
|
159
|
+
if (!(value instanceof ReferenceSubquery)) continue;
|
|
160
|
+
if (resolved[key] === null || resolved[key] === void 0) throw new Error(`Foreign key constraint violation on table "${table.name}" for column "${key}".`);
|
|
161
|
+
}
|
|
162
|
+
return resolved;
|
|
163
|
+
};
|
|
164
|
+
const getReferencedColumn = (table, columnName, resolver) => {
|
|
165
|
+
const column = table.columns[columnName];
|
|
166
|
+
if (!column) throw new Error(`Column "${columnName}" not found on table "${table.name}".`);
|
|
167
|
+
const actualName = column.role === "external-id" ? "_internalId" : columnName;
|
|
168
|
+
const actualColumn = table.columns[actualName];
|
|
169
|
+
if (!actualColumn) throw new Error(`Column "${actualName}" not found on table "${table.name}".`);
|
|
170
|
+
return {
|
|
171
|
+
name: getPhysicalColumnName(table, actualName, resolver),
|
|
172
|
+
column: actualColumn
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
const enforceOutgoingForeignKeys = (namespaceStore, table, row, columnsToCheck, resolver) => {
|
|
176
|
+
for (const relation of Object.values(table.relations)) {
|
|
177
|
+
if (relation.type !== "one") continue;
|
|
178
|
+
const localColumnNames = relation.on.map(([local]) => local);
|
|
179
|
+
if (columnsToCheck && !localColumnNames.some((name) => columnsToCheck.has(name))) continue;
|
|
180
|
+
if (localColumnNames.map((name) => row[getPhysicalColumnName(table, name, resolver)]).some((value) => value === null || value === void 0)) continue;
|
|
181
|
+
const referencedTable = relation.table;
|
|
182
|
+
const referencedStore = getTableStore(namespaceStore, referencedTable, resolver);
|
|
183
|
+
let foundMatch = false;
|
|
184
|
+
for (const targetRow of referencedStore.rows.values()) {
|
|
185
|
+
let matches = true;
|
|
186
|
+
for (const [localName, foreignName] of relation.on) {
|
|
187
|
+
if (!table.columns[localName]) throw new Error(`Column "${localName}" not found on table "${table.name}".`);
|
|
188
|
+
const { name: actualForeignName, column: foreignColumn } = getReferencedColumn(referencedTable, foreignName, resolver);
|
|
189
|
+
const localValue = row[getPhysicalColumnName(table, localName, resolver)];
|
|
190
|
+
const targetValue = targetRow[actualForeignName];
|
|
191
|
+
if (compareNormalizedValues(normalizeIndexValue(localValue, foreignColumn), normalizeIndexValue(targetValue, foreignColumn)) !== 0) {
|
|
192
|
+
matches = false;
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (matches) {
|
|
197
|
+
foundMatch = true;
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (!foundMatch) throw new Error(`Foreign key constraint violation on table "${table.name}" for relation "${relation.name}".`);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
const enforceNoIncomingForeignKeys = (namespaceStore, schema, table, row, resolver) => {
|
|
205
|
+
for (const sourceTable of Object.values(schema.tables)) for (const relation of Object.values(sourceTable.relations)) {
|
|
206
|
+
if (relation.type !== "one") continue;
|
|
207
|
+
if (relation.table.name !== table.name) continue;
|
|
208
|
+
const sourceStore = getTableStore(namespaceStore, sourceTable, resolver);
|
|
209
|
+
const targetColumnInfo = relation.on.map(([, foreignName]) => getReferencedColumn(table, foreignName, resolver));
|
|
210
|
+
const targetValues = targetColumnInfo.map(({ name }) => row[name]);
|
|
211
|
+
if (targetValues.some((value) => value === null || value === void 0)) continue;
|
|
212
|
+
for (const sourceRow of sourceStore.rows.values()) {
|
|
213
|
+
let matches = true;
|
|
214
|
+
for (let i = 0; i < relation.on.length; i += 1) {
|
|
215
|
+
const [localName] = relation.on[i];
|
|
216
|
+
const { column } = targetColumnInfo[i];
|
|
217
|
+
const localValue = sourceRow[getPhysicalColumnName(sourceTable, localName, resolver)];
|
|
218
|
+
if (localValue === null || localValue === void 0) {
|
|
219
|
+
matches = false;
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
if (compareNormalizedValues(normalizeIndexValue(localValue, column), normalizeIndexValue(targetValues[i], column)) !== 0) {
|
|
223
|
+
matches = false;
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (matches) throw new Error(`Foreign key constraint violation on table "${table.name}" for relation "${relation.name}".`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
const findRowByExternalId = (tableStore, table, externalId, resolver) => {
|
|
232
|
+
const idColumnName = getPhysicalColumnName(table, table.getIdColumn().name, resolver);
|
|
233
|
+
for (const [internalId, row] of tableStore.rows) if (row[idColumnName] === externalId) return {
|
|
234
|
+
internalId,
|
|
235
|
+
row
|
|
236
|
+
};
|
|
237
|
+
};
|
|
238
|
+
const resolveCursorValue = (value, column) => {
|
|
239
|
+
if (value && typeof value === "object") {
|
|
240
|
+
const maybeExternalId = value.externalId;
|
|
241
|
+
const maybeInternalId = value.internalId;
|
|
242
|
+
if (typeof maybeExternalId === "string") {
|
|
243
|
+
if (column.role === "external-id") return maybeExternalId;
|
|
244
|
+
if ((column.role === "internal-id" || column.role === "reference") && maybeInternalId) return typeof maybeInternalId === "string" ? BigInt(maybeInternalId) : maybeInternalId;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return value;
|
|
248
|
+
};
|
|
249
|
+
const buildCursorKey = (cursor, table, columnNames, resolver) => {
|
|
250
|
+
if (!cursor) return;
|
|
251
|
+
const cursorObj = typeof cursor === "string" ? decodeCursor(cursor) : cursor;
|
|
252
|
+
const columnMap = resolver ? resolver.getColumnNameMap(table) : void 0;
|
|
253
|
+
return columnNames.map((columnName) => {
|
|
254
|
+
const logicalName = columnMap?.[columnName] ?? columnName;
|
|
255
|
+
const column = table.columns[logicalName];
|
|
256
|
+
if (!column) throw new Error(`Column "${logicalName}" not found on table "${table.name}".`);
|
|
257
|
+
const rawValue = resolveCursorValue(cursorObj.indexValues[column.name], column);
|
|
258
|
+
if (rawValue === void 0) return;
|
|
259
|
+
return normalizeIndexValue(cursorSerializer.deserialize(rawValue, column), column);
|
|
260
|
+
});
|
|
261
|
+
};
|
|
262
|
+
const findRows = (op, namespaceStore, tableStore, resolver, now = () => /* @__PURE__ */ new Date()) => {
|
|
263
|
+
const table = op.table;
|
|
264
|
+
const orderByIndex = op.options.orderByIndex;
|
|
265
|
+
const orderIndexName = orderByIndex?.indexName ?? op.indexName;
|
|
266
|
+
const orderIndex = tableStore.indexes.get(orderIndexName);
|
|
267
|
+
if (!orderIndex) throw new Error(`Missing in-memory index "${orderIndexName}" on table "${table.name}".`);
|
|
268
|
+
const direction = orderByIndex?.direction ?? "asc";
|
|
269
|
+
const afterKey = buildCursorKey(op.options.after, table, orderIndex.definition.columnNames, resolver);
|
|
270
|
+
const beforeKey = buildCursorKey(op.options.before, table, orderIndex.definition.columnNames, resolver);
|
|
271
|
+
const limit = op.withCursor && op.options.pageSize !== void 0 ? op.options.pageSize + 1 : op.options.pageSize;
|
|
272
|
+
const scanOptions = {
|
|
273
|
+
direction,
|
|
274
|
+
limit,
|
|
275
|
+
start: void 0,
|
|
276
|
+
startInclusive: true,
|
|
277
|
+
end: void 0,
|
|
278
|
+
endInclusive: true
|
|
279
|
+
};
|
|
280
|
+
if (afterKey) if (direction === "asc") {
|
|
281
|
+
scanOptions.start = afterKey;
|
|
282
|
+
scanOptions.startInclusive = false;
|
|
283
|
+
} else {
|
|
284
|
+
scanOptions.end = afterKey;
|
|
285
|
+
scanOptions.endInclusive = false;
|
|
286
|
+
}
|
|
287
|
+
if (beforeKey) if (direction === "asc") {
|
|
288
|
+
scanOptions.end = beforeKey;
|
|
289
|
+
scanOptions.endInclusive = false;
|
|
290
|
+
} else {
|
|
291
|
+
scanOptions.start = beforeKey;
|
|
292
|
+
scanOptions.startInclusive = false;
|
|
293
|
+
}
|
|
294
|
+
const entries = orderIndex.index.scan(scanOptions);
|
|
295
|
+
const whereResult = op.options.where ? buildCondition(table.columns, op.options.where) : void 0;
|
|
296
|
+
if (whereResult === false) return [];
|
|
297
|
+
const condition = whereResult === true ? void 0 : whereResult;
|
|
298
|
+
const results = [];
|
|
299
|
+
for (const entry of entries) {
|
|
300
|
+
const row = tableStore.rows.get(entry.value);
|
|
301
|
+
if (!row) continue;
|
|
302
|
+
if (condition && !evaluateCondition(condition, table, row, namespaceStore, resolver, now)) continue;
|
|
303
|
+
const baseOutput = selectRow(row, table, op.options.select, resolver);
|
|
304
|
+
if (op.options.joins && op.options.joins.length > 0) {
|
|
305
|
+
const joined = applyJoins(baseOutput, row, table, op.options.joins, namespaceStore, resolver, now);
|
|
306
|
+
for (const joinedRow of joined) {
|
|
307
|
+
results.push(joinedRow);
|
|
308
|
+
if (limit !== void 0 && results.length >= limit) break;
|
|
309
|
+
}
|
|
310
|
+
} else results.push(baseOutput);
|
|
311
|
+
if (limit !== void 0 && results.length >= limit) break;
|
|
312
|
+
}
|
|
313
|
+
return results;
|
|
314
|
+
};
|
|
315
|
+
const countRows = (op, namespaceStore, tableStore, resolver, now = () => /* @__PURE__ */ new Date()) => {
|
|
316
|
+
const table = op.table;
|
|
317
|
+
const whereResult = op.options.where ? buildCondition(table.columns, op.options.where) : void 0;
|
|
318
|
+
if (whereResult === false) return 0;
|
|
319
|
+
const condition = whereResult === true ? void 0 : whereResult;
|
|
320
|
+
let count = 0;
|
|
321
|
+
for (const row of tableStore.rows.values()) {
|
|
322
|
+
if (condition && !evaluateCondition(condition, table, row, namespaceStore, resolver, now)) continue;
|
|
323
|
+
count += 1;
|
|
324
|
+
}
|
|
325
|
+
return count;
|
|
326
|
+
};
|
|
327
|
+
const resolveDbNowValue = (value, options) => isDbNow(value) ? options.clock.now() : value;
|
|
328
|
+
const createRow = (op, namespaceStore, tableStore, options, resolver) => {
|
|
329
|
+
const table = op.schema.tables[op.table];
|
|
330
|
+
if (!table) throw new Error(`Invalid table name ${op.table}.`);
|
|
331
|
+
const encoded = encodeValuesWithDbDefaults(op.values, table, {
|
|
332
|
+
now: options.clock.now,
|
|
333
|
+
createId: options.idGenerator
|
|
334
|
+
}, resolver);
|
|
335
|
+
const resolvedValues = options.enforceConstraints ? resolveReferenceSubqueriesOrThrow(namespaceStore, table, encoded, resolver) : resolveReferenceSubqueries(namespaceStore, encoded, resolver);
|
|
336
|
+
const row = {};
|
|
337
|
+
for (const columnName of Object.keys(table.columns)) {
|
|
338
|
+
const column = table.columns[columnName];
|
|
339
|
+
if (!column || column.role === "internal-id") continue;
|
|
340
|
+
const physicalColumnName = getPhysicalColumnName(table, column.name, resolver);
|
|
341
|
+
const value = resolvedValues[physicalColumnName];
|
|
342
|
+
if (value === void 0) {
|
|
343
|
+
if (column.isNullable) {
|
|
344
|
+
row[physicalColumnName] = null;
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
if (column.role === "version") {
|
|
348
|
+
row[physicalColumnName] = 0;
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
throw new Error(`Missing required value for column "${column.name}".`);
|
|
352
|
+
}
|
|
353
|
+
row[physicalColumnName] = resolveDbNowValue(value, options);
|
|
354
|
+
}
|
|
355
|
+
const internalId = options.internalIdGeneratorProvided ? options.internalIdGenerator() : tableStore.nextInternalId;
|
|
356
|
+
if (!options.internalIdGeneratorProvided) tableStore.nextInternalId += 1n;
|
|
357
|
+
const internalIdColumnName = getPhysicalColumnName(table, "_internalId", resolver);
|
|
358
|
+
const versionColumnName = getPhysicalColumnName(table, "_version", resolver);
|
|
359
|
+
row[internalIdColumnName] = internalId;
|
|
360
|
+
row[versionColumnName] = row[versionColumnName] ?? 0;
|
|
361
|
+
if (options.enforceConstraints) enforceOutgoingForeignKeys(namespaceStore, table, row, void 0, resolver);
|
|
362
|
+
tableStore.rows.set(internalId, row);
|
|
363
|
+
for (const indexStore of tableStore.indexes.values()) {
|
|
364
|
+
const key = buildIndexKey(table, indexStore.definition, row, resolver);
|
|
365
|
+
indexStore.index.insert(key, internalId, { enforceUnique: options.enforceConstraints });
|
|
366
|
+
}
|
|
367
|
+
return internalId;
|
|
368
|
+
};
|
|
369
|
+
const updateRow = (op, namespaceStore, tableStore, options, resolver) => {
|
|
370
|
+
const table = op.schema.tables[op.table];
|
|
371
|
+
if (!table) throw new Error(`Invalid table name ${op.table}.`);
|
|
372
|
+
const externalId = getExternalId(op.id);
|
|
373
|
+
const versionToCheck = getVersionToCheck(op.id, op.checkVersion);
|
|
374
|
+
const existing = findRowByExternalId(tableStore, table, externalId, resolver);
|
|
375
|
+
if (!existing) {
|
|
376
|
+
if (versionToCheck !== void 0) throw new VersionConflictError(`Version conflict: row "${externalId}" not found.`);
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
const versionColumnName = getPhysicalColumnName(table, "_version", resolver);
|
|
380
|
+
const currentVersion = Number(existing.row[versionColumnName] ?? 0);
|
|
381
|
+
if (versionToCheck !== void 0 && currentVersion !== versionToCheck) throw new VersionConflictError(`Version conflict: row "${externalId}" has changed.`);
|
|
382
|
+
const encoded = encodeValues(op.set, table, false, {}, resolver);
|
|
383
|
+
const resolvedValues = options.enforceConstraints ? resolveReferenceSubqueriesOrThrow(namespaceStore, table, encoded, resolver) : resolveReferenceSubqueries(namespaceStore, encoded, resolver);
|
|
384
|
+
const resolvedUpdateValues = {};
|
|
385
|
+
for (const [columnName, value] of Object.entries(resolvedValues)) resolvedUpdateValues[columnName] = resolveDbNowValue(value, options);
|
|
386
|
+
const updatedRow = {
|
|
387
|
+
...existing.row,
|
|
388
|
+
...resolvedUpdateValues
|
|
389
|
+
};
|
|
390
|
+
updatedRow[versionColumnName] = currentVersion + 1;
|
|
391
|
+
if (options.enforceConstraints) enforceOutgoingForeignKeys(namespaceStore, table, updatedRow, new Set(Object.keys(resolvedValues)), resolver);
|
|
392
|
+
const indexUpdates = Array.from(tableStore.indexes.values()).map((indexStore) => ({
|
|
393
|
+
indexStore,
|
|
394
|
+
oldKey: buildIndexKey(table, indexStore.definition, existing.row, resolver),
|
|
395
|
+
newKey: buildIndexKey(table, indexStore.definition, updatedRow, resolver)
|
|
396
|
+
}));
|
|
397
|
+
const applied = [];
|
|
398
|
+
try {
|
|
399
|
+
for (const update of indexUpdates) {
|
|
400
|
+
update.indexStore.index.update(update.oldKey, update.newKey, existing.internalId, { enforceUnique: options.enforceConstraints });
|
|
401
|
+
applied.push(update);
|
|
402
|
+
}
|
|
403
|
+
} catch (error) {
|
|
404
|
+
for (const update of applied.reverse()) update.indexStore.index.update(update.newKey, update.oldKey, existing.internalId, { enforceUnique: options.enforceConstraints });
|
|
405
|
+
throw error;
|
|
406
|
+
}
|
|
407
|
+
tableStore.rows.set(existing.internalId, updatedRow);
|
|
408
|
+
return () => {
|
|
409
|
+
for (const update of indexUpdates.slice().reverse()) update.indexStore.index.update(update.newKey, update.oldKey, existing.internalId, { enforceUnique: options.enforceConstraints });
|
|
410
|
+
tableStore.rows.set(existing.internalId, existing.row);
|
|
411
|
+
};
|
|
412
|
+
};
|
|
413
|
+
const deleteRow = (op, namespaceStore, tableStore, table, options, resolver) => {
|
|
414
|
+
const externalId = getExternalId(op.id);
|
|
415
|
+
const versionToCheck = getVersionToCheck(op.id, op.checkVersion);
|
|
416
|
+
const existing = findRowByExternalId(tableStore, table, externalId, resolver);
|
|
417
|
+
if (!existing) {
|
|
418
|
+
if (versionToCheck !== void 0) throw new VersionConflictError(`Version conflict: row "${externalId}" not found.`);
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
const versionColumnName = getPhysicalColumnName(table, "_version", resolver);
|
|
422
|
+
const currentVersion = Number(existing.row[versionColumnName] ?? 0);
|
|
423
|
+
if (versionToCheck !== void 0 && currentVersion !== versionToCheck) throw new VersionConflictError(`Version conflict: row "${externalId}" has changed.`);
|
|
424
|
+
if (options.enforceConstraints) enforceNoIncomingForeignKeys(namespaceStore, op.schema, table, existing.row, resolver);
|
|
425
|
+
const indexEntries = Array.from(tableStore.indexes.values()).map((indexStore) => ({
|
|
426
|
+
indexStore,
|
|
427
|
+
key: buildIndexKey(table, indexStore.definition, existing.row, resolver)
|
|
428
|
+
}));
|
|
429
|
+
const removedEntries = [];
|
|
430
|
+
for (const entry of indexEntries) {
|
|
431
|
+
if (!entry.indexStore.index.remove(entry.key, existing.internalId)) {
|
|
432
|
+
for (const removedEntry of removedEntries) removedEntry.indexStore.index.insert(removedEntry.key, existing.internalId, { enforceUnique: options.enforceConstraints });
|
|
433
|
+
throw new Error("Failed to remove index entry during delete.");
|
|
434
|
+
}
|
|
435
|
+
removedEntries.push(entry);
|
|
436
|
+
}
|
|
437
|
+
tableStore.rows.delete(existing.internalId);
|
|
438
|
+
return () => {
|
|
439
|
+
tableStore.rows.set(existing.internalId, existing.row);
|
|
440
|
+
for (const entry of indexEntries) entry.indexStore.index.insert(entry.key, existing.internalId, { enforceUnique: options.enforceConstraints });
|
|
441
|
+
};
|
|
442
|
+
};
|
|
443
|
+
const checkRow = (op, tableStore, table, resolver) => {
|
|
444
|
+
const existing = findRowByExternalId(tableStore, table, op.id.externalId, resolver);
|
|
445
|
+
if (!existing) throw new VersionConflictError(`Version conflict: row "${op.id.externalId}" not found.`);
|
|
446
|
+
const versionColumnName = getPhysicalColumnName(table, "_version", resolver);
|
|
447
|
+
if (Number(existing.row[versionColumnName] ?? 0) !== op.id.version) throw new VersionConflictError(`Version conflict: row "${op.id.externalId}" has changed.`);
|
|
448
|
+
};
|
|
449
|
+
const createInMemoryUowCompiler = () => ({
|
|
450
|
+
compileRetrievalOperation(op) {
|
|
451
|
+
return op;
|
|
452
|
+
},
|
|
453
|
+
compileMutationOperation(op) {
|
|
454
|
+
return {
|
|
455
|
+
query: op,
|
|
456
|
+
operation: op,
|
|
457
|
+
op: op.type,
|
|
458
|
+
expectedAffectedRows: null,
|
|
459
|
+
expectedReturnedRows: null
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
const createInMemoryUowExecutor = (store, options, resolverFactory) => ({
|
|
464
|
+
async executeRetrievalPhase(retrievalBatch) {
|
|
465
|
+
const results = [];
|
|
466
|
+
for (const compiled of retrievalBatch) {
|
|
467
|
+
if (compiled.type === "count" || compiled.type === "find") {
|
|
468
|
+
const resolver = getResolver(compiled.schema, compiled.namespace, resolverFactory);
|
|
469
|
+
const namespaceStore = getNamespaceStore(store, compiled.schema, compiled.namespace, resolver);
|
|
470
|
+
const tableStore = getTableStore(namespaceStore, compiled.table, resolver);
|
|
471
|
+
if (compiled.type === "find") results.push(findRows(compiled, namespaceStore, tableStore, resolver, options.clock.now));
|
|
472
|
+
else results.push([{ count: countRows(compiled, namespaceStore, tableStore, resolver, options.clock.now) }]);
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
throw new Error(`Unsupported in-memory retrieval operation: ${compiled.type}`);
|
|
476
|
+
}
|
|
477
|
+
return results;
|
|
478
|
+
},
|
|
479
|
+
async executeMutationPhase(mutationBatch) {
|
|
480
|
+
const createdInternalIds = [];
|
|
481
|
+
const rollbackActions = [];
|
|
482
|
+
try {
|
|
483
|
+
for (const compiled of mutationBatch) {
|
|
484
|
+
const operation = compiled.query;
|
|
485
|
+
if (operation.type === "create") {
|
|
486
|
+
const resolver = getResolver(operation.schema, operation.namespace, resolverFactory);
|
|
487
|
+
const namespaceStore = getNamespaceStore(store, operation.schema, operation.namespace, resolver);
|
|
488
|
+
const table = operation.schema.tables[operation.table];
|
|
489
|
+
if (!table) throw new Error(`Invalid table name ${operation.table}.`);
|
|
490
|
+
const tableStore = getTableStore(namespaceStore, table, resolver);
|
|
491
|
+
const previousInternalId = tableStore.nextInternalId;
|
|
492
|
+
const internalId = createRow(operation, namespaceStore, tableStore, options, resolver);
|
|
493
|
+
createdInternalIds.push(internalId);
|
|
494
|
+
rollbackActions.push(() => {
|
|
495
|
+
const row = tableStore.rows.get(internalId);
|
|
496
|
+
if (row) {
|
|
497
|
+
for (const indexStore of tableStore.indexes.values()) {
|
|
498
|
+
const key = buildIndexKey(table, indexStore.definition, row, resolver);
|
|
499
|
+
indexStore.index.remove(key, internalId);
|
|
500
|
+
}
|
|
501
|
+
tableStore.rows.delete(internalId);
|
|
502
|
+
}
|
|
503
|
+
tableStore.nextInternalId = previousInternalId;
|
|
504
|
+
});
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
if (operation.type === "update") {
|
|
508
|
+
const resolver = getResolver(operation.schema, operation.namespace, resolverFactory);
|
|
509
|
+
const namespaceStore = getNamespaceStore(store, operation.schema, operation.namespace, resolver);
|
|
510
|
+
const table = operation.schema.tables[operation.table];
|
|
511
|
+
if (!table) throw new Error(`Invalid table name ${operation.table}.`);
|
|
512
|
+
const rollback = updateRow(operation, namespaceStore, getTableStore(namespaceStore, table, resolver), options, resolver);
|
|
513
|
+
if (rollback) rollbackActions.push(rollback);
|
|
514
|
+
continue;
|
|
515
|
+
}
|
|
516
|
+
if (operation.type === "delete") {
|
|
517
|
+
const resolver = getResolver(operation.schema, operation.namespace, resolverFactory);
|
|
518
|
+
const namespaceStore = getNamespaceStore(store, operation.schema, operation.namespace, resolver);
|
|
519
|
+
const table = operation.schema.tables[operation.table];
|
|
520
|
+
if (!table) throw new Error(`Invalid table name ${operation.table}.`);
|
|
521
|
+
const rollback = deleteRow(operation, namespaceStore, getTableStore(namespaceStore, table, resolver), table, options, resolver);
|
|
522
|
+
if (rollback) rollbackActions.push(rollback);
|
|
523
|
+
continue;
|
|
524
|
+
}
|
|
525
|
+
if (operation.type === "check") {
|
|
526
|
+
const resolver = getResolver(operation.schema, operation.namespace, resolverFactory);
|
|
527
|
+
const namespaceStore = getNamespaceStore(store, operation.schema, operation.namespace, resolver);
|
|
528
|
+
const table = operation.schema.tables[operation.table];
|
|
529
|
+
if (!table) throw new Error(`Invalid table name ${operation.table}.`);
|
|
530
|
+
checkRow(operation, getTableStore(namespaceStore, table, resolver), table, resolver);
|
|
531
|
+
continue;
|
|
532
|
+
}
|
|
533
|
+
throw new Error(`Unsupported in-memory mutation "${operation.type}".`);
|
|
534
|
+
}
|
|
535
|
+
} catch (error) {
|
|
536
|
+
for (const rollback of rollbackActions.reverse()) rollback();
|
|
537
|
+
if (error instanceof VersionConflictError) return { success: false };
|
|
538
|
+
throw error;
|
|
539
|
+
}
|
|
540
|
+
return {
|
|
541
|
+
success: true,
|
|
542
|
+
createdInternalIds
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
var InMemoryUowDecoder = class {
|
|
547
|
+
#resolverFactory;
|
|
548
|
+
constructor(resolverFactory) {
|
|
549
|
+
this.#resolverFactory = resolverFactory;
|
|
550
|
+
}
|
|
551
|
+
decode(rawResults, operations) {
|
|
552
|
+
if (rawResults.length !== operations.length) throw new Error("rawResults and ops must have the same length");
|
|
553
|
+
return rawResults.map((result, index) => {
|
|
554
|
+
const op = operations[index];
|
|
555
|
+
if (!op) throw new Error("op must be defined");
|
|
556
|
+
if (op.type === "count") return this.decodeCount(result);
|
|
557
|
+
const resolver = getResolver(op.schema, op.namespace, this.#resolverFactory);
|
|
558
|
+
const decodedRows = result.map((row) => this.decodeRow(row, op.table, resolver));
|
|
559
|
+
if (op.withCursor) return this.decodeCursorResult(decodedRows, op.table, op);
|
|
560
|
+
return decodedRows;
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
decodeCount(result) {
|
|
564
|
+
if (typeof result === "number") return result;
|
|
565
|
+
const first = result[0];
|
|
566
|
+
if (!first) return 0;
|
|
567
|
+
const count = Number(first.count);
|
|
568
|
+
if (Number.isNaN(count)) throw new Error(`Unexpected result for count, received: ${first.count}`);
|
|
569
|
+
return count;
|
|
570
|
+
}
|
|
571
|
+
decodeRow(row, table, resolver) {
|
|
572
|
+
const output = {};
|
|
573
|
+
const columnValues = {};
|
|
574
|
+
const relationData = {};
|
|
575
|
+
const columnMap = resolver ? resolver.getColumnNameMap(table) : void 0;
|
|
576
|
+
for (const key in row) {
|
|
577
|
+
const colonIndex = key.indexOf(":");
|
|
578
|
+
if (colonIndex === -1) {
|
|
579
|
+
const logicalName = columnMap?.[key] ?? key;
|
|
580
|
+
if (table.columns[logicalName]) columnValues[logicalName] = row[key];
|
|
581
|
+
continue;
|
|
582
|
+
}
|
|
583
|
+
const relationName = key.slice(0, colonIndex);
|
|
584
|
+
const remainder = key.slice(colonIndex + 1);
|
|
585
|
+
if (!table.relations[relationName]) continue;
|
|
586
|
+
relationData[relationName] ??= {};
|
|
587
|
+
relationData[relationName][remainder] = row[key];
|
|
588
|
+
}
|
|
589
|
+
for (const relationName in relationData) {
|
|
590
|
+
const relation = table.relations[relationName];
|
|
591
|
+
if (!relation) continue;
|
|
592
|
+
output[relationName] = this.decodeRow(relationData[relationName], relation.table, resolver);
|
|
593
|
+
}
|
|
594
|
+
for (const key in columnValues) {
|
|
595
|
+
const column = table.columns[key];
|
|
596
|
+
if (!column) continue;
|
|
597
|
+
if (column.isHidden) continue;
|
|
598
|
+
if (column.role === "external-id" && columnValues["_internalId"] !== void 0) {
|
|
599
|
+
output[key] = new FragnoId({
|
|
600
|
+
externalId: columnValues[key],
|
|
601
|
+
internalId: columnValues["_internalId"],
|
|
602
|
+
version: columnValues["_version"]
|
|
603
|
+
});
|
|
604
|
+
continue;
|
|
605
|
+
}
|
|
606
|
+
if (column.role === "reference") {
|
|
607
|
+
const value = columnValues[key];
|
|
608
|
+
output[key] = value === null || value === void 0 ? null : FragnoReference.fromInternal(value);
|
|
609
|
+
continue;
|
|
610
|
+
}
|
|
611
|
+
output[key] = columnValues[key];
|
|
612
|
+
}
|
|
613
|
+
return output;
|
|
614
|
+
}
|
|
615
|
+
decodeCursorResult(decodedRows, table, operation) {
|
|
616
|
+
let cursor;
|
|
617
|
+
let hasNextPage = false;
|
|
618
|
+
let items = decodedRows;
|
|
619
|
+
if (operation.options.pageSize && operation.options.pageSize > 0 && decodedRows.length > operation.options.pageSize) {
|
|
620
|
+
hasNextPage = true;
|
|
621
|
+
items = decodedRows.slice(0, operation.options.pageSize);
|
|
622
|
+
if (operation.options.orderByIndex) {
|
|
623
|
+
const lastItem = items[items.length - 1];
|
|
624
|
+
const indexName = operation.options.orderByIndex.indexName;
|
|
625
|
+
let indexColumns;
|
|
626
|
+
if (indexName === "_primary") indexColumns = [table.getIdColumn()];
|
|
627
|
+
else {
|
|
628
|
+
const index = table.indexes[indexName];
|
|
629
|
+
if (index) indexColumns = index.columns;
|
|
630
|
+
}
|
|
631
|
+
if (indexColumns && lastItem) cursor = createCursorFromRecord(lastItem, indexColumns, {
|
|
632
|
+
indexName: operation.options.orderByIndex.indexName,
|
|
633
|
+
orderDirection: operation.options.orderByIndex.direction,
|
|
634
|
+
pageSize: operation.options.pageSize
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return {
|
|
639
|
+
items,
|
|
640
|
+
cursor,
|
|
641
|
+
hasNextPage
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
};
|
|
645
|
+
|
|
646
|
+
//#endregion
|
|
647
|
+
export { InMemoryUowDecoder, createInMemoryUowCompiler, createInMemoryUowExecutor };
|
|
648
|
+
//# sourceMappingURL=in-memory-uow.js.map
|