Skip to content

Commit f97b50d

Browse files
committed
feat: first implementation (base from https://github.com/Cauen/prisma-generator-pothos-codegen)
0 parents  commit f97b50d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+8407
-0
lines changed

.eslintrc

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"extends": ["standard", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended"],
3+
"env": {
4+
"node": true
5+
},
6+
"ignorePatterns": ["examples/*"],
7+
"rules": {
8+
"prettier/prettier": [
9+
"error",
10+
{
11+
"semi": false,
12+
"printWidth": 120,
13+
"tabWidth": 2,
14+
"tabs": false,
15+
"singleQuote": true,
16+
"quoteProps": "consistent",
17+
"jsxSingleQuote": false,
18+
"trailingComma": "all",
19+
"bracketSpacing": true,
20+
"bracketSameLine": false,
21+
"arrowParens": "always",
22+
"endOfLine": "auto"
23+
}
24+
],
25+
"@typescript-eslint/no-unused-vars": [
26+
"warn",
27+
{
28+
"argsIgnorePattern": "^_",
29+
"varsIgnorePattern": "^_",
30+
"caughtErrorsIgnorePattern": "^_"
31+
}
32+
],
33+
"import/order": ["warn", {
34+
"groups": ["builtin", "external", "internal", "parent", "sibling", "index", "object", "type"],
35+
"newlines-between": "never",
36+
"alphabetize": {
37+
"order": "asc",
38+
"caseInsensitive": true
39+
}
40+
}]
41+
},
42+
"parser": "@typescript-eslint/parser",
43+
"plugins": ["@typescript-eslint"],
44+
"parserOptions": {
45+
"ecmaVersion": "latest",
46+
"sourceType": "module"
47+
}
48+
}

.github/workflows/ci.yml

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- master
8+
9+
pull_request:
10+
types: [opened, synchronize]
11+
12+
workflow_dispatch:
13+
14+
jobs:
15+
build:
16+
runs-on: ubuntu-latest
17+
strategy:
18+
matrix:
19+
prisma-version: [4.7.0, 4.8.0]
20+
node-version: [16, 18]
21+
22+
name: Node ${{ matrix.node-version }} with Prisma ${{ matrix.prisma-version }}
23+
steps:
24+
- name: 🛑 Cancel Previous Runs
25+
uses: styfle/[email protected]
26+
27+
- name: ⬇️ Checkout repo
28+
uses: actions/checkout@v3
29+
30+
- name: ⎔ Setup Node.js environment
31+
uses: actions/setup-node@v3
32+
with:
33+
node-version: ${{ matrix.node-version }}
34+
cache: "yarn"
35+
36+
- name: 🏗 Swap Prisma version to ~${{ matrix.prisma-version }}
37+
run: |
38+
sed -i -E 's|"prisma": ".*"|"prisma": "~${{ matrix.prisma-version }}"|g' package.json
39+
sed -i -E 's|"\@prisma/client": ".*"|"\@prisma/client": "~${{ matrix.prisma-version }}"|g' package.json
40+
sed -i -E 's|"\@prisma/generator-helper": ".*"|"\@prisma/generator-helper": "~${{ matrix.prisma-version }}"|g' package.json
41+
sed -i -E 's|"\@prisma/internals": ".*"|"\@prisma/internals": "~${{ matrix.prisma-version }}"|g' package.json
42+
43+
- name: 📥 Install dependencies
44+
run: yarn install
45+
46+
- name: 🧪 Run tests
47+
run: yarn test
48+

.gitignore

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
node_modules
2+
coverage
3+
__snapshots__
4+
generated/*
5+
dmmf.json
6+
log.txt
7+
yarn*.log
8+
dist
9+
tsconfig.tsbuildinfo
10+
TEST-*

.vscode/settings.json

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"files.eol": "\n",
3+
"typescript.tsdk": "node_modules/typescript/lib",
4+
}

CONTRIBUTING.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Disclosures
2+
3+
- We don't use tsconfig paths, because of examples (the prisma generate don't support paths)

README.md

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Prisma Generator Postgres Realtime
2+
3+
A prisma generator that turns your Postgres Database into a realtime Database and make it easy to subscribe to changes from Prisma Client type-safe Api
4+
5+
## How it works?
6+
7+
1. On `prisma generate` it will generate the `prismaExtension.ts` and `prismaRealtimeStatus.json` (to store what migrations have been generated and avoid regenerating them) file and the needed `migrations` to make your database send realtime events
8+
2. Run `prisma migrate dev` to apply all generated migrations
9+
3. Use the generated extension in prisma client to enable a new client/models method called `$subscribe` and start watching to realtime events sent
10+
11+
OBS:
12+
- (Optional) Use the `generatorConfigPath` generator option to customize some options for your project (like excluding models, ...)
13+
14+
### Set up
15+
16+
#### Install generator
17+
`npm install --save-dev prisma-generator-postgres-realtime` (or yarn | pnpm version)
18+
19+
#### Install node-postgres peer dependancy
20+
`npm install pg`
21+
22+
#### Add the generator to your `schema.prisma`
23+
24+
```prisma
25+
// schema.prisma
26+
generator client {
27+
provider = "prisma-client-js"
28+
}
29+
30+
// new generator here ⬇️
31+
generator realtime {
32+
provider = "prisma-generator-postgres-realtime"
33+
generatorConfigPath = "../src/realtime/configs.js" // (optional)
34+
}
35+
36+
/// This is an user
37+
model User {
38+
id String @id
39+
}
40+
```
41+
42+
### Usage
43+
44+
1. Run `prisma generate` to generate the `prismaExtension.ts` file and migrations
45+
2. Run `prisma migrate dev` to apply all generated migrations
46+
3. Import the extension to your prisma client
47+
```ts
48+
/* src/db.ts */
49+
import { PrismaClient } from "@prisma/client";
50+
// Import auto generated extension
51+
import { prismaRealtimeExtension } from './realtime/prismaExtension';
52+
53+
const prisma = new PrismaClient().$extends(PrismaExtension);
54+
55+
// global subscription
56+
prisma.$subscribe(({ dbUser, model, newRow, oldRow, operation, tableName, tableSchema, timestamp }) => {
57+
console.log(`${operation} in ${model} at ${timestamp}`)
58+
})
59+
60+
// typesafe model subscription
61+
prisma.user.$subscribe(({ dbUser, model, newRow, oldRow, operation, tableName, tableSchema, timestamp }) => {
62+
console.log(`${operation} in ${model} at ${timestamp}`)
63+
}, {
64+
// (optional) Enable logs for connection, by defaults only shows errors
65+
logLevel: "all",
66+
// (optional) Custom postgres connection string, by default it uses the one from `process.env.DATABASE_URL`
67+
connectionString: "postgres://postgres:postgres@localhost:5432/postgres"
68+
})
69+
```
70+
71+
### Configuration file (optional)
72+
Create a configuration file (optional) and reference it in your `schema.prisma` generator config called `generatorConfigPath`
73+
74+
This configuration file enables some options like customize generated code, file paths, Prisma importer for some projects like Monorepos and disabling realtime for some specific models
75+
76+
```ts
77+
// ./src/realtime/configs.js
78+
79+
// /** @type {import('prisma-generator-postgres-realtime').Config} */
80+
81+
/** @type {import('../../../../src').Config} */
82+
module.exports = {
83+
migrations: {
84+
// Option to disable the generation of migrations
85+
disabled: false,
86+
// Directory to generate the custom migrations from project root
87+
outputDirPath: "./prisma/migrations",
88+
// Path to generate the status file to from project root
89+
outputStatusFilePath: "./src/realtime/prismaRealtimeStatus.json",
90+
// A function to replace generated source
91+
replacer: (str) => str
92+
// Included models in migrations
93+
excludeModels: [],
94+
// Excluded models in migrations (Ignored if includeModels is set)
95+
includeModels: [],
96+
},
97+
extension: {
98+
// Option to disable the generation of crud
99+
disabled: false,
100+
// Path to generate the inputs file to from project root
101+
outputFilePath: "./src/realtime/prismaExtension.ts",
102+
// The code to import the prisma client (Util for some projects like Monorepos)
103+
prismaClientImporter: `import { Prisma } from "@prisma/client";`,
104+
// A function to replace generated source
105+
replacer: (str) => str,
106+
},
107+
global: {
108+
// Function to run before generate
109+
beforeGenerate: (dmmf) => {},
110+
// Function to run after generate
111+
afterGenerate: (dmmf) => {},
112+
// A function to replace generated source
113+
replacer: (str) => str,
114+
// The name of the postgres trigger
115+
triggerName: "prisma_postgres_realtime_trigger",
116+
},
117+
};
118+
119+
```
120+
121+
### Examples
122+
123+
Check for the [example](/examples/simple) for a running sample
124+
125+
### Disclaimer
126+
127+
#### Prisma Views
128+
129+
Currently, prisma does not enable us distinguish between models and views [(issue)](https://github.com/prisma/prisma/issues/17754). So if you are working with views you can disable generation of views from "options.migrations.excludeModels" or by simply deleting this part of code from the migration

changelog.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Changelog
2+
3+
# 0.1.0
4+
5+
- [x] Feat: First version

examples/readme.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Running examples
2+
3+
## With source code
4+
5+
- Clone this repo
6+
- `cd examples/simple`
7+
- `yarn install`
8+
- `yarn migrate`
9+
- `yarn dev`
10+
- Create/update/delete some data in database and see realtime events logs
11+
12+
## Without
13+
14+
- Clone this repo
15+
- `cd examples/simple`
16+
- `yarn install`
17+
- `yarn add prisma-generator-postgres-realtime`
18+
- Replace generator from `/prisma/schema.prisma` from `ts-node --transpile-only ../../src/generator.ts` to `prisma-generator-postgres-realtime`
19+
- `yarn migrate`
20+
- `yarn dev`
21+
- Create/update/delete some data in database and see realtime events logs

examples/simple/.env

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# POSTGRES_REALTIME_CONFIG_PATH="../src/unexist/configs.js"
2+
DATABASE_URL="postgresql://my-pg-user:my-pg-pass@localhost:5432/realtime-postgres"

examples/simple/nodemon.json

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"watch": ["src", ".env"],
3+
"ext": "ts",
4+
"exec": "yarn build && yarn start"
5+
}

examples/simple/package.json

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "inputs-simple",
3+
"version": "1.0.0",
4+
"main": "index.js",
5+
"license": "MIT",
6+
"scripts": {
7+
"generate": "prisma generate",
8+
"generate-debug": "npx cross-env DEBUG=* prisma generate",
9+
"migrate": "prisma migrate dev",
10+
"type": "tsc --noEmit",
11+
"dev": "nodemon",
12+
"build": "tsup ./src/server.ts",
13+
"start": "node dist/server.js",
14+
"tscheck": "tsc --noEmit"
15+
},
16+
"dependencies": {
17+
"@prisma/client": "5.17.0",
18+
"@prisma/extension-pulse": "^1.2.0",
19+
"apollo-server": "^3.13.0",
20+
"graphql": "^16.8.1",
21+
"pg": "^8.13.1"
22+
},
23+
"devDependencies": {
24+
"@types/pg": "^8.11.10",
25+
"nodemon": "^3.1.0",
26+
"prisma": "^5.17.0",
27+
"ts-node": "^10.9.2",
28+
"tsup": "^8.0.2",
29+
"typescript": "^5.5.3"
30+
}
31+
}

examples/simple/prisma/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.db*

0 commit comments

Comments
 (0)