From 1f5b01159da1a638de4eeefab323a967045a3c97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Str=C3=B6berg?= Date: Mon, 17 Mar 2025 17:26:10 +0100 Subject: [PATCH 1/4] feat(cms): setup email closed COD-281 --- apps/cms/.env.local | 15 + apps/cms/src/payload.config.ts | 15 + libs/app-cms/util/email/eslint.config.mjs | 3 + libs/app-cms/util/email/project.json | 8 + libs/app-cms/util/email/src/index.ts | 1 + .../util/email/src/lib/get-email-adapter.ts | 47 ++++ libs/app-cms/util/email/tsconfig.json | 22 ++ libs/app-cms/util/email/tsconfig.lib.json | 17 ++ libs/app-cms/util/email/tsconfig.spec.json | 22 ++ libs/app-cms/util/email/vite.config.mts | 22 ++ .../util/env-schema/src/lib/env.schema.ts | 42 ++- .../env-schema/src/lib/ethereal.schema.ts | 16 ++ .../env-schema/src/lib/sendgrid.schema.ts | 13 + package.json | 5 + pnpm-lock.yaml | 260 ++++++++++++++++++ tsconfig.base.json | 1 + 16 files changed, 507 insertions(+), 2 deletions(-) create mode 100644 libs/app-cms/util/email/eslint.config.mjs create mode 100644 libs/app-cms/util/email/project.json create mode 100644 libs/app-cms/util/email/src/index.ts create mode 100644 libs/app-cms/util/email/src/lib/get-email-adapter.ts create mode 100644 libs/app-cms/util/email/tsconfig.json create mode 100644 libs/app-cms/util/email/tsconfig.lib.json create mode 100644 libs/app-cms/util/email/tsconfig.spec.json create mode 100644 libs/app-cms/util/email/vite.config.mts create mode 100644 libs/app-cms/util/env-schema/src/lib/ethereal.schema.ts create mode 100644 libs/app-cms/util/env-schema/src/lib/sendgrid.schema.ts diff --git a/apps/cms/.env.local b/apps/cms/.env.local index 1bb0af4fd..a212099bb 100644 --- a/apps/cms/.env.local +++ b/apps/cms/.env.local @@ -30,6 +30,21 @@ S3_ENDPOINT=https://tiuqdqnfadzjngucaatb.supabase.co/storage/v1/s3 S3_FORCE_PATH_STYLE=true S3_REGION=eu-central-1 +# SendGrid credentials (higher priority than ethereal email) +SENDGRID_API_KEY= +SENDGRID_FROM_ADDRESS= +SENDGRID_FROM_NAME= + +# Ethereal email credentials (provide all details to enable) +# Create an account at https://ethereal.email/create +# Read your email at https://ethereal.email/messages +ETHEREAL_FROM_ADDRESS= +ETHEREAL_FROM_NAME= +ETHEREAL_HOST=smtp.ethereal.email +ETHEREAL_PORT=587 +ETHEREAL_USERNAME= +ETHEREAL_PASSWORD= + # Set to true to prevent database sync and behave as if it's production. # This is required when serving the app after running migrations locally. # Otherwise we'll probably run into race condition sync issues. diff --git a/apps/cms/src/payload.config.ts b/apps/cms/src/payload.config.ts index bd517b032..84a7be2ff 100644 --- a/apps/cms/src/payload.config.ts +++ b/apps/cms/src/payload.config.ts @@ -13,6 +13,7 @@ import { mediaBlock } from '@codeware/app-cms/ui/blocks'; import { defaultLexical } from '@codeware/app-cms/ui/fields'; +import { getEmailAdapter } from '@codeware/app-cms/util/email'; import { getPugins } from '@codeware/app-cms/util/plugins'; import categories from './collections/categories/categories.collection'; @@ -54,6 +55,7 @@ export default buildConfig({ prodMigrations: migrations }), editor: defaultLexical, + email: getEmailAdapter(env), plugins: getPugins(env), secret: env.PAYLOAD_SECRET_KEY, // i18n support @@ -81,6 +83,19 @@ export default buildConfig({ // Invoke seed process on payload init onInit: async (payload) => { payload.logger.info(`Using ${payload.db.name} database adapter`); + if (env.EMAIL?.ethereal) { + payload.logger.info('Using Ethereal email adapter'); + payload.logger.info(`[ethereal] Inbox: https://ethereal.email/messages`); + payload.logger.info(`[ethereal] Username: ${env.EMAIL.ethereal.user}`); + payload.logger.info(`[ethereal] Password: ${env.EMAIL.ethereal.pass}`); + } + if (env.EMAIL?.sendgrid) { + payload.logger.info('Using SendGrid email adapter'); + } + if (!env.EMAIL) { + payload.logger.info('Email is disabled'); + } + payload.logger.info('Payload is ready'); await seed({ environment: env.DEPLOY_ENV, diff --git a/libs/app-cms/util/email/eslint.config.mjs b/libs/app-cms/util/email/eslint.config.mjs new file mode 100644 index 000000000..4c373a675 --- /dev/null +++ b/libs/app-cms/util/email/eslint.config.mjs @@ -0,0 +1,3 @@ +import baseConfig from '../../../../eslint.config.mjs'; + +export default [...baseConfig]; diff --git a/libs/app-cms/util/email/project.json b/libs/app-cms/util/email/project.json new file mode 100644 index 000000000..27e7ed1db --- /dev/null +++ b/libs/app-cms/util/email/project.json @@ -0,0 +1,8 @@ +{ + "name": "app-cms-util-email", + "$schema": "../../../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/app-cms/util/email/src", + "projectType": "library", + "tags": ["scope:app-cms", "type:util"], + "targets": {} +} diff --git a/libs/app-cms/util/email/src/index.ts b/libs/app-cms/util/email/src/index.ts new file mode 100644 index 000000000..6620da1e5 --- /dev/null +++ b/libs/app-cms/util/email/src/index.ts @@ -0,0 +1 @@ +export { getEmailAdapter } from './lib/get-email-adapter'; diff --git a/libs/app-cms/util/email/src/lib/get-email-adapter.ts b/libs/app-cms/util/email/src/lib/get-email-adapter.ts new file mode 100644 index 000000000..8ff556abf --- /dev/null +++ b/libs/app-cms/util/email/src/lib/get-email-adapter.ts @@ -0,0 +1,47 @@ +import type { Env } from '@codeware/app-cms/util/env-schema'; +import { nodemailerAdapter } from '@payloadcms/email-nodemailer'; +import nodemailer from 'nodemailer'; +import SMTPTransport from 'nodemailer/lib/smtp-transport'; +import nodemailerSendgrid from 'nodemailer-sendgrid'; + +/** + * Get the email adapter or undefined if email is disabled. + * + * @param env - The environment variables. + * @returns The email adapter or undefined. + */ +export const getEmailAdapter = (env: Env) => { + // First check if sendgrid is configured + if (env.EMAIL?.sendgrid) { + const { apiKey, defaultFromAddress, defaultFromName } = env.EMAIL.sendgrid; + + return nodemailerAdapter({ + defaultFromAddress, + defaultFromName, + transportOptions: nodemailerSendgrid({ + apiKey + }) + }); + } + + // Then check if ethereal is configured + if (env.EMAIL?.ethereal) { + const { defaultFromAddress, defaultFromName, host, port, user, pass } = + env.EMAIL.ethereal; + + const smptConfig: SMTPTransport.Options = { + host, + port, + auth: { user, pass } + }; + + return nodemailerAdapter({ + defaultFromAddress, + defaultFromName, + transport: nodemailer.createTransport(smptConfig) + }); + } + + // Email is disabled + return undefined; +}; diff --git a/libs/app-cms/util/email/tsconfig.json b/libs/app-cms/util/email/tsconfig.json new file mode 100644 index 000000000..13eea9f7e --- /dev/null +++ b/libs/app-cms/util/email/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "forceConsistentCasingInFileNames": true, + "strict": true, + "importHelpers": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "noPropertyAccessFromIndexSignature": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/libs/app-cms/util/email/tsconfig.lib.json b/libs/app-cms/util/email/tsconfig.lib.json new file mode 100644 index 000000000..6cbb4f3e2 --- /dev/null +++ b/libs/app-cms/util/email/tsconfig.lib.json @@ -0,0 +1,17 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../../dist/out-tsc", + "declaration": true, + "types": ["node"] + }, + "include": ["src/**/*.ts"], + "exclude": [ + "vite.config.ts", + "vite.config.mts", + "vitest.config.ts", + "vitest.config.mts", + "src/**/*.spec.ts", + "src/**/*.spec.tsx" + ] +} diff --git a/libs/app-cms/util/email/tsconfig.spec.json b/libs/app-cms/util/email/tsconfig.spec.json new file mode 100644 index 000000000..a10e2fb63 --- /dev/null +++ b/libs/app-cms/util/email/tsconfig.spec.json @@ -0,0 +1,22 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../../dist/out-tsc", + "types": [ + "vitest/globals", + "vitest/importMeta", + "vite/client", + "node", + "vitest" + ] + }, + "include": [ + "vite.config.ts", + "vite.config.mts", + "vitest.config.ts", + "vitest.config.mts", + "src/**/*.spec.ts", + "src/**/*.spec.tsx", + "src/**/*.d.ts" + ] +} diff --git a/libs/app-cms/util/email/vite.config.mts b/libs/app-cms/util/email/vite.config.mts new file mode 100644 index 000000000..5e5438487 --- /dev/null +++ b/libs/app-cms/util/email/vite.config.mts @@ -0,0 +1,22 @@ +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; +import { defineConfig } from 'vite'; + +export default defineConfig({ + root: __dirname, + cacheDir: '../../../../node_modules/.vite/libs/app-cms/util/email', + plugins: [nxViteTsPaths()], + + test: { + name: 'app-cms-util-email', + watch: false, + globals: true, + environment: 'node', + include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + reporters: ['default'], + coverage: { + reportsDirectory: '../../../../coverage/libs/app-cms/util/email', + provider: 'v8' + }, + passWithNoTests: true + } +}); diff --git a/libs/app-cms/util/env-schema/src/lib/env.schema.ts b/libs/app-cms/util/env-schema/src/lib/env.schema.ts index 787299d05..6972bc3dd 100644 --- a/libs/app-cms/util/env-schema/src/lib/env.schema.ts +++ b/libs/app-cms/util/env-schema/src/lib/env.schema.ts @@ -1,9 +1,11 @@ import { withEnvVars } from '@codeware/shared/util/zod'; import { z } from 'zod'; +import { EtherealSchema } from './ethereal.schema'; import { S3StorageSchema } from './s3-storage.schema'; import { SeedSourceSchema } from './seed-source.schema'; import { SeedStrategySchema } from './seed-strategy.schema'; +import { SendGridSchema } from './sendgrid.schema'; /** * Environment base schema with environment variable lookup. @@ -69,18 +71,31 @@ export const EnvSchema = withEnvVars( }) // S3 storage is optional .merge(S3StorageSchema.partial()) + // Ethereal is optional + .merge(EtherealSchema.partial()) + // SendGrid is optional + .merge(SendGridSchema.partial()) ).transform( ({ + ETHEREAL_FROM_ADDRESS, + ETHEREAL_FROM_NAME, + ETHEREAL_HOST, + ETHEREAL_PASSWORD, + ETHEREAL_PORT, + ETHEREAL_USERNAME, S3_ACCESS_KEY_ID, S3_BUCKET, S3_ENDPOINT, S3_FORCE_PATH_STYLE, S3_REGION, S3_SECRET_ACCESS_KEY, + SENDGRID_API_KEY, + SENDGRID_FROM_ADDRESS, + SENDGRID_FROM_NAME, ...env }) => ({ ...env, - // Transform to storage object if access key id is provided + // Transform to storage object if S3 access key id is provided S3_STORAGE: S3_ACCESS_KEY_ID ? { bucket: String(S3_BUCKET), @@ -92,7 +107,30 @@ export const EnvSchema = withEnvVars( secretAccessKey: String(S3_SECRET_ACCESS_KEY) } } - : undefined + : undefined, + EMAIL: + // Transform to sendgrid object if sendgrid api key is provided + SENDGRID_API_KEY + ? { + sendgrid: { + apiKey: SENDGRID_API_KEY, + defaultFromAddress: String(SENDGRID_FROM_ADDRESS), + defaultFromName: String(SENDGRID_FROM_NAME) + } + } + : // Transform to ethereal object if ethereal credentials are provided + ETHEREAL_USERNAME && ETHEREAL_PASSWORD + ? { + ethereal: { + defaultFromAddress: String(ETHEREAL_FROM_ADDRESS), + defaultFromName: String(ETHEREAL_FROM_NAME), + host: String(ETHEREAL_HOST), + port: Number(ETHEREAL_PORT), + user: ETHEREAL_USERNAME, + pass: ETHEREAL_PASSWORD + } + } + : undefined }) ); diff --git a/libs/app-cms/util/env-schema/src/lib/ethereal.schema.ts b/libs/app-cms/util/env-schema/src/lib/ethereal.schema.ts new file mode 100644 index 000000000..2259c262c --- /dev/null +++ b/libs/app-cms/util/env-schema/src/lib/ethereal.schema.ts @@ -0,0 +1,16 @@ +import { z } from 'zod'; + +export const EtherealSchema = z.object({ + ETHEREAL_FROM_ADDRESS: z + .string({ description: 'Default from address' }) + .email() + .optional() + .or(z.literal('')), + ETHEREAL_FROM_NAME: z.string({ description: 'Default from name' }), + ETHEREAL_HOST: z.string({ description: 'Ethereal SMTP host' }), + ETHEREAL_PORT: z.number({ coerce: true, description: 'Ethereal SMTP port' }), + ETHEREAL_USERNAME: z.string({ description: 'Ethereal SMTP username' }), + ETHEREAL_PASSWORD: z.string({ description: 'Ethereal SMTP password' }) +}); + +export type Ethereal = z.infer; diff --git a/libs/app-cms/util/env-schema/src/lib/sendgrid.schema.ts b/libs/app-cms/util/env-schema/src/lib/sendgrid.schema.ts new file mode 100644 index 000000000..134ecd703 --- /dev/null +++ b/libs/app-cms/util/env-schema/src/lib/sendgrid.schema.ts @@ -0,0 +1,13 @@ +import { z } from 'zod'; + +export const SendGridSchema = z.object({ + SENDGRID_API_KEY: z.string({ description: 'SendGrid API key' }), + SENDGRID_FROM_ADDRESS: z + .string({ description: 'Default from address' }) + .email() + .optional() + .or(z.literal('')), + SENDGRID_FROM_NAME: z.string({ description: 'Default from name' }) +}); + +export type SendGrid = z.infer; diff --git a/package.json b/package.json index 0a3209e34..be4614aa1 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "@octokit/request-error": "^5.0.1", "@payloadcms/db-mongodb": "^3.23.0", "@payloadcms/db-postgres": "^3.23.0", + "@payloadcms/email-nodemailer": "^3.23.0", "@payloadcms/next": "^3.23.0", "@payloadcms/plugin-multi-tenant": "^3.23.0", "@payloadcms/plugin-seo": "^3.23.0", @@ -41,6 +42,8 @@ "http-status-codes": "^2.3.0", "isbot": "^4.4.0", "next": "15.1.7", + "nodemailer": "^6.10.0", + "nodemailer-sendgrid": "^1.0.3", "payload": "^3.23.0", "prism-react-renderer": "^2.4.1", "react": "19.0.0", @@ -107,6 +110,8 @@ "@types/jest": "^29.5.12", "@types/kill-port": "^2.0.3", "@types/node": "22.13.2", + "@types/nodemailer": "^6.4.17", + "@types/nodemailer-sendgrid": "^1.0.3", "@types/npm-whoami": "^1.1.2", "@types/react": "19.0.0", "@types/react-dom": "19.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7074b51be..59fbc2d68 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -54,6 +54,9 @@ importers: '@payloadcms/db-postgres': specifier: ^3.23.0 version: 3.28.1(@types/react@19.0.0)(payload@3.28.1(graphql@16.10.0)(typescript@5.7.3))(react@19.0.0) + '@payloadcms/email-nodemailer': + specifier: ^3.23.0 + version: 3.28.1(payload@3.28.1(graphql@16.10.0)(typescript@5.7.3)) '@payloadcms/next': specifier: ^3.23.0 version: 3.28.1(@types/react@19.0.0)(graphql@16.10.0)(monaco-editor@0.52.2)(next@15.1.7(@babel/core@7.26.10)(@playwright/test@1.51.0)(babel-plugin-macros@3.1.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.85.1))(payload@3.28.1(graphql@16.10.0)(typescript@5.7.3))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.3) @@ -105,6 +108,12 @@ importers: next: specifier: 15.1.7 version: 15.1.7(@babel/core@7.26.10)(@playwright/test@1.51.0)(babel-plugin-macros@3.1.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.85.1) + nodemailer: + specifier: ^6.10.0 + version: 6.10.0 + nodemailer-sendgrid: + specifier: ^1.0.3 + version: 1.0.3 payload: specifier: ^3.23.0 version: 3.28.1(graphql@16.10.0)(typescript@5.7.3) @@ -298,6 +307,12 @@ importers: '@types/node': specifier: 22.13.2 version: 22.13.2 + '@types/nodemailer': + specifier: ^6.4.17 + version: 6.4.17 + '@types/nodemailer-sendgrid': + specifier: ^1.0.3 + version: 1.0.3 '@types/npm-whoami': specifier: ^1.1.2 version: 1.1.2 @@ -3787,6 +3802,12 @@ packages: peerDependencies: payload: 3.28.1 + '@payloadcms/email-nodemailer@3.28.1': + resolution: {integrity: sha512-JMTQALZS5Z6JP0wyPtnXUU8lCkJZFoF0K++hMS1PvoTDO/oxA7fucL+owAJdF/bWkPS6jTvT/pIhpJC7VLlwlQ==} + engines: {node: ^18.20.2 || >=20.9.0} + peerDependencies: + payload: 3.28.1 + '@payloadcms/graphql@3.28.1': resolution: {integrity: sha512-TFwxCFOMGOHq6dIdTX8nYY0pqEhv8gckyVkuMXaJJb+kM+aCq6981UgNPc7pvBeCm41fb+gE/E21TchOsEfXTA==} hasBin: true @@ -4186,6 +4207,18 @@ packages: '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + '@sendgrid/client@6.5.5': + resolution: {integrity: sha512-Nbfgo94gbWSL8PIgJfuHoifyOJJepvV8NQkkglctAEfb1hyozKhrzE6v1kPG/z4j0RodaTtXD5LJj/t0q/VhLA==} + engines: {node: '>=6.0.0'} + + '@sendgrid/helpers@6.5.5': + resolution: {integrity: sha512-uRFEanalfss5hDsuzVXZ1wm7i7eEXHh1py80piOXjobiQ+MxmtR19EU+gDSXZ+uMcEehBGhxnb7QDNN0q65qig==} + engines: {node: '>= 6.0.0'} + + '@sendgrid/mail@6.5.5': + resolution: {integrity: sha512-DSu8oTPI0BJFH60jMOG9gM+oeNMoRALFmdAYg2PIXpL+Zbxd7L2GzQZtmf1jLy/8UBImkbB3D74TjiOBiLRK1w==} + engines: {node: '>=6.0.0'} + '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} @@ -4703,6 +4736,9 @@ packages: '@types/busboy@1.5.4': resolution: {integrity: sha512-kG7WrUuAKK0NoyxfQHsVE6j1m01s6kMma64E+OZenQABMQyTJop1DumUWcLwAQ2JzpefU7PDYoRDKl8uZosFjw==} + '@types/caseless@0.12.5': + resolution: {integrity: sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==} + '@types/connect-history-api-fallback@1.5.4': resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==} @@ -4814,6 +4850,12 @@ packages: '@types/node@22.13.2': resolution: {integrity: sha512-Z+r8y3XL9ZpI2EY52YYygAFmo2/oWfNSj4BCpAXE2McAexDk8VcnBMGC9Djn9gTKt4d2T/hhXqmPzo4hfIXtTg==} + '@types/nodemailer-sendgrid@1.0.3': + resolution: {integrity: sha512-UpLLUyrXjcs8PIwhfY0/CqXAoJ5CcDNUs6hia9QT9+kcotCFK6siVC5dHUGpTAsodwteX2JoiQ3Na7ZbDkijgw==} + + '@types/nodemailer@6.4.17': + resolution: {integrity: sha512-I9CCaIp6DTldEg7vyUTZi8+9Vo0hi1/T8gv3C89yk1rSAAzoKQ8H8ki/jBYJSFoH/BisgLP8tkZMlQ91CIquww==} + '@types/npm-whoami@1.1.2': resolution: {integrity: sha512-VDsGWTBHn0lR86lnoZk/O6a0d01Vbw+aEXmwrw72xJPOvbMAiOIKYDjQqqAH/RICARGGGhW3gIOUeR+X2Vs4vQ==} @@ -4843,6 +4885,9 @@ packages: '@types/react@19.0.0': resolution: {integrity: sha512-MY3oPudxvMYyesqs/kW1Bh8y9VqSmf+tzqw3ae8a9DZW68pUe3zAdHeI1jc6iAysuRdACnVknHP8AhwD4/dxtg==} + '@types/request@2.48.12': + resolution: {integrity: sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==} + '@types/retry@0.12.2': resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} @@ -5309,6 +5354,10 @@ packages: resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} engines: {node: '>=12'} + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -5744,6 +5793,10 @@ packages: resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} engines: {node: '>=4'} + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + chalk@3.0.0: resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} engines: {node: '>=8'} @@ -5861,10 +5914,16 @@ packages: collect-v8-coverage@1.0.2: resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} @@ -7289,6 +7348,14 @@ packages: resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} engines: {node: '>= 14.17'} + form-data@2.3.3: + resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} + engines: {node: '>= 0.12'} + + form-data@2.5.3: + resolution: {integrity: sha512-XHIrMD0NpDrNM/Ckf7XJiBbLl57KEhT3+i3yY+eWm+cqYZJQTZrKo8Y8AWKnuV5GT4scfuUGt9LzNoIx3dU1nQ==} + engines: {node: '>= 0.12'} + form-data@4.0.2: resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} engines: {node: '>= 6'} @@ -7587,6 +7654,15 @@ packages: engines: {node: '>=0.4.7'} hasBin: true + har-schema@2.0.0: + resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==} + engines: {node: '>=4'} + + har-validator@5.1.5: + resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==} + engines: {node: '>=6'} + deprecated: this library is no longer supported + harmony-reflect@1.6.2: resolution: {integrity: sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==} @@ -7594,6 +7670,10 @@ packages: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} engines: {node: '>= 0.4'} + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -7725,6 +7805,10 @@ packages: engines: {node: '>=12'} hasBin: true + http-signature@1.2.0: + resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} + engines: {node: '>=0.8', npm: '>=1.3.7'} + http-signature@1.4.0: resolution: {integrity: sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==} engines: {node: '>=0.10'} @@ -8474,6 +8558,10 @@ packages: resolution: {integrity: sha512-9Ag50tKhpTwS6r5wh3MJSAvpSof0UBr39Pto8OnzFT32Z/pAbxAsKHzyvsyMEHVslELvHyO/4/jaQELHk8wDcw==} hasBin: true + jsprim@1.4.2: + resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} + engines: {node: '>=0.6.0'} + jsprim@2.0.2: resolution: {integrity: sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==} engines: {'0': node >=0.6.0} @@ -9366,6 +9454,17 @@ packages: nodeify-ts@1.0.6: resolution: {integrity: sha512-jq+8sqVG1aLqy5maMTceL8NUJ1CvarWztlxvrYh3G0aao9BsVeoVmVedUnrUSBLetP7oLIAJrPrw4+iIo7v3GA==} + nodemailer-sendgrid@1.0.3: + resolution: {integrity: sha512-To/veO2M4evjtv1XrY7BUgE+LDypgs/FBx4wOHb2UNTpvZhiARtvMaBI0685Yxkho0lIPJc4jS0cUE7v+XGNgg==} + + nodemailer@6.10.0: + resolution: {integrity: sha512-SQ3wZCExjeSatLE/HBaXS5vqUOQk6GtBdIIKxiFdmm01mOQZX/POJkO3SUX1wDiYcwUOJwT23scFSC9fY2H8IA==} + engines: {node: '>=6.0.0'} + + nodemailer@6.9.16: + resolution: {integrity: sha512-psAuZdTIRN08HKVd/E8ObdV6NO7NTBY3KsC30F7M4H1OnmLCUNaS56FpYxyb26zWLSyYF9Ozch9KYHhHegsiOQ==} + engines: {node: '>=6.0.0'} + normalize-package-data@5.0.0: resolution: {integrity: sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -9440,6 +9539,9 @@ packages: '@swc/core': optional: true + oauth-sign@0.9.0: + resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -10286,6 +10388,10 @@ packages: resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} engines: {node: '>=0.6'} + qs@6.5.3: + resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==} + engines: {node: '>=0.6'} + quansync@0.2.8: resolution: {integrity: sha512-4+saucphJMazjt7iOM27mbFCk+D9dd/zmgMDCzRZ8MEoBfYp7lAvoN38et/phRQF6wOPMy/OROBGgoWeSKyluA==} @@ -10557,6 +10663,11 @@ packages: engines: {node: '>=10'} hasBin: true + request@2.88.2: + resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==} + engines: {node: '>= 6'} + deprecated: request has been deprecated, see https://github.com/request/request/issues/3142 + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -11230,6 +11341,10 @@ packages: resolution: {integrity: sha512-qlsr7fIC0lSddmA3tzojvzubYxvlGtzumcdHgPwbFWMISQwL22MhM2Y3LNt+6w9Yyx7559VW5ab70dgphm8qQA==} engines: {node: '>=14.18.0'} + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -11425,6 +11540,10 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + tough-cookie@2.5.0: + resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} + engines: {node: '>=0.8'} + tough-cookie@4.1.4: resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} engines: {node: '>=6'} @@ -11832,6 +11951,11 @@ packages: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} hasBin: true + uuid@3.4.0: + resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} + deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + hasBin: true + uuid@8.0.0: resolution: {integrity: sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==} hasBin: true @@ -16617,6 +16741,11 @@ snapshots: - sql.js - sqlite3 + '@payloadcms/email-nodemailer@3.28.1(payload@3.28.1(graphql@16.10.0)(typescript@5.7.3))': + dependencies: + nodemailer: 6.9.16 + payload: 3.28.1(graphql@16.10.0)(typescript@5.7.3) + '@payloadcms/graphql@3.28.1(graphql@16.10.0)(payload@3.28.1(graphql@16.10.0)(typescript@5.7.3))(typescript@5.7.3)': dependencies: graphql: 16.10.0 @@ -17139,6 +17268,22 @@ snapshots: '@sec-ant/readable-stream@0.4.1': {} + '@sendgrid/client@6.5.5': + dependencies: + '@sendgrid/helpers': 6.5.5 + '@types/request': 2.48.12 + request: 2.88.2 + + '@sendgrid/helpers@6.5.5': + dependencies: + chalk: 2.4.2 + deepmerge: 4.3.1 + + '@sendgrid/mail@6.5.5': + dependencies: + '@sendgrid/client': 6.5.5 + '@sendgrid/helpers': 6.5.5 + '@sinclair/typebox@0.27.8': {} '@sindresorhus/is@5.6.0': {} @@ -17797,6 +17942,8 @@ snapshots: dependencies: '@types/node': 22.13.2 + '@types/caseless@0.12.5': {} + '@types/connect-history-api-fallback@1.5.4': dependencies: '@types/express-serve-static-core': 5.0.6 @@ -17933,6 +18080,14 @@ snapshots: dependencies: undici-types: 6.20.0 + '@types/nodemailer-sendgrid@1.0.3': + dependencies: + '@types/nodemailer': 6.4.17 + + '@types/nodemailer@6.4.17': + dependencies: + '@types/node': 22.13.2 + '@types/npm-whoami@1.1.2': {} '@types/parse-json@4.0.2': {} @@ -17961,6 +18116,13 @@ snapshots: dependencies: csstype: 3.1.3 + '@types/request@2.48.12': + dependencies: + '@types/caseless': 0.12.5 + '@types/node': 22.13.2 + '@types/tough-cookie': 4.0.5 + form-data: 2.5.3 + '@types/retry@0.12.2': {} '@types/semver@7.5.8': {} @@ -18667,6 +18829,10 @@ snapshots: ansi-regex@6.1.0: {} + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 @@ -19186,6 +19352,12 @@ snapshots: pathval: 1.1.1 type-detect: 4.1.0 + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + chalk@3.0.0: dependencies: ansi-styles: 4.3.0 @@ -19286,10 +19458,16 @@ snapshots: collect-v8-coverage@1.0.2: {} + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + color-convert@2.0.1: dependencies: color-name: 1.1.4 + color-name@1.1.3: {} + color-name@1.1.4: {} color-string@1.9.1: @@ -20974,6 +21152,20 @@ snapshots: form-data-encoder@2.1.4: {} + form-data@2.3.3: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + form-data@2.5.3: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + safe-buffer: 5.2.1 + form-data@4.0.2: dependencies: asynckit: 0.4.0 @@ -21322,10 +21514,19 @@ snapshots: optionalDependencies: uglify-js: 3.19.3 + har-schema@2.0.0: {} + + har-validator@5.1.5: + dependencies: + ajv: 6.12.6 + har-schema: 2.0.0 + harmony-reflect@1.6.2: {} has-bigints@1.1.0: {} + has-flag@3.0.0: {} + has-flag@4.0.0: {} has-property-descriptors@1.0.2: @@ -21510,6 +21711,12 @@ snapshots: - debug - supports-color + http-signature@1.2.0: + dependencies: + assert-plus: 1.0.0 + jsprim: 1.4.2 + sshpk: 1.18.0 + http-signature@1.4.0: dependencies: assert-plus: 1.0.0 @@ -22437,6 +22644,13 @@ snapshots: jsox@1.2.121: {} + jsprim@1.4.2: + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.4.0 + verror: 1.10.0 + jsprim@2.0.2: dependencies: assert-plus: 1.0.0 @@ -23642,6 +23856,14 @@ snapshots: nodeify-ts@1.0.6: {} + nodemailer-sendgrid@1.0.3: + dependencies: + '@sendgrid/mail': 6.5.5 + + nodemailer@6.10.0: {} + + nodemailer@6.9.16: {} + normalize-package-data@5.0.0: dependencies: hosted-git-info: 6.1.3 @@ -23771,6 +23993,8 @@ snapshots: transitivePeerDependencies: - debug + oauth-sign@0.9.0: {} + object-assign@4.1.1: {} object-hash@3.0.0: {} @@ -24676,6 +24900,8 @@ snapshots: dependencies: side-channel: 1.1.0 + qs@6.5.3: {} + quansync@0.2.8: {} querystring@0.2.0: {} @@ -24965,6 +25191,29 @@ snapshots: glob: 8.1.0 yargs: 17.7.2 + request@2.88.2: + dependencies: + aws-sign2: 0.7.0 + aws4: 1.13.2 + caseless: 0.12.0 + combined-stream: 1.0.8 + extend: 3.0.2 + forever-agent: 0.6.1 + form-data: 2.3.3 + har-validator: 5.1.5 + http-signature: 1.2.0 + is-typedarray: 1.0.0 + isstream: 0.1.2 + json-stringify-safe: 5.0.1 + mime-types: 2.1.35 + oauth-sign: 0.9.0 + performance-now: 2.1.0 + qs: 6.5.3 + safe-buffer: 5.2.1 + tough-cookie: 2.5.0 + tunnel-agent: 0.6.0 + uuid: 3.4.0 + require-directory@2.1.1: {} require-from-string@2.0.2: {} @@ -25751,6 +26000,10 @@ snapshots: transitivePeerDependencies: - supports-color + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -25971,6 +26224,11 @@ snapshots: totalist@3.0.1: {} + tough-cookie@2.5.0: + dependencies: + psl: 1.15.0 + punycode: 2.3.1 + tough-cookie@4.1.4: dependencies: psl: 1.15.0 @@ -26391,6 +26649,8 @@ snapshots: uuid@10.0.0: {} + uuid@3.4.0: {} + uuid@8.0.0: {} uuid@8.3.2: {} diff --git a/tsconfig.base.json b/tsconfig.base.json index 197f1a667..97cedabc9 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -39,6 +39,7 @@ "@codeware/app-cms/util/definitions": [ "libs/app-cms/util/definitions/src/index.ts" ], + "@codeware/app-cms/util/email": ["libs/app-cms/util/email/src/index.ts"], "@codeware/app-cms/util/env-schema": [ "libs/app-cms/util/env-schema/src/index.ts" ], From ee31b797fbd5671ac4a5050a2a9b2a1732e0af6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Str=C3=B6berg?= Date: Fri, 21 Mar 2025 15:21:19 +0100 Subject: [PATCH 2/4] chore(web): implement a workaround to provide dev mode live-reload closed COD-284 --- apps/web/nodemon.json | 18 ++++++++++++++++++ apps/web/project.json | 19 ++++++++++--------- package.json | 2 ++ 3 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 apps/web/nodemon.json diff --git a/apps/web/nodemon.json b/apps/web/nodemon.json new file mode 100644 index 000000000..99ce461ad --- /dev/null +++ b/apps/web/nodemon.json @@ -0,0 +1,18 @@ +{ + "watch": [".", "../../libs/**/*"], + "ext": "cjs,css,ts,tsx", + "ignore": [ + "build/", + "node_modules/", + ".git", + "**/*.json", + "**/*.spec.*", + "**/*.timestamp-*", + "**/*.timestamp-*.mjs", + "**/vite.config.mts.timestamp-*.mjs" + ], + "verbose": false, + "exec": "nx build web && tsx server.ts", + "legacyWatch": false, + "delay": "1000" +} diff --git a/apps/web/project.json b/apps/web/project.json index 9599c99fe..bc3f17009 100644 --- a/apps/web/project.json +++ b/apps/web/project.json @@ -61,16 +61,17 @@ }, "dependsOn": ["build"] }, - "static-serve": { - "executor": "nx:noop", - "metadata": { - "description": "Use start target instead" - } - }, - "serve-static": { - "executor": "nx:noop", + "dev": { + "executor": "nx:run-commands", "metadata": { - "description": "Use start target instead" + "description": "Start Hono and Remix in development mode", + "help": { + "command": "nx dev web" + } + }, + "options": { + "command": "npx concurrently -n \"RMX,HNO\" -c \"magenta,blue\" --pad-prefix \"remix vite:dev\" \"nodemon\"", + "cwd": "apps/web" } } } diff --git a/package.json b/package.json index be4614aa1..049bc7330 100644 --- a/package.json +++ b/package.json @@ -125,6 +125,7 @@ "autoprefixer": "10.4.20", "babel-jest": "^29.7.0", "chalk": "^4.1.0", + "concurrently": "^9.1.2", "create-nx-workspace": "20.4.5", "cz-git": "^1.8.0", "czg": "^1.8.0", @@ -147,6 +148,7 @@ "jsdom": "~26.0.0", "kill-port": "^2.0.1", "memfs": "^4.14.0", + "nodemon": "^3.1.9", "npm-whoami": "^1.1.4", "nx": "20.4.5", "nx-cloud": "19.1.0", From 5d6f0b120092b38707f4b0a77c6b43cc62041bfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Str=C3=B6berg?= Date: Tue, 25 Mar 2025 14:15:52 +0100 Subject: [PATCH 3/4] fix(cms): redirect notify should only act on tenent domain redirects closed COD-285 --- .../components/src/lib/RedirectNotifier.tsx | 11 ++--- .../ui/components/src/lib/redirect-params.ts | 45 ++++++++++++++++--- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/libs/app-cms/ui/components/src/lib/RedirectNotifier.tsx b/libs/app-cms/ui/components/src/lib/RedirectNotifier.tsx index 0193ca0a2..f6dc79039 100644 --- a/libs/app-cms/ui/components/src/lib/RedirectNotifier.tsx +++ b/libs/app-cms/ui/components/src/lib/RedirectNotifier.tsx @@ -18,12 +18,13 @@ export const RedirectNotifier: React.FC = () => { const [isOpen, setIsOpen] = useState(false); - const extractedParams = extractSearchParams(searchParams); + const { isTenantDomainRedirect, redirectParams } = + extractSearchParams(searchParams); useEffect(() => { - if (extractedParams) { + if (isTenantDomainRedirect) { // Clean up URL by removing redirect parameters - const params = new URLSearchParams(extractedParams.origin); + const params = new URLSearchParams(redirectParams); for (const key of Array.from(params.keys())) { params.delete(key); } @@ -37,12 +38,12 @@ export const RedirectNotifier: React.FC = () => { router.replace(newUrl); // TODO: Apply email to login form if possible? - //const email = extractedParams.redirect.email; + //const email = redirectExpected.email; // Open modal setIsOpen(true); } - }, [extractedParams, pathname, router]); + }, [isTenantDomainRedirect, pathname, router]); return ( ; +type Result = { + /** + * Whether the redirect comes from a restricted tenant domain. + * + * When this is `true`, the expected params and values exists in `redirectExpected`. + */ + isTenantDomainRedirect: boolean; + + /** + * Extracted redirect search params. + */ + redirectParams: Record; + + /** + * The expected redirect params from `redirectParams` + * to identify the redirect related to a restricted tenant domain. + */ + redirectExpected: RedirectParams; +}; + /** - * Get the redirect params from the URL search params. + * Get the redirect params from the URL search params + * with an indicator whether this comes from a restricted tenant domain redirect. * * Expecting search params pattern (decoded string): * * `redirect=?from=localhost:3000&email=vega@local.dev` * * @param params - The URL search params from `useSearchParams`. - * @returns Original and redirect params or `null` if there are no redirect params. + * @returns Extracted query params result. */ -export const extractSearchParams = (params: ReadonlyURLSearchParams) => { +export const extractSearchParams = ( + params: ReadonlyURLSearchParams +): Result => { const entries = Array.from(params.entries()); if (!(entries.length === 1 && entries[0][0] === paramKey.redirect)) { - return null; + return { + isTenantDomainRedirect: false, + redirectParams: {}, + redirectExpected: {} as RedirectParams + }; } const redirectParamsWithQuestionMark = entries[0][1]; @@ -39,7 +66,7 @@ export const extractSearchParams = (params: ReadonlyURLSearchParams) => { const searchEntries = Array.from(url.searchParams.entries()); // Extract all search params - const origin = searchEntries.reduce( + const redirectParams = searchEntries.reduce( (acc, [key, value]) => { acc[key] = value; return acc; @@ -48,12 +75,16 @@ export const extractSearchParams = (params: ReadonlyURLSearchParams) => { ); // Extract redirect params - const redirect = searchEntries.reduce((acc, [key, value]) => { + const redirectExpected = searchEntries.reduce((acc, [key, value]) => { if (redirectParamKeys.includes(key)) { acc[key as keyof RedirectParams] = value; } return acc; }, {} as RedirectParams); - return { origin, redirect }; + const isTenantDomainRedirect = + Object.keys(redirectExpected).length === redirectParamKeys.length && + Object.values(redirectExpected).every((value) => value && value !== ''); + + return { isTenantDomainRedirect, redirectParams, redirectExpected }; }; From d75d6362c30a71ef8db68bab93feb76b3ff9fec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Str=C3=B6berg?= Date: Tue, 25 Mar 2025 15:12:25 +0100 Subject: [PATCH 4/4] feat(cms): add support for generating forms Form components are using Shadcn UI closed COD-282 --- .vscode/settings.json | 3 +- apps/cms/src/app/(frontend)/globals.css | 4 +- apps/cms/src/app/(payload)/custom.scss | 61 + .../src/collections/pages/pages.collection.ts | 2 +- apps/cms/src/components/Logo.client.tsx | 4 +- .../migrations/20250325_141317_cod_282.json | 5917 ++++++++++++++++ .../src/migrations/20250325_141317_cod_282.ts | 570 ++ .../migrations/20250326_200110_cod_282_2.json | 5947 +++++++++++++++++ .../migrations/20250326_200110_cod_282_2.ts | 25 + apps/cms/src/migrations/index.ts | 12 + apps/cms/src/payload.config.ts | 3 +- apps/cms/src/tailwind.css | 5 - apps/web/app/components/container.tsx | 6 +- .../web/app/components/desktop-navigation.tsx | 4 +- apps/web/app/root.tsx | 79 +- apps/web/app/routes/$slug.tsx | 21 +- apps/web/app/routes/_api.form-submission.tsx | 56 + apps/web/app/routes/_index.tsx | 21 +- apps/web/app/tailwind.css | 64 + apps/web/app/utils/get-api-options.ts | 38 - .../app/utils/get-payload-request-options.ts | 69 + apps/web/eslint.config.mjs | 20 +- apps/web/package.json | 15 + apps/web/tailwind.config.cjs | 60 +- apps/web/typography.cjs | 17 +- components.json | 17 + eslint.config.mjs | 6 +- libs/app-cms/ui/blocks/src/index.ts | 1 + .../blocks/src/lib/content/content.block.ts | 6 +- .../ui/blocks/src/lib/form/form.block.ts | 47 + libs/app-cms/util/plugins/src/index.ts | 2 +- .../util/plugins/src/lib/get-plugins.ts | 20 + libs/app-cms/util/plugins/src/lib/plugins.ts | 89 - .../lib/plugins/forms/customized-fields.ts | 130 + .../src/lib/plugins/forms/ensure-tenant.ts | 19 + .../src/lib/plugins/forms/tenant-access.ts | 62 + .../src/lib/plugins/get-forms-plugin.ts | 21 + .../lib/plugins/get-multi-tenant-plugin.ts | 28 + .../src/lib/plugins/get-s3-storage-plugin.ts | 37 + .../plugins/src/lib/plugins/get-seo-plugin.ts | 22 + libs/shared/ui/payload-components/README.md | 15 + .../shared/ui/payload-components/project.json | 2 +- .../shared/ui/payload-components/src/index.ts | 11 +- .../src/lib/RenderBlocks.tsx | 30 +- .../payload-components/src/lib/RichText.tsx | 74 - .../src/lib/{ => blocks}/CodeBlock.tsx | 11 +- .../src/lib/{ => blocks}/ContentBlock.tsx | 21 +- .../src/lib/blocks/FormBlock.tsx | 308 + .../src/lib/{ => blocks}/MediaBlock.tsx | 19 +- .../src/lib/blocks/RichText.tsx | 70 + .../src/lib/form-items/Button.tsx | 18 + .../src/lib/form-items/Checkbox.tsx | 26 + .../src/lib/form-items/Input.tsx | 29 + .../src/lib/form-items/Select.tsx | 51 + .../src/lib/form-items/Textarea.tsx | 26 + .../src/lib/form-items/country-options.ts | 987 +++ .../src/lib/layout/ColSpan.tsx | 55 + .../src/lib/providers/PayloadProvider.tsx | 107 + .../src/lib/render-blocks.type.ts | 5 - .../ui/react-components/src/lib/Image.tsx | 4 +- libs/shared/ui/shadcn/.babelrc | 12 + libs/shared/ui/shadcn/eslint.config.mjs | 13 + libs/shared/ui/shadcn/project.json | 9 + libs/shared/ui/shadcn/src/index.ts | 15 + .../ui/shadcn/src/lib/components/button.tsx | 56 + .../ui/shadcn/src/lib/components/card.tsx | 86 + .../ui/shadcn/src/lib/components/checkbox.tsx | 28 + .../ui/shadcn/src/lib/components/dialog.tsx | 120 + .../src/lib/components/dropdown-menu.tsx | 198 + .../ui/shadcn/src/lib/components/form.tsx | 178 + .../ui/shadcn/src/lib/components/input.tsx | 22 + .../ui/shadcn/src/lib/components/label.tsx | 24 + .../ui/shadcn/src/lib/components/menubar.tsx | 254 + .../shadcn/src/lib/components/radio-group.tsx | 42 + .../ui/shadcn/src/lib/components/select.tsx | 158 + .../ui/shadcn/src/lib/components/sonner.tsx | 29 + .../ui/shadcn/src/lib/components/textarea.tsx | 22 + libs/shared/ui/shadcn/src/lib/hooks/.gitkeep | 0 libs/shared/ui/shadcn/src/lib/utils/cn.ts | 6 + libs/shared/ui/shadcn/tsconfig.json | 20 + libs/shared/ui/shadcn/tsconfig.lib.json | 23 + libs/shared/ui/shadcn/tsconfig.spec.json | 22 + libs/shared/ui/shadcn/vite.config.mts | 22 + libs/shared/util/payload-api/src/index.ts | 12 +- .../src/lib/create-request-init.ts | 87 - .../util/payload-api/src/lib/find-by-slug.ts | 14 +- .../util/payload-api/src/lib/get-shallow.ts | 22 +- .../payload-api/src/lib/invoke-request.ts | 99 - libs/shared/util/payload-api/src/lib/post.ts | 34 + .../src/lib/utils/create-request-init.ts | 121 + .../src/lib/{ => utils}/definitions.ts | 5 + .../src/lib/utils/invoke-request.ts | 158 + .../payload-types/src/lib/custom-types.ts | 23 + .../payload-types/src/lib/payload-types.ts | 580 +- package.json | 41 +- pnpm-lock.yaml | 1527 ++++- project.json | 24 + tsconfig.base.json | 2 + 98 files changed, 18740 insertions(+), 767 deletions(-) create mode 100644 apps/cms/src/migrations/20250325_141317_cod_282.json create mode 100644 apps/cms/src/migrations/20250325_141317_cod_282.ts create mode 100644 apps/cms/src/migrations/20250326_200110_cod_282_2.json create mode 100644 apps/cms/src/migrations/20250326_200110_cod_282_2.ts delete mode 100644 apps/cms/src/tailwind.css create mode 100644 apps/web/app/routes/_api.form-submission.tsx delete mode 100644 apps/web/app/utils/get-api-options.ts create mode 100644 apps/web/app/utils/get-payload-request-options.ts create mode 100644 components.json create mode 100644 libs/app-cms/ui/blocks/src/lib/form/form.block.ts create mode 100644 libs/app-cms/util/plugins/src/lib/get-plugins.ts delete mode 100644 libs/app-cms/util/plugins/src/lib/plugins.ts create mode 100644 libs/app-cms/util/plugins/src/lib/plugins/forms/customized-fields.ts create mode 100644 libs/app-cms/util/plugins/src/lib/plugins/forms/ensure-tenant.ts create mode 100644 libs/app-cms/util/plugins/src/lib/plugins/forms/tenant-access.ts create mode 100644 libs/app-cms/util/plugins/src/lib/plugins/get-forms-plugin.ts create mode 100644 libs/app-cms/util/plugins/src/lib/plugins/get-multi-tenant-plugin.ts create mode 100644 libs/app-cms/util/plugins/src/lib/plugins/get-s3-storage-plugin.ts create mode 100644 libs/app-cms/util/plugins/src/lib/plugins/get-seo-plugin.ts create mode 100644 libs/shared/ui/payload-components/README.md delete mode 100644 libs/shared/ui/payload-components/src/lib/RichText.tsx rename libs/shared/ui/payload-components/src/lib/{ => blocks}/CodeBlock.tsx (53%) rename libs/shared/ui/payload-components/src/lib/{ => blocks}/ContentBlock.tsx (61%) create mode 100644 libs/shared/ui/payload-components/src/lib/blocks/FormBlock.tsx rename libs/shared/ui/payload-components/src/lib/{ => blocks}/MediaBlock.tsx (61%) create mode 100644 libs/shared/ui/payload-components/src/lib/blocks/RichText.tsx create mode 100644 libs/shared/ui/payload-components/src/lib/form-items/Button.tsx create mode 100644 libs/shared/ui/payload-components/src/lib/form-items/Checkbox.tsx create mode 100644 libs/shared/ui/payload-components/src/lib/form-items/Input.tsx create mode 100644 libs/shared/ui/payload-components/src/lib/form-items/Select.tsx create mode 100644 libs/shared/ui/payload-components/src/lib/form-items/Textarea.tsx create mode 100644 libs/shared/ui/payload-components/src/lib/form-items/country-options.ts create mode 100644 libs/shared/ui/payload-components/src/lib/layout/ColSpan.tsx create mode 100644 libs/shared/ui/payload-components/src/lib/providers/PayloadProvider.tsx delete mode 100644 libs/shared/ui/payload-components/src/lib/render-blocks.type.ts create mode 100644 libs/shared/ui/shadcn/.babelrc create mode 100644 libs/shared/ui/shadcn/eslint.config.mjs create mode 100644 libs/shared/ui/shadcn/project.json create mode 100644 libs/shared/ui/shadcn/src/index.ts create mode 100644 libs/shared/ui/shadcn/src/lib/components/button.tsx create mode 100644 libs/shared/ui/shadcn/src/lib/components/card.tsx create mode 100644 libs/shared/ui/shadcn/src/lib/components/checkbox.tsx create mode 100644 libs/shared/ui/shadcn/src/lib/components/dialog.tsx create mode 100644 libs/shared/ui/shadcn/src/lib/components/dropdown-menu.tsx create mode 100644 libs/shared/ui/shadcn/src/lib/components/form.tsx create mode 100644 libs/shared/ui/shadcn/src/lib/components/input.tsx create mode 100644 libs/shared/ui/shadcn/src/lib/components/label.tsx create mode 100644 libs/shared/ui/shadcn/src/lib/components/menubar.tsx create mode 100644 libs/shared/ui/shadcn/src/lib/components/radio-group.tsx create mode 100644 libs/shared/ui/shadcn/src/lib/components/select.tsx create mode 100644 libs/shared/ui/shadcn/src/lib/components/sonner.tsx create mode 100644 libs/shared/ui/shadcn/src/lib/components/textarea.tsx create mode 100644 libs/shared/ui/shadcn/src/lib/hooks/.gitkeep create mode 100644 libs/shared/ui/shadcn/src/lib/utils/cn.ts create mode 100644 libs/shared/ui/shadcn/tsconfig.json create mode 100644 libs/shared/ui/shadcn/tsconfig.lib.json create mode 100644 libs/shared/ui/shadcn/tsconfig.spec.json create mode 100644 libs/shared/ui/shadcn/vite.config.mts delete mode 100644 libs/shared/util/payload-api/src/lib/create-request-init.ts delete mode 100644 libs/shared/util/payload-api/src/lib/invoke-request.ts create mode 100644 libs/shared/util/payload-api/src/lib/post.ts create mode 100644 libs/shared/util/payload-api/src/lib/utils/create-request-init.ts rename libs/shared/util/payload-api/src/lib/{ => utils}/definitions.ts (75%) create mode 100644 libs/shared/util/payload-api/src/lib/utils/invoke-request.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index b0a75918e..445e881bb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,7 +8,8 @@ "eslint.validate": ["json"], "files.associations": { ".*.*__tmpl__": "plaintext", - "*.css": "tailwindcss" + "*.css": "tailwindcss", + "*.scss": "tailwindcss" }, "jest.runMode": { "coverage": true, diff --git a/apps/cms/src/app/(frontend)/globals.css b/apps/cms/src/app/(frontend)/globals.css index f317d8006..2e0beffff 100644 --- a/apps/cms/src/app/(frontend)/globals.css +++ b/apps/cms/src/app/(frontend)/globals.css @@ -1,4 +1,6 @@ -@import '../../tailwind.css'; +@tailwind base; +@tailwind components; +@tailwind utilities; :root { --steel-blue: #588bae; diff --git a/apps/cms/src/app/(payload)/custom.scss b/apps/cms/src/app/(payload)/custom.scss index e69de29bb..d9712f7cd 100644 --- a/apps/cms/src/app/(payload)/custom.scss +++ b/apps/cms/src/app/(payload)/custom.scss @@ -0,0 +1,61 @@ +/** + * Do not import base directives here, it will break the payloadcms styles. + */ +@tailwind components; +@tailwind utilities; + +:root { + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + --primary: 240 5.9% 10%; + --primary-foreground: 0 0% 98%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 46.1%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --ring: 240 5.9% 10%; + --radius: 0.5rem; +} + +[data-theme='dark'] { + --background: 240 10% 3.9%; + --foreground: 0 0% 98%; + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 240 5.9% 10%; + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + --accent: 240 3.7% 15.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --ring: 240 4.9% 83.9%; +} + +/** +{ + @apply border-border; +} +body { + @apply bg-background text-foreground; + font-feature-settings: + 'rlig' 1, + 'calt' 1; +} */ diff --git a/apps/cms/src/collections/pages/pages.collection.ts b/apps/cms/src/collections/pages/pages.collection.ts index cf2752f13..cce6b6ae8 100644 --- a/apps/cms/src/collections/pages/pages.collection.ts +++ b/apps/cms/src/collections/pages/pages.collection.ts @@ -74,7 +74,7 @@ const pages: CollectionConfig<'pages'> = { name: 'layout', type: 'blocks', label: 'Layout builder', - blockReferences: ['content', 'media', 'code'], + blockReferences: ['content', 'form', 'media', 'code'], blocks: [], required: true, localized: true, diff --git a/apps/cms/src/components/Logo.client.tsx b/apps/cms/src/components/Logo.client.tsx index bddff425e..70b0868b2 100644 --- a/apps/cms/src/components/Logo.client.tsx +++ b/apps/cms/src/components/Logo.client.tsx @@ -1,8 +1,6 @@ 'use client'; import { CdwrCloud } from '@codeware/shared/ui/react-components'; -import '../tailwind.css'; - const Logo: React.FC = () => { return (
@@ -10,7 +8,7 @@ const Logo: React.FC = () => {
diff --git a/apps/cms/src/migrations/20250325_141317_cod_282.json b/apps/cms/src/migrations/20250325_141317_cod_282.json new file mode 100644 index 000000000..bf971384c --- /dev/null +++ b/apps/cms/src/migrations/20250325_141317_cod_282.json @@ -0,0 +1,5917 @@ +{ + "id": "f5f274a7-57af-415b-91b2-5ea6d95a6062", + "prevId": "00000000-0000-0000-0000-000000000000", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.categories": { + "name": "categories", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "categories_tenant_idx": { + "name": "categories_tenant_idx", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "categories_slug_idx": { + "name": "categories_slug_idx", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "categories_updated_at_idx": { + "name": "categories_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "categories_created_at_idx": { + "name": "categories_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "categories_tenant_id_tenants_id_fk": { + "name": "categories_tenant_id_tenants_id_fk", + "tableFrom": "categories", + "tableTo": "tenants", + "columnsFrom": ["tenant_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.categories_locales": { + "name": "categories_locales", + "schema": "", + "columns": { + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "categories_locales_locale_parent_id_unique": { + "name": "categories_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "categories_locales_parent_id_fk": { + "name": "categories_locales_parent_id_fk", + "tableFrom": "categories_locales", + "tableTo": "categories", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.media": { + "name": "media", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "alt": { + "name": "alt", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "prefix": { + "name": "prefix", + "type": "varchar", + "primaryKey": false, + "notNull": false, + "default": "'media'" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "url": { + "name": "url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "thumbnail_u_r_l": { + "name": "thumbnail_u_r_l", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "filename": { + "name": "filename", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "mime_type": { + "name": "mime_type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "filesize": { + "name": "filesize", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "width": { + "name": "width", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "height": { + "name": "height", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "focal_x": { + "name": "focal_x", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "focal_y": { + "name": "focal_y", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_thumbnail_url": { + "name": "sizes_thumbnail_url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_thumbnail_width": { + "name": "sizes_thumbnail_width", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_thumbnail_height": { + "name": "sizes_thumbnail_height", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_thumbnail_mime_type": { + "name": "sizes_thumbnail_mime_type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_thumbnail_filesize": { + "name": "sizes_thumbnail_filesize", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_thumbnail_filename": { + "name": "sizes_thumbnail_filename", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_square_url": { + "name": "sizes_square_url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_square_width": { + "name": "sizes_square_width", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_square_height": { + "name": "sizes_square_height", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_square_mime_type": { + "name": "sizes_square_mime_type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_square_filesize": { + "name": "sizes_square_filesize", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_square_filename": { + "name": "sizes_square_filename", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_small_url": { + "name": "sizes_small_url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_small_width": { + "name": "sizes_small_width", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_small_height": { + "name": "sizes_small_height", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_small_mime_type": { + "name": "sizes_small_mime_type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_small_filesize": { + "name": "sizes_small_filesize", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_small_filename": { + "name": "sizes_small_filename", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_medium_url": { + "name": "sizes_medium_url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_medium_width": { + "name": "sizes_medium_width", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_medium_height": { + "name": "sizes_medium_height", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_medium_mime_type": { + "name": "sizes_medium_mime_type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_medium_filesize": { + "name": "sizes_medium_filesize", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_medium_filename": { + "name": "sizes_medium_filename", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_large_url": { + "name": "sizes_large_url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_large_width": { + "name": "sizes_large_width", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_large_height": { + "name": "sizes_large_height", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_large_mime_type": { + "name": "sizes_large_mime_type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_large_filesize": { + "name": "sizes_large_filesize", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_large_filename": { + "name": "sizes_large_filename", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_xlarge_url": { + "name": "sizes_xlarge_url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_xlarge_width": { + "name": "sizes_xlarge_width", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_xlarge_height": { + "name": "sizes_xlarge_height", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_xlarge_mime_type": { + "name": "sizes_xlarge_mime_type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_xlarge_filesize": { + "name": "sizes_xlarge_filesize", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_xlarge_filename": { + "name": "sizes_xlarge_filename", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_og_url": { + "name": "sizes_og_url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_og_width": { + "name": "sizes_og_width", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_og_height": { + "name": "sizes_og_height", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_og_mime_type": { + "name": "sizes_og_mime_type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_og_filesize": { + "name": "sizes_og_filesize", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_og_filename": { + "name": "sizes_og_filename", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "media_tenant_idx": { + "name": "media_tenant_idx", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_updated_at_idx": { + "name": "media_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_created_at_idx": { + "name": "media_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_filename_idx": { + "name": "media_filename_idx", + "columns": [ + { + "expression": "filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_sizes_thumbnail_sizes_thumbnail_filename_idx": { + "name": "media_sizes_thumbnail_sizes_thumbnail_filename_idx", + "columns": [ + { + "expression": "sizes_thumbnail_filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_sizes_square_sizes_square_filename_idx": { + "name": "media_sizes_square_sizes_square_filename_idx", + "columns": [ + { + "expression": "sizes_square_filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_sizes_small_sizes_small_filename_idx": { + "name": "media_sizes_small_sizes_small_filename_idx", + "columns": [ + { + "expression": "sizes_small_filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_sizes_medium_sizes_medium_filename_idx": { + "name": "media_sizes_medium_sizes_medium_filename_idx", + "columns": [ + { + "expression": "sizes_medium_filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_sizes_large_sizes_large_filename_idx": { + "name": "media_sizes_large_sizes_large_filename_idx", + "columns": [ + { + "expression": "sizes_large_filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_sizes_xlarge_sizes_xlarge_filename_idx": { + "name": "media_sizes_xlarge_sizes_xlarge_filename_idx", + "columns": [ + { + "expression": "sizes_xlarge_filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_sizes_og_sizes_og_filename_idx": { + "name": "media_sizes_og_sizes_og_filename_idx", + "columns": [ + { + "expression": "sizes_og_filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "media_tenant_id_tenants_id_fk": { + "name": "media_tenant_id_tenants_id_fk", + "tableFrom": "media", + "tableTo": "tenants", + "columnsFrom": ["tenant_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.media_locales": { + "name": "media_locales", + "schema": "", + "columns": { + "caption": { + "name": "caption", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "media_locales_locale_parent_id_unique": { + "name": "media_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "media_locales_parent_id_fk": { + "name": "media_locales_parent_id_fk", + "tableFrom": "media_locales", + "tableTo": "media", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pages_blocks_content_columns": { + "name": "pages_blocks_content_columns", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "size": { + "name": "size", + "type": "enum_pages_blocks_content_columns_size", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'full'" + }, + "rich_text": { + "name": "rich_text", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "pages_blocks_content_columns_order_idx": { + "name": "pages_blocks_content_columns_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_content_columns_parent_id_idx": { + "name": "pages_blocks_content_columns_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_content_columns_locale_idx": { + "name": "pages_blocks_content_columns_locale_idx", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pages_blocks_content_columns_parent_id_fk": { + "name": "pages_blocks_content_columns_parent_id_fk", + "tableFrom": "pages_blocks_content_columns", + "tableTo": "pages_blocks_content", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pages_blocks_content": { + "name": "pages_blocks_content", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "pages_blocks_content_order_idx": { + "name": "pages_blocks_content_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_content_parent_id_idx": { + "name": "pages_blocks_content_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_content_path_idx": { + "name": "pages_blocks_content_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_content_locale_idx": { + "name": "pages_blocks_content_locale_idx", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pages_blocks_content_parent_id_fk": { + "name": "pages_blocks_content_parent_id_fk", + "tableFrom": "pages_blocks_content", + "tableTo": "pages", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pages_blocks_form": { + "name": "pages_blocks_form", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "form_id": { + "name": "form_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "enable_intro": { + "name": "enable_intro", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "intro_content": { + "name": "intro_content", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "pages_blocks_form_order_idx": { + "name": "pages_blocks_form_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_form_parent_id_idx": { + "name": "pages_blocks_form_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_form_path_idx": { + "name": "pages_blocks_form_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_form_locale_idx": { + "name": "pages_blocks_form_locale_idx", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_form_form_idx": { + "name": "pages_blocks_form_form_idx", + "columns": [ + { + "expression": "form_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pages_blocks_form_form_id_forms_id_fk": { + "name": "pages_blocks_form_form_id_forms_id_fk", + "tableFrom": "pages_blocks_form", + "tableTo": "forms", + "columnsFrom": ["form_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "pages_blocks_form_parent_id_fk": { + "name": "pages_blocks_form_parent_id_fk", + "tableFrom": "pages_blocks_form", + "tableTo": "pages", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pages_blocks_media": { + "name": "pages_blocks_media", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "media_id": { + "name": "media_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "pages_blocks_media_order_idx": { + "name": "pages_blocks_media_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_media_parent_id_idx": { + "name": "pages_blocks_media_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_media_path_idx": { + "name": "pages_blocks_media_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_media_locale_idx": { + "name": "pages_blocks_media_locale_idx", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_media_media_idx": { + "name": "pages_blocks_media_media_idx", + "columns": [ + { + "expression": "media_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pages_blocks_media_media_id_media_id_fk": { + "name": "pages_blocks_media_media_id_media_id_fk", + "tableFrom": "pages_blocks_media", + "tableTo": "media", + "columnsFrom": ["media_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "pages_blocks_media_parent_id_fk": { + "name": "pages_blocks_media_parent_id_fk", + "tableFrom": "pages_blocks_media", + "tableTo": "pages", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pages_blocks_code": { + "name": "pages_blocks_code", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "language": { + "name": "language", + "type": "enum_pages_blocks_code_language", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'ts'" + }, + "code": { + "name": "code", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "pages_blocks_code_order_idx": { + "name": "pages_blocks_code_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_code_parent_id_idx": { + "name": "pages_blocks_code_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_code_path_idx": { + "name": "pages_blocks_code_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_code_locale_idx": { + "name": "pages_blocks_code_locale_idx", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pages_blocks_code_parent_id_fk": { + "name": "pages_blocks_code_parent_id_fk", + "tableFrom": "pages_blocks_code", + "tableTo": "pages", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pages": { + "name": "pages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "published_at": { + "name": "published_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "pages_tenant_idx": { + "name": "pages_tenant_idx", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_slug_idx": { + "name": "pages_slug_idx", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_updated_at_idx": { + "name": "pages_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_created_at_idx": { + "name": "pages_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pages_tenant_id_tenants_id_fk": { + "name": "pages_tenant_id_tenants_id_fk", + "tableFrom": "pages", + "tableTo": "tenants", + "columnsFrom": ["tenant_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pages_locales": { + "name": "pages_locales", + "schema": "", + "columns": { + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "header": { + "name": "header", + "type": "varchar", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "meta_title": { + "name": "meta_title", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "meta_image_id": { + "name": "meta_image_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "meta_description": { + "name": "meta_description", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "pages_meta_meta_image_idx": { + "name": "pages_meta_meta_image_idx", + "columns": [ + { + "expression": "meta_image_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_locales_locale_parent_id_unique": { + "name": "pages_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pages_locales_meta_image_id_media_id_fk": { + "name": "pages_locales_meta_image_id_media_id_fk", + "tableFrom": "pages_locales", + "tableTo": "media", + "columnsFrom": ["meta_image_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "pages_locales_parent_id_fk": { + "name": "pages_locales_parent_id_fk", + "tableFrom": "pages_locales", + "tableTo": "pages", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.posts": { + "name": "posts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "hero_image_id": { + "name": "hero_image_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "published_at": { + "name": "published_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "posts_tenant_idx": { + "name": "posts_tenant_idx", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_hero_image_idx": { + "name": "posts_hero_image_idx", + "columns": [ + { + "expression": "hero_image_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_slug_idx": { + "name": "posts_slug_idx", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_updated_at_idx": { + "name": "posts_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_created_at_idx": { + "name": "posts_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "posts_tenant_id_tenants_id_fk": { + "name": "posts_tenant_id_tenants_id_fk", + "tableFrom": "posts", + "tableTo": "tenants", + "columnsFrom": ["tenant_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "posts_hero_image_id_media_id_fk": { + "name": "posts_hero_image_id_media_id_fk", + "tableFrom": "posts", + "tableTo": "media", + "columnsFrom": ["hero_image_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.posts_locales": { + "name": "posts_locales", + "schema": "", + "columns": { + "title": { + "name": "title", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "meta_title": { + "name": "meta_title", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "meta_image_id": { + "name": "meta_image_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "meta_description": { + "name": "meta_description", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "posts_meta_meta_image_idx": { + "name": "posts_meta_meta_image_idx", + "columns": [ + { + "expression": "meta_image_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_locales_locale_parent_id_unique": { + "name": "posts_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "posts_locales_meta_image_id_media_id_fk": { + "name": "posts_locales_meta_image_id_media_id_fk", + "tableFrom": "posts_locales", + "tableTo": "media", + "columnsFrom": ["meta_image_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "posts_locales_parent_id_fk": { + "name": "posts_locales_parent_id_fk", + "tableFrom": "posts_locales", + "tableTo": "posts", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.posts_rels": { + "name": "posts_rels", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "order": { + "name": "order", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "parent_id": { + "name": "parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "posts_id": { + "name": "posts_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "categories_id": { + "name": "categories_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "users_id": { + "name": "users_id", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "posts_rels_order_idx": { + "name": "posts_rels_order_idx", + "columns": [ + { + "expression": "order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_rels_parent_idx": { + "name": "posts_rels_parent_idx", + "columns": [ + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_rels_path_idx": { + "name": "posts_rels_path_idx", + "columns": [ + { + "expression": "path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_rels_posts_id_idx": { + "name": "posts_rels_posts_id_idx", + "columns": [ + { + "expression": "posts_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_rels_categories_id_idx": { + "name": "posts_rels_categories_id_idx", + "columns": [ + { + "expression": "categories_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_rels_users_id_idx": { + "name": "posts_rels_users_id_idx", + "columns": [ + { + "expression": "users_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "posts_rels_parent_fk": { + "name": "posts_rels_parent_fk", + "tableFrom": "posts_rels", + "tableTo": "posts", + "columnsFrom": ["parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "posts_rels_posts_fk": { + "name": "posts_rels_posts_fk", + "tableFrom": "posts_rels", + "tableTo": "posts", + "columnsFrom": ["posts_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "posts_rels_categories_fk": { + "name": "posts_rels_categories_fk", + "tableFrom": "posts_rels", + "tableTo": "categories", + "columnsFrom": ["categories_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "posts_rels_users_fk": { + "name": "posts_rels_users_fk", + "tableFrom": "posts_rels", + "tableTo": "users", + "columnsFrom": ["users_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.tenants_domains_page_types": { + "name": "tenants_domains_page_types", + "schema": "", + "columns": { + "order": { + "name": "order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "parent_id": { + "name": "parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "enum_tenants_domains_page_types", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + } + }, + "indexes": { + "tenants_domains_page_types_order_idx": { + "name": "tenants_domains_page_types_order_idx", + "columns": [ + { + "expression": "order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "tenants_domains_page_types_parent_idx": { + "name": "tenants_domains_page_types_parent_idx", + "columns": [ + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "tenants_domains_page_types_parent_fk": { + "name": "tenants_domains_page_types_parent_fk", + "tableFrom": "tenants_domains_page_types", + "tableTo": "tenants_domains", + "columnsFrom": ["parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.tenants_domains": { + "name": "tenants_domains", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "domain": { + "name": "domain", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "tenants_domains_order_idx": { + "name": "tenants_domains_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "tenants_domains_parent_id_idx": { + "name": "tenants_domains_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "tenants_domains_parent_id_fk": { + "name": "tenants_domains_parent_id_fk", + "tableFrom": "tenants_domains", + "tableTo": "tenants", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.tenants": { + "name": "tenants", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "enable_a_p_i_key": { + "name": "enable_a_p_i_key", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "api_key": { + "name": "api_key", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "api_key_index": { + "name": "api_key_index", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "tenants_slug_idx": { + "name": "tenants_slug_idx", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "tenants_updated_at_idx": { + "name": "tenants_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "tenants_created_at_idx": { + "name": "tenants_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.users_tenants": { + "name": "users_tenants", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "enum_users_tenants_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'user'" + } + }, + "indexes": { + "users_tenants_order_idx": { + "name": "users_tenants_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "users_tenants_parent_id_idx": { + "name": "users_tenants_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "users_tenants_tenant_idx": { + "name": "users_tenants_tenant_idx", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "users_tenants_tenant_id_tenants_id_fk": { + "name": "users_tenants_tenant_id_tenants_id_fk", + "tableFrom": "users_tenants", + "tableTo": "tenants", + "columnsFrom": ["tenant_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "users_tenants_parent_id_fk": { + "name": "users_tenants_parent_id_fk", + "tableFrom": "users_tenants", + "tableTo": "users", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "enum_users_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'user'" + }, + "description": { + "name": "description", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "email": { + "name": "email", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "reset_password_token": { + "name": "reset_password_token", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "reset_password_expiration": { + "name": "reset_password_expiration", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": false + }, + "salt": { + "name": "salt", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "hash": { + "name": "hash", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "login_attempts": { + "name": "login_attempts", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "lock_until": { + "name": "lock_until", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "users_updated_at_idx": { + "name": "users_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "users_created_at_idx": { + "name": "users_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "users_email_idx": { + "name": "users_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_checkbox": { + "name": "forms_blocks_checkbox", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "width": { + "name": "width", + "type": "enum_forms_blocks_checkbox_width", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'12'" + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "default_value": { + "name": "default_value", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_blocks_checkbox_order_idx": { + "name": "forms_blocks_checkbox_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_checkbox_parent_id_idx": { + "name": "forms_blocks_checkbox_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_checkbox_path_idx": { + "name": "forms_blocks_checkbox_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_checkbox_parent_id_fk": { + "name": "forms_blocks_checkbox_parent_id_fk", + "tableFrom": "forms_blocks_checkbox", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_checkbox_locales": { + "name": "forms_blocks_checkbox_locales", + "schema": "", + "columns": { + "label": { + "name": "label", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_checkbox_locales_locale_parent_id_unique": { + "name": "forms_blocks_checkbox_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_checkbox_locales_parent_id_fk": { + "name": "forms_blocks_checkbox_locales_parent_id_fk", + "tableFrom": "forms_blocks_checkbox_locales", + "tableTo": "forms_blocks_checkbox", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_country": { + "name": "forms_blocks_country", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "width": { + "name": "width", + "type": "enum_forms_blocks_country_width", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'12'" + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_blocks_country_order_idx": { + "name": "forms_blocks_country_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_country_parent_id_idx": { + "name": "forms_blocks_country_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_country_path_idx": { + "name": "forms_blocks_country_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_country_parent_id_fk": { + "name": "forms_blocks_country_parent_id_fk", + "tableFrom": "forms_blocks_country", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_country_locales": { + "name": "forms_blocks_country_locales", + "schema": "", + "columns": { + "label": { + "name": "label", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "placeholder": { + "name": "placeholder", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_country_locales_locale_parent_id_unique": { + "name": "forms_blocks_country_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_country_locales_parent_id_fk": { + "name": "forms_blocks_country_locales_parent_id_fk", + "tableFrom": "forms_blocks_country_locales", + "tableTo": "forms_blocks_country", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_email": { + "name": "forms_blocks_email", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "width": { + "name": "width", + "type": "enum_forms_blocks_email_width", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'12'" + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_blocks_email_order_idx": { + "name": "forms_blocks_email_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_email_parent_id_idx": { + "name": "forms_blocks_email_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_email_path_idx": { + "name": "forms_blocks_email_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_email_parent_id_fk": { + "name": "forms_blocks_email_parent_id_fk", + "tableFrom": "forms_blocks_email", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_email_locales": { + "name": "forms_blocks_email_locales", + "schema": "", + "columns": { + "label": { + "name": "label", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "placeholder": { + "name": "placeholder", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_email_locales_locale_parent_id_unique": { + "name": "forms_blocks_email_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_email_locales_parent_id_fk": { + "name": "forms_blocks_email_locales_parent_id_fk", + "tableFrom": "forms_blocks_email_locales", + "tableTo": "forms_blocks_email", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_message": { + "name": "forms_blocks_message", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_blocks_message_order_idx": { + "name": "forms_blocks_message_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_message_parent_id_idx": { + "name": "forms_blocks_message_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_message_path_idx": { + "name": "forms_blocks_message_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_message_parent_id_fk": { + "name": "forms_blocks_message_parent_id_fk", + "tableFrom": "forms_blocks_message", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_message_locales": { + "name": "forms_blocks_message_locales", + "schema": "", + "columns": { + "message": { + "name": "message", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_message_locales_locale_parent_id_unique": { + "name": "forms_blocks_message_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_message_locales_parent_id_fk": { + "name": "forms_blocks_message_locales_parent_id_fk", + "tableFrom": "forms_blocks_message_locales", + "tableTo": "forms_blocks_message", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_number": { + "name": "forms_blocks_number", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "width": { + "name": "width", + "type": "enum_forms_blocks_number_width", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'12'" + }, + "default_value": { + "name": "default_value", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_blocks_number_order_idx": { + "name": "forms_blocks_number_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_number_parent_id_idx": { + "name": "forms_blocks_number_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_number_path_idx": { + "name": "forms_blocks_number_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_number_parent_id_fk": { + "name": "forms_blocks_number_parent_id_fk", + "tableFrom": "forms_blocks_number", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_number_locales": { + "name": "forms_blocks_number_locales", + "schema": "", + "columns": { + "label": { + "name": "label", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "placeholder": { + "name": "placeholder", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_number_locales_locale_parent_id_unique": { + "name": "forms_blocks_number_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_number_locales_parent_id_fk": { + "name": "forms_blocks_number_locales_parent_id_fk", + "tableFrom": "forms_blocks_number_locales", + "tableTo": "forms_blocks_number", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_select_options": { + "name": "forms_blocks_select_options", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "value": { + "name": "value", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_select_options_order_idx": { + "name": "forms_blocks_select_options_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_select_options_parent_id_idx": { + "name": "forms_blocks_select_options_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_select_options_parent_id_fk": { + "name": "forms_blocks_select_options_parent_id_fk", + "tableFrom": "forms_blocks_select_options", + "tableTo": "forms_blocks_select", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_select_options_locales": { + "name": "forms_blocks_select_options_locales", + "schema": "", + "columns": { + "label": { + "name": "label", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_select_options_locales_locale_parent_id_unique": { + "name": "forms_blocks_select_options_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_select_options_locales_parent_id_fk": { + "name": "forms_blocks_select_options_locales_parent_id_fk", + "tableFrom": "forms_blocks_select_options_locales", + "tableTo": "forms_blocks_select_options", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_select": { + "name": "forms_blocks_select", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "width": { + "name": "width", + "type": "enum_forms_blocks_select_width", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'12'" + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_blocks_select_order_idx": { + "name": "forms_blocks_select_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_select_parent_id_idx": { + "name": "forms_blocks_select_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_select_path_idx": { + "name": "forms_blocks_select_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_select_parent_id_fk": { + "name": "forms_blocks_select_parent_id_fk", + "tableFrom": "forms_blocks_select", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_select_locales": { + "name": "forms_blocks_select_locales", + "schema": "", + "columns": { + "label": { + "name": "label", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "placeholder": { + "name": "placeholder", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "default_value": { + "name": "default_value", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_select_locales_locale_parent_id_unique": { + "name": "forms_blocks_select_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_select_locales_parent_id_fk": { + "name": "forms_blocks_select_locales_parent_id_fk", + "tableFrom": "forms_blocks_select_locales", + "tableTo": "forms_blocks_select", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_text": { + "name": "forms_blocks_text", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "width": { + "name": "width", + "type": "enum_forms_blocks_text_width", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'12'" + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_blocks_text_order_idx": { + "name": "forms_blocks_text_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_text_parent_id_idx": { + "name": "forms_blocks_text_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_text_path_idx": { + "name": "forms_blocks_text_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_text_parent_id_fk": { + "name": "forms_blocks_text_parent_id_fk", + "tableFrom": "forms_blocks_text", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_text_locales": { + "name": "forms_blocks_text_locales", + "schema": "", + "columns": { + "label": { + "name": "label", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "placeholder": { + "name": "placeholder", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "default_value": { + "name": "default_value", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_text_locales_locale_parent_id_unique": { + "name": "forms_blocks_text_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_text_locales_parent_id_fk": { + "name": "forms_blocks_text_locales_parent_id_fk", + "tableFrom": "forms_blocks_text_locales", + "tableTo": "forms_blocks_text", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_textarea": { + "name": "forms_blocks_textarea", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "width": { + "name": "width", + "type": "enum_forms_blocks_textarea_width", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'12'" + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_blocks_textarea_order_idx": { + "name": "forms_blocks_textarea_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_textarea_parent_id_idx": { + "name": "forms_blocks_textarea_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_textarea_path_idx": { + "name": "forms_blocks_textarea_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_textarea_parent_id_fk": { + "name": "forms_blocks_textarea_parent_id_fk", + "tableFrom": "forms_blocks_textarea", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_textarea_locales": { + "name": "forms_blocks_textarea_locales", + "schema": "", + "columns": { + "label": { + "name": "label", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "placeholder": { + "name": "placeholder", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "default_value": { + "name": "default_value", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_textarea_locales_locale_parent_id_unique": { + "name": "forms_blocks_textarea_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_textarea_locales_parent_id_fk": { + "name": "forms_blocks_textarea_locales_parent_id_fk", + "tableFrom": "forms_blocks_textarea_locales", + "tableTo": "forms_blocks_textarea", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_emails": { + "name": "forms_emails", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "email_to": { + "name": "email_to", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "cc": { + "name": "cc", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "bcc": { + "name": "bcc", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "reply_to": { + "name": "reply_to", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "email_from": { + "name": "email_from", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_emails_order_idx": { + "name": "forms_emails_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_emails_parent_id_idx": { + "name": "forms_emails_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_emails_parent_id_fk": { + "name": "forms_emails_parent_id_fk", + "tableFrom": "forms_emails", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_emails_locales": { + "name": "forms_emails_locales", + "schema": "", + "columns": { + "subject": { + "name": "subject", + "type": "varchar", + "primaryKey": false, + "notNull": true, + "default": "'You''''ve received a new message.'" + }, + "message": { + "name": "message", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_emails_locales_locale_parent_id_unique": { + "name": "forms_emails_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_emails_locales_parent_id_fk": { + "name": "forms_emails_locales_parent_id_fk", + "tableFrom": "forms_emails_locales", + "tableTo": "forms_emails", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms": { + "name": "forms", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "confirmation_type": { + "name": "confirmation_type", + "type": "enum_forms_confirmation_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'message'" + }, + "redirect_type": { + "name": "redirect_type", + "type": "enum_forms_redirect_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'reference'" + }, + "redirect_url": { + "name": "redirect_url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "forms_tenant_idx": { + "name": "forms_tenant_idx", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_updated_at_idx": { + "name": "forms_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_created_at_idx": { + "name": "forms_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_tenant_id_tenants_id_fk": { + "name": "forms_tenant_id_tenants_id_fk", + "tableFrom": "forms", + "tableTo": "tenants", + "columnsFrom": ["tenant_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_locales": { + "name": "forms_locales", + "schema": "", + "columns": { + "submit_button_label": { + "name": "submit_button_label", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "confirmation_message": { + "name": "confirmation_message", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_locales_locale_parent_id_unique": { + "name": "forms_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_locales_parent_id_fk": { + "name": "forms_locales_parent_id_fk", + "tableFrom": "forms_locales", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_rels": { + "name": "forms_rels", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "order": { + "name": "order", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "parent_id": { + "name": "parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "pages_id": { + "name": "pages_id", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_rels_order_idx": { + "name": "forms_rels_order_idx", + "columns": [ + { + "expression": "order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_rels_parent_idx": { + "name": "forms_rels_parent_idx", + "columns": [ + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_rels_path_idx": { + "name": "forms_rels_path_idx", + "columns": [ + { + "expression": "path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_rels_pages_id_idx": { + "name": "forms_rels_pages_id_idx", + "columns": [ + { + "expression": "pages_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_rels_parent_fk": { + "name": "forms_rels_parent_fk", + "tableFrom": "forms_rels", + "tableTo": "forms", + "columnsFrom": ["parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "forms_rels_pages_fk": { + "name": "forms_rels_pages_fk", + "tableFrom": "forms_rels", + "tableTo": "pages", + "columnsFrom": ["pages_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.form_submissions_submission_data": { + "name": "form_submissions_submission_data", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "field": { + "name": "field", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "form_submissions_submission_data_order_idx": { + "name": "form_submissions_submission_data_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "form_submissions_submission_data_parent_id_idx": { + "name": "form_submissions_submission_data_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "form_submissions_submission_data_parent_id_fk": { + "name": "form_submissions_submission_data_parent_id_fk", + "tableFrom": "form_submissions_submission_data", + "tableTo": "form_submissions", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.form_submissions": { + "name": "form_submissions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "form_id": { + "name": "form_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "form_submissions_form_idx": { + "name": "form_submissions_form_idx", + "columns": [ + { + "expression": "form_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "form_submissions_updated_at_idx": { + "name": "form_submissions_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "form_submissions_created_at_idx": { + "name": "form_submissions_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "form_submissions_form_id_forms_id_fk": { + "name": "form_submissions_form_id_forms_id_fk", + "tableFrom": "form_submissions", + "tableTo": "forms", + "columnsFrom": ["form_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.payload_locked_documents": { + "name": "payload_locked_documents", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "global_slug": { + "name": "global_slug", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "payload_locked_documents_global_slug_idx": { + "name": "payload_locked_documents_global_slug_idx", + "columns": [ + { + "expression": "global_slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_updated_at_idx": { + "name": "payload_locked_documents_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_created_at_idx": { + "name": "payload_locked_documents_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.payload_locked_documents_rels": { + "name": "payload_locked_documents_rels", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "order": { + "name": "order", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "parent_id": { + "name": "parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "categories_id": { + "name": "categories_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "media_id": { + "name": "media_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "pages_id": { + "name": "pages_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "posts_id": { + "name": "posts_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "tenants_id": { + "name": "tenants_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "users_id": { + "name": "users_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "forms_id": { + "name": "forms_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "form_submissions_id": { + "name": "form_submissions_id", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "payload_locked_documents_rels_order_idx": { + "name": "payload_locked_documents_rels_order_idx", + "columns": [ + { + "expression": "order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_parent_idx": { + "name": "payload_locked_documents_rels_parent_idx", + "columns": [ + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_path_idx": { + "name": "payload_locked_documents_rels_path_idx", + "columns": [ + { + "expression": "path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_categories_id_idx": { + "name": "payload_locked_documents_rels_categories_id_idx", + "columns": [ + { + "expression": "categories_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_media_id_idx": { + "name": "payload_locked_documents_rels_media_id_idx", + "columns": [ + { + "expression": "media_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_pages_id_idx": { + "name": "payload_locked_documents_rels_pages_id_idx", + "columns": [ + { + "expression": "pages_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_posts_id_idx": { + "name": "payload_locked_documents_rels_posts_id_idx", + "columns": [ + { + "expression": "posts_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_tenants_id_idx": { + "name": "payload_locked_documents_rels_tenants_id_idx", + "columns": [ + { + "expression": "tenants_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_users_id_idx": { + "name": "payload_locked_documents_rels_users_id_idx", + "columns": [ + { + "expression": "users_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_forms_id_idx": { + "name": "payload_locked_documents_rels_forms_id_idx", + "columns": [ + { + "expression": "forms_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_form_submissions_id_idx": { + "name": "payload_locked_documents_rels_form_submissions_id_idx", + "columns": [ + { + "expression": "form_submissions_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "payload_locked_documents_rels_parent_fk": { + "name": "payload_locked_documents_rels_parent_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "payload_locked_documents", + "columnsFrom": ["parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_locked_documents_rels_categories_fk": { + "name": "payload_locked_documents_rels_categories_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "categories", + "columnsFrom": ["categories_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_locked_documents_rels_media_fk": { + "name": "payload_locked_documents_rels_media_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "media", + "columnsFrom": ["media_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_locked_documents_rels_pages_fk": { + "name": "payload_locked_documents_rels_pages_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "pages", + "columnsFrom": ["pages_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_locked_documents_rels_posts_fk": { + "name": "payload_locked_documents_rels_posts_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "posts", + "columnsFrom": ["posts_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_locked_documents_rels_tenants_fk": { + "name": "payload_locked_documents_rels_tenants_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "tenants", + "columnsFrom": ["tenants_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_locked_documents_rels_users_fk": { + "name": "payload_locked_documents_rels_users_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "users", + "columnsFrom": ["users_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_locked_documents_rels_forms_fk": { + "name": "payload_locked_documents_rels_forms_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "forms", + "columnsFrom": ["forms_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_locked_documents_rels_form_submissions_fk": { + "name": "payload_locked_documents_rels_form_submissions_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "form_submissions", + "columnsFrom": ["form_submissions_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.payload_preferences": { + "name": "payload_preferences", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "key": { + "name": "key", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "value": { + "name": "value", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "payload_preferences_key_idx": { + "name": "payload_preferences_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_preferences_updated_at_idx": { + "name": "payload_preferences_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_preferences_created_at_idx": { + "name": "payload_preferences_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.payload_preferences_rels": { + "name": "payload_preferences_rels", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "order": { + "name": "order", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "parent_id": { + "name": "parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "tenants_id": { + "name": "tenants_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "users_id": { + "name": "users_id", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "payload_preferences_rels_order_idx": { + "name": "payload_preferences_rels_order_idx", + "columns": [ + { + "expression": "order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_preferences_rels_parent_idx": { + "name": "payload_preferences_rels_parent_idx", + "columns": [ + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_preferences_rels_path_idx": { + "name": "payload_preferences_rels_path_idx", + "columns": [ + { + "expression": "path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_preferences_rels_tenants_id_idx": { + "name": "payload_preferences_rels_tenants_id_idx", + "columns": [ + { + "expression": "tenants_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_preferences_rels_users_id_idx": { + "name": "payload_preferences_rels_users_id_idx", + "columns": [ + { + "expression": "users_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "payload_preferences_rels_parent_fk": { + "name": "payload_preferences_rels_parent_fk", + "tableFrom": "payload_preferences_rels", + "tableTo": "payload_preferences", + "columnsFrom": ["parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_preferences_rels_tenants_fk": { + "name": "payload_preferences_rels_tenants_fk", + "tableFrom": "payload_preferences_rels", + "tableTo": "tenants", + "columnsFrom": ["tenants_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_preferences_rels_users_fk": { + "name": "payload_preferences_rels_users_fk", + "tableFrom": "payload_preferences_rels", + "tableTo": "users", + "columnsFrom": ["users_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.payload_migrations": { + "name": "payload_migrations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "batch": { + "name": "batch", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "payload_migrations_updated_at_idx": { + "name": "payload_migrations_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_migrations_created_at_idx": { + "name": "payload_migrations_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public._locales": { + "name": "_locales", + "schema": "public", + "values": ["en", "sv"] + }, + "public.enum_pages_blocks_content_columns_size": { + "name": "enum_pages_blocks_content_columns_size", + "schema": "public", + "values": ["one-third", "half", "two-thirds", "full"] + }, + "public.enum_pages_blocks_code_language": { + "name": "enum_pages_blocks_code_language", + "schema": "public", + "values": ["ts", "plaintext", "tsx", "js", "jsx"] + }, + "public.enum_tenants_domains_page_types": { + "name": "enum_tenants_domains_page_types", + "schema": "public", + "values": ["cms", "client", "disabled"] + }, + "public.enum_users_tenants_role": { + "name": "enum_users_tenants_role", + "schema": "public", + "values": ["user", "admin"] + }, + "public.enum_users_role": { + "name": "enum_users_role", + "schema": "public", + "values": ["user", "system-user"] + }, + "public.enum_forms_blocks_checkbox_width": { + "name": "enum_forms_blocks_checkbox_width", + "schema": "public", + "values": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] + }, + "public.enum_forms_blocks_country_width": { + "name": "enum_forms_blocks_country_width", + "schema": "public", + "values": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] + }, + "public.enum_forms_blocks_email_width": { + "name": "enum_forms_blocks_email_width", + "schema": "public", + "values": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] + }, + "public.enum_forms_blocks_number_width": { + "name": "enum_forms_blocks_number_width", + "schema": "public", + "values": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] + }, + "public.enum_forms_blocks_select_width": { + "name": "enum_forms_blocks_select_width", + "schema": "public", + "values": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] + }, + "public.enum_forms_blocks_text_width": { + "name": "enum_forms_blocks_text_width", + "schema": "public", + "values": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] + }, + "public.enum_forms_blocks_textarea_width": { + "name": "enum_forms_blocks_textarea_width", + "schema": "public", + "values": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] + }, + "public.enum_forms_confirmation_type": { + "name": "enum_forms_confirmation_type", + "schema": "public", + "values": ["message", "redirect"] + }, + "public.enum_forms_redirect_type": { + "name": "enum_forms_redirect_type", + "schema": "public", + "values": ["reference", "custom"] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} diff --git a/apps/cms/src/migrations/20250325_141317_cod_282.ts b/apps/cms/src/migrations/20250325_141317_cod_282.ts new file mode 100644 index 000000000..360bdd81c --- /dev/null +++ b/apps/cms/src/migrations/20250325_141317_cod_282.ts @@ -0,0 +1,570 @@ +import { MigrateDownArgs, MigrateUpArgs, sql } from '@payloadcms/db-postgres'; + +export async function up({ db, payload, req }: MigrateUpArgs): Promise { + await db.execute(sql` + CREATE TYPE "public"."enum_forms_blocks_checkbox_width" AS ENUM('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'); + CREATE TYPE "public"."enum_forms_blocks_country_width" AS ENUM('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'); + CREATE TYPE "public"."enum_forms_blocks_email_width" AS ENUM('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'); + CREATE TYPE "public"."enum_forms_blocks_number_width" AS ENUM('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'); + CREATE TYPE "public"."enum_forms_blocks_select_width" AS ENUM('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'); + CREATE TYPE "public"."enum_forms_blocks_text_width" AS ENUM('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'); + CREATE TYPE "public"."enum_forms_blocks_textarea_width" AS ENUM('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'); + CREATE TYPE "public"."enum_forms_confirmation_type" AS ENUM('message', 'redirect'); + CREATE TYPE "public"."enum_forms_redirect_type" AS ENUM('reference', 'custom'); + CREATE TABLE IF NOT EXISTS "pages_blocks_form" ( + "_order" integer NOT NULL, + "_parent_id" integer NOT NULL, + "_path" text NOT NULL, + "_locale" "_locales" NOT NULL, + "id" varchar PRIMARY KEY NOT NULL, + "form_id" integer NOT NULL, + "enable_intro" boolean, + "intro_content" jsonb, + "block_name" varchar + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_checkbox" ( + "_order" integer NOT NULL, + "_parent_id" integer NOT NULL, + "_path" text NOT NULL, + "id" varchar PRIMARY KEY NOT NULL, + "name" varchar NOT NULL, + "width" "enum_forms_blocks_checkbox_width" DEFAULT '12', + "required" boolean, + "default_value" boolean, + "block_name" varchar + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_checkbox_locales" ( + "label" varchar, + "id" serial PRIMARY KEY NOT NULL, + "_locale" "_locales" NOT NULL, + "_parent_id" varchar NOT NULL + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_country" ( + "_order" integer NOT NULL, + "_parent_id" integer NOT NULL, + "_path" text NOT NULL, + "id" varchar PRIMARY KEY NOT NULL, + "name" varchar NOT NULL, + "width" "enum_forms_blocks_country_width" DEFAULT '12', + "required" boolean, + "block_name" varchar + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_country_locales" ( + "label" varchar, + "placeholder" varchar, + "id" serial PRIMARY KEY NOT NULL, + "_locale" "_locales" NOT NULL, + "_parent_id" varchar NOT NULL + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_email" ( + "_order" integer NOT NULL, + "_parent_id" integer NOT NULL, + "_path" text NOT NULL, + "id" varchar PRIMARY KEY NOT NULL, + "name" varchar NOT NULL, + "width" "enum_forms_blocks_email_width" DEFAULT '12', + "required" boolean, + "block_name" varchar + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_email_locales" ( + "label" varchar, + "placeholder" varchar, + "id" serial PRIMARY KEY NOT NULL, + "_locale" "_locales" NOT NULL, + "_parent_id" varchar NOT NULL + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_message" ( + "_order" integer NOT NULL, + "_parent_id" integer NOT NULL, + "_path" text NOT NULL, + "id" varchar PRIMARY KEY NOT NULL, + "block_name" varchar + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_message_locales" ( + "message" jsonb, + "id" serial PRIMARY KEY NOT NULL, + "_locale" "_locales" NOT NULL, + "_parent_id" varchar NOT NULL + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_number" ( + "_order" integer NOT NULL, + "_parent_id" integer NOT NULL, + "_path" text NOT NULL, + "id" varchar PRIMARY KEY NOT NULL, + "name" varchar NOT NULL, + "width" "enum_forms_blocks_number_width" DEFAULT '12', + "default_value" numeric, + "required" boolean, + "block_name" varchar + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_number_locales" ( + "label" varchar, + "placeholder" varchar, + "id" serial PRIMARY KEY NOT NULL, + "_locale" "_locales" NOT NULL, + "_parent_id" varchar NOT NULL + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_select_options" ( + "_order" integer NOT NULL, + "_parent_id" varchar NOT NULL, + "id" varchar PRIMARY KEY NOT NULL, + "value" varchar NOT NULL + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_select_options_locales" ( + "label" varchar NOT NULL, + "id" serial PRIMARY KEY NOT NULL, + "_locale" "_locales" NOT NULL, + "_parent_id" varchar NOT NULL + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_select" ( + "_order" integer NOT NULL, + "_parent_id" integer NOT NULL, + "_path" text NOT NULL, + "id" varchar PRIMARY KEY NOT NULL, + "name" varchar NOT NULL, + "width" "enum_forms_blocks_select_width" DEFAULT '12', + "required" boolean, + "block_name" varchar + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_select_locales" ( + "label" varchar, + "placeholder" varchar, + "default_value" varchar, + "id" serial PRIMARY KEY NOT NULL, + "_locale" "_locales" NOT NULL, + "_parent_id" varchar NOT NULL + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_text" ( + "_order" integer NOT NULL, + "_parent_id" integer NOT NULL, + "_path" text NOT NULL, + "id" varchar PRIMARY KEY NOT NULL, + "name" varchar NOT NULL, + "width" "enum_forms_blocks_text_width" DEFAULT '12', + "required" boolean, + "block_name" varchar + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_text_locales" ( + "label" varchar, + "placeholder" varchar, + "default_value" varchar, + "id" serial PRIMARY KEY NOT NULL, + "_locale" "_locales" NOT NULL, + "_parent_id" varchar NOT NULL + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_textarea" ( + "_order" integer NOT NULL, + "_parent_id" integer NOT NULL, + "_path" text NOT NULL, + "id" varchar PRIMARY KEY NOT NULL, + "name" varchar NOT NULL, + "width" "enum_forms_blocks_textarea_width" DEFAULT '12', + "required" boolean, + "block_name" varchar + ); + + CREATE TABLE IF NOT EXISTS "forms_blocks_textarea_locales" ( + "label" varchar, + "placeholder" varchar, + "default_value" varchar, + "id" serial PRIMARY KEY NOT NULL, + "_locale" "_locales" NOT NULL, + "_parent_id" varchar NOT NULL + ); + + CREATE TABLE IF NOT EXISTS "forms_emails" ( + "_order" integer NOT NULL, + "_parent_id" integer NOT NULL, + "id" varchar PRIMARY KEY NOT NULL, + "email_to" varchar, + "cc" varchar, + "bcc" varchar, + "reply_to" varchar, + "email_from" varchar + ); + + CREATE TABLE IF NOT EXISTS "forms_emails_locales" ( + "subject" varchar DEFAULT 'You''''ve received a new message.' NOT NULL, + "message" jsonb, + "id" serial PRIMARY KEY NOT NULL, + "_locale" "_locales" NOT NULL, + "_parent_id" varchar NOT NULL + ); + + CREATE TABLE IF NOT EXISTS "forms" ( + "id" serial PRIMARY KEY NOT NULL, + "tenant_id" integer, + "title" varchar NOT NULL, + "confirmation_type" "enum_forms_confirmation_type" DEFAULT 'message', + "redirect_type" "enum_forms_redirect_type" DEFAULT 'reference', + "redirect_url" varchar, + "updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL, + "created_at" timestamp(3) with time zone DEFAULT now() NOT NULL + ); + + CREATE TABLE IF NOT EXISTS "forms_locales" ( + "submit_button_label" varchar, + "confirmation_message" jsonb, + "id" serial PRIMARY KEY NOT NULL, + "_locale" "_locales" NOT NULL, + "_parent_id" integer NOT NULL + ); + + CREATE TABLE IF NOT EXISTS "forms_rels" ( + "id" serial PRIMARY KEY NOT NULL, + "order" integer, + "parent_id" integer NOT NULL, + "path" varchar NOT NULL, + "pages_id" integer + ); + + CREATE TABLE IF NOT EXISTS "form_submissions_submission_data" ( + "_order" integer NOT NULL, + "_parent_id" integer NOT NULL, + "id" varchar PRIMARY KEY NOT NULL, + "field" varchar NOT NULL, + "value" varchar NOT NULL + ); + + CREATE TABLE IF NOT EXISTS "form_submissions" ( + "id" serial PRIMARY KEY NOT NULL, + "form_id" integer NOT NULL, + "updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL, + "created_at" timestamp(3) with time zone DEFAULT now() NOT NULL + ); + + ALTER TABLE "payload_locked_documents_rels" ADD COLUMN "forms_id" integer; + ALTER TABLE "payload_locked_documents_rels" ADD COLUMN "form_submissions_id" integer; + DO $$ BEGIN + ALTER TABLE "pages_blocks_form" ADD CONSTRAINT "pages_blocks_form_form_id_forms_id_fk" FOREIGN KEY ("form_id") REFERENCES "public"."forms"("id") ON DELETE set null ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "pages_blocks_form" ADD CONSTRAINT "pages_blocks_form_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_checkbox" ADD CONSTRAINT "forms_blocks_checkbox_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_checkbox_locales" ADD CONSTRAINT "forms_blocks_checkbox_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms_blocks_checkbox"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_country" ADD CONSTRAINT "forms_blocks_country_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_country_locales" ADD CONSTRAINT "forms_blocks_country_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms_blocks_country"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_email" ADD CONSTRAINT "forms_blocks_email_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_email_locales" ADD CONSTRAINT "forms_blocks_email_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms_blocks_email"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_message" ADD CONSTRAINT "forms_blocks_message_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_message_locales" ADD CONSTRAINT "forms_blocks_message_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms_blocks_message"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_number" ADD CONSTRAINT "forms_blocks_number_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_number_locales" ADD CONSTRAINT "forms_blocks_number_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms_blocks_number"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_select_options" ADD CONSTRAINT "forms_blocks_select_options_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms_blocks_select"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_select_options_locales" ADD CONSTRAINT "forms_blocks_select_options_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms_blocks_select_options"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_select" ADD CONSTRAINT "forms_blocks_select_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_select_locales" ADD CONSTRAINT "forms_blocks_select_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms_blocks_select"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_text" ADD CONSTRAINT "forms_blocks_text_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_text_locales" ADD CONSTRAINT "forms_blocks_text_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms_blocks_text"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_textarea" ADD CONSTRAINT "forms_blocks_textarea_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_blocks_textarea_locales" ADD CONSTRAINT "forms_blocks_textarea_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms_blocks_textarea"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_emails" ADD CONSTRAINT "forms_emails_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_emails_locales" ADD CONSTRAINT "forms_emails_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms_emails"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms" ADD CONSTRAINT "forms_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE set null ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_locales" ADD CONSTRAINT "forms_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."forms"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_rels" ADD CONSTRAINT "forms_rels_parent_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."forms"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "forms_rels" ADD CONSTRAINT "forms_rels_pages_fk" FOREIGN KEY ("pages_id") REFERENCES "public"."pages"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "form_submissions_submission_data" ADD CONSTRAINT "form_submissions_submission_data_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."form_submissions"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "form_submissions" ADD CONSTRAINT "form_submissions_form_id_forms_id_fk" FOREIGN KEY ("form_id") REFERENCES "public"."forms"("id") ON DELETE set null ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + CREATE INDEX IF NOT EXISTS "pages_blocks_form_order_idx" ON "pages_blocks_form" USING btree ("_order"); + CREATE INDEX IF NOT EXISTS "pages_blocks_form_parent_id_idx" ON "pages_blocks_form" USING btree ("_parent_id"); + CREATE INDEX IF NOT EXISTS "pages_blocks_form_path_idx" ON "pages_blocks_form" USING btree ("_path"); + CREATE INDEX IF NOT EXISTS "pages_blocks_form_locale_idx" ON "pages_blocks_form" USING btree ("_locale"); + CREATE INDEX IF NOT EXISTS "pages_blocks_form_form_idx" ON "pages_blocks_form" USING btree ("form_id"); + CREATE INDEX IF NOT EXISTS "forms_blocks_checkbox_order_idx" ON "forms_blocks_checkbox" USING btree ("_order"); + CREATE INDEX IF NOT EXISTS "forms_blocks_checkbox_parent_id_idx" ON "forms_blocks_checkbox" USING btree ("_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_blocks_checkbox_path_idx" ON "forms_blocks_checkbox" USING btree ("_path"); + CREATE UNIQUE INDEX IF NOT EXISTS "forms_blocks_checkbox_locales_locale_parent_id_unique" ON "forms_blocks_checkbox_locales" USING btree ("_locale","_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_blocks_country_order_idx" ON "forms_blocks_country" USING btree ("_order"); + CREATE INDEX IF NOT EXISTS "forms_blocks_country_parent_id_idx" ON "forms_blocks_country" USING btree ("_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_blocks_country_path_idx" ON "forms_blocks_country" USING btree ("_path"); + CREATE UNIQUE INDEX IF NOT EXISTS "forms_blocks_country_locales_locale_parent_id_unique" ON "forms_blocks_country_locales" USING btree ("_locale","_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_blocks_email_order_idx" ON "forms_blocks_email" USING btree ("_order"); + CREATE INDEX IF NOT EXISTS "forms_blocks_email_parent_id_idx" ON "forms_blocks_email" USING btree ("_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_blocks_email_path_idx" ON "forms_blocks_email" USING btree ("_path"); + CREATE UNIQUE INDEX IF NOT EXISTS "forms_blocks_email_locales_locale_parent_id_unique" ON "forms_blocks_email_locales" USING btree ("_locale","_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_blocks_message_order_idx" ON "forms_blocks_message" USING btree ("_order"); + CREATE INDEX IF NOT EXISTS "forms_blocks_message_parent_id_idx" ON "forms_blocks_message" USING btree ("_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_blocks_message_path_idx" ON "forms_blocks_message" USING btree ("_path"); + CREATE UNIQUE INDEX IF NOT EXISTS "forms_blocks_message_locales_locale_parent_id_unique" ON "forms_blocks_message_locales" USING btree ("_locale","_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_blocks_number_order_idx" ON "forms_blocks_number" USING btree ("_order"); + CREATE INDEX IF NOT EXISTS "forms_blocks_number_parent_id_idx" ON "forms_blocks_number" USING btree ("_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_blocks_number_path_idx" ON "forms_blocks_number" USING btree ("_path"); + CREATE UNIQUE INDEX IF NOT EXISTS "forms_blocks_number_locales_locale_parent_id_unique" ON "forms_blocks_number_locales" USING btree ("_locale","_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_blocks_select_options_order_idx" ON "forms_blocks_select_options" USING btree ("_order"); + CREATE INDEX IF NOT EXISTS "forms_blocks_select_options_parent_id_idx" ON "forms_blocks_select_options" USING btree ("_parent_id"); + CREATE UNIQUE INDEX IF NOT EXISTS "forms_blocks_select_options_locales_locale_parent_id_unique" ON "forms_blocks_select_options_locales" USING btree ("_locale","_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_blocks_select_order_idx" ON "forms_blocks_select" USING btree ("_order"); + CREATE INDEX IF NOT EXISTS "forms_blocks_select_parent_id_idx" ON "forms_blocks_select" USING btree ("_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_blocks_select_path_idx" ON "forms_blocks_select" USING btree ("_path"); + CREATE UNIQUE INDEX IF NOT EXISTS "forms_blocks_select_locales_locale_parent_id_unique" ON "forms_blocks_select_locales" USING btree ("_locale","_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_blocks_text_order_idx" ON "forms_blocks_text" USING btree ("_order"); + CREATE INDEX IF NOT EXISTS "forms_blocks_text_parent_id_idx" ON "forms_blocks_text" USING btree ("_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_blocks_text_path_idx" ON "forms_blocks_text" USING btree ("_path"); + CREATE UNIQUE INDEX IF NOT EXISTS "forms_blocks_text_locales_locale_parent_id_unique" ON "forms_blocks_text_locales" USING btree ("_locale","_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_blocks_textarea_order_idx" ON "forms_blocks_textarea" USING btree ("_order"); + CREATE INDEX IF NOT EXISTS "forms_blocks_textarea_parent_id_idx" ON "forms_blocks_textarea" USING btree ("_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_blocks_textarea_path_idx" ON "forms_blocks_textarea" USING btree ("_path"); + CREATE UNIQUE INDEX IF NOT EXISTS "forms_blocks_textarea_locales_locale_parent_id_unique" ON "forms_blocks_textarea_locales" USING btree ("_locale","_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_emails_order_idx" ON "forms_emails" USING btree ("_order"); + CREATE INDEX IF NOT EXISTS "forms_emails_parent_id_idx" ON "forms_emails" USING btree ("_parent_id"); + CREATE UNIQUE INDEX IF NOT EXISTS "forms_emails_locales_locale_parent_id_unique" ON "forms_emails_locales" USING btree ("_locale","_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_tenant_idx" ON "forms" USING btree ("tenant_id"); + CREATE INDEX IF NOT EXISTS "forms_updated_at_idx" ON "forms" USING btree ("updated_at"); + CREATE INDEX IF NOT EXISTS "forms_created_at_idx" ON "forms" USING btree ("created_at"); + CREATE UNIQUE INDEX IF NOT EXISTS "forms_locales_locale_parent_id_unique" ON "forms_locales" USING btree ("_locale","_parent_id"); + CREATE INDEX IF NOT EXISTS "forms_rels_order_idx" ON "forms_rels" USING btree ("order"); + CREATE INDEX IF NOT EXISTS "forms_rels_parent_idx" ON "forms_rels" USING btree ("parent_id"); + CREATE INDEX IF NOT EXISTS "forms_rels_path_idx" ON "forms_rels" USING btree ("path"); + CREATE INDEX IF NOT EXISTS "forms_rels_pages_id_idx" ON "forms_rels" USING btree ("pages_id"); + CREATE INDEX IF NOT EXISTS "form_submissions_submission_data_order_idx" ON "form_submissions_submission_data" USING btree ("_order"); + CREATE INDEX IF NOT EXISTS "form_submissions_submission_data_parent_id_idx" ON "form_submissions_submission_data" USING btree ("_parent_id"); + CREATE INDEX IF NOT EXISTS "form_submissions_form_idx" ON "form_submissions" USING btree ("form_id"); + CREATE INDEX IF NOT EXISTS "form_submissions_updated_at_idx" ON "form_submissions" USING btree ("updated_at"); + CREATE INDEX IF NOT EXISTS "form_submissions_created_at_idx" ON "form_submissions" USING btree ("created_at"); + DO $$ BEGIN + ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_forms_fk" FOREIGN KEY ("forms_id") REFERENCES "public"."forms"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + DO $$ BEGIN + ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_form_submissions_fk" FOREIGN KEY ("form_submissions_id") REFERENCES "public"."form_submissions"("id") ON DELETE cascade ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + CREATE INDEX IF NOT EXISTS "payload_locked_documents_rels_forms_id_idx" ON "payload_locked_documents_rels" USING btree ("forms_id"); + CREATE INDEX IF NOT EXISTS "payload_locked_documents_rels_form_submissions_id_idx" ON "payload_locked_documents_rels" USING btree ("form_submissions_id");`); +} + +export async function down({ + db, + payload, + req +}: MigrateDownArgs): Promise { + await db.execute(sql` + ALTER TABLE "pages_blocks_form" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_checkbox" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_checkbox_locales" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_country" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_country_locales" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_email" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_email_locales" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_message" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_message_locales" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_number" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_number_locales" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_select_options" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_select_options_locales" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_select" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_select_locales" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_text" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_text_locales" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_textarea" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_blocks_textarea_locales" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_emails" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_emails_locales" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_locales" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "forms_rels" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "form_submissions_submission_data" DISABLE ROW LEVEL SECURITY; + ALTER TABLE "form_submissions" DISABLE ROW LEVEL SECURITY; + DROP TABLE "pages_blocks_form" CASCADE; + DROP TABLE "forms_blocks_checkbox" CASCADE; + DROP TABLE "forms_blocks_checkbox_locales" CASCADE; + DROP TABLE "forms_blocks_country" CASCADE; + DROP TABLE "forms_blocks_country_locales" CASCADE; + DROP TABLE "forms_blocks_email" CASCADE; + DROP TABLE "forms_blocks_email_locales" CASCADE; + DROP TABLE "forms_blocks_message" CASCADE; + DROP TABLE "forms_blocks_message_locales" CASCADE; + DROP TABLE "forms_blocks_number" CASCADE; + DROP TABLE "forms_blocks_number_locales" CASCADE; + DROP TABLE "forms_blocks_select_options" CASCADE; + DROP TABLE "forms_blocks_select_options_locales" CASCADE; + DROP TABLE "forms_blocks_select" CASCADE; + DROP TABLE "forms_blocks_select_locales" CASCADE; + DROP TABLE "forms_blocks_text" CASCADE; + DROP TABLE "forms_blocks_text_locales" CASCADE; + DROP TABLE "forms_blocks_textarea" CASCADE; + DROP TABLE "forms_blocks_textarea_locales" CASCADE; + DROP TABLE "forms_emails" CASCADE; + DROP TABLE "forms_emails_locales" CASCADE; + DROP TABLE "forms" CASCADE; + DROP TABLE "forms_locales" CASCADE; + DROP TABLE "forms_rels" CASCADE; + DROP TABLE "form_submissions_submission_data" CASCADE; + DROP TABLE "form_submissions" CASCADE; + ALTER TABLE "payload_locked_documents_rels" DROP CONSTRAINT "payload_locked_documents_rels_forms_fk"; + + ALTER TABLE "payload_locked_documents_rels" DROP CONSTRAINT "payload_locked_documents_rels_form_submissions_fk"; + + DROP INDEX IF EXISTS "payload_locked_documents_rels_forms_id_idx"; + DROP INDEX IF EXISTS "payload_locked_documents_rels_form_submissions_id_idx"; + ALTER TABLE "payload_locked_documents_rels" DROP COLUMN IF EXISTS "forms_id"; + ALTER TABLE "payload_locked_documents_rels" DROP COLUMN IF EXISTS "form_submissions_id"; + DROP TYPE "public"."enum_forms_blocks_checkbox_width"; + DROP TYPE "public"."enum_forms_blocks_country_width"; + DROP TYPE "public"."enum_forms_blocks_email_width"; + DROP TYPE "public"."enum_forms_blocks_number_width"; + DROP TYPE "public"."enum_forms_blocks_select_width"; + DROP TYPE "public"."enum_forms_blocks_text_width"; + DROP TYPE "public"."enum_forms_blocks_textarea_width"; + DROP TYPE "public"."enum_forms_confirmation_type"; + DROP TYPE "public"."enum_forms_redirect_type";`); +} diff --git a/apps/cms/src/migrations/20250326_200110_cod_282_2.json b/apps/cms/src/migrations/20250326_200110_cod_282_2.json new file mode 100644 index 000000000..6add001c7 --- /dev/null +++ b/apps/cms/src/migrations/20250326_200110_cod_282_2.json @@ -0,0 +1,5947 @@ +{ + "id": "3df88941-eb87-4a66-9fae-71f05939067d", + "prevId": "00000000-0000-0000-0000-000000000000", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.categories": { + "name": "categories", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "categories_tenant_idx": { + "name": "categories_tenant_idx", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "categories_slug_idx": { + "name": "categories_slug_idx", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "categories_updated_at_idx": { + "name": "categories_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "categories_created_at_idx": { + "name": "categories_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "categories_tenant_id_tenants_id_fk": { + "name": "categories_tenant_id_tenants_id_fk", + "tableFrom": "categories", + "tableTo": "tenants", + "columnsFrom": ["tenant_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.categories_locales": { + "name": "categories_locales", + "schema": "", + "columns": { + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "categories_locales_locale_parent_id_unique": { + "name": "categories_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "categories_locales_parent_id_fk": { + "name": "categories_locales_parent_id_fk", + "tableFrom": "categories_locales", + "tableTo": "categories", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.media": { + "name": "media", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "alt": { + "name": "alt", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "prefix": { + "name": "prefix", + "type": "varchar", + "primaryKey": false, + "notNull": false, + "default": "'media'" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "url": { + "name": "url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "thumbnail_u_r_l": { + "name": "thumbnail_u_r_l", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "filename": { + "name": "filename", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "mime_type": { + "name": "mime_type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "filesize": { + "name": "filesize", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "width": { + "name": "width", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "height": { + "name": "height", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "focal_x": { + "name": "focal_x", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "focal_y": { + "name": "focal_y", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_thumbnail_url": { + "name": "sizes_thumbnail_url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_thumbnail_width": { + "name": "sizes_thumbnail_width", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_thumbnail_height": { + "name": "sizes_thumbnail_height", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_thumbnail_mime_type": { + "name": "sizes_thumbnail_mime_type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_thumbnail_filesize": { + "name": "sizes_thumbnail_filesize", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_thumbnail_filename": { + "name": "sizes_thumbnail_filename", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_square_url": { + "name": "sizes_square_url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_square_width": { + "name": "sizes_square_width", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_square_height": { + "name": "sizes_square_height", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_square_mime_type": { + "name": "sizes_square_mime_type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_square_filesize": { + "name": "sizes_square_filesize", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_square_filename": { + "name": "sizes_square_filename", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_small_url": { + "name": "sizes_small_url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_small_width": { + "name": "sizes_small_width", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_small_height": { + "name": "sizes_small_height", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_small_mime_type": { + "name": "sizes_small_mime_type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_small_filesize": { + "name": "sizes_small_filesize", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_small_filename": { + "name": "sizes_small_filename", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_medium_url": { + "name": "sizes_medium_url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_medium_width": { + "name": "sizes_medium_width", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_medium_height": { + "name": "sizes_medium_height", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_medium_mime_type": { + "name": "sizes_medium_mime_type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_medium_filesize": { + "name": "sizes_medium_filesize", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_medium_filename": { + "name": "sizes_medium_filename", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_large_url": { + "name": "sizes_large_url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_large_width": { + "name": "sizes_large_width", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_large_height": { + "name": "sizes_large_height", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_large_mime_type": { + "name": "sizes_large_mime_type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_large_filesize": { + "name": "sizes_large_filesize", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_large_filename": { + "name": "sizes_large_filename", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_xlarge_url": { + "name": "sizes_xlarge_url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_xlarge_width": { + "name": "sizes_xlarge_width", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_xlarge_height": { + "name": "sizes_xlarge_height", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_xlarge_mime_type": { + "name": "sizes_xlarge_mime_type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_xlarge_filesize": { + "name": "sizes_xlarge_filesize", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_xlarge_filename": { + "name": "sizes_xlarge_filename", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_og_url": { + "name": "sizes_og_url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_og_width": { + "name": "sizes_og_width", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_og_height": { + "name": "sizes_og_height", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_og_mime_type": { + "name": "sizes_og_mime_type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "sizes_og_filesize": { + "name": "sizes_og_filesize", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "sizes_og_filename": { + "name": "sizes_og_filename", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "media_tenant_idx": { + "name": "media_tenant_idx", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_updated_at_idx": { + "name": "media_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_created_at_idx": { + "name": "media_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_filename_idx": { + "name": "media_filename_idx", + "columns": [ + { + "expression": "filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_sizes_thumbnail_sizes_thumbnail_filename_idx": { + "name": "media_sizes_thumbnail_sizes_thumbnail_filename_idx", + "columns": [ + { + "expression": "sizes_thumbnail_filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_sizes_square_sizes_square_filename_idx": { + "name": "media_sizes_square_sizes_square_filename_idx", + "columns": [ + { + "expression": "sizes_square_filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_sizes_small_sizes_small_filename_idx": { + "name": "media_sizes_small_sizes_small_filename_idx", + "columns": [ + { + "expression": "sizes_small_filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_sizes_medium_sizes_medium_filename_idx": { + "name": "media_sizes_medium_sizes_medium_filename_idx", + "columns": [ + { + "expression": "sizes_medium_filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_sizes_large_sizes_large_filename_idx": { + "name": "media_sizes_large_sizes_large_filename_idx", + "columns": [ + { + "expression": "sizes_large_filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_sizes_xlarge_sizes_xlarge_filename_idx": { + "name": "media_sizes_xlarge_sizes_xlarge_filename_idx", + "columns": [ + { + "expression": "sizes_xlarge_filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "media_sizes_og_sizes_og_filename_idx": { + "name": "media_sizes_og_sizes_og_filename_idx", + "columns": [ + { + "expression": "sizes_og_filename", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "media_tenant_id_tenants_id_fk": { + "name": "media_tenant_id_tenants_id_fk", + "tableFrom": "media", + "tableTo": "tenants", + "columnsFrom": ["tenant_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.media_locales": { + "name": "media_locales", + "schema": "", + "columns": { + "caption": { + "name": "caption", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "media_locales_locale_parent_id_unique": { + "name": "media_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "media_locales_parent_id_fk": { + "name": "media_locales_parent_id_fk", + "tableFrom": "media_locales", + "tableTo": "media", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pages_blocks_content_columns": { + "name": "pages_blocks_content_columns", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "size": { + "name": "size", + "type": "enum_pages_blocks_content_columns_size", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'full'" + }, + "rich_text": { + "name": "rich_text", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "pages_blocks_content_columns_order_idx": { + "name": "pages_blocks_content_columns_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_content_columns_parent_id_idx": { + "name": "pages_blocks_content_columns_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_content_columns_locale_idx": { + "name": "pages_blocks_content_columns_locale_idx", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pages_blocks_content_columns_parent_id_fk": { + "name": "pages_blocks_content_columns_parent_id_fk", + "tableFrom": "pages_blocks_content_columns", + "tableTo": "pages_blocks_content", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pages_blocks_content": { + "name": "pages_blocks_content", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "pages_blocks_content_order_idx": { + "name": "pages_blocks_content_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_content_parent_id_idx": { + "name": "pages_blocks_content_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_content_path_idx": { + "name": "pages_blocks_content_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_content_locale_idx": { + "name": "pages_blocks_content_locale_idx", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pages_blocks_content_parent_id_fk": { + "name": "pages_blocks_content_parent_id_fk", + "tableFrom": "pages_blocks_content", + "tableTo": "pages", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pages_blocks_form": { + "name": "pages_blocks_form", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "form_id": { + "name": "form_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "enable_intro": { + "name": "enable_intro", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "intro_content": { + "name": "intro_content", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "pages_blocks_form_order_idx": { + "name": "pages_blocks_form_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_form_parent_id_idx": { + "name": "pages_blocks_form_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_form_path_idx": { + "name": "pages_blocks_form_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_form_locale_idx": { + "name": "pages_blocks_form_locale_idx", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_form_form_idx": { + "name": "pages_blocks_form_form_idx", + "columns": [ + { + "expression": "form_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pages_blocks_form_form_id_forms_id_fk": { + "name": "pages_blocks_form_form_id_forms_id_fk", + "tableFrom": "pages_blocks_form", + "tableTo": "forms", + "columnsFrom": ["form_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "pages_blocks_form_parent_id_fk": { + "name": "pages_blocks_form_parent_id_fk", + "tableFrom": "pages_blocks_form", + "tableTo": "pages", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pages_blocks_media": { + "name": "pages_blocks_media", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "media_id": { + "name": "media_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "pages_blocks_media_order_idx": { + "name": "pages_blocks_media_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_media_parent_id_idx": { + "name": "pages_blocks_media_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_media_path_idx": { + "name": "pages_blocks_media_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_media_locale_idx": { + "name": "pages_blocks_media_locale_idx", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_media_media_idx": { + "name": "pages_blocks_media_media_idx", + "columns": [ + { + "expression": "media_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pages_blocks_media_media_id_media_id_fk": { + "name": "pages_blocks_media_media_id_media_id_fk", + "tableFrom": "pages_blocks_media", + "tableTo": "media", + "columnsFrom": ["media_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "pages_blocks_media_parent_id_fk": { + "name": "pages_blocks_media_parent_id_fk", + "tableFrom": "pages_blocks_media", + "tableTo": "pages", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pages_blocks_code": { + "name": "pages_blocks_code", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "language": { + "name": "language", + "type": "enum_pages_blocks_code_language", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'ts'" + }, + "code": { + "name": "code", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "pages_blocks_code_order_idx": { + "name": "pages_blocks_code_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_code_parent_id_idx": { + "name": "pages_blocks_code_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_code_path_idx": { + "name": "pages_blocks_code_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_blocks_code_locale_idx": { + "name": "pages_blocks_code_locale_idx", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pages_blocks_code_parent_id_fk": { + "name": "pages_blocks_code_parent_id_fk", + "tableFrom": "pages_blocks_code", + "tableTo": "pages", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pages": { + "name": "pages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "published_at": { + "name": "published_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "pages_tenant_idx": { + "name": "pages_tenant_idx", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_slug_idx": { + "name": "pages_slug_idx", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_updated_at_idx": { + "name": "pages_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_created_at_idx": { + "name": "pages_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pages_tenant_id_tenants_id_fk": { + "name": "pages_tenant_id_tenants_id_fk", + "tableFrom": "pages", + "tableTo": "tenants", + "columnsFrom": ["tenant_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.pages_locales": { + "name": "pages_locales", + "schema": "", + "columns": { + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "header": { + "name": "header", + "type": "varchar", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "meta_title": { + "name": "meta_title", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "meta_image_id": { + "name": "meta_image_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "meta_description": { + "name": "meta_description", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "pages_meta_meta_image_idx": { + "name": "pages_meta_meta_image_idx", + "columns": [ + { + "expression": "meta_image_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "pages_locales_locale_parent_id_unique": { + "name": "pages_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "pages_locales_meta_image_id_media_id_fk": { + "name": "pages_locales_meta_image_id_media_id_fk", + "tableFrom": "pages_locales", + "tableTo": "media", + "columnsFrom": ["meta_image_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "pages_locales_parent_id_fk": { + "name": "pages_locales_parent_id_fk", + "tableFrom": "pages_locales", + "tableTo": "pages", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.posts": { + "name": "posts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "hero_image_id": { + "name": "hero_image_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "published_at": { + "name": "published_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "posts_tenant_idx": { + "name": "posts_tenant_idx", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_hero_image_idx": { + "name": "posts_hero_image_idx", + "columns": [ + { + "expression": "hero_image_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_slug_idx": { + "name": "posts_slug_idx", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_updated_at_idx": { + "name": "posts_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_created_at_idx": { + "name": "posts_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "posts_tenant_id_tenants_id_fk": { + "name": "posts_tenant_id_tenants_id_fk", + "tableFrom": "posts", + "tableTo": "tenants", + "columnsFrom": ["tenant_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "posts_hero_image_id_media_id_fk": { + "name": "posts_hero_image_id_media_id_fk", + "tableFrom": "posts", + "tableTo": "media", + "columnsFrom": ["hero_image_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.posts_locales": { + "name": "posts_locales", + "schema": "", + "columns": { + "title": { + "name": "title", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "meta_title": { + "name": "meta_title", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "meta_image_id": { + "name": "meta_image_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "meta_description": { + "name": "meta_description", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "posts_meta_meta_image_idx": { + "name": "posts_meta_meta_image_idx", + "columns": [ + { + "expression": "meta_image_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_locales_locale_parent_id_unique": { + "name": "posts_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "posts_locales_meta_image_id_media_id_fk": { + "name": "posts_locales_meta_image_id_media_id_fk", + "tableFrom": "posts_locales", + "tableTo": "media", + "columnsFrom": ["meta_image_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "posts_locales_parent_id_fk": { + "name": "posts_locales_parent_id_fk", + "tableFrom": "posts_locales", + "tableTo": "posts", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.posts_rels": { + "name": "posts_rels", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "order": { + "name": "order", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "parent_id": { + "name": "parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "posts_id": { + "name": "posts_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "categories_id": { + "name": "categories_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "users_id": { + "name": "users_id", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "posts_rels_order_idx": { + "name": "posts_rels_order_idx", + "columns": [ + { + "expression": "order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_rels_parent_idx": { + "name": "posts_rels_parent_idx", + "columns": [ + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_rels_path_idx": { + "name": "posts_rels_path_idx", + "columns": [ + { + "expression": "path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_rels_posts_id_idx": { + "name": "posts_rels_posts_id_idx", + "columns": [ + { + "expression": "posts_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_rels_categories_id_idx": { + "name": "posts_rels_categories_id_idx", + "columns": [ + { + "expression": "categories_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "posts_rels_users_id_idx": { + "name": "posts_rels_users_id_idx", + "columns": [ + { + "expression": "users_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "posts_rels_parent_fk": { + "name": "posts_rels_parent_fk", + "tableFrom": "posts_rels", + "tableTo": "posts", + "columnsFrom": ["parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "posts_rels_posts_fk": { + "name": "posts_rels_posts_fk", + "tableFrom": "posts_rels", + "tableTo": "posts", + "columnsFrom": ["posts_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "posts_rels_categories_fk": { + "name": "posts_rels_categories_fk", + "tableFrom": "posts_rels", + "tableTo": "categories", + "columnsFrom": ["categories_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "posts_rels_users_fk": { + "name": "posts_rels_users_fk", + "tableFrom": "posts_rels", + "tableTo": "users", + "columnsFrom": ["users_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.tenants_domains_page_types": { + "name": "tenants_domains_page_types", + "schema": "", + "columns": { + "order": { + "name": "order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "parent_id": { + "name": "parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "enum_tenants_domains_page_types", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + } + }, + "indexes": { + "tenants_domains_page_types_order_idx": { + "name": "tenants_domains_page_types_order_idx", + "columns": [ + { + "expression": "order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "tenants_domains_page_types_parent_idx": { + "name": "tenants_domains_page_types_parent_idx", + "columns": [ + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "tenants_domains_page_types_parent_fk": { + "name": "tenants_domains_page_types_parent_fk", + "tableFrom": "tenants_domains_page_types", + "tableTo": "tenants_domains", + "columnsFrom": ["parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.tenants_domains": { + "name": "tenants_domains", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "domain": { + "name": "domain", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "tenants_domains_order_idx": { + "name": "tenants_domains_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "tenants_domains_parent_id_idx": { + "name": "tenants_domains_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "tenants_domains_parent_id_fk": { + "name": "tenants_domains_parent_id_fk", + "tableFrom": "tenants_domains", + "tableTo": "tenants", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.tenants": { + "name": "tenants", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "enable_a_p_i_key": { + "name": "enable_a_p_i_key", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "api_key": { + "name": "api_key", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "api_key_index": { + "name": "api_key_index", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "tenants_slug_idx": { + "name": "tenants_slug_idx", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "tenants_updated_at_idx": { + "name": "tenants_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "tenants_created_at_idx": { + "name": "tenants_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.users_tenants": { + "name": "users_tenants", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "enum_users_tenants_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'user'" + } + }, + "indexes": { + "users_tenants_order_idx": { + "name": "users_tenants_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "users_tenants_parent_id_idx": { + "name": "users_tenants_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "users_tenants_tenant_idx": { + "name": "users_tenants_tenant_idx", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "users_tenants_tenant_id_tenants_id_fk": { + "name": "users_tenants_tenant_id_tenants_id_fk", + "tableFrom": "users_tenants", + "tableTo": "tenants", + "columnsFrom": ["tenant_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "users_tenants_parent_id_fk": { + "name": "users_tenants_parent_id_fk", + "tableFrom": "users_tenants", + "tableTo": "users", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "enum_users_role", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'user'" + }, + "description": { + "name": "description", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "email": { + "name": "email", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "reset_password_token": { + "name": "reset_password_token", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "reset_password_expiration": { + "name": "reset_password_expiration", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": false + }, + "salt": { + "name": "salt", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "hash": { + "name": "hash", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "login_attempts": { + "name": "login_attempts", + "type": "numeric", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "lock_until": { + "name": "lock_until", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "users_updated_at_idx": { + "name": "users_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "users_created_at_idx": { + "name": "users_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "users_email_idx": { + "name": "users_email_idx", + "columns": [ + { + "expression": "email", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_checkbox": { + "name": "forms_blocks_checkbox", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "width": { + "name": "width", + "type": "enum_forms_blocks_checkbox_width", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'12'" + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "default_value": { + "name": "default_value", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_blocks_checkbox_order_idx": { + "name": "forms_blocks_checkbox_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_checkbox_parent_id_idx": { + "name": "forms_blocks_checkbox_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_checkbox_path_idx": { + "name": "forms_blocks_checkbox_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_checkbox_parent_id_fk": { + "name": "forms_blocks_checkbox_parent_id_fk", + "tableFrom": "forms_blocks_checkbox", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_checkbox_locales": { + "name": "forms_blocks_checkbox_locales", + "schema": "", + "columns": { + "label": { + "name": "label", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_checkbox_locales_locale_parent_id_unique": { + "name": "forms_blocks_checkbox_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_checkbox_locales_parent_id_fk": { + "name": "forms_blocks_checkbox_locales_parent_id_fk", + "tableFrom": "forms_blocks_checkbox_locales", + "tableTo": "forms_blocks_checkbox", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_country": { + "name": "forms_blocks_country", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "width": { + "name": "width", + "type": "enum_forms_blocks_country_width", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'12'" + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_blocks_country_order_idx": { + "name": "forms_blocks_country_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_country_parent_id_idx": { + "name": "forms_blocks_country_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_country_path_idx": { + "name": "forms_blocks_country_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_country_parent_id_fk": { + "name": "forms_blocks_country_parent_id_fk", + "tableFrom": "forms_blocks_country", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_country_locales": { + "name": "forms_blocks_country_locales", + "schema": "", + "columns": { + "label": { + "name": "label", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "placeholder": { + "name": "placeholder", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_country_locales_locale_parent_id_unique": { + "name": "forms_blocks_country_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_country_locales_parent_id_fk": { + "name": "forms_blocks_country_locales_parent_id_fk", + "tableFrom": "forms_blocks_country_locales", + "tableTo": "forms_blocks_country", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_email": { + "name": "forms_blocks_email", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "width": { + "name": "width", + "type": "enum_forms_blocks_email_width", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'12'" + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_blocks_email_order_idx": { + "name": "forms_blocks_email_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_email_parent_id_idx": { + "name": "forms_blocks_email_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_email_path_idx": { + "name": "forms_blocks_email_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_email_parent_id_fk": { + "name": "forms_blocks_email_parent_id_fk", + "tableFrom": "forms_blocks_email", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_email_locales": { + "name": "forms_blocks_email_locales", + "schema": "", + "columns": { + "label": { + "name": "label", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "placeholder": { + "name": "placeholder", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_email_locales_locale_parent_id_unique": { + "name": "forms_blocks_email_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_email_locales_parent_id_fk": { + "name": "forms_blocks_email_locales_parent_id_fk", + "tableFrom": "forms_blocks_email_locales", + "tableTo": "forms_blocks_email", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_message": { + "name": "forms_blocks_message", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_blocks_message_order_idx": { + "name": "forms_blocks_message_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_message_parent_id_idx": { + "name": "forms_blocks_message_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_message_path_idx": { + "name": "forms_blocks_message_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_message_parent_id_fk": { + "name": "forms_blocks_message_parent_id_fk", + "tableFrom": "forms_blocks_message", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_message_locales": { + "name": "forms_blocks_message_locales", + "schema": "", + "columns": { + "message": { + "name": "message", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_message_locales_locale_parent_id_unique": { + "name": "forms_blocks_message_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_message_locales_parent_id_fk": { + "name": "forms_blocks_message_locales_parent_id_fk", + "tableFrom": "forms_blocks_message_locales", + "tableTo": "forms_blocks_message", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_number": { + "name": "forms_blocks_number", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "width": { + "name": "width", + "type": "enum_forms_blocks_number_width", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'12'" + }, + "default_value": { + "name": "default_value", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_blocks_number_order_idx": { + "name": "forms_blocks_number_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_number_parent_id_idx": { + "name": "forms_blocks_number_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_number_path_idx": { + "name": "forms_blocks_number_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_number_parent_id_fk": { + "name": "forms_blocks_number_parent_id_fk", + "tableFrom": "forms_blocks_number", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_number_locales": { + "name": "forms_blocks_number_locales", + "schema": "", + "columns": { + "label": { + "name": "label", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "placeholder": { + "name": "placeholder", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_number_locales_locale_parent_id_unique": { + "name": "forms_blocks_number_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_number_locales_parent_id_fk": { + "name": "forms_blocks_number_locales_parent_id_fk", + "tableFrom": "forms_blocks_number_locales", + "tableTo": "forms_blocks_number", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_select_options": { + "name": "forms_blocks_select_options", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "value": { + "name": "value", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_select_options_order_idx": { + "name": "forms_blocks_select_options_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_select_options_parent_id_idx": { + "name": "forms_blocks_select_options_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_select_options_parent_id_fk": { + "name": "forms_blocks_select_options_parent_id_fk", + "tableFrom": "forms_blocks_select_options", + "tableTo": "forms_blocks_select", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_select_options_locales": { + "name": "forms_blocks_select_options_locales", + "schema": "", + "columns": { + "label": { + "name": "label", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_select_options_locales_locale_parent_id_unique": { + "name": "forms_blocks_select_options_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_select_options_locales_parent_id_fk": { + "name": "forms_blocks_select_options_locales_parent_id_fk", + "tableFrom": "forms_blocks_select_options_locales", + "tableTo": "forms_blocks_select_options", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_select": { + "name": "forms_blocks_select", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "width": { + "name": "width", + "type": "enum_forms_blocks_select_width", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'12'" + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_blocks_select_order_idx": { + "name": "forms_blocks_select_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_select_parent_id_idx": { + "name": "forms_blocks_select_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_select_path_idx": { + "name": "forms_blocks_select_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_select_parent_id_fk": { + "name": "forms_blocks_select_parent_id_fk", + "tableFrom": "forms_blocks_select", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_select_locales": { + "name": "forms_blocks_select_locales", + "schema": "", + "columns": { + "label": { + "name": "label", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "placeholder": { + "name": "placeholder", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "default_value": { + "name": "default_value", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_select_locales_locale_parent_id_unique": { + "name": "forms_blocks_select_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_select_locales_parent_id_fk": { + "name": "forms_blocks_select_locales_parent_id_fk", + "tableFrom": "forms_blocks_select_locales", + "tableTo": "forms_blocks_select", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_text": { + "name": "forms_blocks_text", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "width": { + "name": "width", + "type": "enum_forms_blocks_text_width", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'12'" + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_blocks_text_order_idx": { + "name": "forms_blocks_text_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_text_parent_id_idx": { + "name": "forms_blocks_text_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_text_path_idx": { + "name": "forms_blocks_text_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_text_parent_id_fk": { + "name": "forms_blocks_text_parent_id_fk", + "tableFrom": "forms_blocks_text", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_text_locales": { + "name": "forms_blocks_text_locales", + "schema": "", + "columns": { + "label": { + "name": "label", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "placeholder": { + "name": "placeholder", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "default_value": { + "name": "default_value", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_text_locales_locale_parent_id_unique": { + "name": "forms_blocks_text_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_text_locales_parent_id_fk": { + "name": "forms_blocks_text_locales_parent_id_fk", + "tableFrom": "forms_blocks_text_locales", + "tableTo": "forms_blocks_text", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_textarea": { + "name": "forms_blocks_textarea", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_path": { + "name": "_path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "width": { + "name": "width", + "type": "enum_forms_blocks_textarea_width", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'12'" + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "block_name": { + "name": "block_name", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_blocks_textarea_order_idx": { + "name": "forms_blocks_textarea_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_textarea_parent_id_idx": { + "name": "forms_blocks_textarea_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_blocks_textarea_path_idx": { + "name": "forms_blocks_textarea_path_idx", + "columns": [ + { + "expression": "_path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_textarea_parent_id_fk": { + "name": "forms_blocks_textarea_parent_id_fk", + "tableFrom": "forms_blocks_textarea", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_blocks_textarea_locales": { + "name": "forms_blocks_textarea_locales", + "schema": "", + "columns": { + "label": { + "name": "label", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "placeholder": { + "name": "placeholder", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "default_value": { + "name": "default_value", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_blocks_textarea_locales_locale_parent_id_unique": { + "name": "forms_blocks_textarea_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_blocks_textarea_locales_parent_id_fk": { + "name": "forms_blocks_textarea_locales_parent_id_fk", + "tableFrom": "forms_blocks_textarea_locales", + "tableTo": "forms_blocks_textarea", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_emails": { + "name": "forms_emails", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "email_to": { + "name": "email_to", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "cc": { + "name": "cc", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "bcc": { + "name": "bcc", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "reply_to": { + "name": "reply_to", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "email_from": { + "name": "email_from", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_emails_order_idx": { + "name": "forms_emails_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_emails_parent_id_idx": { + "name": "forms_emails_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_emails_parent_id_fk": { + "name": "forms_emails_parent_id_fk", + "tableFrom": "forms_emails", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_emails_locales": { + "name": "forms_emails_locales", + "schema": "", + "columns": { + "subject": { + "name": "subject", + "type": "varchar", + "primaryKey": false, + "notNull": true, + "default": "'You''''ve received a new message.'" + }, + "message": { + "name": "message", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_emails_locales_locale_parent_id_unique": { + "name": "forms_emails_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_emails_locales_parent_id_fk": { + "name": "forms_emails_locales_parent_id_fk", + "tableFrom": "forms_emails_locales", + "tableTo": "forms_emails", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms": { + "name": "forms", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "confirmation_type": { + "name": "confirmation_type", + "type": "enum_forms_confirmation_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'message'" + }, + "redirect_type": { + "name": "redirect_type", + "type": "enum_forms_redirect_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'reference'" + }, + "redirect_url": { + "name": "redirect_url", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "forms_tenant_idx": { + "name": "forms_tenant_idx", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_updated_at_idx": { + "name": "forms_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_created_at_idx": { + "name": "forms_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_tenant_id_tenants_id_fk": { + "name": "forms_tenant_id_tenants_id_fk", + "tableFrom": "forms", + "tableTo": "tenants", + "columnsFrom": ["tenant_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_locales": { + "name": "forms_locales", + "schema": "", + "columns": { + "submit_button_label": { + "name": "submit_button_label", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "confirmation_message": { + "name": "confirmation_message", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "_locale": { + "name": "_locale", + "type": "_locales", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "forms_locales_locale_parent_id_unique": { + "name": "forms_locales_locale_parent_id_unique", + "columns": [ + { + "expression": "_locale", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_locales_parent_id_fk": { + "name": "forms_locales_parent_id_fk", + "tableFrom": "forms_locales", + "tableTo": "forms", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.forms_rels": { + "name": "forms_rels", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "order": { + "name": "order", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "parent_id": { + "name": "parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "pages_id": { + "name": "pages_id", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "forms_rels_order_idx": { + "name": "forms_rels_order_idx", + "columns": [ + { + "expression": "order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_rels_parent_idx": { + "name": "forms_rels_parent_idx", + "columns": [ + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_rels_path_idx": { + "name": "forms_rels_path_idx", + "columns": [ + { + "expression": "path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "forms_rels_pages_id_idx": { + "name": "forms_rels_pages_id_idx", + "columns": [ + { + "expression": "pages_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "forms_rels_parent_fk": { + "name": "forms_rels_parent_fk", + "tableFrom": "forms_rels", + "tableTo": "forms", + "columnsFrom": ["parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "forms_rels_pages_fk": { + "name": "forms_rels_pages_fk", + "tableFrom": "forms_rels", + "tableTo": "pages", + "columnsFrom": ["pages_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.form_submissions_submission_data": { + "name": "form_submissions_submission_data", + "schema": "", + "columns": { + "_order": { + "name": "_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "_parent_id": { + "name": "_parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "id": { + "name": "id", + "type": "varchar", + "primaryKey": true, + "notNull": true + }, + "field": { + "name": "field", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "form_submissions_submission_data_order_idx": { + "name": "form_submissions_submission_data_order_idx", + "columns": [ + { + "expression": "_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "form_submissions_submission_data_parent_id_idx": { + "name": "form_submissions_submission_data_parent_id_idx", + "columns": [ + { + "expression": "_parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "form_submissions_submission_data_parent_id_fk": { + "name": "form_submissions_submission_data_parent_id_fk", + "tableFrom": "form_submissions_submission_data", + "tableTo": "form_submissions", + "columnsFrom": ["_parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.form_submissions": { + "name": "form_submissions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "tenant_id": { + "name": "tenant_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "form_id": { + "name": "form_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "form_submissions_tenant_idx": { + "name": "form_submissions_tenant_idx", + "columns": [ + { + "expression": "tenant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "form_submissions_form_idx": { + "name": "form_submissions_form_idx", + "columns": [ + { + "expression": "form_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "form_submissions_updated_at_idx": { + "name": "form_submissions_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "form_submissions_created_at_idx": { + "name": "form_submissions_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "form_submissions_tenant_id_tenants_id_fk": { + "name": "form_submissions_tenant_id_tenants_id_fk", + "tableFrom": "form_submissions", + "tableTo": "tenants", + "columnsFrom": ["tenant_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "form_submissions_form_id_forms_id_fk": { + "name": "form_submissions_form_id_forms_id_fk", + "tableFrom": "form_submissions", + "tableTo": "forms", + "columnsFrom": ["form_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.payload_locked_documents": { + "name": "payload_locked_documents", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "global_slug": { + "name": "global_slug", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "payload_locked_documents_global_slug_idx": { + "name": "payload_locked_documents_global_slug_idx", + "columns": [ + { + "expression": "global_slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_updated_at_idx": { + "name": "payload_locked_documents_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_created_at_idx": { + "name": "payload_locked_documents_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.payload_locked_documents_rels": { + "name": "payload_locked_documents_rels", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "order": { + "name": "order", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "parent_id": { + "name": "parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "categories_id": { + "name": "categories_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "media_id": { + "name": "media_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "pages_id": { + "name": "pages_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "posts_id": { + "name": "posts_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "tenants_id": { + "name": "tenants_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "users_id": { + "name": "users_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "forms_id": { + "name": "forms_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "form_submissions_id": { + "name": "form_submissions_id", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "payload_locked_documents_rels_order_idx": { + "name": "payload_locked_documents_rels_order_idx", + "columns": [ + { + "expression": "order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_parent_idx": { + "name": "payload_locked_documents_rels_parent_idx", + "columns": [ + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_path_idx": { + "name": "payload_locked_documents_rels_path_idx", + "columns": [ + { + "expression": "path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_categories_id_idx": { + "name": "payload_locked_documents_rels_categories_id_idx", + "columns": [ + { + "expression": "categories_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_media_id_idx": { + "name": "payload_locked_documents_rels_media_id_idx", + "columns": [ + { + "expression": "media_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_pages_id_idx": { + "name": "payload_locked_documents_rels_pages_id_idx", + "columns": [ + { + "expression": "pages_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_posts_id_idx": { + "name": "payload_locked_documents_rels_posts_id_idx", + "columns": [ + { + "expression": "posts_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_tenants_id_idx": { + "name": "payload_locked_documents_rels_tenants_id_idx", + "columns": [ + { + "expression": "tenants_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_users_id_idx": { + "name": "payload_locked_documents_rels_users_id_idx", + "columns": [ + { + "expression": "users_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_forms_id_idx": { + "name": "payload_locked_documents_rels_forms_id_idx", + "columns": [ + { + "expression": "forms_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_locked_documents_rels_form_submissions_id_idx": { + "name": "payload_locked_documents_rels_form_submissions_id_idx", + "columns": [ + { + "expression": "form_submissions_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "payload_locked_documents_rels_parent_fk": { + "name": "payload_locked_documents_rels_parent_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "payload_locked_documents", + "columnsFrom": ["parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_locked_documents_rels_categories_fk": { + "name": "payload_locked_documents_rels_categories_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "categories", + "columnsFrom": ["categories_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_locked_documents_rels_media_fk": { + "name": "payload_locked_documents_rels_media_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "media", + "columnsFrom": ["media_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_locked_documents_rels_pages_fk": { + "name": "payload_locked_documents_rels_pages_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "pages", + "columnsFrom": ["pages_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_locked_documents_rels_posts_fk": { + "name": "payload_locked_documents_rels_posts_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "posts", + "columnsFrom": ["posts_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_locked_documents_rels_tenants_fk": { + "name": "payload_locked_documents_rels_tenants_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "tenants", + "columnsFrom": ["tenants_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_locked_documents_rels_users_fk": { + "name": "payload_locked_documents_rels_users_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "users", + "columnsFrom": ["users_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_locked_documents_rels_forms_fk": { + "name": "payload_locked_documents_rels_forms_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "forms", + "columnsFrom": ["forms_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_locked_documents_rels_form_submissions_fk": { + "name": "payload_locked_documents_rels_form_submissions_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "form_submissions", + "columnsFrom": ["form_submissions_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.payload_preferences": { + "name": "payload_preferences", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "key": { + "name": "key", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "value": { + "name": "value", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "payload_preferences_key_idx": { + "name": "payload_preferences_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_preferences_updated_at_idx": { + "name": "payload_preferences_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_preferences_created_at_idx": { + "name": "payload_preferences_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.payload_preferences_rels": { + "name": "payload_preferences_rels", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "order": { + "name": "order", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "parent_id": { + "name": "parent_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "tenants_id": { + "name": "tenants_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "users_id": { + "name": "users_id", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "payload_preferences_rels_order_idx": { + "name": "payload_preferences_rels_order_idx", + "columns": [ + { + "expression": "order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_preferences_rels_parent_idx": { + "name": "payload_preferences_rels_parent_idx", + "columns": [ + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_preferences_rels_path_idx": { + "name": "payload_preferences_rels_path_idx", + "columns": [ + { + "expression": "path", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_preferences_rels_tenants_id_idx": { + "name": "payload_preferences_rels_tenants_id_idx", + "columns": [ + { + "expression": "tenants_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_preferences_rels_users_id_idx": { + "name": "payload_preferences_rels_users_id_idx", + "columns": [ + { + "expression": "users_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "payload_preferences_rels_parent_fk": { + "name": "payload_preferences_rels_parent_fk", + "tableFrom": "payload_preferences_rels", + "tableTo": "payload_preferences", + "columnsFrom": ["parent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_preferences_rels_tenants_fk": { + "name": "payload_preferences_rels_tenants_fk", + "tableFrom": "payload_preferences_rels", + "tableTo": "tenants", + "columnsFrom": ["tenants_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "payload_preferences_rels_users_fk": { + "name": "payload_preferences_rels_users_fk", + "tableFrom": "payload_preferences_rels", + "tableTo": "users", + "columnsFrom": ["users_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.payload_migrations": { + "name": "payload_migrations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "batch": { + "name": "batch", + "type": "numeric", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp(3) with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "payload_migrations_updated_at_idx": { + "name": "payload_migrations_updated_at_idx", + "columns": [ + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "payload_migrations_created_at_idx": { + "name": "payload_migrations_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public._locales": { + "name": "_locales", + "schema": "public", + "values": ["en", "sv"] + }, + "public.enum_pages_blocks_content_columns_size": { + "name": "enum_pages_blocks_content_columns_size", + "schema": "public", + "values": ["one-third", "half", "two-thirds", "full"] + }, + "public.enum_pages_blocks_code_language": { + "name": "enum_pages_blocks_code_language", + "schema": "public", + "values": ["ts", "plaintext", "tsx", "js", "jsx"] + }, + "public.enum_tenants_domains_page_types": { + "name": "enum_tenants_domains_page_types", + "schema": "public", + "values": ["cms", "client", "disabled"] + }, + "public.enum_users_tenants_role": { + "name": "enum_users_tenants_role", + "schema": "public", + "values": ["user", "admin"] + }, + "public.enum_users_role": { + "name": "enum_users_role", + "schema": "public", + "values": ["user", "system-user"] + }, + "public.enum_forms_blocks_checkbox_width": { + "name": "enum_forms_blocks_checkbox_width", + "schema": "public", + "values": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] + }, + "public.enum_forms_blocks_country_width": { + "name": "enum_forms_blocks_country_width", + "schema": "public", + "values": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] + }, + "public.enum_forms_blocks_email_width": { + "name": "enum_forms_blocks_email_width", + "schema": "public", + "values": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] + }, + "public.enum_forms_blocks_number_width": { + "name": "enum_forms_blocks_number_width", + "schema": "public", + "values": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] + }, + "public.enum_forms_blocks_select_width": { + "name": "enum_forms_blocks_select_width", + "schema": "public", + "values": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] + }, + "public.enum_forms_blocks_text_width": { + "name": "enum_forms_blocks_text_width", + "schema": "public", + "values": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] + }, + "public.enum_forms_blocks_textarea_width": { + "name": "enum_forms_blocks_textarea_width", + "schema": "public", + "values": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"] + }, + "public.enum_forms_confirmation_type": { + "name": "enum_forms_confirmation_type", + "schema": "public", + "values": ["message", "redirect"] + }, + "public.enum_forms_redirect_type": { + "name": "enum_forms_redirect_type", + "schema": "public", + "values": ["reference", "custom"] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + } +} diff --git a/apps/cms/src/migrations/20250326_200110_cod_282_2.ts b/apps/cms/src/migrations/20250326_200110_cod_282_2.ts new file mode 100644 index 000000000..b32407667 --- /dev/null +++ b/apps/cms/src/migrations/20250326_200110_cod_282_2.ts @@ -0,0 +1,25 @@ +import { MigrateDownArgs, MigrateUpArgs, sql } from '@payloadcms/db-postgres'; + +export async function up({ db, payload, req }: MigrateUpArgs): Promise { + await db.execute(sql` + ALTER TABLE "form_submissions" ADD COLUMN "tenant_id" integer; + DO $$ BEGIN + ALTER TABLE "form_submissions" ADD CONSTRAINT "form_submissions_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE set null ON UPDATE no action; + EXCEPTION + WHEN duplicate_object THEN null; + END $$; + + CREATE INDEX IF NOT EXISTS "form_submissions_tenant_idx" ON "form_submissions" USING btree ("tenant_id");`); +} + +export async function down({ + db, + payload, + req +}: MigrateDownArgs): Promise { + await db.execute(sql` + ALTER TABLE "form_submissions" DROP CONSTRAINT "form_submissions_tenant_id_tenants_id_fk"; + + DROP INDEX IF EXISTS "form_submissions_tenant_idx"; + ALTER TABLE "form_submissions" DROP COLUMN IF EXISTS "tenant_id";`); +} diff --git a/apps/cms/src/migrations/index.ts b/apps/cms/src/migrations/index.ts index 229e4c619..b8120fb86 100644 --- a/apps/cms/src/migrations/index.ts +++ b/apps/cms/src/migrations/index.ts @@ -7,6 +7,8 @@ import * as migration_20250305_165910_cod_254 from './20250305_165910_cod_254'; import * as migration_20250306_133219_cod_254_1 from './20250306_133219_cod_254_1'; import * as migration_20250314_143517_cod_280 from './20250314_143517_cod_280'; import * as migration_20250317_105827_cod_278 from './20250317_105827_cod_278'; +import * as migration_20250325_141317_cod_282 from './20250325_141317_cod_282'; +import * as migration_20250326_200110_cod_282_2 from './20250326_200110_cod_282_2'; export const migrations = [ { @@ -53,5 +55,15 @@ export const migrations = [ up: migration_20250317_105827_cod_278.up, down: migration_20250317_105827_cod_278.down, name: '20250317_105827_cod_278' + }, + { + up: migration_20250325_141317_cod_282.up, + down: migration_20250325_141317_cod_282.down, + name: '20250325_141317_cod_282' + }, + { + up: migration_20250326_200110_cod_282_2.up, + down: migration_20250326_200110_cod_282_2.down, + name: '20250326_200110_cod_282_2' } ]; diff --git a/apps/cms/src/payload.config.ts b/apps/cms/src/payload.config.ts index 84a7be2ff..3b469f42a 100644 --- a/apps/cms/src/payload.config.ts +++ b/apps/cms/src/payload.config.ts @@ -10,6 +10,7 @@ import { seed } from '@codeware/app-cms/feature/seed'; import { codeBlock, contentBlock, + formBlock, mediaBlock } from '@codeware/app-cms/ui/blocks'; import { defaultLexical } from '@codeware/app-cms/ui/fields'; @@ -43,7 +44,7 @@ export default buildConfig({ }, // Declare blocks globally and reference then by slug elsewhere // https://payloadcms.com/docs/fields/blocks#block-references - blocks: [codeBlock, contentBlock, mediaBlock], + blocks: [codeBlock, contentBlock, formBlock, mediaBlock], collections: [categories, media, pages, posts, tenants, users], cors: env.CORS_URLS === '*' ? '*' : env.CORS_URLS.split(',').filter(Boolean), csrf: env.CSRF_URLS ? env.CSRF_URLS.split(',').filter(Boolean) : undefined, diff --git a/apps/cms/src/tailwind.css b/apps/cms/src/tailwind.css deleted file mode 100644 index 8b14a9e47..000000000 --- a/apps/cms/src/tailwind.css +++ /dev/null @@ -1,5 +0,0 @@ -@layer codeware { - @tailwind base; - @tailwind components; - @tailwind utilities; -} diff --git a/apps/web/app/components/container.tsx b/apps/web/app/components/container.tsx index 3e25e14f1..fb24d54b9 100644 --- a/apps/web/app/components/container.tsx +++ b/apps/web/app/components/container.tsx @@ -1,4 +1,4 @@ -import clsx from 'clsx'; +import { cn } from '@codeware/shared/ui/shadcn'; import { forwardRef } from 'react'; export const ContainerOuter = forwardRef< @@ -6,7 +6,7 @@ export const ContainerOuter = forwardRef< React.ComponentPropsWithoutRef<'div'> >(function OuterContainer({ className, children, ...props }, ref) { return ( -
+
{children}
); @@ -19,7 +19,7 @@ export const ContainerInner = forwardRef< return (
{children}
diff --git a/apps/web/app/components/desktop-navigation.tsx b/apps/web/app/components/desktop-navigation.tsx index cb37127bb..e903e42df 100644 --- a/apps/web/app/components/desktop-navigation.tsx +++ b/apps/web/app/components/desktop-navigation.tsx @@ -1,5 +1,5 @@ +import { cn } from '@codeware/shared/ui/shadcn'; import { NavLink } from '@remix-run/react'; -import clsx from 'clsx'; import { filterPages } from '../utils/filter-pages'; import { usePages } from '../utils/pages'; @@ -16,7 +16,7 @@ function NavItem({ - clsx( + cn( 'relative block px-3 py-2 transition min-w-max', isActive ? 'text-teal-500 dark:text-teal-400' diff --git a/apps/web/app/root.tsx b/apps/web/app/root.tsx index 42a4abc91..7de88ec1d 100644 --- a/apps/web/app/root.tsx +++ b/apps/web/app/root.tsx @@ -1,3 +1,7 @@ +import { + PayloadProvider, + type PayloadValue +} from '@codeware/shared/ui/payload-components'; import { CdwrCloud } from '@codeware/shared/ui/react-components'; import { getShallow } from '@codeware/shared/util/payload-api'; import type { Page, Post } from '@codeware/shared/util/payload-types'; @@ -14,9 +18,12 @@ import { Scripts, ScrollRestoration, data, - useLoaderData + useLoaderData, + useNavigate } from '@remix-run/react'; +import env from '../env-resolver/env'; + import { Container } from './components/container'; import { DesktopNavigation } from './components/desktop-navigation'; import { GeneralErrorBoundary } from './components/error-boundary'; @@ -25,9 +32,8 @@ import { MobileNavigation } from './components/mobile-navigation'; import { ThemeSwitch, useTheme } from './routes/resources.theme-switch'; import stylesheet from './tailwind.css?url'; import { ClientHintCheck, getHints } from './utils/client-hints'; -import { getApiOptions } from './utils/get-api-options'; +import { getPayloadRequestOptions } from './utils/get-payload-request-options'; import { type Theme, getTheme } from './utils/theme.server'; - export type PageDetails = Pick & { slug: string }; export type PostDetails = Pick & { slug: string }; @@ -63,8 +69,13 @@ export async function loader({ context, request }: LoaderFunctionArgs) { // Fetch layout data but don't propagate the exception to the error boundary try { - pages = await getShallow('pages', getApiOptions(context, request)); - posts = await getShallow('posts', getApiOptions(context, request)); + const requestOptions = getPayloadRequestOptions( + 'GET', + context, + request.headers + ); + pages = await getShallow('pages', requestOptions); + posts = await getShallow('posts', requestOptions); } catch (e) { const error = e as Error; console.error(`Failed to load shallow data: ${error.message}`); @@ -87,6 +98,7 @@ export async function loader({ context, request }: LoaderFunctionArgs) { return { displayError, + env, pages: pageDetails, posts: postDetails, requestInfo: { @@ -137,10 +149,53 @@ export function Layout({ children }: { children: React.ReactNode }) { } export default function App() { - const data = useLoaderData(); + const loaderData = useLoaderData(); + const navigate = useNavigate(); + const theme = useTheme(); + + // Provide app opinionated context to Payload components + const context: PayloadValue = { + navigate: (path: string) => { + if (path.match(/^https?:\/\//)) { + console.warn( + 'Payload navigation to external URL is not supported:', + path + ); + } else { + navigate(path); + } + }, + payloadUrl: loaderData.env.PAYLOAD_URL, + submitForm: async (formData) => { + try { + // Send to server-side action to use secure API key authentication + const response = await fetch('/form-submission', { + method: 'POST', + body: JSON.stringify(formData), + headers: { + 'Content-Type': 'application/json' + } + }); + + if (!response.ok) { + throw new Error(`Server returned ${response.status}`); + } + + const result = await response.json(); + return { data: result, success: true }; + } catch (e) { + const error = e as Error; + return { + success: false, + data: { error: error?.message ?? 'Unknown error' } + }; + } + }, + theme + }; return ( - <> +
@@ -155,7 +210,7 @@ export default function App() {
- +
@@ -166,7 +221,7 @@ export default function App() {
@@ -176,16 +231,16 @@ export default function App() {
- {data.displayError && ( + {loaderData.displayError && (
-

{data.displayError}

+

{loaderData.displayError}

)}
- + ); } diff --git a/apps/web/app/routes/$slug.tsx b/apps/web/app/routes/$slug.tsx index a814ea81c..30bd0c17e 100644 --- a/apps/web/app/routes/$slug.tsx +++ b/apps/web/app/routes/$slug.tsx @@ -3,11 +3,8 @@ import { findBySlug } from '@codeware/shared/util/payload-api'; import type { LoaderFunctionArgs, MetaFunction } from '@remix-run/node'; import { json, useLoaderData, useRouteError } from '@remix-run/react'; -import env from '../../env-resolver/env'; import { Container } from '../components/container'; -import { getApiOptions } from '../utils/get-api-options'; - -import { useTheme } from './resources.theme-switch'; +import { getPayloadRequestOptions } from '../utils/get-payload-request-options'; type LoaderError = { message: string; @@ -37,7 +34,7 @@ export async function loader({ context, params, request }: LoaderFunctionArgs) { const page = await findBySlug( 'pages', slug, - getApiOptions(context, request) + getPayloadRequestOptions('GET', context, request.headers) ); if (!page) { const error: LoaderError = { @@ -46,7 +43,7 @@ export async function loader({ context, params, request }: LoaderFunctionArgs) { }; throw Response.json(error); } - return json({ page, apiUrl: env.PAYLOAD_URL }); + return json({ page }); } catch (e) { const error = e as Error; throw Response.json({ message: error.message }, { status: 404 }); @@ -54,8 +51,7 @@ export async function loader({ context, params, request }: LoaderFunctionArgs) { } export default function Page() { - const { page, apiUrl } = useLoaderData(); - const theme = useTheme(); + const { page } = useLoaderData(); return ( @@ -66,13 +62,8 @@ export default function Page() { )} -
- +
+
); diff --git a/apps/web/app/routes/_api.form-submission.tsx b/apps/web/app/routes/_api.form-submission.tsx new file mode 100644 index 000000000..8f5dcca84 --- /dev/null +++ b/apps/web/app/routes/_api.form-submission.tsx @@ -0,0 +1,56 @@ +import { post } from '@codeware/shared/util/payload-api'; +import type { FormSubmission } from '@codeware/shared/util/payload-types'; +import { type ActionFunctionArgs, json } from '@remix-run/node'; + +import { getPayloadRequestOptions } from '../utils/get-payload-request-options'; + +/** + * Handle form submission requests to the Payload REST API. + */ +export async function action({ context, request }: ActionFunctionArgs) { + if (request.method !== 'POST') { + return json({ message: 'Method not allowed' }, { status: 405 }); + } + if (request.headers.get('Content-Type') !== 'application/json') { + return json( + { message: 'Invalid content type, expecting "application/json"' }, + { status: 415 } + ); + } + + // Get the body from the request + const body = (await request.json()) as FormSubmission; + + if (!body?.form || !(body?.submissionData ?? []).length) { + return json({ message: 'Invalid form submission body' }, { status: 400 }); + } + + // Create request options with authentication + const requestOptions = getPayloadRequestOptions( + 'POST', + context, + request.headers, + body + ); + + console.log('Send form submission request', requestOptions); + + try { + const response = await post('form-submissions', requestOptions); + return json({ success: true, data: response }); + } catch (e) { + const error = e as Error; + return json( + { success: false, data: { error: error?.message ?? 'Unknown error' } }, + { status: 400 } + ); + } +} + +// Add a loader to handle GET requests if needed +export async function loader() { + return json( + { message: 'This endpoint only accepts POST requests' }, + { status: 405 } + ); +} diff --git a/apps/web/app/routes/_index.tsx b/apps/web/app/routes/_index.tsx index 0576a93af..ae2c6b0eb 100644 --- a/apps/web/app/routes/_index.tsx +++ b/apps/web/app/routes/_index.tsx @@ -3,11 +3,8 @@ import { findBySlug } from '@codeware/shared/util/payload-api'; import { type LoaderFunctionArgs, json } from '@remix-run/node'; import { MetaFunction, useLoaderData, useRouteError } from '@remix-run/react'; -import env from '../../env-resolver/env'; import { Container } from '../components/container'; -import { getApiOptions } from '../utils/get-api-options'; - -import { useTheme } from './resources.theme-switch'; +import { getPayloadRequestOptions } from '../utils/get-payload-request-options'; type LoaderError = { message: string; @@ -27,7 +24,7 @@ export async function loader({ context, request }: LoaderFunctionArgs) { const page = await findBySlug( 'pages', 'home', - getApiOptions(context, request) + getPayloadRequestOptions('GET', context, request.headers) ); if (!page) { @@ -38,12 +35,11 @@ export async function loader({ context, request }: LoaderFunctionArgs) { throw Response.json(error); } - return json({ page, apiUrl: env.PAYLOAD_URL }); + return json({ page }); } export default function Index() { - const { page, apiUrl } = useLoaderData(); - const theme = useTheme(); + const { page } = useLoaderData(); return ( @@ -54,13 +50,8 @@ export default function Index() { )} -
- +
+
); diff --git a/apps/web/app/tailwind.css b/apps/web/app/tailwind.css index b5c61c956..78f3563fe 100644 --- a/apps/web/app/tailwind.css +++ b/apps/web/app/tailwind.css @@ -1,3 +1,67 @@ @tailwind base; @tailwind components; @tailwind utilities; + +/* + * Variables required by shadcn/ui. + * Keep in sync with Tailwind theme variables. + */ +@layer base { + :root { + --background: theme('colors.white'); + --foreground: theme('colors.zinc.600'); + --primary: theme('colors.zinc.900'); + --primary-foreground: theme('colors.zinc.50'); + --secondary: theme('colors.zinc.100'); + --secondary-foreground: theme('colors.zinc.900'); + --accent: theme('colors.zinc.100'); + --accent-foreground: theme('colors.zinc.900'); + --muted: theme('colors.zinc.100'); + --muted-foreground: theme('colors.zinc.500'); + --destructive: theme('colors.red.500'); + --destructive-foreground: theme('colors.zinc.50'); + --border: theme('colors.zinc.100'); + --ring: theme('colors.zinc.900'); + --card: theme('colors.zinc.50'); + --card-foreground: theme('colors.zinc.900'); + --input: theme('colors.zinc.100'); + --popover: theme('colors.zinc.50'); + --popover-foreground: theme('colors.zinc.900'); + --radius: 0.5rem; + } + + .dark { + --background: theme('colors.zinc.900'); + --foreground: theme('colors.zinc.400'); + --primary: theme('colors.zinc.700'); + --primary-foreground: theme('colors.zinc.300'); + --secondary: theme('colors.zinc.800'); + --secondary-foreground: theme('colors.zinc.100'); + --accent: theme('colors.zinc.800'); + --accent-foreground: theme('colors.zinc.100'); + --muted: theme('colors.zinc.400'); + --muted-foreground: theme('colors.zinc.500'); + --destructive: theme('colors.red.600'); + --destructive-foreground: theme('colors.zinc.100'); + --border: theme('colors.zinc.700/0.4'); + --ring: theme('colors.zinc.700'); + --card: theme('colors.zinc.800'); + --card-foreground: theme('colors.zinc.100'); + --input: theme('colors.zinc.700/0.4'); + --popover: theme('colors.zinc.800'); + --popover-foreground: theme('colors.zinc.100'); + --radius: 0.5rem; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + /* font-feature-settings: + 'rlig' 1, + 'calt' 1; */ + } +} diff --git a/apps/web/app/utils/get-api-options.ts b/apps/web/app/utils/get-api-options.ts deleted file mode 100644 index e8395fb40..000000000 --- a/apps/web/app/utils/get-api-options.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type { RequestOptions } from '@codeware/shared/util/payload-api'; -import type { AppLoadContext as RemixAppLoadContext } from '@remix-run/node'; - -import env from '../../env-resolver/env'; - -export type AppLoadContext = { - deviceId: string; - tenantApiKey: string; - tenantId: string; -}; - -/** - * Get the options for a request to the Payload API. - * - * Api key authorization and signature verification are enabled. - * - * @param context - The context of the request. - * @param request - The request. - * @returns The options for the request. - */ -export const getApiOptions = ( - context: AppLoadContext | RemixAppLoadContext, - request: Request -): RequestOptions => { - const { deviceId, tenantApiKey, tenantId } = context as AppLoadContext; - return { - apiUrl: env.PAYLOAD_URL, - debug: env.DEBUG, - request, - useSignature: { - deployEnv: env.DEPLOY_ENV, - deviceId, - secret: env.SIGNATURE_SECRET, - tenantId - }, - tenantApiKey - }; -}; diff --git a/apps/web/app/utils/get-payload-request-options.ts b/apps/web/app/utils/get-payload-request-options.ts new file mode 100644 index 000000000..96b77f9c1 --- /dev/null +++ b/apps/web/app/utils/get-payload-request-options.ts @@ -0,0 +1,69 @@ +import type { + MethodOptions, + RequestBaseOptions, + RequestMethod +} from '@codeware/shared/util/payload-api'; +import type { AppLoadContext as RemixAppLoadContext } from '@remix-run/node'; + +import env from '../../env-resolver/env'; + +export type AppLoadContext = { + deviceId: string; + tenantApiKey: string; + tenantId: string; +}; + +/** + * Get the options for a request to the Payload REST API. + * + * Api key authorization and signature verification are enabled. + * + * @param context - The context of the request. + * @param request - The request. + * @returns The options for the request. + */ +export function getPayloadRequestOptions( + method: 'GET', + context: AppLoadContext | RemixAppLoadContext, + headers?: Headers +): RequestBaseOptions; +export function getPayloadRequestOptions>( + method: 'POST', + context: AppLoadContext | RemixAppLoadContext, + headers?: Headers, + body?: TBody +): RequestBaseOptions & MethodOptions<'POST'>; +export function getPayloadRequestOptions< + T extends RequestMethod, + TBody = Record +>( + method: T, + context: AppLoadContext | RemixAppLoadContext, + headers?: Headers, + body?: TBody +): RequestBaseOptions | (RequestBaseOptions & MethodOptions<'POST'>) { + const { deviceId, tenantApiKey, tenantId } = context as AppLoadContext; + + const baseOptions: RequestBaseOptions = { + apiUrl: env.PAYLOAD_URL, + debug: env.DEBUG, + headers, + signatureVertification: { + deployEnv: env.DEPLOY_ENV, + deviceId, + secret: env.SIGNATURE_SECRET, + tenantId, + userAgent: headers?.get('User-Agent') ?? null + }, + tenantApiKey + }; + + if (method === 'GET') { + return baseOptions; + } + + return { + ...baseOptions, + body: body ?? {} + }; +} diff --git a/apps/web/eslint.config.mjs b/apps/web/eslint.config.mjs index 8c22ae5c5..c871ef4fa 100644 --- a/apps/web/eslint.config.mjs +++ b/apps/web/eslint.config.mjs @@ -23,10 +23,28 @@ export default [ // Payload 'react-dom', // Remix + 'isbot', + // Payload components '@heroicons/react', '@payloadcms/richtext-lexical', - 'isbot', 'prism-react-renderer', + // Payload components - Tailwind/Shadcn + '@radix-ui/react-checkbox', + '@radix-ui/react-dialog', + '@radix-ui/react-dropdown-menu', + '@radix-ui/react-label', + '@radix-ui/react-menubar', + '@radix-ui/react-radio-group', + '@radix-ui/react-select', + '@radix-ui/react-slot', + 'class-variance-authority', + 'clsx', + 'lucide-react', + 'next-themes', + 'react-hook-form', + 'sonner', + 'tailwind-merge', + 'tailwindcss-animate', // Dev dependencies '@nx/vite', '@remix-run/testing', diff --git a/apps/web/package.json b/apps/web/package.json index 31033350a..f0bfb4421 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -13,18 +13,33 @@ "@infisical/sdk": "^3.0.4", "@nx/react": "^20.0.0", "@payloadcms/richtext-lexical": "^3.23.0", + "@radix-ui/react-checkbox": "^1.1.4", + "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-dropdown-menu": "^2.1.6", + "@radix-ui/react-label": "^2.1.2", + "@radix-ui/react-menubar": "^1.1.6", + "@radix-ui/react-radio-group": "^1.2.3", + "@radix-ui/react-select": "^2.1.6", + "@radix-ui/react-slot": "^1.1.2", "@remix-run/node": "^2.16.0", "@remix-run/react": "^2.16.0", "@tailwindcss/typography": "^0.5.15", + "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "hono": "^4.6.10", "isbot": "^4.4.0", "jsonc-eslint-parser": "2.4.0", + "lucide-react": "^0.483.0", + "next-themes": "^0.4.6", "prism-react-renderer": "2.4.1", "react": "19.0.0", "react-dom": "19.0.0", + "react-hook-form": "^7.54.2", "remix-hono": "^0.0.16", "remix-utils": "^8.4.0", + "sonner": "^2.0.1", + "tailwind-merge": "^2.3.0", + "tailwindcss-animate": "^1.0.7", "tiny-invariant": "^1.3.3", "zod": "^3.23.8" }, diff --git a/apps/web/tailwind.config.cjs b/apps/web/tailwind.config.cjs index e08945cd2..99bbc0382 100644 --- a/apps/web/tailwind.config.cjs +++ b/apps/web/tailwind.config.cjs @@ -13,6 +13,64 @@ module.exports = { ], darkMode: 'selector', theme: { + extend: { + // shadcn/ui css support: + // Variables are defined in app/tailwind.css + colors: { + border: 'var(--border)', + input: 'var(--input)', + ring: 'var(--ring)', + background: 'var(--background)', + foreground: 'var(--foreground)', + primary: { + DEFAULT: 'var(--primary)', + foreground: 'var(--primary-foreground)' + }, + secondary: { + DEFAULT: 'var(--secondary)', + foreground: 'var(--secondary-foreground)' + }, + destructive: { + DEFAULT: 'var(--destructive)', + foreground: 'var(--destructive-foreground)' + }, + muted: { + DEFAULT: 'var(--muted)', + foreground: 'var(--muted-foreground)' + }, + accent: { + DEFAULT: 'var(--accent)', + foreground: 'var(--accent-foreground)' + }, + popover: { + DEFAULT: 'var(--popover)', + foreground: 'var(--popover-foreground)' + }, + card: { + DEFAULT: 'var(--card)', + foreground: 'var(--card-foreground)' + } + }, + borderRadius: { + lg: `var(--radius)`, + md: `calc(var(--radius) - 2px)`, + sm: 'calc(var(--radius) - 4px)' + }, + keyframes: { + 'accordion-down': { + from: { height: '0' }, + to: { height: 'var(--radix-accordion-content-height)' } + }, + 'accordion-up': { + from: { height: 'var(--radix-accordion-content-height)' }, + to: { height: '0' } + } + }, + animation: { + 'accordion-down': 'accordion-down 0.2s ease-out', + 'accordion-up': 'accordion-up 0.2s ease-out' + } + }, fontSize: { xs: ['0.8125rem', { lineHeight: '1.5rem' }], sm: ['0.875rem', { lineHeight: '1.5rem' }], @@ -30,5 +88,5 @@ module.exports = { }, typography: typographyStyles }, - plugins: [require('@tailwindcss/typography')] + plugins: [require('@tailwindcss/typography'), require('tailwindcss-animate')] }; diff --git a/apps/web/typography.cjs b/apps/web/typography.cjs index 71982417e..687e37475 100644 --- a/apps/web/typography.cjs +++ b/apps/web/typography.cjs @@ -70,7 +70,7 @@ module.exports = function typographyStyles({ theme }) { color: 'var(--tw-prose-body)', lineHeight: theme('lineHeight.7'), '> *': { - marginTop: theme('spacing.10'), + // marginTop: theme('spacing.10'), marginBottom: theme('spacing.10') }, p: { @@ -86,18 +86,18 @@ module.exports = function typographyStyles({ theme }) { h2: { fontSize: theme('fontSize.xl')[0], lineHeight: theme('lineHeight.7'), - marginTop: theme('spacing.20'), + // marginTop: theme('spacing.20'), marginBottom: theme('spacing.4') }, h3: { fontSize: theme('fontSize.base')[0], lineHeight: theme('lineHeight.7'), - marginTop: theme('spacing.16'), + // marginTop: theme('spacing.16'), marginBottom: theme('spacing.4') }, - ':is(h2, h3) + *': { - marginTop: 0 - }, + // ':is(h2, h3) + *': { + // marginTop: 0 + // }, // Images img: { @@ -275,11 +275,6 @@ module.exports = function typographyStyles({ theme }) { }, ':is(tbody, tfoot) td:not(:last-child)': { paddingRight: theme('spacing.2') - }, - - // Grid - '.grid :is(h1, h2, h3, h4, p):first-of-type': { - marginTop: 0 } } } diff --git a/components.json b/components.json new file mode 100644 index 000000000..a2411a496 --- /dev/null +++ b/components.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "default", + "rsc": false, + "tailwind": { + "config": "libs/shared/ui/shadcn/src/lib/tailwind.config.ts", + "css": "libs/shared/ui/shadcn/src/lib/global.css", + "baseColor": "neutral", + "cssVariables": true + }, + "aliases": { + "components": "@codeware/shared/ui/shadcn/components", + "hooks": "@codeware/shared/ui/shadcn/hooks", + "ui": "@codeware/shared/ui/shadcn/components", + "utils": "@codeware/shared/ui/shadcn/utils" + } +} diff --git a/eslint.config.mjs b/eslint.config.mjs index 4bbf85667..403a03a00 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -36,11 +36,13 @@ export default [ 'scope:core', 'scope:shared', 'domain:signature' - ] + ], + notDependOnLibsWithTags: ['domain:client'] }, { sourceTag: 'scope:app-cms', - onlyDependOnLibsWithTags: ['scope:app-cms', 'scope:shared'] + onlyDependOnLibsWithTags: ['scope:app-cms', 'scope:shared'], + notDependOnLibsWithTags: ['domain:client'] }, { sourceTag: 'scope:web', diff --git a/libs/app-cms/ui/blocks/src/index.ts b/libs/app-cms/ui/blocks/src/index.ts index 0c76ebe83..cd8a856dc 100644 --- a/libs/app-cms/ui/blocks/src/index.ts +++ b/libs/app-cms/ui/blocks/src/index.ts @@ -1,3 +1,4 @@ export { codeBlock } from './lib/code/code.block'; export { contentBlock } from './lib/content/content.block'; +export { formBlock } from './lib/form/form.block'; export { mediaBlock } from './lib/media/media.block'; diff --git a/libs/app-cms/ui/blocks/src/lib/content/content.block.ts b/libs/app-cms/ui/blocks/src/lib/content/content.block.ts index bc905e686..3af9a45fc 100644 --- a/libs/app-cms/ui/blocks/src/lib/content/content.block.ts +++ b/libs/app-cms/ui/blocks/src/lib/content/content.block.ts @@ -49,8 +49,10 @@ export const contentBlock: Block = { features: ({ rootFeatures }) => { return [ ...rootFeatures, - BlocksFeature({ blocks: ['code', 'media'] }), - HeadingFeature({ enabledHeadingSizes: ['h2', 'h3', 'h4'] }) + BlocksFeature({ blocks: ['code', 'form', 'media'] }), + HeadingFeature({ + enabledHeadingSizes: ['h2', 'h3', 'h4', 'h5'] + }) ]; } }), diff --git a/libs/app-cms/ui/blocks/src/lib/form/form.block.ts b/libs/app-cms/ui/blocks/src/lib/form/form.block.ts new file mode 100644 index 000000000..4729386c7 --- /dev/null +++ b/libs/app-cms/ui/blocks/src/lib/form/form.block.ts @@ -0,0 +1,47 @@ +import { lexicalEditor } from '@payloadcms/richtext-lexical'; +import { HeadingFeature } from '@payloadcms/richtext-lexical'; +import type { Block } from 'payload'; + +/** + * Form block for building a custom form. + */ +export const formBlock: Block = { + slug: 'form', + interfaceName: 'FormBlock', + labels: { + plural: 'Form Blocks', + singular: 'Form Block' + }, + fields: [ + { + name: 'form', + type: 'relationship', + relationTo: 'forms', + required: true + }, + { + name: 'enableIntro', + type: 'checkbox', + label: { + en: 'Add an introduction to the form', + sv: 'Lägg till en introduktion till formuläret' + } + }, + { + name: 'introContent', + type: 'richText', + label: { en: 'Introduction', sv: 'Introduktion' }, + admin: { + condition: (_, { enableIntro }) => Boolean(enableIntro) + }, + editor: lexicalEditor({ + features: ({ rootFeatures }) => { + return [ + ...rootFeatures, + HeadingFeature({ enabledHeadingSizes: ['h1', 'h2', 'h3', 'h4'] }) + ]; + } + }) + } + ] +}; diff --git a/libs/app-cms/util/plugins/src/index.ts b/libs/app-cms/util/plugins/src/index.ts index 5f3035026..6ba81a336 100644 --- a/libs/app-cms/util/plugins/src/index.ts +++ b/libs/app-cms/util/plugins/src/index.ts @@ -1 +1 @@ -export { getPugins } from './lib/plugins'; +export { getPugins } from './lib/get-plugins'; diff --git a/libs/app-cms/util/plugins/src/lib/get-plugins.ts b/libs/app-cms/util/plugins/src/lib/get-plugins.ts new file mode 100644 index 000000000..72f1f1f10 --- /dev/null +++ b/libs/app-cms/util/plugins/src/lib/get-plugins.ts @@ -0,0 +1,20 @@ +import type { Env } from '@codeware/app-cms/util/env-schema'; +import type { Plugin } from 'payload'; + +import { getFormsPlugin } from './plugins/get-forms-plugin'; +import { getMultiTenantPlugin } from './plugins/get-multi-tenant-plugin'; +import { getS3StoragePlugin } from './plugins/get-s3-storage-plugin'; +import { getSeoPlugin } from './plugins/get-seo-plugin'; + +/** + * Get the Payload plugins. + * + * @param env - The environment variables + * @returns Array of plugins + */ +export const getPugins = (env: Env): Array => [ + getFormsPlugin(), + getMultiTenantPlugin(), + getSeoPlugin(), + getS3StoragePlugin(env) +]; diff --git a/libs/app-cms/util/plugins/src/lib/plugins.ts b/libs/app-cms/util/plugins/src/lib/plugins.ts deleted file mode 100644 index 458d7c7cd..000000000 --- a/libs/app-cms/util/plugins/src/lib/plugins.ts +++ /dev/null @@ -1,89 +0,0 @@ -import type { Env } from '@codeware/app-cms/util/env-schema'; -import { hasRole } from '@codeware/app-cms/util/misc'; -import type { Page, Post } from '@codeware/shared/util/payload-types'; -import { multiTenantPlugin } from '@payloadcms/plugin-multi-tenant'; -import { seoPlugin } from '@payloadcms/plugin-seo'; -import type { GenerateTitle, GenerateURL } from '@payloadcms/plugin-seo/types'; -import { s3Storage } from '@payloadcms/storage-s3'; -import type { Config, Plugin } from 'payload'; - -/** - * Get the Payload plugins. - * - * @param env - The environment variables - * @returns Array of plugins - */ -export const getPugins = (env: Env): Array => { - // SEO auto-generate functions - const generateTitle: GenerateTitle = async ({ doc }) => - 'name' in doc ? doc.name : doc.title; - const generateURL: GenerateURL = async ({ - collectionSlug, - doc, - req: { origin } - }) => `${origin}/${collectionSlug}/${doc.slug ?? ''}`; - - // S3 storage configuration. - // Important! - // Plugins that have components must always be enabled. - // Otherwise those components will not be generated in `importMap.js`. - // To support run-time enable/disable, we can force all plugins to be enabled for some Nx targets. - // Hopefully this will be adressed by Payload to make `importMap.js` include all defined plugins by default. - const s3 = (env.S3_STORAGE ?? {}) as NonNullable; - const s3Enabled = - Boolean(s3.bucket) || - // TODO: Running `dev` target without S3 will trigger db sync to remove prefix column from media collection. - // Until this is fixed (by Payload?) it's better to use S3 for develpment as well. - ['build', 'gen', 'payload'].includes(env.NX_TASK_TARGET_TARGET); - - return [ - // Multi-tenant - multiTenantPlugin({ - // Default values, but specified for clarity - cleanupAfterTenantDelete: true, - tenantsSlug: 'tenants', - tenantField: { - name: 'tenant' - }, - collections: { - categories: {}, - media: {}, - pages: {}, - posts: {} - }, - tenantsArrayField: { - includeDefaultField: false - }, - tenantSelectorLabel: { en: 'Workspace scope', sv: 'Vald arbetsyta' }, - userHasAccessToAllTenants: (user) => hasRole(user, 'system-user') - }), - - // SEO - seoPlugin({ - uploadsCollection: 'media', - generateTitle, - generateURL - }), - - // S3 Storage - s3Storage({ - collections: { - media: { - disableLocalStorage: true, - prefix: 'media' - } - }, - bucket: s3.bucket, - config: { - credentials: { - accessKeyId: s3.credentials?.accessKeyId, - secretAccessKey: s3.credentials?.secretAccessKey - }, - forcePathStyle: s3.forcePathStyle, - region: s3.region, - endpoint: s3.endpoint - }, - enabled: s3Enabled - }) - ]; -}; diff --git a/libs/app-cms/util/plugins/src/lib/plugins/forms/customized-fields.ts b/libs/app-cms/util/plugins/src/lib/plugins/forms/customized-fields.ts new file mode 100644 index 000000000..f55ed3ba5 --- /dev/null +++ b/libs/app-cms/util/plugins/src/lib/plugins/forms/customized-fields.ts @@ -0,0 +1,130 @@ +import { fields as defaultFields } from '@payloadcms/plugin-form-builder'; +import { type Block, Field } from 'payload'; + +/** + * Customized width field for form builder. + * + * Replace the default width field with a select field + * to allow selecting the width from a list of predefined values. + */ +const widthSelect: Field = { + name: 'width', + type: 'select', + interfaceName: 'FieldWidth', + label: 'Field width', + options: [ + { label: '1', value: '1' }, + { label: '2', value: '2' }, + { label: '3', value: '3' }, + { label: '4', value: '4' }, + { label: '5', value: '5' }, + { label: '6', value: '6' }, + { label: '7', value: '7' }, + { label: '8', value: '8' }, + { label: '9', value: '9' }, + { label: '10', value: '10' }, + { label: '11', value: '11' }, + { label: '12 (full width)', value: '12' } + ], + defaultValue: '12', + admin: { + description: 'Set the width of the field in the 12 column grid layout.' + } +}; + +/** + * Extend the default form block fields with placeholder when it doesn't exist. + * + * Add the placeholder last on the row with a label field + * and distribute the width evenly for all row fields. + */ +export const customizedFields = Object.keys(defaultFields).reduce( + (acc, fieldName) => { + const block = defaultFields[fieldName] as Block; + + // Ignore block fields that we don't want to customize at all + if (['payment', 'state'].includes(fieldName)) { + acc[fieldName] = block; + return acc; + } + + // Ignore checkbox since a placeholder makes no sense. + if (fieldName !== 'checkbox') { + // Check if a placeholder is already present as a field or row field. + const phField = block.fields?.find( + (f) => f.type === 'text' && f.name === 'placeholder' + ); + const phRowField = block.fields?.find( + (f) => + f.type === 'row' && + f.fields.some((f) => f.type === 'text' && f.name === 'placeholder') + ); + + if (phField || phRowField) { + // Placeholder already present + acc[fieldName] = block; + return acc; + } + + // Add placeholder field to the row with a label field + const rowWithLabel = block.fields?.find( + (fRow) => + fRow.type === 'row' && + fRow.fields.some((f) => f.type === 'text' && f.name === 'label') + ); + + // Add placeholder field to the row + if (rowWithLabel && rowWithLabel.type === 'row') { + rowWithLabel.fields.push({ + name: 'placeholder', + type: 'text', + label: 'Placeholder', + localized: true, + admin: { + width: '' // Updated below... + } + }); + + // Distribute width of row over all cells + const fieldWidth = Math.floor(100 / rowWithLabel.fields.length); + const restWidth = 100 - fieldWidth * rowWithLabel.fields.length; + + for (let i = 0; i < rowWithLabel.fields.length; i++) { + const cell = rowWithLabel.fields[i]; + cell.admin = cell.admin || {}; + cell.admin.width = `${fieldWidth + (i === 0 ? restWidth : 0)}%`; + } + } + } + + // Replace width field based on percentage (number) to a grid based with 12 columns + + // The width field can be located as a normal field or as a row field + for (let index = 0; index < (block.fields ?? []).length; index++) { + const lookupField = block.fields[index]; + + if (lookupField.type === 'number' && lookupField.name === 'width') { + // Found as normal field; replace it and stop looking for row fields + block.fields[index] = widthSelect; + break; + } + + // Lookup within any row fields + if (lookupField.type === 'row') { + const rowFieldIndex = lookupField.fields.findIndex( + (f) => f.type === 'number' && f.name === 'width' + ); + if (rowFieldIndex >= 0) { + // Found within row field; replace it and stop looking for more + lookupField.fields[rowFieldIndex] = widthSelect; + break; + } + } + } + + // Set the possibly modified field + acc[fieldName] = block; + return acc; + }, + {} as Record +); diff --git a/libs/app-cms/util/plugins/src/lib/plugins/forms/ensure-tenant.ts b/libs/app-cms/util/plugins/src/lib/plugins/forms/ensure-tenant.ts new file mode 100644 index 000000000..ca4ad5c71 --- /dev/null +++ b/libs/app-cms/util/plugins/src/lib/plugins/forms/ensure-tenant.ts @@ -0,0 +1,19 @@ +import { isTenant } from '@codeware/app-cms/util/misc'; +import type { FormSubmission } from '@codeware/shared/util/payload-types'; +import type { CollectionBeforeValidateHook } from 'payload'; + +export const ensureTenant: CollectionBeforeValidateHook< + FormSubmission +> = async ({ req: { user }, data, operation }) => { + if (operation !== 'create' || !data) { + return data; + } + + if (!isTenant(user)) { + return data; + } + + // Update tenant from the request + data.tenant = user.id; + return data; +}; diff --git a/libs/app-cms/util/plugins/src/lib/plugins/forms/tenant-access.ts b/libs/app-cms/util/plugins/src/lib/plugins/forms/tenant-access.ts new file mode 100644 index 000000000..b6a2e9dcc --- /dev/null +++ b/libs/app-cms/util/plugins/src/lib/plugins/forms/tenant-access.ts @@ -0,0 +1,62 @@ +import { getUserTenantIDs, hasRole } from '@codeware/app-cms/util/misc'; +import type { Access } from 'payload'; +import { parseCookies } from 'payload'; + +/** + * Custom tenant read access control for form submissions. + * + * Form submissions collection doesn't have a tenant field + * as the documents are created by the client via fetch request + * without any tenant context. + * + * Instead we lookup the connected forms, which have tenant details + * and compare with the user's tenant IDs. + * + * @deprecated Use `ensureTenant` instead. + * + * Kept as a valuable function that might be usable elsewhere. + */ +export const tenantAccess: Access = async ({ + req: { headers, payload, user } +}) => { + // Get tenant if scoped via cookie + const tenantCookieName = `${payload.config.cookiePrefix}-tenant`; + const selectedTenant = parseCookies(headers).get(tenantCookieName); + + // Get tenant IDs for the user + const userTenantIDs = getUserTenantIDs(user); + + let tenantIDs: Array = []; + + if (selectedTenant) { + // Only allow access to the selected tenant forms + tenantIDs = [Number(selectedTenant)]; + } else if (hasRole(user, 'system-user')) { + // System user can access all when no tenant is selected + return true; + } else { + // User can access all forms for their tenant IDs + tenantIDs = userTenantIDs; + } + + // Get all forms for the tenant IDs + const forms = await payload.find({ + collection: 'forms', + where: { tenant: { in: tenantIDs } }, + depth: 0, + pagination: false + }); + + if (forms.totalDocs === 0) { + return false; + } + + const formIds = forms.docs.map((form) => form.id); + + // Query form submissions for the form ids + return { + form: { + in: formIds + } + }; +}; diff --git a/libs/app-cms/util/plugins/src/lib/plugins/get-forms-plugin.ts b/libs/app-cms/util/plugins/src/lib/plugins/get-forms-plugin.ts new file mode 100644 index 000000000..bceae7395 --- /dev/null +++ b/libs/app-cms/util/plugins/src/lib/plugins/get-forms-plugin.ts @@ -0,0 +1,21 @@ +import { formBuilderPlugin } from '@payloadcms/plugin-form-builder'; + +import { customizedFields } from './forms/customized-fields'; +import { ensureTenant } from './forms/ensure-tenant'; + +export const getFormsPlugin = () => { + return formBuilderPlugin({ + fields: { + ...customizedFields, + // Disable unsupported form fields + payment: false, + state: false + }, + formSubmissionOverrides: { + hooks: { + beforeValidate: [ensureTenant] + } + }, + redirectRelationships: ['pages'] + }); +}; diff --git a/libs/app-cms/util/plugins/src/lib/plugins/get-multi-tenant-plugin.ts b/libs/app-cms/util/plugins/src/lib/plugins/get-multi-tenant-plugin.ts new file mode 100644 index 000000000..984478599 --- /dev/null +++ b/libs/app-cms/util/plugins/src/lib/plugins/get-multi-tenant-plugin.ts @@ -0,0 +1,28 @@ +import { hasRole } from '@codeware/app-cms/util/misc'; +import type { Config } from '@codeware/shared/util/payload-types'; +import { multiTenantPlugin } from '@payloadcms/plugin-multi-tenant'; + +export const getMultiTenantPlugin = () => { + return multiTenantPlugin({ + // Default values, but specified for clarity + cleanupAfterTenantDelete: true, + debug: false, + tenantsSlug: 'tenants', + tenantField: { + name: 'tenant' + }, + collections: { + categories: {}, + forms: {}, + 'form-submissions': {}, + media: {}, + pages: {}, + posts: {} + }, + tenantsArrayField: { + includeDefaultField: false + }, + tenantSelectorLabel: { en: 'Workspace scope', sv: 'Vald arbetsyta' }, + userHasAccessToAllTenants: (user) => hasRole(user, 'system-user') + }); +}; diff --git a/libs/app-cms/util/plugins/src/lib/plugins/get-s3-storage-plugin.ts b/libs/app-cms/util/plugins/src/lib/plugins/get-s3-storage-plugin.ts new file mode 100644 index 000000000..6baf1812a --- /dev/null +++ b/libs/app-cms/util/plugins/src/lib/plugins/get-s3-storage-plugin.ts @@ -0,0 +1,37 @@ +import type { Env } from '@codeware/app-cms/util/env-schema'; +import { s3Storage } from '@payloadcms/storage-s3'; + +export const getS3StoragePlugin = (env: Env) => { + // S3 storage configuration. + // Important! + // Plugins that have components must always be enabled. + // Otherwise those components will not be generated in `importMap.js`. + // To support run-time enable/disable, we can force all plugins to be enabled for some Nx targets. + // Hopefully this will be adressed by Payload to make `importMap.js` include all defined plugins by default. + const s3 = (env.S3_STORAGE ?? {}) as NonNullable; + const s3Enabled = + Boolean(s3.bucket) || + // TODO: Running `dev` target without S3 will trigger db sync to remove prefix column from media collection. + // Until this is fixed (by Payload?) it's better to use S3 for develpment as well. + ['build', 'gen', 'payload'].includes(env.NX_TASK_TARGET_TARGET); + + return s3Storage({ + collections: { + media: { + disableLocalStorage: true, + prefix: 'media' + } + }, + bucket: s3.bucket, + config: { + credentials: { + accessKeyId: s3.credentials?.accessKeyId, + secretAccessKey: s3.credentials?.secretAccessKey + }, + forcePathStyle: s3.forcePathStyle, + region: s3.region, + endpoint: s3.endpoint + }, + enabled: s3Enabled + }); +}; diff --git a/libs/app-cms/util/plugins/src/lib/plugins/get-seo-plugin.ts b/libs/app-cms/util/plugins/src/lib/plugins/get-seo-plugin.ts new file mode 100644 index 000000000..aca621738 --- /dev/null +++ b/libs/app-cms/util/plugins/src/lib/plugins/get-seo-plugin.ts @@ -0,0 +1,22 @@ +import type { Page, Post } from '@codeware/shared/util/payload-types'; +import { seoPlugin } from '@payloadcms/plugin-seo'; +import type { GenerateTitle, GenerateURL } from '@payloadcms/plugin-seo/types'; + +// SEO auto-generate functions + +const generateTitle: GenerateTitle = async ({ doc }) => + 'name' in doc ? doc.name : doc.title; + +const generateURL: GenerateURL = async ({ + collectionSlug, + doc, + req: { origin } +}) => `${origin}/${collectionSlug}/${doc.slug ?? ''}`; + +export const getSeoPlugin = () => { + return seoPlugin({ + uploadsCollection: 'media', + generateTitle, + generateURL + }); +}; diff --git a/libs/shared/ui/payload-components/README.md b/libs/shared/ui/payload-components/README.md new file mode 100644 index 000000000..e94a1539a --- /dev/null +++ b/libs/shared/ui/payload-components/README.md @@ -0,0 +1,15 @@ +# Payload Components for Clients + +These components are designed to be used by clients that depends on Payload headless CMS. + +The client fetches data from Payload API and use one or many of the components to render the UI. + +The reason for scoping to clients is the dependency to `RenderBlocksProvider` that must be used near the application root, and the fact that the components converts Api data to React elements. + +## Types + +Payload types are used in this project to get type safe components. + +## Enforce module boundaries + +To enforce this contraint the project have the tag `domain:client`, which is a forbidden tag for `scope:app` and `scope:app-cms`. diff --git a/libs/shared/ui/payload-components/project.json b/libs/shared/ui/payload-components/project.json index 1a07fa5a8..657f26632 100644 --- a/libs/shared/ui/payload-components/project.json +++ b/libs/shared/ui/payload-components/project.json @@ -3,6 +3,6 @@ "$schema": "../../../../node_modules/nx/schemas/project-schema.json", "sourceRoot": "libs/shared/ui/payload-components/src", "projectType": "library", - "tags": ["scope:shared", "type:ui"], + "tags": ["scope:shared", "type:ui", "domain:client"], "targets": {} } diff --git a/libs/shared/ui/payload-components/src/index.ts b/libs/shared/ui/payload-components/src/index.ts index 41af806d8..40b491a7f 100644 --- a/libs/shared/ui/payload-components/src/index.ts +++ b/libs/shared/ui/payload-components/src/index.ts @@ -1,6 +1,7 @@ -export * from './lib/CodeBlock'; -export * from './lib/ContentBlock'; -export * from './lib/MediaBlock'; -export * from './lib/RichText'; +export * from './lib/blocks/CodeBlock'; +export * from './lib/blocks/ContentBlock'; +export * from './lib/blocks/MediaBlock'; +export * from './lib/blocks/RichText'; export * from './lib/RenderBlocks'; -export * from './lib/render-blocks.type'; + +export * from './lib/providers/PayloadProvider'; diff --git a/libs/shared/ui/payload-components/src/lib/RenderBlocks.tsx b/libs/shared/ui/payload-components/src/lib/RenderBlocks.tsx index 7d111cb5e..c37d5baba 100644 --- a/libs/shared/ui/payload-components/src/lib/RenderBlocks.tsx +++ b/libs/shared/ui/payload-components/src/lib/RenderBlocks.tsx @@ -1,39 +1,31 @@ -import type { - CodeBlock as CodeBlockType, - ContentBlock as ContentBlockType, - MediaBlock as MediaBlockType, - Page -} from '@codeware/shared/util/payload-types'; +import type { BlockSlug, Page } from '@codeware/shared/util/payload-types'; import React, { Fragment } from 'react'; // import { CallToActionBlock } from '@/blocks/CallToAction/Component' -import { CodeBlock } from './CodeBlock'; -import { ContentBlock } from './ContentBlock'; -import { MediaBlock } from './MediaBlock'; -import type { RenderBlocksExtraProps } from './render-blocks.type'; +import { CodeBlock } from './blocks/CodeBlock'; +import { ContentBlock } from './blocks/ContentBlock'; +import { FormBlock } from './blocks/FormBlock'; +import { MediaBlock } from './blocks/MediaBlock'; const blocksMap: Record< - | CodeBlockType['blockType'] - | ContentBlockType['blockType'] - | MediaBlockType['blockType'], + BlockSlug, // eslint-disable-next-line @typescript-eslint/no-explicit-any React.JSXElementConstructor > = { code: CodeBlock, content: ContentBlock, + form: FormBlock, media: MediaBlock }; -type Props = RenderBlocksExtraProps & { +type Props = { blocks: Page['layout']; }; /** * Renders the blocks of a page. */ -export const RenderBlocks: React.FC = (props) => { - const { blocks, ...rest } = props; - +export const RenderBlocks: React.FC = ({ blocks }) => { const hasBlocks = blocks && Array.isArray(blocks) && blocks.length > 0; if (hasBlocks) { @@ -45,7 +37,7 @@ export const RenderBlocks: React.FC = (props) => { if (Block) { return (
- +
); } @@ -57,5 +49,3 @@ export const RenderBlocks: React.FC = (props) => { return null; }; - -export default RenderBlocks; diff --git a/libs/shared/ui/payload-components/src/lib/RichText.tsx b/libs/shared/ui/payload-components/src/lib/RichText.tsx deleted file mode 100644 index 826cb1fb7..000000000 --- a/libs/shared/ui/payload-components/src/lib/RichText.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import type { - CodeBlock as CodeBlockProps, - MediaBlock as MediaBlockProps -} from '@codeware/shared/util/payload-types'; -import type { - DefaultNodeTypes, - SerializedBlockNode -} from '@payloadcms/richtext-lexical'; -import type { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical'; -import { - JSXConvertersFunction, - RichText as RichTextWithoutBlocks -} from '@payloadcms/richtext-lexical/react'; -import { clsx } from 'clsx'; - -import { CodeBlock } from './CodeBlock'; -import { MediaBlock } from './MediaBlock'; -import type { RenderBlocksExtraProps } from './render-blocks.type'; - -type NodeTypes = - | DefaultNodeTypes - | SerializedBlockNode; - -/** - * Converts custom Payload blocks from Lexical to React JSX components. - * - * Blocks defined in `app-cms-ui-blocks` must be added here to be rendered in a client. - */ -const jsxConverters = - (args: { - apiUrl: string; - enableProse: boolean; - isDark: boolean; - }): JSXConvertersFunction => - ({ defaultConverters }) => ({ - ...defaultConverters, - blocks: { - code: ({ node }) => , - media: ({ node }) => ( - - ) - } - }); - -type Props = { - data: SerializedEditorState; -} & Pick & - React.HTMLAttributes; - -/** - * Rich text component to render Payload Lexical editor data. - */ -export const RichText = (props: Props) => { - const { className = '', enableProse, apiUrl, isDark, ...rest } = props; - return ( - - ); -}; - -export default RichText; diff --git a/libs/shared/ui/payload-components/src/lib/CodeBlock.tsx b/libs/shared/ui/payload-components/src/lib/blocks/CodeBlock.tsx similarity index 53% rename from libs/shared/ui/payload-components/src/lib/CodeBlock.tsx rename to libs/shared/ui/payload-components/src/lib/blocks/CodeBlock.tsx index 74f41efd8..b00af0759 100644 --- a/libs/shared/ui/payload-components/src/lib/CodeBlock.tsx +++ b/libs/shared/ui/payload-components/src/lib/blocks/CodeBlock.tsx @@ -1,20 +1,19 @@ import { Code } from '@codeware/shared/ui/react-components'; import type { CodeBlock as CodeBlockProps } from '@codeware/shared/util/payload-types'; -import type { RenderBlocksExtraProps } from './render-blocks.type'; +import { usePayload } from '../providers/PayloadProvider'; -type Props = CodeBlockProps & Pick; +type Props = CodeBlockProps; export const CodeBlock: React.FC = (props) => { - const { code, isDark, language } = props; + const { code, language } = props; + const { theme } = usePayload(); return ( ); }; - -export default CodeBlock; diff --git a/libs/shared/ui/payload-components/src/lib/ContentBlock.tsx b/libs/shared/ui/payload-components/src/lib/blocks/ContentBlock.tsx similarity index 61% rename from libs/shared/ui/payload-components/src/lib/ContentBlock.tsx rename to libs/shared/ui/payload-components/src/lib/blocks/ContentBlock.tsx index 80d80ebb2..f16527113 100644 --- a/libs/shared/ui/payload-components/src/lib/ContentBlock.tsx +++ b/libs/shared/ui/payload-components/src/lib/blocks/ContentBlock.tsx @@ -1,12 +1,10 @@ +import { cn } from '@codeware/shared/ui/shadcn'; import type { ContentBlock as ContentBlockProps } from '@codeware/shared/util/payload-types'; -import { clsx } from 'clsx'; import React from 'react'; -import type { RenderBlocksExtraProps } from './render-blocks.type'; import { RichText } from './RichText'; -type Props = ContentBlockProps & - Pick; +type Props = ContentBlockProps; /** * Render Payload content block data, @@ -15,9 +13,7 @@ type Props = ContentBlockProps & * User defined column sizes are applied for tablets and desktops. * Mobile devices display all columns as full width. */ -export const ContentBlock: React.FC = (props) => { - const { apiUrl, columns, enableProse, isDark } = props; - +export const ContentBlock: React.FC = ({ columns }) => { return (
{columns?.map((col, index) => { @@ -26,21 +22,14 @@ export const ContentBlock: React.FC = (props) => { return (
- {richText && ( - - )} + {richText && }
); })} diff --git a/libs/shared/ui/payload-components/src/lib/blocks/FormBlock.tsx b/libs/shared/ui/payload-components/src/lib/blocks/FormBlock.tsx new file mode 100644 index 000000000..f047ab26a --- /dev/null +++ b/libs/shared/ui/payload-components/src/lib/blocks/FormBlock.tsx @@ -0,0 +1,308 @@ +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + Form, + FormField, + FormItem, + FormMessage, + cn +} from '@codeware/shared/ui/shadcn'; +import type { + FormBlock as FormBlockProps, + FormSubmission, + FormSubmissionData, + Form as FormType +} from '@codeware/shared/util/payload-types'; +import type { FieldValues } from '@payloadcms/plugin-form-builder/types'; +import { useCallback, useState } from 'react'; +import { FieldErrors, useForm } from 'react-hook-form'; +import { toast } from 'sonner'; + +import { Button } from '../form-items/Button'; +import { Checkbox } from '../form-items/Checkbox'; +import { countryOptions } from '../form-items/country-options'; +import { Input } from '../form-items/Input'; +import { Select } from '../form-items/Select'; +import { Textarea } from '../form-items/Textarea'; +import ColSpan from '../layout/ColSpan'; +import { usePayload } from '../providers/PayloadProvider'; + +import { RichText } from './RichText'; + +// Assume form has the proper type but validate it before render anyway +type Props = FormBlockProps; + +/** + * Render Payload form block data, with the configured form fields. + */ +export const FormBlock: React.FC = ({ + enableIntro, + form: formFromProps, + introContent +}) => { + const formBuilder = + typeof formFromProps === 'object' ? formFromProps : ({} as FormType); + + // Since FormField is using a controlled component, + // we need to provide default values for the form fields + // since undefined is not allowed and will throw console errors. + const defaultValues = formBuilder.fields?.reduce((acc, field) => { + // Form fields have a name property + if ('name' in field) { + acc[field.name] = + ('defaultValue' in field ? field.defaultValue : '') ?? ''; + } + return acc; + }, {} as FieldValues); + + // Initialize form without zod validation + const form = useForm({ + defaultValues + }); + + // Payload context + const { navigate, submitForm } = usePayload(); + + // Control loading state and open confirmation dialog + const [isLoading, setIsLoading] = useState(false); + const [openConfirmationDialog, setOpenConfirmationDialog] = useState(false); + + const { + confirmationMessage, + confirmationType, + id: formId, + redirect, + submitButtonLabel + } = formBuilder; + + // Submit handler + const onSubmit = useCallback( + (formValue: FieldValues) => { + const invokeSubmit = async () => { + setIsLoading(true); + try { + // Convert form data to submission data + const submissionData: FormSubmissionData = Object.entries( + formValue + ).map(([field, value]) => ({ + field, + value: String(value) + })); + + // Invoke provider callback + const { success } = await submitForm({ + form: formId, + submissionData + }); + + setIsLoading(false); + + // Show error toast if response is not ok + if (!success) { + toast.error('Form submission failed'); + return; + } + + // Successfully submitted form + form.reset(); + + // Act on the type of confirmation + let confirmed = false; + if (confirmationType === 'message') { + // Open dialog with a message + setOpenConfirmationDialog(true); + confirmed = true; + } else if (confirmationType === 'redirect' && redirect) { + // Redirect to collection document or URL if provided + const { type, reference, url } = redirect; + // Default to the url + let href = url; + if ( + type === 'reference' && + typeof reference?.value === 'object' && + reference.value.slug + ) { + // Get reference url + // TODO: Are other collections than pages prefixed with their slug? + href = + reference.relationTo === 'pages' + ? reference.value.slug + : reference.relationTo + ? `/${reference.relationTo}` + : ''; + } + if (href) { + try { + console.log('Redirecting to', href); + navigate(href); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } catch (_) { + // Do nothing + } + confirmed = true; + } else { + console.warn('Unable to extract redirect url'); + } + } + + // Show success toast when user isn't confirmed at all + if (!confirmed) { + toast.success('Form submitted successfully'); + } + } catch (err) { + console.warn('Unknown error on form submission', err); + setIsLoading(false); + + // Show error toast + toast.error('Form submission failed', { + description: 'Please try again.' + }); + } + }; + + invokeSubmit(); + }, + [confirmationType, form, formId, navigate, redirect, submitForm] + ); + + const onError = (errors: FieldErrors) => { + console.log('[DEBUG] errors', errors); + }; + + if (formBuilder.id === undefined) { + console.warn('Form builder is not an object?'); + return null; + } + + return ( +
+ {enableIntro && introContent && ( + + )} +
+ +
1 + })} + > + {/* Loop through form builder field definitions */} + {formBuilder?.fields?.map((fieldDef, index) => { + // Handle message separately since it's not a form field. + // It can be used to display a message to the user anywhere in the form. + if (fieldDef.blockType === 'message') { + return ( + fieldDef.message && ( +
+ +
+ ) + ); + } + return ( + + { + return ( + + {/* (HÃ¥kan) I chose to do this way to get full type safety on the builderField. + Could this be improved to detect missing component implementations? */} + {fieldDef.blockType === 'checkbox' && ( + + )} + {fieldDef.blockType === 'country' && ( + + )} + {fieldDef.blockType === 'number' && ( + + )} + {fieldDef.blockType === 'select' && ( + + )} + {fieldDef.blockType === 'textarea' && ( +