Skip to content

Commit

Permalink
wip new init flow
Browse files Browse the repository at this point in the history
  • Loading branch information
timsuchanek committed Aug 22, 2019
1 parent 5811f51 commit 6550975
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 49 deletions.
34 changes: 22 additions & 12 deletions cli/introspection/src/commands/Init.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Command, Env, arg, format } from '@prisma/cli'
import { isError } from 'util'
import { writeFileSync } from 'fs'
import { join } from 'path'
import { mkdirpSync } from 'fs-extra'
import { InitPromptResult } from '../types'
import { initPrompt } from '../prompt/initPrompt'
import fs from 'fs'
import path from 'path'
import chalk from 'chalk'
import { printError, printFix } from '../prompt/utils/print'

export class Init implements Command {
static new(env: Env): Init {
Expand All @@ -26,16 +27,25 @@ export class Init implements Command {
}

const outputDirName = args._[0]
const outputDir = outputDirName ? join(process.cwd(), outputDirName) : process.cwd()
await initPrompt(outputDir)
}

patchPrismaConfig(result: InitPromptResult, outputDir: string) {
if (!result.introspectionResult || !result.introspectionResult.sdl) {
return
const outputDir = outputDirName ? path.join(process.cwd(), outputDirName) : process.cwd()

if (!fs.existsSync(outputDir)) {
mkdirpSync(outputDir)
} else {
const schemaExists = fs.existsSync(path.join(outputDir, 'schema.prisma'))
const prismaSchemaExists = fs.existsSync(path.join(outputDir, 'prisma/schema.prisma'))
if (schemaExists || prismaSchemaExists) {
const filePath = schemaExists ? 'schema.prisma' : 'prisma/schema.prisma'
console.log(printError(`The project directory must not contain a ${chalk.bold(filePath)} file.`))
console.log(
printFix(`Run the command in a directory without a ${chalk.bold(filePath)} file
or provide a project name, e.g.: ${chalk.bold('prisma2 init hello-world')}`),
)
process.exit(1)
}
}
mkdirpSync(join(outputDir, 'prisma'))
writeFileSync(join(outputDir, 'prisma/schema.prisma'), result.introspectionResult.sdl)

await initPrompt(outputDir)
}

help() {
Expand Down
4 changes: 4 additions & 0 deletions cli/introspection/src/prompt/components/InitState.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react'
import useGlobalHook from '../utils/useGlobalHook'
import { Example } from '../types'
import { DatabaseCredentials } from '../../types'

export type DBType = 'postgres' | 'sqlite' | 'mysql'
export type Language = 'blank' | 'ts' | 'js'
Expand All @@ -12,11 +13,14 @@ export type InitState = {
usePhoton: boolean
useLift: boolean
useDemoScript?: boolean
dbCredentials?: DatabaseCredentials
outputDir: string
}

const initialState: InitState = {
usePhoton: true,
useLift: true,
outputDir: process.cwd(),
}

const actions = {
Expand Down
8 changes: 3 additions & 5 deletions cli/introspection/src/prompt/initPrompt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,13 @@ import Step60ProcessBlank from './screens/Step60ProcessBlank'
import Step4DemoScriptSelection from './screens/Step4DemoScriptSelection'
import Step60DownloadExample from './screens/Step60DownloadExample'

export async function initPrompt(outputDir?: string) {
// go crazy on handling the outputDir...

export async function initPrompt(outputDir: string) {
return new Promise(resolve => {
render(
<Box marginTop={1} flexDirection="column">
<TabIndexProvider>
<Router defaultRoute="tool-selection">
<Route path="home" component={<Step0StarterVsBlank />} />
<Router defaultRoute="home">
<Route path="home" component={<Step0StarterVsBlank outputDir={outputDir} />} />
<Route path="starter-selection" component={<Step1StarterSelection />} />
<Route path="db-selection" component={<Step2DBSelection />} />
<Route path="sqlite-file-selection" component={<Step2SqliteFileSelection />} />
Expand Down
14 changes: 12 additions & 2 deletions cli/introspection/src/prompt/screens/Step0StarterVsBlank.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import React from 'react'
import React, { useEffect } from 'react'
import { Color, Box } from 'ink'
import BorderBox from '../components/BorderBox'
import chalk from 'chalk'
import { Link } from '../components/Link'
import { useExampleApi } from '../utils/useExampleApi'
import { useInitState } from '../components/InitState'

const Step0StarterVsBlank: React.FC = () => {
type Props = {
outputDir: string
}

const Step0StarterVsBlank: React.FC<Props> = ({ outputDir }) => {
// already cache the result for later screens
const { setState } = useInitState()[1]
useEffect(() => {
// setState({ outputDir })
})

useExampleApi()
return (
<Box flexDirection="column">
Expand Down
22 changes: 20 additions & 2 deletions cli/introspection/src/prompt/screens/Step2DBSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,40 @@ import { Color, Box } from 'ink'
import BorderBox from '../components/BorderBox'
import chalk from 'chalk'
import { Link } from '../components/Link'
import { useInitState } from '../components/InitState'

const Step2DBSelection: React.FC = () => {
const [state] = useInitState()

const sqliteHref = state.selectedLanguage === 'blank' ? 'tool-selection' : 'download-example'

return (
<Box flexDirection="column">
<Box flexDirection="column" marginLeft={2}>
<Color bold>Select the database you want to use.</Color>
<Color dim>Use SQLite if you don't have a database running yet.</Color>
</Box>
<BorderBox flexDirection="column" title={chalk.bold('Supported databases')} marginTop={1} marginBottom={1}>
<Link label="SQLite" href="success" description="Easiest to set up" tabIndex={0} />
<Link label="MySQL" href="mysql-blank" description="Requires running a MySQL database" tabIndex={1} />
<Link
label="SQLite"
href={sqliteHref}
description="Easiest to set up"
tabIndex={0}
state={{ selectedDb: 'sqlite' }}
/>
<Link
label="MySQL"
href="mysql-blank"
description="Requires running a MySQL database"
tabIndex={1}
state={{ selectedDb: 'mysql' }}
/>
<Link
label="PostgreSQL"
href="postgres-blank"
description="Requires running a PostgreSQL database"
tabIndex={2}
state={{ selectedDb: 'postgres' }}
/>
<Box marginLeft={2}>
<Color dim>MongoDB {' '} (Coming soon)</Color>
Expand Down
21 changes: 20 additions & 1 deletion cli/introspection/src/prompt/screens/Step60ProcessBlank.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,31 @@
import React from 'react'
import React, { useEffect, useContext } from 'react'
import { Color, Box } from 'ink'
import { useInitState } from '../components/InitState'
import fs from 'fs'
import path from 'path'
import { sqliteSchemaOnly } from '../utils/templates'
import { RouterContext } from '../components/Router'
import { sync as makeDirSync } from 'make-dir'

const Step60ProcessBlank: React.FC = () => {
const [state] = useInitState()
const router = useContext(RouterContext)
useEffect(() => {
// perform actions to get blank project going...
// state.blank??
if (state.selectedDb === 'sqlite' && !state.useDemoScript) {
makeDirSync(path.join(state.outputDir, './prisma'))
fs.writeFileSync(path.join(state.outputDir, './prisma/schema.prisma'), sqliteSchemaOnly(state.usePhoton))
router.setRoute('success')
}
}, [state])

return (
<Box flexDirection="column">
<Box flexDirection="column" marginLeft={2}>
<Color bold>Processsing the blank stuff...</Color>
<Color dim>Please wait a few years</Color>
{JSON.stringify(state)}
</Box>
</Box>
)
Expand Down
75 changes: 48 additions & 27 deletions cli/introspection/src/prompt/screens/Step61Success.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,69 @@ import React, { useEffect } from 'react'
import { Color, Box } from 'ink'
import BorderBox from '../components/BorderBox'
import chalk from 'chalk'
import { useInitState } from '../components/InitState'
import path from 'path'

const Step61Success: React.FC = () => {
useEffect(() => {
setTimeout(() => {
process.exit()
}, 5)
})
const [state] = useInitState()
const showDirectoryCreated = state.outputDir !== process.cwd()
const projectName = showDirectoryCreated ? path.relative(process.cwd(), state.outputDir) : '?'
return (
<Box flexDirection="column">
<Box marginLeft={2} marginBottom={1}>
<Color green>
<Color bgKeyword="green" white>
<Color bold> SUCCESS </Color>
</Color>{' '}
Congratulations, you're all set!
Aw yeah, you're all set!
</Color>
</Box>
<BorderBox flexDirection="column" title={chalk.bold('Info')}>
<Box marginLeft={2} marginBottom={1} flexDirection="column">
<Color>
The <Color bold>PROJECT_NAME</Color> directory was created. It contains your{' '}
</Color>
<Color>Prisma setup and the starter code for a EXAMPLE_NAME.</Color>
</Box>
<Box marginLeft={2} marginBottom={1} flexDirection="column">
<Color>Prisma is connected to your database at:</Color>
<Color>
<Color bold>DB_HOST</Color> as <Color bold>DB_USER</Color>
</Color>
</Box>
<Box marginLeft={2} marginBottom={1} flexDirection="column">
<Color>Your database has been seeded with the data in:</Color>
<Color bold>PROJECT_NAME/PATH/TO/SEEDING/FILE</Color>
</Box>
<Box marginLeft={2} flexDirection="column">
<Color>If you encounter any issues, please report them here:</Color>
<Color bold>ISSUES_LINK</Color>
</Box>
</BorderBox>
{showDirectoryCreated ||
(state.selectedExample && (
<BorderBox flexDirection="column" title={chalk.bold('Info')}>
{showDirectoryCreated && (
<Box marginLeft={2} marginBottom={1} flexDirection="column">
<Color>
The <Color bold>{projectName}</Color> directory was created. It contains your{' '}
</Color>
<Color>Prisma setup {state.selectedExample ? 'and the starter code for a EXAMPLE_NAME' : ''}</Color>
</Box>
)}
{state.selectedExample && (
<>
<Box marginLeft={2} marginBottom={1} flexDirection="column">
<Color>Prisma is connected to your database at:</Color>
<Color>
<Color bold>DB_HOST</Color> as <Color bold>DB_USER</Color>
</Color>
</Box>
<Box marginLeft={2} marginBottom={1} flexDirection="column">
<Color>Your database has been seeded with the data in:</Color>
<Color bold>PROJECT_NAME/PATH/TO/SEEDING/FILE</Color>
</Box>
<Box marginLeft={2} flexDirection="column">
<Color>If you encounter any issues, please report them here:</Color>
<Color bold>ISSUES_LINK</Color>
</Box>
</>
)}
</BorderBox>
))}
<BorderBox flexDirection="column" marginTop={1} marginBottom={1} title={chalk.bold('Next steps')}>
<Box marginLeft={2} width={100} flexDirection="column">
<Color>Navigate into the project directory:</Color>
<Box marginBottom={1} flexDirection="column">
<Color bold>$ cd PROJECT_NAME</Color>
</Box>
{showDirectoryCreated && (
<>
<Color>Navigate into the project directory:</Color>
<Box marginBottom={1} flexDirection="column">
<Color bold>$ cd PROJECT_NAME</Color>
</Box>
</>
)}
<Color>Start Prisma's development mode to enable access to</Color>
<Color>
Prisma Studio and watch <Color bold>schema.prisma</Color> for changes:
Expand All @@ -61,6 +79,9 @@ const Step61Success: React.FC = () => {
<Color>Explore sample operations and evolve the project:</Color>
<Color bold>EXAMPLE_SHORTLINK</Color>
</Box>
{state.selectedLanguage === 'blank' && (
<Color>We're missing some better text when you chose the blank flow... Coming soon</Color>
)}
</BorderBox>
</Box>
)
Expand Down
9 changes: 9 additions & 0 deletions cli/introspection/src/prompt/utils/print.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import chalk from 'chalk'

export function printError(text) {
return chalk.bold.bgRed(' ERROR ') + ' ' + chalk.red(text)
}

export function printFix(text) {
return chalk.bgWhite.black.bold(' FIX ') + ' ' + text
}
29 changes: 29 additions & 0 deletions cli/introspection/src/prompt/utils/templates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export const sqliteSchemaOnly = (usePhoton: boolean) => `datasource db {
provider = "sqlite"
url = "file:./dev.db"
}
${
usePhoton
? `
generator photon {
provider = "photonjs"
}`
: ''
}
model User {
id String @default(cuid()) @id @unique
email String @unique
name String?
posts Post[]
}
model Post {
id String @default(cuid()) @id @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
published Boolean
title String
content String?
author User?
}`

0 comments on commit 6550975

Please sign in to comment.