refract
A TypeScript CDK for Prisma.
Installation
yarn add @cwqt/refract
npx ts-node refract.ts
Example
schema.ts
const Role = Enum('Role', ['USER', 'ADMIN'] as const);
const Post = Model('Post');
const User = Model('User');
const Timestamps = Mixin()
.Field('createdAt', DateTime(Default('now()')))
.Field('updatedAt', DateTime(UpdatedAt));
User.Field('id', Int(Index, Default('autoincrement()')))
.Field('email', Varchar(Unique))
.Field('name', Varchar(Nullable))
.Field('role', Role('USER'))
.Relation('posts', OneToMany(Post))
.Mixin(Timestamps);
Post.Field('id', Int(Index, Default('autoincrement()')))
.Field('published', Boolean(Default(false)))
.Field('title', Varchar(Limit(255)))
.Field('authorId', Int(Nullable))
.Relation('author', ManyToOne(User, Pk('id').Fk('authorId'), Nullable))
.Mixin(Timestamps)
.Raw(`@@map("comments")`);
export default [Role, User, Post];
refract.ts
import Refract from '@cwqt/refract';
import schema from './schema';
Refract({
datasource: {
provider: 'postgresql',
url: process.env.PG_URL,
shadowDatabaseUrl: process.env.PG_SHADOW_URL,
referentialIntegrity: 'prisma',
},
generators: [
{
provider: 'prisma-client-js',
previewFeatures: ['referentialIntegrity'],
engineType: 'library',
binaryTargets: ['native'],
},
],
output: path.join(process.cwd(), 'myschema.prisma'),
schema,
});
Handling circular relationships
At some point you'll wanna split the schema across files, which introduces issues circular relationships when you're importing for .Relation()
s
One way to get around this is to have a file with all the models/enums defined, and have files import those & apply the fields, e.g.
const User = Model("User");
const Post = Model("Posts");
import { User, Post } from './models'
User
.Field("id", Int(Index, Default("autoincrement()")))
.Relation("posts", OneToMany(Post))
import { User, Post } from './models'
Post
.Field("id", Int(Index, Default("autoincrement()")))
.Field("authorId", Int())
.Relation("author", ManyToOne(User, Pk("id").Fk("authorId")))
import * as schema from './models'
require("./posts.ts");
require("./users.ts");
Refract({
datasource: {...},
generators: [...],
schema
})
Another way is to use a string
instead of the model as the 1st argument of the Relation type, e.g. .Relation("posts", OneToMany("Posts"))
.
Caveats
- Only tested on
mysql
- Doesn't have all features, yet (PRs welcome!)
- Made in two weekends while drinking 🥴