Prisma, non un ORM tradizionale
Cos'è prisma? Perché usarlo? Una panoramica introduttiva per cercare di capirlo
Difficile dire cos’è Prisma, forse riesce meglio dire cosa non è. Non è un ORM tradizionale, non crea dei modelli (o entità) nel linguaggio in cui stiamo sviluppando, ma crea degli schema in una strana estensione .prisma
.
Il flusso
Sulla documentazione ufficale di Prisma c’è la stessa immagine che riporto sotto per dare un’idea ad altissimo livello su come lavora Prisma dietro le quinte.
Prisma si interfaccia con il database come segue:
Connettendosi al DB, innanzitutto;
Introspeziona lo schema del DB e genera il datamodel (che sarà proprio
datamodel.prisma
, il file prodotto di cui ne ho già accennato)Genera il client, un codice autogenerato che può essere integrato nel nostro software nel linguaggio che scegliamo, lo spiego meglio più avanti.
Creare un’applicazione Prisma
Nota: Per la mia applicazione d’esempio, ho utilizzato un database mongo che avevo su una virtual machine. Faccio questa doverosa precisazione perché l’introspezione su mongodb alla data in cui scrivo non è supportata e questo presenta un ostacolo se l’architettura di partenza è pensata database-first, perché sarete costretti a creare tutti gli schema manualmente. Sorry.
Per utilizzare Prisma a pieno occurrono alcuni passaggi preliminari:
Bisogna avere installato sulla propria macchina Docker (e ahimè non si scappa);
Installare la CLI di Prisma:
npm install -g prisma
o per mac:
brew tap prisma/prismabrew install prisma
Adesso ti servirà il microservizio di Prisma, contenuto in un container docker per agganciarci al nostro database e generare lo schema. Per farlo, ci metteremo sulla directory scelta del progetto e creeremo il file docker-compose.yml
, che ho già opportunamente modificato per farlo funzionare con il mio db:
version: '3'services:prisma:image: prismagraphql/prisma:1.28restart: alwaysports:- "4468:4468"environment:PRISMA_CONFIG: |port: 4468databases:default:connector: mongouri: mongodb://172.22.156.180database: "test"mongo:image: mongo:3.6restart: alwaysenvironment:MONGO_INITDB_ROOT_USERNAME: prismaMONGO_INITDB_ROOT_PASSWORD: prismaports:- "27017:27017"volumes:- mongo:/var/lib/mongovolumes:mongo:
La mia prima impressione è stata:
Pura. Magia. Nera.
Tentando di semplificare mi sono concentrato su:
Connection string del database
Porta che utilizzerà il servizio
Una volta impostate entrambe, Prisma introspezionerà il db e genererà lo schema, ma solo eseguendo il seguente comando:
docker-compose up -d
Se l’esito del comando dato sarà positivo, vedrai che si è generato un file denominato datamodel.prisma
che conterrà quanto segue come default:
type User {id: ID! @uniquename: String!}
Bene, hai il tuo schema generato ma nonostante ciò non puoi ancora interagire con il db. Per farlo ci serve che prisma generi per noi un servizio che ci permetta di interrogare il db e fare delle operazioni. Per questo, creeremo un secondo file ma stavolta generandolo tramite questo comando:
prisma init --endpoint http://localhost:4468
Questo genererà un file prisma.yml
che in questa introduzione userai per generare il client e inizializzare il servizio.
Il file prisma.yml
si presenterà così al suo interno:
endpoint: http://localhost:4468datamodel: datamodel.prisma
A questo aggiungi le due proprietà con i relativi sotto elementi, il perché lo spiego a seguire:
endpoint: http://localhost:4468datamodel: datamodel.prismadatabaseType: documentgenerate:- generator: javascript-clientoutput: ./generated/prisma-client/
NOTE: Da documentazione ufficiale, se il db è Mongo deve essere esplicitata la proprietà
databaseType
adocument
. Prisma su questo fronte mi da’ l’impressione di essere ancora un po’ acerbo per mongo ma sono sicuro che subirà ancora aggiornamenti non lontani dalla data in cui scrivo questo post.
La proprietà generate
esplicita in quale linguaggio il codice per generare il client, deve essere prodotto. Dal momento che mi trovo su node ho ovviamente optato per il javascript-generator
e impostato come output ./generated/prisma-client/
, ma tu vai e sii l’artefice del tuo destino.
Fatto ciò, esegui il comando che genererà, come da te indicato, il codice:
prisma generate
Se adesso tu andassi a dare un’occhiata al file nel percorso ./generated/prisma-client/schema-prisma.js
troveresti qualcosa di familiare… il datamodel.prisma
riscritto come proprietà typeDefs
!
module.exports = {typeDefs: // Code generated by Prisma (prisma@1.28.5). DO NOT EDIT.// Please don't change this file manually but run `prisma generate` to update it.// For more information, please read the docs: https://www.prisma.io/docs/prisma-client///... omesso il resto per brevità}
Tornando alla directory principale, installa le dipendenze per far funzionare il codice staticamente prodotto:
npm init -ynpm install --save prisma-client-lib
Crea il file index.js
e scrivi una funzione che crei un utente:
const { prisma } = require('./generated/prisma-client')// A `main` function so that we can use async/awaitasync function main() {// Create a new user called `Alice`const newUser = await prisma.createUser({ name: 'Alice' })console.log(`Created new user: ${newUser.name} (ID: ${newUser.id})`)// Read all users from the database and print them to the consoleconst allUsers = await prisma.users()console.log(allUsers)}main().catch(e => console.error(e))
Finito! Adesso mettiamo su il servizio…
Fatto questo, possiamo dare il finale ed agognato comando:
prisma deploy
Quest’ultimo avvierà un servizio che ti permetterà di interagire con il db con lo schema graphQL. In console vedrai un messaggio come questo:
Deploying service `default` to stage `default` to server `local` 566ms
L’endpoint che puoi consultare sarà lo stesso che avete dichiarato all’inizio, ossia http://localhost:4468
Se a questo punto tu dessi il comando:
node index
Verrà:
generato un utente di nome “Alice”
ritornata una lista di tutti gli utenti
Esplorando il servizio con il playground offerto da yoga (l’editor visuale online per eseguire le query in graphql) hai a disposizione tutta la documentazione necessaria per fare mutation, query e subscription.
Se utilizzi quel codice staticamente prodotto e decidi di aggiornare il datamodel.prisma
ricordati che devi far rigenererare al tuo client, per farlo ridai sempre il comando:
prisma generate