-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(prisma): Support multi file Prisma schemas (#10869)
feat(prisma): Support multi file Prisma schemas (#10869) by @dthyresson Prisma's `prismaSchemaFolder` [feature](https://www.prisma.io/docs/orm/prisma-schema/overview/location#multi-file-prisma-schema) allows you to define multiple files in a schema subdirectory of your prisma directory. This PR updates: * Prisma utilities * generators * dbAuth setup * documentation to support single and multi file Prisma schemas. If you have enabled Prisma multi file schemas, you configure your project toml api `schemaPath` setting the directory where your schema.prisma can be found, for example: './api/db/schema' When [organizing your Prisma Schema into multiple files](https://www.prisma.io/blog/organize-your-prisma-schema-with-multi-file-support), you will need [enable](https://www.prisma.io/docs/orm/prisma-schema/overview/location#multi-file-prisma-schema) that feature in Prisma, move your `schema.prisma` file into a new directory such as `./api/db/schema` and then set `schemaPath` in the api toml config. ::: For example: ```toml title="redwood.toml" [api] port = 8911 schemaPath = "./api/db/schema" ``` --------- Co-authored-by: Josh GM Walker <56300765+Josh-Walker-GM@users.noreply.github.com>
- Loading branch information
1 parent
531a144
commit cf4dc76
Showing
12 changed files
with
237 additions
and
159 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
feat(prisma): Support multi file Prisma schemas (#10869) by @dthyresson | ||
|
||
Prisma's `prismaSchemaFolder` [feature](https://www.prisma.io/docs/orm/prisma-schema/overview/location#multi-file-prisma-schema) allows you to define multiple files in a schema subdirectory of your prisma directory. | ||
|
||
This PR updates: | ||
|
||
* Prisma utilities | ||
* generators | ||
* dbAuth setup | ||
* documentation | ||
|
||
to support single and multi file Prisma schemas. | ||
|
||
If you have enabled Prisma multi file schemas, you configure your project toml api `schemaPath` setting the directory where your schema.prisma can be found, for example: './api/db/schema' | ||
|
||
When [organizing your Prisma Schema into multiple files](https://www.prisma.io/blog/organize-your-prisma-schema-with-multi-file-support), you will need [enable](https://www.prisma.io/docs/orm/prisma-schema/overview/location#multi-file-prisma-schema) that feature in Prisma, move your `schema.prisma` file into a new directory such as `./api/db/schema` and then set `schemaPath` in the api toml config. | ||
::: | ||
|
||
For example: | ||
|
||
```toml title="redwood.toml" | ||
[api] | ||
port = 8911 | ||
schemaPath = "./api/db/schema" | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
208 changes: 100 additions & 108 deletions
208
packages/cli/src/commands/setup/deploy/providers/render.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,127 +1,119 @@ | ||
// import terminalLink from 'terminal-link' | ||
import path from 'path' | ||
|
||
import { getSchema, getConfig } from '@prisma/internals' | ||
import execa from 'execa' | ||
import fs from 'fs-extra' | ||
import { Listr } from 'listr2' | ||
import terminalLink from 'terminal-link' | ||
|
||
import { recordTelemetryAttributes } from '@redwoodjs/cli-helpers' | ||
import { errorTelemetry } from '@redwoodjs/telemetry' | ||
import { getPaths } from '@redwoodjs/project-config' | ||
|
||
import { getPaths, writeFilesTask, printSetupNotes } from '../../../../lib' | ||
import c from '../../../../lib/colors' | ||
import { addFilesTask, updateApiURLTask } from '../helpers' | ||
import { | ||
POSTGRES_YAML, | ||
RENDER_HEALTH_CHECK, | ||
RENDER_YAML, | ||
SQLITE_YAML, | ||
} from '../templates/render' | ||
|
||
export const command = 'render' | ||
export const description = 'Setup Render deploy' | ||
// It's easy for the api side to exceed Render's free-plan limit. | ||
// Because telemetryMiddleware is added to Yargs as middleware, | ||
// we need to set the env var here outside the handler to correctly disable it. | ||
if (process.argv.slice(2).includes('api')) { | ||
process.env.REDWOOD_DISABLE_TELEMETRY = 1 | ||
} | ||
|
||
export const getRenderYamlContent = async (database) => { | ||
if (database === 'none') { | ||
return { | ||
path: path.join(getPaths().base, 'render.yaml'), | ||
content: RENDER_YAML(''), | ||
} | ||
} | ||
if (!fs.existsSync('api/db/schema.prisma')) { | ||
throw new Error("Could not find prisma schema at 'api/db/schema.prisma'") | ||
} | ||
export const command = 'render <side>' | ||
export const description = 'Build, migrate, and serve command for Render deploy' | ||
|
||
const schema = await getSchema('api/db/schema.prisma') | ||
const config = await getConfig({ datamodel: schema }) | ||
const detectedDatabase = config.datasources[0].activeProvider | ||
export const builder = (yargs) => { | ||
yargs | ||
.positional('side', { | ||
choices: ['api', 'web'], | ||
description: 'Side to deploy', | ||
type: 'string', | ||
}) | ||
.option('prisma', { | ||
description: 'Apply database migrations', | ||
type: 'boolean', | ||
default: true, | ||
}) | ||
.option('data-migrate', { | ||
description: 'Apply data migrations', | ||
type: 'boolean', | ||
default: true, | ||
alias: 'dm', | ||
}) | ||
.epilogue( | ||
`For more commands, options, and examples, see ${terminalLink( | ||
'Redwood CLI Reference', | ||
'https://redwoodjs.com/docs/cli-commands#deploy', | ||
)}`, | ||
) | ||
} | ||
|
||
if (detectedDatabase === database) { | ||
switch (database) { | ||
case 'postgresql': | ||
return { | ||
path: path.join(getPaths().base, 'render.yaml'), | ||
content: RENDER_YAML(POSTGRES_YAML), | ||
} | ||
case 'sqlite': | ||
return { | ||
path: path.join(getPaths().base, 'render.yaml'), | ||
content: RENDER_YAML(SQLITE_YAML), | ||
} | ||
default: | ||
throw new Error(` | ||
Unexpected datasource provider found: ${database}`) | ||
} | ||
} else { | ||
throw new Error(` | ||
Prisma datasource provider is detected to be ${detectedDatabase}. | ||
export const handler = async ({ side, prisma, dataMigrate }) => { | ||
recordTelemetryAttributes({ | ||
command: 'deploy render', | ||
side, | ||
prisma, | ||
dataMigrate, | ||
}) | ||
|
||
Option 1: Update your schema.prisma provider to be ${database}, then run | ||
yarn rw prisma migrate dev | ||
yarn rw setup deploy render --database ${database} | ||
const rwjsPaths = getPaths() | ||
|
||
Option 2: Rerun setup deploy command with current schema.prisma provider: | ||
yarn rw setup deploy render --database ${detectedDatabase}`) | ||
const execaConfig = { | ||
cwd: rwjsPaths.base, | ||
shell: true, | ||
stdio: 'inherit', | ||
} | ||
} | ||
|
||
export const builder = (yargs) => | ||
yargs.option('database', { | ||
alias: 'd', | ||
choices: ['none', 'postgresql', 'sqlite'], | ||
description: 'Database deployment for Render only', | ||
default: 'postgresql', | ||
type: 'string', | ||
}) | ||
async function runApiCommands() { | ||
if (prisma) { | ||
console.log('Running database migrations...') | ||
execa.commandSync( | ||
`node_modules/.bin/prisma migrate deploy --schema "${rwjsPaths.api.dbSchema}"`, | ||
execaConfig, | ||
) | ||
} | ||
|
||
// any notes to print out when the job is done | ||
const notes = [ | ||
'You are ready to deploy to Render!\n', | ||
'Go to https://dashboard.render.com/iacs to create your account and deploy to Render', | ||
'Check out the deployment docs at https://render.com/docs/deploy-redwood for detailed instructions', | ||
'Note: After first deployment to Render update the rewrite rule destination in `./render.yaml`', | ||
] | ||
if (dataMigrate) { | ||
console.log('Running data migrations...') | ||
const packageJson = fs.readJsonSync( | ||
path.join(rwjsPaths.base, 'package.json'), | ||
) | ||
const hasDataMigratePackage = | ||
!!packageJson.devDependencies['@redwoodjs/cli-data-migrate'] | ||
|
||
const additionalFiles = [ | ||
{ | ||
path: path.join(getPaths().base, 'api/src/functions/healthz.js'), | ||
content: RENDER_HEALTH_CHECK, | ||
}, | ||
] | ||
if (!hasDataMigratePackage) { | ||
console.error( | ||
[ | ||
"Skipping data migrations; your project doesn't have the `@redwoodjs/cli-data-migrate` package as a dev dependency.", | ||
"Without it installed, you're likely to run into memory issues during deploy.", | ||
"If you want to run data migrations, add the package to your project's root package.json and deploy again:", | ||
'', | ||
'```', | ||
'yarn add -D @redwoodjs/cli-data-migrate', | ||
'```', | ||
].join('\n'), | ||
) | ||
} else { | ||
execa.commandSync('yarn rw dataMigrate up', execaConfig) | ||
} | ||
} | ||
|
||
export const handler = async ({ force, database }) => { | ||
recordTelemetryAttributes({ | ||
command: 'setup deploy render', | ||
force, | ||
database, | ||
}) | ||
const tasks = new Listr( | ||
[ | ||
{ | ||
title: 'Adding render.yaml', | ||
task: async () => { | ||
const fileData = await getRenderYamlContent(database) | ||
let files = {} | ||
files[fileData.path] = fileData.content | ||
return writeFilesTask(files, { overwriteExisting: force }) | ||
}, | ||
}, | ||
updateApiURLTask('/.redwood/functions'), | ||
// Add health check api function | ||
addFilesTask({ | ||
files: additionalFiles, | ||
force, | ||
}), | ||
printSetupNotes(notes), | ||
], | ||
{ rendererOptions: { collapseSubtasks: false } }, | ||
) | ||
const serverFilePath = path.join(rwjsPaths.api.dist, 'server.js') | ||
const hasServerFile = fs.pathExistsSync(serverFilePath) | ||
|
||
if (hasServerFile) { | ||
execa(`yarn node ${serverFilePath}`, execaConfig) | ||
} else { | ||
const { handler } = await import( | ||
'@redwoodjs/api-server/dist/apiCLIConfigHandler.js' | ||
) | ||
handler() | ||
} | ||
} | ||
|
||
async function runWebCommands() { | ||
execa.commandSync('yarn install', execaConfig) | ||
execa.commandSync('yarn rw build web --verbose', execaConfig) | ||
} | ||
|
||
try { | ||
await tasks.run() | ||
} catch (e) { | ||
errorTelemetry(process.argv, e.message) | ||
console.error(c.error(e.message)) | ||
process.exit(e?.exitCode || 1) | ||
if (side === 'api') { | ||
runApiCommands() | ||
} else if (side === 'web') { | ||
runWebCommands() | ||
} | ||
} |
Oops, something went wrong.