diff --git a/src/packages/cli/src/Init.ts b/src/packages/cli/src/Init.ts index d4d4b0ecdccc..a9b9fa493356 100644 --- a/src/packages/cli/src/Init.ts +++ b/src/packages/cli/src/Init.ts @@ -12,6 +12,7 @@ import { protocolToDatabaseType, databaseTypeToConnectorType, } from '@prisma/sdk/dist/convertCredentials' +import { ConnectorType } from '@prisma/generator-helper' import chalk from 'chalk' import dotenv from 'dotenv' import fs from 'fs' @@ -42,27 +43,28 @@ export const defaultEnv = ( ? `# Environment variables declared in this file are automatically made available to Prisma. # See the documentation for more detail: https://pris.ly/d/prisma-schema#using-environment-variables -# Prisma supports the native connection string format for PostgreSQL, MySQL and SQLite. +# Prisma supports the native connection string format for PostgreSQL, MySQL, SQL Server and SQLite. # See the documentation for all the connection string options: https://pris.ly/d/connection-strings\n\n` : '' env += `DATABASE_URL="${url}"` return env } -export const defaultPort = (provider = 'postgresql') => { +export const defaultPort = (provider: ConnectorType) => { switch (provider) { case 'mysql': return 3306 case 'sqlserver': return 1433 + case 'mongodb': + return 27017 case 'postgresql': - default: return 5432 } } export const defaultURL = ( - provider = 'postgresql', + provider: ConnectorType, port = defaultPort(provider), schema = 'public', ) => { @@ -73,6 +75,8 @@ export const defaultURL = ( return `${provider}://johndoe:randompassword@localhost:${port}/mydb` case 'sqlserver': return `${provider}://localhost:${port};database=mydb;user=SA;password=randompassword;` + case 'mongodb': + return `mongodb://johndoe:randompassword@localhost:${port}/mydb?authSource=admin` case 'sqlite': return 'file:./dev.db' } @@ -149,8 +153,8 @@ export class Init implements Command { process.exit(1) } - let provider: undefined | string - let url: undefined | string + let provider: ConnectorType + let url: string | undefined if (args['--url']) { const canConnect = await canConnectToDatabase(args['--url']) @@ -172,8 +176,21 @@ export class Init implements Command { ) url = args['--url'] } else if (args['--provider']) { - provider = args['--provider'] + const providerLowercase = args['--provider'].toLowerCase() + if ( + !['postgresql', 'mysql', 'sqlserver', 'sqlite', 'mongodb'].includes( + providerLowercase, + ) + ) { + throw new Error( + `Provider "${args['--provider']}" is invalid or not supported. Try again with "postgresql", "mysql", "sqlserver" or "sqlite".`, + ) + } + provider = providerLowercase as ConnectorType url = defaultURL(provider) + } else { + // Default to PostgreSQL + provider = 'postgresql' } /** @@ -192,6 +209,7 @@ export class Init implements Command { path.join(prismaFolder, 'schema.prisma'), defaultSchema(provider), ) + let warning const envPath = path.join(outputDir, '.env') if (!fs.existsSync(envPath)) { @@ -225,16 +243,21 @@ export class Init implements Command { )} to install Prisma Client. You can then start querying your database.`, ] - if (!url) { - steps.unshift( - `Set the ${chalk.green('provider')} of the ${chalk.green( - 'datasource', - )} block in ${chalk.green( - 'schema.prisma', - )} to match your database: ${chalk.green('postgresql')}, ${chalk.green( - 'mysql', - )} or ${chalk.green('sqlite')}.`, - ) + if (!url || args['--provider']) { + if (!args['--provider']) { + steps.unshift( + `Set the ${chalk.green('provider')} of the ${chalk.green( + 'datasource', + )} block in ${chalk.green( + 'schema.prisma', + )} to match your database: ${chalk.green( + 'postgresql', + )}, ${chalk.green('mysql')}, ${chalk.green( + 'sqlserver', + )} or ${chalk.green('sqlite')}.`, + ) + } + steps.unshift( `Set the ${chalk.green('DATABASE_URL')} in the ${chalk.green( '.env', diff --git a/src/packages/cli/src/__tests__/__snapshots__/init.test.ts.snap b/src/packages/cli/src/__tests__/__snapshots__/init.test.ts.snap index 1e7a997771c8..39b992ba1447 100644 --- a/src/packages/cli/src/__tests__/__snapshots__/init.test.ts.snap +++ b/src/packages/cli/src/__tests__/__snapshots__/init.test.ts.snap @@ -8,7 +8,7 @@ Environment variables loaded from .env Next steps: 1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started -2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql or sqlite. +2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql, sqlserver or sqlite. 3. Run prisma db pull to turn your database schema into a Prisma data model. 4. Run prisma generate to install Prisma Client. You can then start querying your database. @@ -24,7 +24,7 @@ SOMTHING="is here" # Environment variables declared in this file are automatically made available to Prisma. # See the documentation for more detail: https://pris.ly/d/prisma-schema#using-environment-variables -# Prisma supports the native connection string format for PostgreSQL, MySQL and SQLite. +# Prisma supports the native connection string format for PostgreSQL, MySQL, SQL Server and SQLite. # See the documentation for all the connection string options: https://pris.ly/d/connection-strings DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public" @@ -37,7 +37,7 @@ exports[`is schema and env written on disk replace 1`] = ` Next steps: 1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started -2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql or sqlite. +2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql, sqlserver or sqlite. 3. Run prisma db pull to turn your database schema into a Prisma data model. 4. Run prisma generate to install Prisma Client. You can then start querying your database. @@ -56,7 +56,7 @@ warn Prisma would have added DATABASE_URL="postgresql://johndoe:randompassword@l Next steps: 1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started -2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql or sqlite. +2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql, sqlserver or sqlite. 3. Run prisma db pull to turn your database schema into a Prisma data model. 4. Run prisma generate to install Prisma Client. You can then start querying your database. @@ -65,14 +65,30 @@ https://pris.ly/d/getting-started `; -exports[`works with provider param 1`] = ` +exports[`works with provider param - SQLITE 1`] = ` ✔ Your Prisma schema was created at prisma/schema.prisma. You can now open it in your favorite editor. Next steps: -1. Run prisma db pull to turn your database schema into a Prisma data model. -2. Run prisma generate to install Prisma Client. You can then start querying your database. +1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started +2. Run prisma db pull to turn your database schema into a Prisma data model. +3. Run prisma generate to install Prisma Client. You can then start querying your database. + +More information in our documentation: +https://pris.ly/d/getting-started + +`; + +exports[`works with provider param - mysql 1`] = ` + +✔ Your Prisma schema was created at prisma/schema.prisma. + You can now open it in your favorite editor. + +Next steps: +1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started +2. Run prisma db pull to turn your database schema into a Prisma data model. +3. Run prisma generate to install Prisma Client. You can then start querying your database. More information in our documentation: https://pris.ly/d/getting-started diff --git a/src/packages/cli/src/__tests__/init.test.ts b/src/packages/cli/src/__tests__/init.test.ts index 799ab30df890..7badf32245b5 100644 --- a/src/packages/cli/src/__tests__/init.test.ts +++ b/src/packages/cli/src/__tests__/init.test.ts @@ -33,20 +33,21 @@ test('works with url param', async () => { const env = fs.readFileSync(join(ctx.tmpDir, '.env'), 'utf-8') expect(env).toMatchInlineSnapshot(` - # Environment variables declared in this file are automatically made available to Prisma. - # See the documentation for more detail: https://pris.ly/d/prisma-schema#using-environment-variables +# Environment variables declared in this file are automatically made available to Prisma. +# See the documentation for more detail: https://pris.ly/d/prisma-schema#using-environment-variables - # Prisma supports the native connection string format for PostgreSQL, MySQL and SQLite. - # See the documentation for all the connection string options: https://pris.ly/d/connection-strings +# Prisma supports the native connection string format for PostgreSQL, MySQL, SQL Server and SQLite. +# See the documentation for all the connection string options: https://pris.ly/d/connection-strings - DATABASE_URL="file:dev.db" - `) +DATABASE_URL="file:dev.db" +`) }) -test('works with provider param', async () => { +test('works with provider param - mysql', async () => { ctx.fixture('init') const result = await ctx.cli('init', '--provider', 'mysql') expect(stripAnsi(result.stdout)).toMatchSnapshot() + const schema = fs.readFileSync( join(ctx.tmpDir, 'prisma', 'schema.prisma'), 'utf-8', @@ -55,14 +56,43 @@ test('works with provider param', async () => { const env = fs.readFileSync(join(ctx.tmpDir, '.env'), 'utf-8') expect(env).toMatchInlineSnapshot(` - # Environment variables declared in this file are automatically made available to Prisma. - # See the documentation for more detail: https://pris.ly/d/prisma-schema#using-environment-variables +# Environment variables declared in this file are automatically made available to Prisma. +# See the documentation for more detail: https://pris.ly/d/prisma-schema#using-environment-variables + +# Prisma supports the native connection string format for PostgreSQL, MySQL, SQL Server and SQLite. +# See the documentation for all the connection string options: https://pris.ly/d/connection-strings + +DATABASE_URL="mysql://johndoe:randompassword@localhost:3306/mydb" +`) +}) + +test('works with provider param - SQLITE', async () => { + ctx.fixture('init') + const result = await ctx.cli('init', '--provider', 'SQLITE') + expect(stripAnsi(result.stdout)).toMatchSnapshot() + + const schema = fs.readFileSync( + join(ctx.tmpDir, 'prisma', 'schema.prisma'), + 'utf-8', + ) + expect(schema).toMatch(defaultSchema('sqlite')) + + const env = fs.readFileSync(join(ctx.tmpDir, '.env'), 'utf-8') + expect(env).toMatchInlineSnapshot(` +# Environment variables declared in this file are automatically made available to Prisma. +# See the documentation for more detail: https://pris.ly/d/prisma-schema#using-environment-variables - # Prisma supports the native connection string format for PostgreSQL, MySQL and SQLite. - # See the documentation for all the connection string options: https://pris.ly/d/connection-strings +# Prisma supports the native connection string format for PostgreSQL, MySQL, SQL Server and SQLite. +# See the documentation for all the connection string options: https://pris.ly/d/connection-strings - DATABASE_URL="mysql://johndoe:randompassword@localhost:3306/mydb" - `) +DATABASE_URL="file:./dev.db" +`) +}) + +test('errors with invalid provider param', async () => { + ctx.fixture('init') + const result = ctx.cli('init', '--provider', 'INVALID') + await expect(result).rejects.toThrowError() }) test('warns when DATABASE_URL present in .env ', async () => { @@ -82,6 +112,7 @@ test('warns when DATABASE_URL present in .env ', async () => { const env = fs.readFileSync(join(ctx.tmpDir, '.env'), 'utf-8') expect(env).toMatch(`DATABASE_URL="postgres://dont:overwrite@me:5432/tests"`) }) + test('appends when .env present', async () => { fs.writeFileSync(join(ctx.tmpDir, '.env'), `SOMTHING="is here"`) const result = await ctx.cli('init')