From 9eaa59466ce3fb9de0adf782c50859e3998e7700 Mon Sep 17 00:00:00 2001 From: Tim Leslie Date: Wed, 14 Jul 2021 09:50:51 +1000 Subject: [PATCH] Add support for MongoDB --- .github/workflows/tests.yml | 11 +++++++++-- packages/keystone/src/lib/core/prisma-schema.ts | 16 ++++++++++++++-- packages/keystone/src/lib/createSystem.ts | 2 ++ packages/types/src/config/index.ts | 5 +++++ packages/types/src/core.ts | 2 +- tests/api-tests/access-control/utils.ts | 12 ++++++++++-- 6 files changed, 41 insertions(+), 7 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0e1e0d9cf98..786237f2757 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -108,11 +108,18 @@ jobs: POSTGRES_DB: test_db ports: - 5432:5432 + mongodb: + image: mongo + env: + MONGO_INITDB_ROOT_USERNAME: keystone5 + MONGO_INITDB_ROOT_PASSWORD: k3yst0n3 + ports: + - 27017:27017 strategy: fail-fast: false matrix: index: [0, 1, 2, 3, 4, 5, 6, 7, 8] - adapter: ['postgresql', 'sqlite'] + adapter: ['postgresql', 'sqlite', 'mongodb'] steps: - name: Checkout Repo uses: actions/checkout@v2 @@ -153,7 +160,7 @@ jobs: CI_NODE_TOTAL: 9 CI_NODE_INDEX: ${{ matrix.index }} TEST_ADAPTER: ${{ matrix.adapter }} - DATABASE_URL: ${{ matrix.adapter == 'sqlite' && 'file:./dev.db' || 'postgres://keystone5:k3yst0n3@localhost:5432/test_db' }} + DATABASE_URL: ${{ matrix.adapter == 'sqlite' && 'file:./dev.db' || matrix.adapter == 'postgresql' && 'postgres://keystone5:k3yst0n3@localhost:5432/test_db' || 'mongodb://keystone5:k3yst0n3@localhost:27017/test_db' }} non-api-tests: name: Package Unit Tests diff --git a/packages/keystone/src/lib/core/prisma-schema.ts b/packages/keystone/src/lib/core/prisma-schema.ts index 21dd43c7810..d03f7a323c8 100644 --- a/packages/keystone/src/lib/core/prisma-schema.ts +++ b/packages/keystone/src/lib/core/prisma-schema.ts @@ -198,13 +198,22 @@ export function printPrismaSchema( let prismaSchema = `datasource ${provider} { url = env("DATABASE_URL") provider = "${provider}" -} +}\n\n`; -generator client { + if (provider === 'mongodb') { + prismaSchema += `generator client { provider = "prisma-client-js" + previewFeatures = ["mongoDb"] output = "${clientDir}" } \n`; + } else { + prismaSchema += `generator client { + provider = "prisma-client-js" + output = "${clientDir}" + } + \n`; + } for (const [listKey, { resolvedDbFields }] of Object.entries(lists)) { prismaSchema += `model ${listKey} {`; for (const [fieldPath, field] of Object.entries(resolvedDbFields)) { @@ -214,6 +223,9 @@ generator client { if (fieldPath === 'id') { assertDbFieldIsValidForIdField(listKey, field); prismaSchema += ' @id'; + if (provider === 'mongodb') { + prismaSchema += ' @map("_id")'; + } } } prismaSchema += `\n}\n`; diff --git a/packages/keystone/src/lib/createSystem.ts b/packages/keystone/src/lib/createSystem.ts index 1a0a6114dcf..aacdf85e38e 100644 --- a/packages/keystone/src/lib/createSystem.ts +++ b/packages/keystone/src/lib/createSystem.ts @@ -10,6 +10,8 @@ export function getDBProvider(db: KeystoneConfig['db']): DatabaseProvider { return 'postgresql'; } else if (db.adapter === 'prisma_sqlite' || db.provider === 'sqlite') { return 'sqlite'; + } else if (db.provider === 'mongodb') { + return 'mongodb'; } else { throw new Error( 'Invalid db configuration. Please specify db.provider as either "sqlite" or "postgresql"' diff --git a/packages/types/src/config/index.ts b/packages/types/src/config/index.ts index 0717d6c62aa..a6f25530d9e 100644 --- a/packages/types/src/config/index.ts +++ b/packages/types/src/config/index.ts @@ -84,6 +84,11 @@ export type DatabaseConfig = { provider: 'sqlite'; } ) + | { + /** @deprecated The `adapter` option is deprecated. Please use `{ provider: '...' }` */ + adapter?: undefined; + provider: 'mongodb'; + } ); // config.ui diff --git a/packages/types/src/core.ts b/packages/types/src/core.ts index c62f91b0f79..d51051d6471 100644 --- a/packages/types/src/core.ts +++ b/packages/types/src/core.ts @@ -8,7 +8,7 @@ type FieldDefaultValueArgs = originalInput: TGeneratedListTypes['inputs']['create']; }; -export type DatabaseProvider = 'sqlite' | 'postgresql'; +export type DatabaseProvider = 'sqlite' | 'postgresql' | 'mongodb'; export type FieldDefaultValue = | T diff --git a/tests/api-tests/access-control/utils.ts b/tests/api-tests/access-control/utils.ts index 012a038f17c..40f44ea2d92 100644 --- a/tests/api-tests/access-control/utils.ts +++ b/tests/api-tests/access-control/utils.ts @@ -4,8 +4,16 @@ import { statelessSessions } from '@keystone-next/keystone/session'; import { createAuth } from '@keystone-next/auth'; import { apiTestConfig } from '../utils'; -const FAKE_ID = { postgresql: 'cdsfasfafafadfasdf', sqlite: 'cdsfasfafafadfasdf' } as const; -const FAKE_ID_2 = { postgresql: 'csdfbstrsbaf', sqlite: 'csdfbstrsbaf' } as const; +const FAKE_ID = { + postgresql: 'cdsfasfafafadfasdf', + sqlite: 'cdsfasfafafadfasdf', + mongodb: 'cdsfasfafafadfasdf', +} as const; +const FAKE_ID_2 = { + postgresql: 'csdfbstrsbaf', + sqlite: 'csdfbstrsbaf', + mongodb: 'csdfbstrsbaf', +} as const; const COOKIE_SECRET = 'qwertyuiopasdfghjlkzxcvbmnm1234567890'; const yesNo = (truthy: boolean | undefined) => (truthy ? 'Yes' : 'No');