├── .github
└── workflows
│ └── database.yml
├── .gitignore
├── LICENSE
├── README.md
├── docker-compose.yml
├── next-screenshot.png
├── next
├── .env.example
├── .eslintrc.json
├── .gitignore
├── README.md
├── next-env.d.ts
├── next.config.js
├── package-lock.json
├── package.json
├── pages
│ ├── _app.tsx
│ ├── api
│ │ ├── user.ts
│ │ └── users.ts
│ └── index.tsx
├── public
│ ├── favicon.ico
│ └── vercel.svg
└── tsconfig.json
└── prisma
├── .env.example
├── .npmignore
├── migrations
├── 20211125013629_initial
│ └── migration.sql
└── migration_lock.toml
├── package-lock.json
├── package.json
├── schema.prisma
├── src
├── index.d.ts
└── index.ts
└── tsconfig.json
/.github/workflows/database.yml:
--------------------------------------------------------------------------------
1 | name: Prisma
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request: {}
8 |
9 | defaults:
10 | run:
11 | working-directory: prisma/
12 |
13 | jobs:
14 | package:
15 | runs-on: ubuntu-latest
16 |
17 | steps:
18 | - name: Checkout
19 | uses: actions/checkout@v2
20 |
21 | - name: Cache node modules
22 | uses: actions/cache@v1
23 | with:
24 | path: ~/.npm
25 | key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
26 | restore-keys: |
27 | ${{ runner.os }}-node-
28 | ${{ runner.os }}-
29 |
30 | - name: Setup Node.js 16.x
31 | uses: actions/setup-node@v1
32 | with:
33 | node-version: 16.x
34 |
35 | - name: Install dependencies
36 | run: npm ci
37 |
38 | - name: Generate Client
39 | run: npx prisma generate
40 |
41 | - name: Pack the package
42 | run: npm pack
43 |
44 | # setup again with the github npm registry
45 | - name: Setup Node.js 16.x (GitHub npm registry)
46 | uses: actions/setup-node@v1
47 | with:
48 | node-version: 16.x
49 | registry-url: https://npm.pkg.github.com/
50 | scope: "@marcmogdanz"
51 |
52 | - run: npm publish
53 | env:
54 | NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
55 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/node_modules/
2 | **/dist/
3 | **/.env
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Marc Mogdanz
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # typed-prisma-package
2 |
3 | This repository is an example on how to manage your prisma setup from a central place and export a package which wraps the "normal" Prisma but include your specific typings. It is useful for e.g. a microservice setup in which every service can import the package and you can manage/publish the prisma package from a dedicated place/repository.
4 |
5 | ## Structure
6 |
7 | - The `prisma/` directory contains everything prisma related (e.g. schema, migrations) and also the code to bundle the typed prisma package in your own
8 | - The `next/` directory is a basic webapp to showcase how it works on the other side when you use the package, in your case this does NOT need to be in the same repository!
9 | - The `.github/workflows/` directory contains an example GitHub Actions file on how to publish the package to a npm registry
10 |
11 | ## Manual setup
12 |
13 | Start the database in background via docker
14 |
15 | ```bash
16 | $ docker-compose up -d postgres
17 | ```
18 |
19 | Switch to the prisma directory
20 |
21 | ```bash
22 | $ cd prisma
23 | ```
24 |
25 | Install dependencies
26 |
27 | ```bash
28 | $ npm i
29 | ```
30 |
31 | Create the npm package, this step will also run the `prepare` script which generates the typings via `prisma generate` and compiles the `index.ts`
32 |
33 | ```bash
34 | $ npm pack
35 | ```
36 |
37 | The above steps are the ones necessary to create the package, from here you could e.g. run `npm publish` or manually use the generated `.tgz` file which we're going to do now for the example.
38 |
39 | ---
40 |
41 | But first we need to make sure all migrations are deployed against the local database
42 |
43 | ```bash
44 | prisma migrate deploy
45 | ```
46 |
47 | Now we can move the generated package over in the example Next.js app
48 |
49 | ```bash
50 | mv marcmogdanz-typed-prisma-package-1.0.0.tgz ../next
51 | ```
52 |
53 | And switch over to the directory
54 |
55 | ```bash
56 | cd ../next
57 | ```
58 |
59 | Now we can simply install the package
60 |
61 | ```bash
62 | npm i marcmogdanz-typed-prisma-package-1.0.0.tgz
63 | ```
64 |
65 | And run the Next.js app
66 |
67 | ```bash
68 | npm run dev
69 | ```
70 |
71 | Now you can head to [http://localhost:3000](http://localhost:3000), create an example user and see all existing users. Check out the routes in the `next/pages/api` directory to see the typed prisma package in action.
72 |
73 | 
74 |
75 | # CI via GitHub Actions
76 |
77 | In the `.github/workflows/database.yml` file you can find an example on how to pack and publish this to a (private) npm registry, in this case GitHub's.
78 | The package is now available [here](https://github.com/MarcMogdanz/typed-prisma-package/packages/1114330) and the easiest way to install it another project is to create a `.npmrc` in the repository where you want to use the package (e.g. my example Next.js app) and override the registry key for your scope (in my case `@marcmogdanz`) like below:
79 |
80 | ```
81 | @marcmogdanz:registry = https://npm.pkg.github.com/marcmogdanz
82 |
83 | _authToken = "ghp_TOKEN_WITH_PACKAGE_ACCESS"
84 | always-auth = true
85 | ```
86 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.5"
2 |
3 | services:
4 | postgres:
5 | image: postgres:14
6 | environment:
7 | POSTGRES_USER: postgres
8 | POSTGRES_PASSWORD: postgres
9 | POSTGRES_DB: postgres
10 | PGDATA: /data/postgres
11 | volumes:
12 | - postgres:/data/postgres
13 | ports:
14 | - "5432:5432"
15 |
16 | volumes:
17 | postgres: {}
18 |
--------------------------------------------------------------------------------
/next-screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarcMogdanz/typed-prisma-package/318467d7789a60c28c7c536ac3ce1ff89b1305ae/next-screenshot.png
--------------------------------------------------------------------------------
/next/.env.example:
--------------------------------------------------------------------------------
1 | DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres?schema=public"
2 |
--------------------------------------------------------------------------------
/next/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/next/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 |
27 | # local env files
28 | .env.local
29 | .env.development.local
30 | .env.test.local
31 | .env.production.local
32 |
33 | # vercel
34 | .vercel
35 |
36 | # typescript
37 | *.tsbuildinfo
38 |
--------------------------------------------------------------------------------
/next/README.md:
--------------------------------------------------------------------------------
1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2 |
3 | ## Getting Started
4 |
5 | First, run the development server:
6 |
7 | ```bash
8 | npm run dev
9 | # or
10 | yarn dev
11 | ```
12 |
13 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
14 |
15 | You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
16 |
17 | [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
18 |
19 | The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
20 |
21 | ## Learn More
22 |
23 | To learn more about Next.js, take a look at the following resources:
24 |
25 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
26 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
27 |
28 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
29 |
30 | ## Deploy on Vercel
31 |
32 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
33 |
34 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
35 |
--------------------------------------------------------------------------------
/next/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | ///
4 |
5 | // NOTE: This file should not be edited
6 | // see https://nextjs.org/docs/basic-features/typescript for more information.
7 |
--------------------------------------------------------------------------------
/next/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | module.exports = {
3 | reactStrictMode: true,
4 | }
5 |
--------------------------------------------------------------------------------
/next/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "next",
3 | "private": true,
4 | "scripts": {
5 | "dev": "next dev",
6 | "build": "next build",
7 | "start": "next start",
8 | "lint": "next lint"
9 | },
10 | "dependencies": {
11 | "@marcmogdanz/typed-prisma-package": "file:marcmogdanz-typed-prisma-package-1.0.0.tgz",
12 | "next": "12.0.4",
13 | "react": "17.0.2",
14 | "react-dom": "17.0.2",
15 | "swr": "^1.0.1"
16 | },
17 | "devDependencies": {
18 | "@types/node": "16.11.10",
19 | "@types/react": "17.0.37",
20 | "eslint": "7.32.0",
21 | "eslint-config-next": "12.0.4",
22 | "typescript": "4.5.2"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/next/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import type { AppProps } from "next/app";
2 |
3 | function MyApp({ Component, pageProps }: AppProps) {
4 | return ;
5 | }
6 |
7 | export default MyApp;
8 |
--------------------------------------------------------------------------------
/next/pages/api/user.ts:
--------------------------------------------------------------------------------
1 | import type { NextApiRequest, NextApiResponse } from "next";
2 | import * as Prisma from "@marcmogdanz/typed-prisma-package";
3 |
4 | export type User = {
5 | id: string;
6 | name: string;
7 | };
8 |
9 | export default async function handler(
10 | req: NextApiRequest,
11 | res: NextApiResponse
12 | ) {
13 | const { name } = JSON.parse(req.body);
14 |
15 | const { prisma } = await Prisma.createContext();
16 |
17 | const user = await prisma.user.create({
18 | data: {
19 | name,
20 | },
21 | });
22 |
23 | res.status(200).json({
24 | id: user.id,
25 | name: user.name,
26 | });
27 | }
28 |
--------------------------------------------------------------------------------
/next/pages/api/users.ts:
--------------------------------------------------------------------------------
1 | import type { NextApiRequest, NextApiResponse } from "next";
2 | import * as Prisma from "@marcmogdanz/typed-prisma-package";
3 | import { User } from "./user";
4 |
5 | export default async function handler(
6 | req: NextApiRequest,
7 | res: NextApiResponse
8 | ) {
9 | console.log("req", req.body);
10 |
11 | const { prisma } = await Prisma.createContext();
12 |
13 | const users = await prisma.user.findMany();
14 |
15 | res.status(200).json(users);
16 | }
17 |
--------------------------------------------------------------------------------
/next/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import type { NextPage } from "next";
2 | import { useState } from "react";
3 | import useSWR from "swr";
4 | import { User } from "./api/user";
5 |
6 | const fetcher = (url: string) => fetch(url).then((res) => res.json());
7 |
8 | const Home: NextPage = () => {
9 | const [name, setName] = useState("");
10 |
11 | const createUser = async () => {
12 | await fetch("/api/user", {
13 | method: "POST",
14 | body: JSON.stringify({ name }),
15 | }).then((res) => res.json());
16 | };
17 |
18 | const { data, error } = useSWR("/api/users", fetcher);
19 | if (error) return