@fragno-dev/db 0.2.2 → 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 +202 -140
- package/CHANGELOG.md +35 -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 +39 -29
- package/dist/adapters/generic-sql/query/where-builder.js.map +1 -1
- package/dist/adapters/generic-sql/sqlite-storage.d.ts +13 -0
- package/dist/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
- package/dist/adapters/generic-sql/sqlite-storage.js +15 -0
- package/dist/adapters/generic-sql/sqlite-storage.js.map +1 -0
- package/dist/adapters/generic-sql/uow-decoder.js +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 +18 -7
- package/dist/db-fragment-definition-builder.d.ts.map +1 -1
- package/dist/db-fragment-definition-builder.js +116 -54
- 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 +79 -2
- package/dist/fragments/internal-fragment.d.ts.map +1 -1
- package/dist/fragments/internal-fragment.js +150 -32
- 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 +42 -1
- package/dist/hooks/hooks.d.ts.map +1 -1
- package/dist/hooks/hooks.js +72 -6
- 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 +15 -8
- 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.map +1 -1
- package/dist/query/unit-of-work/execute-unit-of-work.js +11 -6
- 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 +50 -14
- package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
- package/dist/query/unit-of-work/unit-of-work.js +86 -5
- package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
- package/dist/query/value-decoding.js +9 -6
- package/dist/query/value-decoding.js.map +1 -1
- package/dist/query/value-encoding.js +29 -9
- package/dist/query/value-encoding.js.map +1 -1
- package/dist/schema/create.d.ts +38 -14
- package/dist/schema/create.d.ts.map +1 -1
- package/dist/schema/create.js +81 -42
- package/dist/schema/create.js.map +1 -1
- package/dist/schema/generate-id.js +2 -2
- package/dist/schema/generate-id.js.map +1 -1
- package/dist/schema/type-conversion/create-sql-type-mapper.js +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} +10 -10
- package/src/adapters/{drizzle/drizzle-adapter-sqlite3.test.ts → generic-sql/sql-adapter-sqlite3-uow.test.ts} +7 -7
- 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 +30 -12
- package/src/db-fragment-definition-builder.ts +142 -73
- package/src/db-fragment-instantiator.test.ts +105 -13
- package/src/db-fragment-integration.test.ts +9 -7
- 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 +458 -8
- package/src/fragments/internal-fragment.ts +322 -63
- 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 +165 -5
- package/src/hooks/hooks.ts +197 -9
- 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 +64 -26
- 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 +25 -1
- package/src/query/unit-of-work/execute-unit-of-work.ts +25 -8
- package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +12 -12
- 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 +168 -37
- package/src/query/unit-of-work/unit-of-work.ts +203 -18
- 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 +185 -47
- package/src/schema/generate-id.test.ts +2 -2
- package/src/schema/generate-id.ts +2 -2
- 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
|
@@ -161,7 +161,7 @@ export type RetrievalOperation<
|
|
|
161
161
|
| {
|
|
162
162
|
type: "find";
|
|
163
163
|
schema: TSchema;
|
|
164
|
-
namespace?: string;
|
|
164
|
+
namespace?: string | null;
|
|
165
165
|
table: TTable;
|
|
166
166
|
indexName: string;
|
|
167
167
|
options: FindOptions<TTable, SelectClause<TTable>>;
|
|
@@ -171,7 +171,7 @@ export type RetrievalOperation<
|
|
|
171
171
|
| {
|
|
172
172
|
type: "count";
|
|
173
173
|
schema: TSchema;
|
|
174
|
-
namespace?: string;
|
|
174
|
+
namespace?: string | null;
|
|
175
175
|
table: TTable;
|
|
176
176
|
indexName: string;
|
|
177
177
|
options: Pick<FindOptions<TTable>, "where" | "useIndex">;
|
|
@@ -187,7 +187,7 @@ export type MutationOperation<
|
|
|
187
187
|
| {
|
|
188
188
|
type: "update";
|
|
189
189
|
schema: TSchema;
|
|
190
|
-
namespace?: string;
|
|
190
|
+
namespace?: string | null;
|
|
191
191
|
table: TTable["name"];
|
|
192
192
|
id: FragnoId | string;
|
|
193
193
|
checkVersion: boolean;
|
|
@@ -196,7 +196,7 @@ export type MutationOperation<
|
|
|
196
196
|
| {
|
|
197
197
|
type: "create";
|
|
198
198
|
schema: TSchema;
|
|
199
|
-
namespace?: string;
|
|
199
|
+
namespace?: string | null;
|
|
200
200
|
table: TTable["name"];
|
|
201
201
|
values: TableToInsertValues<TTable>;
|
|
202
202
|
generatedExternalId: string;
|
|
@@ -204,7 +204,7 @@ export type MutationOperation<
|
|
|
204
204
|
| {
|
|
205
205
|
type: "delete";
|
|
206
206
|
schema: TSchema;
|
|
207
|
-
namespace?: string;
|
|
207
|
+
namespace?: string | null;
|
|
208
208
|
table: TTable["name"];
|
|
209
209
|
id: FragnoId | string;
|
|
210
210
|
checkVersion: boolean;
|
|
@@ -212,7 +212,7 @@ export type MutationOperation<
|
|
|
212
212
|
| {
|
|
213
213
|
type: "check";
|
|
214
214
|
schema: TSchema;
|
|
215
|
-
namespace?: string;
|
|
215
|
+
namespace?: string | null;
|
|
216
216
|
table: TTable["name"];
|
|
217
217
|
id: FragnoId;
|
|
218
218
|
};
|
|
@@ -222,6 +222,14 @@ export type MutationOperation<
|
|
|
222
222
|
*/
|
|
223
223
|
export interface CompiledMutation<TOutput> {
|
|
224
224
|
query: TOutput;
|
|
225
|
+
/**
|
|
226
|
+
* Original mutation operation for execution metadata (e.g., outbox payloads).
|
|
227
|
+
*/
|
|
228
|
+
operation?: MutationOperation<AnySchema>;
|
|
229
|
+
/**
|
|
230
|
+
* Idempotency key for the Unit of Work that produced this mutation.
|
|
231
|
+
*/
|
|
232
|
+
uowId?: string;
|
|
225
233
|
/**
|
|
226
234
|
* The type of mutation operation (create, update, delete, or check).
|
|
227
235
|
*/
|
|
@@ -832,7 +840,7 @@ export function buildJoinIndexed<TTable extends AnyTable, TJoinOut>(
|
|
|
832
840
|
|
|
833
841
|
builder[name] = (builderFn?: (b: JoinFindBuilder<AnyTable>) => JoinFindBuilder<AnyTable>) => {
|
|
834
842
|
// Create join builder for this relation's table
|
|
835
|
-
const joinBuilder = new JoinFindBuilder(relation.table.
|
|
843
|
+
const joinBuilder = new JoinFindBuilder(relation.table.name, relation.table);
|
|
836
844
|
if (builderFn) {
|
|
837
845
|
builderFn(joinBuilder);
|
|
838
846
|
}
|
|
@@ -933,7 +941,7 @@ export interface IUnitOfWork {
|
|
|
933
941
|
): TypedUnitOfWork<TOtherSchema, [], any, TOtherHooks>;
|
|
934
942
|
|
|
935
943
|
// Schema registration (for cross-fragment operations like hooks)
|
|
936
|
-
registerSchema(schema: AnySchema, namespace: string): void;
|
|
944
|
+
registerSchema(schema: AnySchema, namespace: string | null): void;
|
|
937
945
|
|
|
938
946
|
// Hook triggering (schema-agnostic, string-based hook names)
|
|
939
947
|
triggerHook(hookName: string, payload: unknown, options?: TriggerHookOptions): void;
|
|
@@ -951,11 +959,50 @@ export interface IUnitOfWork {
|
|
|
951
959
|
export interface IUnitOfWorkRestricted
|
|
952
960
|
extends Omit<IUnitOfWork, "executeRetrieve" | "executeMutations"> {}
|
|
953
961
|
|
|
962
|
+
export type UOWInstrumentationPhase =
|
|
963
|
+
| "beforeRetrieve"
|
|
964
|
+
| "afterRetrieve"
|
|
965
|
+
| "beforeMutate"
|
|
966
|
+
| "afterMutate";
|
|
967
|
+
|
|
968
|
+
export type UOWInstrumentationInjection =
|
|
969
|
+
| { type: "conflict"; reason?: string }
|
|
970
|
+
| { type: "error"; error: Error };
|
|
971
|
+
|
|
972
|
+
export type UOWInstrumentationContext = {
|
|
973
|
+
phase: UOWInstrumentationPhase;
|
|
974
|
+
uowName?: string;
|
|
975
|
+
idempotencyKey: string;
|
|
976
|
+
retrievalOpsCount: number;
|
|
977
|
+
mutationOpsCount: number;
|
|
978
|
+
uow: IUnitOfWork;
|
|
979
|
+
};
|
|
980
|
+
|
|
981
|
+
export type UOWInstrumentation = {
|
|
982
|
+
beforeRetrieve?: (
|
|
983
|
+
ctx: UOWInstrumentationContext,
|
|
984
|
+
) => void | Promise<void> | UOWInstrumentationInjection;
|
|
985
|
+
afterRetrieve?: (
|
|
986
|
+
ctx: UOWInstrumentationContext,
|
|
987
|
+
) => void | Promise<void> | UOWInstrumentationInjection;
|
|
988
|
+
beforeMutate?: (
|
|
989
|
+
ctx: UOWInstrumentationContext,
|
|
990
|
+
) => void | Promise<void> | UOWInstrumentationInjection;
|
|
991
|
+
afterMutate?: (
|
|
992
|
+
ctx: UOWInstrumentationContext,
|
|
993
|
+
) => void | Promise<void> | UOWInstrumentationInjection;
|
|
994
|
+
};
|
|
995
|
+
|
|
996
|
+
export type UOWInstrumentationFinalizer = {
|
|
997
|
+
afterRetrieve?: (ctx: UOWInstrumentationContext) => void | Promise<void>;
|
|
998
|
+
afterMutate?: (ctx: UOWInstrumentationContext) => void | Promise<void>;
|
|
999
|
+
};
|
|
1000
|
+
|
|
954
1001
|
export function createUnitOfWork(
|
|
955
1002
|
compiler: UOWCompiler<unknown>,
|
|
956
1003
|
executor: UOWExecutor<unknown, unknown>,
|
|
957
1004
|
decoder: UOWDecoder<unknown>,
|
|
958
|
-
schemaNamespaceMap?: WeakMap<AnySchema, string>,
|
|
1005
|
+
schemaNamespaceMap?: WeakMap<AnySchema, string | null>,
|
|
959
1006
|
name?: string,
|
|
960
1007
|
): UnitOfWork {
|
|
961
1008
|
return new UnitOfWork(compiler, executor, decoder, name, undefined, schemaNamespaceMap);
|
|
@@ -965,6 +1012,16 @@ export interface UnitOfWorkConfig {
|
|
|
965
1012
|
dryRun?: boolean;
|
|
966
1013
|
onQuery?: (query: unknown) => void;
|
|
967
1014
|
idempotencyKey?: string;
|
|
1015
|
+
instrumentation?: UOWInstrumentation;
|
|
1016
|
+
instrumentationFinalizer?: UOWInstrumentationFinalizer;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
function isUowInstrumentationInjection(value: unknown): value is UOWInstrumentationInjection {
|
|
1020
|
+
if (!value || typeof value !== "object") {
|
|
1021
|
+
return false;
|
|
1022
|
+
}
|
|
1023
|
+
const injection = value as UOWInstrumentationInjection;
|
|
1024
|
+
return injection.type === "conflict" || injection.type === "error";
|
|
968
1025
|
}
|
|
969
1026
|
|
|
970
1027
|
/**
|
|
@@ -1207,7 +1264,7 @@ export class UnitOfWork<const TRawInput = unknown> implements IUnitOfWork {
|
|
|
1207
1264
|
#compiler: UOWCompiler<unknown>;
|
|
1208
1265
|
#executor: UOWExecutor<unknown, TRawInput>;
|
|
1209
1266
|
#decoder: UOWDecoder<TRawInput>;
|
|
1210
|
-
#schemaNamespaceMap: WeakMap<AnySchema, string>;
|
|
1267
|
+
#schemaNamespaceMap: WeakMap<AnySchema, string | null>;
|
|
1211
1268
|
|
|
1212
1269
|
#retrievalResults?: unknown[];
|
|
1213
1270
|
#createdInternalIds: (bigint | null)[] = [];
|
|
@@ -1232,7 +1289,7 @@ export class UnitOfWork<const TRawInput = unknown> implements IUnitOfWork {
|
|
|
1232
1289
|
decoder: UOWDecoder<TRawInput>,
|
|
1233
1290
|
name?: string,
|
|
1234
1291
|
config?: UnitOfWorkConfig,
|
|
1235
|
-
schemaNamespaceMap?: WeakMap<AnySchema, string>,
|
|
1292
|
+
schemaNamespaceMap?: WeakMap<AnySchema, string | null>,
|
|
1236
1293
|
) {
|
|
1237
1294
|
this.#compiler = compiler;
|
|
1238
1295
|
this.#executor = executor;
|
|
@@ -1243,12 +1300,67 @@ export class UnitOfWork<const TRawInput = unknown> implements IUnitOfWork {
|
|
|
1243
1300
|
this.#idempotencyKey = config?.idempotencyKey ?? crypto.randomUUID();
|
|
1244
1301
|
}
|
|
1245
1302
|
|
|
1303
|
+
#createInstrumentationContext(phase: UOWInstrumentationPhase): UOWInstrumentationContext {
|
|
1304
|
+
return {
|
|
1305
|
+
phase,
|
|
1306
|
+
uowName: this.#name,
|
|
1307
|
+
idempotencyKey: this.#idempotencyKey,
|
|
1308
|
+
retrievalOpsCount: this.#retrievalOps.length,
|
|
1309
|
+
mutationOpsCount: this.#mutationOps.length,
|
|
1310
|
+
uow: this,
|
|
1311
|
+
};
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
async #runInstrumentation(
|
|
1315
|
+
phase: UOWInstrumentationPhase,
|
|
1316
|
+
): Promise<UOWInstrumentationInjection | null> {
|
|
1317
|
+
const hook = this.#config?.instrumentation?.[phase];
|
|
1318
|
+
if (!hook) {
|
|
1319
|
+
return null;
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
const result = await hook(this.#createInstrumentationContext(phase));
|
|
1323
|
+
if (isUowInstrumentationInjection(result)) {
|
|
1324
|
+
return result;
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
return null;
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
async #runInstrumentationFinalizer(phase: "afterRetrieve" | "afterMutate"): Promise<void> {
|
|
1331
|
+
const hook = this.#config?.instrumentationFinalizer?.[phase];
|
|
1332
|
+
if (!hook) {
|
|
1333
|
+
return;
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
await hook(this.#createInstrumentationContext(phase));
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
#handleRetrieveInjection(injection: UOWInstrumentationInjection): never {
|
|
1340
|
+
if (injection.type === "error") {
|
|
1341
|
+
throw injection.error;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
throw new Error(injection.reason ?? "Injected conflict");
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
#handleMutationInjection(injection: UOWInstrumentationInjection): { success: false } | never {
|
|
1348
|
+
if (injection.type === "error") {
|
|
1349
|
+
throw injection.error;
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
this.#state = "executed";
|
|
1353
|
+
this.#createdInternalIds.length = 0;
|
|
1354
|
+
this.#mutationPhaseDeferred.resolve();
|
|
1355
|
+
return { success: false };
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1246
1358
|
/**
|
|
1247
1359
|
* Register a schema with its namespace for cross-fragment operations.
|
|
1248
1360
|
* This is used for internal fragments like hooks that need to create
|
|
1249
1361
|
* records in a different schema during the same transaction.
|
|
1250
1362
|
*/
|
|
1251
|
-
registerSchema(schema: AnySchema, namespace: string): void {
|
|
1363
|
+
registerSchema(schema: AnySchema, namespace: string | null): void {
|
|
1252
1364
|
this.#schemaNamespaceMap.set(schema, namespace);
|
|
1253
1365
|
}
|
|
1254
1366
|
|
|
@@ -1426,13 +1538,25 @@ export class UnitOfWork<const TRawInput = unknown> implements IUnitOfWork {
|
|
|
1426
1538
|
);
|
|
1427
1539
|
}
|
|
1428
1540
|
|
|
1541
|
+
let afterRan = false;
|
|
1542
|
+
let failed = false;
|
|
1429
1543
|
try {
|
|
1430
1544
|
// Wait for all children to signal readiness
|
|
1431
1545
|
await this.#coordinator.retrievalReadinessPromise;
|
|
1432
1546
|
|
|
1547
|
+
const beforeInjection = await this.#runInstrumentation("beforeRetrieve");
|
|
1548
|
+
if (beforeInjection) {
|
|
1549
|
+
return this.#handleRetrieveInjection(beforeInjection);
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1433
1552
|
if (this.#retrievalOps.length === 0) {
|
|
1434
1553
|
this.#state = "building-mutation";
|
|
1435
1554
|
const emptyResults: unknown[] = [];
|
|
1555
|
+
afterRan = true;
|
|
1556
|
+
const afterInjection = await this.#runInstrumentation("afterRetrieve");
|
|
1557
|
+
if (afterInjection) {
|
|
1558
|
+
return this.#handleRetrieveInjection(afterInjection);
|
|
1559
|
+
}
|
|
1436
1560
|
this.#retrievalPhaseDeferred.resolve(emptyResults);
|
|
1437
1561
|
return emptyResults;
|
|
1438
1562
|
}
|
|
@@ -1450,6 +1574,11 @@ export class UnitOfWork<const TRawInput = unknown> implements IUnitOfWork {
|
|
|
1450
1574
|
if (this.#config?.dryRun) {
|
|
1451
1575
|
this.#state = "executed";
|
|
1452
1576
|
const emptyResults: unknown[] = [];
|
|
1577
|
+
afterRan = true;
|
|
1578
|
+
const afterInjection = await this.#runInstrumentation("afterRetrieve");
|
|
1579
|
+
if (afterInjection) {
|
|
1580
|
+
return this.#handleRetrieveInjection(afterInjection);
|
|
1581
|
+
}
|
|
1453
1582
|
this.#retrievalPhaseDeferred.resolve(emptyResults);
|
|
1454
1583
|
return emptyResults;
|
|
1455
1584
|
}
|
|
@@ -1462,12 +1591,33 @@ export class UnitOfWork<const TRawInput = unknown> implements IUnitOfWork {
|
|
|
1462
1591
|
this.#retrievalResults = results;
|
|
1463
1592
|
this.#state = "building-mutation";
|
|
1464
1593
|
|
|
1594
|
+
afterRan = true;
|
|
1595
|
+
const afterInjection = await this.#runInstrumentation("afterRetrieve");
|
|
1596
|
+
if (afterInjection) {
|
|
1597
|
+
return this.#handleRetrieveInjection(afterInjection);
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1465
1600
|
this.#retrievalPhaseDeferred.resolve(this.#retrievalResults);
|
|
1466
1601
|
|
|
1467
1602
|
return this.#retrievalResults;
|
|
1468
1603
|
} catch (error) {
|
|
1469
1604
|
this.#retrievalError = error instanceof Error ? error : new Error(String(error));
|
|
1605
|
+
failed = true;
|
|
1470
1606
|
throw error;
|
|
1607
|
+
} finally {
|
|
1608
|
+
try {
|
|
1609
|
+
await this.#runInstrumentationFinalizer("afterRetrieve");
|
|
1610
|
+
} catch {
|
|
1611
|
+
// Ignore finalizer errors when unwinding failures.
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
if (!afterRan && failed) {
|
|
1615
|
+
try {
|
|
1616
|
+
await this.#runInstrumentation("afterRetrieve");
|
|
1617
|
+
} catch {
|
|
1618
|
+
// Ignore after-retrieve hook errors when unwinding failures.
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1471
1621
|
}
|
|
1472
1622
|
}
|
|
1473
1623
|
|
|
@@ -1484,15 +1634,23 @@ export class UnitOfWork<const TRawInput = unknown> implements IUnitOfWork {
|
|
|
1484
1634
|
throw new Error(`Cannot execute mutations from state ${this.#state}.`);
|
|
1485
1635
|
}
|
|
1486
1636
|
|
|
1637
|
+
let afterRan = false;
|
|
1638
|
+
let failed = false;
|
|
1487
1639
|
try {
|
|
1488
1640
|
// Wait for all children to signal readiness
|
|
1489
1641
|
await this.#coordinator.mutationReadinessPromise;
|
|
1490
1642
|
|
|
1643
|
+
const beforeInjection = await this.#runInstrumentation("beforeMutate");
|
|
1644
|
+
if (beforeInjection) {
|
|
1645
|
+
return this.#handleMutationInjection(beforeInjection);
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1491
1648
|
// Compile mutation operations using single compiler
|
|
1492
1649
|
const mutationBatch: CompiledMutation<unknown>[] = [];
|
|
1493
1650
|
for (const op of this.#mutationOps) {
|
|
1494
1651
|
const compiled = this.#compiler.compileMutationOperation(op);
|
|
1495
1652
|
if (compiled !== null) {
|
|
1653
|
+
compiled.uowId = this.#idempotencyKey;
|
|
1496
1654
|
this.#config?.onQuery?.(compiled);
|
|
1497
1655
|
mutationBatch.push(compiled);
|
|
1498
1656
|
}
|
|
@@ -1500,6 +1658,11 @@ export class UnitOfWork<const TRawInput = unknown> implements IUnitOfWork {
|
|
|
1500
1658
|
|
|
1501
1659
|
if (this.#config?.dryRun) {
|
|
1502
1660
|
this.#state = "executed";
|
|
1661
|
+
afterRan = true;
|
|
1662
|
+
const afterInjection = await this.#runInstrumentation("afterMutate");
|
|
1663
|
+
if (afterInjection) {
|
|
1664
|
+
return this.#handleMutationInjection(afterInjection);
|
|
1665
|
+
}
|
|
1503
1666
|
this.#mutationPhaseDeferred.resolve();
|
|
1504
1667
|
return {
|
|
1505
1668
|
success: true,
|
|
@@ -1516,6 +1679,12 @@ export class UnitOfWork<const TRawInput = unknown> implements IUnitOfWork {
|
|
|
1516
1679
|
this.#createdInternalIds.push(...result.createdInternalIds);
|
|
1517
1680
|
}
|
|
1518
1681
|
|
|
1682
|
+
afterRan = true;
|
|
1683
|
+
const afterInjection = await this.#runInstrumentation("afterMutate");
|
|
1684
|
+
if (afterInjection) {
|
|
1685
|
+
return this.#handleMutationInjection(afterInjection);
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1519
1688
|
// Resolve the mutation phase promise to unblock waiting service methods
|
|
1520
1689
|
this.#mutationPhaseDeferred.resolve();
|
|
1521
1690
|
|
|
@@ -1524,7 +1693,22 @@ export class UnitOfWork<const TRawInput = unknown> implements IUnitOfWork {
|
|
|
1524
1693
|
};
|
|
1525
1694
|
} catch (error) {
|
|
1526
1695
|
this.#mutationError = error instanceof Error ? error : new Error(String(error));
|
|
1696
|
+
failed = true;
|
|
1527
1697
|
throw error;
|
|
1698
|
+
} finally {
|
|
1699
|
+
try {
|
|
1700
|
+
await this.#runInstrumentationFinalizer("afterMutate");
|
|
1701
|
+
} catch {
|
|
1702
|
+
// Ignore finalizer errors when unwinding failures.
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
if (!afterRan && failed) {
|
|
1706
|
+
try {
|
|
1707
|
+
await this.#runInstrumentation("afterMutate");
|
|
1708
|
+
} catch {
|
|
1709
|
+
// Ignore after-mutate hook errors when unwinding failures.
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1528
1712
|
}
|
|
1529
1713
|
}
|
|
1530
1714
|
|
|
@@ -1623,6 +1807,7 @@ export class UnitOfWork<const TRawInput = unknown> implements IUnitOfWork {
|
|
|
1623
1807
|
for (const op of this.#mutationOps) {
|
|
1624
1808
|
const compiled = compiler.compileMutationOperation(op);
|
|
1625
1809
|
if (compiled !== null) {
|
|
1810
|
+
compiled.uowId = this.#idempotencyKey;
|
|
1626
1811
|
mutationBatch.push(compiled);
|
|
1627
1812
|
}
|
|
1628
1813
|
}
|
|
@@ -1648,12 +1833,12 @@ export class TypedUnitOfWork<
|
|
|
1648
1833
|
> implements IUnitOfWork
|
|
1649
1834
|
{
|
|
1650
1835
|
#schema: TSchema;
|
|
1651
|
-
#namespace?: string;
|
|
1836
|
+
#namespace?: string | null;
|
|
1652
1837
|
#uow: UnitOfWork<TRawInput>;
|
|
1653
1838
|
#operationIndices: number[] = [];
|
|
1654
1839
|
#cachedRetrievalPhase?: Promise<TRetrievalResults>;
|
|
1655
1840
|
|
|
1656
|
-
constructor(schema: TSchema, namespace: string | undefined, uow: UnitOfWork<TRawInput>) {
|
|
1841
|
+
constructor(schema: TSchema, namespace: string | null | undefined, uow: UnitOfWork<TRawInput>) {
|
|
1657
1842
|
this.#schema = schema;
|
|
1658
1843
|
this.#namespace = namespace;
|
|
1659
1844
|
this.#uow = uow;
|
|
@@ -1746,7 +1931,7 @@ export class TypedUnitOfWork<
|
|
|
1746
1931
|
return this.#uow.forSchema<TOtherSchema, TOtherHooks>(schema, hooks);
|
|
1747
1932
|
}
|
|
1748
1933
|
|
|
1749
|
-
registerSchema(schema: AnySchema, namespace: string): void {
|
|
1934
|
+
registerSchema(schema: AnySchema, namespace: string | null): void {
|
|
1750
1935
|
this.#uow.registerSchema(schema, namespace);
|
|
1751
1936
|
}
|
|
1752
1937
|
|
|
@@ -1989,7 +2174,7 @@ export class TypedUnitOfWork<
|
|
|
1989
2174
|
let updatedValues = values;
|
|
1990
2175
|
|
|
1991
2176
|
// Check if ID value is provided in values
|
|
1992
|
-
const providedIdValue = (values as Record<string, unknown>)[idColumn.
|
|
2177
|
+
const providedIdValue = (values as Record<string, unknown>)[idColumn.name];
|
|
1993
2178
|
|
|
1994
2179
|
if (providedIdValue !== undefined) {
|
|
1995
2180
|
// Extract string from FragnoId or use string directly
|
|
@@ -2007,7 +2192,7 @@ export class TypedUnitOfWork<
|
|
|
2007
2192
|
const generated = idColumn.generateDefaultValue();
|
|
2008
2193
|
if (generated === undefined) {
|
|
2009
2194
|
throw new Error(
|
|
2010
|
-
`No ID value provided and ID column ${idColumn.
|
|
2195
|
+
`No ID value provided and ID column ${idColumn.name} has no default generator`,
|
|
2011
2196
|
);
|
|
2012
2197
|
}
|
|
2013
2198
|
externalId = generated as string;
|
|
@@ -2015,7 +2200,7 @@ export class TypedUnitOfWork<
|
|
|
2015
2200
|
// Add the generated ID to values so it's used in the insert
|
|
2016
2201
|
updatedValues = {
|
|
2017
2202
|
...values,
|
|
2018
|
-
[idColumn.
|
|
2203
|
+
[idColumn.name]: externalId,
|
|
2019
2204
|
} as TableToInsertValues<TSchema["tables"][TableName]>;
|
|
2020
2205
|
}
|
|
2021
2206
|
|
|
@@ -4,11 +4,12 @@ import { decodeResult } from "./value-decoding";
|
|
|
4
4
|
import {
|
|
5
5
|
SQLocalDriverConfig,
|
|
6
6
|
NodePostgresDriverConfig,
|
|
7
|
+
PGLiteDriverConfig,
|
|
7
8
|
MySQL2DriverConfig,
|
|
8
9
|
} from "../adapters/generic-sql/driver-config";
|
|
9
10
|
|
|
10
11
|
describe("decodeResult", () => {
|
|
11
|
-
const testSchema = schema((s) => {
|
|
12
|
+
const testSchema = schema("test", (s) => {
|
|
12
13
|
return s
|
|
13
14
|
.addTable("users", (t) => {
|
|
14
15
|
return t
|
|
@@ -40,6 +41,7 @@ describe("decodeResult", () => {
|
|
|
40
41
|
|
|
41
42
|
const sqliteConfig = new SQLocalDriverConfig();
|
|
42
43
|
const postgresqlConfig = new NodePostgresDriverConfig();
|
|
44
|
+
const pgliteConfig = new PGLiteDriverConfig();
|
|
43
45
|
const mysqlConfig = new MySQL2DriverConfig();
|
|
44
46
|
|
|
45
47
|
describe("basic decoding", () => {
|
|
@@ -105,6 +107,15 @@ describe("decodeResult", () => {
|
|
|
105
107
|
|
|
106
108
|
expect(result["createdAt"]).toBe(date);
|
|
107
109
|
});
|
|
110
|
+
|
|
111
|
+
it("should normalize Date values from pglite timestamp parsing", () => {
|
|
112
|
+
const localDate = new Date("2024-01-15T10:30:00");
|
|
113
|
+
const expected = new Date(localDate.getTime() - localDate.getTimezoneOffset() * 60_000);
|
|
114
|
+
const result = decodeResult({ createdAt: localDate }, usersTable, pgliteConfig);
|
|
115
|
+
|
|
116
|
+
assert.instanceOf(result["createdAt"], Date);
|
|
117
|
+
expect((result["createdAt"] as Date).toISOString()).toBe(expected.toISOString());
|
|
118
|
+
});
|
|
108
119
|
});
|
|
109
120
|
|
|
110
121
|
describe("nullable columns", () => {
|
|
@@ -206,7 +217,7 @@ describe("decodeResult", () => {
|
|
|
206
217
|
});
|
|
207
218
|
|
|
208
219
|
it("should handle multiple relations in same result", () => {
|
|
209
|
-
const schemaWithMultipleRelations = schema((s) => {
|
|
220
|
+
const schemaWithMultipleRelations = schema("schemawithmultiplerelations", (s) => {
|
|
210
221
|
return s
|
|
211
222
|
.addTable("users", (t) => {
|
|
212
223
|
return t.addColumn("id", idColumn()).addColumn("name", column("string"));
|
|
@@ -2,6 +2,8 @@ import type { AnyTable } from "../schema/create";
|
|
|
2
2
|
import { createSQLSerializer } from "./serialize/create-sql-serializer";
|
|
3
3
|
import { FragnoId, FragnoReference } from "../schema/create";
|
|
4
4
|
import type { DriverConfig } from "../adapters/generic-sql/driver-config";
|
|
5
|
+
import type { SQLiteStorageMode } from "../adapters/generic-sql/sqlite-storage";
|
|
6
|
+
import type { NamingResolver } from "../naming/sql-naming";
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Decodes a database result record to application format.
|
|
@@ -15,6 +17,7 @@ import type { DriverConfig } from "../adapters/generic-sql/driver-config";
|
|
|
15
17
|
* @param result - The raw database result record
|
|
16
18
|
* @param table - The table schema definition containing column and relation information
|
|
17
19
|
* @param driverConfig - The driver configuration containing database type information
|
|
20
|
+
* @param sqliteStorageMode - Optional SQLite storage mode override
|
|
18
21
|
* @returns A record in application format with deserialized values
|
|
19
22
|
*
|
|
20
23
|
* @example
|
|
@@ -31,11 +34,14 @@ export function decodeResult(
|
|
|
31
34
|
result: Record<string, unknown>,
|
|
32
35
|
table: AnyTable,
|
|
33
36
|
driverConfig: DriverConfig,
|
|
37
|
+
sqliteStorageMode?: SQLiteStorageMode,
|
|
38
|
+
resolver?: NamingResolver,
|
|
34
39
|
): Record<string, unknown> {
|
|
35
|
-
const serializer = createSQLSerializer(driverConfig);
|
|
40
|
+
const serializer = createSQLSerializer(driverConfig, sqliteStorageMode);
|
|
36
41
|
const output: Record<string, unknown> = {};
|
|
37
42
|
// First pass: collect all column values
|
|
38
43
|
const columnValues: Record<string, unknown> = {};
|
|
44
|
+
const columnMap = resolver ? resolver.getColumnNameMap(table) : undefined;
|
|
39
45
|
|
|
40
46
|
// Collect all relation data (including nested) keyed by relation name
|
|
41
47
|
const relationData: Record<string, Record<string, unknown>> = {};
|
|
@@ -46,13 +52,14 @@ export function decodeResult(
|
|
|
46
52
|
|
|
47
53
|
// Direct column (no colon)
|
|
48
54
|
if (colonIndex === -1) {
|
|
49
|
-
const
|
|
55
|
+
const logicalName = columnMap?.[k] ?? k;
|
|
56
|
+
const col = table.columns[logicalName];
|
|
50
57
|
if (!col) {
|
|
51
58
|
continue;
|
|
52
59
|
}
|
|
53
60
|
|
|
54
61
|
// Store all column values (including hidden ones for FragnoId creation)
|
|
55
|
-
columnValues[
|
|
62
|
+
columnValues[logicalName] = serializer.deserialize(value, col);
|
|
56
63
|
continue;
|
|
57
64
|
}
|
|
58
65
|
|
|
@@ -78,7 +85,13 @@ export function decodeResult(
|
|
|
78
85
|
}
|
|
79
86
|
|
|
80
87
|
// Recursively decode the relation data
|
|
81
|
-
output[relationName] = decodeResult(
|
|
88
|
+
output[relationName] = decodeResult(
|
|
89
|
+
relationData[relationName],
|
|
90
|
+
relation.table,
|
|
91
|
+
driverConfig,
|
|
92
|
+
sqliteStorageMode,
|
|
93
|
+
resolver,
|
|
94
|
+
);
|
|
82
95
|
}
|
|
83
96
|
|
|
84
97
|
// Second pass: create output with FragnoId objects where appropriate
|
|
@@ -7,10 +7,15 @@ import {
|
|
|
7
7
|
schema,
|
|
8
8
|
referenceColumn,
|
|
9
9
|
} from "../schema/create";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
resolveFragnoIdValue,
|
|
12
|
+
encodeValues,
|
|
13
|
+
encodeValuesWithDbDefaults,
|
|
14
|
+
ReferenceSubquery,
|
|
15
|
+
} from "./value-encoding";
|
|
11
16
|
|
|
12
17
|
describe("encodeValues", () => {
|
|
13
|
-
const testSchema = schema((s) => {
|
|
18
|
+
const testSchema = schema("test", (s) => {
|
|
14
19
|
return s
|
|
15
20
|
.addTable("users", (t) => {
|
|
16
21
|
return t
|
|
@@ -128,6 +133,84 @@ describe("encodeValues", () => {
|
|
|
128
133
|
|
|
129
134
|
expect(result["viewCount"]).toBe(100);
|
|
130
135
|
});
|
|
136
|
+
|
|
137
|
+
it("should use injected runtime defaults when provided", () => {
|
|
138
|
+
const testDate = new Date("2024-02-01T00:00:00Z");
|
|
139
|
+
const testSchemaWithDefaults = schema("testschemawithdefaults", (s) =>
|
|
140
|
+
s.addTable("entries", (t) =>
|
|
141
|
+
t.addColumn("id", idColumn()).addColumn(
|
|
142
|
+
"createdAt",
|
|
143
|
+
column("timestamp").defaultTo$((b) => b.now()),
|
|
144
|
+
),
|
|
145
|
+
),
|
|
146
|
+
);
|
|
147
|
+
const entriesTable = testSchemaWithDefaults.tables.entries;
|
|
148
|
+
|
|
149
|
+
const result = encodeValues({}, entriesTable, true, {
|
|
150
|
+
createId: () => "entry_1",
|
|
151
|
+
now: () => testDate,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
expect(result["id"]).toBe("entry_1");
|
|
155
|
+
expect(result["createdAt"]).toBe(testDate);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
describe("database defaults in memory", () => {
|
|
160
|
+
it("should apply static and dbSpecial defaults when requested", () => {
|
|
161
|
+
const testDate = new Date("2024-03-01T00:00:00Z");
|
|
162
|
+
const testSchemaWithDbDefaults = schema("testschemawithdbdefaults", (s) =>
|
|
163
|
+
s.addTable("posts", (t) =>
|
|
164
|
+
t
|
|
165
|
+
.addColumn("id", idColumn())
|
|
166
|
+
.addColumn("title", column("string"))
|
|
167
|
+
.addColumn("status", column("string").defaultTo("draft"))
|
|
168
|
+
.addColumn(
|
|
169
|
+
"createdAt",
|
|
170
|
+
column("timestamp").defaultTo((b) => b.now()),
|
|
171
|
+
),
|
|
172
|
+
),
|
|
173
|
+
);
|
|
174
|
+
const postsTable = testSchemaWithDbDefaults.tables.posts;
|
|
175
|
+
|
|
176
|
+
const result = encodeValuesWithDbDefaults({ title: "Hello" }, postsTable, {
|
|
177
|
+
createId: () => "post_1",
|
|
178
|
+
now: () => testDate,
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
expect(result).toEqual({
|
|
182
|
+
id: "post_1",
|
|
183
|
+
title: "Hello",
|
|
184
|
+
_version: 0,
|
|
185
|
+
status: "draft",
|
|
186
|
+
createdAt: testDate,
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it("should not override explicit values when applying db defaults", () => {
|
|
191
|
+
const testSchemaWithDbDefaults = schema("testschemawithdbdefaults", (s) =>
|
|
192
|
+
s.addTable("posts", (t) =>
|
|
193
|
+
t
|
|
194
|
+
.addColumn("id", idColumn())
|
|
195
|
+
.addColumn("title", column("string"))
|
|
196
|
+
.addColumn("status", column("string").defaultTo("draft")),
|
|
197
|
+
),
|
|
198
|
+
);
|
|
199
|
+
const postsTable = testSchemaWithDbDefaults.tables.posts;
|
|
200
|
+
|
|
201
|
+
const result = encodeValuesWithDbDefaults(
|
|
202
|
+
{ title: "Hello", status: "published" },
|
|
203
|
+
postsTable,
|
|
204
|
+
{ createId: () => "post_2" },
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
expect(result).toEqual({
|
|
208
|
+
id: "post_2",
|
|
209
|
+
title: "Hello",
|
|
210
|
+
_version: 0,
|
|
211
|
+
status: "published",
|
|
212
|
+
});
|
|
213
|
+
});
|
|
131
214
|
});
|
|
132
215
|
|
|
133
216
|
describe("complete record encoding", () => {
|