neoorm 0.8.0 → 0.8.2
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/README.md +13 -6
- package/dist/bin/neoorm.d.ts +1 -1
- package/dist/bin/neoorm.d.ts.map +1 -1
- package/dist/bin/neoorm.js +148 -75
- package/dist/bin/neoorm.js.map +1 -1
- package/dist/codegen/diff-manifest.d.ts.map +1 -1
- package/dist/codegen/diff-manifest.js +106 -4
- package/dist/codegen/diff-manifest.js.map +1 -1
- package/dist/codegen/generate-summary.d.ts +5 -1
- package/dist/codegen/generate-summary.d.ts.map +1 -1
- package/dist/codegen/generate-summary.js +10 -1
- package/dist/codegen/generate-summary.js.map +1 -1
- package/dist/codegen/generate.d.ts +24 -4
- package/dist/codegen/generate.d.ts.map +1 -1
- package/dist/codegen/generate.js +150 -13
- package/dist/codegen/generate.js.map +1 -1
- package/dist/codegen/manifest-relations.d.ts +2 -0
- package/dist/codegen/manifest-relations.d.ts.map +1 -1
- package/dist/codegen/manifest-relations.js +2 -1
- package/dist/codegen/manifest-relations.js.map +1 -1
- package/dist/codegen/schema-to-manifest.d.ts +1 -1
- package/dist/codegen/schema-to-manifest.d.ts.map +1 -1
- package/dist/codegen/schema-to-manifest.js +349 -29
- package/dist/codegen/schema-to-manifest.js.map +1 -1
- package/dist/codegen/validation/emit-elysia.d.ts +4 -0
- package/dist/codegen/validation/emit-elysia.d.ts.map +1 -0
- package/dist/codegen/validation/emit-elysia.js +304 -0
- package/dist/codegen/validation/emit-elysia.js.map +1 -0
- package/dist/codegen/validation/emit-typebox.d.ts +4 -0
- package/dist/codegen/validation/emit-typebox.d.ts.map +1 -0
- package/dist/codegen/validation/emit-typebox.js +360 -0
- package/dist/codegen/validation/emit-typebox.js.map +1 -0
- package/dist/codegen/validation/emit-zod.d.ts +4 -0
- package/dist/codegen/validation/emit-zod.d.ts.map +1 -0
- package/dist/codegen/validation/emit-zod.js +288 -0
- package/dist/codegen/validation/emit-zod.js.map +1 -0
- package/dist/codegen/validation/from-manifest.d.ts +5 -0
- package/dist/codegen/validation/from-manifest.d.ts.map +1 -0
- package/dist/codegen/validation/from-manifest.js +284 -0
- package/dist/codegen/validation/from-manifest.js.map +1 -0
- package/dist/codegen/validation/infer.d.ts +47 -0
- package/dist/codegen/validation/infer.d.ts.map +1 -0
- package/dist/codegen/validation/infer.js +2 -0
- package/dist/codegen/validation/infer.js.map +1 -0
- package/dist/codegen/validation/json-generic-types.d.ts +7 -0
- package/dist/codegen/validation/json-generic-types.d.ts.map +1 -0
- package/dist/codegen/validation/json-generic-types.js +295 -0
- package/dist/codegen/validation/json-generic-types.js.map +1 -0
- package/dist/codegen/validation/types.d.ts +84 -0
- package/dist/codegen/validation/types.d.ts.map +1 -0
- package/dist/codegen/validation/types.js +6 -0
- package/dist/codegen/validation/types.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +30 -0
- package/dist/config.js.map +1 -1
- package/dist/datasource-provider.d.ts +5 -1
- package/dist/datasource-provider.d.ts.map +1 -1
- package/dist/datasource-provider.js +21 -2
- package/dist/datasource-provider.js.map +1 -1
- package/dist/dialect/column-kind-support.d.ts +9 -0
- package/dist/dialect/column-kind-support.d.ts.map +1 -0
- package/dist/dialect/column-kind-support.js +25 -0
- package/dist/dialect/column-kind-support.js.map +1 -0
- package/dist/dialect/fk.d.ts +30 -1
- package/dist/dialect/fk.d.ts.map +1 -1
- package/dist/dialect/fk.js +113 -0
- package/dist/dialect/fk.js.map +1 -1
- package/dist/dialect/index.d.ts +6 -1
- package/dist/dialect/index.d.ts.map +1 -1
- package/dist/dialect/index.js +5 -0
- package/dist/dialect/index.js.map +1 -1
- package/dist/dialect/mariadb.d.ts +4 -0
- package/dist/dialect/mariadb.d.ts.map +1 -0
- package/dist/dialect/mariadb.js +15 -0
- package/dist/dialect/mariadb.js.map +1 -0
- package/dist/dialect/mariadb.test.d.ts +2 -0
- package/dist/dialect/mariadb.test.d.ts.map +1 -0
- package/dist/dialect/mariadb.test.js +151 -0
- package/dist/dialect/mariadb.test.js.map +1 -0
- package/dist/dialect/mysql-family.d.ts +14 -0
- package/dist/dialect/mysql-family.d.ts.map +1 -0
- package/dist/dialect/mysql-family.js +453 -0
- package/dist/dialect/mysql-family.js.map +1 -0
- package/dist/dialect/mysql.d.ts +6 -0
- package/dist/dialect/mysql.d.ts.map +1 -0
- package/dist/dialect/mysql.js +16 -0
- package/dist/dialect/mysql.js.map +1 -0
- package/dist/dialect/mysql.test.d.ts +2 -0
- package/dist/dialect/mysql.test.d.ts.map +1 -0
- package/dist/dialect/mysql.test.js +211 -0
- package/dist/dialect/mysql.test.js.map +1 -0
- package/dist/dialect/placeholders.d.ts +7 -0
- package/dist/dialect/placeholders.d.ts.map +1 -0
- package/dist/dialect/placeholders.js +18 -0
- package/dist/dialect/placeholders.js.map +1 -0
- package/dist/dialect/postgres.d.ts +2 -1
- package/dist/dialect/postgres.d.ts.map +1 -1
- package/dist/dialect/postgres.js +93 -30
- package/dist/dialect/postgres.js.map +1 -1
- package/dist/dialect/resolve.d.ts +13 -0
- package/dist/dialect/resolve.d.ts.map +1 -0
- package/dist/dialect/resolve.js +66 -0
- package/dist/dialect/resolve.js.map +1 -0
- package/dist/dialect/shared.d.ts +8 -1
- package/dist/dialect/shared.d.ts.map +1 -1
- package/dist/dialect/shared.js +37 -0
- package/dist/dialect/shared.js.map +1 -1
- package/dist/dialect/sqlite.d.ts.map +1 -1
- package/dist/dialect/sqlite.js +50 -18
- package/dist/dialect/sqlite.js.map +1 -1
- package/dist/dialect/sqlite.test.js +43 -1
- package/dist/dialect/sqlite.test.js.map +1 -1
- package/dist/dialect/types.d.ts +60 -3
- package/dist/dialect/types.d.ts.map +1 -1
- package/dist/docs/pages.d.ts.map +1 -1
- package/dist/docs/pages.js +5 -0
- package/dist/docs/pages.js.map +1 -1
- package/dist/docs/render.js +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/init/scaffold.d.ts +2 -1
- package/dist/init/scaffold.d.ts.map +1 -1
- package/dist/init/scaffold.js.map +1 -1
- package/dist/init/templates.d.ts +3 -2
- package/dist/init/templates.d.ts.map +1 -1
- package/dist/init/templates.js +19 -9
- package/dist/init/templates.js.map +1 -1
- package/dist/introspect/group-fks.d.ts +24 -0
- package/dist/introspect/group-fks.d.ts.map +1 -0
- package/dist/introspect/group-fks.js +48 -0
- package/dist/introspect/group-fks.js.map +1 -0
- package/dist/introspect/mysql/to-manifest.d.ts +4 -0
- package/dist/introspect/mysql/to-manifest.d.ts.map +1 -0
- package/dist/introspect/mysql/to-manifest.js +317 -0
- package/dist/introspect/mysql/to-manifest.js.map +1 -0
- package/dist/introspect/pull.d.ts +1 -0
- package/dist/introspect/pull.d.ts.map +1 -1
- package/dist/introspect/pull.js +186 -9
- package/dist/introspect/pull.js.map +1 -1
- package/dist/introspect/queries.d.ts +11 -1
- package/dist/introspect/queries.d.ts.map +1 -1
- package/dist/introspect/queries.js +43 -12
- package/dist/introspect/queries.js.map +1 -1
- package/dist/introspect/sqlite/to-manifest.d.ts.map +1 -1
- package/dist/introspect/sqlite/to-manifest.js +99 -26
- package/dist/introspect/sqlite/to-manifest.js.map +1 -1
- package/dist/introspect/to-manifest.d.ts.map +1 -1
- package/dist/introspect/to-manifest.js +154 -28
- package/dist/introspect/to-manifest.js.map +1 -1
- package/dist/migrate/dev-lock.d.ts +15 -0
- package/dist/migrate/dev-lock.d.ts.map +1 -0
- package/dist/migrate/dev-lock.js +101 -0
- package/dist/migrate/dev-lock.js.map +1 -0
- package/dist/migrate/runner.d.ts.map +1 -1
- package/dist/migrate/runner.js +143 -51
- package/dist/migrate/runner.js.map +1 -1
- package/dist/plugins/builtin.d.ts +62 -12
- package/dist/plugins/builtin.d.ts.map +1 -1
- package/dist/plugins/builtin.js +378 -30
- package/dist/plugins/builtin.js.map +1 -1
- package/dist/plugins/index.d.ts +1 -0
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/json/operators.d.ts.map +1 -1
- package/dist/plugins/json/operators.js +69 -3
- package/dist/plugins/json/operators.js.map +1 -1
- package/dist/plugins/postgis/columns.d.ts.map +1 -1
- package/dist/plugins/postgis/columns.js +52 -0
- package/dist/plugins/postgis/columns.js.map +1 -1
- package/dist/plugins/postgis/columns.test.js +13 -0
- package/dist/plugins/postgis/columns.test.js.map +1 -1
- package/dist/plugins/postgis/operators.d.ts.map +1 -1
- package/dist/plugins/postgis/operators.js +15 -3
- package/dist/plugins/postgis/operators.js.map +1 -1
- package/dist/plugins/types.d.ts +3 -0
- package/dist/plugins/types.d.ts.map +1 -1
- package/dist/runtime/client.d.ts +31 -4
- package/dist/runtime/client.d.ts.map +1 -1
- package/dist/runtime/client.js +131 -6
- package/dist/runtime/client.js.map +1 -1
- package/dist/runtime/driver.d.ts +2 -0
- package/dist/runtime/driver.d.ts.map +1 -1
- package/dist/runtime/driver.js +12 -0
- package/dist/runtime/driver.js.map +1 -1
- package/dist/runtime/error-hints.d.ts.map +1 -1
- package/dist/runtime/error-hints.js +37 -10
- package/dist/runtime/error-hints.js.map +1 -1
- package/dist/runtime/executor.d.ts +1 -0
- package/dist/runtime/executor.d.ts.map +1 -1
- package/dist/runtime/executor.js +7 -1
- package/dist/runtime/executor.js.map +1 -1
- package/dist/runtime/mariadb-driver.d.ts +25 -0
- package/dist/runtime/mariadb-driver.d.ts.map +1 -0
- package/dist/runtime/mariadb-driver.js +103 -0
- package/dist/runtime/mariadb-driver.js.map +1 -0
- package/dist/runtime/mysql-driver.d.ts +25 -0
- package/dist/runtime/mysql-driver.d.ts.map +1 -0
- package/dist/runtime/mysql-driver.js +101 -0
- package/dist/runtime/mysql-driver.js.map +1 -0
- package/dist/runtime/mysql-error.d.ts +15 -0
- package/dist/runtime/mysql-error.d.ts.map +1 -0
- package/dist/runtime/mysql-error.js +119 -0
- package/dist/runtime/mysql-error.js.map +1 -0
- package/dist/runtime/mysql-family-pool.d.ts +50 -0
- package/dist/runtime/mysql-family-pool.d.ts.map +1 -0
- package/dist/runtime/mysql-family-pool.js +52 -0
- package/dist/runtime/mysql-family-pool.js.map +1 -0
- package/dist/runtime/mysql-family-pool.test.d.ts +2 -0
- package/dist/runtime/mysql-family-pool.test.d.ts.map +1 -0
- package/dist/runtime/mysql-family-pool.test.js +169 -0
- package/dist/runtime/mysql-family-pool.test.js.map +1 -0
- package/dist/runtime/mysql-placeholders.d.ts +18 -0
- package/dist/runtime/mysql-placeholders.d.ts.map +1 -0
- package/dist/runtime/mysql-placeholders.js +133 -0
- package/dist/runtime/mysql-placeholders.js.map +1 -0
- package/dist/runtime/mysql-placeholders.test.d.ts +2 -0
- package/dist/runtime/mysql-placeholders.test.d.ts.map +1 -0
- package/dist/runtime/mysql-placeholders.test.js +33 -0
- package/dist/runtime/mysql-placeholders.test.js.map +1 -0
- package/dist/runtime/query/aggregate.d.ts.map +1 -1
- package/dist/runtime/query/aggregate.js +3 -3
- package/dist/runtime/query/aggregate.js.map +1 -1
- package/dist/runtime/query/compile-aggregate.d.ts +1 -1
- package/dist/runtime/query/compile-aggregate.d.ts.map +1 -1
- package/dist/runtime/query/compile-aggregate.js +33 -28
- package/dist/runtime/query/compile-aggregate.js.map +1 -1
- package/dist/runtime/query/compile-where.d.ts +9 -9
- package/dist/runtime/query/compile-where.d.ts.map +1 -1
- package/dist/runtime/query/compile-where.js +108 -76
- package/dist/runtime/query/compile-where.js.map +1 -1
- package/dist/runtime/query/compile-write.d.ts +9 -9
- package/dist/runtime/query/compile-write.d.ts.map +1 -1
- package/dist/runtime/query/compile-write.js +77 -63
- package/dist/runtime/query/compile-write.js.map +1 -1
- package/dist/runtime/query/count.d.ts.map +1 -1
- package/dist/runtime/query/count.js +4 -1
- package/dist/runtime/query/count.js.map +1 -1
- package/dist/runtime/query/create.d.ts.map +1 -1
- package/dist/runtime/query/create.js +38 -12
- package/dist/runtime/query/create.js.map +1 -1
- package/dist/runtime/query/cursor.d.ts +1 -1
- package/dist/runtime/query/cursor.d.ts.map +1 -1
- package/dist/runtime/query/cursor.js +6 -7
- package/dist/runtime/query/cursor.js.map +1 -1
- package/dist/runtime/query/delete.d.ts.map +1 -1
- package/dist/runtime/query/delete.js +41 -15
- package/dist/runtime/query/delete.js.map +1 -1
- package/dist/runtime/query/execute.d.ts +1 -0
- package/dist/runtime/query/execute.d.ts.map +1 -1
- package/dist/runtime/query/execute.js +23 -8
- package/dist/runtime/query/execute.js.map +1 -1
- package/dist/runtime/query/find-or-create.d.ts +1 -1
- package/dist/runtime/query/find-or-create.d.ts.map +1 -1
- package/dist/runtime/query/find-or-create.js +16 -8
- package/dist/runtime/query/find-or-create.js.map +1 -1
- package/dist/runtime/query/find.d.ts +2 -0
- package/dist/runtime/query/find.d.ts.map +1 -1
- package/dist/runtime/query/find.js +116 -68
- package/dist/runtime/query/find.js.map +1 -1
- package/dist/runtime/query/group-by.d.ts.map +1 -1
- package/dist/runtime/query/group-by.js.map +1 -1
- package/dist/runtime/query/mutation-returning.d.ts +10 -0
- package/dist/runtime/query/mutation-returning.d.ts.map +1 -0
- package/dist/runtime/query/mutation-returning.js +85 -0
- package/dist/runtime/query/mutation-returning.js.map +1 -0
- package/dist/runtime/query/paginate.d.ts.map +1 -1
- package/dist/runtime/query/paginate.js +3 -3
- package/dist/runtime/query/paginate.js.map +1 -1
- package/dist/runtime/query/projection.d.ts.map +1 -1
- package/dist/runtime/query/projection.js +1 -1
- package/dist/runtime/query/projection.js.map +1 -1
- package/dist/runtime/query/relation-join.d.ts +5 -0
- package/dist/runtime/query/relation-join.d.ts.map +1 -0
- package/dist/runtime/query/relation-join.js +26 -0
- package/dist/runtime/query/relation-join.js.map +1 -0
- package/dist/runtime/query/relation-planner.d.ts +1 -1
- package/dist/runtime/query/relation-planner.d.ts.map +1 -1
- package/dist/runtime/query/relation-planner.js +72 -58
- package/dist/runtime/query/relation-planner.js.map +1 -1
- package/dist/runtime/query/relation-writes.d.ts +2 -2
- package/dist/runtime/query/relation-writes.d.ts.map +1 -1
- package/dist/runtime/query/relation-writes.js +272 -116
- package/dist/runtime/query/relation-writes.js.map +1 -1
- package/dist/runtime/query/table-index.d.ts +1 -1
- package/dist/runtime/query/table-index.d.ts.map +1 -1
- package/dist/runtime/query/table-index.js +17 -10
- package/dist/runtime/query/table-index.js.map +1 -1
- package/dist/runtime/query/unique.d.ts +3 -0
- package/dist/runtime/query/unique.d.ts.map +1 -1
- package/dist/runtime/query/unique.js +26 -6
- package/dist/runtime/query/unique.js.map +1 -1
- package/dist/runtime/query/unique.test.js +110 -7
- package/dist/runtime/query/unique.test.js.map +1 -1
- package/dist/runtime/query/update.d.ts.map +1 -1
- package/dist/runtime/query/update.js +89 -23
- package/dist/runtime/query/update.js.map +1 -1
- package/dist/runtime/query/updated-at.js +2 -2
- package/dist/runtime/query/updated-at.js.map +1 -1
- package/dist/runtime/query/upsert.d.ts.map +1 -1
- package/dist/runtime/query/upsert.js +29 -5
- package/dist/runtime/query/upsert.js.map +1 -1
- package/dist/runtime/sqlite-open.js +1 -1
- package/dist/runtime/sqlite-open.js.map +1 -1
- package/dist/runtime/transaction.d.ts +1 -0
- package/dist/runtime/transaction.d.ts.map +1 -1
- package/dist/runtime/transaction.js +8 -0
- package/dist/runtime/transaction.js.map +1 -1
- package/dist/runtime/types.d.ts +10 -2
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/schema/column-constraints.d.ts +26 -0
- package/dist/schema/column-constraints.d.ts.map +1 -0
- package/dist/schema/column-constraints.js +143 -0
- package/dist/schema/column-constraints.js.map +1 -0
- package/dist/schema/column.d.ts +92 -3
- package/dist/schema/column.d.ts.map +1 -1
- package/dist/schema/column.js +17 -11
- package/dist/schema/column.js.map +1 -1
- package/dist/schema/index.d.ts +9 -6
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +8 -2
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/json-column.d.ts +9 -0
- package/dist/schema/json-column.d.ts.map +1 -0
- package/dist/schema/json-column.js +11 -0
- package/dist/schema/json-column.js.map +1 -0
- package/dist/schema/many-to-many.d.ts +1 -1
- package/dist/schema/many-to-many.d.ts.map +1 -1
- package/dist/schema/nested-relation-types.d.ts +10 -9
- package/dist/schema/nested-relation-types.d.ts.map +1 -1
- package/dist/schema/relation-types.d.ts +80 -19
- package/dist/schema/relation-types.d.ts.map +1 -1
- package/dist/schema/relation.d.ts +11 -1
- package/dist/schema/relation.d.ts.map +1 -1
- package/dist/schema/relation.js +6 -0
- package/dist/schema/relation.js.map +1 -1
- package/dist/schema/table.d.ts +74 -11
- package/dist/schema/table.d.ts.map +1 -1
- package/dist/schema/table.js +93 -7
- package/dist/schema/table.js.map +1 -1
- package/dist/schema/types.d.ts +7 -6
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/sql/builder.d.ts +13 -3
- package/dist/sql/builder.d.ts.map +1 -1
- package/dist/sql/builder.js +155 -5
- package/dist/sql/builder.js.map +1 -1
- package/dist/sql/index.d.ts +1 -0
- package/dist/sql/index.d.ts.map +1 -1
- package/dist/sql/index.js.map +1 -1
- package/dist/sql/qualify-tables.d.ts +15 -0
- package/dist/sql/qualify-tables.d.ts.map +1 -0
- package/dist/sql/qualify-tables.js +206 -0
- package/dist/sql/qualify-tables.js.map +1 -0
- package/dist/sql/template.d.ts +5 -0
- package/dist/sql/template.d.ts.map +1 -1
- package/dist/sql/template.js +23 -3
- package/dist/sql/template.js.map +1 -1
- package/dist/utils/load-ts.d.ts +2 -1
- package/dist/utils/load-ts.d.ts.map +1 -1
- package/dist/utils/load-ts.js +13 -1
- package/dist/utils/load-ts.js.map +1 -1
- package/docs/cli.md +4 -4
- package/docs/configuration.md +12 -5
- package/docs/elysia.md +131 -0
- package/docs/errors.md +1 -1
- package/docs/examples.md +4 -2
- package/docs/getting-started.md +28 -2
- package/docs/mariadb.md +149 -0
- package/docs/migrations.md +5 -3
- package/docs/mysql.md +134 -0
- package/docs/plugins.md +2 -0
- package/docs/queries.md +14 -11
- package/docs/relations.md +19 -4
- package/docs/schema.md +100 -9
- package/docs/sqlite.md +14 -2
- package/docs/typebox.md +139 -0
- package/docs/zod.md +128 -0
- package/package.json +33 -3
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
import { isSqliteProvider, } from "../datasource-provider.js";
|
|
1
|
+
import { isMariadbProvider, isMysqlFamilyProvider, isSqliteProvider, } from "../datasource-provider.js";
|
|
2
|
+
import { MYSQL_UNSUPPORTED_COLUMN_KINDS, mysqlUnsupportedColumnKindMessage, SQLITE_UNSUPPORTED_COLUMN_KINDS, sqliteUnsupportedColumnKindMessage, } from "../dialect/column-kind-support.js";
|
|
2
3
|
import { parseFkTarget } from "../dialect/fk.js";
|
|
3
4
|
import { resolveIndexSqlName } from "../dialect/postgres.js";
|
|
4
5
|
import { collectExtensionsForKinds, getColumnType, getPluginRegistry, } from "../plugins/registry.js";
|
|
5
6
|
import { schemaError } from "../runtime/error-builders.js";
|
|
6
7
|
import { formatCandidateList, listColumnTsNames, listTableAccessors, suggestSchemaColumn, suggestSchemaTableAccessor, } from "../runtime/error-hints.js";
|
|
7
8
|
import { resolveFkTargetSqlColumn } from "../runtime/query/primary-key.js";
|
|
9
|
+
import { compileColumnCheckConstraints, quoteSqlColumn, } from "../schema/column-constraints.js";
|
|
8
10
|
import { fk, resolveFkAccessorTarget, } from "../schema/relation.js";
|
|
9
|
-
import { findPrimaryKeyColumn, } from "../schema/table.js";
|
|
11
|
+
import { findPrimaryKeyColumn, isIndexExpr, } from "../schema/table.js";
|
|
10
12
|
import { resolveSqlColumnName } from "../utils/case.js";
|
|
11
13
|
import { singularize } from "../utils/inflect.js";
|
|
12
|
-
|
|
14
|
+
const POSTGIS_COLUMN_KINDS = new Set(["geometry", "geography", "point"]);
|
|
15
|
+
function buildEnumCheckExpression(sqlName, values, provider) {
|
|
13
16
|
const quoted = values
|
|
14
17
|
.map((value) => `'${value.replace(/'/g, "''")}'`)
|
|
15
18
|
.join(", ");
|
|
16
|
-
return
|
|
19
|
+
return `${quoteSqlColumn(sqlName, provider)} IN (${quoted})`;
|
|
17
20
|
}
|
|
18
21
|
function resolveEnumTypeName(tableSqlName, columnSqlName, explicitName) {
|
|
19
22
|
return explicitName ?? `${tableSqlName}_${columnSqlName}`;
|
|
@@ -28,7 +31,7 @@ function requireColumnDef(columns, tsName, tableAccessor) {
|
|
|
28
31
|
function inferFkAs(tsName) {
|
|
29
32
|
return tsName.replace(/_(Id|id)$/, "").replace(/Id$/, "");
|
|
30
33
|
}
|
|
31
|
-
function
|
|
34
|
+
function _pluralize(word) {
|
|
32
35
|
if (/(s|x|z|ch|sh)$/.test(word)) {
|
|
33
36
|
return `${word}es`;
|
|
34
37
|
}
|
|
@@ -40,11 +43,11 @@ function pluralize(word) {
|
|
|
40
43
|
function autoJunctionName(leftSql, rightSql) {
|
|
41
44
|
return [leftSql, rightSql].sort().join("_");
|
|
42
45
|
}
|
|
43
|
-
function finalizeEnumColumns(manifestTables, enumMode) {
|
|
46
|
+
function finalizeEnumColumns(manifestTables, enumMode, provider) {
|
|
44
47
|
const enumTypes = {};
|
|
45
48
|
for (const table of Object.values(manifestTables)) {
|
|
46
49
|
for (const col of table.columns) {
|
|
47
|
-
if (col.kind !== "enum") {
|
|
50
|
+
if (col.kind !== "enum" && col.kind !== "enumArray") {
|
|
48
51
|
continue;
|
|
49
52
|
}
|
|
50
53
|
const values = col.typeOptions?.values;
|
|
@@ -52,7 +55,10 @@ function finalizeEnumColumns(manifestTables, enumMode) {
|
|
|
52
55
|
continue;
|
|
53
56
|
}
|
|
54
57
|
if (enumMode === "check") {
|
|
55
|
-
|
|
58
|
+
if (col.kind === "enumArray") {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const enumCheck = buildEnumCheckExpression(col.sqlName, values, provider);
|
|
56
62
|
col.checkExpression = col.checkExpression
|
|
57
63
|
? `(${col.checkExpression}) AND (${enumCheck})`
|
|
58
64
|
: enumCheck;
|
|
@@ -92,7 +98,7 @@ function resolveSqlName(tsName, col, columnNaming) {
|
|
|
92
98
|
const mapName = "_meta" in col ? col._meta.mapName : undefined;
|
|
93
99
|
return resolveSqlColumnName(tsName, columnNaming, mapName);
|
|
94
100
|
}
|
|
95
|
-
function resolveFkTargetSql(col, tables, defaultColumnNaming,
|
|
101
|
+
function resolveFkTargetSql(col, tables, defaultColumnNaming, _sourceColumnNaming) {
|
|
96
102
|
const { accessor, column } = resolveFkAccessorTarget(col._meta, tables);
|
|
97
103
|
const targetTable = tables[accessor];
|
|
98
104
|
if (!targetTable) {
|
|
@@ -117,12 +123,14 @@ function compileIndexWhere(where, columns, columnNaming, provider) {
|
|
|
117
123
|
for (const [tsName, value] of Object.entries(where)) {
|
|
118
124
|
const col = requireColumnDef(columns, tsName);
|
|
119
125
|
const sqlName = resolveSqlName(tsName, col, columnNaming);
|
|
120
|
-
const quoted =
|
|
126
|
+
const quoted = isMysqlFamilyProvider(provider)
|
|
127
|
+
? `\`${sqlName.replace(/`/g, "``")}\``
|
|
128
|
+
: `"${sqlName.replace(/"/g, '""')}"`;
|
|
121
129
|
if (value === null) {
|
|
122
130
|
parts.push(`${quoted} IS NULL`);
|
|
123
131
|
}
|
|
124
132
|
else if (typeof value === "boolean") {
|
|
125
|
-
parts.push(isSqliteProvider(provider)
|
|
133
|
+
parts.push(isSqliteProvider(provider) || isMysqlFamilyProvider(provider)
|
|
126
134
|
? `${quoted} = ${value ? 1 : 0}`
|
|
127
135
|
: `${quoted} = ${value}`);
|
|
128
136
|
}
|
|
@@ -135,7 +143,7 @@ function compileIndexWhere(where, columns, columnNaming, provider) {
|
|
|
135
143
|
}
|
|
136
144
|
return parts.join(" AND ");
|
|
137
145
|
}
|
|
138
|
-
function columnToManifest(tsName, col, columnNaming, tables, defaultColumnNaming) {
|
|
146
|
+
function columnToManifest(tsName, col, columnNaming, tables, defaultColumnNaming, provider) {
|
|
139
147
|
if (isFkBuilder(col)) {
|
|
140
148
|
const meta = col._meta;
|
|
141
149
|
const fkTarget = resolveFkTargetSql(col, tables, defaultColumnNaming, columnNaming);
|
|
@@ -162,6 +170,15 @@ function columnToManifest(tsName, col, columnNaming, tables, defaultColumnNaming
|
|
|
162
170
|
if (meta.onDelete !== undefined) {
|
|
163
171
|
result.onDelete = meta.onDelete;
|
|
164
172
|
}
|
|
173
|
+
if (meta.onUpdate !== undefined) {
|
|
174
|
+
result.onUpdate = meta.onUpdate;
|
|
175
|
+
}
|
|
176
|
+
if (meta.deferrable !== undefined) {
|
|
177
|
+
if (isMysqlFamilyProvider(provider)) {
|
|
178
|
+
throw schemaError("invalid_column", `${isMariadbProvider(provider) ? "MariaDB" : "MySQL"} does not support deferrable foreign keys`);
|
|
179
|
+
}
|
|
180
|
+
result.deferrable = meta.deferrable;
|
|
181
|
+
}
|
|
165
182
|
if (meta.hidden === true) {
|
|
166
183
|
result.hidden = true;
|
|
167
184
|
}
|
|
@@ -177,6 +194,18 @@ function columnToManifest(tsName, col, columnNaming, tables, defaultColumnNaming
|
|
|
177
194
|
if ("updatedAt" in meta && meta.updatedAt === true) {
|
|
178
195
|
validateUpdatedAtColumn(tsName, meta.kind);
|
|
179
196
|
}
|
|
197
|
+
if (isMysqlFamilyProvider(provider) &&
|
|
198
|
+
POSTGIS_COLUMN_KINDS.has(meta.kind)) {
|
|
199
|
+
throw schemaError("invalid_column", `PostGIS column kind "${meta.kind}" is not supported on ${isMariadbProvider(provider) ? "MariaDB" : "MySQL"}`);
|
|
200
|
+
}
|
|
201
|
+
if (isMysqlFamilyProvider(provider) &&
|
|
202
|
+
MYSQL_UNSUPPORTED_COLUMN_KINDS.has(meta.kind)) {
|
|
203
|
+
throw schemaError("invalid_column", mysqlUnsupportedColumnKindMessage(meta.kind, isMariadbProvider(provider) ? "MariaDB" : "MySQL"));
|
|
204
|
+
}
|
|
205
|
+
if (isSqliteProvider(provider) &&
|
|
206
|
+
SQLITE_UNSUPPORTED_COLUMN_KINDS.has(meta.kind)) {
|
|
207
|
+
throw schemaError("invalid_column", sqliteUnsupportedColumnKindMessage(meta.kind));
|
|
208
|
+
}
|
|
180
209
|
const result = {
|
|
181
210
|
tsName,
|
|
182
211
|
sqlName: resolveSqlName(tsName, col, columnNaming),
|
|
@@ -204,28 +233,130 @@ function columnToManifest(tsName, col, columnNaming, tables, defaultColumnNaming
|
|
|
204
233
|
if (meta.hidden === true) {
|
|
205
234
|
result.hidden = true;
|
|
206
235
|
}
|
|
207
|
-
|
|
208
|
-
|
|
236
|
+
const compiledCheck = compileColumnCheckConstraints(result, meta, provider);
|
|
237
|
+
if (compiledCheck !== undefined) {
|
|
238
|
+
result.checkExpression = compiledCheck;
|
|
209
239
|
}
|
|
240
|
+
copyStructuredConstraints(result, meta);
|
|
210
241
|
return result;
|
|
211
242
|
}
|
|
243
|
+
function jsonSafeConstraint(value) {
|
|
244
|
+
return typeof value === "bigint" ? value.toString() : value;
|
|
245
|
+
}
|
|
246
|
+
function copyStructuredConstraints(result, meta) {
|
|
247
|
+
if (meta.checkMin !== undefined) {
|
|
248
|
+
result.checkMin = jsonSafeConstraint(meta.checkMin);
|
|
249
|
+
}
|
|
250
|
+
if (meta.checkMax !== undefined) {
|
|
251
|
+
result.checkMax = jsonSafeConstraint(meta.checkMax);
|
|
252
|
+
}
|
|
253
|
+
if (meta.checkPositive === true) {
|
|
254
|
+
result.checkPositive = true;
|
|
255
|
+
}
|
|
256
|
+
if (meta.checkMinLength !== undefined) {
|
|
257
|
+
result.checkMinLength = meta.checkMinLength;
|
|
258
|
+
}
|
|
259
|
+
if (meta.checkMaxLength !== undefined) {
|
|
260
|
+
result.checkMaxLength = meta.checkMaxLength;
|
|
261
|
+
}
|
|
262
|
+
if (meta.checkNotEmpty === true) {
|
|
263
|
+
result.checkNotEmpty = true;
|
|
264
|
+
}
|
|
265
|
+
if (meta.checkEmail === true) {
|
|
266
|
+
result.checkEmail = true;
|
|
267
|
+
}
|
|
268
|
+
if (meta.checkUrl === true) {
|
|
269
|
+
result.checkUrl = true;
|
|
270
|
+
}
|
|
271
|
+
if (meta.validation !== undefined) {
|
|
272
|
+
result.validation = meta.validation;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function extraIndexUsing(extra) {
|
|
276
|
+
if (extra.kind !== "index")
|
|
277
|
+
return undefined;
|
|
278
|
+
if ("using" in extra && typeof extra.using === "string") {
|
|
279
|
+
return extra.using;
|
|
280
|
+
}
|
|
281
|
+
if ("_using" in extra && typeof extra._using === "string") {
|
|
282
|
+
return extra._using;
|
|
283
|
+
}
|
|
284
|
+
return undefined;
|
|
285
|
+
}
|
|
286
|
+
function extraIndexOpclass(extra) {
|
|
287
|
+
if (extra.kind !== "index")
|
|
288
|
+
return undefined;
|
|
289
|
+
if ("opclass" in extra && typeof extra.opclass === "string") {
|
|
290
|
+
return extra.opclass;
|
|
291
|
+
}
|
|
292
|
+
if ("_opclass" in extra && typeof extra._opclass === "string") {
|
|
293
|
+
return extra._opclass;
|
|
294
|
+
}
|
|
295
|
+
return undefined;
|
|
296
|
+
}
|
|
297
|
+
function extraIndexKeys(extra) {
|
|
298
|
+
if (extra.kind !== "index")
|
|
299
|
+
return [];
|
|
300
|
+
if ("keys" in extra && extra.keys)
|
|
301
|
+
return extra.keys;
|
|
302
|
+
return extra.columns;
|
|
303
|
+
}
|
|
304
|
+
function sanitizeIndexNamePart(sql) {
|
|
305
|
+
const token = sql
|
|
306
|
+
.replace(/[^A-Za-z0-9]+/g, "_")
|
|
307
|
+
.replace(/^_|_$/g, "")
|
|
308
|
+
.slice(0, 40);
|
|
309
|
+
return token.length > 0 ? token : "expr";
|
|
310
|
+
}
|
|
311
|
+
const NON_UNIQUE_INDEX_METHODS = new Set(["gin", "gist", "brin"]);
|
|
212
312
|
function extrasToManifest(extras, columns, tableSqlName, columnNaming, provider) {
|
|
213
313
|
const indexes = [];
|
|
214
314
|
let primaryKey = [];
|
|
315
|
+
const compositeFks = [];
|
|
215
316
|
for (const extra of extras) {
|
|
216
317
|
if (extra.kind === "index") {
|
|
318
|
+
const using = extraIndexUsing(extra);
|
|
319
|
+
const opclass = extraIndexOpclass(extra);
|
|
320
|
+
if (extra.unique && using && NON_UNIQUE_INDEX_METHODS.has(using)) {
|
|
321
|
+
throw schemaError("invalid_column", `UNIQUE indexes cannot use ${using}`);
|
|
322
|
+
}
|
|
323
|
+
if (using && using !== "btree") {
|
|
324
|
+
if (isSqliteProvider(provider)) {
|
|
325
|
+
throw schemaError("invalid_column", `SQLite does not support ${using} indexes`);
|
|
326
|
+
}
|
|
327
|
+
if (isMysqlFamilyProvider(provider) && using !== "hash") {
|
|
328
|
+
throw schemaError("invalid_column", `${isMariadbProvider(provider) ? "MariaDB" : "MySQL"} does not support ${using} indexes`);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
217
331
|
const wherePredicate = "where" in extra &&
|
|
218
332
|
extra.where !== undefined &&
|
|
219
333
|
typeof extra.where !== "function"
|
|
220
334
|
? extra.where
|
|
221
335
|
: undefined;
|
|
222
|
-
const
|
|
336
|
+
const keys = extraIndexKeys(extra).map((key) => {
|
|
337
|
+
if (isIndexExpr(key)) {
|
|
338
|
+
return { expr: key.sql };
|
|
339
|
+
}
|
|
340
|
+
return {
|
|
341
|
+
sqlName: resolveSqlName(key, requireColumnDef(columns, key), columnNaming),
|
|
342
|
+
};
|
|
343
|
+
});
|
|
344
|
+
const sqlColumns = keys
|
|
345
|
+
.map((key) => key.sqlName)
|
|
346
|
+
.filter((name) => name !== undefined);
|
|
347
|
+
const nameParts = keys.map((key) => key.sqlName ?? sanitizeIndexNamePart(key.expr ?? "expr"));
|
|
223
348
|
const index = {
|
|
224
|
-
name:
|
|
349
|
+
name: nameParts.join("_") || "expr",
|
|
225
350
|
columns: sqlColumns,
|
|
226
351
|
unique: extra.unique,
|
|
352
|
+
keys,
|
|
353
|
+
...(using && using !== "btree" ? { using } : {}),
|
|
354
|
+
...(opclass ? { opclass } : {}),
|
|
227
355
|
};
|
|
228
356
|
if (wherePredicate) {
|
|
357
|
+
if (isMysqlFamilyProvider(provider)) {
|
|
358
|
+
throw schemaError("invalid_column", `${isMariadbProvider(provider) ? "MariaDB" : "MySQL"} does not support partial indexes (index({ where }))`);
|
|
359
|
+
}
|
|
229
360
|
index.whereSql = compileIndexWhere(wherePredicate, columns, columnNaming, provider);
|
|
230
361
|
}
|
|
231
362
|
index.sqlName = resolveIndexSqlName(tableSqlName, index);
|
|
@@ -234,8 +365,89 @@ function extrasToManifest(extras, columns, tableSqlName, columnNaming, provider)
|
|
|
234
365
|
else if (extra.kind === "primaryKey") {
|
|
235
366
|
primaryKey = extra.columns.map((tsName) => resolveSqlName(tsName, requireColumnDef(columns, tsName), columnNaming));
|
|
236
367
|
}
|
|
368
|
+
else if (extra.kind === "foreignKey") {
|
|
369
|
+
compositeFks.push(extra);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return { indexes, primaryKey, compositeFks };
|
|
373
|
+
}
|
|
374
|
+
function rejectMysqlDeferrable(provider, deferrable) {
|
|
375
|
+
if (!deferrable)
|
|
376
|
+
return;
|
|
377
|
+
if (isMysqlFamilyProvider(provider)) {
|
|
378
|
+
throw schemaError("invalid_column", `${isMariadbProvider(provider) ? "MariaDB" : "MySQL"} does not support deferrable foreign keys`);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
function resolveCompositeForeignKeys(args) {
|
|
382
|
+
const result = [];
|
|
383
|
+
for (const extra of args.extras) {
|
|
384
|
+
if (!extra._as) {
|
|
385
|
+
throw schemaError("invalid_column", `foreignKey() on "${args.accessor}" requires .as("relationName")`);
|
|
386
|
+
}
|
|
387
|
+
if (!extra._inverse) {
|
|
388
|
+
throw schemaError("invalid_column", `foreignKey() on "${args.accessor}" requires .inverse("relationName")`);
|
|
389
|
+
}
|
|
390
|
+
if (!extra.targetTable) {
|
|
391
|
+
throw schemaError("invalid_column", `foreignKey() on "${args.accessor}" requires .references("table", ...)`);
|
|
392
|
+
}
|
|
393
|
+
if (extra.columns.length < 2) {
|
|
394
|
+
throw schemaError("invalid_column", `foreignKey() on "${args.accessor}" needs at least two local columns (use fk() for a single-column relation)`);
|
|
395
|
+
}
|
|
396
|
+
if (extra.columns.length !== extra.targetColumns.length) {
|
|
397
|
+
throw schemaError("invalid_column", `foreignKey() on "${args.accessor}" local and referenced column counts must match`);
|
|
398
|
+
}
|
|
399
|
+
rejectMysqlDeferrable(args.provider, extra._deferrable);
|
|
400
|
+
const targetDef = args.schemaTables[extra.targetTable];
|
|
401
|
+
if (!targetDef) {
|
|
402
|
+
throw schemaError("unknown_fk_target", `foreignKey() on "${args.accessor}" references unknown table accessor "${extra.targetTable}"`, { tableAccessor: args.accessor }, suggestSchemaTableAccessor(extra.targetTable, args.schemaTables));
|
|
403
|
+
}
|
|
404
|
+
const localSql = [];
|
|
405
|
+
for (const tsName of extra.columns) {
|
|
406
|
+
const def = requireColumnDef(args.localDefs, tsName, args.accessor);
|
|
407
|
+
if (isFkBuilder(def)) {
|
|
408
|
+
throw schemaError("invalid_column", `foreignKey() column "${tsName}" on "${args.accessor}" must not also be fk()`);
|
|
409
|
+
}
|
|
410
|
+
localSql.push(resolveSqlName(tsName, def, args.columnNaming));
|
|
411
|
+
}
|
|
412
|
+
const targetNaming = targetDef._columnNaming ?? args.columnNaming;
|
|
413
|
+
const targetSql = [];
|
|
414
|
+
for (const tsName of extra.targetColumns) {
|
|
415
|
+
const def = requireColumnDef(targetDef._columns, tsName, extra.targetTable);
|
|
416
|
+
targetSql.push(resolveSqlName(tsName, def, targetNaming));
|
|
417
|
+
}
|
|
418
|
+
const fk = {
|
|
419
|
+
name: extra.constraintName ??
|
|
420
|
+
`${args.tableSqlName}_${localSql.join("_")}_fkey`,
|
|
421
|
+
columns: localSql,
|
|
422
|
+
targetTable: targetDef._tableName,
|
|
423
|
+
targetColumns: targetSql,
|
|
424
|
+
};
|
|
425
|
+
if (extra._onDelete !== undefined)
|
|
426
|
+
fk.onDelete = extra._onDelete;
|
|
427
|
+
if (extra._onUpdate !== undefined)
|
|
428
|
+
fk.onUpdate = extra._onUpdate;
|
|
429
|
+
if (extra._deferrable !== undefined)
|
|
430
|
+
fk.deferrable = extra._deferrable;
|
|
431
|
+
result.push(fk);
|
|
237
432
|
}
|
|
238
|
-
return
|
|
433
|
+
return result;
|
|
434
|
+
}
|
|
435
|
+
function columnSetIsUnique(table, sqlNames) {
|
|
436
|
+
if (sqlNames.length === 0)
|
|
437
|
+
return false;
|
|
438
|
+
if (table.primaryKey.length === sqlNames.length &&
|
|
439
|
+
sqlNames.every((name) => table.primaryKey.includes(name))) {
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
442
|
+
if (sqlNames.length === 1) {
|
|
443
|
+
return isUniqueColumn(table, sqlNames[0] ?? "");
|
|
444
|
+
}
|
|
445
|
+
return table.indexes.some((idx) => idx.unique &&
|
|
446
|
+
!idx.whereSql &&
|
|
447
|
+
!(idx.using && idx.using !== "btree") &&
|
|
448
|
+
!(idx.keys?.some((key) => key.expr) ?? false) &&
|
|
449
|
+
idx.columns.length === sqlNames.length &&
|
|
450
|
+
sqlNames.every((name) => idx.columns.includes(name)));
|
|
239
451
|
}
|
|
240
452
|
function buildRelations(columns, sourceAccessor, sqlNameToAccessor, manifestTables) {
|
|
241
453
|
const relations = [];
|
|
@@ -262,6 +474,52 @@ function buildRelations(columns, sourceAccessor, sqlNameToAccessor, manifestTabl
|
|
|
262
474
|
if (col.onDelete !== undefined) {
|
|
263
475
|
rel.onDelete = col.onDelete;
|
|
264
476
|
}
|
|
477
|
+
if (col.onUpdate !== undefined) {
|
|
478
|
+
rel.onUpdate = col.onUpdate;
|
|
479
|
+
}
|
|
480
|
+
if (col.deferrable !== undefined) {
|
|
481
|
+
rel.deferrable = col.deferrable;
|
|
482
|
+
}
|
|
483
|
+
relations.push(rel);
|
|
484
|
+
}
|
|
485
|
+
return relations;
|
|
486
|
+
}
|
|
487
|
+
function extraFkRelations(table, schemaTable) {
|
|
488
|
+
const relations = [];
|
|
489
|
+
const extras = schemaTable._extras.filter((extra) => extra.kind === "foreignKey");
|
|
490
|
+
const fks = table.foreignKeys ?? [];
|
|
491
|
+
for (let i = 0; i < extras.length; i++) {
|
|
492
|
+
const extra = extras[i];
|
|
493
|
+
const fk = fks[i];
|
|
494
|
+
if (!extra || !fk)
|
|
495
|
+
continue;
|
|
496
|
+
const targetAccessor = extra.targetTable;
|
|
497
|
+
const localTs = extra.columns;
|
|
498
|
+
const firstLocal = localTs[0];
|
|
499
|
+
const firstSql = fk.columns[0];
|
|
500
|
+
const firstTarget = fk.targetColumns[0];
|
|
501
|
+
if (!firstLocal || !firstSql || !firstTarget)
|
|
502
|
+
continue;
|
|
503
|
+
const rel = {
|
|
504
|
+
name: extra._as,
|
|
505
|
+
targetTable: fk.targetTable,
|
|
506
|
+
targetAccessor,
|
|
507
|
+
fkColumn: firstLocal,
|
|
508
|
+
fkSqlColumn: firstSql,
|
|
509
|
+
targetColumn: firstTarget,
|
|
510
|
+
fkColumns: localTs,
|
|
511
|
+
fkSqlColumns: fk.columns,
|
|
512
|
+
targetColumns: fk.targetColumns,
|
|
513
|
+
referencedSqlColumns: fk.targetColumns,
|
|
514
|
+
cardinality: "one",
|
|
515
|
+
inverse: extra._inverse,
|
|
516
|
+
};
|
|
517
|
+
if (extra._onDelete !== undefined)
|
|
518
|
+
rel.onDelete = extra._onDelete;
|
|
519
|
+
if (extra._onUpdate !== undefined)
|
|
520
|
+
rel.onUpdate = extra._onUpdate;
|
|
521
|
+
if (extra._deferrable !== undefined)
|
|
522
|
+
rel.deferrable = extra._deferrable;
|
|
265
523
|
relations.push(rel);
|
|
266
524
|
}
|
|
267
525
|
return relations;
|
|
@@ -272,8 +530,10 @@ function isUniqueColumn(table, fkSqlColumn) {
|
|
|
272
530
|
return true;
|
|
273
531
|
return table.indexes.some((idx) => idx.unique &&
|
|
274
532
|
!idx.whereSql &&
|
|
533
|
+
!idx.using &&
|
|
275
534
|
idx.columns.length === 1 &&
|
|
276
|
-
idx.columns[0] === fkSqlColumn
|
|
535
|
+
idx.columns[0] === fkSqlColumn &&
|
|
536
|
+
!(idx.keys?.some((key) => key.expr) ?? false));
|
|
277
537
|
}
|
|
278
538
|
function resolveM2M(incoming) {
|
|
279
539
|
return {
|
|
@@ -298,7 +558,7 @@ function resolveM2M(incoming) {
|
|
|
298
558
|
* @param plugins - Column type plugins (defaults to built-in registry).
|
|
299
559
|
* @param options - Enum mode and datasource provider hints.
|
|
300
560
|
*/
|
|
301
|
-
export function schemaToManifest(schema,
|
|
561
|
+
export function schemaToManifest(schema, _plugins = getPluginRegistry(), options = {}) {
|
|
302
562
|
const enumMode = options.enumMode ?? "check";
|
|
303
563
|
const provider = options.provider;
|
|
304
564
|
const datasourceUrl = options.url;
|
|
@@ -314,8 +574,8 @@ export function schemaToManifest(schema, plugins = getPluginRegistry(), options
|
|
|
314
574
|
const columnNaming = tableDef._columnNaming ?? defaultColumnNaming;
|
|
315
575
|
const columns = Object.entries(tableDef._columns)
|
|
316
576
|
.filter(([, col]) => !isManyToMany(col))
|
|
317
|
-
.map(([name, col]) => columnToManifest(name, col, columnNaming, tables, defaultColumnNaming));
|
|
318
|
-
const { indexes, primaryKey } = extrasToManifest(tableDef._extras, tableDef._columns, tableDef._tableName, columnNaming, provider);
|
|
577
|
+
.map(([name, col]) => columnToManifest(name, col, columnNaming, tables, defaultColumnNaming, provider));
|
|
578
|
+
const { indexes, primaryKey, compositeFks } = extrasToManifest(tableDef._extras, tableDef._columns, tableDef._tableName, columnNaming, provider);
|
|
319
579
|
for (const col of columns) {
|
|
320
580
|
if (!col.index)
|
|
321
581
|
continue;
|
|
@@ -323,6 +583,7 @@ export function schemaToManifest(schema, plugins = getPluginRegistry(), options
|
|
|
323
583
|
name: col.sqlName,
|
|
324
584
|
columns: [col.sqlName],
|
|
325
585
|
unique: false,
|
|
586
|
+
keys: [{ sqlName: col.sqlName }],
|
|
326
587
|
};
|
|
327
588
|
const already = indexes.some((idx) => !idx.unique &&
|
|
328
589
|
idx.columns.length === 1 &&
|
|
@@ -358,6 +619,20 @@ export function schemaToManifest(schema, plugins = getPluginRegistry(), options
|
|
|
358
619
|
relations: [],
|
|
359
620
|
indexes,
|
|
360
621
|
primaryKey: pk,
|
|
622
|
+
...(compositeFks.length > 0
|
|
623
|
+
? {
|
|
624
|
+
foreignKeys: resolveCompositeForeignKeys({
|
|
625
|
+
accessor,
|
|
626
|
+
tableSqlName: tableDef._tableName,
|
|
627
|
+
columns,
|
|
628
|
+
extras: compositeFks,
|
|
629
|
+
columnNaming,
|
|
630
|
+
localDefs: tableDef._columns,
|
|
631
|
+
schemaTables: tables,
|
|
632
|
+
...(provider ? { provider } : {}),
|
|
633
|
+
}),
|
|
634
|
+
}
|
|
635
|
+
: {}),
|
|
361
636
|
};
|
|
362
637
|
}
|
|
363
638
|
const autoJunctionAccessors = new Set();
|
|
@@ -369,6 +644,11 @@ export function schemaToManifest(schema, plugins = getPluginRegistry(), options
|
|
|
369
644
|
columnToManifest(leftTsName, leftFk, columnNaming, tables, defaultColumnNaming),
|
|
370
645
|
columnToManifest(rightTsName, rightFk, columnNaming, tables, defaultColumnNaming),
|
|
371
646
|
];
|
|
647
|
+
const leftCol = columns[0];
|
|
648
|
+
const rightCol = columns[1];
|
|
649
|
+
if (!leftCol || !rightCol) {
|
|
650
|
+
throw new Error(`M2M junction "${accessor}" must have exactly two FK columns`);
|
|
651
|
+
}
|
|
372
652
|
const table = {
|
|
373
653
|
accessor,
|
|
374
654
|
sqlName,
|
|
@@ -376,7 +656,7 @@ export function schemaToManifest(schema, plugins = getPluginRegistry(), options
|
|
|
376
656
|
columns,
|
|
377
657
|
relations: [],
|
|
378
658
|
indexes: [],
|
|
379
|
-
primaryKey: [
|
|
659
|
+
primaryKey: [leftCol.sqlName, rightCol.sqlName],
|
|
380
660
|
};
|
|
381
661
|
manifestTables[accessor] = table;
|
|
382
662
|
sqlNameToAccessor[sqlName] = accessor;
|
|
@@ -451,14 +731,27 @@ export function schemaToManifest(schema, plugins = getPluginRegistry(), options
|
|
|
451
731
|
});
|
|
452
732
|
}
|
|
453
733
|
for (const table of Object.values(manifestTables)) {
|
|
454
|
-
|
|
734
|
+
for (const fk of table.foreignKeys ?? []) {
|
|
735
|
+
const target = Object.values(manifestTables).find((item) => item.sqlName === fk.targetTable);
|
|
736
|
+
if (!target) {
|
|
737
|
+
throw schemaError("unknown_fk_target", `foreignKey on "${table.accessor}" references unknown table ${fk.targetTable}`);
|
|
738
|
+
}
|
|
739
|
+
if (!columnSetIsUnique(target, fk.targetColumns)) {
|
|
740
|
+
throw schemaError("invalid_column", `foreignKey on "${table.accessor}" target (${fk.targetColumns.join(", ")}) must be a primary key or unique index on "${target.accessor}"`);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
const schemaTable = tables[table.accessor];
|
|
744
|
+
table.relations = [
|
|
745
|
+
...buildRelations(table.columns, table.accessor, sqlNameToAccessor, manifestTables),
|
|
746
|
+
...(schemaTable ? extraFkRelations(table, schemaTable) : []),
|
|
747
|
+
];
|
|
455
748
|
}
|
|
456
749
|
for (const table of Object.values(manifestTables)) {
|
|
457
750
|
if (autoJunctionAccessors.has(table.accessor))
|
|
458
751
|
continue;
|
|
459
752
|
const fkRelations = table.relations.filter((rel) => {
|
|
460
|
-
const
|
|
461
|
-
return col
|
|
753
|
+
const names = rel.fkColumns ?? [rel.fkColumn];
|
|
754
|
+
return names.every((name) => table.columns.some((col) => col.tsName === name || col.sqlName === name));
|
|
462
755
|
});
|
|
463
756
|
for (const rel of fkRelations) {
|
|
464
757
|
const inverseTable = manifestTables[rel.targetAccessor];
|
|
@@ -478,18 +771,36 @@ export function schemaToManifest(schema, plugins = getPluginRegistry(), options
|
|
|
478
771
|
"Each inverse relation name must be unique on the target table",
|
|
479
772
|
]);
|
|
480
773
|
}
|
|
481
|
-
|
|
774
|
+
const localSql = rel.fkSqlColumns ?? [rel.fkSqlColumn];
|
|
775
|
+
const inverseRel = {
|
|
482
776
|
name: rel.inverse,
|
|
483
777
|
targetTable: table.sqlName,
|
|
484
778
|
targetAccessor: table.accessor,
|
|
485
779
|
fkColumn: rel.fkColumn,
|
|
486
780
|
fkSqlColumn: rel.fkSqlColumn,
|
|
487
781
|
targetColumn: table.primaryKey[0] ?? rel.targetColumn,
|
|
488
|
-
cardinality:
|
|
782
|
+
cardinality: columnSetIsUnique(table, localSql)
|
|
489
783
|
? "one"
|
|
490
784
|
: "many",
|
|
491
785
|
inverse: rel.name,
|
|
492
|
-
}
|
|
786
|
+
};
|
|
787
|
+
if (rel.fkColumns)
|
|
788
|
+
inverseRel.fkColumns = rel.fkColumns;
|
|
789
|
+
if (rel.fkSqlColumns)
|
|
790
|
+
inverseRel.fkSqlColumns = rel.fkSqlColumns;
|
|
791
|
+
if (table.primaryKey.length > 1) {
|
|
792
|
+
inverseRel.targetColumns = table.primaryKey;
|
|
793
|
+
}
|
|
794
|
+
inverseRel.referencedSqlColumns = rel.referencedSqlColumns ??
|
|
795
|
+
rel.targetColumns ?? [rel.targetColumn];
|
|
796
|
+
if (rel.onDelete !== undefined)
|
|
797
|
+
inverseRel.onDelete = rel.onDelete;
|
|
798
|
+
if (rel.onUpdate !== undefined)
|
|
799
|
+
inverseRel.onUpdate = rel.onUpdate;
|
|
800
|
+
if (rel.deferrable !== undefined) {
|
|
801
|
+
inverseRel.deferrable = rel.deferrable;
|
|
802
|
+
}
|
|
803
|
+
inverseTable.relations.push(inverseRel);
|
|
493
804
|
}
|
|
494
805
|
}
|
|
495
806
|
const manyToMany = incomingM2Ms.map(resolveM2M);
|
|
@@ -521,7 +832,7 @@ export function schemaToManifest(schema, plugins = getPluginRegistry(), options
|
|
|
521
832
|
});
|
|
522
833
|
}
|
|
523
834
|
}
|
|
524
|
-
const enumTypes = finalizeEnumColumns(manifestTables, enumMode);
|
|
835
|
+
const enumTypes = finalizeEnumColumns(manifestTables, enumMode, provider);
|
|
525
836
|
const pluginExtensions = collectExtensionsForKinds(Object.values(manifestTables).flatMap((table) => table.columns.map((col) => col.kind)));
|
|
526
837
|
const userExtensions = schema._extensions ?? [];
|
|
527
838
|
const extensions = [...new Set([...pluginExtensions, ...userExtensions])];
|
|
@@ -590,6 +901,15 @@ export function validateManifest(manifest) {
|
|
|
590
901
|
});
|
|
591
902
|
}
|
|
592
903
|
}
|
|
904
|
+
for (const fk of table.foreignKeys ?? []) {
|
|
905
|
+
const target = Object.values(manifest.tables).find((item) => item.sqlName === fk.targetTable);
|
|
906
|
+
if (!target) {
|
|
907
|
+
errors.push({
|
|
908
|
+
code: "unknown_fk_target",
|
|
909
|
+
message: `FK constraint ${fk.name} on ${table.accessor} references unknown table ${fk.targetTable}`,
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
}
|
|
593
913
|
}
|
|
594
914
|
return errors;
|
|
595
915
|
}
|