@hexys/prismix
Version:
Create multiple Prisma schema files with shared model relations.
173 lines (130 loc) • 5.47 kB
Markdown
# `Prismix`
### *The Prisma schema mixer 🍹*
_Made for Prisma `^2.0`_
[](https://www.npmjs.com/package/prismix)
[](https://www.npmjs.com/package/prismix)
Prisma restricts your schema to a single file, Prismix allows you to write as many schema files as you'd like, wherever you like—all while supporting cross-file model relations 🤯
> Learn more about Prisma: [prisma.io](https://prisma.io)
Unlike `prisma-merge`, Prismix allows model relations to exist between files by combining models and enums, allowing you to extend and override Models as you please. This is ideal when working in a monorepo where parts of your schema need to exist in separate modules.
## Installation
1. Install Prismix
```
yarn add prismix --dev
```
or NPM
```
npm install prismix --dev
```
2. Create a `prismix.config.json` file in the root of your project. This allows you to define how you would like Prismix to merge your schemas.
```json
{
"mixers": [
{
"input": [
"base.prisma",
"./modules/auth/auth.prisma",
"./modules/posts/posts.prisma",
],
"output": "prisma/schema.prisma"
}
]
}
```
The order of your input files effects how overrides are considered, the later inputs take priority over the earlier inputs.
The default `output` value is `prisma/schema.prisma` (it can be omitted from the config) and Prisma encourages you to keep is as such, especially if you want to use `prisma format`.
3. Add the `npx prismix` command as a prefix to your `package.json` scripts.
```json
{
"name": "my-app",
"version": "1.0.0",
"scripts": {
"prismix": "npx prismix && prisma format",
"dev": "yarn prismix && ts-node server.ts",
}
}
```
Or just run `npx prismix` from within the repo that contains the Prismix config file.
Using `prisma format` is optional, but I like clean code.
Note: If you are using a monorepo you won't be able to run this command from the root, if you add a script `"prismix": "npx prismix"` you could run `yarn workspace my-app prismix`.
## Cross-file relations
In order to relate to a model defined in another file you **must create an alias model**. This is simply a model with only the `` field.
This is to ensure Prisma can parse the schema file, as Prismix uses the Prisma SDK to parse each file individually before merging models at field level.
```prisma
model Post {
id String (autoincrement())
}
```
In the above example `Post` would be a model defined in another schema, any fields added in this schema file will be merged with any `Post` model(s) in other schema files. The `` field is the only required field in an extended model, however you may add fields specific to a relation. (this is shown in greater detail below)
## Example
Let's go over how Prismix merges schemas. We'll keep it simple with two schemas that need to relate to each other.
## `base.prisma`
```prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = "postgresql://..."
}
model Account {
id Int (autoincrement())
username String
email String
status String
@("accounts")
}
```
We've established our `generator` and `datasource`, as well as our first model, `Account`. It is required that these two definitions be present in at least one of your schemas.
## `posts.prisma`
Now we'll create the Posts schema in a different file. In order for posts to relate to accounts we can define an **empty model** to represent the account.
```prisma
model Post {
id Int (autoincrement())
title String
content String
account_id Int
account Account (fields: [account_id], references: [id])
@("posts")
}
model Account {
id Int
posts Post[]
}
```
When Prismix merges these two schemas the relations will be connected.
## `schema.prisma`
This is the generated file, do not edit this file!
```prisma
// *** GENERATED BY PRISMIX :: DO NOT EDIT ***
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = "postgresql://..."
}
model Account {
id Int (autoincrement())
username String
email String
status String
posts Post[]
}
model Posts {
id Int (autoincrement())
title String
content String
account_id Int
account Account (fields: [account_id], references: [id])
@("posts")
}
```
As you can see the property `posts` was added on to the original Account schema and the `account` relation on the Posts schema links to the original Account schema.
## How it works
Using the Prisma SDK we parse the input schemas into a DMMF objects, then process the schema merge into a single DMMF object as per the config file, finally it is converted back into Prisma schema format using a custom deserializer, adapted from `/prisma-schema-transformer` and written to the output location.
## To-do
- [x] Make it work
- [x] Add glob support for wildcard schema discovery
- [ ] Make `prismix.config.json` optional
- [ ] Add command flags
Created by [](https://twitter.com/jamiepine)