From 23f1ed4a4805bb5477297e558d18911f0891606d Mon Sep 17 00:00:00 2001 From: Sasha <64744993+r1tsuu@users.noreply.github.com> Date: Thu, 19 Dec 2024 18:08:17 +0200 Subject: [PATCH] feat(db-postgres, db-sqlite): drizzle schema generation (#9953) This PR allows to have full type safety on `payload.drizzle` with a single command ```sh pnpm payload generate:db-schema ``` Which generates TypeScript code with Drizzle declarations based on the current database schema. Example of generated file with the website template: https://gist.github.com/r1tsuu/b8687f211b51d9a3a7e78ba41e8fbf03 Video that shows the power: https://github.com/user-attachments/assets/3ced958b-ec1d-49f5-9f51-d859d5fae236 We also now proxy drizzle package the same way we do for Lexical so you don't have to install it (and you shouldn't because you may have version mismatch). Instead, you can import from Drizzle like this: ```ts import { pgTable, index, foreignKey, integer, text, varchar, jsonb, boolean, numeric, serial, timestamp, uniqueIndex, pgEnum, } from '@payloadcms/db-postgres/drizzle/pg-core' import { sql } from '@payloadcms/db-postgres/drizzle' import { relations } from '@payloadcms/db-postgres/drizzle/relations' ``` Fixes https://github.com/payloadcms/payload/discussions/4318 In the future we can also support types generation for mongoose / raw mongodb results. --- docs/database/postgres.mdx | 64 +- docs/database/sqlite.mdx | 89 +- package.json | 1 + packages/db-postgres/package.json | 40 + .../db-postgres/src/drizzle-proxy/index.ts | 1 + .../src/drizzle-proxy/node-postgres.ts | 1 + .../db-postgres/src/drizzle-proxy/pg-core.ts | 1 + .../src/drizzle-proxy/relations.ts | 1 + packages/db-postgres/src/index.ts | 11 + packages/db-postgres/src/types.ts | 15 +- packages/db-sqlite/package.json | 40 + .../db-sqlite/src/columnToCodeConverter.ts | 126 + packages/db-sqlite/src/drizzle-proxy/index.ts | 1 + .../db-sqlite/src/drizzle-proxy/libsql.ts | 1 + .../db-sqlite/src/drizzle-proxy/relations.ts | 1 + .../src/drizzle-proxy/sqlite-core.ts | 1 + packages/db-sqlite/src/index.ts | 8 + packages/db-vercel-postgres/package.json | 40 + .../src/drizzle-proxy/index.ts | 1 + .../src/drizzle-proxy/node-postgres.ts | 1 + .../src/drizzle-proxy/pg-core.ts | 1 + .../src/drizzle-proxy/relations.ts | 1 + packages/db-vercel-postgres/src/index.ts | 11 + packages/db-vercel-postgres/src/types.ts | 16 +- packages/drizzle/src/exports/postgres.ts | 2 + packages/drizzle/src/index.ts | 1 + .../src/postgres/columnToCodeConverter.ts | 94 + packages/drizzle/src/types.ts | 9 + .../src/utilities/createSchemaGenerator.ts | 311 +++ packages/payload/src/bin/index.ts | 17 + packages/payload/src/database/types.ts | 16 +- packages/payload/src/index.ts | 1 + test/database/.gitignore | 1 + test/database/int.spec.ts | 57 +- test/database/payload-generated-schema.ts | 2112 +++++++++++++++++ test/generateDatabaseSchema.ts | 48 + test/helpers/database.ts | 0 test/jest.setup.js | 7 +- .../relationships/payload-generated-schema.ts | 1402 +++++++++++ 39 files changed, 4519 insertions(+), 32 deletions(-) create mode 100644 packages/db-postgres/src/drizzle-proxy/index.ts create mode 100644 packages/db-postgres/src/drizzle-proxy/node-postgres.ts create mode 100644 packages/db-postgres/src/drizzle-proxy/pg-core.ts create mode 100644 packages/db-postgres/src/drizzle-proxy/relations.ts create mode 100644 packages/db-sqlite/src/columnToCodeConverter.ts create mode 100644 packages/db-sqlite/src/drizzle-proxy/index.ts create mode 100644 packages/db-sqlite/src/drizzle-proxy/libsql.ts create mode 100644 packages/db-sqlite/src/drizzle-proxy/relations.ts create mode 100644 packages/db-sqlite/src/drizzle-proxy/sqlite-core.ts create mode 100644 packages/db-vercel-postgres/src/drizzle-proxy/index.ts create mode 100644 packages/db-vercel-postgres/src/drizzle-proxy/node-postgres.ts create mode 100644 packages/db-vercel-postgres/src/drizzle-proxy/pg-core.ts create mode 100644 packages/db-vercel-postgres/src/drizzle-proxy/relations.ts create mode 100644 packages/drizzle/src/postgres/columnToCodeConverter.ts create mode 100644 packages/drizzle/src/utilities/createSchemaGenerator.ts create mode 100644 test/database/payload-generated-schema.ts create mode 100644 test/generateDatabaseSchema.ts create mode 100644 test/helpers/database.ts create mode 100644 test/relationships/payload-generated-schema.ts diff --git a/docs/database/postgres.mdx b/docs/database/postgres.mdx index f4c0166fa9..93cd7d8f31 100644 --- a/docs/database/postgres.mdx +++ b/docs/database/postgres.mdx @@ -65,21 +65,33 @@ export default buildConfig({ | `schemaName` (experimental) | A string for the postgres schema to use, defaults to 'public'. | | `idType` | A string of 'serial', or 'uuid' that is used for the data type given to id columns. | | `transactionOptions` | A PgTransactionConfig object for transactions, or set to `false` to disable using transactions. [More details](https://orm.drizzle.team/docs/transactions) | -| `disableCreateDatabase` | Pass `true` to disable auto database creation if it doesn't exist. Defaults to `false`. | +| `disableCreateDatabase` | Pass `true` to disable auto database creation if it doesn't exist. Defaults to `false`. | | `localesSuffix` | A string appended to the end of table names for storing localized fields. Default is '_locales'. | | `relationshipsSuffix` | A string appended to the end of table names for storing relationships. Default is '_rels'. | | `versionsSuffix` | A string appended to the end of table names for storing versions. Defaults to '_v'. | | `beforeSchemaInit` | Drizzle schema hook. Runs before the schema is built. [More Details](#beforeschemainit) | | `afterSchemaInit` | Drizzle schema hook. Runs after the schema is built. [More Details](#afterschemainit) | +| `generateSchemaOutputFile` | Override generated schema from `payload generate:db-schema` file path. Defaults to `{CWD}/src/payload-generated.schema.ts` | ## Access to Drizzle After Payload is initialized, this adapter will expose the full power of Drizzle to you for use if you need it. -You can access Drizzle as follows: +To ensure type-safety, you need to generate Drizzle schema first with: +```sh +npx payload generate:db-schema +``` -```text -payload.db.drizzle +Then, you can access Drizzle as follows: +```ts +import { posts } from './payload-generated-schema' +// To avoid installing Drizzle, you can import everything that drizzle has from our re-export path. +import { eq, sql, and } from '@payloadcms/db-postgres/drizzle' + +// Drizzle's Querying API: https://orm.drizzle.team/docs/rqb +const posts = await payload.db.drizzle.query.posts.findMany() +// Drizzle's Select API https://orm.drizzle.team/docs/select +const result = await payload.db.drizzle.select().from(posts).where(and(eq(posts.id, 50), sql`lower(${posts.title}) = 'example post title'`)) ``` ## Tables, relations, and enums @@ -114,7 +126,7 @@ Runs before the schema is built. You can use this hook to extend your database s ```ts import { postgresAdapter } from '@payloadcms/db-postgres' -import { integer, pgTable, serial } from 'drizzle-orm/pg-core' +import { integer, pgTable, serial } from '@payloadcms/db-postgres/drizzle/pg-core' postgresAdapter({ beforeSchemaInit: [ @@ -194,7 +206,7 @@ The following example adds the `extra_integer_column` column and a composite ind ```ts import { postgresAdapter } from '@payloadcms/db-postgres' -import { index, integer } from 'drizzle-orm/pg-core' +import { index, integer } from '@payloadcms/db-postgres/drizzle/pg-core' import { buildConfig } from 'payload' export default buildConfig({ @@ -236,3 +248,43 @@ export default buildConfig({ }) ``` + +### Note for generated schema: +Columns and tables, added in schema hooks won't be added to the generated via `payload generate:db-schema` Drizzle schema. +If you want them to be there, you either have to edit this file manually or mutate the internal Payload "raw" SQL schema in the `beforeSchemaInit`: + +```ts +import { postgresAdapter } from '@payloadcms/db-postgres' + +postgresAdapter({ + beforeSchemaInit: [ + ({ schema, adapter }) => { + // Add a new table + schema.rawTables.myTable = { + name: 'my_table', + columns: [{ + name: 'my_id', + type: 'serial', + primaryKey: true + }], + } + + // Add a new column to generated by Payload table: + schema.rawTables.posts.columns.customColumn = { + name: 'custom_column', + // Note that Payload SQL doesn't support everything that Drizzle does. + type: 'integer', + notNull: true + } + // Add a new index to generated by Payload table: + schema.rawTables.posts.indexes.customColumnIdx = { + name: 'custom_column_idx', + unique: true, + on: ['custom_column'] + } + + return schema + }, + ], +}) +``` diff --git a/docs/database/sqlite.mdx b/docs/database/sqlite.mdx index 7d2df38227..bb1684a09e 100644 --- a/docs/database/sqlite.mdx +++ b/docs/database/sqlite.mdx @@ -34,28 +34,41 @@ export default buildConfig({ ## Options -| Option | Description | -| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `client` \* | [Client connection options](https://orm.drizzle.team/docs/get-started-sqlite#turso) that will be passed to `createClient` from `@libsql/client`. | -| `push` | Disable Drizzle's [`db push`](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push) in development mode. By default, `push` is enabled for development mode only. | -| `migrationDir` | Customize the directory that migrations are stored. | -| `logger` | The instance of the logger to be passed to drizzle. By default Payload's will be used. | -| `idType` | A string of 'number', or 'uuid' that is used for the data type given to id columns. | -| `transactionOptions` | A SQLiteTransactionConfig object for transactions, or set to `false` to disable using transactions. [More details](https://orm.drizzle.team/docs/transactions) | -| `localesSuffix` | A string appended to the end of table names for storing localized fields. Default is '_locales'. | -| `relationshipsSuffix` | A string appended to the end of table names for storing relationships. Default is '_rels'. | -| `versionsSuffix` | A string appended to the end of table names for storing versions. Defaults to '_v'. | -| `beforeSchemaInit` | Drizzle schema hook. Runs before the schema is built. [More Details](#beforeschemainit) | -| `afterSchemaInit` | Drizzle schema hook. Runs after the schema is built. [More Details](#afterschemainit) | +| Option | Description | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `client` \* | [Client connection options](https://orm.drizzle.team/docs/get-started-sqlite#turso) that will be passed to `createClient` from `@libsql/client`. | +| `push` | Disable Drizzle's [`db push`](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push) in development mode. By default, `push` is enabled for development mode only. | +| `migrationDir` | Customize the directory that migrations are stored. | +| `logger` | The instance of the logger to be passed to drizzle. By default Payload's will be used. | +| `idType` | A string of 'number', or 'uuid' that is used for the data type given to id columns. | +| `transactionOptions` | A SQLiteTransactionConfig object for transactions, or set to `false` to disable using transactions. [More details](https://orm.drizzle.team/docs/transactions) | +| `localesSuffix` | A string appended to the end of table names for storing localized fields. Default is '_locales'. | +| `relationshipsSuffix` | A string appended to the end of table names for storing relationships. Default is '_rels'. | +| `versionsSuffix` | A string appended to the end of table names for storing versions. Defaults to '_v'. | +| `beforeSchemaInit` | Drizzle schema hook. Runs before the schema is built. [More Details](#beforeschemainit) | +| `afterSchemaInit` | Drizzle schema hook. Runs after the schema is built. [More Details](#afterschemainit) | +| `generateSchemaOutputFile` | Override generated schema from `payload generate:db-schema` file path. Defaults to `{CWD}/src/payload-generated.schema.ts` | ## Access to Drizzle After Payload is initialized, this adapter will expose the full power of Drizzle to you for use if you need it. -You can access Drizzle as follows: +To ensure type-safety, you need to generate Drizzle schema first with: +```sh +npx payload generate:db-schema +``` -```text -payload.db.drizzle +Then, you can access Drizzle as follows: +```ts +// Import table from the generated file +import { posts } from './payload-generated-schema' +// To avoid installing Drizzle, you can import everything that drizzle has from our re-export path. +import { eq, sql, and } from '@payloadcms/db-sqlite/drizzle' + +// Drizzle's Querying API: https://orm.drizzle.team/docs/rqb +const posts = await payload.db.drizzle.query.posts.findMany() +// Drizzle's Select API https://orm.drizzle.team/docs/select +const result = await payload.db.drizzle.select().from(posts).where(and(eq(posts.id, 50), sql`lower(${posts.title}) = 'example post title'`)) ``` ## Tables and relations @@ -89,7 +102,7 @@ Runs before the schema is built. You can use this hook to extend your database s ```ts import { sqliteAdapter } from '@payloadcms/db-sqlite' -import { integer, sqliteTable } from 'drizzle-orm/sqlite-core' +import { integer, sqliteTable } from '@payloadcms/db-sqlite/drizzle/sqlite-core' sqliteAdapter({ beforeSchemaInit: [ @@ -169,7 +182,7 @@ The following example adds the `extra_integer_column` column and a composite ind ```ts import { sqliteAdapter } from '@payloadcms/db-sqlite' -import { index, integer } from 'drizzle-orm/sqlite-core' +import { index, integer } from '@payloadcms/db-sqlite/drizzle/sqlite-core' import { buildConfig } from 'payload' export default buildConfig({ @@ -211,3 +224,43 @@ export default buildConfig({ }) ``` + +### Note for generated schema: +Columns and tables, added in schema hooks won't be added to the generated via `payload generate:db-schema` Drizzle schema. +If you want them to be there, you either have to edit this file manually or mutate the internal Payload "raw" SQL schema in the `beforeSchemaInit`: + +```ts +import { sqliteAdapter } from '@payloadcms/db-sqlite' + +sqliteAdapter({ + beforeSchemaInit: [ + ({ schema, adapter }) => { + // Add a new table + schema.rawTables.myTable = { + name: 'my_table', + columns: [{ + name: 'my_id', + type: 'integer', + primaryKey: true + }], + } + + // Add a new column to generated by Payload table: + schema.rawTables.posts.columns.customColumn = { + name: 'custom_column', + // Note that Payload SQL doesn't support everything that Drizzle does. + type: 'integer', + notNull: true + } + // Add a new index to generated by Payload table: + schema.rawTables.posts.indexes.customColumnIdx = { + name: 'custom_column_idx', + unique: true, + on: ['custom_column'] + } + + return schema + }, + ], +}) +``` diff --git a/package.json b/package.json index 8bde434092..4aef0f0275 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "clean:build": "node ./scripts/delete-recursively.js 'media/' '**/dist/' '**/.cache/' '**/.next/' '**/.turbo/' '**/tsconfig.tsbuildinfo' '**/payload*.tgz' '**/meta_*.json'", "clean:cache": "node ./scripts/delete-recursively.js node_modules/.cache! packages/payload/node_modules/.cache! .next/*", "dev": "cross-env NODE_OPTIONS=--no-deprecation tsx ./test/dev.ts", + "dev:generate-db-schema": "pnpm runts ./test/generateDatabaseSchema.ts", "dev:generate-graphql-schema": "pnpm runts ./test/generateGraphQLSchema.ts", "dev:generate-importmap": "pnpm runts ./test/generateImportMap.ts", "dev:generate-types": "pnpm runts ./test/generateTypes.ts", diff --git a/packages/db-postgres/package.json b/packages/db-postgres/package.json index 75d3575351..ba56166439 100644 --- a/packages/db-postgres/package.json +++ b/packages/db-postgres/package.json @@ -33,6 +33,26 @@ "import": "./src/exports/migration-utils.ts", "types": "./src/exports/migration-utils.ts", "default": "./src/exports/migration-utils.ts" + }, + "./drizzle": { + "import": "./src/drizzle-proxy/index.ts", + "types": "./src/drizzle-proxy/index.ts", + "default": "./src/drizzle-proxy/index.ts" + }, + "./drizzle/pg-core": { + "import": "./src/drizzle-proxy/pg-core.ts", + "types": "./src/drizzle-proxy/pg-core.ts", + "default": "./src/drizzle-proxy/pg-core.ts" + }, + "./drizzle/node-postgres": { + "import": "./src/drizzle-proxy/node-postgres.ts", + "types": "./src/drizzle-proxy/node-postgres.ts", + "default": "./src/drizzle-proxy/node-postgres.ts" + }, + "./drizzle/relations": { + "import": "./src/drizzle-proxy/relations.ts", + "types": "./src/drizzle-proxy/relations.ts", + "default": "./src/drizzle-proxy/relations.ts" } }, "main": "./src/index.ts", @@ -90,6 +110,26 @@ "import": "./dist/exports/migration-utils.js", "types": "./dist/exports/migration-utils.d.ts", "default": "./dist/exports/migration-utils.js" + }, + "./drizzle": { + "import": "./dist/drizzle-proxy/index.js", + "types": "./dist/drizzle-proxy/index.d.ts", + "default": "./dist/drizzle-proxy/index.js" + }, + "./drizzle/pg-core": { + "import": "./dist/drizzle-proxy/pg-core.js", + "types": "./dist/drizzle-proxy/pg-core.d.ts", + "default": "./dist/drizzle-proxy/pg-core.js" + }, + "./drizzle/node-postgres": { + "import": "./dist/drizzle-proxy/node-postgres.js", + "types": "./dist/drizzle-proxy/node-postgres.d.ts", + "default": "./dist/drizzle-proxy/node-postgres.js" + }, + "./drizzle/relations": { + "import": "./dist/drizzle-proxy/relations.js", + "types": "./dist/drizzle-proxy/relations.d.ts", + "default": "./dist/drizzle-proxy/relations.js" } }, "main": "./dist/index.js", diff --git a/packages/db-postgres/src/drizzle-proxy/index.ts b/packages/db-postgres/src/drizzle-proxy/index.ts new file mode 100644 index 0000000000..7af40b613e --- /dev/null +++ b/packages/db-postgres/src/drizzle-proxy/index.ts @@ -0,0 +1 @@ +export * from 'drizzle-orm' diff --git a/packages/db-postgres/src/drizzle-proxy/node-postgres.ts b/packages/db-postgres/src/drizzle-proxy/node-postgres.ts new file mode 100644 index 0000000000..57bb06884a --- /dev/null +++ b/packages/db-postgres/src/drizzle-proxy/node-postgres.ts @@ -0,0 +1 @@ +export * from 'drizzle-orm/node-postgres' diff --git a/packages/db-postgres/src/drizzle-proxy/pg-core.ts b/packages/db-postgres/src/drizzle-proxy/pg-core.ts new file mode 100644 index 0000000000..68c0ae5deb --- /dev/null +++ b/packages/db-postgres/src/drizzle-proxy/pg-core.ts @@ -0,0 +1 @@ +export * from 'drizzle-orm/pg-core' diff --git a/packages/db-postgres/src/drizzle-proxy/relations.ts b/packages/db-postgres/src/drizzle-proxy/relations.ts new file mode 100644 index 0000000000..d0ab736355 --- /dev/null +++ b/packages/db-postgres/src/drizzle-proxy/relations.ts @@ -0,0 +1 @@ +export * from 'drizzle-orm/relations' diff --git a/packages/db-postgres/src/index.ts b/packages/db-postgres/src/index.ts index d73bc5649b..d08366be54 100644 --- a/packages/db-postgres/src/index.ts +++ b/packages/db-postgres/src/index.ts @@ -10,6 +10,7 @@ import { create, createGlobal, createGlobalVersion, + createSchemaGenerator, createVersion, deleteMany, deleteOne, @@ -36,6 +37,7 @@ import { updateVersion, } from '@payloadcms/drizzle' import { + columnToCodeConverter, countDistinct, createDatabase, createExtensions, @@ -106,6 +108,14 @@ export function postgresAdapter(args: Args): DatabaseAdapterObj json: true, }, fieldConstraints: {}, + generateSchema: createSchemaGenerator({ + columnToCodeConverter, + corePackageSuffix: 'pg-core', + defaultOutputFile: args.generateSchemaOutputFile, + enumImport: 'pgEnum', + schemaImport: 'pgSchema', + tableImport: 'pgTable', + }), idType: postgresIDType, initializing, localesSuffix: args.localesSuffix || '_locales', @@ -188,4 +198,5 @@ export function postgresAdapter(args: Args): DatabaseAdapterObj } export type { MigrateDownArgs, MigrateUpArgs } from '@payloadcms/drizzle/postgres' +export { geometryColumn } from '@payloadcms/drizzle/postgres' export { sql } from 'drizzle-orm' diff --git a/packages/db-postgres/src/types.ts b/packages/db-postgres/src/types.ts index f3aaa5423f..ec20052653 100644 --- a/packages/db-postgres/src/types.ts +++ b/packages/db-postgres/src/types.ts @@ -8,6 +8,7 @@ import type { } from '@payloadcms/drizzle/postgres' import type { DrizzleAdapter } from '@payloadcms/drizzle/types' import type { DrizzleConfig } from 'drizzle-orm' +import type { NodePgDatabase } from 'drizzle-orm/node-postgres' import type { PgSchema, PgTableFn, PgTransactionConfig } from 'drizzle-orm/pg-core' import type { Pool, PoolConfig } from 'pg' @@ -30,6 +31,8 @@ export type Args = { */ disableCreateDatabase?: boolean extensions?: string[] + /** Generated schema from payload generate:db-schema file path */ + generateSchemaOutputFile?: string idType?: 'serial' | 'uuid' localesSuffix?: string logger?: DrizzleConfig['logger'] @@ -52,7 +55,17 @@ export type Args = { versionsSuffix?: string } +export interface GeneratedDatabaseSchema { + schemaUntyped: Record +} + +type ResolveSchemaType = 'schema' extends keyof T + ? T['schema'] + : GeneratedDatabaseSchema['schemaUntyped'] + +type Drizzle = NodePgDatabase> export type PostgresAdapter = { + drizzle: Drizzle pool: Pool poolOptions: PoolConfig } & BasePostgresAdapter @@ -65,7 +78,7 @@ declare module 'payload' { beforeSchemaInit: PostgresSchemaHook[] beginTransaction: (options?: PgTransactionConfig) => Promise - drizzle: PostgresDB + drizzle: Drizzle enums: Record extensions: Record /** diff --git a/packages/db-sqlite/package.json b/packages/db-sqlite/package.json index 63ce307b91..d4828e6e02 100644 --- a/packages/db-sqlite/package.json +++ b/packages/db-sqlite/package.json @@ -33,6 +33,26 @@ "import": "./src/exports/migration-utils.ts", "require": "./src/exports/migration-utils.ts", "types": "./src/exports/migration-utils.ts" + }, + "./drizzle": { + "import": "./src/drizzle-proxy/index.ts", + "types": "./src/drizzle-proxy/index.ts", + "default": "./src/drizzle-proxy/index.ts" + }, + "./drizzle/sqlite-core": { + "import": "./src/drizzle-proxy/sqlite-core.ts", + "types": "./src/drizzle-proxy/sqlite-core.ts", + "default": "./src/drizzle-proxy/sqlite-core.ts" + }, + "./drizzle/libsql": { + "import": "./src/drizzle-proxy/libsql.ts", + "types": "./src/drizzle-proxy/libsql.ts", + "default": "./src/drizzle-proxy/libsql.ts" + }, + "./drizzle/relations": { + "import": "./src/drizzle-proxy/relations.ts", + "types": "./src/drizzle-proxy/relations.ts", + "default": "./src/drizzle-proxy/relations.ts" } }, "main": "./src/index.ts", @@ -86,6 +106,26 @@ "import": "./dist/exports/migration-utils.js", "require": "./dist/exports/migration-utils.js", "types": "./dist/exports/migration-utils.d.ts" + }, + "./drizzle": { + "import": "./dist/drizzle-proxy/index.js", + "types": "./dist/drizzle-proxy/index.d.ts", + "default": "./dist/drizzle-proxy/index.js" + }, + "./drizzle/sqlite-core": { + "import": "./dist/drizzle-proxy/sqlite-core.js", + "types": "./dist/drizzle-proxy/sqlite-core.d.ts", + "default": "./dist/drizzle-proxy/sqlite-core.js" + }, + "./drizzle/libsql": { + "import": "./dist/drizzle-proxy/libsql.js", + "types": "./dist/drizzle-proxy/libsql.d.ts", + "default": "./dist/drizzle-proxy/libsql.js" + }, + "./drizzle/relations": { + "import": "./dist/drizzle-proxy/relations.js", + "types": "./dist/drizzle-proxy/relations.d.ts", + "default": "./dist/drizzle-proxy/relations.js" } }, "main": "./dist/index.js", diff --git a/packages/db-sqlite/src/columnToCodeConverter.ts b/packages/db-sqlite/src/columnToCodeConverter.ts new file mode 100644 index 0000000000..5aca601099 --- /dev/null +++ b/packages/db-sqlite/src/columnToCodeConverter.ts @@ -0,0 +1,126 @@ +import type { ColumnToCodeConverter } from '@payloadcms/drizzle/types' + +export const columnToCodeConverter: ColumnToCodeConverter = ({ + adapter, + addImport, + column, + locales, + tableKey, +}) => { + let columnBuilderFn: string = column.type + + const columnBuilderArgsArray: string[] = [] + + let defaultStatement: null | string = null + + switch (column.type) { + case 'boolean': { + columnBuilderFn = 'integer' + columnBuilderArgsArray.push("mode: 'boolean'") + break + } + + case 'enum': { + let options: string[] + if ('locale' in column) { + options = locales + } else { + options = column.options + } + + columnBuilderFn = 'text' + columnBuilderArgsArray.push(`enum: [${options.map((locale) => `'${locale}'`).join(', ')}]`) + + break + } + + case 'geometry': + case 'jsonb': { + columnBuilderFn = 'text' + columnBuilderArgsArray.push("mode: 'json'") + break + } + + case 'serial': { + columnBuilderFn = 'integer' + break + } + + case 'timestamp': { + columnBuilderFn = 'text' + defaultStatement = `default(sql\`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))\`)` + break + } + + case 'uuid': { + columnBuilderFn = 'text' + + if (column.defaultRandom) { + addImport('crypto', 'randomUUID') + defaultStatement = `$defaultFn(() => randomUUID())` + } + + break + } + + case 'varchar': { + columnBuilderFn = 'text' + break + } + + default: { + columnBuilderFn = column.type + } + } + + addImport(`${adapter.packageName}/drizzle/sqlite-core`, columnBuilderFn) + + let columnBuilderArgs = '' + + if (columnBuilderArgsArray.length) { + columnBuilderArgs = `, {${columnBuilderArgsArray.join(',')}}` + } + + let code = `${columnBuilderFn}('${column.name}'${columnBuilderArgs})` + + if (column.notNull) { + code = `${code}.notNull()` + } + + if (column.primaryKey) { + code = `${code}.primaryKey()` + } + + if (defaultStatement) { + code = `${code}.${defaultStatement}` + } else if (typeof column.default !== 'undefined') { + let sanitizedDefault = column.default + + if (column.type === 'jsonb' || column.type === 'geometry') { + sanitizedDefault = `'${JSON.stringify(column.default)}'` + } else if (typeof column.default === 'string') { + sanitizedDefault = JSON.stringify(column.default) + } else if (column.type === 'numeric') { + sanitizedDefault = `'${column.default}'` + } + + code = `${code}.default(${sanitizedDefault})` + } + + if (column.reference) { + let callback = `()` + + if (column.reference.table === tableKey) { + addImport(`${adapter.packageName}/drizzle/sqlite-core`, 'type AnySQLiteColumn') + callback = `${callback}: AnySQLiteColumn` + } + + callback = `${callback} => ${column.reference.table}.${column.reference.name}` + + code = `${code}.references(${callback}, { + ${column.reference.onDelete ? `onDelete: '${column.reference.onDelete}'` : ''} + })` + } + + return code +} diff --git a/packages/db-sqlite/src/drizzle-proxy/index.ts b/packages/db-sqlite/src/drizzle-proxy/index.ts new file mode 100644 index 0000000000..7af40b613e --- /dev/null +++ b/packages/db-sqlite/src/drizzle-proxy/index.ts @@ -0,0 +1 @@ +export * from 'drizzle-orm' diff --git a/packages/db-sqlite/src/drizzle-proxy/libsql.ts b/packages/db-sqlite/src/drizzle-proxy/libsql.ts new file mode 100644 index 0000000000..93390cb2dc --- /dev/null +++ b/packages/db-sqlite/src/drizzle-proxy/libsql.ts @@ -0,0 +1 @@ +export * from 'drizzle-orm/libsql' diff --git a/packages/db-sqlite/src/drizzle-proxy/relations.ts b/packages/db-sqlite/src/drizzle-proxy/relations.ts new file mode 100644 index 0000000000..d0ab736355 --- /dev/null +++ b/packages/db-sqlite/src/drizzle-proxy/relations.ts @@ -0,0 +1 @@ +export * from 'drizzle-orm/relations' diff --git a/packages/db-sqlite/src/drizzle-proxy/sqlite-core.ts b/packages/db-sqlite/src/drizzle-proxy/sqlite-core.ts new file mode 100644 index 0000000000..24439b562a --- /dev/null +++ b/packages/db-sqlite/src/drizzle-proxy/sqlite-core.ts @@ -0,0 +1 @@ +export * from 'drizzle-orm/sqlite-core' diff --git a/packages/db-sqlite/src/index.ts b/packages/db-sqlite/src/index.ts index 5d7c24aade..6e1faa01ec 100644 --- a/packages/db-sqlite/src/index.ts +++ b/packages/db-sqlite/src/index.ts @@ -11,6 +11,7 @@ import { create, createGlobal, createGlobalVersion, + createSchemaGenerator, createVersion, deleteMany, deleteOne, @@ -42,6 +43,7 @@ import { fileURLToPath } from 'url' import type { Args, SQLiteAdapter } from './types.js' +import { columnToCodeConverter } from './columnToCodeConverter.js' import { connect } from './connect.js' import { countDistinct } from './countDistinct.js' import { convertPathToJSONTraversal } from './createJSONQuery/convertPathToJSONTraversal.js' @@ -93,6 +95,12 @@ export function sqliteAdapter(args: Args): DatabaseAdapterObj { json: true, }, fieldConstraints: {}, + generateSchema: createSchemaGenerator({ + columnToCodeConverter, + corePackageSuffix: 'sqlite-core', + defaultOutputFile: args.generateSchemaOutputFile, + tableImport: 'sqliteTable', + }), idType: sqliteIDType, initializing, localesSuffix: args.localesSuffix || '_locales', diff --git a/packages/db-vercel-postgres/package.json b/packages/db-vercel-postgres/package.json index 8488484c74..f4846956e0 100644 --- a/packages/db-vercel-postgres/package.json +++ b/packages/db-vercel-postgres/package.json @@ -33,6 +33,26 @@ "import": "./src/exports/migration-utils.ts", "types": "./src/exports/migration-utils.ts", "default": "./src/exports/migration-utils.ts" + }, + "./drizzle": { + "import": "./src/drizzle-proxy/index.ts", + "types": "./src/drizzle-proxy/index.ts", + "default": "./src/drizzle-proxy/index.ts" + }, + "./drizzle/pg-core": { + "import": "./src/drizzle-proxy/pg-core.ts", + "types": "./src/drizzle-proxy/pg-core.ts", + "default": "./src/drizzle-proxy/pg-core.ts" + }, + "./drizzle/node-postgres": { + "import": "./src/drizzle-proxy/node-postgres.ts", + "types": "./src/drizzle-proxy/node-postgres.ts", + "default": "./src/drizzle-proxy/node-postgres.ts" + }, + "./drizzle/relations": { + "import": "./src/drizzle-proxy/relations.ts", + "types": "./src/drizzle-proxy/relations.ts", + "default": "./src/drizzle-proxy/relations.ts" } }, "main": "./src/index.ts", @@ -91,6 +111,26 @@ "import": "./dist/exports/migration-utils.js", "types": "./dist/exports/migration-utils.d.ts", "default": "./dist/exports/migration-utils.js" + }, + "./drizzle": { + "import": "./dist/drizzle-proxy/index.js", + "types": "./dist/drizzle-proxy/index.d.ts", + "default": "./dist/drizzle-proxy/index.js" + }, + "./drizzle/pg-core": { + "import": "./dist/drizzle-proxy/pg-core.js", + "types": "./dist/drizzle-proxy/pg-core.d.ts", + "default": "./dist/drizzle-proxy/pg-core.js" + }, + "./drizzle/node-postgres": { + "import": "./dist/drizzle-proxy/node-postgres.js", + "types": "./dist/drizzle-proxy/node-postgres.d.ts", + "default": "./dist/drizzle-proxy/node-postgres.js" + }, + "./drizzle/relations": { + "import": "./dist/drizzle-proxy/relations.js", + "types": "./dist/drizzle-proxy/relations.d.ts", + "default": "./dist/drizzle-proxy/relations.js" } }, "main": "./dist/index.js", diff --git a/packages/db-vercel-postgres/src/drizzle-proxy/index.ts b/packages/db-vercel-postgres/src/drizzle-proxy/index.ts new file mode 100644 index 0000000000..7af40b613e --- /dev/null +++ b/packages/db-vercel-postgres/src/drizzle-proxy/index.ts @@ -0,0 +1 @@ +export * from 'drizzle-orm' diff --git a/packages/db-vercel-postgres/src/drizzle-proxy/node-postgres.ts b/packages/db-vercel-postgres/src/drizzle-proxy/node-postgres.ts new file mode 100644 index 0000000000..57bb06884a --- /dev/null +++ b/packages/db-vercel-postgres/src/drizzle-proxy/node-postgres.ts @@ -0,0 +1 @@ +export * from 'drizzle-orm/node-postgres' diff --git a/packages/db-vercel-postgres/src/drizzle-proxy/pg-core.ts b/packages/db-vercel-postgres/src/drizzle-proxy/pg-core.ts new file mode 100644 index 0000000000..68c0ae5deb --- /dev/null +++ b/packages/db-vercel-postgres/src/drizzle-proxy/pg-core.ts @@ -0,0 +1 @@ +export * from 'drizzle-orm/pg-core' diff --git a/packages/db-vercel-postgres/src/drizzle-proxy/relations.ts b/packages/db-vercel-postgres/src/drizzle-proxy/relations.ts new file mode 100644 index 0000000000..d0ab736355 --- /dev/null +++ b/packages/db-vercel-postgres/src/drizzle-proxy/relations.ts @@ -0,0 +1 @@ +export * from 'drizzle-orm/relations' diff --git a/packages/db-vercel-postgres/src/index.ts b/packages/db-vercel-postgres/src/index.ts index 8de6be3d44..ca8594c993 100644 --- a/packages/db-vercel-postgres/src/index.ts +++ b/packages/db-vercel-postgres/src/index.ts @@ -10,6 +10,7 @@ import { create, createGlobal, createGlobalVersion, + createSchemaGenerator, createVersion, deleteMany, deleteOne, @@ -36,6 +37,7 @@ import { updateVersion, } from '@payloadcms/drizzle' import { + columnToCodeConverter, countDistinct, createDatabase, createExtensions, @@ -100,6 +102,14 @@ export function vercelPostgresAdapter(args: Args = {}): DatabaseAdapterObj(), initializing, @@ -189,4 +199,5 @@ export function vercelPostgresAdapter(args: Args = {}): DatabaseAdapterObj +} + +type ResolveSchemaType = 'schema' extends keyof T + ? T['schema'] + : GeneratedDatabaseSchema['schemaUntyped'] + +type Drizzle = NodePgDatabase> + export type VercelPostgresAdapter = { + drizzle: Drizzle forceUseVercelPostgres?: boolean pool?: VercelPool poolOptions?: Args['pool'] @@ -77,7 +91,7 @@ declare module 'payload' { afterSchemaInit: PostgresSchemaHook[] beforeSchemaInit: PostgresSchemaHook[] beginTransaction: (options?: PgTransactionConfig) => Promise - drizzle: PostgresDB + drizzle: Drizzle enums: Record extensions: Record extensionsFilter: Set diff --git a/packages/drizzle/src/exports/postgres.ts b/packages/drizzle/src/exports/postgres.ts index bf63a1868c..7ce85415d1 100644 --- a/packages/drizzle/src/exports/postgres.ts +++ b/packages/drizzle/src/exports/postgres.ts @@ -1,3 +1,4 @@ +export { columnToCodeConverter } from '../postgres/columnToCodeConverter.js' export { countDistinct } from '../postgres/countDistinct.js' export { createDatabase } from '../postgres/createDatabase.js' export { createExtensions } from '../postgres/createExtensions.js' @@ -10,4 +11,5 @@ export { init } from '../postgres/init.js' export { insert } from '../postgres/insert.js' export { migratePostgresV2toV3 } from '../postgres/predefinedMigrations/v2-v3/index.js' export { requireDrizzleKit } from '../postgres/requireDrizzleKit.js' +export { geometryColumn } from '../postgres/schema/geometryColumn.js' export * from '../postgres/types.js' diff --git a/packages/drizzle/src/index.ts b/packages/drizzle/src/index.ts index 69ef55cd53..f7036cfc0d 100644 --- a/packages/drizzle/src/index.ts +++ b/packages/drizzle/src/index.ts @@ -38,6 +38,7 @@ export { updateVersion } from './updateVersion.js' export { upsertRow } from './upsertRow/index.js' export { buildCreateMigration } from './utilities/buildCreateMigration.js' export { buildIndexName } from './utilities/buildIndexName.js' +export { createSchemaGenerator } from './utilities/createSchemaGenerator.js' export { executeSchemaHooks } from './utilities/executeSchemaHooks.js' export { extendDrizzleTable } from './utilities/extendDrizzleTable.js' export { hasLocalesTable } from './utilities/hasLocalesTable.js' diff --git a/packages/drizzle/src/postgres/columnToCodeConverter.ts b/packages/drizzle/src/postgres/columnToCodeConverter.ts new file mode 100644 index 0000000000..571dfa7142 --- /dev/null +++ b/packages/drizzle/src/postgres/columnToCodeConverter.ts @@ -0,0 +1,94 @@ +import type { ColumnToCodeConverter } from '../types.js' +export const columnToCodeConverter: ColumnToCodeConverter = ({ + adapter, + addEnum, + addImport, + column, + tableKey, +}) => { + let columnBuilderFn: string = column.type + + if (column.type === 'geometry') { + columnBuilderFn = 'geometryColumn' + addImport(adapter.packageName, columnBuilderFn) + } else if (column.type === 'enum') { + if ('locale' in column) { + columnBuilderFn = `enum__locales` + } else { + addEnum(column.enumName, column.options) + columnBuilderFn = column.enumName + } + } else { + addImport(`${adapter.packageName}/drizzle/pg-core`, columnBuilderFn) + } + + const columnBuilderArgsArray: string[] = [] + + if (column.type === 'timestamp') { + columnBuilderArgsArray.push(`mode: '${column.mode}'`) + if (column.withTimezone) { + columnBuilderArgsArray.push('withTimezone: true') + } + + if (typeof column.precision === 'number') { + columnBuilderArgsArray.push(`precision: ${column.precision}`) + } + } + + let columnBuilderArgs = '' + + if (columnBuilderArgsArray.length) { + columnBuilderArgs = `, {${columnBuilderArgsArray.join(',')}}` + } + + let code = `${columnBuilderFn}('${column.name}'${columnBuilderArgs})` + + if (column.type === 'timestamp' && column.defaultNow) { + code = `${code}.defaultNow()` + } + + if (column.type === 'uuid' && column.defaultRandom) { + code = `${code}.defaultRandom()` + } + + if (column.notNull) { + code = `${code}.notNull()` + } + + if (column.primaryKey) { + code = `${code}.primaryKey()` + } + + if (typeof column.default !== 'undefined') { + let sanitizedDefault = column.default + + if (column.type === 'geometry') { + sanitizedDefault = `sql\`${column.default}\`` + } else if (column.type === 'jsonb') { + sanitizedDefault = `sql\`'${JSON.stringify(column.default)}'::jsonb\`` + } else if (column.type === 'numeric') { + sanitizedDefault = `'${column.default}'` + } else if (typeof column.default === 'string') { + sanitizedDefault = `${JSON.stringify(column.default)}` + } + + code = `${code}.default(${sanitizedDefault})` + } + + if (column.reference) { + let callback = `()` + + if (column.reference.table === tableKey) { + addImport(`${adapter.packageName}/drizzle/pg-core`, 'type AnyPgColumn') + callback = `${callback}: AnyPgColumn` + } + + callback = `${callback} => ${column.reference.table}.${column.reference.name}` + + code = `${code}.references(${callback}, { + ${column.reference.onDelete ? `onDelete: '${column.reference.onDelete}'` : ''} + })` + } + + return code +} diff --git a/packages/drizzle/src/types.ts b/packages/drizzle/src/types.ts index e22d376faf..e3b78be236 100644 --- a/packages/drizzle/src/types.ts +++ b/packages/drizzle/src/types.ts @@ -286,6 +286,15 @@ export type SetColumnID = (args: { fields: FlattenedField[] }) => IDType +export type ColumnToCodeConverter = (args: { + adapter: DrizzleAdapter + addEnum: (name: string, options: string[]) => void + addImport: (from: string, name: string) => void + column: RawColumn + locales?: string[] + tableKey: string +}) => string + export type BuildDrizzleTable = (args: { adapter: T locales: string[] diff --git a/packages/drizzle/src/utilities/createSchemaGenerator.ts b/packages/drizzle/src/utilities/createSchemaGenerator.ts new file mode 100644 index 0000000000..36d8957379 --- /dev/null +++ b/packages/drizzle/src/utilities/createSchemaGenerator.ts @@ -0,0 +1,311 @@ +import type { GenerateSchema } from 'payload' + +import { exec } from 'child_process' +import { existsSync } from 'fs' +import { writeFile } from 'fs/promises' +import path from 'path' +import { promisify } from 'util' + +import type { ColumnToCodeConverter, DrizzleAdapter } from '../types.js' + +const execAsync = promisify(exec) + +/** + * @example + * console.log(sanitizeObjectKey("oneTwo")); // oneTwo + * console.log(sanitizeObjectKey("one-two")); // 'one-two' + * console.log(sanitizeObjectKey("_one$Two3")); // _one$Two3 + * console.log(sanitizeObjectKey("3invalid")); // '3invalid' + */ +const sanitizeObjectKey = (key: string) => { + // Regular expression for a valid identifier + const identifierRegex = /^[a-z_$][\w$]*$/i + if (identifierRegex.test(key)) { + return key + } + + return `'${key}'` +} + +/** + * @example + * (columns default-valuesID) -> columns['default-valuesID'] + * (columns defaultValues) -> columns.defaultValues + */ +const accessProperty = (objName: string, key: string) => { + const sanitized = sanitizeObjectKey(key) + + if (sanitized.startsWith("'")) { + return `${objName}[${sanitized}]` + } + + return `${objName}.${key}` +} + +export const createSchemaGenerator = ({ + columnToCodeConverter, + corePackageSuffix, + defaultOutputFile, + enumImport, + schemaImport, + tableImport, +}: { + columnToCodeConverter: ColumnToCodeConverter + corePackageSuffix: string + defaultOutputFile?: string + enumImport?: string + schemaImport?: string + tableImport: string +}): GenerateSchema => { + return async function generateSchema( + this: DrizzleAdapter, + { log = true, outputFile = defaultOutputFile, prettify = true } = {}, + ) { + const importDeclarations: Record> = {} + + const tableDeclarations: string[] = [] + const enumDeclarations: string[] = [] + const relationsDeclarations: string[] = [] + + const addImport = (from: string, name: string) => { + if (!importDeclarations[from]) { + importDeclarations[from] = new Set() + } + + importDeclarations[from].add(name) + } + + const corePackage = `${this.packageName}/drizzle/${corePackageSuffix}` + + let schemaDeclaration: null | string = null + + if (this.schemaName) { + addImport(corePackage, schemaImport) + schemaDeclaration = `export const db_schema = ${schemaImport}('${this.schemaName}')` + } + + const enumFn = this.schemaName ? `db_schema.enum` : enumImport + + const enumsList: string[] = [] + const addEnum = (name: string, options: string[]) => { + if (enumsList.some((each) => each === name)) { + return + } + enumsList.push(name) + enumDeclarations.push( + `export const ${name} = ${enumFn}('${name}', [${options.map((option) => `'${option}'`).join(', ')}])`, + ) + } + + if (this.payload.config.localization && enumImport) { + addEnum('enum__locales', this.payload.config.localization.localeCodes) + } + + const tableFn = this.schemaName ? `db_schema.table` : tableImport + + if (!this.schemaName) { + addImport(corePackage, tableImport) + } + + addImport(corePackage, 'index') + addImport(corePackage, 'uniqueIndex') + addImport(corePackage, 'foreignKey') + + addImport(`${this.packageName}/drizzle`, 'sql') + addImport(`${this.packageName}/drizzle`, 'relations') + + for (const tableName in this.rawTables) { + const table = this.rawTables[tableName] + + const extrasDeclarations: string[] = [] + + if (table.indexes) { + for (const key in table.indexes) { + const index = table.indexes[key] + let indexDeclaration = `${sanitizeObjectKey(key)}: ${index.unique ? 'uniqueIndex' : 'index'}('${index.name}')` + indexDeclaration += `.on(${typeof index.on === 'string' ? `${accessProperty('columns', index.on)}` : `${index.on.map((on) => `${accessProperty('columns', on)}`).join(', ')}`}),` + extrasDeclarations.push(indexDeclaration) + } + } + + if (table.foreignKeys) { + for (const key in table.foreignKeys) { + const foreignKey = table.foreignKeys[key] + + let foreignKeyDeclaration = `${sanitizeObjectKey(key)}: foreignKey({ + columns: [${foreignKey.columns.map((col) => `columns['${col}']`).join(', ')}], + foreignColumns: [${foreignKey.foreignColumns.map((col) => `${accessProperty(col.table, col.name)}`).join(', ')}], + name: '${foreignKey.name}' + })` + + if (foreignKey.onDelete) { + foreignKeyDeclaration += `.onDelete('${foreignKey.onDelete}')` + } + if (foreignKey.onUpdate) { + foreignKeyDeclaration += `.onUpdate('${foreignKey.onDelete}')` + } + + foreignKeyDeclaration += ',' + + extrasDeclarations.push(foreignKeyDeclaration) + } + } + + const tableCode = ` +export const ${tableName} = ${tableFn}('${tableName}', { +${Object.entries(table.columns) + .map( + ([key, column]) => + ` ${sanitizeObjectKey(key)}: ${columnToCodeConverter({ + adapter: this, + addEnum, + addImport, + column, + locales: this.payload.config.localization + ? this.payload.config.localization.localeCodes + : undefined, + tableKey: tableName, + })},`, + ) + .join('\n')} +}${ + extrasDeclarations.length + ? `, (columns) => ({ + ${extrasDeclarations.join('\n ')} + })` + : '' + } +) +` + + tableDeclarations.push(tableCode) + } + + for (const tableName in this.rawRelations) { + const relations = this.rawRelations[tableName] + const properties: string[] = [] + + for (const key in relations) { + const relation = relations[key] + let declaration: string + + if (relation.type === 'one') { + declaration = `${sanitizeObjectKey(key)}: one(${relation.to}, { + ${relation.fields.some((field) => field.table !== tableName) ? '// @ts-expect-error Drizzle TypeScript bug for ONE relationships with a field in different table' : ''} + fields: [${relation.fields.map((field) => `${accessProperty(field.table, field.name)}`).join(', ')}], + references: [${relation.references.map((col) => `${accessProperty(relation.to, col)}`).join(', ')}], + ${relation.relationName ? `relationName: '${relation.relationName}',` : ''} + }),` + } else { + declaration = `${sanitizeObjectKey(key)}: many(${relation.to}, { + ${relation.relationName ? `relationName: '${relation.relationName}',` : ''} + }),` + } + + properties.push(declaration) + } + + // beautify / lintify relations callback output, when no many for example, don't add it + const args = [] + + if (Object.values(relations).some((rel) => rel.type === 'one')) { + args.push('one') + } + + if (Object.values(relations).some((rel) => rel.type === 'many')) { + args.push('many') + } + + const arg = args.length ? `{ ${args.join(', ')} }` : '' + + const declaration = `export const relations_${tableName} = relations(${tableName}, (${arg}) => ({ + ${properties.join('\n ')} + }))` + + relationsDeclarations.push(declaration) + } + + if (enumDeclarations.length && !this.schemaName) { + addImport(corePackage, enumImport) + } + + const importDeclarationsSanitized: string[] = [] + + for (const moduleName in importDeclarations) { + const moduleImports = importDeclarations[moduleName] + + importDeclarationsSanitized.push( + `import { ${Array.from(moduleImports).join(', ')} } from '${moduleName}'`, + ) + } + + const schemaType = ` +type DatabaseSchema = { + ${[ + this.schemaName ? 'db_schema' : null, + ...enumsList, + ...Object.keys(this.rawTables), + ...Object.keys(this.rawRelations).map((table) => `relations_${table}`), + ] + .filter(Boolean) + .map((name) => `${name}: typeof ${name}`) + .join('\n ')} +} + ` + + const finalDeclaration = ` +declare module '${this.packageName}/types' { + export interface GeneratedDatabaseSchema { + schema: DatabaseSchema + } +} + ` + + const warning = ` +/* tslint:disable */ +/* eslint-disable */ +/** + * This file was automatically generated by Payload. + * DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config, + * and re-run \`payload generate:db-schema\` to regenerate this file. + */ +` + + const code = [ + warning, + ...importDeclarationsSanitized, + schemaDeclaration, + ...enumDeclarations, + ...tableDeclarations, + ...relationsDeclarations, + schemaType, + finalDeclaration, + ] + .filter(Boolean) + .join('\n') + + if (!outputFile) { + const cwd = process.cwd() + const srcDir = path.resolve(cwd, 'src') + + if (existsSync(srcDir)) { + outputFile = path.resolve(srcDir, 'payload-generated-schema.ts') + } else { + outputFile = path.resolve(cwd, 'payload-generated-schema.ts') + } + } + + await writeFile(outputFile, code, 'utf-8') + + if (prettify) { + try { + await execAsync(`npx prettier ${outputFile} --write`) + // eslint-disable-next-line no-empty + } catch {} + } + + if (log) { + this.payload.logger.info(`Written ${outputFile}`) + } + } +} diff --git a/packages/payload/src/bin/index.ts b/packages/payload/src/bin/index.ts index 4a2508c63a..603a17eaa3 100755 --- a/packages/payload/src/bin/index.ts +++ b/packages/payload/src/bin/index.ts @@ -109,6 +109,23 @@ export const bin = async () => { } } + if (script === 'generate:db-schema') { + const payload = await getPayload({ config }) + + if (typeof payload.db.generateSchema !== 'function') { + payload.logger.error({ + msg: `${payload.db.packageName} does not support database schema generation`, + }) + + process.exit(1) + } + + await payload.db.generateSchema({ + log: args.log === 'false' ? false : true, + prettify: args.prettify === 'false' ? false : true, + }) + } + console.error(`Unknown script: "${script}".`) process.exit(1) } diff --git a/packages/payload/src/database/types.ts b/packages/payload/src/database/types.ts index cee966f9da..13a35f4451 100644 --- a/packages/payload/src/database/types.ts +++ b/packages/payload/src/database/types.ts @@ -70,6 +70,8 @@ export interface BaseDatabaseAdapter { findVersions: FindVersions + generateSchema?: GenerateSchema + /** * Perform startup tasks required to interact with the database such as building Schema and models */ @@ -89,16 +91,15 @@ export interface BaseDatabaseAdapter { * Drop the current database and run all migrate up functions */ migrateFresh: (args: { forceAcceptWarning?: boolean }) => Promise - /** * Run all migration down functions before running up */ migrateRefresh: () => Promise + /** * Run all migrate down functions */ migrateReset: () => Promise - /** * Read the current state of migrations and output the result to show which have been run */ @@ -111,6 +112,7 @@ export interface BaseDatabaseAdapter { * The name of the database adapter */ name: string + /** * Full package name of the database adapter * @@ -122,12 +124,12 @@ export interface BaseDatabaseAdapter { * reference to the instance of payload */ payload: Payload - queryDrafts: QueryDrafts /** * Abort any changes since the start of the transaction. */ rollbackTransaction: RollbackTransaction + /** * A key-value store of all sessions open (used for transactions) */ @@ -521,3 +523,11 @@ export type MigrationTemplateArgs = { packageName?: string upSQL?: string } + +export type GenerateSchemaArgs = { + log?: boolean + outputFile?: string + prettify?: boolean +} + +export type GenerateSchema = (args?: GenerateSchemaArgs) => Promise diff --git a/packages/payload/src/index.ts b/packages/payload/src/index.ts index ba26cacfb5..19e2defc64 100644 --- a/packages/payload/src/index.ts +++ b/packages/payload/src/index.ts @@ -1050,6 +1050,7 @@ export type { FindOneArgs, FindVersions, FindVersionsArgs, + GenerateSchema, Init, Migration, MigrationData, diff --git a/test/database/.gitignore b/test/database/.gitignore index 24a8e4db00..300771cb24 100644 --- a/test/database/.gitignore +++ b/test/database/.gitignore @@ -1 +1,2 @@ migrations +*.generated-schema.ts diff --git a/test/database/int.spec.ts b/test/database/int.spec.ts index e39a222422..22b6538884 100644 --- a/test/database/int.spec.ts +++ b/test/database/int.spec.ts @@ -1,6 +1,5 @@ import type { MongooseAdapter } from '@payloadcms/db-mongodb' import type { PostgresAdapter } from '@payloadcms/db-postgres/types' -import type { Table } from 'drizzle-orm' import type { NextRESTClient } from 'helpers/NextRESTClient.js' import type { Payload, PayloadRequest, TypeWithID } from 'payload' @@ -8,6 +7,7 @@ import { migrateRelationshipsV2_V3, migrateVersionsV1_V2, } from '@payloadcms/db-mongodb/migration-utils' +import { desc, type Table } from 'drizzle-orm' import * as drizzlePg from 'drizzle-orm/pg-core' import * as drizzleSqlite from 'drizzle-orm/sqlite-core' import fs from 'fs' @@ -788,6 +788,61 @@ describe('database', () => { }) }) + describe('Schema generation', () => { + if (process.env.PAYLOAD_DATABASE.includes('postgres')) { + it('should generate Drizzle Postgres schema', async () => { + const generatedAdapterName = process.env.PAYLOAD_DATABASE + + const outputFile = path.resolve(dirname, `${generatedAdapterName}.generated-schema.ts`) + + await payload.db.generateSchema({ + outputFile, + }) + + const module = await import(outputFile) + + // Confirm that the generated module exports every relation + for (const relation in payload.db.relations) { + expect(module).toHaveProperty(relation) + } + + // Confirm that module exports every table + for (const table in payload.db.tables) { + expect(module).toHaveProperty(table) + } + + // Confirm that module exports every enum + for (const enumName in payload.db.enums) { + expect(module).toHaveProperty(enumName) + } + }) + } + + if (process.env.PAYLOAD_DATABASE.includes('sqlite')) { + it('should generate Drizzle SQLite schema', async () => { + const generatedAdapterName = process.env.PAYLOAD_DATABASE + + const outputFile = path.resolve(dirname, `${generatedAdapterName}.generated-schema.ts`) + + await payload.db.generateSchema({ + outputFile, + }) + + const module = await import(outputFile) + + // Confirm that the generated module exports every relation + for (const relation in payload.db.relations) { + expect(module).toHaveProperty(relation) + } + + // Confirm that module exports every table + for (const table in payload.db.tables) { + expect(module).toHaveProperty(table) + } + }) + } + }) + describe('drizzle: schema hooks', () => { it('should add tables with hooks', async () => { // eslint-disable-next-line jest/no-conditional-in-test diff --git a/test/database/payload-generated-schema.ts b/test/database/payload-generated-schema.ts new file mode 100644 index 0000000000..9bf6cf6320 --- /dev/null +++ b/test/database/payload-generated-schema.ts @@ -0,0 +1,2112 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * This file was automatically generated by Payload. + * DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config, + * and re-run `payload generate:db-schema` to regenerate this file. + */ + +import { + sqliteTable, + index, + uniqueIndex, + foreignKey, + integer, + text, + numeric, +} from '@payloadcms/db-sqlite/drizzle/sqlite-core' +import { sql, relations } from '@payloadcms/db-sqlite/drizzle' + +export const posts = sqliteTable( + 'posts', + { + id: integer('id').primaryKey(), + title: text('title').notNull(), + hasTransaction: integer('has_transaction', { mode: 'boolean' }), + throwAfterChange: integer('throw_after_change', { mode: 'boolean' }).default(false), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + }, + (columns) => ({ + posts_updated_at_idx: index('posts_updated_at_idx').on(columns.updatedAt), + posts_created_at_idx: index('posts_created_at_idx').on(columns.createdAt), + }), +) + +export const default_values_array = sqliteTable( + 'default_values_array', + { + _order: integer('_order').notNull(), + _parentID: integer('_parent_id').notNull(), + id: text('id').primaryKey(), + defaultValue: text('default_value').default('default value from database'), + }, + (columns) => ({ + _orderIdx: index('default_values_array_order_idx').on(columns._order), + _parentIDIdx: index('default_values_array_parent_id_idx').on(columns._parentID), + _parentIDFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [default_values.id], + name: 'default_values_array_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const default_values = sqliteTable( + 'default_values', + { + id: integer('id').primaryKey(), + title: text('title'), + defaultValue: text('default_value').default('default value from database'), + group_defaultValue: text('group_default_value').default('default value from database'), + select: text('select', { enum: ['option0', 'option1', 'default'] }).default('default'), + point: text('point', { mode: 'json' }).default('"SRID=4326;POINT(10 20)"'), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + }, + (columns) => ({ + default_values_updated_at_idx: index('default_values_updated_at_idx').on(columns.updatedAt), + default_values_created_at_idx: index('default_values_created_at_idx').on(columns.createdAt), + }), +) + +export const relation_a = sqliteTable( + 'relation_a', + { + id: integer('id').primaryKey(), + title: text('title'), + richText: text('rich_text', { mode: 'json' }), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + }, + (columns) => ({ + relation_a_updated_at_idx: index('relation_a_updated_at_idx').on(columns.updatedAt), + relation_a_created_at_idx: index('relation_a_created_at_idx').on(columns.createdAt), + }), +) + +export const relation_b = sqliteTable( + 'relation_b', + { + id: integer('id').primaryKey(), + title: text('title'), + relationship: integer('relationship_id').references(() => relation_a.id, { + onDelete: 'set null', + }), + richText: text('rich_text', { mode: 'json' }), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + }, + (columns) => ({ + relation_b_relationship_idx: index('relation_b_relationship_idx').on(columns.relationship), + relation_b_updated_at_idx: index('relation_b_updated_at_idx').on(columns.updatedAt), + relation_b_created_at_idx: index('relation_b_created_at_idx').on(columns.createdAt), + }), +) + +export const pg_migrations_my_array_my_sub_array = sqliteTable( + 'pg_migrations_my_array_my_sub_array', + { + _order: integer('_order').notNull(), + _parentID: text('_parent_id').notNull(), + id: text('id').primaryKey(), + }, + (columns) => ({ + _orderIdx: index('pg_migrations_my_array_my_sub_array_order_idx').on(columns._order), + _parentIDIdx: index('pg_migrations_my_array_my_sub_array_parent_id_idx').on(columns._parentID), + _parentIDFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [pg_migrations_my_array.id], + name: 'pg_migrations_my_array_my_sub_array_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const pg_migrations_my_array_my_sub_array_locales = sqliteTable( + 'pg_migrations_my_array_my_sub_array_locales', + { + relation3: integer('relation3_id').references(() => relation_b.id, { + onDelete: 'set null', + }), + id: integer('id').primaryKey(), + _locale: text('_locale', { enum: ['en', 'es'] }).notNull(), + _parentID: text('_parent_id').notNull(), + }, + (columns) => ({ + pg_migrations_my_array_my_sub_array_relation3_idx: index( + 'pg_migrations_my_array_my_sub_array_relation3_idx', + ).on(columns.relation3, columns._locale), + _localeParent: uniqueIndex( + 'pg_migrations_my_array_my_sub_array_locales_locale_parent_id_unique', + ).on(columns._locale, columns._parentID), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [pg_migrations_my_array_my_sub_array.id], + name: 'pg_migrations_my_array_my_sub_array_locales_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const pg_migrations_my_array = sqliteTable( + 'pg_migrations_my_array', + { + _order: integer('_order').notNull(), + _parentID: integer('_parent_id').notNull(), + id: text('id').primaryKey(), + relation2: integer('relation2_id').references(() => relation_b.id, { + onDelete: 'set null', + }), + }, + (columns) => ({ + _orderIdx: index('pg_migrations_my_array_order_idx').on(columns._order), + _parentIDIdx: index('pg_migrations_my_array_parent_id_idx').on(columns._parentID), + pg_migrations_my_array_relation2_idx: index('pg_migrations_my_array_relation2_idx').on( + columns.relation2, + ), + _parentIDFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [pg_migrations.id], + name: 'pg_migrations_my_array_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const pg_migrations_blocks_my_block = sqliteTable( + 'pg_migrations_blocks_my_block', + { + _order: integer('_order').notNull(), + _parentID: integer('_parent_id').notNull(), + _path: text('_path').notNull(), + id: text('id').primaryKey(), + relation5: integer('relation5_id').references(() => relation_a.id, { + onDelete: 'set null', + }), + blockName: text('block_name'), + }, + (columns) => ({ + _orderIdx: index('pg_migrations_blocks_my_block_order_idx').on(columns._order), + _parentIDIdx: index('pg_migrations_blocks_my_block_parent_id_idx').on(columns._parentID), + _pathIdx: index('pg_migrations_blocks_my_block_path_idx').on(columns._path), + pg_migrations_blocks_my_block_relation5_idx: index( + 'pg_migrations_blocks_my_block_relation5_idx', + ).on(columns.relation5), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [pg_migrations.id], + name: 'pg_migrations_blocks_my_block_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const pg_migrations_blocks_my_block_locales = sqliteTable( + 'pg_migrations_blocks_my_block_locales', + { + relation6: integer('relation6_id').references(() => relation_b.id, { + onDelete: 'set null', + }), + id: integer('id').primaryKey(), + _locale: text('_locale', { enum: ['en', 'es'] }).notNull(), + _parentID: text('_parent_id').notNull(), + }, + (columns) => ({ + pg_migrations_blocks_my_block_relation6_idx: index( + 'pg_migrations_blocks_my_block_relation6_idx', + ).on(columns.relation6, columns._locale), + _localeParent: uniqueIndex('pg_migrations_blocks_my_block_locales_locale_parent_id_unique').on( + columns._locale, + columns._parentID, + ), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [pg_migrations_blocks_my_block.id], + name: 'pg_migrations_blocks_my_block_locales_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const pg_migrations = sqliteTable( + 'pg_migrations', + { + id: integer('id').primaryKey(), + relation1: integer('relation1_id').references(() => relation_a.id, { + onDelete: 'set null', + }), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + }, + (columns) => ({ + pg_migrations_relation1_idx: index('pg_migrations_relation1_idx').on(columns.relation1), + pg_migrations_updated_at_idx: index('pg_migrations_updated_at_idx').on(columns.updatedAt), + pg_migrations_created_at_idx: index('pg_migrations_created_at_idx').on(columns.createdAt), + }), +) + +export const pg_migrations_locales = sqliteTable( + 'pg_migrations_locales', + { + myGroup_relation4: integer('my_group_relation4_id').references(() => relation_b.id, { + onDelete: 'set null', + }), + id: integer('id').primaryKey(), + _locale: text('_locale', { enum: ['en', 'es'] }).notNull(), + _parentID: integer('_parent_id').notNull(), + }, + (columns) => ({ + pg_migrations_my_group_my_group_relation4_idx: index( + 'pg_migrations_my_group_my_group_relation4_idx', + ).on(columns.myGroup_relation4, columns._locale), + _localeParent: uniqueIndex('pg_migrations_locales_locale_parent_id_unique').on( + columns._locale, + columns._parentID, + ), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [pg_migrations.id], + name: 'pg_migrations_locales_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const _pg_migrations_v_version_my_array_my_sub_array = sqliteTable( + '_pg_migrations_v_version_my_array_my_sub_array', + { + _order: integer('_order').notNull(), + _parentID: integer('_parent_id').notNull(), + id: integer('id').primaryKey(), + _uuid: text('_uuid'), + }, + (columns) => ({ + _orderIdx: index('_pg_migrations_v_version_my_array_my_sub_array_order_idx').on(columns._order), + _parentIDIdx: index('_pg_migrations_v_version_my_array_my_sub_array_parent_id_idx').on( + columns._parentID, + ), + _parentIDFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [_pg_migrations_v_version_my_array.id], + name: '_pg_migrations_v_version_my_array_my_sub_array_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const _pg_migrations_v_version_my_array_my_sub_array_locales = sqliteTable( + '_pg_migrations_v_version_my_array_my_sub_array_locales', + { + relation3: integer('relation3_id').references(() => relation_b.id, { + onDelete: 'set null', + }), + id: integer('id').primaryKey(), + _locale: text('_locale', { enum: ['en', 'es'] }).notNull(), + _parentID: integer('_parent_id').notNull(), + }, + (columns) => ({ + _pg_migrations_v_version_my_array_my_sub_array_relation3_idx: index( + '_pg_migrations_v_version_my_array_my_sub_array_relation3_idx', + ).on(columns.relation3, columns._locale), + _localeParent: uniqueIndex( + '_pg_migrations_v_version_my_array_my_sub_array_locales_locale_parent_id_unique', + ).on(columns._locale, columns._parentID), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [_pg_migrations_v_version_my_array_my_sub_array.id], + name: '_pg_migrations_v_version_my_array_my_sub_array_locales_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const _pg_migrations_v_version_my_array = sqliteTable( + '_pg_migrations_v_version_my_array', + { + _order: integer('_order').notNull(), + _parentID: integer('_parent_id').notNull(), + id: integer('id').primaryKey(), + relation2: integer('relation2_id').references(() => relation_b.id, { + onDelete: 'set null', + }), + _uuid: text('_uuid'), + }, + (columns) => ({ + _orderIdx: index('_pg_migrations_v_version_my_array_order_idx').on(columns._order), + _parentIDIdx: index('_pg_migrations_v_version_my_array_parent_id_idx').on(columns._parentID), + _pg_migrations_v_version_my_array_relation2_idx: index( + '_pg_migrations_v_version_my_array_relation2_idx', + ).on(columns.relation2), + _parentIDFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [_pg_migrations_v.id], + name: '_pg_migrations_v_version_my_array_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const _pg_migrations_v_blocks_my_block = sqliteTable( + '_pg_migrations_v_blocks_my_block', + { + _order: integer('_order').notNull(), + _parentID: integer('_parent_id').notNull(), + _path: text('_path').notNull(), + id: integer('id').primaryKey(), + relation5: integer('relation5_id').references(() => relation_a.id, { + onDelete: 'set null', + }), + _uuid: text('_uuid'), + blockName: text('block_name'), + }, + (columns) => ({ + _orderIdx: index('_pg_migrations_v_blocks_my_block_order_idx').on(columns._order), + _parentIDIdx: index('_pg_migrations_v_blocks_my_block_parent_id_idx').on(columns._parentID), + _pathIdx: index('_pg_migrations_v_blocks_my_block_path_idx').on(columns._path), + _pg_migrations_v_blocks_my_block_relation5_idx: index( + '_pg_migrations_v_blocks_my_block_relation5_idx', + ).on(columns.relation5), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [_pg_migrations_v.id], + name: '_pg_migrations_v_blocks_my_block_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const _pg_migrations_v_blocks_my_block_locales = sqliteTable( + '_pg_migrations_v_blocks_my_block_locales', + { + relation6: integer('relation6_id').references(() => relation_b.id, { + onDelete: 'set null', + }), + id: integer('id').primaryKey(), + _locale: text('_locale', { enum: ['en', 'es'] }).notNull(), + _parentID: integer('_parent_id').notNull(), + }, + (columns) => ({ + _pg_migrations_v_blocks_my_block_relation6_idx: index( + '_pg_migrations_v_blocks_my_block_relation6_idx', + ).on(columns.relation6, columns._locale), + _localeParent: uniqueIndex( + '_pg_migrations_v_blocks_my_block_locales_locale_parent_id_unique', + ).on(columns._locale, columns._parentID), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [_pg_migrations_v_blocks_my_block.id], + name: '_pg_migrations_v_blocks_my_block_locales_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const _pg_migrations_v = sqliteTable( + '_pg_migrations_v', + { + id: integer('id').primaryKey(), + parent: integer('parent_id').references(() => pg_migrations.id, { + onDelete: 'set null', + }), + version_relation1: integer('version_relation1_id').references(() => relation_a.id, { + onDelete: 'set null', + }), + version_updatedAt: text('version_updated_at').default( + sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`, + ), + version_createdAt: text('version_created_at').default( + sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`, + ), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + }, + (columns) => ({ + _pg_migrations_v_parent_idx: index('_pg_migrations_v_parent_idx').on(columns.parent), + _pg_migrations_v_version_version_relation1_idx: index( + '_pg_migrations_v_version_version_relation1_idx', + ).on(columns.version_relation1), + _pg_migrations_v_version_version_updated_at_idx: index( + '_pg_migrations_v_version_version_updated_at_idx', + ).on(columns.version_updatedAt), + _pg_migrations_v_version_version_created_at_idx: index( + '_pg_migrations_v_version_version_created_at_idx', + ).on(columns.version_createdAt), + _pg_migrations_v_created_at_idx: index('_pg_migrations_v_created_at_idx').on(columns.createdAt), + _pg_migrations_v_updated_at_idx: index('_pg_migrations_v_updated_at_idx').on(columns.updatedAt), + }), +) + +export const _pg_migrations_v_locales = sqliteTable( + '_pg_migrations_v_locales', + { + version_myGroup_relation4: integer('version_my_group_relation4_id').references( + () => relation_b.id, + { + onDelete: 'set null', + }, + ), + id: integer('id').primaryKey(), + _locale: text('_locale', { enum: ['en', 'es'] }).notNull(), + _parentID: integer('_parent_id').notNull(), + }, + (columns) => ({ + _pg_migrations_v_version_my_group_version_my_group_relation4_idx: index( + '_pg_migrations_v_version_my_group_version_my_group_relation4_idx', + ).on(columns.version_myGroup_relation4, columns._locale), + _localeParent: uniqueIndex('_pg_migrations_v_locales_locale_parent_id_unique').on( + columns._locale, + columns._parentID, + ), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [_pg_migrations_v.id], + name: '_pg_migrations_v_locales_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const customs_customSelect = sqliteTable( + 'customs_customSelect', + { + order: integer('order').notNull(), + parent: integer('parent_id').notNull(), + value: text('value', { enum: ['a', 'b', 'c'] }), + id: integer('id').primaryKey(), + }, + (columns) => ({ + orderIdx: index('customs_customSelect_order_idx').on(columns.order), + parentIdx: index('customs_customSelect_parent_idx').on(columns.parent), + parentFk: foreignKey({ + columns: [columns['parent']], + foreignColumns: [customs.id], + name: 'customs_customSelect_parent_fk', + }).onDelete('cascade'), + }), +) + +export const customArrays = sqliteTable( + 'customArrays', + { + _order: integer('_order').notNull(), + _parentID: integer('_parent_id').notNull(), + id: text('id').primaryKey(), + text: text('text'), + }, + (columns) => ({ + _orderIdx: index('customArrays_order_idx').on(columns._order), + _parentIDIdx: index('customArrays_parent_id_idx').on(columns._parentID), + _parentIDFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [customs.id], + name: 'customArrays_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const customArrays_locales = sqliteTable( + 'customArrays_locales', + { + localizedText: text('localized_text'), + id: integer('id').primaryKey(), + _locale: text('_locale', { enum: ['en', 'es'] }).notNull(), + _parentID: text('_parent_id').notNull(), + }, + (columns) => ({ + _localeParent: uniqueIndex('customArrays_locales_locale_parent_id_unique').on( + columns._locale, + columns._parentID, + ), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [customArrays.id], + name: 'customArrays_locales_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const customBlocks = sqliteTable( + 'customBlocks', + { + _order: integer('_order').notNull(), + _parentID: integer('_parent_id').notNull(), + _path: text('_path').notNull(), + id: text('id').primaryKey(), + text: text('text'), + blockName: text('block_name'), + }, + (columns) => ({ + _orderIdx: index('customBlocks_order_idx').on(columns._order), + _parentIDIdx: index('customBlocks_parent_id_idx').on(columns._parentID), + _pathIdx: index('customBlocks_path_idx').on(columns._path), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [customs.id], + name: 'customBlocks_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const customBlocks_locales = sqliteTable( + 'customBlocks_locales', + { + localizedText: text('localized_text'), + id: integer('id').primaryKey(), + _locale: text('_locale', { enum: ['en', 'es'] }).notNull(), + _parentID: text('_parent_id').notNull(), + }, + (columns) => ({ + _localeParent: uniqueIndex('customBlocks_locales_locale_parent_id_unique').on( + columns._locale, + columns._parentID, + ), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [customBlocks.id], + name: 'customBlocks_locales_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const customs = sqliteTable( + 'customs', + { + id: integer('id').primaryKey(), + text: text('text'), + radio: text('radio', { enum: ['a', 'b', 'c'] }), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + _status: text('_status', { enum: ['draft', 'published'] }).default('draft'), + }, + (columns) => ({ + customs_updated_at_idx: index('customs_updated_at_idx').on(columns.updatedAt), + customs_created_at_idx: index('customs_created_at_idx').on(columns.createdAt), + customs__status_idx: index('customs__status_idx').on(columns._status), + }), +) + +export const customs_locales = sqliteTable( + 'customs_locales', + { + localizedText: text('localized_text'), + id: integer('id').primaryKey(), + _locale: text('_locale', { enum: ['en', 'es'] }).notNull(), + _parentID: integer('_parent_id').notNull(), + }, + (columns) => ({ + _localeParent: uniqueIndex('customs_locales_locale_parent_id_unique').on( + columns._locale, + columns._parentID, + ), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [customs.id], + name: 'customs_locales_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const customs_rels = sqliteTable( + 'customs_rels', + { + id: integer('id').primaryKey(), + order: integer('order'), + parent: integer('parent_id').notNull(), + path: text('path').notNull(), + 'relation-aID': integer('relation_a_id'), + }, + (columns) => ({ + order: index('customs_rels_order_idx').on(columns.order), + parentIdx: index('customs_rels_parent_idx').on(columns.parent), + pathIdx: index('customs_rels_path_idx').on(columns.path), + customs_rels_relation_a_id_idx: index('customs_rels_relation_a_id_idx').on( + columns['relation-aID'], + ), + parentFk: foreignKey({ + columns: [columns['parent']], + foreignColumns: [customs.id], + name: 'customs_rels_parent_fk', + }).onDelete('cascade'), + 'relation-aIdFk': foreignKey({ + columns: [columns['relation-aID']], + foreignColumns: [relation_a.id], + name: 'customs_rels_relation_a_fk', + }).onDelete('cascade'), + }), +) + +export const __customs_v_version_customSelect_v = sqliteTable( + '__customs_v_version_customSelect_v', + { + order: integer('order').notNull(), + parent: integer('parent_id').notNull(), + value: text('value', { enum: ['a', 'b', 'c'] }), + id: integer('id').primaryKey(), + }, + (columns) => ({ + orderIdx: index('__customs_v_version_customSelect_v_order_idx').on(columns.order), + parentIdx: index('__customs_v_version_customSelect_v_parent_idx').on(columns.parent), + parentFk: foreignKey({ + columns: [columns['parent']], + foreignColumns: [_customs_v.id], + name: '__customs_v_version_customSelect_v_parent_fk', + }).onDelete('cascade'), + }), +) + +export const _customArrays_v = sqliteTable( + '_customArrays_v', + { + _order: integer('_order').notNull(), + _parentID: integer('_parent_id').notNull(), + id: integer('id').primaryKey(), + text: text('text'), + _uuid: text('_uuid'), + }, + (columns) => ({ + _orderIdx: index('_customArrays_v_order_idx').on(columns._order), + _parentIDIdx: index('_customArrays_v_parent_id_idx').on(columns._parentID), + _parentIDFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [_customs_v.id], + name: '_customArrays_v_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const _customArrays_v_locales = sqliteTable( + '_customArrays_v_locales', + { + localizedText: text('localized_text'), + id: integer('id').primaryKey(), + _locale: text('_locale', { enum: ['en', 'es'] }).notNull(), + _parentID: integer('_parent_id').notNull(), + }, + (columns) => ({ + _localeParent: uniqueIndex('_customArrays_v_locales_locale_parent_id_unique').on( + columns._locale, + columns._parentID, + ), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [_customArrays_v.id], + name: '_customArrays_v_locales_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const _customBlocks_v = sqliteTable( + '_customBlocks_v', + { + _order: integer('_order').notNull(), + _parentID: integer('_parent_id').notNull(), + _path: text('_path').notNull(), + id: integer('id').primaryKey(), + text: text('text'), + _uuid: text('_uuid'), + blockName: text('block_name'), + }, + (columns) => ({ + _orderIdx: index('_customBlocks_v_order_idx').on(columns._order), + _parentIDIdx: index('_customBlocks_v_parent_id_idx').on(columns._parentID), + _pathIdx: index('_customBlocks_v_path_idx').on(columns._path), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [_customs_v.id], + name: '_customBlocks_v_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const _customBlocks_v_locales = sqliteTable( + '_customBlocks_v_locales', + { + localizedText: text('localized_text'), + id: integer('id').primaryKey(), + _locale: text('_locale', { enum: ['en', 'es'] }).notNull(), + _parentID: integer('_parent_id').notNull(), + }, + (columns) => ({ + _localeParent: uniqueIndex('_customBlocks_v_locales_locale_parent_id_unique').on( + columns._locale, + columns._parentID, + ), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [_customBlocks_v.id], + name: '_customBlocks_v_locales_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const _customs_v = sqliteTable( + '_customs_v', + { + id: integer('id').primaryKey(), + parent: integer('parent_id').references(() => customs.id, { + onDelete: 'set null', + }), + version_text: text('version_text'), + version_radio: text('version_radio', { enum: ['a', 'b', 'c'] }), + version_updatedAt: text('version_updated_at').default( + sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`, + ), + version_createdAt: text('version_created_at').default( + sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`, + ), + version__status: text('version__status', { enum: ['draft', 'published'] }).default('draft'), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + snapshot: integer('snapshot', { mode: 'boolean' }), + publishedLocale: text('published_locale', { enum: ['en', 'es'] }), + latest: integer('latest', { mode: 'boolean' }), + }, + (columns) => ({ + _customs_v_parent_idx: index('_customs_v_parent_idx').on(columns.parent), + _customs_v_version_version_updated_at_idx: index( + '_customs_v_version_version_updated_at_idx', + ).on(columns.version_updatedAt), + _customs_v_version_version_created_at_idx: index( + '_customs_v_version_version_created_at_idx', + ).on(columns.version_createdAt), + _customs_v_version_version__status_idx: index('_customs_v_version_version__status_idx').on( + columns.version__status, + ), + _customs_v_created_at_idx: index('_customs_v_created_at_idx').on(columns.createdAt), + _customs_v_updated_at_idx: index('_customs_v_updated_at_idx').on(columns.updatedAt), + _customs_v_snapshot_idx: index('_customs_v_snapshot_idx').on(columns.snapshot), + _customs_v_published_locale_idx: index('_customs_v_published_locale_idx').on( + columns.publishedLocale, + ), + _customs_v_latest_idx: index('_customs_v_latest_idx').on(columns.latest), + }), +) + +export const _customs_v_locales = sqliteTable( + '_customs_v_locales', + { + version_localizedText: text('version_localized_text'), + id: integer('id').primaryKey(), + _locale: text('_locale', { enum: ['en', 'es'] }).notNull(), + _parentID: integer('_parent_id').notNull(), + }, + (columns) => ({ + _localeParent: uniqueIndex('_customs_v_locales_locale_parent_id_unique').on( + columns._locale, + columns._parentID, + ), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [_customs_v.id], + name: '_customs_v_locales_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const _customs_v_rels = sqliteTable( + '_customs_v_rels', + { + id: integer('id').primaryKey(), + order: integer('order'), + parent: integer('parent_id').notNull(), + path: text('path').notNull(), + 'relation-aID': integer('relation_a_id'), + }, + (columns) => ({ + order: index('_customs_v_rels_order_idx').on(columns.order), + parentIdx: index('_customs_v_rels_parent_idx').on(columns.parent), + pathIdx: index('_customs_v_rels_path_idx').on(columns.path), + _customs_v_rels_relation_a_id_idx: index('_customs_v_rels_relation_a_id_idx').on( + columns['relation-aID'], + ), + parentFk: foreignKey({ + columns: [columns['parent']], + foreignColumns: [_customs_v.id], + name: '_customs_v_rels_parent_fk', + }).onDelete('cascade'), + 'relation-aIdFk': foreignKey({ + columns: [columns['relation-aID']], + foreignColumns: [relation_a.id], + name: '_customs_v_rels_relation_a_fk', + }).onDelete('cascade'), + }), +) + +export const places = sqliteTable( + 'places', + { + id: integer('id').primaryKey(), + country: text('country'), + city: text('city'), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + }, + (columns) => ({ + places_updated_at_idx: index('places_updated_at_idx').on(columns.updatedAt), + places_created_at_idx: index('places_created_at_idx').on(columns.createdAt), + }), +) + +export const fields_persistance = sqliteTable( + 'fields_persistance', + { + id: integer('id').primaryKey(), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + }, + (columns) => ({ + fields_persistance_updated_at_idx: index('fields_persistance_updated_at_idx').on( + columns.updatedAt, + ), + fields_persistance_created_at_idx: index('fields_persistance_created_at_idx').on( + columns.createdAt, + ), + }), +) + +export const custom_ids = sqliteTable( + 'custom_ids', + { + id: text('id').primaryKey(), + title: text('title'), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + _status: text('_status', { enum: ['draft', 'published'] }).default('draft'), + }, + (columns) => ({ + custom_ids_updated_at_idx: index('custom_ids_updated_at_idx').on(columns.updatedAt), + custom_ids_created_at_idx: index('custom_ids_created_at_idx').on(columns.createdAt), + custom_ids__status_idx: index('custom_ids__status_idx').on(columns._status), + }), +) + +export const _custom_ids_v = sqliteTable( + '_custom_ids_v', + { + id: integer('id').primaryKey(), + parent: text('parent_id').references(() => custom_ids.id, { + onDelete: 'set null', + }), + version_title: text('version_title'), + version_updatedAt: text('version_updated_at').default( + sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`, + ), + version_createdAt: text('version_created_at').default( + sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`, + ), + version__status: text('version__status', { enum: ['draft', 'published'] }).default('draft'), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + snapshot: integer('snapshot', { mode: 'boolean' }), + publishedLocale: text('published_locale', { enum: ['en', 'es'] }), + latest: integer('latest', { mode: 'boolean' }), + }, + (columns) => ({ + _custom_ids_v_parent_idx: index('_custom_ids_v_parent_idx').on(columns.parent), + _custom_ids_v_version_version_updated_at_idx: index( + '_custom_ids_v_version_version_updated_at_idx', + ).on(columns.version_updatedAt), + _custom_ids_v_version_version_created_at_idx: index( + '_custom_ids_v_version_version_created_at_idx', + ).on(columns.version_createdAt), + _custom_ids_v_version_version__status_idx: index( + '_custom_ids_v_version_version__status_idx', + ).on(columns.version__status), + _custom_ids_v_created_at_idx: index('_custom_ids_v_created_at_idx').on(columns.createdAt), + _custom_ids_v_updated_at_idx: index('_custom_ids_v_updated_at_idx').on(columns.updatedAt), + _custom_ids_v_snapshot_idx: index('_custom_ids_v_snapshot_idx').on(columns.snapshot), + _custom_ids_v_published_locale_idx: index('_custom_ids_v_published_locale_idx').on( + columns.publishedLocale, + ), + _custom_ids_v_latest_idx: index('_custom_ids_v_latest_idx').on(columns.latest), + }), +) + +export const fake_custom_ids = sqliteTable( + 'fake_custom_ids', + { + id: integer('id').primaryKey(), + title: text('title'), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + }, + (columns) => ({ + fake_custom_ids_updated_at_idx: index('fake_custom_ids_updated_at_idx').on(columns.updatedAt), + fake_custom_ids_created_at_idx: index('fake_custom_ids_created_at_idx').on(columns.createdAt), + }), +) + +export const relationships_migration = sqliteTable( + 'relationships_migration', + { + id: integer('id').primaryKey(), + relationship: integer('relationship_id').references(() => default_values.id, { + onDelete: 'set null', + }), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + }, + (columns) => ({ + relationships_migration_relationship_idx: index('relationships_migration_relationship_idx').on( + columns.relationship, + ), + relationships_migration_updated_at_idx: index('relationships_migration_updated_at_idx').on( + columns.updatedAt, + ), + relationships_migration_created_at_idx: index('relationships_migration_created_at_idx').on( + columns.createdAt, + ), + }), +) + +export const relationships_migration_rels = sqliteTable( + 'relationships_migration_rels', + { + id: integer('id').primaryKey(), + order: integer('order'), + parent: integer('parent_id').notNull(), + path: text('path').notNull(), + 'default-valuesID': integer('default_values_id'), + }, + (columns) => ({ + order: index('relationships_migration_rels_order_idx').on(columns.order), + parentIdx: index('relationships_migration_rels_parent_idx').on(columns.parent), + pathIdx: index('relationships_migration_rels_path_idx').on(columns.path), + relationships_migration_rels_default_values_id_idx: index( + 'relationships_migration_rels_default_values_id_idx', + ).on(columns['default-valuesID']), + parentFk: foreignKey({ + columns: [columns['parent']], + foreignColumns: [relationships_migration.id], + name: 'relationships_migration_rels_parent_fk', + }).onDelete('cascade'), + 'default-valuesIdFk': foreignKey({ + columns: [columns['default-valuesID']], + foreignColumns: [default_values.id], + name: 'relationships_migration_rels_default_values_fk', + }).onDelete('cascade'), + }), +) + +export const _relationships_migration_v = sqliteTable( + '_relationships_migration_v', + { + id: integer('id').primaryKey(), + parent: integer('parent_id').references(() => relationships_migration.id, { + onDelete: 'set null', + }), + version_relationship: integer('version_relationship_id').references(() => default_values.id, { + onDelete: 'set null', + }), + version_updatedAt: text('version_updated_at').default( + sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`, + ), + version_createdAt: text('version_created_at').default( + sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`, + ), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + }, + (columns) => ({ + _relationships_migration_v_parent_idx: index('_relationships_migration_v_parent_idx').on( + columns.parent, + ), + _relationships_migration_v_version_version_relationship_idx: index( + '_relationships_migration_v_version_version_relationship_idx', + ).on(columns.version_relationship), + _relationships_migration_v_version_version_updated_at_idx: index( + '_relationships_migration_v_version_version_updated_at_idx', + ).on(columns.version_updatedAt), + _relationships_migration_v_version_version_created_at_idx: index( + '_relationships_migration_v_version_version_created_at_idx', + ).on(columns.version_createdAt), + _relationships_migration_v_created_at_idx: index( + '_relationships_migration_v_created_at_idx', + ).on(columns.createdAt), + _relationships_migration_v_updated_at_idx: index( + '_relationships_migration_v_updated_at_idx', + ).on(columns.updatedAt), + }), +) + +export const _relationships_migration_v_rels = sqliteTable( + '_relationships_migration_v_rels', + { + id: integer('id').primaryKey(), + order: integer('order'), + parent: integer('parent_id').notNull(), + path: text('path').notNull(), + 'default-valuesID': integer('default_values_id'), + }, + (columns) => ({ + order: index('_relationships_migration_v_rels_order_idx').on(columns.order), + parentIdx: index('_relationships_migration_v_rels_parent_idx').on(columns.parent), + pathIdx: index('_relationships_migration_v_rels_path_idx').on(columns.path), + _relationships_migration_v_rels_default_values_id_idx: index( + '_relationships_migration_v_rels_default_values_id_idx', + ).on(columns['default-valuesID']), + parentFk: foreignKey({ + columns: [columns['parent']], + foreignColumns: [_relationships_migration_v.id], + name: '_relationships_migration_v_rels_parent_fk', + }).onDelete('cascade'), + 'default-valuesIdFk': foreignKey({ + columns: [columns['default-valuesID']], + foreignColumns: [default_values.id], + name: '_relationships_migration_v_rels_default_values_fk', + }).onDelete('cascade'), + }), +) + +export const users = sqliteTable( + 'users', + { + id: integer('id').primaryKey(), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + email: text('email').notNull(), + resetPasswordToken: text('reset_password_token'), + resetPasswordExpiration: text('reset_password_expiration').default( + sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`, + ), + salt: text('salt'), + hash: text('hash'), + loginAttempts: numeric('login_attempts').default('0'), + lockUntil: text('lock_until').default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + }, + (columns) => ({ + users_updated_at_idx: index('users_updated_at_idx').on(columns.updatedAt), + users_created_at_idx: index('users_created_at_idx').on(columns.createdAt), + users_email_idx: uniqueIndex('users_email_idx').on(columns.email), + }), +) + +export const payload_locked_documents = sqliteTable( + 'payload_locked_documents', + { + id: integer('id').primaryKey(), + globalSlug: text('global_slug'), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + }, + (columns) => ({ + payload_locked_documents_global_slug_idx: index('payload_locked_documents_global_slug_idx').on( + columns.globalSlug, + ), + payload_locked_documents_updated_at_idx: index('payload_locked_documents_updated_at_idx').on( + columns.updatedAt, + ), + payload_locked_documents_created_at_idx: index('payload_locked_documents_created_at_idx').on( + columns.createdAt, + ), + }), +) + +export const payload_locked_documents_rels = sqliteTable( + 'payload_locked_documents_rels', + { + id: integer('id').primaryKey(), + order: integer('order'), + parent: integer('parent_id').notNull(), + path: text('path').notNull(), + postsID: integer('posts_id'), + 'default-valuesID': integer('default_values_id'), + 'relation-aID': integer('relation_a_id'), + 'relation-bID': integer('relation_b_id'), + 'pg-migrationsID': integer('pg_migrations_id'), + 'custom-schemaID': integer('customs_id'), + placesID: integer('places_id'), + 'fields-persistanceID': integer('fields_persistance_id'), + 'custom-idsID': text('custom_ids_id'), + 'fake-custom-idsID': integer('fake_custom_ids_id'), + 'relationships-migrationID': integer('relationships_migration_id'), + usersID: integer('users_id'), + }, + (columns) => ({ + order: index('payload_locked_documents_rels_order_idx').on(columns.order), + parentIdx: index('payload_locked_documents_rels_parent_idx').on(columns.parent), + pathIdx: index('payload_locked_documents_rels_path_idx').on(columns.path), + payload_locked_documents_rels_posts_id_idx: index( + 'payload_locked_documents_rels_posts_id_idx', + ).on(columns.postsID), + payload_locked_documents_rels_default_values_id_idx: index( + 'payload_locked_documents_rels_default_values_id_idx', + ).on(columns['default-valuesID']), + payload_locked_documents_rels_relation_a_id_idx: index( + 'payload_locked_documents_rels_relation_a_id_idx', + ).on(columns['relation-aID']), + payload_locked_documents_rels_relation_b_id_idx: index( + 'payload_locked_documents_rels_relation_b_id_idx', + ).on(columns['relation-bID']), + payload_locked_documents_rels_pg_migrations_id_idx: index( + 'payload_locked_documents_rels_pg_migrations_id_idx', + ).on(columns['pg-migrationsID']), + payload_locked_documents_rels_customs_id_idx: index( + 'payload_locked_documents_rels_customs_id_idx', + ).on(columns['custom-schemaID']), + payload_locked_documents_rels_places_id_idx: index( + 'payload_locked_documents_rels_places_id_idx', + ).on(columns.placesID), + payload_locked_documents_rels_fields_persistance_id_idx: index( + 'payload_locked_documents_rels_fields_persistance_id_idx', + ).on(columns['fields-persistanceID']), + payload_locked_documents_rels_custom_ids_id_idx: index( + 'payload_locked_documents_rels_custom_ids_id_idx', + ).on(columns['custom-idsID']), + payload_locked_documents_rels_fake_custom_ids_id_idx: index( + 'payload_locked_documents_rels_fake_custom_ids_id_idx', + ).on(columns['fake-custom-idsID']), + payload_locked_documents_rels_relationships_migration_id_idx: index( + 'payload_locked_documents_rels_relationships_migration_id_idx', + ).on(columns['relationships-migrationID']), + payload_locked_documents_rels_users_id_idx: index( + 'payload_locked_documents_rels_users_id_idx', + ).on(columns.usersID), + parentFk: foreignKey({ + columns: [columns['parent']], + foreignColumns: [payload_locked_documents.id], + name: 'payload_locked_documents_rels_parent_fk', + }).onDelete('cascade'), + postsIdFk: foreignKey({ + columns: [columns['postsID']], + foreignColumns: [posts.id], + name: 'payload_locked_documents_rels_posts_fk', + }).onDelete('cascade'), + 'default-valuesIdFk': foreignKey({ + columns: [columns['default-valuesID']], + foreignColumns: [default_values.id], + name: 'payload_locked_documents_rels_default_values_fk', + }).onDelete('cascade'), + 'relation-aIdFk': foreignKey({ + columns: [columns['relation-aID']], + foreignColumns: [relation_a.id], + name: 'payload_locked_documents_rels_relation_a_fk', + }).onDelete('cascade'), + 'relation-bIdFk': foreignKey({ + columns: [columns['relation-bID']], + foreignColumns: [relation_b.id], + name: 'payload_locked_documents_rels_relation_b_fk', + }).onDelete('cascade'), + 'pg-migrationsIdFk': foreignKey({ + columns: [columns['pg-migrationsID']], + foreignColumns: [pg_migrations.id], + name: 'payload_locked_documents_rels_pg_migrations_fk', + }).onDelete('cascade'), + 'custom-schemaIdFk': foreignKey({ + columns: [columns['custom-schemaID']], + foreignColumns: [customs.id], + name: 'payload_locked_documents_rels_custom_schema_fk', + }).onDelete('cascade'), + placesIdFk: foreignKey({ + columns: [columns['placesID']], + foreignColumns: [places.id], + name: 'payload_locked_documents_rels_places_fk', + }).onDelete('cascade'), + 'fields-persistanceIdFk': foreignKey({ + columns: [columns['fields-persistanceID']], + foreignColumns: [fields_persistance.id], + name: 'payload_locked_documents_rels_fields_persistance_fk', + }).onDelete('cascade'), + 'custom-idsIdFk': foreignKey({ + columns: [columns['custom-idsID']], + foreignColumns: [custom_ids.id], + name: 'payload_locked_documents_rels_custom_ids_fk', + }).onDelete('cascade'), + 'fake-custom-idsIdFk': foreignKey({ + columns: [columns['fake-custom-idsID']], + foreignColumns: [fake_custom_ids.id], + name: 'payload_locked_documents_rels_fake_custom_ids_fk', + }).onDelete('cascade'), + 'relationships-migrationIdFk': foreignKey({ + columns: [columns['relationships-migrationID']], + foreignColumns: [relationships_migration.id], + name: 'payload_locked_documents_rels_relationships_migration_fk', + }).onDelete('cascade'), + usersIdFk: foreignKey({ + columns: [columns['usersID']], + foreignColumns: [users.id], + name: 'payload_locked_documents_rels_users_fk', + }).onDelete('cascade'), + }), +) + +export const payload_preferences = sqliteTable( + 'payload_preferences', + { + id: integer('id').primaryKey(), + key: text('key'), + value: text('value', { mode: 'json' }), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + }, + (columns) => ({ + payload_preferences_key_idx: index('payload_preferences_key_idx').on(columns.key), + payload_preferences_updated_at_idx: index('payload_preferences_updated_at_idx').on( + columns.updatedAt, + ), + payload_preferences_created_at_idx: index('payload_preferences_created_at_idx').on( + columns.createdAt, + ), + }), +) + +export const payload_preferences_rels = sqliteTable( + 'payload_preferences_rels', + { + id: integer('id').primaryKey(), + order: integer('order'), + parent: integer('parent_id').notNull(), + path: text('path').notNull(), + usersID: integer('users_id'), + }, + (columns) => ({ + order: index('payload_preferences_rels_order_idx').on(columns.order), + parentIdx: index('payload_preferences_rels_parent_idx').on(columns.parent), + pathIdx: index('payload_preferences_rels_path_idx').on(columns.path), + payload_preferences_rels_users_id_idx: index('payload_preferences_rels_users_id_idx').on( + columns.usersID, + ), + parentFk: foreignKey({ + columns: [columns['parent']], + foreignColumns: [payload_preferences.id], + name: 'payload_preferences_rels_parent_fk', + }).onDelete('cascade'), + usersIdFk: foreignKey({ + columns: [columns['usersID']], + foreignColumns: [users.id], + name: 'payload_preferences_rels_users_fk', + }).onDelete('cascade'), + }), +) + +export const payload_migrations = sqliteTable( + 'payload_migrations', + { + id: integer('id').primaryKey(), + name: text('name'), + batch: numeric('batch'), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + }, + (columns) => ({ + payload_migrations_updated_at_idx: index('payload_migrations_updated_at_idx').on( + columns.updatedAt, + ), + payload_migrations_created_at_idx: index('payload_migrations_created_at_idx').on( + columns.createdAt, + ), + }), +) + +export const customGlobal = sqliteTable('customGlobal', { + id: integer('id').primaryKey(), + text: text('text'), + updatedAt: text('updated_at').default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + createdAt: text('created_at').default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), +}) + +export const _customGlobal_v = sqliteTable( + '_customGlobal_v', + { + id: integer('id').primaryKey(), + version_text: text('version_text'), + version_updatedAt: text('version_updated_at').default( + sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`, + ), + version_createdAt: text('version_created_at').default( + sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`, + ), + createdAt: text('created_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + updatedAt: text('updated_at') + .notNull() + .default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`), + }, + (columns) => ({ + _customGlobal_v_created_at_idx: index('_customGlobal_v_created_at_idx').on(columns.createdAt), + _customGlobal_v_updated_at_idx: index('_customGlobal_v_updated_at_idx').on(columns.updatedAt), + }), +) + +export const relations_posts = relations(posts, () => ({})) +export const relations_default_values_array = relations(default_values_array, ({ one }) => ({ + _parentID: one(default_values, { + fields: [default_values_array._parentID], + references: [default_values.id], + relationName: 'array', + }), +})) +export const relations_default_values = relations(default_values, ({ many }) => ({ + array: many(default_values_array, { + relationName: 'array', + }), +})) +export const relations_relation_a = relations(relation_a, () => ({})) +export const relations_relation_b = relations(relation_b, ({ one }) => ({ + relationship: one(relation_a, { + fields: [relation_b.relationship], + references: [relation_a.id], + relationName: 'relationship', + }), +})) +export const relations_pg_migrations_my_array_my_sub_array_locales = relations( + pg_migrations_my_array_my_sub_array_locales, + ({ one }) => ({ + _parentID: one(pg_migrations_my_array_my_sub_array, { + fields: [pg_migrations_my_array_my_sub_array_locales._parentID], + references: [pg_migrations_my_array_my_sub_array.id], + relationName: '_locales', + }), + relation3: one(relation_b, { + fields: [pg_migrations_my_array_my_sub_array_locales.relation3], + references: [relation_b.id], + relationName: 'relation3', + }), + }), +) +export const relations_pg_migrations_my_array_my_sub_array = relations( + pg_migrations_my_array_my_sub_array, + ({ one, many }) => ({ + _parentID: one(pg_migrations_my_array, { + fields: [pg_migrations_my_array_my_sub_array._parentID], + references: [pg_migrations_my_array.id], + relationName: 'mySubArray', + }), + _locales: many(pg_migrations_my_array_my_sub_array_locales, { + relationName: '_locales', + }), + relation3: one(relation_b, { + // @ts-expect-error Drizzle TypeScript bug for ONE relationships with a field in different table + fields: [pg_migrations_my_array_my_sub_array_locales.relation3], + references: [relation_b.id], + relationName: 'relation3', + }), + }), +) +export const relations_pg_migrations_my_array = relations( + pg_migrations_my_array, + ({ one, many }) => ({ + _parentID: one(pg_migrations, { + fields: [pg_migrations_my_array._parentID], + references: [pg_migrations.id], + relationName: 'myArray', + }), + relation2: one(relation_b, { + fields: [pg_migrations_my_array.relation2], + references: [relation_b.id], + relationName: 'relation2', + }), + mySubArray: many(pg_migrations_my_array_my_sub_array, { + relationName: 'mySubArray', + }), + }), +) +export const relations_pg_migrations_blocks_my_block_locales = relations( + pg_migrations_blocks_my_block_locales, + ({ one }) => ({ + _parentID: one(pg_migrations_blocks_my_block, { + fields: [pg_migrations_blocks_my_block_locales._parentID], + references: [pg_migrations_blocks_my_block.id], + relationName: '_locales', + }), + relation6: one(relation_b, { + fields: [pg_migrations_blocks_my_block_locales.relation6], + references: [relation_b.id], + relationName: 'relation6', + }), + }), +) +export const relations_pg_migrations_blocks_my_block = relations( + pg_migrations_blocks_my_block, + ({ one, many }) => ({ + _parentID: one(pg_migrations, { + fields: [pg_migrations_blocks_my_block._parentID], + references: [pg_migrations.id], + relationName: '_blocks_myBlock', + }), + _locales: many(pg_migrations_blocks_my_block_locales, { + relationName: '_locales', + }), + relation5: one(relation_a, { + fields: [pg_migrations_blocks_my_block.relation5], + references: [relation_a.id], + relationName: 'relation5', + }), + relation6: one(relation_b, { + // @ts-expect-error Drizzle TypeScript bug for ONE relationships with a field in different table + fields: [pg_migrations_blocks_my_block_locales.relation6], + references: [relation_b.id], + relationName: 'relation6', + }), + }), +) +export const relations_pg_migrations_locales = relations(pg_migrations_locales, ({ one }) => ({ + _parentID: one(pg_migrations, { + fields: [pg_migrations_locales._parentID], + references: [pg_migrations.id], + relationName: '_locales', + }), + myGroup_relation4: one(relation_b, { + fields: [pg_migrations_locales.myGroup_relation4], + references: [relation_b.id], + relationName: 'myGroup_relation4', + }), +})) +export const relations_pg_migrations = relations(pg_migrations, ({ one, many }) => ({ + relation1: one(relation_a, { + fields: [pg_migrations.relation1], + references: [relation_a.id], + relationName: 'relation1', + }), + myArray: many(pg_migrations_my_array, { + relationName: 'myArray', + }), + _blocks_myBlock: many(pg_migrations_blocks_my_block, { + relationName: '_blocks_myBlock', + }), + _locales: many(pg_migrations_locales, { + relationName: '_locales', + }), +})) +export const relations__pg_migrations_v_version_my_array_my_sub_array_locales = relations( + _pg_migrations_v_version_my_array_my_sub_array_locales, + ({ one }) => ({ + _parentID: one(_pg_migrations_v_version_my_array_my_sub_array, { + fields: [_pg_migrations_v_version_my_array_my_sub_array_locales._parentID], + references: [_pg_migrations_v_version_my_array_my_sub_array.id], + relationName: '_locales', + }), + relation3: one(relation_b, { + fields: [_pg_migrations_v_version_my_array_my_sub_array_locales.relation3], + references: [relation_b.id], + relationName: 'relation3', + }), + }), +) +export const relations__pg_migrations_v_version_my_array_my_sub_array = relations( + _pg_migrations_v_version_my_array_my_sub_array, + ({ one, many }) => ({ + _parentID: one(_pg_migrations_v_version_my_array, { + fields: [_pg_migrations_v_version_my_array_my_sub_array._parentID], + references: [_pg_migrations_v_version_my_array.id], + relationName: 'mySubArray', + }), + _locales: many(_pg_migrations_v_version_my_array_my_sub_array_locales, { + relationName: '_locales', + }), + relation3: one(relation_b, { + // @ts-expect-error Drizzle TypeScript bug for ONE relationships with a field in different table + fields: [_pg_migrations_v_version_my_array_my_sub_array_locales.relation3], + references: [relation_b.id], + relationName: 'relation3', + }), + }), +) +export const relations__pg_migrations_v_version_my_array = relations( + _pg_migrations_v_version_my_array, + ({ one, many }) => ({ + _parentID: one(_pg_migrations_v, { + fields: [_pg_migrations_v_version_my_array._parentID], + references: [_pg_migrations_v.id], + relationName: 'version_myArray', + }), + relation2: one(relation_b, { + fields: [_pg_migrations_v_version_my_array.relation2], + references: [relation_b.id], + relationName: 'relation2', + }), + mySubArray: many(_pg_migrations_v_version_my_array_my_sub_array, { + relationName: 'mySubArray', + }), + }), +) +export const relations__pg_migrations_v_blocks_my_block_locales = relations( + _pg_migrations_v_blocks_my_block_locales, + ({ one }) => ({ + _parentID: one(_pg_migrations_v_blocks_my_block, { + fields: [_pg_migrations_v_blocks_my_block_locales._parentID], + references: [_pg_migrations_v_blocks_my_block.id], + relationName: '_locales', + }), + relation6: one(relation_b, { + fields: [_pg_migrations_v_blocks_my_block_locales.relation6], + references: [relation_b.id], + relationName: 'relation6', + }), + }), +) +export const relations__pg_migrations_v_blocks_my_block = relations( + _pg_migrations_v_blocks_my_block, + ({ one, many }) => ({ + _parentID: one(_pg_migrations_v, { + fields: [_pg_migrations_v_blocks_my_block._parentID], + references: [_pg_migrations_v.id], + relationName: '_blocks_myBlock', + }), + _locales: many(_pg_migrations_v_blocks_my_block_locales, { + relationName: '_locales', + }), + relation5: one(relation_a, { + fields: [_pg_migrations_v_blocks_my_block.relation5], + references: [relation_a.id], + relationName: 'relation5', + }), + relation6: one(relation_b, { + // @ts-expect-error Drizzle TypeScript bug for ONE relationships with a field in different table + fields: [_pg_migrations_v_blocks_my_block_locales.relation6], + references: [relation_b.id], + relationName: 'relation6', + }), + }), +) +export const relations__pg_migrations_v_locales = relations( + _pg_migrations_v_locales, + ({ one }) => ({ + _parentID: one(_pg_migrations_v, { + fields: [_pg_migrations_v_locales._parentID], + references: [_pg_migrations_v.id], + relationName: '_locales', + }), + version_myGroup_relation4: one(relation_b, { + fields: [_pg_migrations_v_locales.version_myGroup_relation4], + references: [relation_b.id], + relationName: 'version_myGroup_relation4', + }), + }), +) +export const relations__pg_migrations_v = relations(_pg_migrations_v, ({ one, many }) => ({ + parent: one(pg_migrations, { + fields: [_pg_migrations_v.parent], + references: [pg_migrations.id], + relationName: 'parent', + }), + version_relation1: one(relation_a, { + fields: [_pg_migrations_v.version_relation1], + references: [relation_a.id], + relationName: 'version_relation1', + }), + version_myArray: many(_pg_migrations_v_version_my_array, { + relationName: 'version_myArray', + }), + _blocks_myBlock: many(_pg_migrations_v_blocks_my_block, { + relationName: '_blocks_myBlock', + }), + _locales: many(_pg_migrations_v_locales, { + relationName: '_locales', + }), +})) +export const relations_customs_customSelect = relations(customs_customSelect, ({ one }) => ({ + parent: one(customs, { + fields: [customs_customSelect.parent], + references: [customs.id], + relationName: 'select', + }), +})) +export const relations_customArrays_locales = relations(customArrays_locales, ({ one }) => ({ + _parentID: one(customArrays, { + fields: [customArrays_locales._parentID], + references: [customArrays.id], + relationName: '_locales', + }), +})) +export const relations_customArrays = relations(customArrays, ({ one, many }) => ({ + _parentID: one(customs, { + fields: [customArrays._parentID], + references: [customs.id], + relationName: 'array', + }), + _locales: many(customArrays_locales, { + relationName: '_locales', + }), +})) +export const relations_customBlocks_locales = relations(customBlocks_locales, ({ one }) => ({ + _parentID: one(customBlocks, { + fields: [customBlocks_locales._parentID], + references: [customBlocks.id], + relationName: '_locales', + }), +})) +export const relations_customBlocks = relations(customBlocks, ({ one, many }) => ({ + _parentID: one(customs, { + fields: [customBlocks._parentID], + references: [customs.id], + relationName: '_blocks_block', + }), + _locales: many(customBlocks_locales, { + relationName: '_locales', + }), +})) +export const relations_customs_locales = relations(customs_locales, ({ one }) => ({ + _parentID: one(customs, { + fields: [customs_locales._parentID], + references: [customs.id], + relationName: '_locales', + }), +})) +export const relations_customs_rels = relations(customs_rels, ({ one }) => ({ + parent: one(customs, { + fields: [customs_rels.parent], + references: [customs.id], + relationName: '_rels', + }), + 'relation-aID': one(relation_a, { + fields: [customs_rels['relation-aID']], + references: [relation_a.id], + relationName: 'relation-a', + }), +})) +export const relations_customs = relations(customs, ({ many }) => ({ + select: many(customs_customSelect, { + relationName: 'select', + }), + array: many(customArrays, { + relationName: 'array', + }), + _blocks_block: many(customBlocks, { + relationName: '_blocks_block', + }), + _locales: many(customs_locales, { + relationName: '_locales', + }), + _rels: many(customs_rels, { + relationName: '_rels', + }), +})) +export const relations___customs_v_version_customSelect_v = relations( + __customs_v_version_customSelect_v, + ({ one }) => ({ + parent: one(_customs_v, { + fields: [__customs_v_version_customSelect_v.parent], + references: [_customs_v.id], + relationName: 'version_select', + }), + }), +) +export const relations__customArrays_v_locales = relations(_customArrays_v_locales, ({ one }) => ({ + _parentID: one(_customArrays_v, { + fields: [_customArrays_v_locales._parentID], + references: [_customArrays_v.id], + relationName: '_locales', + }), +})) +export const relations__customArrays_v = relations(_customArrays_v, ({ one, many }) => ({ + _parentID: one(_customs_v, { + fields: [_customArrays_v._parentID], + references: [_customs_v.id], + relationName: 'version_array', + }), + _locales: many(_customArrays_v_locales, { + relationName: '_locales', + }), +})) +export const relations__customBlocks_v_locales = relations(_customBlocks_v_locales, ({ one }) => ({ + _parentID: one(_customBlocks_v, { + fields: [_customBlocks_v_locales._parentID], + references: [_customBlocks_v.id], + relationName: '_locales', + }), +})) +export const relations__customBlocks_v = relations(_customBlocks_v, ({ one, many }) => ({ + _parentID: one(_customs_v, { + fields: [_customBlocks_v._parentID], + references: [_customs_v.id], + relationName: '_blocks_block', + }), + _locales: many(_customBlocks_v_locales, { + relationName: '_locales', + }), +})) +export const relations__customs_v_locales = relations(_customs_v_locales, ({ one }) => ({ + _parentID: one(_customs_v, { + fields: [_customs_v_locales._parentID], + references: [_customs_v.id], + relationName: '_locales', + }), +})) +export const relations__customs_v_rels = relations(_customs_v_rels, ({ one }) => ({ + parent: one(_customs_v, { + fields: [_customs_v_rels.parent], + references: [_customs_v.id], + relationName: '_rels', + }), + 'relation-aID': one(relation_a, { + fields: [_customs_v_rels['relation-aID']], + references: [relation_a.id], + relationName: 'relation-a', + }), +})) +export const relations__customs_v = relations(_customs_v, ({ one, many }) => ({ + parent: one(customs, { + fields: [_customs_v.parent], + references: [customs.id], + relationName: 'parent', + }), + version_select: many(__customs_v_version_customSelect_v, { + relationName: 'version_select', + }), + version_array: many(_customArrays_v, { + relationName: 'version_array', + }), + _blocks_block: many(_customBlocks_v, { + relationName: '_blocks_block', + }), + _locales: many(_customs_v_locales, { + relationName: '_locales', + }), + _rels: many(_customs_v_rels, { + relationName: '_rels', + }), +})) +export const relations_places = relations(places, () => ({})) +export const relations_fields_persistance = relations(fields_persistance, () => ({})) +export const relations_custom_ids = relations(custom_ids, () => ({})) +export const relations__custom_ids_v = relations(_custom_ids_v, ({ one }) => ({ + parent: one(custom_ids, { + fields: [_custom_ids_v.parent], + references: [custom_ids.id], + relationName: 'parent', + }), +})) +export const relations_fake_custom_ids = relations(fake_custom_ids, () => ({})) +export const relations_relationships_migration_rels = relations( + relationships_migration_rels, + ({ one }) => ({ + parent: one(relationships_migration, { + fields: [relationships_migration_rels.parent], + references: [relationships_migration.id], + relationName: '_rels', + }), + 'default-valuesID': one(default_values, { + fields: [relationships_migration_rels['default-valuesID']], + references: [default_values.id], + relationName: 'default-values', + }), + }), +) +export const relations_relationships_migration = relations( + relationships_migration, + ({ one, many }) => ({ + relationship: one(default_values, { + fields: [relationships_migration.relationship], + references: [default_values.id], + relationName: 'relationship', + }), + _rels: many(relationships_migration_rels, { + relationName: '_rels', + }), + }), +) +export const relations__relationships_migration_v_rels = relations( + _relationships_migration_v_rels, + ({ one }) => ({ + parent: one(_relationships_migration_v, { + fields: [_relationships_migration_v_rels.parent], + references: [_relationships_migration_v.id], + relationName: '_rels', + }), + 'default-valuesID': one(default_values, { + fields: [_relationships_migration_v_rels['default-valuesID']], + references: [default_values.id], + relationName: 'default-values', + }), + }), +) +export const relations__relationships_migration_v = relations( + _relationships_migration_v, + ({ one, many }) => ({ + parent: one(relationships_migration, { + fields: [_relationships_migration_v.parent], + references: [relationships_migration.id], + relationName: 'parent', + }), + version_relationship: one(default_values, { + fields: [_relationships_migration_v.version_relationship], + references: [default_values.id], + relationName: 'version_relationship', + }), + _rels: many(_relationships_migration_v_rels, { + relationName: '_rels', + }), + }), +) +export const relations_users = relations(users, () => ({})) +export const relations_payload_locked_documents_rels = relations( + payload_locked_documents_rels, + ({ one }) => ({ + parent: one(payload_locked_documents, { + fields: [payload_locked_documents_rels.parent], + references: [payload_locked_documents.id], + relationName: '_rels', + }), + postsID: one(posts, { + fields: [payload_locked_documents_rels.postsID], + references: [posts.id], + relationName: 'posts', + }), + 'default-valuesID': one(default_values, { + fields: [payload_locked_documents_rels['default-valuesID']], + references: [default_values.id], + relationName: 'default-values', + }), + 'relation-aID': one(relation_a, { + fields: [payload_locked_documents_rels['relation-aID']], + references: [relation_a.id], + relationName: 'relation-a', + }), + 'relation-bID': one(relation_b, { + fields: [payload_locked_documents_rels['relation-bID']], + references: [relation_b.id], + relationName: 'relation-b', + }), + 'pg-migrationsID': one(pg_migrations, { + fields: [payload_locked_documents_rels['pg-migrationsID']], + references: [pg_migrations.id], + relationName: 'pg-migrations', + }), + 'custom-schemaID': one(customs, { + fields: [payload_locked_documents_rels['custom-schemaID']], + references: [customs.id], + relationName: 'custom-schema', + }), + placesID: one(places, { + fields: [payload_locked_documents_rels.placesID], + references: [places.id], + relationName: 'places', + }), + 'fields-persistanceID': one(fields_persistance, { + fields: [payload_locked_documents_rels['fields-persistanceID']], + references: [fields_persistance.id], + relationName: 'fields-persistance', + }), + 'custom-idsID': one(custom_ids, { + fields: [payload_locked_documents_rels['custom-idsID']], + references: [custom_ids.id], + relationName: 'custom-ids', + }), + 'fake-custom-idsID': one(fake_custom_ids, { + fields: [payload_locked_documents_rels['fake-custom-idsID']], + references: [fake_custom_ids.id], + relationName: 'fake-custom-ids', + }), + 'relationships-migrationID': one(relationships_migration, { + fields: [payload_locked_documents_rels['relationships-migrationID']], + references: [relationships_migration.id], + relationName: 'relationships-migration', + }), + usersID: one(users, { + fields: [payload_locked_documents_rels.usersID], + references: [users.id], + relationName: 'users', + }), + }), +) +export const relations_payload_locked_documents = relations( + payload_locked_documents, + ({ many }) => ({ + _rels: many(payload_locked_documents_rels, { + relationName: '_rels', + }), + }), +) +export const relations_payload_preferences_rels = relations( + payload_preferences_rels, + ({ one }) => ({ + parent: one(payload_preferences, { + fields: [payload_preferences_rels.parent], + references: [payload_preferences.id], + relationName: '_rels', + }), + usersID: one(users, { + fields: [payload_preferences_rels.usersID], + references: [users.id], + relationName: 'users', + }), + }), +) +export const relations_payload_preferences = relations(payload_preferences, ({ many }) => ({ + _rels: many(payload_preferences_rels, { + relationName: '_rels', + }), +})) +export const relations_payload_migrations = relations(payload_migrations, () => ({})) +export const relations_customGlobal = relations(customGlobal, () => ({})) +export const relations__customGlobal_v = relations(_customGlobal_v, () => ({})) + +type DatabaseSchema = { + posts: typeof posts + default_values_array: typeof default_values_array + default_values: typeof default_values + relation_a: typeof relation_a + relation_b: typeof relation_b + pg_migrations_my_array_my_sub_array: typeof pg_migrations_my_array_my_sub_array + pg_migrations_my_array_my_sub_array_locales: typeof pg_migrations_my_array_my_sub_array_locales + pg_migrations_my_array: typeof pg_migrations_my_array + pg_migrations_blocks_my_block: typeof pg_migrations_blocks_my_block + pg_migrations_blocks_my_block_locales: typeof pg_migrations_blocks_my_block_locales + pg_migrations: typeof pg_migrations + pg_migrations_locales: typeof pg_migrations_locales + _pg_migrations_v_version_my_array_my_sub_array: typeof _pg_migrations_v_version_my_array_my_sub_array + _pg_migrations_v_version_my_array_my_sub_array_locales: typeof _pg_migrations_v_version_my_array_my_sub_array_locales + _pg_migrations_v_version_my_array: typeof _pg_migrations_v_version_my_array + _pg_migrations_v_blocks_my_block: typeof _pg_migrations_v_blocks_my_block + _pg_migrations_v_blocks_my_block_locales: typeof _pg_migrations_v_blocks_my_block_locales + _pg_migrations_v: typeof _pg_migrations_v + _pg_migrations_v_locales: typeof _pg_migrations_v_locales + customs_customSelect: typeof customs_customSelect + customArrays: typeof customArrays + customArrays_locales: typeof customArrays_locales + customBlocks: typeof customBlocks + customBlocks_locales: typeof customBlocks_locales + customs: typeof customs + customs_locales: typeof customs_locales + customs_rels: typeof customs_rels + __customs_v_version_customSelect_v: typeof __customs_v_version_customSelect_v + _customArrays_v: typeof _customArrays_v + _customArrays_v_locales: typeof _customArrays_v_locales + _customBlocks_v: typeof _customBlocks_v + _customBlocks_v_locales: typeof _customBlocks_v_locales + _customs_v: typeof _customs_v + _customs_v_locales: typeof _customs_v_locales + _customs_v_rels: typeof _customs_v_rels + places: typeof places + fields_persistance: typeof fields_persistance + custom_ids: typeof custom_ids + _custom_ids_v: typeof _custom_ids_v + fake_custom_ids: typeof fake_custom_ids + relationships_migration: typeof relationships_migration + relationships_migration_rels: typeof relationships_migration_rels + _relationships_migration_v: typeof _relationships_migration_v + _relationships_migration_v_rels: typeof _relationships_migration_v_rels + users: typeof users + payload_locked_documents: typeof payload_locked_documents + payload_locked_documents_rels: typeof payload_locked_documents_rels + payload_preferences: typeof payload_preferences + payload_preferences_rels: typeof payload_preferences_rels + payload_migrations: typeof payload_migrations + customGlobal: typeof customGlobal + _customGlobal_v: typeof _customGlobal_v + relations_posts: typeof relations_posts + relations_default_values_array: typeof relations_default_values_array + relations_default_values: typeof relations_default_values + relations_relation_a: typeof relations_relation_a + relations_relation_b: typeof relations_relation_b + relations_pg_migrations_my_array_my_sub_array_locales: typeof relations_pg_migrations_my_array_my_sub_array_locales + relations_pg_migrations_my_array_my_sub_array: typeof relations_pg_migrations_my_array_my_sub_array + relations_pg_migrations_my_array: typeof relations_pg_migrations_my_array + relations_pg_migrations_blocks_my_block_locales: typeof relations_pg_migrations_blocks_my_block_locales + relations_pg_migrations_blocks_my_block: typeof relations_pg_migrations_blocks_my_block + relations_pg_migrations_locales: typeof relations_pg_migrations_locales + relations_pg_migrations: typeof relations_pg_migrations + relations__pg_migrations_v_version_my_array_my_sub_array_locales: typeof relations__pg_migrations_v_version_my_array_my_sub_array_locales + relations__pg_migrations_v_version_my_array_my_sub_array: typeof relations__pg_migrations_v_version_my_array_my_sub_array + relations__pg_migrations_v_version_my_array: typeof relations__pg_migrations_v_version_my_array + relations__pg_migrations_v_blocks_my_block_locales: typeof relations__pg_migrations_v_blocks_my_block_locales + relations__pg_migrations_v_blocks_my_block: typeof relations__pg_migrations_v_blocks_my_block + relations__pg_migrations_v_locales: typeof relations__pg_migrations_v_locales + relations__pg_migrations_v: typeof relations__pg_migrations_v + relations_customs_customSelect: typeof relations_customs_customSelect + relations_customArrays_locales: typeof relations_customArrays_locales + relations_customArrays: typeof relations_customArrays + relations_customBlocks_locales: typeof relations_customBlocks_locales + relations_customBlocks: typeof relations_customBlocks + relations_customs_locales: typeof relations_customs_locales + relations_customs_rels: typeof relations_customs_rels + relations_customs: typeof relations_customs + relations___customs_v_version_customSelect_v: typeof relations___customs_v_version_customSelect_v + relations__customArrays_v_locales: typeof relations__customArrays_v_locales + relations__customArrays_v: typeof relations__customArrays_v + relations__customBlocks_v_locales: typeof relations__customBlocks_v_locales + relations__customBlocks_v: typeof relations__customBlocks_v + relations__customs_v_locales: typeof relations__customs_v_locales + relations__customs_v_rels: typeof relations__customs_v_rels + relations__customs_v: typeof relations__customs_v + relations_places: typeof relations_places + relations_fields_persistance: typeof relations_fields_persistance + relations_custom_ids: typeof relations_custom_ids + relations__custom_ids_v: typeof relations__custom_ids_v + relations_fake_custom_ids: typeof relations_fake_custom_ids + relations_relationships_migration_rels: typeof relations_relationships_migration_rels + relations_relationships_migration: typeof relations_relationships_migration + relations__relationships_migration_v_rels: typeof relations__relationships_migration_v_rels + relations__relationships_migration_v: typeof relations__relationships_migration_v + relations_users: typeof relations_users + relations_payload_locked_documents_rels: typeof relations_payload_locked_documents_rels + relations_payload_locked_documents: typeof relations_payload_locked_documents + relations_payload_preferences_rels: typeof relations_payload_preferences_rels + relations_payload_preferences: typeof relations_payload_preferences + relations_payload_migrations: typeof relations_payload_migrations + relations_customGlobal: typeof relations_customGlobal + relations__customGlobal_v: typeof relations__customGlobal_v +} + +declare module '@payloadcms/db-sqlite/types' { + export interface GeneratedDatabaseSchema { + schema: DatabaseSchema + } +} diff --git a/test/generateDatabaseSchema.ts b/test/generateDatabaseSchema.ts new file mode 100644 index 0000000000..a7a84621d7 --- /dev/null +++ b/test/generateDatabaseSchema.ts @@ -0,0 +1,48 @@ +import path from 'path' +import { getPayload, type SanitizedConfig } from 'payload' +import { fileURLToPath } from 'url' + +import { generateDatabaseAdapter } from './generateDatabaseAdapter.js' +import { setTestEnvPaths } from './helpers/setTestEnvPaths.js' + +const [testConfigDir] = process.argv.slice(2) + +const filename = fileURLToPath(import.meta.url) +const dirname = path.dirname(filename) + +const writeDBAdapter = process.env.WRITE_DB_ADAPTER !== 'false' +process.env.PAYLOAD_DROP_DATABASE = process.env.PAYLOAD_DROP_DATABASE || 'true' + +if (process.env.PAYLOAD_DATABASE === 'mongodb') { + throw new Error('Not supported') +} + +if (writeDBAdapter) { + generateDatabaseAdapter(process.env.PAYLOAD_DATABASE || 'postgres') + process.env.WRITE_DB_ADAPTER = 'false' +} + +const loadConfig = async (configPath: string): Promise => { + return await ( + await import(configPath) + ).default +} + +if (!testConfigDir) { + throw new Error('Yo must Specify testConfigDir') +} + +const testDir = path.resolve(dirname, testConfigDir) +const config = await loadConfig(path.resolve(testDir, 'config.ts')) + +setTestEnvPaths(testDir) + +const payload = await getPayload({ config }) + +// await payload.db.dropDatabase({ adapter: payload.db }) + +await payload.db.generateSchema({ + outputFile: path.resolve(testDir, 'payload-generated-schema.ts'), +}) + +process.exit(0) diff --git a/test/helpers/database.ts b/test/helpers/database.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/jest.setup.js b/test/jest.setup.js index f20b17c90c..83d33b6994 100644 --- a/test/jest.setup.js +++ b/test/jest.setup.js @@ -25,6 +25,9 @@ jest.spyOn(nodemailer, 'createTestAccount').mockImplementation(() => { }) }) -const dbAdapter = process.env.PAYLOAD_DATABASE || 'mongodb' +if (!process.env.PAYLOAD_DATABASE) { + // Mutate env so we can use conditions by DB adapter in tests properly without ignoring // eslint no-jest-conditions. + process.env.PAYLOAD_DATABASE = 'sqlite-uuid' +} -generateDatabaseAdapter(dbAdapter) +generateDatabaseAdapter(process.env.PAYLOAD_DATABASE) diff --git a/test/relationships/payload-generated-schema.ts b/test/relationships/payload-generated-schema.ts new file mode 100644 index 0000000000..cf92ea33df --- /dev/null +++ b/test/relationships/payload-generated-schema.ts @@ -0,0 +1,1402 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * This file was automatically generated by Payload. + * DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config, + * and re-run `payload generate:db-schema` to regenerate this file. + */ + +import { + pgTable, + index, + uniqueIndex, + foreignKey, + integer, + text, + varchar, + serial, + numeric, + timestamp, + boolean, + type AnyPgColumn, + jsonb, + pgEnum, +} from '@payloadcms/db-postgres/drizzle/pg-core' +import { sql, relations } from '@payloadcms/db-postgres/drizzle' +export const enum__locales = pgEnum('enum__locales', ['en', 'de']) +export const enum_movie_reviews_visibility = pgEnum('enum_movie_reviews_visibility', [ + 'followers', + 'public', +]) + +export const posts_blocks_block = pgTable( + 'posts_blocks_block', + { + _order: integer('_order').notNull(), + _parentID: integer('_parent_id').notNull(), + _path: text('_path').notNull(), + id: varchar('id').primaryKey(), + relationField: integer('relation_field_id').references(() => relation.id, { + onDelete: 'set null', + }), + blockName: varchar('block_name'), + }, + (columns) => ({ + _orderIdx: index('posts_blocks_block_order_idx').on(columns._order), + _parentIDIdx: index('posts_blocks_block_parent_id_idx').on(columns._parentID), + _pathIdx: index('posts_blocks_block_path_idx').on(columns._path), + posts_blocks_block_relation_field_idx: index('posts_blocks_block_relation_field_idx').on( + columns.relationField, + ), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [posts.id], + name: 'posts_blocks_block_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const posts = pgTable( + 'posts', + { + id: serial('id').primaryKey(), + title: varchar('title'), + description: varchar('description'), + number: numeric('number'), + relationField: integer('relation_field_id').references(() => relation.id, { + onDelete: 'set null', + }), + defaultAccessRelation: integer('default_access_relation_id').references( + () => strict_access.id, + { + onDelete: 'set null', + }, + ), + chainedRelation: integer('chained_relation_id').references(() => chained.id, { + onDelete: 'set null', + }), + maxDepthRelation: integer('max_depth_relation_id').references(() => relation.id, { + onDelete: 'set null', + }), + customIdRelation: varchar('custom_id_relation_id').references(() => custom_id.id, { + onDelete: 'set null', + }), + customIdNumberRelation: numeric('custom_id_number_relation_id').references( + () => custom_id_number.id, + { + onDelete: 'set null', + }, + ), + filteredRelation: integer('filtered_relation_id').references(() => relation.id, { + onDelete: 'set null', + }), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + posts_relation_field_idx: index('posts_relation_field_idx').on(columns.relationField), + posts_default_access_relation_idx: index('posts_default_access_relation_idx').on( + columns.defaultAccessRelation, + ), + posts_chained_relation_idx: index('posts_chained_relation_idx').on(columns.chainedRelation), + posts_max_depth_relation_idx: index('posts_max_depth_relation_idx').on( + columns.maxDepthRelation, + ), + posts_custom_id_relation_idx: index('posts_custom_id_relation_idx').on( + columns.customIdRelation, + ), + posts_custom_id_number_relation_idx: index('posts_custom_id_number_relation_idx').on( + columns.customIdNumberRelation, + ), + posts_filtered_relation_idx: index('posts_filtered_relation_idx').on(columns.filteredRelation), + posts_updated_at_idx: index('posts_updated_at_idx').on(columns.updatedAt), + posts_created_at_idx: index('posts_created_at_idx').on(columns.createdAt), + }), +) + +export const posts_localized = pgTable( + 'posts_localized', + { + id: serial('id').primaryKey(), + title: varchar('title'), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + posts_localized_updated_at_idx: index('posts_localized_updated_at_idx').on(columns.updatedAt), + posts_localized_created_at_idx: index('posts_localized_created_at_idx').on(columns.createdAt), + }), +) + +export const posts_localized_locales = pgTable( + 'posts_localized_locales', + { + relationField: integer('relation_field_id').references(() => relation.id, { + onDelete: 'set null', + }), + id: serial('id').primaryKey(), + _locale: enum__locales('_locale').notNull(), + _parentID: integer('_parent_id').notNull(), + }, + (columns) => ({ + posts_localized_relation_field_idx: index('posts_localized_relation_field_idx').on( + columns.relationField, + columns._locale, + ), + _localeParent: uniqueIndex('posts_localized_locales_locale_parent_id_unique').on( + columns._locale, + columns._parentID, + ), + _parentIdFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [posts_localized.id], + name: 'posts_localized_locales_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const relation = pgTable( + 'relation', + { + id: serial('id').primaryKey(), + name: varchar('name'), + disableRelation: boolean('disable_relation').notNull().default(false), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + relation_updated_at_idx: index('relation_updated_at_idx').on(columns.updatedAt), + relation_created_at_idx: index('relation_created_at_idx').on(columns.createdAt), + }), +) + +export const strict_access = pgTable( + 'strict_access', + { + id: serial('id').primaryKey(), + name: varchar('name'), + disableRelation: boolean('disable_relation').notNull().default(false), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + strict_access_updated_at_idx: index('strict_access_updated_at_idx').on(columns.updatedAt), + strict_access_created_at_idx: index('strict_access_created_at_idx').on(columns.createdAt), + }), +) + +export const chained = pgTable( + 'chained', + { + id: serial('id').primaryKey(), + name: varchar('name'), + relation: integer('relation_id').references((): AnyPgColumn => chained.id, { + onDelete: 'set null', + }), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + chained_relation_idx: index('chained_relation_idx').on(columns.relation), + chained_updated_at_idx: index('chained_updated_at_idx').on(columns.updatedAt), + chained_created_at_idx: index('chained_created_at_idx').on(columns.createdAt), + }), +) + +export const custom_id = pgTable( + 'custom_id', + { + id: varchar('id').primaryKey(), + name: varchar('name'), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + custom_id_updated_at_idx: index('custom_id_updated_at_idx').on(columns.updatedAt), + custom_id_created_at_idx: index('custom_id_created_at_idx').on(columns.createdAt), + }), +) + +export const custom_id_number = pgTable( + 'custom_id_number', + { + id: numeric('id').primaryKey(), + name: varchar('name'), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + custom_id_number_updated_at_idx: index('custom_id_number_updated_at_idx').on(columns.updatedAt), + custom_id_number_created_at_idx: index('custom_id_number_created_at_idx').on(columns.createdAt), + }), +) + +export const screenings = pgTable( + 'screenings', + { + id: serial('id').primaryKey(), + name: varchar('name'), + movie: integer('movie_id').references(() => movies.id, { + onDelete: 'set null', + }), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + screenings_movie_idx: index('screenings_movie_idx').on(columns.movie), + screenings_updated_at_idx: index('screenings_updated_at_idx').on(columns.updatedAt), + screenings_created_at_idx: index('screenings_created_at_idx').on(columns.createdAt), + }), +) + +export const movies = pgTable( + 'movies', + { + id: serial('id').primaryKey(), + name: varchar('name'), + director: integer('director_id').references(() => directors.id, { + onDelete: 'set null', + }), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + movies_director_idx: index('movies_director_idx').on(columns.director), + movies_updated_at_idx: index('movies_updated_at_idx').on(columns.updatedAt), + movies_created_at_idx: index('movies_created_at_idx').on(columns.createdAt), + }), +) + +export const directors = pgTable( + 'directors', + { + id: serial('id').primaryKey(), + name: varchar('name'), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + directors_updated_at_idx: index('directors_updated_at_idx').on(columns.updatedAt), + directors_created_at_idx: index('directors_created_at_idx').on(columns.createdAt), + }), +) + +export const directors_rels = pgTable( + 'directors_rels', + { + id: serial('id').primaryKey(), + order: integer('order'), + parent: integer('parent_id').notNull(), + path: varchar('path').notNull(), + moviesID: integer('movies_id'), + }, + (columns) => ({ + order: index('directors_rels_order_idx').on(columns.order), + parentIdx: index('directors_rels_parent_idx').on(columns.parent), + pathIdx: index('directors_rels_path_idx').on(columns.path), + directors_rels_movies_id_idx: index('directors_rels_movies_id_idx').on(columns.moviesID), + parentFk: foreignKey({ + columns: [columns['parent']], + foreignColumns: [directors.id], + name: 'directors_rels_parent_fk', + }).onDelete('cascade'), + moviesIdFk: foreignKey({ + columns: [columns['moviesID']], + foreignColumns: [movies.id], + name: 'directors_rels_movies_fk', + }).onDelete('cascade'), + }), +) + +export const movie_reviews = pgTable( + 'movie_reviews', + { + id: serial('id').primaryKey(), + movieReviewer: integer('movie_reviewer_id') + .notNull() + .references(() => users.id, { + onDelete: 'set null', + }), + visibility: enum_movie_reviews_visibility('visibility').notNull(), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + movie_reviews_movie_reviewer_idx: index('movie_reviews_movie_reviewer_idx').on( + columns.movieReviewer, + ), + movie_reviews_updated_at_idx: index('movie_reviews_updated_at_idx').on(columns.updatedAt), + movie_reviews_created_at_idx: index('movie_reviews_created_at_idx').on(columns.createdAt), + }), +) + +export const movie_reviews_rels = pgTable( + 'movie_reviews_rels', + { + id: serial('id').primaryKey(), + order: integer('order'), + parent: integer('parent_id').notNull(), + path: varchar('path').notNull(), + usersID: integer('users_id'), + }, + (columns) => ({ + order: index('movie_reviews_rels_order_idx').on(columns.order), + parentIdx: index('movie_reviews_rels_parent_idx').on(columns.parent), + pathIdx: index('movie_reviews_rels_path_idx').on(columns.path), + movie_reviews_rels_users_id_idx: index('movie_reviews_rels_users_id_idx').on(columns.usersID), + parentFk: foreignKey({ + columns: [columns['parent']], + foreignColumns: [movie_reviews.id], + name: 'movie_reviews_rels_parent_fk', + }).onDelete('cascade'), + usersIdFk: foreignKey({ + columns: [columns['usersID']], + foreignColumns: [users.id], + name: 'movie_reviews_rels_users_fk', + }).onDelete('cascade'), + }), +) + +export const polymorphic_relationships = pgTable( + 'polymorphic_relationships', + { + id: serial('id').primaryKey(), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + polymorphic_relationships_updated_at_idx: index('polymorphic_relationships_updated_at_idx').on( + columns.updatedAt, + ), + polymorphic_relationships_created_at_idx: index('polymorphic_relationships_created_at_idx').on( + columns.createdAt, + ), + }), +) + +export const polymorphic_relationships_rels = pgTable( + 'polymorphic_relationships_rels', + { + id: serial('id').primaryKey(), + order: integer('order'), + parent: integer('parent_id').notNull(), + path: varchar('path').notNull(), + moviesID: integer('movies_id'), + }, + (columns) => ({ + order: index('polymorphic_relationships_rels_order_idx').on(columns.order), + parentIdx: index('polymorphic_relationships_rels_parent_idx').on(columns.parent), + pathIdx: index('polymorphic_relationships_rels_path_idx').on(columns.path), + polymorphic_relationships_rels_movies_id_idx: index( + 'polymorphic_relationships_rels_movies_id_idx', + ).on(columns.moviesID), + parentFk: foreignKey({ + columns: [columns['parent']], + foreignColumns: [polymorphic_relationships.id], + name: 'polymorphic_relationships_rels_parent_fk', + }).onDelete('cascade'), + moviesIdFk: foreignKey({ + columns: [columns['moviesID']], + foreignColumns: [movies.id], + name: 'polymorphic_relationships_rels_movies_fk', + }).onDelete('cascade'), + }), +) + +export const tree = pgTable( + 'tree', + { + id: serial('id').primaryKey(), + text: varchar('text'), + parent: integer('parent_id').references((): AnyPgColumn => tree.id, { + onDelete: 'set null', + }), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + tree_parent_idx: index('tree_parent_idx').on(columns.parent), + tree_updated_at_idx: index('tree_updated_at_idx').on(columns.updatedAt), + tree_created_at_idx: index('tree_created_at_idx').on(columns.createdAt), + }), +) + +export const pages_menu = pgTable( + 'pages_menu', + { + _order: integer('_order').notNull(), + _parentID: integer('_parent_id').notNull(), + id: varchar('id').primaryKey(), + label: varchar('label'), + }, + (columns) => ({ + _orderIdx: index('pages_menu_order_idx').on(columns._order), + _parentIDIdx: index('pages_menu_parent_id_idx').on(columns._parentID), + _parentIDFk: foreignKey({ + columns: [columns['_parentID']], + foreignColumns: [pages.id], + name: 'pages_menu_parent_id_fk', + }).onDelete('cascade'), + }), +) + +export const pages = pgTable( + 'pages', + { + id: serial('id').primaryKey(), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + pages_updated_at_idx: index('pages_updated_at_idx').on(columns.updatedAt), + pages_created_at_idx: index('pages_created_at_idx').on(columns.createdAt), + }), +) + +export const rels_to_pages = pgTable( + 'rels_to_pages', + { + id: serial('id').primaryKey(), + page: integer('page_id').references(() => pages.id, { + onDelete: 'set null', + }), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + rels_to_pages_page_idx: index('rels_to_pages_page_idx').on(columns.page), + rels_to_pages_updated_at_idx: index('rels_to_pages_updated_at_idx').on(columns.updatedAt), + rels_to_pages_created_at_idx: index('rels_to_pages_created_at_idx').on(columns.createdAt), + }), +) + +export const rels_to_pages_and_custom_text_ids = pgTable( + 'rels_to_pages_and_custom_text_ids', + { + id: serial('id').primaryKey(), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + rels_to_pages_and_custom_text_ids_updated_at_idx: index( + 'rels_to_pages_and_custom_text_ids_updated_at_idx', + ).on(columns.updatedAt), + rels_to_pages_and_custom_text_ids_created_at_idx: index( + 'rels_to_pages_and_custom_text_ids_created_at_idx', + ).on(columns.createdAt), + }), +) + +export const rels_to_pages_and_custom_text_ids_rels = pgTable( + 'rels_to_pages_and_custom_text_ids_rels', + { + id: serial('id').primaryKey(), + order: integer('order'), + parent: integer('parent_id').notNull(), + path: varchar('path').notNull(), + pagesID: integer('pages_id'), + 'custom-idID': varchar('custom_id_id'), + 'custom-id-numberID': numeric('custom_id_number_id'), + }, + (columns) => ({ + order: index('rels_to_pages_and_custom_text_ids_rels_order_idx').on(columns.order), + parentIdx: index('rels_to_pages_and_custom_text_ids_rels_parent_idx').on(columns.parent), + pathIdx: index('rels_to_pages_and_custom_text_ids_rels_path_idx').on(columns.path), + rels_to_pages_and_custom_text_ids_rels_pages_id_idx: index( + 'rels_to_pages_and_custom_text_ids_rels_pages_id_idx', + ).on(columns.pagesID), + rels_to_pages_and_custom_text_ids_rels_custom_id_id_idx: index( + 'rels_to_pages_and_custom_text_ids_rels_custom_id_id_idx', + ).on(columns['custom-idID']), + rels_to_pages_and_custom_text_ids_rels_custom_id_number_id_idx: index( + 'rels_to_pages_and_custom_text_ids_rels_custom_id_number_id_idx', + ).on(columns['custom-id-numberID']), + parentFk: foreignKey({ + columns: [columns['parent']], + foreignColumns: [rels_to_pages_and_custom_text_ids.id], + name: 'rels_to_pages_and_custom_text_ids_rels_parent_fk', + }).onDelete('cascade'), + pagesIdFk: foreignKey({ + columns: [columns['pagesID']], + foreignColumns: [pages.id], + name: 'rels_to_pages_and_custom_text_ids_rels_pages_fk', + }).onDelete('cascade'), + 'custom-idIdFk': foreignKey({ + columns: [columns['custom-idID']], + foreignColumns: [custom_id.id], + name: 'rels_to_pages_and_custom_text_ids_rels_custom_id_fk', + }).onDelete('cascade'), + 'custom-id-numberIdFk': foreignKey({ + columns: [columns['custom-id-numberID']], + foreignColumns: [custom_id_number.id], + name: 'rels_to_pages_and_custom_text_ids_rels_custom_id_number_fk', + }).onDelete('cascade'), + }), +) + +export const object_writes = pgTable( + 'object_writes', + { + id: serial('id').primaryKey(), + one: integer('one_id').references(() => movies.id, { + onDelete: 'set null', + }), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + object_writes_one_idx: index('object_writes_one_idx').on(columns.one), + object_writes_updated_at_idx: index('object_writes_updated_at_idx').on(columns.updatedAt), + object_writes_created_at_idx: index('object_writes_created_at_idx').on(columns.createdAt), + }), +) + +export const object_writes_rels = pgTable( + 'object_writes_rels', + { + id: serial('id').primaryKey(), + order: integer('order'), + parent: integer('parent_id').notNull(), + path: varchar('path').notNull(), + moviesID: integer('movies_id'), + }, + (columns) => ({ + order: index('object_writes_rels_order_idx').on(columns.order), + parentIdx: index('object_writes_rels_parent_idx').on(columns.parent), + pathIdx: index('object_writes_rels_path_idx').on(columns.path), + object_writes_rels_movies_id_idx: index('object_writes_rels_movies_id_idx').on( + columns.moviesID, + ), + parentFk: foreignKey({ + columns: [columns['parent']], + foreignColumns: [object_writes.id], + name: 'object_writes_rels_parent_fk', + }).onDelete('cascade'), + moviesIdFk: foreignKey({ + columns: [columns['moviesID']], + foreignColumns: [movies.id], + name: 'object_writes_rels_movies_fk', + }).onDelete('cascade'), + }), +) + +export const users = pgTable( + 'users', + { + id: serial('id').primaryKey(), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + email: varchar('email').notNull(), + resetPasswordToken: varchar('reset_password_token'), + resetPasswordExpiration: timestamp('reset_password_expiration', { + mode: 'string', + withTimezone: true, + precision: 3, + }), + salt: varchar('salt'), + hash: varchar('hash'), + loginAttempts: numeric('login_attempts').default('0'), + lockUntil: timestamp('lock_until', { mode: 'string', withTimezone: true, precision: 3 }), + }, + (columns) => ({ + users_updated_at_idx: index('users_updated_at_idx').on(columns.updatedAt), + users_created_at_idx: index('users_created_at_idx').on(columns.createdAt), + users_email_idx: uniqueIndex('users_email_idx').on(columns.email), + }), +) + +export const payload_locked_documents = pgTable( + 'payload_locked_documents', + { + id: serial('id').primaryKey(), + globalSlug: varchar('global_slug'), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + payload_locked_documents_global_slug_idx: index('payload_locked_documents_global_slug_idx').on( + columns.globalSlug, + ), + payload_locked_documents_updated_at_idx: index('payload_locked_documents_updated_at_idx').on( + columns.updatedAt, + ), + payload_locked_documents_created_at_idx: index('payload_locked_documents_created_at_idx').on( + columns.createdAt, + ), + }), +) + +export const payload_locked_documents_rels = pgTable( + 'payload_locked_documents_rels', + { + id: serial('id').primaryKey(), + order: integer('order'), + parent: integer('parent_id').notNull(), + path: varchar('path').notNull(), + postsID: integer('posts_id'), + postsLocalizedID: integer('posts_localized_id'), + relationID: integer('relation_id'), + 'strict-accessID': integer('strict_access_id'), + chainedID: integer('chained_id'), + 'custom-idID': varchar('custom_id_id'), + 'custom-id-numberID': numeric('custom_id_number_id'), + screeningsID: integer('screenings_id'), + moviesID: integer('movies_id'), + directorsID: integer('directors_id'), + movieReviewsID: integer('movie_reviews_id'), + 'polymorphic-relationshipsID': integer('polymorphic_relationships_id'), + treeID: integer('tree_id'), + pagesID: integer('pages_id'), + 'rels-to-pagesID': integer('rels_to_pages_id'), + 'rels-to-pages-and-custom-text-idsID': integer('rels_to_pages_and_custom_text_ids_id'), + 'object-writesID': integer('object_writes_id'), + usersID: integer('users_id'), + }, + (columns) => ({ + order: index('payload_locked_documents_rels_order_idx').on(columns.order), + parentIdx: index('payload_locked_documents_rels_parent_idx').on(columns.parent), + pathIdx: index('payload_locked_documents_rels_path_idx').on(columns.path), + payload_locked_documents_rels_posts_id_idx: index( + 'payload_locked_documents_rels_posts_id_idx', + ).on(columns.postsID), + payload_locked_documents_rels_posts_localized_id_idx: index( + 'payload_locked_documents_rels_posts_localized_id_idx', + ).on(columns.postsLocalizedID), + payload_locked_documents_rels_relation_id_idx: index( + 'payload_locked_documents_rels_relation_id_idx', + ).on(columns.relationID), + payload_locked_documents_rels_strict_access_id_idx: index( + 'payload_locked_documents_rels_strict_access_id_idx', + ).on(columns['strict-accessID']), + payload_locked_documents_rels_chained_id_idx: index( + 'payload_locked_documents_rels_chained_id_idx', + ).on(columns.chainedID), + payload_locked_documents_rels_custom_id_id_idx: index( + 'payload_locked_documents_rels_custom_id_id_idx', + ).on(columns['custom-idID']), + payload_locked_documents_rels_custom_id_number_id_idx: index( + 'payload_locked_documents_rels_custom_id_number_id_idx', + ).on(columns['custom-id-numberID']), + payload_locked_documents_rels_screenings_id_idx: index( + 'payload_locked_documents_rels_screenings_id_idx', + ).on(columns.screeningsID), + payload_locked_documents_rels_movies_id_idx: index( + 'payload_locked_documents_rels_movies_id_idx', + ).on(columns.moviesID), + payload_locked_documents_rels_directors_id_idx: index( + 'payload_locked_documents_rels_directors_id_idx', + ).on(columns.directorsID), + payload_locked_documents_rels_movie_reviews_id_idx: index( + 'payload_locked_documents_rels_movie_reviews_id_idx', + ).on(columns.movieReviewsID), + payload_locked_documents_rels_polymorphic_relationships_id_idx: index( + 'payload_locked_documents_rels_polymorphic_relationships_id_idx', + ).on(columns['polymorphic-relationshipsID']), + payload_locked_documents_rels_tree_id_idx: index( + 'payload_locked_documents_rels_tree_id_idx', + ).on(columns.treeID), + payload_locked_documents_rels_pages_id_idx: index( + 'payload_locked_documents_rels_pages_id_idx', + ).on(columns.pagesID), + payload_locked_documents_rels_rels_to_pages_id_idx: index( + 'payload_locked_documents_rels_rels_to_pages_id_idx', + ).on(columns['rels-to-pagesID']), + payload_locked_documents_rels_rels_to_pages_and_custom_text_ids_id_idx: index( + 'payload_locked_documents_rels_rels_to_pages_and_custom_text_ids_id_idx', + ).on(columns['rels-to-pages-and-custom-text-idsID']), + payload_locked_documents_rels_object_writes_id_idx: index( + 'payload_locked_documents_rels_object_writes_id_idx', + ).on(columns['object-writesID']), + payload_locked_documents_rels_users_id_idx: index( + 'payload_locked_documents_rels_users_id_idx', + ).on(columns.usersID), + parentFk: foreignKey({ + columns: [columns['parent']], + foreignColumns: [payload_locked_documents.id], + name: 'payload_locked_documents_rels_parent_fk', + }).onDelete('cascade'), + postsIdFk: foreignKey({ + columns: [columns['postsID']], + foreignColumns: [posts.id], + name: 'payload_locked_documents_rels_posts_fk', + }).onDelete('cascade'), + postsLocalizedIdFk: foreignKey({ + columns: [columns['postsLocalizedID']], + foreignColumns: [posts_localized.id], + name: 'payload_locked_documents_rels_posts_localized_fk', + }).onDelete('cascade'), + relationIdFk: foreignKey({ + columns: [columns['relationID']], + foreignColumns: [relation.id], + name: 'payload_locked_documents_rels_relation_fk', + }).onDelete('cascade'), + 'strict-accessIdFk': foreignKey({ + columns: [columns['strict-accessID']], + foreignColumns: [strict_access.id], + name: 'payload_locked_documents_rels_strict_access_fk', + }).onDelete('cascade'), + chainedIdFk: foreignKey({ + columns: [columns['chainedID']], + foreignColumns: [chained.id], + name: 'payload_locked_documents_rels_chained_fk', + }).onDelete('cascade'), + 'custom-idIdFk': foreignKey({ + columns: [columns['custom-idID']], + foreignColumns: [custom_id.id], + name: 'payload_locked_documents_rels_custom_id_fk', + }).onDelete('cascade'), + 'custom-id-numberIdFk': foreignKey({ + columns: [columns['custom-id-numberID']], + foreignColumns: [custom_id_number.id], + name: 'payload_locked_documents_rels_custom_id_number_fk', + }).onDelete('cascade'), + screeningsIdFk: foreignKey({ + columns: [columns['screeningsID']], + foreignColumns: [screenings.id], + name: 'payload_locked_documents_rels_screenings_fk', + }).onDelete('cascade'), + moviesIdFk: foreignKey({ + columns: [columns['moviesID']], + foreignColumns: [movies.id], + name: 'payload_locked_documents_rels_movies_fk', + }).onDelete('cascade'), + directorsIdFk: foreignKey({ + columns: [columns['directorsID']], + foreignColumns: [directors.id], + name: 'payload_locked_documents_rels_directors_fk', + }).onDelete('cascade'), + movieReviewsIdFk: foreignKey({ + columns: [columns['movieReviewsID']], + foreignColumns: [movie_reviews.id], + name: 'payload_locked_documents_rels_movie_reviews_fk', + }).onDelete('cascade'), + 'polymorphic-relationshipsIdFk': foreignKey({ + columns: [columns['polymorphic-relationshipsID']], + foreignColumns: [polymorphic_relationships.id], + name: 'payload_locked_documents_rels_polymorphic_relationships_fk', + }).onDelete('cascade'), + treeIdFk: foreignKey({ + columns: [columns['treeID']], + foreignColumns: [tree.id], + name: 'payload_locked_documents_rels_tree_fk', + }).onDelete('cascade'), + pagesIdFk: foreignKey({ + columns: [columns['pagesID']], + foreignColumns: [pages.id], + name: 'payload_locked_documents_rels_pages_fk', + }).onDelete('cascade'), + 'rels-to-pagesIdFk': foreignKey({ + columns: [columns['rels-to-pagesID']], + foreignColumns: [rels_to_pages.id], + name: 'payload_locked_documents_rels_rels_to_pages_fk', + }).onDelete('cascade'), + 'rels-to-pages-and-custom-text-idsIdFk': foreignKey({ + columns: [columns['rels-to-pages-and-custom-text-idsID']], + foreignColumns: [rels_to_pages_and_custom_text_ids.id], + name: 'payload_locked_documents_rels_rels_to_pages_and_custom_text_ids_fk', + }).onDelete('cascade'), + 'object-writesIdFk': foreignKey({ + columns: [columns['object-writesID']], + foreignColumns: [object_writes.id], + name: 'payload_locked_documents_rels_object_writes_fk', + }).onDelete('cascade'), + usersIdFk: foreignKey({ + columns: [columns['usersID']], + foreignColumns: [users.id], + name: 'payload_locked_documents_rels_users_fk', + }).onDelete('cascade'), + }), +) + +export const payload_preferences = pgTable( + 'payload_preferences', + { + id: serial('id').primaryKey(), + key: varchar('key'), + value: jsonb('value'), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + payload_preferences_key_idx: index('payload_preferences_key_idx').on(columns.key), + payload_preferences_updated_at_idx: index('payload_preferences_updated_at_idx').on( + columns.updatedAt, + ), + payload_preferences_created_at_idx: index('payload_preferences_created_at_idx').on( + columns.createdAt, + ), + }), +) + +export const payload_preferences_rels = pgTable( + 'payload_preferences_rels', + { + id: serial('id').primaryKey(), + order: integer('order'), + parent: integer('parent_id').notNull(), + path: varchar('path').notNull(), + usersID: integer('users_id'), + }, + (columns) => ({ + order: index('payload_preferences_rels_order_idx').on(columns.order), + parentIdx: index('payload_preferences_rels_parent_idx').on(columns.parent), + pathIdx: index('payload_preferences_rels_path_idx').on(columns.path), + payload_preferences_rels_users_id_idx: index('payload_preferences_rels_users_id_idx').on( + columns.usersID, + ), + parentFk: foreignKey({ + columns: [columns['parent']], + foreignColumns: [payload_preferences.id], + name: 'payload_preferences_rels_parent_fk', + }).onDelete('cascade'), + usersIdFk: foreignKey({ + columns: [columns['usersID']], + foreignColumns: [users.id], + name: 'payload_preferences_rels_users_fk', + }).onDelete('cascade'), + }), +) + +export const payload_migrations = pgTable( + 'payload_migrations', + { + id: serial('id').primaryKey(), + name: varchar('name'), + batch: numeric('batch'), + updatedAt: timestamp('updated_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + createdAt: timestamp('created_at', { mode: 'string', withTimezone: true, precision: 3 }) + .defaultNow() + .notNull(), + }, + (columns) => ({ + payload_migrations_updated_at_idx: index('payload_migrations_updated_at_idx').on( + columns.updatedAt, + ), + payload_migrations_created_at_idx: index('payload_migrations_created_at_idx').on( + columns.createdAt, + ), + }), +) + +export const relations_posts_blocks_block = relations(posts_blocks_block, ({ one }) => ({ + _parentID: one(posts, { + fields: [posts_blocks_block._parentID], + references: [posts.id], + relationName: '_blocks_block', + }), + relationField: one(relation, { + fields: [posts_blocks_block.relationField], + references: [relation.id], + relationName: 'relationField', + }), +})) +export const relations_posts = relations(posts, ({ one, many }) => ({ + relationField: one(relation, { + fields: [posts.relationField], + references: [relation.id], + relationName: 'relationField', + }), + _blocks_block: many(posts_blocks_block, { + relationName: '_blocks_block', + }), + defaultAccessRelation: one(strict_access, { + fields: [posts.defaultAccessRelation], + references: [strict_access.id], + relationName: 'defaultAccessRelation', + }), + chainedRelation: one(chained, { + fields: [posts.chainedRelation], + references: [chained.id], + relationName: 'chainedRelation', + }), + maxDepthRelation: one(relation, { + fields: [posts.maxDepthRelation], + references: [relation.id], + relationName: 'maxDepthRelation', + }), + customIdRelation: one(custom_id, { + fields: [posts.customIdRelation], + references: [custom_id.id], + relationName: 'customIdRelation', + }), + customIdNumberRelation: one(custom_id_number, { + fields: [posts.customIdNumberRelation], + references: [custom_id_number.id], + relationName: 'customIdNumberRelation', + }), + filteredRelation: one(relation, { + fields: [posts.filteredRelation], + references: [relation.id], + relationName: 'filteredRelation', + }), +})) +export const relations_posts_localized_locales = relations(posts_localized_locales, ({ one }) => ({ + _parentID: one(posts_localized, { + fields: [posts_localized_locales._parentID], + references: [posts_localized.id], + relationName: '_locales', + }), + relationField: one(relation, { + fields: [posts_localized_locales.relationField], + references: [relation.id], + relationName: 'relationField', + }), +})) +export const relations_posts_localized = relations(posts_localized, ({ many }) => ({ + _locales: many(posts_localized_locales, { + relationName: '_locales', + }), +})) +export const relations_relation = relations(relation, () => ({})) +export const relations_strict_access = relations(strict_access, () => ({})) +export const relations_chained = relations(chained, ({ one }) => ({ + relation: one(chained, { + fields: [chained.relation], + references: [chained.id], + relationName: 'relation', + }), +})) +export const relations_custom_id = relations(custom_id, () => ({})) +export const relations_custom_id_number = relations(custom_id_number, () => ({})) +export const relations_screenings = relations(screenings, ({ one }) => ({ + movie: one(movies, { + fields: [screenings.movie], + references: [movies.id], + relationName: 'movie', + }), +})) +export const relations_movies = relations(movies, ({ one }) => ({ + director: one(directors, { + fields: [movies.director], + references: [directors.id], + relationName: 'director', + }), +})) +export const relations_directors_rels = relations(directors_rels, ({ one }) => ({ + parent: one(directors, { + fields: [directors_rels.parent], + references: [directors.id], + relationName: '_rels', + }), + moviesID: one(movies, { + fields: [directors_rels.moviesID], + references: [movies.id], + relationName: 'movies', + }), +})) +export const relations_directors = relations(directors, ({ many }) => ({ + _rels: many(directors_rels, { + relationName: '_rels', + }), +})) +export const relations_movie_reviews_rels = relations(movie_reviews_rels, ({ one }) => ({ + parent: one(movie_reviews, { + fields: [movie_reviews_rels.parent], + references: [movie_reviews.id], + relationName: '_rels', + }), + usersID: one(users, { + fields: [movie_reviews_rels.usersID], + references: [users.id], + relationName: 'users', + }), +})) +export const relations_movie_reviews = relations(movie_reviews, ({ one, many }) => ({ + movieReviewer: one(users, { + fields: [movie_reviews.movieReviewer], + references: [users.id], + relationName: 'movieReviewer', + }), + _rels: many(movie_reviews_rels, { + relationName: '_rels', + }), +})) +export const relations_polymorphic_relationships_rels = relations( + polymorphic_relationships_rels, + ({ one }) => ({ + parent: one(polymorphic_relationships, { + fields: [polymorphic_relationships_rels.parent], + references: [polymorphic_relationships.id], + relationName: '_rels', + }), + moviesID: one(movies, { + fields: [polymorphic_relationships_rels.moviesID], + references: [movies.id], + relationName: 'movies', + }), + }), +) +export const relations_polymorphic_relationships = relations( + polymorphic_relationships, + ({ many }) => ({ + _rels: many(polymorphic_relationships_rels, { + relationName: '_rels', + }), + }), +) +export const relations_tree = relations(tree, ({ one }) => ({ + parent: one(tree, { + fields: [tree.parent], + references: [tree.id], + relationName: 'parent', + }), +})) +export const relations_pages_menu = relations(pages_menu, ({ one }) => ({ + _parentID: one(pages, { + fields: [pages_menu._parentID], + references: [pages.id], + relationName: 'menu', + }), +})) +export const relations_pages = relations(pages, ({ many }) => ({ + menu: many(pages_menu, { + relationName: 'menu', + }), +})) +export const relations_rels_to_pages = relations(rels_to_pages, ({ one }) => ({ + page: one(pages, { + fields: [rels_to_pages.page], + references: [pages.id], + relationName: 'page', + }), +})) +export const relations_rels_to_pages_and_custom_text_ids_rels = relations( + rels_to_pages_and_custom_text_ids_rels, + ({ one }) => ({ + parent: one(rels_to_pages_and_custom_text_ids, { + fields: [rels_to_pages_and_custom_text_ids_rels.parent], + references: [rels_to_pages_and_custom_text_ids.id], + relationName: '_rels', + }), + pagesID: one(pages, { + fields: [rels_to_pages_and_custom_text_ids_rels.pagesID], + references: [pages.id], + relationName: 'pages', + }), + 'custom-idID': one(custom_id, { + fields: [rels_to_pages_and_custom_text_ids_rels['custom-idID']], + references: [custom_id.id], + relationName: 'custom-id', + }), + 'custom-id-numberID': one(custom_id_number, { + fields: [rels_to_pages_and_custom_text_ids_rels['custom-id-numberID']], + references: [custom_id_number.id], + relationName: 'custom-id-number', + }), + }), +) +export const relations_rels_to_pages_and_custom_text_ids = relations( + rels_to_pages_and_custom_text_ids, + ({ many }) => ({ + _rels: many(rels_to_pages_and_custom_text_ids_rels, { + relationName: '_rels', + }), + }), +) +export const relations_object_writes_rels = relations(object_writes_rels, ({ one }) => ({ + parent: one(object_writes, { + fields: [object_writes_rels.parent], + references: [object_writes.id], + relationName: '_rels', + }), + moviesID: one(movies, { + fields: [object_writes_rels.moviesID], + references: [movies.id], + relationName: 'movies', + }), +})) +export const relations_object_writes = relations(object_writes, ({ one, many }) => ({ + one: one(movies, { + fields: [object_writes.one], + references: [movies.id], + relationName: 'one', + }), + _rels: many(object_writes_rels, { + relationName: '_rels', + }), +})) +export const relations_users = relations(users, () => ({})) +export const relations_payload_locked_documents_rels = relations( + payload_locked_documents_rels, + ({ one }) => ({ + parent: one(payload_locked_documents, { + fields: [payload_locked_documents_rels.parent], + references: [payload_locked_documents.id], + relationName: '_rels', + }), + postsID: one(posts, { + fields: [payload_locked_documents_rels.postsID], + references: [posts.id], + relationName: 'posts', + }), + postsLocalizedID: one(posts_localized, { + fields: [payload_locked_documents_rels.postsLocalizedID], + references: [posts_localized.id], + relationName: 'postsLocalized', + }), + relationID: one(relation, { + fields: [payload_locked_documents_rels.relationID], + references: [relation.id], + relationName: 'relation', + }), + 'strict-accessID': one(strict_access, { + fields: [payload_locked_documents_rels['strict-accessID']], + references: [strict_access.id], + relationName: 'strict-access', + }), + chainedID: one(chained, { + fields: [payload_locked_documents_rels.chainedID], + references: [chained.id], + relationName: 'chained', + }), + 'custom-idID': one(custom_id, { + fields: [payload_locked_documents_rels['custom-idID']], + references: [custom_id.id], + relationName: 'custom-id', + }), + 'custom-id-numberID': one(custom_id_number, { + fields: [payload_locked_documents_rels['custom-id-numberID']], + references: [custom_id_number.id], + relationName: 'custom-id-number', + }), + screeningsID: one(screenings, { + fields: [payload_locked_documents_rels.screeningsID], + references: [screenings.id], + relationName: 'screenings', + }), + moviesID: one(movies, { + fields: [payload_locked_documents_rels.moviesID], + references: [movies.id], + relationName: 'movies', + }), + directorsID: one(directors, { + fields: [payload_locked_documents_rels.directorsID], + references: [directors.id], + relationName: 'directors', + }), + movieReviewsID: one(movie_reviews, { + fields: [payload_locked_documents_rels.movieReviewsID], + references: [movie_reviews.id], + relationName: 'movieReviews', + }), + 'polymorphic-relationshipsID': one(polymorphic_relationships, { + fields: [payload_locked_documents_rels['polymorphic-relationshipsID']], + references: [polymorphic_relationships.id], + relationName: 'polymorphic-relationships', + }), + treeID: one(tree, { + fields: [payload_locked_documents_rels.treeID], + references: [tree.id], + relationName: 'tree', + }), + pagesID: one(pages, { + fields: [payload_locked_documents_rels.pagesID], + references: [pages.id], + relationName: 'pages', + }), + 'rels-to-pagesID': one(rels_to_pages, { + fields: [payload_locked_documents_rels['rels-to-pagesID']], + references: [rels_to_pages.id], + relationName: 'rels-to-pages', + }), + 'rels-to-pages-and-custom-text-idsID': one(rels_to_pages_and_custom_text_ids, { + fields: [payload_locked_documents_rels['rels-to-pages-and-custom-text-idsID']], + references: [rels_to_pages_and_custom_text_ids.id], + relationName: 'rels-to-pages-and-custom-text-ids', + }), + 'object-writesID': one(object_writes, { + fields: [payload_locked_documents_rels['object-writesID']], + references: [object_writes.id], + relationName: 'object-writes', + }), + usersID: one(users, { + fields: [payload_locked_documents_rels.usersID], + references: [users.id], + relationName: 'users', + }), + }), +) +export const relations_payload_locked_documents = relations( + payload_locked_documents, + ({ many }) => ({ + _rels: many(payload_locked_documents_rels, { + relationName: '_rels', + }), + }), +) +export const relations_payload_preferences_rels = relations( + payload_preferences_rels, + ({ one }) => ({ + parent: one(payload_preferences, { + fields: [payload_preferences_rels.parent], + references: [payload_preferences.id], + relationName: '_rels', + }), + usersID: one(users, { + fields: [payload_preferences_rels.usersID], + references: [users.id], + relationName: 'users', + }), + }), +) +export const relations_payload_preferences = relations(payload_preferences, ({ many }) => ({ + _rels: many(payload_preferences_rels, { + relationName: '_rels', + }), +})) +export const relations_payload_migrations = relations(payload_migrations, () => ({})) + +type DatabaseSchema = { + enum__locales: typeof enum__locales + enum_movie_reviews_visibility: typeof enum_movie_reviews_visibility + posts_blocks_block: typeof posts_blocks_block + posts: typeof posts + posts_localized: typeof posts_localized + posts_localized_locales: typeof posts_localized_locales + relation: typeof relation + strict_access: typeof strict_access + chained: typeof chained + custom_id: typeof custom_id + custom_id_number: typeof custom_id_number + screenings: typeof screenings + movies: typeof movies + directors: typeof directors + directors_rels: typeof directors_rels + movie_reviews: typeof movie_reviews + movie_reviews_rels: typeof movie_reviews_rels + polymorphic_relationships: typeof polymorphic_relationships + polymorphic_relationships_rels: typeof polymorphic_relationships_rels + tree: typeof tree + pages_menu: typeof pages_menu + pages: typeof pages + rels_to_pages: typeof rels_to_pages + rels_to_pages_and_custom_text_ids: typeof rels_to_pages_and_custom_text_ids + rels_to_pages_and_custom_text_ids_rels: typeof rels_to_pages_and_custom_text_ids_rels + object_writes: typeof object_writes + object_writes_rels: typeof object_writes_rels + users: typeof users + payload_locked_documents: typeof payload_locked_documents + payload_locked_documents_rels: typeof payload_locked_documents_rels + payload_preferences: typeof payload_preferences + payload_preferences_rels: typeof payload_preferences_rels + payload_migrations: typeof payload_migrations + relations_posts_blocks_block: typeof relations_posts_blocks_block + relations_posts: typeof relations_posts + relations_posts_localized_locales: typeof relations_posts_localized_locales + relations_posts_localized: typeof relations_posts_localized + relations_relation: typeof relations_relation + relations_strict_access: typeof relations_strict_access + relations_chained: typeof relations_chained + relations_custom_id: typeof relations_custom_id + relations_custom_id_number: typeof relations_custom_id_number + relations_screenings: typeof relations_screenings + relations_movies: typeof relations_movies + relations_directors_rels: typeof relations_directors_rels + relations_directors: typeof relations_directors + relations_movie_reviews_rels: typeof relations_movie_reviews_rels + relations_movie_reviews: typeof relations_movie_reviews + relations_polymorphic_relationships_rels: typeof relations_polymorphic_relationships_rels + relations_polymorphic_relationships: typeof relations_polymorphic_relationships + relations_tree: typeof relations_tree + relations_pages_menu: typeof relations_pages_menu + relations_pages: typeof relations_pages + relations_rels_to_pages: typeof relations_rels_to_pages + relations_rels_to_pages_and_custom_text_ids_rels: typeof relations_rels_to_pages_and_custom_text_ids_rels + relations_rels_to_pages_and_custom_text_ids: typeof relations_rels_to_pages_and_custom_text_ids + relations_object_writes_rels: typeof relations_object_writes_rels + relations_object_writes: typeof relations_object_writes + relations_users: typeof relations_users + relations_payload_locked_documents_rels: typeof relations_payload_locked_documents_rels + relations_payload_locked_documents: typeof relations_payload_locked_documents + relations_payload_preferences_rels: typeof relations_payload_preferences_rels + relations_payload_preferences: typeof relations_payload_preferences + relations_payload_migrations: typeof relations_payload_migrations +} + +declare module '@payloadcms/db-postgres/types' { + export interface GeneratedDatabaseSchema { + schema: DatabaseSchema + } +}