@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
|
@@ -2,7 +2,6 @@ import type { AnySchema } from "./schema/create";
|
|
|
2
2
|
import type { SimpleQueryInterface } from "./query/simple-query-interface";
|
|
3
3
|
import type { DatabaseAdapter } from "./adapters/adapters";
|
|
4
4
|
import type { IUnitOfWork } from "./query/unit-of-work/unit-of-work";
|
|
5
|
-
import { TypedUnitOfWork, UnitOfWork } from "./query/unit-of-work/unit-of-work";
|
|
6
5
|
import type {
|
|
7
6
|
RequestThisContext,
|
|
8
7
|
FragnoPublicConfig,
|
|
@@ -14,31 +13,42 @@ import {
|
|
|
14
13
|
type ServiceConstructorFn,
|
|
15
14
|
} from "@fragno-dev/core";
|
|
16
15
|
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
type
|
|
22
|
-
type ExecuteRestrictedUnitOfWorkOptions,
|
|
23
|
-
type HandlerTxCallbacks,
|
|
24
|
-
type ServiceTxCallbacks,
|
|
16
|
+
createServiceTxBuilder,
|
|
17
|
+
createHandlerTxBuilder,
|
|
18
|
+
ServiceTxBuilder,
|
|
19
|
+
HandlerTxBuilder,
|
|
20
|
+
type ExecuteTxOptions,
|
|
25
21
|
} from "./query/unit-of-work/execute-unit-of-work";
|
|
26
22
|
import {
|
|
27
23
|
prepareHookMutations,
|
|
28
|
-
processHooks,
|
|
29
24
|
type HooksMap,
|
|
30
25
|
type HookFn,
|
|
31
26
|
type HookContext,
|
|
27
|
+
type HookProcessorConfig,
|
|
28
|
+
type DurableHooksProcessingOptions,
|
|
29
|
+
createHookScheduler,
|
|
32
30
|
} from "./hooks/hooks";
|
|
33
31
|
import type { InternalFragmentInstance } from "./fragments/internal-fragment";
|
|
32
|
+
import { resolveDatabaseAdapter } from "./util/default-database-adapter";
|
|
33
|
+
import { sanitizeNamespace } from "./naming/sql-naming";
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
|
-
* Extended FragnoPublicConfig
|
|
37
|
-
*
|
|
36
|
+
* Extended FragnoPublicConfig for database fragments.
|
|
37
|
+
* If databaseAdapter is omitted and better-sqlite3 is available, a default SQLite adapter is used.
|
|
38
38
|
*/
|
|
39
39
|
export type FragnoPublicConfigWithDatabase = FragnoPublicConfig & {
|
|
40
40
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
41
|
-
databaseAdapter
|
|
41
|
+
databaseAdapter?: DatabaseAdapter<any>;
|
|
42
|
+
/**
|
|
43
|
+
* Optional durable hooks processing configuration.
|
|
44
|
+
*/
|
|
45
|
+
durableHooks?: DurableHooksProcessingOptions;
|
|
46
|
+
/**
|
|
47
|
+
* Optional override for database namespace. If provided (including null), it is used as-is
|
|
48
|
+
* without sanitization — the caller is responsible for providing a valid namespace.
|
|
49
|
+
* When omitted, defaults to a sanitized version of schema.name.
|
|
50
|
+
*/
|
|
51
|
+
databaseNamespace?: string | null;
|
|
42
52
|
};
|
|
43
53
|
|
|
44
54
|
/**
|
|
@@ -48,6 +58,7 @@ export type FragnoPublicConfigWithDatabase = FragnoPublicConfig & {
|
|
|
48
58
|
export type ImplicitDatabaseDependencies<TSchema extends AnySchema> = {
|
|
49
59
|
/**
|
|
50
60
|
* Database query engine for the fragment's schema.
|
|
61
|
+
* @deprecated Prefer handlerTx/serviceTx instead of direct db usage.
|
|
51
62
|
*/
|
|
52
63
|
db: SimpleQueryInterface<TSchema>;
|
|
53
64
|
/**
|
|
@@ -57,7 +68,7 @@ export type ImplicitDatabaseDependencies<TSchema extends AnySchema> = {
|
|
|
57
68
|
/**
|
|
58
69
|
* The database namespace for this fragment.
|
|
59
70
|
*/
|
|
60
|
-
namespace: string;
|
|
71
|
+
namespace: string | null;
|
|
61
72
|
/**
|
|
62
73
|
* Create a new Unit of Work for database operations.
|
|
63
74
|
*/
|
|
@@ -69,35 +80,38 @@ export type ImplicitDatabaseDependencies<TSchema extends AnySchema> = {
|
|
|
69
80
|
*/
|
|
70
81
|
export type DatabaseServiceContext<THooks extends HooksMap> = RequestThisContext & {
|
|
71
82
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*/
|
|
76
|
-
uow<TSchema extends AnySchema>(schema: TSchema): TypedUnitOfWork<TSchema, [], unknown, THooks>;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Execute a transaction with two-phase callbacks (retrieve + mutate).
|
|
80
|
-
*
|
|
81
|
-
* @param schema - Schema to use for the transaction
|
|
82
|
-
* @param callbacks - Object containing retrieve and mutate callbacks
|
|
83
|
-
* @returns Promise resolving to the mutation result with promises awaited 1 level deep
|
|
83
|
+
* Create a service-level transaction builder using the fluent API.
|
|
84
|
+
* Returns a builder that can be chained with withServiceCalls, retrieve,
|
|
85
|
+
* transformRetrieve, mutate, transform, and build.
|
|
84
86
|
*
|
|
85
87
|
* @example
|
|
86
88
|
* ```ts
|
|
87
|
-
* return this.
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* })
|
|
89
|
+
* return this.serviceTx(schema)
|
|
90
|
+
* .withServiceCalls(() => [otherService.getData()])
|
|
91
|
+
* .retrieve((uow) => uow.find("users", ...))
|
|
92
|
+
* .transformRetrieve(([users]) => users[0])
|
|
93
|
+
* .mutate(({ uow, retrieveResult, serviceIntermediateResult }) =>
|
|
94
|
+
* uow.create("records", { ... })
|
|
95
|
+
* )
|
|
96
|
+
* .transform(({ mutateResult, serviceResult }) => ({ id: mutateResult }))
|
|
97
|
+
* .build();
|
|
95
98
|
* ```
|
|
96
99
|
*/
|
|
97
|
-
|
|
100
|
+
serviceTx<TSchema extends AnySchema>(
|
|
98
101
|
schema: TSchema,
|
|
99
|
-
|
|
100
|
-
|
|
102
|
+
): ServiceTxBuilder<
|
|
103
|
+
TSchema,
|
|
104
|
+
readonly [],
|
|
105
|
+
[],
|
|
106
|
+
[],
|
|
107
|
+
unknown,
|
|
108
|
+
unknown,
|
|
109
|
+
false,
|
|
110
|
+
false,
|
|
111
|
+
false,
|
|
112
|
+
false,
|
|
113
|
+
THooks
|
|
114
|
+
>;
|
|
101
115
|
};
|
|
102
116
|
|
|
103
117
|
/**
|
|
@@ -105,92 +119,24 @@ export type DatabaseServiceContext<THooks extends HooksMap> = RequestThisContext
|
|
|
105
119
|
*/
|
|
106
120
|
export type DatabaseHandlerContext<THooks extends HooksMap = {}> = RequestThisContext & {
|
|
107
121
|
/**
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
* callback is re-executed on optimistic concurrency conflicts, ensuring retries work properly.
|
|
112
|
-
* Automatically provides the UOW factory from context.
|
|
113
|
-
* Promises in the returned object are awaited 1 level deep.
|
|
114
|
-
*
|
|
115
|
-
* @param callback - Async function that receives a context with forSchema, executeRetrieve, executeMutate, nonce, and currentAttempt
|
|
116
|
-
* @param options - Optional configuration for retry policy and abort signal
|
|
117
|
-
* @returns Promise resolving to the callback's return value with promises awaited 1 level deep
|
|
118
|
-
* @throws Error if retries are exhausted or callback throws an error
|
|
122
|
+
* Create a handler-level transaction builder using the fluent API.
|
|
123
|
+
* Returns a builder that can be chained with withServiceCalls, retrieve,
|
|
124
|
+
* transformRetrieve, mutate, transform, and execute.
|
|
119
125
|
*
|
|
120
126
|
* @example
|
|
121
127
|
* ```ts
|
|
122
|
-
* const result = await this.
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
* const profileId = uow.create("profiles", { userId });
|
|
130
|
-
*
|
|
131
|
-
* // Execute mutation phase
|
|
132
|
-
* await executeMutate();
|
|
133
|
-
*
|
|
134
|
-
* return { userId, profileId };
|
|
135
|
-
* });
|
|
136
|
-
* ```
|
|
137
|
-
*/
|
|
138
|
-
uow<TResult>(
|
|
139
|
-
callback: (context: {
|
|
140
|
-
forSchema: <TSchema extends AnySchema, H extends HooksMap = THooks>(
|
|
141
|
-
schema: TSchema,
|
|
142
|
-
hooks?: H,
|
|
143
|
-
) => TypedUnitOfWork<TSchema, [], unknown, H>;
|
|
144
|
-
executeRetrieve: () => Promise<void>;
|
|
145
|
-
executeMutate: () => Promise<void>;
|
|
146
|
-
nonce: string;
|
|
147
|
-
currentAttempt: number;
|
|
148
|
-
}) => Promise<TResult> | TResult,
|
|
149
|
-
options?: Omit<ExecuteRestrictedUnitOfWorkOptions, "createUnitOfWork">,
|
|
150
|
-
): Promise<AwaitedPromisesInObject<TResult>>;
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Execute a transaction with automatic retry support.
|
|
154
|
-
* Provides two overloads: array syntax (common case) and callback syntax (advanced).
|
|
155
|
-
*
|
|
156
|
-
* Array syntax - pass a factory function that returns service calls:
|
|
157
|
-
* ```ts
|
|
158
|
-
* const [transfer, notify] = await this.tx(
|
|
159
|
-
* () => [
|
|
160
|
-
* services.transfer({ from, to, amount }),
|
|
161
|
-
* services.notify({ userId, message })
|
|
162
|
-
* ]
|
|
163
|
-
* );
|
|
164
|
-
* ```
|
|
165
|
-
*
|
|
166
|
-
* Callback syntax - for handlers that need direct UOW access:
|
|
167
|
-
* ```ts
|
|
168
|
-
* const result = await this.tx({
|
|
169
|
-
* retrieve: ({ forSchema }) => {
|
|
170
|
-
* const uow = forSchema(schema);
|
|
171
|
-
* uow.find("users", ...);
|
|
172
|
-
* return services.transfer({ ... });
|
|
173
|
-
* },
|
|
174
|
-
* mutate: ({ forSchema }, transferPromise) => {
|
|
175
|
-
* const uow = forSchema(schema);
|
|
176
|
-
* uow.create("auditLog", { ... });
|
|
177
|
-
* return transferPromise;
|
|
178
|
-
* }
|
|
179
|
-
* });
|
|
128
|
+
* const result = await this.handlerTx()
|
|
129
|
+
* .withServiceCalls(() => [userService.getUser(id)])
|
|
130
|
+
* .mutate(({ forSchema, idempotencyKey, currentAttempt, serviceIntermediateResult }) => {
|
|
131
|
+
* return forSchema(ordersSchema).create("orders", { ... });
|
|
132
|
+
* })
|
|
133
|
+
* .transform(({ mutateResult, serviceResult }) => ({ ... }))
|
|
134
|
+
* .execute();
|
|
180
135
|
* ```
|
|
181
|
-
*
|
|
182
|
-
* Note: Handler callbacks are synchronous only to prevent accidentally awaiting services in wrong place.
|
|
183
136
|
*/
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
options?: Omit<ExecuteRestrictedUnitOfWorkOptions, "createUnitOfWork">,
|
|
188
|
-
): Promise<{ [K in keyof T]: T[K] }>;
|
|
189
|
-
// Overload 2: Callback syntax (advanced, sync callbacks only)
|
|
190
|
-
tx<TRetrieveResult, TMutationResult>(
|
|
191
|
-
callbacks: HandlerTxCallbacks<TRetrieveResult, TMutationResult, THooks>,
|
|
192
|
-
options?: Omit<ExecuteRestrictedUnitOfWorkOptions, "createUnitOfWork">,
|
|
193
|
-
): Promise<AwaitedPromisesInObject<TMutationResult>>;
|
|
137
|
+
handlerTx(
|
|
138
|
+
options?: Omit<ExecuteTxOptions, "createUnitOfWork">,
|
|
139
|
+
): HandlerTxBuilder<readonly [], [], [], unknown, unknown, false, false, false, false, THooks>;
|
|
194
140
|
};
|
|
195
141
|
|
|
196
142
|
/**
|
|
@@ -214,21 +160,23 @@ export type DatabaseFragmentContext<TSchema extends AnySchema> = {
|
|
|
214
160
|
function createDatabaseContext<TSchema extends AnySchema>(
|
|
215
161
|
options: FragnoPublicConfigWithDatabase,
|
|
216
162
|
schema: TSchema,
|
|
217
|
-
namespace: string,
|
|
218
163
|
): DatabaseFragmentContext<TSchema> {
|
|
219
|
-
const databaseAdapter = options
|
|
220
|
-
|
|
221
|
-
if (!databaseAdapter) {
|
|
222
|
-
throw new Error(
|
|
223
|
-
"Database fragment requires a database adapter to be provided in options.databaseAdapter",
|
|
224
|
-
);
|
|
225
|
-
}
|
|
164
|
+
const databaseAdapter = resolveDatabaseAdapter(options, schema);
|
|
226
165
|
|
|
166
|
+
const namespace = resolveDatabaseNamespace(options, schema);
|
|
227
167
|
const db = databaseAdapter.createQueryEngine(schema, namespace);
|
|
228
168
|
|
|
229
169
|
return { databaseAdapter, db };
|
|
230
170
|
}
|
|
231
171
|
|
|
172
|
+
function resolveDatabaseNamespace<TSchema extends AnySchema>(
|
|
173
|
+
options: FragnoPublicConfigWithDatabase,
|
|
174
|
+
schema: TSchema,
|
|
175
|
+
): string | null {
|
|
176
|
+
const hasOverride = options.databaseNamespace !== undefined;
|
|
177
|
+
return hasOverride ? (options.databaseNamespace ?? null) : sanitizeNamespace(schema.name);
|
|
178
|
+
}
|
|
179
|
+
|
|
232
180
|
/**
|
|
233
181
|
* Storage type for database fragments - stores the Unit of Work.
|
|
234
182
|
*/
|
|
@@ -240,7 +188,7 @@ export type DatabaseRequestStorage = {
|
|
|
240
188
|
* Builder for database fragments that wraps the core fragment builder
|
|
241
189
|
* and provides database-specific functionality.
|
|
242
190
|
*
|
|
243
|
-
* Database fragments
|
|
191
|
+
* Database fragments use FragnoPublicConfigWithDatabase and default the adapter when possible.
|
|
244
192
|
*/
|
|
245
193
|
export class DatabaseFragmentDefinitionBuilder<
|
|
246
194
|
TSchema extends AnySchema,
|
|
@@ -270,7 +218,6 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
270
218
|
TLinkedFragments
|
|
271
219
|
>;
|
|
272
220
|
#schema: TSchema;
|
|
273
|
-
#namespace: string;
|
|
274
221
|
#hooksFactory?: (context: { config: TConfig; options: FragnoPublicConfigWithDatabase }) => THooks;
|
|
275
222
|
|
|
276
223
|
constructor(
|
|
@@ -288,7 +235,6 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
288
235
|
TLinkedFragments
|
|
289
236
|
>,
|
|
290
237
|
schema: TSchema,
|
|
291
|
-
namespace?: string,
|
|
292
238
|
hooksFactory?: (context: {
|
|
293
239
|
config: TConfig;
|
|
294
240
|
options: FragnoPublicConfigWithDatabase;
|
|
@@ -296,7 +242,6 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
296
242
|
) {
|
|
297
243
|
this.#baseBuilder = baseBuilder;
|
|
298
244
|
this.#schema = schema;
|
|
299
|
-
this.#namespace = namespace ?? baseBuilder.name;
|
|
300
245
|
this.#hooksFactory = hooksFactory;
|
|
301
246
|
}
|
|
302
247
|
|
|
@@ -326,7 +271,8 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
326
271
|
> {
|
|
327
272
|
// Wrap user function to inject DB context
|
|
328
273
|
const wrappedFn = (context: { config: TConfig; options: FragnoPublicConfigWithDatabase }) => {
|
|
329
|
-
const dbContext = createDatabaseContext(context.options, this.#schema
|
|
274
|
+
const dbContext = createDatabaseContext(context.options, this.#schema);
|
|
275
|
+
const namespace = resolveDatabaseNamespace(context.options, this.#schema);
|
|
330
276
|
|
|
331
277
|
// Call user function with enriched context
|
|
332
278
|
const userDeps = fn({
|
|
@@ -341,7 +287,7 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
341
287
|
const implicitDeps: ImplicitDatabaseDependencies<TSchema> = {
|
|
342
288
|
db: dbContext.db,
|
|
343
289
|
schema: this.#schema,
|
|
344
|
-
namespace
|
|
290
|
+
namespace,
|
|
345
291
|
createUnitOfWork: createUow,
|
|
346
292
|
};
|
|
347
293
|
|
|
@@ -354,12 +300,7 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
354
300
|
// Create new base builder with wrapped function
|
|
355
301
|
const newBaseBuilder = this.#baseBuilder.withDependencies(wrappedFn);
|
|
356
302
|
|
|
357
|
-
return new DatabaseFragmentDefinitionBuilder(
|
|
358
|
-
newBaseBuilder,
|
|
359
|
-
this.#schema,
|
|
360
|
-
this.#namespace,
|
|
361
|
-
this.#hooksFactory,
|
|
362
|
-
);
|
|
303
|
+
return new DatabaseFragmentDefinitionBuilder(newBaseBuilder, this.#schema, this.#hooksFactory);
|
|
363
304
|
}
|
|
364
305
|
|
|
365
306
|
providesBaseService<TNewService>(
|
|
@@ -387,12 +328,7 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
387
328
|
> {
|
|
388
329
|
const newBaseBuilder = this.#baseBuilder.providesBaseService<TNewService>(fn);
|
|
389
330
|
|
|
390
|
-
return new DatabaseFragmentDefinitionBuilder(
|
|
391
|
-
newBaseBuilder,
|
|
392
|
-
this.#schema,
|
|
393
|
-
this.#namespace,
|
|
394
|
-
this.#hooksFactory,
|
|
395
|
-
);
|
|
331
|
+
return new DatabaseFragmentDefinitionBuilder(newBaseBuilder, this.#schema, this.#hooksFactory);
|
|
396
332
|
}
|
|
397
333
|
|
|
398
334
|
providesService<TServiceName extends string, TService>(
|
|
@@ -424,12 +360,7 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
424
360
|
fn,
|
|
425
361
|
);
|
|
426
362
|
|
|
427
|
-
return new DatabaseFragmentDefinitionBuilder(
|
|
428
|
-
newBaseBuilder,
|
|
429
|
-
this.#schema,
|
|
430
|
-
this.#namespace,
|
|
431
|
-
this.#hooksFactory,
|
|
432
|
-
);
|
|
363
|
+
return new DatabaseFragmentDefinitionBuilder(newBaseBuilder, this.#schema, this.#hooksFactory);
|
|
433
364
|
}
|
|
434
365
|
|
|
435
366
|
/**
|
|
@@ -468,12 +399,7 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
468
399
|
fn,
|
|
469
400
|
);
|
|
470
401
|
|
|
471
|
-
return new DatabaseFragmentDefinitionBuilder(
|
|
472
|
-
newBaseBuilder,
|
|
473
|
-
this.#schema,
|
|
474
|
-
this.#namespace,
|
|
475
|
-
this.#hooksFactory,
|
|
476
|
-
);
|
|
402
|
+
return new DatabaseFragmentDefinitionBuilder(newBaseBuilder, this.#schema, this.#hooksFactory);
|
|
477
403
|
}
|
|
478
404
|
|
|
479
405
|
/**
|
|
@@ -487,7 +413,7 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
487
413
|
* ```ts
|
|
488
414
|
* .provideHooks(({ defineHook, config }) => ({
|
|
489
415
|
* onSubscribe: defineHook(async function (payload: { email: string }) {
|
|
490
|
-
* // 'this' context available (HookServiceContext with
|
|
416
|
+
* // 'this' context available (HookServiceContext with idempotencyKey)
|
|
491
417
|
* await config.onSubscribe?.(payload.email);
|
|
492
418
|
* }),
|
|
493
419
|
* }))
|
|
@@ -537,7 +463,6 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
537
463
|
const newBuilder = new DatabaseFragmentDefinitionBuilder(
|
|
538
464
|
this.#baseBuilder,
|
|
539
465
|
this.#schema,
|
|
540
|
-
this.#namespace,
|
|
541
466
|
) as unknown as DatabaseFragmentDefinitionBuilder<
|
|
542
467
|
TSchema,
|
|
543
468
|
TConfig,
|
|
@@ -578,12 +503,7 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
578
503
|
> {
|
|
579
504
|
const newBaseBuilder = this.#baseBuilder.usesService<TServiceName, TService>(serviceName);
|
|
580
505
|
|
|
581
|
-
return new DatabaseFragmentDefinitionBuilder(
|
|
582
|
-
newBaseBuilder,
|
|
583
|
-
this.#schema,
|
|
584
|
-
this.#namespace,
|
|
585
|
-
this.#hooksFactory,
|
|
586
|
-
);
|
|
506
|
+
return new DatabaseFragmentDefinitionBuilder(newBaseBuilder, this.#schema, this.#hooksFactory);
|
|
587
507
|
}
|
|
588
508
|
|
|
589
509
|
/**
|
|
@@ -609,12 +529,7 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
609
529
|
serviceName,
|
|
610
530
|
);
|
|
611
531
|
|
|
612
|
-
return new DatabaseFragmentDefinitionBuilder(
|
|
613
|
-
newBaseBuilder,
|
|
614
|
-
this.#schema,
|
|
615
|
-
this.#namespace,
|
|
616
|
-
this.#hooksFactory,
|
|
617
|
-
);
|
|
532
|
+
return new DatabaseFragmentDefinitionBuilder(newBaseBuilder, this.#schema, this.#hooksFactory);
|
|
618
533
|
}
|
|
619
534
|
|
|
620
535
|
/**
|
|
@@ -663,12 +578,13 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
663
578
|
}
|
|
664
579
|
}
|
|
665
580
|
|
|
666
|
-
const { db } = createDatabaseContext(context.options, this.#schema
|
|
581
|
+
const { db } = createDatabaseContext(context.options, this.#schema);
|
|
582
|
+
const namespace = resolveDatabaseNamespace(context.options, this.#schema);
|
|
667
583
|
|
|
668
584
|
const implicitDeps: ImplicitDatabaseDependencies<TSchema> = {
|
|
669
585
|
db,
|
|
670
586
|
schema: this.#schema,
|
|
671
|
-
namespace
|
|
587
|
+
namespace,
|
|
672
588
|
createUnitOfWork: () => db.createUnitOfWork(),
|
|
673
589
|
};
|
|
674
590
|
|
|
@@ -681,7 +597,7 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
681
597
|
// Use the adapter's shared context storage (all fragments using the same adapter share this storage)
|
|
682
598
|
const builderWithExternalStorage = this.#baseBuilder.withExternalRequestStorage(
|
|
683
599
|
({ options }) => {
|
|
684
|
-
const dbContext = createDatabaseContext(options, this.#schema
|
|
600
|
+
const dbContext = createDatabaseContext(options, this.#schema);
|
|
685
601
|
return dbContext.databaseAdapter.contextStorage;
|
|
686
602
|
},
|
|
687
603
|
);
|
|
@@ -690,7 +606,7 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
690
606
|
const builderWithStorage = builderWithExternalStorage.withRequestStorage(
|
|
691
607
|
({ options }): DatabaseRequestStorage => {
|
|
692
608
|
// Create database context - needed here to create the UOW
|
|
693
|
-
const dbContextForStorage = createDatabaseContext(options, this.#schema
|
|
609
|
+
const dbContextForStorage = createDatabaseContext(options, this.#schema);
|
|
694
610
|
|
|
695
611
|
// Create a new Unit of Work for this request
|
|
696
612
|
const uow: IUnitOfWork = dbContextForStorage.db.createUnitOfWork();
|
|
@@ -706,68 +622,109 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
706
622
|
options: FragnoPublicConfigWithDatabase;
|
|
707
623
|
}) => InternalFragmentInstance;
|
|
708
624
|
|
|
625
|
+
// Cache per instantiated fragment (deps object is unique per instantiation).
|
|
626
|
+
const hooksConfigCache = new WeakMap<object, HookProcessorConfig<THooks>>();
|
|
627
|
+
|
|
628
|
+
const createHooksConfig = (context: {
|
|
629
|
+
config: TConfig;
|
|
630
|
+
options: FragnoPublicConfigWithDatabase;
|
|
631
|
+
deps: TDeps;
|
|
632
|
+
}) => {
|
|
633
|
+
if (!this.#hooksFactory) {
|
|
634
|
+
return undefined;
|
|
635
|
+
}
|
|
636
|
+
const depsKey =
|
|
637
|
+
typeof context.deps === "object" && context.deps !== null
|
|
638
|
+
? (context.deps as object)
|
|
639
|
+
: undefined;
|
|
640
|
+
const cachedHooksConfig = depsKey ? hooksConfigCache.get(depsKey) : undefined;
|
|
641
|
+
if (cachedHooksConfig) {
|
|
642
|
+
return cachedHooksConfig;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
const namespace = resolveDatabaseNamespace(context.options, this.#schema);
|
|
646
|
+
const namespaceKey = namespace ?? this.#schema.name;
|
|
647
|
+
const durableHooksOptions = context.options.durableHooks;
|
|
648
|
+
const baseAdapter = resolveDatabaseAdapter(context.options, this.#schema);
|
|
649
|
+
const hookAdapter = baseAdapter.getHookProcessingAdapter?.() ?? baseAdapter;
|
|
650
|
+
const hookOptions =
|
|
651
|
+
hookAdapter === baseAdapter
|
|
652
|
+
? context.options
|
|
653
|
+
: { ...context.options, databaseAdapter: hookAdapter };
|
|
654
|
+
const dbContextForHooks = createDatabaseContext(hookOptions, this.#schema);
|
|
655
|
+
const hooksConfig: HookProcessorConfig<THooks> = {
|
|
656
|
+
hooks: this.#hooksFactory(context),
|
|
657
|
+
namespace: namespaceKey,
|
|
658
|
+
internalFragment: internalFragmentFactory({
|
|
659
|
+
config: context.config,
|
|
660
|
+
options: hookOptions,
|
|
661
|
+
}),
|
|
662
|
+
handlerTx: (execOptions?: Omit<ExecuteTxOptions, "createUnitOfWork">) => {
|
|
663
|
+
const userOnBeforeMutate = execOptions?.onBeforeMutate;
|
|
664
|
+
const userOnAfterMutate = execOptions?.onAfterMutate;
|
|
665
|
+
return createHandlerTxBuilder<THooks>({
|
|
666
|
+
...execOptions,
|
|
667
|
+
createUnitOfWork: () => {
|
|
668
|
+
const uow = dbContextForHooks.db.createUnitOfWork();
|
|
669
|
+
uow.registerSchema(
|
|
670
|
+
hooksConfig.internalFragment.$internal.deps.schema,
|
|
671
|
+
hooksConfig.internalFragment.$internal.deps.namespace,
|
|
672
|
+
);
|
|
673
|
+
return uow;
|
|
674
|
+
},
|
|
675
|
+
onBeforeMutate: (uow) => {
|
|
676
|
+
prepareHookMutations(uow, hooksConfig);
|
|
677
|
+
if (userOnBeforeMutate) {
|
|
678
|
+
userOnBeforeMutate(uow);
|
|
679
|
+
}
|
|
680
|
+
},
|
|
681
|
+
onAfterMutate: async (uow) => {
|
|
682
|
+
void hooksConfig.scheduler?.schedule().catch((error) => {
|
|
683
|
+
console.error("Durable hooks processing failed", error);
|
|
684
|
+
});
|
|
685
|
+
if (userOnAfterMutate) {
|
|
686
|
+
await userOnAfterMutate(uow);
|
|
687
|
+
}
|
|
688
|
+
},
|
|
689
|
+
});
|
|
690
|
+
},
|
|
691
|
+
stuckProcessingTimeoutMinutes: durableHooksOptions?.stuckProcessingTimeoutMinutes,
|
|
692
|
+
onStuckProcessingHooks: durableHooksOptions?.onStuckProcessingHooks,
|
|
693
|
+
};
|
|
694
|
+
hooksConfig.scheduler = createHookScheduler(hooksConfig);
|
|
695
|
+
if (depsKey) {
|
|
696
|
+
hooksConfigCache.set(depsKey, hooksConfig);
|
|
697
|
+
}
|
|
698
|
+
return hooksConfig;
|
|
699
|
+
};
|
|
700
|
+
|
|
709
701
|
const builderWithContext = builderWithStorage.withThisContext<
|
|
710
702
|
DatabaseServiceContext<THooks>,
|
|
711
703
|
DatabaseHandlerContext<THooks>
|
|
712
|
-
>(({ storage, config, options }) => {
|
|
704
|
+
>(({ storage, config, options, deps }) => {
|
|
713
705
|
// Create hooks config if hooks factory is defined
|
|
714
|
-
const hooksConfig =
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
internalFragment: internalFragmentFactory({ config, options }),
|
|
719
|
-
}
|
|
720
|
-
: undefined;
|
|
721
|
-
|
|
722
|
-
function forSchema<TSchema extends AnySchema>(
|
|
723
|
-
schema: TSchema,
|
|
724
|
-
): TypedUnitOfWork<TSchema, [], unknown, THooks> {
|
|
725
|
-
const uow = storage.getStore()?.uow;
|
|
726
|
-
if (!uow) {
|
|
727
|
-
throw new Error(
|
|
728
|
-
"No UnitOfWork in context. Service must be called within a route handler OR using `withUnitOfWork`.",
|
|
729
|
-
);
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
return uow.restrict().forSchema<TSchema, THooks>(schema);
|
|
733
|
-
}
|
|
706
|
+
const hooksConfig = createHooksConfig({ config, options, deps });
|
|
707
|
+
const internalFragment =
|
|
708
|
+
hooksConfig?.internalFragment ??
|
|
709
|
+
(internalFragmentFactory ? internalFragmentFactory({ config, options }) : undefined);
|
|
734
710
|
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
TRetrievalResults extends unknown[],
|
|
738
|
-
TMutationResult = void,
|
|
739
|
-
>(
|
|
740
|
-
schema: TSchema,
|
|
741
|
-
callbacks: ServiceTxCallbacks<TSchema, TRetrievalResults, TMutationResult, THooks>,
|
|
742
|
-
): Promise<AwaitedPromisesInObject<TMutationResult>> => {
|
|
711
|
+
// Builder API: serviceTx using createServiceTxBuilder
|
|
712
|
+
function serviceTx<TSchema extends AnySchema>(schema: TSchema) {
|
|
743
713
|
const uow = storage.getStore()?.uow;
|
|
744
714
|
if (!uow) {
|
|
745
715
|
throw new Error(
|
|
746
716
|
"No UnitOfWork in context. Service must be called within a route handler OR using `withUnitOfWork`.",
|
|
747
717
|
);
|
|
748
718
|
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
};
|
|
719
|
+
return createServiceTxBuilder<TSchema, THooks>(schema, uow, hooksConfig?.hooks);
|
|
720
|
+
}
|
|
752
721
|
|
|
753
722
|
const serviceContext: DatabaseServiceContext<THooks> = {
|
|
754
|
-
|
|
755
|
-
tx: serviceTx,
|
|
723
|
+
serviceTx,
|
|
756
724
|
};
|
|
757
725
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
forSchema: <S extends AnySchema, H extends HooksMap = THooks>(
|
|
761
|
-
schema: S,
|
|
762
|
-
hooks?: H,
|
|
763
|
-
) => TypedUnitOfWork<S, [], unknown, H>;
|
|
764
|
-
executeRetrieve: () => Promise<void>;
|
|
765
|
-
executeMutate: () => Promise<void>;
|
|
766
|
-
nonce: string;
|
|
767
|
-
currentAttempt: number;
|
|
768
|
-
}) => Promise<TResult> | TResult,
|
|
769
|
-
execOptions?: Omit<ExecuteRestrictedUnitOfWorkOptions, "createUnitOfWork">,
|
|
770
|
-
): Promise<AwaitedPromisesInObject<TResult>> {
|
|
726
|
+
// Builder API: handlerTx using createHandlerTxBuilder
|
|
727
|
+
function handlerTx(execOptions?: Omit<ExecuteTxOptions, "createUnitOfWork">) {
|
|
771
728
|
const currentStorage = storage.getStore();
|
|
772
729
|
if (!currentStorage) {
|
|
773
730
|
throw new Error(
|
|
@@ -775,34 +732,20 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
775
732
|
);
|
|
776
733
|
}
|
|
777
734
|
|
|
778
|
-
const wrappedCallback = async (context: {
|
|
779
|
-
forSchema: <S extends AnySchema, H extends HooksMap = THooks>(
|
|
780
|
-
schema: S,
|
|
781
|
-
hooks?: H,
|
|
782
|
-
) => TypedUnitOfWork<S, [], unknown, H>;
|
|
783
|
-
executeRetrieve: () => Promise<void>;
|
|
784
|
-
executeMutate: () => Promise<void>;
|
|
785
|
-
nonce: string;
|
|
786
|
-
currentAttempt: number;
|
|
787
|
-
}): Promise<TResult> => {
|
|
788
|
-
return callback(context);
|
|
789
|
-
};
|
|
790
|
-
|
|
791
735
|
const userOnBeforeMutate = execOptions?.onBeforeMutate;
|
|
792
|
-
const
|
|
736
|
+
const userOnAfterMutate = execOptions?.onAfterMutate;
|
|
793
737
|
|
|
794
|
-
return
|
|
738
|
+
return createHandlerTxBuilder<THooks>({
|
|
795
739
|
...execOptions,
|
|
796
740
|
createUnitOfWork: () => {
|
|
797
741
|
currentStorage.uow.reset();
|
|
798
|
-
if (
|
|
742
|
+
if (internalFragment) {
|
|
799
743
|
currentStorage.uow.registerSchema(
|
|
800
|
-
|
|
801
|
-
|
|
744
|
+
internalFragment.$internal.deps.schema,
|
|
745
|
+
internalFragment.$internal.deps.namespace,
|
|
802
746
|
);
|
|
803
747
|
}
|
|
804
|
-
|
|
805
|
-
return currentStorage.uow as UnitOfWork;
|
|
748
|
+
return currentStorage.uow;
|
|
806
749
|
},
|
|
807
750
|
onBeforeMutate: (uow) => {
|
|
808
751
|
if (hooksConfig) {
|
|
@@ -812,94 +755,21 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
812
755
|
userOnBeforeMutate(uow);
|
|
813
756
|
}
|
|
814
757
|
},
|
|
815
|
-
|
|
816
|
-
if (hooksConfig) {
|
|
817
|
-
|
|
758
|
+
onAfterMutate: async (uow) => {
|
|
759
|
+
if (hooksConfig?.scheduler) {
|
|
760
|
+
void hooksConfig.scheduler.schedule().catch((error) => {
|
|
761
|
+
console.error("Durable hooks processing failed", error);
|
|
762
|
+
});
|
|
818
763
|
}
|
|
819
|
-
if (
|
|
820
|
-
await
|
|
764
|
+
if (userOnAfterMutate) {
|
|
765
|
+
await userOnAfterMutate(uow);
|
|
821
766
|
}
|
|
822
767
|
},
|
|
823
768
|
});
|
|
824
769
|
}
|
|
825
770
|
|
|
826
|
-
// Handler tx method with two overloads
|
|
827
|
-
function handlerTx<T extends readonly unknown[]>(
|
|
828
|
-
servicesFactory: () => readonly [...{ [K in keyof T]: Promise<T[K]> }],
|
|
829
|
-
execOptions?: Omit<ExecuteRestrictedUnitOfWorkOptions, "createUnitOfWork">,
|
|
830
|
-
): Promise<{ [K in keyof T]: T[K] }>;
|
|
831
|
-
function handlerTx<TRetrieveResult, TMutationResult>(
|
|
832
|
-
callbacks: HandlerTxCallbacks<TRetrieveResult, TMutationResult, THooks>,
|
|
833
|
-
execOptions?: Omit<ExecuteRestrictedUnitOfWorkOptions, "createUnitOfWork">,
|
|
834
|
-
): Promise<AwaitedPromisesInObject<TMutationResult>>;
|
|
835
|
-
async function handlerTx<T extends readonly unknown[], TRetrieveResult, TMutationResult>(
|
|
836
|
-
factoryOrCallbacks:
|
|
837
|
-
| (() => readonly [...{ [K in keyof T]: Promise<T[K]> }])
|
|
838
|
-
| HandlerTxCallbacks<TRetrieveResult, TMutationResult, THooks>,
|
|
839
|
-
execOptions?: Omit<ExecuteRestrictedUnitOfWorkOptions, "createUnitOfWork">,
|
|
840
|
-
): Promise<{ [K in keyof T]: T[K] } | AwaitedPromisesInObject<TMutationResult>> {
|
|
841
|
-
const currentStorage = storage.getStore();
|
|
842
|
-
if (!currentStorage) {
|
|
843
|
-
throw new Error(
|
|
844
|
-
"No storage in context. Handler must be called within a request context.",
|
|
845
|
-
);
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
const userOnBeforeMutate = execOptions?.onBeforeMutate;
|
|
849
|
-
const userOnSuccess = execOptions?.onSuccess;
|
|
850
|
-
|
|
851
|
-
const createUow = () => {
|
|
852
|
-
currentStorage.uow.reset();
|
|
853
|
-
|
|
854
|
-
if (hooksConfig) {
|
|
855
|
-
currentStorage.uow.registerSchema(
|
|
856
|
-
hooksConfig.internalFragment.$internal.deps.schema,
|
|
857
|
-
hooksConfig.internalFragment.$internal.deps.namespace,
|
|
858
|
-
);
|
|
859
|
-
}
|
|
860
|
-
// Safe cast: currentStorage.uow is always a UnitOfWork instance
|
|
861
|
-
return currentStorage.uow as UnitOfWork;
|
|
862
|
-
};
|
|
863
|
-
|
|
864
|
-
const options: ExecuteRestrictedUnitOfWorkOptions = {
|
|
865
|
-
...execOptions,
|
|
866
|
-
createUnitOfWork: createUow,
|
|
867
|
-
onBeforeMutate: (uow) => {
|
|
868
|
-
if (hooksConfig) {
|
|
869
|
-
prepareHookMutations(uow, hooksConfig);
|
|
870
|
-
}
|
|
871
|
-
if (userOnBeforeMutate) {
|
|
872
|
-
userOnBeforeMutate(uow);
|
|
873
|
-
}
|
|
874
|
-
},
|
|
875
|
-
onSuccess: async (uow) => {
|
|
876
|
-
if (hooksConfig) {
|
|
877
|
-
await processHooks(hooksConfig);
|
|
878
|
-
}
|
|
879
|
-
if (userOnSuccess) {
|
|
880
|
-
await userOnSuccess(uow);
|
|
881
|
-
}
|
|
882
|
-
},
|
|
883
|
-
};
|
|
884
|
-
|
|
885
|
-
// Check if it's a function (array syntax factory) or callbacks object (callback syntax)
|
|
886
|
-
if (typeof factoryOrCallbacks === "function") {
|
|
887
|
-
// Array syntax - factoryOrCallbacks is a factory function
|
|
888
|
-
return executeTxArray(
|
|
889
|
-
factoryOrCallbacks as () => readonly [...{ [K in keyof T]: Promise<T[K]> }],
|
|
890
|
-
options,
|
|
891
|
-
) as Promise<{ [K in keyof T]: T[K] }>;
|
|
892
|
-
} else {
|
|
893
|
-
return executeTxCallbacks(
|
|
894
|
-
factoryOrCallbacks as HandlerTxCallbacks<TRetrieveResult, TMutationResult, THooks>,
|
|
895
|
-
options,
|
|
896
|
-
);
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
|
|
900
771
|
const handlerContext: DatabaseHandlerContext<THooks> = {
|
|
901
|
-
|
|
902
|
-
tx: handlerTx,
|
|
772
|
+
handlerTx,
|
|
903
773
|
};
|
|
904
774
|
|
|
905
775
|
return { serviceContext, handlerContext };
|
|
@@ -907,6 +777,15 @@ export class DatabaseFragmentDefinitionBuilder<
|
|
|
907
777
|
|
|
908
778
|
// Build the final definition
|
|
909
779
|
const finalDef = builderWithContext.build();
|
|
780
|
+
if (this.#hooksFactory) {
|
|
781
|
+
finalDef.internalDataFactory = ({ config, options, deps }) => ({
|
|
782
|
+
durableHooks: createHooksConfig({
|
|
783
|
+
config: config as TConfig,
|
|
784
|
+
options: options as FragnoPublicConfigWithDatabase,
|
|
785
|
+
deps: deps as TDeps,
|
|
786
|
+
}),
|
|
787
|
+
});
|
|
788
|
+
}
|
|
910
789
|
|
|
911
790
|
// Return the complete definition with proper typing and dependencies
|
|
912
791
|
return {
|