typhex 0.1.0-alpha.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/CHANGELOG.md +20 -0
- package/LICENSE +21 -0
- package/README.md +417 -0
- package/SECURITY.md +32 -0
- package/dist/arrow/aggregates.d.ts +12 -0
- package/dist/arrow/aggregates.d.ts.map +1 -0
- package/dist/arrow/aggregates.js +32 -0
- package/dist/arrow/aggregates.js.map +1 -0
- package/dist/arrow/constants.d.ts +15 -0
- package/dist/arrow/constants.d.ts.map +1 -0
- package/dist/arrow/constants.js +42 -0
- package/dist/arrow/constants.js.map +1 -0
- package/dist/arrow/index.d.ts +7 -0
- package/dist/arrow/index.d.ts.map +1 -0
- package/dist/arrow/index.js +7 -0
- package/dist/arrow/index.js.map +1 -0
- package/dist/config/index.d.ts +6 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +4 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/load-config.d.ts +19 -0
- package/dist/config/load-config.d.ts.map +1 -0
- package/dist/config/load-config.js +84 -0
- package/dist/config/load-config.js.map +1 -0
- package/dist/config/load-env.d.ts +7 -0
- package/dist/config/load-env.d.ts.map +1 -0
- package/dist/config/load-env.js +62 -0
- package/dist/config/load-env.js.map +1 -0
- package/dist/config/types.d.ts +20 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +10 -0
- package/dist/config/types.js.map +1 -0
- package/dist/dbs/base-migrator.d.ts +20 -0
- package/dist/dbs/base-migrator.d.ts.map +1 -0
- package/dist/dbs/base-migrator.js +112 -0
- package/dist/dbs/base-migrator.js.map +1 -0
- package/dist/dbs/index.d.ts +9 -0
- package/dist/dbs/index.d.ts.map +1 -0
- package/dist/dbs/index.js +17 -0
- package/dist/dbs/index.js.map +1 -0
- package/dist/dbs/postgres/dialect.d.ts +8 -0
- package/dist/dbs/postgres/dialect.d.ts.map +1 -0
- package/dist/dbs/postgres/dialect.js +17 -0
- package/dist/dbs/postgres/dialect.js.map +1 -0
- package/dist/dbs/postgres/driver.d.ts +42 -0
- package/dist/dbs/postgres/driver.d.ts.map +1 -0
- package/dist/dbs/postgres/driver.js +111 -0
- package/dist/dbs/postgres/driver.js.map +1 -0
- package/dist/dbs/postgres/index.d.ts +6 -0
- package/dist/dbs/postgres/index.d.ts.map +1 -0
- package/dist/dbs/postgres/index.js +5 -0
- package/dist/dbs/postgres/index.js.map +1 -0
- package/dist/dbs/postgres/migrator.d.ts +13 -0
- package/dist/dbs/postgres/migrator.d.ts.map +1 -0
- package/dist/dbs/postgres/migrator.js +22 -0
- package/dist/dbs/postgres/migrator.js.map +1 -0
- package/dist/dbs/postgres/query-compiler.d.ts +22 -0
- package/dist/dbs/postgres/query-compiler.d.ts.map +1 -0
- package/dist/dbs/postgres/query-compiler.js +140 -0
- package/dist/dbs/postgres/query-compiler.js.map +1 -0
- package/dist/dbs/postgres/trx.d.ts +16 -0
- package/dist/dbs/postgres/trx.d.ts.map +1 -0
- package/dist/dbs/postgres/trx.js +68 -0
- package/dist/dbs/postgres/trx.js.map +1 -0
- package/dist/dbs/query-compiler.d.ts +135 -0
- package/dist/dbs/query-compiler.d.ts.map +1 -0
- package/dist/dbs/query-compiler.js +775 -0
- package/dist/dbs/query-compiler.js.map +1 -0
- package/dist/dbs/sqlite/dialect.d.ts +8 -0
- package/dist/dbs/sqlite/dialect.d.ts.map +1 -0
- package/dist/dbs/sqlite/dialect.js +17 -0
- package/dist/dbs/sqlite/dialect.js.map +1 -0
- package/dist/dbs/sqlite/driver.d.ts +9 -0
- package/dist/dbs/sqlite/driver.d.ts.map +1 -0
- package/dist/dbs/sqlite/driver.js +66 -0
- package/dist/dbs/sqlite/driver.js.map +1 -0
- package/dist/dbs/sqlite/index.d.ts +6 -0
- package/dist/dbs/sqlite/index.d.ts.map +1 -0
- package/dist/dbs/sqlite/index.js +5 -0
- package/dist/dbs/sqlite/index.js.map +1 -0
- package/dist/dbs/sqlite/migrator.d.ts +13 -0
- package/dist/dbs/sqlite/migrator.d.ts.map +1 -0
- package/dist/dbs/sqlite/migrator.js +22 -0
- package/dist/dbs/sqlite/migrator.js.map +1 -0
- package/dist/dbs/sqlite/query-compiler.d.ts +26 -0
- package/dist/dbs/sqlite/query-compiler.d.ts.map +1 -0
- package/dist/dbs/sqlite/query-compiler.js +80 -0
- package/dist/dbs/sqlite/query-compiler.js.map +1 -0
- package/dist/dbs/sqlite/trx.d.ts +13 -0
- package/dist/dbs/sqlite/trx.d.ts.map +1 -0
- package/dist/dbs/sqlite/trx.js +69 -0
- package/dist/dbs/sqlite/trx.js.map +1 -0
- package/dist/dbs/types.d.ts +92 -0
- package/dist/dbs/types.d.ts.map +1 -0
- package/dist/dbs/types.js +26 -0
- package/dist/dbs/types.js.map +1 -0
- package/dist/dialect.d.ts +3 -0
- package/dist/dialect.d.ts.map +1 -0
- package/dist/dialect.js +2 -0
- package/dist/dialect.js.map +1 -0
- package/dist/driver/factory.d.ts +19 -0
- package/dist/driver/factory.d.ts.map +1 -0
- package/dist/driver/factory.js +24 -0
- package/dist/driver/factory.js.map +1 -0
- package/dist/driver/index.d.ts +6 -0
- package/dist/driver/index.d.ts.map +1 -0
- package/dist/driver/index.js +3 -0
- package/dist/driver/index.js.map +1 -0
- package/dist/driver/sqlite.d.ts +15 -0
- package/dist/driver/sqlite.d.ts.map +1 -0
- package/dist/driver/sqlite.js +74 -0
- package/dist/driver/sqlite.js.map +1 -0
- package/dist/driver/types.d.ts +75 -0
- package/dist/driver/types.d.ts.map +1 -0
- package/dist/driver/types.js +2 -0
- package/dist/driver/types.js.map +1 -0
- package/dist/entity/entity.d.ts +67 -0
- package/dist/entity/entity.d.ts.map +1 -0
- package/dist/entity/entity.js +139 -0
- package/dist/entity/entity.js.map +1 -0
- package/dist/entity/global-driver.d.ts +38 -0
- package/dist/entity/global-driver.d.ts.map +1 -0
- package/dist/entity/global-driver.js +109 -0
- package/dist/entity/global-driver.js.map +1 -0
- package/dist/entity/index.d.ts +8 -0
- package/dist/entity/index.d.ts.map +1 -0
- package/dist/entity/index.js +3 -0
- package/dist/entity/index.js.map +1 -0
- package/dist/entity/pk-columns.d.ts +5 -0
- package/dist/entity/pk-columns.d.ts.map +1 -0
- package/dist/entity/pk-columns.js +14 -0
- package/dist/entity/pk-columns.js.map +1 -0
- package/dist/entity/relations.d.ts +134 -0
- package/dist/entity/relations.d.ts.map +1 -0
- package/dist/entity/relations.js +23 -0
- package/dist/entity/relations.js.map +1 -0
- package/dist/entity/schema-inference.d.ts +77 -0
- package/dist/entity/schema-inference.d.ts.map +1 -0
- package/dist/entity/schema-inference.js +6 -0
- package/dist/entity/schema-inference.js.map +1 -0
- package/dist/entity/types.d.ts +30 -0
- package/dist/entity/types.d.ts.map +1 -0
- package/dist/entity/types.js +5 -0
- package/dist/entity/types.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/ir/index.d.ts +2 -0
- package/dist/ir/index.d.ts.map +1 -0
- package/dist/ir/index.js +2 -0
- package/dist/ir/index.js.map +1 -0
- package/dist/ir/types.d.ts +148 -0
- package/dist/ir/types.d.ts.map +1 -0
- package/dist/ir/types.js +97 -0
- package/dist/ir/types.js.map +1 -0
- package/dist/migration/cli.d.ts +18 -0
- package/dist/migration/cli.d.ts.map +1 -0
- package/dist/migration/cli.js +236 -0
- package/dist/migration/cli.js.map +1 -0
- package/dist/migration/diff.d.ts +10 -0
- package/dist/migration/diff.d.ts.map +1 -0
- package/dist/migration/diff.js +10 -0
- package/dist/migration/diff.js.map +1 -0
- package/dist/migration/generator.d.ts +12 -0
- package/dist/migration/generator.d.ts.map +1 -0
- package/dist/migration/generator.js +98 -0
- package/dist/migration/generator.js.map +1 -0
- package/dist/migration/index.d.ts +7 -0
- package/dist/migration/index.d.ts.map +1 -0
- package/dist/migration/index.js +5 -0
- package/dist/migration/index.js.map +1 -0
- package/dist/migration/runner.d.ts +32 -0
- package/dist/migration/runner.d.ts.map +1 -0
- package/dist/migration/runner.js +279 -0
- package/dist/migration/runner.js.map +1 -0
- package/dist/migration/topo-sort.d.ts +12 -0
- package/dist/migration/topo-sort.d.ts.map +1 -0
- package/dist/migration/topo-sort.js +42 -0
- package/dist/migration/topo-sort.js.map +1 -0
- package/dist/migration/types.d.ts +45 -0
- package/dist/migration/types.d.ts.map +1 -0
- package/dist/migration/types.js +2 -0
- package/dist/migration/types.js.map +1 -0
- package/dist/orm/aggregates.d.ts +19 -0
- package/dist/orm/aggregates.d.ts.map +1 -0
- package/dist/orm/aggregates.js +32 -0
- package/dist/orm/aggregates.js.map +1 -0
- package/dist/orm/db.d.ts +105 -0
- package/dist/orm/db.d.ts.map +1 -0
- package/dist/orm/db.js +172 -0
- package/dist/orm/db.js.map +1 -0
- package/dist/orm/expr.d.ts +125 -0
- package/dist/orm/expr.d.ts.map +1 -0
- package/dist/orm/expr.js +10 -0
- package/dist/orm/expr.js.map +1 -0
- package/dist/orm/helpers/insert-graph/insert-graph-batch-executor.d.ts +9 -0
- package/dist/orm/helpers/insert-graph/insert-graph-batch-executor.d.ts.map +1 -0
- package/dist/orm/helpers/insert-graph/insert-graph-batch-executor.js +44 -0
- package/dist/orm/helpers/insert-graph/insert-graph-batch-executor.js.map +1 -0
- package/dist/orm/helpers/insert-graph/insert-graph-executor.d.ts +13 -0
- package/dist/orm/helpers/insert-graph/insert-graph-executor.d.ts.map +1 -0
- package/dist/orm/helpers/insert-graph/insert-graph-executor.js +42 -0
- package/dist/orm/helpers/insert-graph/insert-graph-executor.js.map +1 -0
- package/dist/orm/helpers/insert-graph/insert-graph-planner.d.ts +46 -0
- package/dist/orm/helpers/insert-graph/insert-graph-planner.d.ts.map +1 -0
- package/dist/orm/helpers/insert-graph/insert-graph-planner.js +258 -0
- package/dist/orm/helpers/insert-graph/insert-graph-planner.js.map +1 -0
- package/dist/orm/helpers/insert-graph/insert-graph-sequential-executor.d.ts +7 -0
- package/dist/orm/helpers/insert-graph/insert-graph-sequential-executor.d.ts.map +1 -0
- package/dist/orm/helpers/insert-graph/insert-graph-sequential-executor.js +8 -0
- package/dist/orm/helpers/insert-graph/insert-graph-sequential-executor.js.map +1 -0
- package/dist/orm/helpers/insert-graph/sequence-id-assigner.d.ts +15 -0
- package/dist/orm/helpers/insert-graph/sequence-id-assigner.d.ts.map +1 -0
- package/dist/orm/helpers/insert-graph/sequence-id-assigner.js +48 -0
- package/dist/orm/helpers/insert-graph/sequence-id-assigner.js.map +1 -0
- package/dist/orm/helpers/query-plan/expr-builder.d.ts +155 -0
- package/dist/orm/helpers/query-plan/expr-builder.d.ts.map +1 -0
- package/dist/orm/helpers/query-plan/expr-builder.js +297 -0
- package/dist/orm/helpers/query-plan/expr-builder.js.map +1 -0
- package/dist/orm/helpers/query-plan/query-ir-analyzer.d.ts +48 -0
- package/dist/orm/helpers/query-plan/query-ir-analyzer.d.ts.map +1 -0
- package/dist/orm/helpers/query-plan/query-ir-analyzer.js +262 -0
- package/dist/orm/helpers/query-plan/query-ir-analyzer.js.map +1 -0
- package/dist/orm/helpers/query-plan/query-plan.d.ts +164 -0
- package/dist/orm/helpers/query-plan/query-plan.d.ts.map +1 -0
- package/dist/orm/helpers/query-plan/query-plan.js +549 -0
- package/dist/orm/helpers/query-plan/query-plan.js.map +1 -0
- package/dist/orm/helpers/query-plan/select-classifier.d.ts +161 -0
- package/dist/orm/helpers/query-plan/select-classifier.d.ts.map +1 -0
- package/dist/orm/helpers/query-plan/select-classifier.js +359 -0
- package/dist/orm/helpers/query-plan/select-classifier.js.map +1 -0
- package/dist/orm/helpers/relations/relation-assembler.d.ts +21 -0
- package/dist/orm/helpers/relations/relation-assembler.d.ts.map +1 -0
- package/dist/orm/helpers/relations/relation-assembler.js +60 -0
- package/dist/orm/helpers/relations/relation-assembler.js.map +1 -0
- package/dist/orm/helpers/relations/relation-fetcher.d.ts +30 -0
- package/dist/orm/helpers/relations/relation-fetcher.d.ts.map +1 -0
- package/dist/orm/helpers/relations/relation-fetcher.js +128 -0
- package/dist/orm/helpers/relations/relation-fetcher.js.map +1 -0
- package/dist/orm/helpers/relations/relation-joins.d.ts +74 -0
- package/dist/orm/helpers/relations/relation-joins.d.ts.map +1 -0
- package/dist/orm/helpers/relations/relation-joins.js +138 -0
- package/dist/orm/helpers/relations/relation-joins.js.map +1 -0
- package/dist/orm/helpers/relations/relation-resolver.d.ts +14 -0
- package/dist/orm/helpers/relations/relation-resolver.d.ts.map +1 -0
- package/dist/orm/helpers/relations/relation-resolver.js +25 -0
- package/dist/orm/helpers/relations/relation-resolver.js.map +1 -0
- package/dist/orm/index.d.ts +7 -0
- package/dist/orm/index.d.ts.map +1 -0
- package/dist/orm/index.js +5 -0
- package/dist/orm/index.js.map +1 -0
- package/dist/orm/query-builder.d.ts +136 -0
- package/dist/orm/query-builder.d.ts.map +1 -0
- package/dist/orm/query-builder.js +433 -0
- package/dist/orm/query-builder.js.map +1 -0
- package/dist/orm/query-helpers.d.ts +35 -0
- package/dist/orm/query-helpers.d.ts.map +1 -0
- package/dist/orm/query-helpers.js +83 -0
- package/dist/orm/query-helpers.js.map +1 -0
- package/dist/orm/query-state.d.ts +56 -0
- package/dist/orm/query-state.d.ts.map +1 -0
- package/dist/orm/query-state.js +112 -0
- package/dist/orm/query-state.js.map +1 -0
- package/dist/orm/single-row-query-builder.d.ts +18 -0
- package/dist/orm/single-row-query-builder.d.ts.map +1 -0
- package/dist/orm/single-row-query-builder.js +90 -0
- package/dist/orm/single-row-query-builder.js.map +1 -0
- package/dist/orm/trx.d.ts +40 -0
- package/dist/orm/trx.d.ts.map +1 -0
- package/dist/orm/trx.js +118 -0
- package/dist/orm/trx.js.map +1 -0
- package/dist/parser/acorn-helpers.d.ts +43 -0
- package/dist/parser/acorn-helpers.d.ts.map +1 -0
- package/dist/parser/acorn-helpers.js +104 -0
- package/dist/parser/acorn-helpers.js.map +1 -0
- package/dist/parser/acorn-member.d.ts +16 -0
- package/dist/parser/acorn-member.d.ts.map +1 -0
- package/dist/parser/acorn-member.js +31 -0
- package/dist/parser/acorn-member.js.map +1 -0
- package/dist/parser/acorn-types.d.ts +14 -0
- package/dist/parser/acorn-types.d.ts.map +1 -0
- package/dist/parser/acorn-types.js +6 -0
- package/dist/parser/acorn-types.js.map +1 -0
- package/dist/parser/arrow-source.d.ts +23 -0
- package/dist/parser/arrow-source.d.ts.map +1 -0
- package/dist/parser/arrow-source.js +70 -0
- package/dist/parser/arrow-source.js.map +1 -0
- package/dist/parser/group-by.d.ts +17 -0
- package/dist/parser/group-by.d.ts.map +1 -0
- package/dist/parser/group-by.js +62 -0
- package/dist/parser/group-by.js.map +1 -0
- package/dist/parser/index.d.ts +5 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +3 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/parse-arrow.d.ts +10 -0
- package/dist/parser/parse-arrow.d.ts.map +1 -0
- package/dist/parser/parse-arrow.js +9 -0
- package/dist/parser/parse-arrow.js.map +1 -0
- package/dist/parser/predicate-walk.d.ts +24 -0
- package/dist/parser/predicate-walk.d.ts.map +1 -0
- package/dist/parser/predicate-walk.js +247 -0
- package/dist/parser/predicate-walk.js.map +1 -0
- package/dist/parser/resolve.d.ts +25 -0
- package/dist/parser/resolve.d.ts.map +1 -0
- package/dist/parser/resolve.js +134 -0
- package/dist/parser/resolve.js.map +1 -0
- package/dist/parser/select.d.ts +7 -0
- package/dist/parser/select.d.ts.map +1 -0
- package/dist/parser/select.js +333 -0
- package/dist/parser/select.js.map +1 -0
- package/dist/parser/update.d.ts +7 -0
- package/dist/parser/update.d.ts.map +1 -0
- package/dist/parser/update.js +51 -0
- package/dist/parser/update.js.map +1 -0
- package/dist/postgres/aggregates.d.ts +12 -0
- package/dist/postgres/aggregates.d.ts.map +1 -0
- package/dist/postgres/aggregates.js +19 -0
- package/dist/postgres/aggregates.js.map +1 -0
- package/dist/postgres.d.ts +6 -0
- package/dist/postgres.d.ts.map +1 -0
- package/dist/postgres.js +6 -0
- package/dist/postgres.js.map +1 -0
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +2 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/types.d.ts +16 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +40 -0
- package/dist/schema/types.js.map +1 -0
- package/dist/sqlite/aggregates.d.ts +8 -0
- package/dist/sqlite/aggregates.d.ts.map +1 -0
- package/dist/sqlite/aggregates.js +11 -0
- package/dist/sqlite/aggregates.js.map +1 -0
- package/dist/sqlite.d.ts +6 -0
- package/dist/sqlite.d.ts.map +1 -0
- package/dist/sqlite.js +6 -0
- package/dist/sqlite.js.map +1 -0
- package/dist/transformer/bindings.d.ts +18 -0
- package/dist/transformer/bindings.d.ts.map +1 -0
- package/dist/transformer/bindings.js +52 -0
- package/dist/transformer/bindings.js.map +1 -0
- package/dist/transformer/index.d.ts +17 -0
- package/dist/transformer/index.d.ts.map +1 -0
- package/dist/transformer/index.js +75 -0
- package/dist/transformer/index.js.map +1 -0
- package/dist/transformer/ir-emit.d.ts +12 -0
- package/dist/transformer/ir-emit.d.ts.map +1 -0
- package/dist/transformer/ir-emit.js +144 -0
- package/dist/transformer/ir-emit.js.map +1 -0
- package/dist/transformer/join-transformer.d.ts +12 -0
- package/dist/transformer/join-transformer.d.ts.map +1 -0
- package/dist/transformer/join-transformer.js +102 -0
- package/dist/transformer/join-transformer.js.map +1 -0
- package/dist/transformer/orderby-transformer.d.ts +13 -0
- package/dist/transformer/orderby-transformer.d.ts.map +1 -0
- package/dist/transformer/orderby-transformer.js +84 -0
- package/dist/transformer/orderby-transformer.js.map +1 -0
- package/dist/transformer/select-transformer.d.ts +9 -0
- package/dist/transformer/select-transformer.d.ts.map +1 -0
- package/dist/transformer/select-transformer.js +222 -0
- package/dist/transformer/select-transformer.js.map +1 -0
- package/dist/transformer/shared.d.ts +12 -0
- package/dist/transformer/shared.d.ts.map +1 -0
- package/dist/transformer/shared.js +12 -0
- package/dist/transformer/shared.js.map +1 -0
- package/dist/transformer/subquery-transformer.d.ts +15 -0
- package/dist/transformer/subquery-transformer.d.ts.map +1 -0
- package/dist/transformer/subquery-transformer.js +43 -0
- package/dist/transformer/subquery-transformer.js.map +1 -0
- package/dist/transformer/ts-aggregates.d.ts +13 -0
- package/dist/transformer/ts-aggregates.d.ts.map +1 -0
- package/dist/transformer/ts-aggregates.js +83 -0
- package/dist/transformer/ts-aggregates.js.map +1 -0
- package/dist/transformer/ts-binary.d.ts +8 -0
- package/dist/transformer/ts-binary.d.ts.map +1 -0
- package/dist/transformer/ts-binary.js +32 -0
- package/dist/transformer/ts-binary.js.map +1 -0
- package/dist/transformer/ts-member.d.ts +12 -0
- package/dist/transformer/ts-member.d.ts.map +1 -0
- package/dist/transformer/ts-member.js +22 -0
- package/dist/transformer/ts-member.js.map +1 -0
- package/dist/transformer/ts-utils.d.ts +10 -0
- package/dist/transformer/ts-utils.d.ts.map +1 -0
- package/dist/transformer/ts-utils.js +38 -0
- package/dist/transformer/ts-utils.js.map +1 -0
- package/dist/transformer/typhex-type.d.ts +8 -0
- package/dist/transformer/typhex-type.d.ts.map +1 -0
- package/dist/transformer/typhex-type.js +52 -0
- package/dist/transformer/typhex-type.js.map +1 -0
- package/dist/transformer/where-transformer.d.ts +33 -0
- package/dist/transformer/where-transformer.d.ts.map +1 -0
- package/dist/transformer/where-transformer.js +400 -0
- package/dist/transformer/where-transformer.js.map +1 -0
- package/dist/utils.d.ts +5 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +30 -0
- package/dist/utils.js.map +1 -0
- package/docs/drivers/postgres.md +54 -0
- package/docs/drivers/sqlite.md +33 -0
- package/docs/guide/aggregations.md +272 -0
- package/docs/guide/bulk-operations.md +204 -0
- package/docs/guide/cte-and-unions.md +270 -0
- package/docs/guide/entities-relations.md +208 -0
- package/docs/guide/expressions.md +98 -0
- package/docs/guide/filtering-by-relations.md +166 -0
- package/docs/guide/getting-started.md +277 -0
- package/docs/guide/querying-relations.md +133 -0
- package/docs/guide/subqueries.md +152 -0
- package/docs/guide/transactions.md +146 -0
- package/docs/guide/typescript-transformer.md +138 -0
- package/docs/index.md +33 -0
- package/docs/migrations/overview.md +143 -0
- package/docs/public-api.md +133 -0
- package/docs/reference/api.md +665 -0
- package/docs/reference/architecture.md +83 -0
- package/docs/release-checklist.md +55 -0
- package/etc/typhex.api.md +774 -0
- package/package.json +137 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Subqueries
|
|
2
|
+
|
|
3
|
+
Typhex supports `IN` subqueries in runtime mode and transformer mode. Scalar and correlated subqueries are transformer-only because the compiler needs to capture the outer query reference.
|
|
4
|
+
|
|
5
|
+
## `IN` Subqueries
|
|
6
|
+
|
|
7
|
+
In runtime mode, build the inner query first and pass it through the params object:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
const activePostAuthors = Post.query()
|
|
11
|
+
.where((p) => p.active === 1)
|
|
12
|
+
.select((p) => p.authorId);
|
|
13
|
+
|
|
14
|
+
const authors = await Author.query()
|
|
15
|
+
.where((a, posts) => a.id in posts, { posts: activePostAuthors })
|
|
16
|
+
.toArray();
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```sql
|
|
20
|
+
SELECT "t0"."id", "t0"."name"
|
|
21
|
+
FROM "authors" AS "t0"
|
|
22
|
+
WHERE "t0"."id" IN (
|
|
23
|
+
SELECT "t1"."authorId" FROM "posts" AS "t1" WHERE ("t1"."active" = ?)
|
|
24
|
+
)
|
|
25
|
+
-- params: [1]
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
With the transformer enabled, the inner query can be written inline:
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
const authors = await Author.query()
|
|
32
|
+
.where(
|
|
33
|
+
(a) =>
|
|
34
|
+
a.id in
|
|
35
|
+
Post.query()
|
|
36
|
+
.where((p) => p.active === 1)
|
|
37
|
+
.select((p) => p.authorId),
|
|
38
|
+
)
|
|
39
|
+
.toArray();
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
```sql
|
|
43
|
+
SELECT "t0"."id", "t0"."name"
|
|
44
|
+
FROM "authors" AS "t0"
|
|
45
|
+
WHERE "t0"."id" IN (
|
|
46
|
+
SELECT "t1"."authorId" FROM "posts" AS "t1" WHERE ("t1"."active" = ?)
|
|
47
|
+
)
|
|
48
|
+
-- params: [1]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Nested inline `IN` subqueries use the same transformer path:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
const authors = await Author.query()
|
|
55
|
+
.where(
|
|
56
|
+
(a) =>
|
|
57
|
+
a.id in
|
|
58
|
+
Post.query()
|
|
59
|
+
.where(
|
|
60
|
+
(p) =>
|
|
61
|
+
p.authorId in
|
|
62
|
+
Author.query()
|
|
63
|
+
.where((candidate) => candidate.name !== "Carol")
|
|
64
|
+
.select((candidate) => candidate.id),
|
|
65
|
+
)
|
|
66
|
+
.select((p) => p.authorId),
|
|
67
|
+
)
|
|
68
|
+
.toArray();
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
```sql
|
|
72
|
+
SELECT "t0"."id", "t0"."name"
|
|
73
|
+
FROM "authors" AS "t0"
|
|
74
|
+
WHERE "t0"."id" IN (
|
|
75
|
+
SELECT "t1"."authorId" FROM "posts" AS "t1"
|
|
76
|
+
WHERE "t1"."authorId" IN (
|
|
77
|
+
SELECT "t2"."id" FROM "authors" AS "t2" WHERE ("t2"."name" <> ?)
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
-- params: ["Carol"]
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Scalar Subqueries
|
|
84
|
+
|
|
85
|
+
Use `.select(() => count())` on the inner query when the subquery should return one value:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import { count } from "typhex";
|
|
89
|
+
|
|
90
|
+
const authorsWithCounts = await Author.query()
|
|
91
|
+
.select((a) => ({
|
|
92
|
+
name: a.name,
|
|
93
|
+
postCount: Post.query()
|
|
94
|
+
.where((p) => p.authorId === a.id)
|
|
95
|
+
.select(() => count()),
|
|
96
|
+
}))
|
|
97
|
+
.toArray();
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
```sql
|
|
101
|
+
SELECT "t0"."name" AS "name",
|
|
102
|
+
(SELECT COUNT(*) FROM "posts" AS "t1" WHERE ("t1"."authorId" = "t0"."id")) AS "postCount"
|
|
103
|
+
FROM "authors" AS "t0"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The `a.id` reference is correlated to the outer row, so this form requires the TypeScript transformer.
|
|
107
|
+
|
|
108
|
+
## Comparing Against Subqueries
|
|
109
|
+
|
|
110
|
+
Scalar subqueries can appear in `where()` comparisons:
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
const prolificAuthors = await Author.query()
|
|
114
|
+
.where(
|
|
115
|
+
(a) =>
|
|
116
|
+
Post.query()
|
|
117
|
+
.where((p) => p.authorId === a.id)
|
|
118
|
+
.select(() => count()) > 1,
|
|
119
|
+
)
|
|
120
|
+
.toArray();
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
```sql
|
|
124
|
+
SELECT "t0"."id", "t0"."name"
|
|
125
|
+
FROM "authors" AS "t0"
|
|
126
|
+
WHERE ((SELECT COUNT(*) FROM "posts" AS "t1" WHERE ("t1"."authorId" = "t0"."id")) > ?)
|
|
127
|
+
-- params: [1]
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Ordering by Subqueries
|
|
131
|
+
|
|
132
|
+
Correlated scalar subqueries also work in `orderBy()`:
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
const sorted = await Author.query()
|
|
136
|
+
.orderBy(
|
|
137
|
+
(a) =>
|
|
138
|
+
Post.query()
|
|
139
|
+
.where((p) => p.authorId === a.id)
|
|
140
|
+
.select(() => count()),
|
|
141
|
+
"desc",
|
|
142
|
+
)
|
|
143
|
+
.toArray();
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```sql
|
|
147
|
+
SELECT "t0"."id", "t0"."name"
|
|
148
|
+
FROM "authors" AS "t0"
|
|
149
|
+
ORDER BY (SELECT COUNT(*) FROM "posts" AS "t1" WHERE ("t1"."authorId" = "t0"."id")) DESC
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Run `npm run subqueries` from `examples/` for a complete transformer-backed demo.
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Transactions
|
|
2
|
+
|
|
3
|
+
Typhex provides two transaction APIs. Both support nested savepoints and configurable isolation levels.
|
|
4
|
+
|
|
5
|
+
## Callback API (Recommended)
|
|
6
|
+
|
|
7
|
+
Pass an async callback to `db.transaction()`. Any `Entity.query()` call inside the callback **automatically uses the active transaction** — no need to thread a `trx` argument through your code:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { Db, Entity, createSqliteDriver } from "typhex";
|
|
11
|
+
|
|
12
|
+
await db.transaction(async () => {
|
|
13
|
+
const user = await User.query().insert({ name: "Alice" });
|
|
14
|
+
await Post.query().insert({ title: "Hello", authorId: user.id });
|
|
15
|
+
});
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
```sql
|
|
19
|
+
BEGIN
|
|
20
|
+
INSERT INTO users (name) VALUES (?)
|
|
21
|
+
INSERT INTO posts (title, authorId) VALUES (?, ?)
|
|
22
|
+
COMMIT
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If the callback throws, the transaction is rolled back automatically:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
await db
|
|
29
|
+
.transaction(async () => {
|
|
30
|
+
await User.query().insert({ name: "Bob" });
|
|
31
|
+
throw new Error("oops");
|
|
32
|
+
})
|
|
33
|
+
.catch((e) => console.log("rolled back:", e.message));
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```sql
|
|
37
|
+
BEGIN
|
|
38
|
+
INSERT INTO users (name) VALUES (?)
|
|
39
|
+
ROLLBACK
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Explicit API (Service-Layer Pattern)
|
|
43
|
+
|
|
44
|
+
Use `db.beginTrx()` when you need to pass the transaction handle to functions that shouldn't know about `db`:
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import { Trx } from "typhex";
|
|
48
|
+
|
|
49
|
+
async function createUserWithPost(trx: Trx, name: string, title: string) {
|
|
50
|
+
const user = await User.query(trx).insert({ name });
|
|
51
|
+
await Post.query(trx).insert({ title, authorId: user.id });
|
|
52
|
+
return user;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const trx = await db.beginTrx();
|
|
56
|
+
try {
|
|
57
|
+
const user = await createUserWithPost(trx, "Carol", "Carol's post");
|
|
58
|
+
await trx.commit();
|
|
59
|
+
} catch {
|
|
60
|
+
await trx.rollback();
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`Entity.query(trx)` routes the query through the given transaction connection.
|
|
65
|
+
|
|
66
|
+
## Nested Transactions (Savepoints)
|
|
67
|
+
|
|
68
|
+
Calling `trx.transaction()` (or `db.transaction()` inside an active transaction) creates a **savepoint**. Rolling back the inner transaction only undoes work since the savepoint — the outer transaction is unaffected:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
await db.transaction(async (outer) => {
|
|
72
|
+
const dave = await User.query(outer).insert({ name: "Dave" });
|
|
73
|
+
|
|
74
|
+
// Inner savepoint — will be rolled back
|
|
75
|
+
await outer
|
|
76
|
+
.transaction(async (inner) => {
|
|
77
|
+
await Post.query(inner).insert({ title: "Draft", authorId: dave.id });
|
|
78
|
+
throw new Error("discard draft");
|
|
79
|
+
})
|
|
80
|
+
.catch(() => {}); // only the draft is lost
|
|
81
|
+
|
|
82
|
+
// Dave still exists; publish a different post
|
|
83
|
+
await Post.query(outer).insert({ title: "Published", authorId: dave.id });
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
```sql
|
|
88
|
+
BEGIN
|
|
89
|
+
INSERT INTO users (name) VALUES (?)
|
|
90
|
+
SAVEPOINT sp_1
|
|
91
|
+
INSERT INTO posts (title, authorId) VALUES (?, ?)
|
|
92
|
+
ROLLBACK TO SAVEPOINT sp_1
|
|
93
|
+
INSERT INTO posts (title, authorId) VALUES (?, ?)
|
|
94
|
+
COMMIT
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Transaction Options
|
|
98
|
+
|
|
99
|
+
### Isolation Level
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
await db.transaction(
|
|
103
|
+
async () => {
|
|
104
|
+
// ...
|
|
105
|
+
},
|
|
106
|
+
{ isolationLevel: "SERIALIZABLE" },
|
|
107
|
+
);
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
```sql
|
|
111
|
+
-- SQLite
|
|
112
|
+
BEGIN IMMEDIATE
|
|
113
|
+
...
|
|
114
|
+
COMMIT
|
|
115
|
+
|
|
116
|
+
-- PostgreSQL
|
|
117
|
+
BEGIN ISOLATION LEVEL SERIALIZABLE
|
|
118
|
+
...
|
|
119
|
+
COMMIT
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
SQLite maps `"SERIALIZABLE"` to `BEGIN IMMEDIATE`.
|
|
123
|
+
|
|
124
|
+
### SQLite Exclusive Mode
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
const trx = await db.beginTrx({ sqliteMode: "exclusive" });
|
|
128
|
+
await User.query(trx).insert({ name: "Frank" });
|
|
129
|
+
await trx.commit();
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`sqliteMode` accepts `"deferred"` (default), `"immediate"`, or `"exclusive"`.
|
|
133
|
+
|
|
134
|
+
## With insertGraph
|
|
135
|
+
|
|
136
|
+
`insertGraph` respects an active transaction — pass `trx` to keep the whole graph insertion atomic:
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
await db.transaction(async (trx) => {
|
|
140
|
+
await Post.query(trx).insertGraph({
|
|
141
|
+
title: "Hello",
|
|
142
|
+
author: { name: "Alice" },
|
|
143
|
+
tags: [{ name: "typescript" }, { name: "orm" }],
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
```
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# TypeScript Transformer
|
|
2
|
+
|
|
3
|
+
The TypeScript transformer is the **recommended way to use Typhex**. It runs as a compiler plugin during `tsc`, converting arrow-function predicates to IR at build time. The result: no runtime parsing overhead and no closure boilerplate at the call site.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
### 1. Install ts-patch
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install --save-dev ts-patch
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### 2. Configure `tsconfig.json`
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"compilerOptions": {
|
|
18
|
+
"plugins": [{ "transform": "typhex/transformer" }]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### 3. Patch TypeScript (one-time)
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx ts-patch install
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
To keep the patch across reinstalls, add it as a `postinstall` script:
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"scripts": {
|
|
34
|
+
"postinstall": "ts-patch install -s"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
After this, `tsc` (or `tspc`) automatically applies the transformer whenever it compiles your project.
|
|
40
|
+
|
|
41
|
+
## What Changes at the Call Site
|
|
42
|
+
|
|
43
|
+
With the transformer, you **never need a second argument** to `.where()` or `.select()`. Closure variables are detected and injected automatically:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
// Without transformer — runtime mode
|
|
47
|
+
const country = "US";
|
|
48
|
+
users.where((u) => u.country === country, { country }); // [!code --]
|
|
49
|
+
|
|
50
|
+
// With transformer — compiler handles it
|
|
51
|
+
const country = "US";
|
|
52
|
+
users.where((u) => u.country === country); // [!code ++]
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The same applies to projections and aggregate expressions:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
const cutoff = 5;
|
|
59
|
+
orders.select((o) => ({ smalls: sum(o.qty < cutoff ? 1 : 0) }));
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Multiple variables are all captured at once:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
const minAge = 25;
|
|
66
|
+
const maxAge = 35;
|
|
67
|
+
|
|
68
|
+
const inRange = await User.query()
|
|
69
|
+
.where((u) => u.age >= minAge && u.age <= maxAge)
|
|
70
|
+
.orderBy((u) => u.name, "asc")
|
|
71
|
+
.toArray();
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Select, OrderBy, Having
|
|
75
|
+
|
|
76
|
+
The transformer handles every method that takes an arrow function — `.where()`, `.select()`, `.having()`, `.orderBy()`, `.groupBy()`:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
const minRevenue = 200;
|
|
80
|
+
|
|
81
|
+
const highRevenue = await Order.query()
|
|
82
|
+
.select((o) => ({ category: o.category, revenue: sum(o.price) }))
|
|
83
|
+
.groupBy((o) => o.category)
|
|
84
|
+
.having((o) => sum(o.price) >= minRevenue)
|
|
85
|
+
.toArray();
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Transformer-Only Query Shapes
|
|
89
|
+
|
|
90
|
+
Some query shapes depend on compile-time closure capture and are transformer-only:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
// Correlated scalar subquery in SELECT
|
|
94
|
+
Author.query().select((a) => ({
|
|
95
|
+
name: a.name,
|
|
96
|
+
postCount: Post.query()
|
|
97
|
+
.where((p) => p.authorId === a.id)
|
|
98
|
+
.select(() => count()),
|
|
99
|
+
}));
|
|
100
|
+
|
|
101
|
+
// Correlated scalar subquery in ORDER BY
|
|
102
|
+
Author.query().orderBy(
|
|
103
|
+
(a) =>
|
|
104
|
+
Post.query()
|
|
105
|
+
.where((p) => p.authorId === a.id)
|
|
106
|
+
.select(() => count()),
|
|
107
|
+
"desc",
|
|
108
|
+
);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Runtime mode still supports `IN` subqueries by passing the inner query through the params object. See [Subqueries](/guide/subqueries).
|
|
112
|
+
|
|
113
|
+
## How It Works
|
|
114
|
+
|
|
115
|
+
The transformer is a TypeScript compiler plugin. At compile time it:
|
|
116
|
+
|
|
117
|
+
1. Finds every `.where()`, `.select()`, `.having()`, `.groupBy()`, and `.orderBy()` call with an arrow function
|
|
118
|
+
2. Parses the function body into Typhex IR using the TypeScript AST
|
|
119
|
+
3. Replaces the call with `.where(compiledIr, { capturedVars... })`
|
|
120
|
+
|
|
121
|
+
The compiled output is standard JavaScript with IR pre-built — no dynamic parsing at runtime.
|
|
122
|
+
|
|
123
|
+
## Runtime Mode as Fallback
|
|
124
|
+
|
|
125
|
+
If you run files directly with `tsx` (no build step), or work in a plain JavaScript codebase, Typhex falls back to the runtime Acorn parser. Closure variables must be passed explicitly:
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
const country = "US";
|
|
129
|
+
await User.query()
|
|
130
|
+
.where((u) => u.country === country, { country })
|
|
131
|
+
.toArray();
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
SQL output is identical either way; only the call site differs.
|
|
135
|
+
|
|
136
|
+
::: warning tsx and ts-node
|
|
137
|
+
`tsx` and `ts-node` do not run the TypeScript compiler pipeline, so the transformer plugin is not invoked even if configured in `tsconfig.json`. Use `tspc` (ts-patch's compiler wrapper) or a `tsc --watch` build step to get the transformer at dev time.
|
|
138
|
+
:::
|
package/docs/index.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: home
|
|
3
|
+
|
|
4
|
+
hero:
|
|
5
|
+
name: Typhex
|
|
6
|
+
text: Arrow-function queries for TypeScript
|
|
7
|
+
tagline: Type-safe SQL without string templates or verbose builders. Write predicates like TypeScript — Typhex compiles them to safe, parameterized SQL at build time.
|
|
8
|
+
actions:
|
|
9
|
+
- theme: brand
|
|
10
|
+
text: Get Started
|
|
11
|
+
link: /guide/getting-started
|
|
12
|
+
- theme: alt
|
|
13
|
+
text: View on GitHub
|
|
14
|
+
link: https://github.com/kalyvasio/typhex
|
|
15
|
+
|
|
16
|
+
features:
|
|
17
|
+
- title: Arrow-Function Predicates
|
|
18
|
+
details: Write `users.where(u => u.age > 18)` — no string templates, no SQL injection, no verbose builder syntax. Predicates compile to SQL at build time via the TypeScript transformer.
|
|
19
|
+
- title: TypeScript-Native
|
|
20
|
+
details: Types flow from your schema definition — no decorators, no code generation. The compiler plugin auto-captures closure variables so there's no boilerplate at the call site.
|
|
21
|
+
- title: Relations & Joins
|
|
22
|
+
details: Declare `manyToOne`, `oneToMany`, and `manyToMany` relations. Reference them in `where()` for automatic JOINs and `select()` for eager loading — never N+1.
|
|
23
|
+
- title: Expression Queries
|
|
24
|
+
details: Use ternaries, arithmetic, bitwise operators, null checks, and computed projections inside `where()`, `select()`, aggregate arguments, `having()`, and `orderBy()`.
|
|
25
|
+
- title: Aggregations
|
|
26
|
+
details: Full GROUP BY / HAVING support with `sum()`, `avg()`, `min()`, `max()`, `count()`, `distinct()`, and `groupConcat()`. Filter groups with arrow-function `having()` predicates.
|
|
27
|
+
- title: CTEs and Subqueries
|
|
28
|
+
details: Build `WITH` clauses, recursive CTEs, `UNION ALL` branches, `IN` subqueries, and transformer-backed correlated scalar subqueries.
|
|
29
|
+
- title: Transactions
|
|
30
|
+
details: Callback API with implicit AsyncLocalStorage propagation. Explicit API for service-layer patterns. Nested savepoints. Configurable isolation levels.
|
|
31
|
+
- title: SQLite + PostgreSQL
|
|
32
|
+
details: Built-in drivers for both databases. Bulk inserts, upserts (`onConflict`), and `insertGraph` for nested object graphs. The query API is identical across drivers.
|
|
33
|
+
---
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Migrations
|
|
2
|
+
|
|
3
|
+
Typhex includes a schema-diffing migration system. Define your entities, generate SQL migration files, apply them to the database, and inspect their status.
|
|
4
|
+
|
|
5
|
+
## API
|
|
6
|
+
|
|
7
|
+
### `db.generateMigrations(dir)`
|
|
8
|
+
|
|
9
|
+
Diffs current entity definitions against the database and writes new `.js` migration modules for any schema changes.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
const files = await db.generateMigrations("./migrations");
|
|
13
|
+
// Returns: { name: string, upSql: string, downSql: string, content: string }[]
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
On first run (no existing migration files), generates `CREATE TABLE` statements for all registered entities. On subsequent runs, generates `ALTER TABLE` statements for any new columns detected.
|
|
17
|
+
|
|
18
|
+
### `db.runMigrations(dir)`
|
|
19
|
+
|
|
20
|
+
Applies all pending migration files in `dir`, in lexicographic order by filename.
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
const result = await db.runMigrations("./migrations");
|
|
24
|
+
// Returns: { applied: string[], skipped: string[] }
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Files already applied (tracked in a `_typhex_migrations` table) are skipped.
|
|
28
|
+
|
|
29
|
+
### `db.migrationStatus(dir)`
|
|
30
|
+
|
|
31
|
+
Inspects which migrations have been applied and which are pending.
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
const status = await db.migrationStatus("./migrations");
|
|
35
|
+
// Returns: { applied: MigrationRecord[], pending: string[] }
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Workflow
|
|
39
|
+
|
|
40
|
+
A typical migration flow:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { Db, Entity, createSqliteDriver } from "typhex";
|
|
44
|
+
|
|
45
|
+
const User = Entity("users", {
|
|
46
|
+
id: "integer primary key autoincrement",
|
|
47
|
+
name: "text not null",
|
|
48
|
+
email: "text",
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const db = new Db(createSqliteDriver({ path: "./app.db" }));
|
|
52
|
+
|
|
53
|
+
// 1. Generate any new migrations from current entity definitions
|
|
54
|
+
await db.generateMigrations("./migrations");
|
|
55
|
+
|
|
56
|
+
// 2. Apply them
|
|
57
|
+
await db.runMigrations("./migrations");
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The first run creates files like:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
migrations/
|
|
64
|
+
2026042823220001_add_users_table.js
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Each file exports SQL plus executable `up(db)` and `down(db)` functions:
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
export const upSql = `CREATE TABLE IF NOT EXISTS "users" ("id" integer primary key autoincrement, "name" text not null, "email" text);`;
|
|
71
|
+
|
|
72
|
+
export const downSql = `DROP TABLE IF EXISTS "users";`;
|
|
73
|
+
|
|
74
|
+
export async function up(db) {
|
|
75
|
+
await db.run(upSql);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export async function down(db) {
|
|
79
|
+
await db.run(downSql);
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
When you add a column to your entity (e.g., `age: "integer"`), the next `generateMigrations()` call writes a new file:
|
|
84
|
+
|
|
85
|
+
```sql
|
|
86
|
+
-- 2026042823230001_add_age_column_on_users.js
|
|
87
|
+
ALTER TABLE users ADD COLUMN age integer;
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`runMigrations()` then applies only the new file — already-applied files are skipped.
|
|
91
|
+
|
|
92
|
+
## PostgreSQL
|
|
93
|
+
|
|
94
|
+
The migration API is identical for PostgreSQL. Use PostgreSQL column types in your schema:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import { Db, Entity, createPostgresDriver } from "typhex";
|
|
98
|
+
|
|
99
|
+
const User = Entity("users", {
|
|
100
|
+
id: "SERIAL PRIMARY KEY",
|
|
101
|
+
name: "VARCHAR(255) NOT NULL",
|
|
102
|
+
email: "VARCHAR(255)",
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
const db = new Db(
|
|
106
|
+
createPostgresDriver({
|
|
107
|
+
connectionString: process.env.TYPHEX_POSTGRES_URL!,
|
|
108
|
+
}),
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
await db.generateMigrations("./migrations");
|
|
112
|
+
await db.runMigrations("./migrations");
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## CLI
|
|
116
|
+
|
|
117
|
+
Typhex ships a CLI that loads a `typhex.config.js` from your project root:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
npx typhex migrate:generate --entities ./dist/entities.js --db ./app.db --dir ./migrations
|
|
121
|
+
npx typhex migrate:run --db ./app.db --dir ./migrations
|
|
122
|
+
npx typhex migrate:status --db ./app.db --dir ./migrations
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The same config can create a `Db` in application code:
|
|
126
|
+
|
|
127
|
+
```js
|
|
128
|
+
// typhex.config.js
|
|
129
|
+
export default {
|
|
130
|
+
dialect: "sqlite",
|
|
131
|
+
database: "./app.db",
|
|
132
|
+
migrationsFolder: "./migrations",
|
|
133
|
+
entities: "./dist/entities.js",
|
|
134
|
+
};
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import { Db } from "typhex";
|
|
139
|
+
|
|
140
|
+
const db = await Db.fromConfig();
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Use `url` instead of `database` for PostgreSQL connection strings.
|