Skip to content

Commit

Permalink
feat(cli): introduce multiple flags for init (#21314)
Browse files Browse the repository at this point in the history
Co-authored-by: Jan Piotrowski <[email protected]>
Co-authored-by: Joël Galeran <[email protected]>
Co-authored-by: DavidHancu <[email protected]>
  • Loading branch information
4 people authored Oct 5, 2023
1 parent 85ba508 commit eb9ef4d
Show file tree
Hide file tree
Showing 3 changed files with 283 additions and 15 deletions.
67 changes: 60 additions & 7 deletions packages/cli/src/Init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,31 @@ import { isError } from 'util'

import { printError } from './utils/prompt/utils/print'

export const defaultSchema = (provider: ConnectorType = 'postgresql') => {
export const defaultSchema = (props?: {
datasourceProvider?: ConnectorType
generatorProvider?: string
previewFeatures?: string[]
output?: string
}) => {
const {
datasourceProvider = 'postgresql',
generatorProvider = defaultGeneratorProvider,
previewFeatures = defaultPreviewFeatures,
output = defaultOutput,
} = props || {}
return `// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
provider = "${generatorProvider}"
${
previewFeatures.length > 0
? ` previewFeatures = [${previewFeatures.map((feature) => `"${feature}"`).join(', ')}]\n`
: ''
}${output != defaultOutput ? ` output = "${output}"\n` : ''}}
datasource db {
provider = "${provider}"
provider = "${datasourceProvider}"
url = env("DATABASE_URL")
}
`
Expand Down Expand Up @@ -95,6 +110,12 @@ export const defaultGitIgnore = () => {
`
}

export const defaultGeneratorProvider = 'prisma-client-js'

export const defaultPreviewFeatures = []

export const defaultOutput = 'node_modules/.prisma/client'

export class Init implements Command {
static new(): Init {
return new Init()
Expand All @@ -110,6 +131,9 @@ export class Init implements Command {
-h, --help Display this help message
--datasource-provider Define the datasource provider to use: postgresql, mysql, sqlite, sqlserver, mongodb or cockroachdb
--generator-provider Define the generator provider to use. Default: \`prisma-client-js\`
--preview-feature Define a preview feature to use.
--output Define Prisma Client generator output path to use.
--url Define a custom datasource url
${bold('Examples')}
Expand All @@ -119,6 +143,15 @@ export class Init implements Command {
Set up a new Prisma project and specify MySQL as the datasource provider to use
${dim('$')} prisma init --datasource-provider mysql
Set up a new Prisma project and specify prisma-client-go as the generator provider to use
${dim('$')} prisma init --generator-provider prisma-client-go
Set up a new Prisma project and specify x and y as the preview features to use
${dim('$')} prisma init --preview-feature x --preview-feature y
Set up a new Prisma project and specify ./generated-client as the output path to use
${dim('$')} prisma init --output ./generated-client
Set up a new Prisma project and specify the url that will be used
${dim('$')} prisma init --url mysql://user:password@localhost:3306/mydb
Expand All @@ -131,6 +164,9 @@ export class Init implements Command {
'-h': '--help',
'--url': String,
'--datasource-provider': String,
'--generator-provider': String,
'--preview-feature': [String],
'--output': String,
})

if (isError(args) || args['--help']) {
Expand Down Expand Up @@ -192,7 +228,10 @@ export class Init implements Command {
}
const provider = providerLowercase as ConnectorType
const url = defaultURL(provider)
return Promise.resolve({ provider, url })
return Promise.resolve({
provider,
url,
})
},
)
.with(
Expand Down Expand Up @@ -221,8 +260,14 @@ export class Init implements Command {
)
.otherwise(() => {
// Default to PostgreSQL
return Promise.resolve({ provider: 'postgresql' as ConnectorType, url: undefined })
return Promise.resolve({
provider: 'postgresql' as ConnectorType,
url: undefined,
})
})
const generatorProvider = args['--generator-provider']
const previewFeatures = args['--preview-feature']
const output = args['--output']

/**
* Validation successful? Let's create everything!
Expand All @@ -236,7 +281,15 @@ export class Init implements Command {
fs.mkdirSync(prismaFolder)
}

fs.writeFileSync(path.join(prismaFolder, 'schema.prisma'), defaultSchema(provider))
fs.writeFileSync(
path.join(prismaFolder, 'schema.prisma'),
defaultSchema({
datasourceProvider: provider,
generatorProvider,
previewFeatures,
output,
}),
)

const warnings: string[] = []
const envPath = path.join(outputDir, '.env')
Expand Down
104 changes: 96 additions & 8 deletions packages/cli/src/__tests__/commands/Init.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ test('works with url param', async () => {
expect(stripAnsi(result.stdout)).toMatchSnapshot()

const schema = fs.readFileSync(join(ctx.tmpDir, 'prisma', 'schema.prisma'), 'utf-8')
expect(schema).toMatch(defaultSchema('sqlite'))
expect(schema).toMatch(
defaultSchema({
datasourceProvider: 'sqlite',
}),
)
expect(schema).toMatchSnapshot()

const env = fs.readFileSync(join(ctx.tmpDir, '.env'), 'utf-8')
Expand All @@ -46,7 +50,11 @@ test('works with provider param - postgresql', async () => {
expect(stripAnsi(result.stdout)).toMatchSnapshot()

const schema = fs.readFileSync(join(ctx.tmpDir, 'prisma', 'schema.prisma'), 'utf-8')
expect(schema).toMatch(defaultSchema('postgresql'))
expect(schema).toMatch(
defaultSchema({
datasourceProvider: 'postgresql',
}),
)
expect(schema).toMatchSnapshot()

const env = fs.readFileSync(join(ctx.tmpDir, '.env'), 'utf-8')
Expand All @@ -67,7 +75,11 @@ test('works with provider param - cockroachdb', async () => {
expect(stripAnsi(result.stdout)).toMatchSnapshot()

const schema = fs.readFileSync(join(ctx.tmpDir, 'prisma', 'schema.prisma'), 'utf-8')
expect(schema).toMatch(defaultSchema('cockroachdb'))
expect(schema).toMatch(
defaultSchema({
datasourceProvider: 'cockroachdb',
}),
)
expect(schema).toMatchSnapshot()

const env = fs.readFileSync(join(ctx.tmpDir, '.env'), 'utf-8')
Expand All @@ -94,7 +106,11 @@ test('works with provider and url params - cockroachdb', async () => {
expect(stripAnsi(result.stdout)).toMatchSnapshot()

const schema = fs.readFileSync(join(ctx.tmpDir, 'prisma', 'schema.prisma'), 'utf-8')
expect(schema).toMatch(defaultSchema('cockroachdb'))
expect(schema).toMatch(
defaultSchema({
datasourceProvider: 'cockroachdb',
}),
)
expect(schema).toMatchSnapshot()

const env = fs.readFileSync(join(ctx.tmpDir, '.env'), 'utf-8')
Expand All @@ -115,7 +131,11 @@ test('works with provider param - mysql', async () => {
expect(stripAnsi(result.stdout)).toMatchSnapshot()

const schema = fs.readFileSync(join(ctx.tmpDir, 'prisma', 'schema.prisma'), 'utf-8')
expect(schema).toMatch(defaultSchema('mysql'))
expect(schema).toMatch(
defaultSchema({
datasourceProvider: 'mysql',
}),
)
expect(schema).toMatchSnapshot()

const env = fs.readFileSync(join(ctx.tmpDir, '.env'), 'utf-8')
Expand All @@ -136,7 +156,11 @@ test('works with provider param - SQLITE', async () => {
expect(stripAnsi(result.stdout)).toMatchSnapshot()

const schema = fs.readFileSync(join(ctx.tmpDir, 'prisma', 'schema.prisma'), 'utf-8')
expect(schema).toMatch(defaultSchema('sqlite'))
expect(schema).toMatch(
defaultSchema({
datasourceProvider: 'sqlite',
}),
)
expect(schema).toMatchSnapshot()

const env = fs.readFileSync(join(ctx.tmpDir, '.env'), 'utf-8')
Expand All @@ -157,7 +181,11 @@ test('works with provider param - SqlServer', async () => {
expect(stripAnsi(result.stdout)).toMatchSnapshot()

const schema = fs.readFileSync(join(ctx.tmpDir, 'prisma', 'schema.prisma'), 'utf-8')
expect(schema).toMatch(defaultSchema('sqlserver'))
expect(schema).toMatch(
defaultSchema({
datasourceProvider: 'sqlserver',
}),
)
expect(schema).toMatchSnapshot()

const env = fs.readFileSync(join(ctx.tmpDir, '.env'), 'utf-8')
Expand All @@ -178,7 +206,11 @@ test('works with provider param - MongoDB', async () => {
expect(stripAnsi(result.stdout)).toMatchSnapshot()

const schema = fs.readFileSync(join(ctx.tmpDir, 'prisma', 'schema.prisma'), 'utf-8')
expect(schema).toMatch(defaultSchema('mongodb'))
expect(schema).toMatch(
defaultSchema({
datasourceProvider: 'mongodb',
}),
)
expect(schema).toMatchSnapshot()

const env = fs.readFileSync(join(ctx.tmpDir, '.env'), 'utf-8')
Expand All @@ -199,6 +231,62 @@ test('errors with invalid provider param', async () => {
await expect(result).rejects.toThrow()
})

test('works with generator param - `go run github.com/steebchen/prisma-client-go`', async () => {
ctx.fixture('init')
const result = await ctx.cli('init', '--generator-provider', 'go run github.com/steebchen/prisma-client-go')
expect(stripAnsi(result.stdout)).toMatchSnapshot()

const schema = fs.readFileSync(join(ctx.tmpDir, 'prisma', 'schema.prisma'), 'utf-8')
expect(schema).toMatch(
defaultSchema({
generatorProvider: 'go run github.com/steebchen/prisma-client-go',
}),
)
expect(schema).toMatchSnapshot()
})

test('works with preview features - mock test', async () => {
ctx.fixture('init')
const result = await ctx.cli('init', '--preview-feature', 'mock-123')
expect(stripAnsi(result.stdout)).toMatchSnapshot()

const schema = fs.readFileSync(join(ctx.tmpDir, 'prisma', 'schema.prisma'), 'utf-8')
expect(schema).toMatch(
defaultSchema({
previewFeatures: ['mock-123'],
}),
)
expect(schema).toMatchSnapshot()
})

test('works with preview features - multiple', async () => {
ctx.fixture('init')
const result = await ctx.cli('init', '--preview-feature', 'mock-123', '--preview-feature', 'mock-456')
expect(stripAnsi(result.stdout)).toMatchSnapshot()

const schema = fs.readFileSync(join(ctx.tmpDir, 'prisma', 'schema.prisma'), 'utf-8')
expect(schema).toMatch(
defaultSchema({
previewFeatures: ['mock-123', 'mock-456'],
}),
)
expect(schema).toMatchSnapshot()
})

test('works with custom output', async () => {
ctx.fixture('init')
const result = await ctx.cli('init', '--output', './db')
expect(stripAnsi(result.stdout)).toMatchSnapshot()

const schema = fs.readFileSync(join(ctx.tmpDir, 'prisma', 'schema.prisma'), 'utf-8')
expect(schema).toMatch(
defaultSchema({
output: './db',
}),
)
expect(schema).toMatchSnapshot()
})

test('warns when DATABASE_URL present in .env ', async () => {
fs.writeFileSync(join(ctx.tmpDir, '.env'), `DATABASE_URL="postgres://dont:overwrite@me:5432/tests"`)
const result = await ctx.cli('init')
Expand Down
Loading

0 comments on commit eb9ef4d

Please sign in to comment.