mirror of
https://github.com/dillonkearns/elm-pages-v3-beta.git
synced 2024-12-23 11:55:41 +03:00
Migrate some code from todo example to prisma.
This commit is contained in:
parent
e6c372b14b
commit
114043eaee
@ -27,7 +27,6 @@ import Pages.Msg
|
||||
import Pages.PageUrl exposing (PageUrl)
|
||||
import Pages.Script as Script
|
||||
import Pages.Url
|
||||
import Request.Hasura
|
||||
import Route
|
||||
import RouteBuilder exposing (StatelessRoute, StaticPayload)
|
||||
import SendGrid
|
||||
@ -215,13 +214,15 @@ data routeParams =
|
||||
(\emailIfValid ->
|
||||
case maybeSessionId of
|
||||
Just sessionId ->
|
||||
Data.Session.get sessionId
|
||||
|> Request.Hasura.backendTask
|
||||
BackendTask.Custom.run
|
||||
"getEmailBySessionId"
|
||||
(Encode.string sessionId)
|
||||
(Decode.maybe Decode.string)
|
||||
|> BackendTask.allowFatal
|
||||
|> BackendTask.map
|
||||
(\maybeUserSession ->
|
||||
( okSessionThing
|
||||
, maybeUserSession
|
||||
|> Maybe.map .emailAddress
|
||||
|> Data
|
||||
|> Server.Response.render
|
||||
)
|
||||
@ -230,24 +231,27 @@ data routeParams =
|
||||
Nothing ->
|
||||
case emailIfValid of
|
||||
Just confirmedEmail ->
|
||||
Data.Session.findOrCreateUser confirmedEmail
|
||||
|> Request.Hasura.mutationBackendTask
|
||||
BackendTask.Time.now
|
||||
|> BackendTask.andThen
|
||||
(\userId ->
|
||||
BackendTask.Time.now
|
||||
|> BackendTask.andThen
|
||||
(\now_ ->
|
||||
let
|
||||
expirationTime : Time.Posix
|
||||
expirationTime =
|
||||
Time.millisToPosix (Time.posixToMillis now_ + (1000 * 60 * 30))
|
||||
in
|
||||
Data.Session.create expirationTime userId
|
||||
|> Request.Hasura.mutationBackendTask
|
||||
)
|
||||
(\now_ ->
|
||||
let
|
||||
expirationTime : Time.Posix
|
||||
expirationTime =
|
||||
Time.millisToPosix (Time.posixToMillis now_ + (1000 * 60 * 30))
|
||||
in
|
||||
BackendTask.Custom.run "findOrCreateUserAndSession"
|
||||
(Encode.object
|
||||
[ ( "confirmedEmail"
|
||||
, Encode.string confirmedEmail
|
||||
)
|
||||
, ( "expirationTime", expirationTime |> Time.posixToMillis |> Encode.int )
|
||||
]
|
||||
)
|
||||
Decode.string
|
||||
|> BackendTask.allowFatal
|
||||
)
|
||||
|> BackendTask.map
|
||||
(\(Uuid sessionId) ->
|
||||
(\sessionId ->
|
||||
( okSessionThing
|
||||
|> Session.insert "sessionId" sessionId
|
||||
, Route.Visibility__ { visibility = Nothing }
|
||||
@ -267,13 +271,19 @@ data routeParams =
|
||||
|
||||
Nothing ->
|
||||
maybeSessionId
|
||||
|> Maybe.map (Data.Session.get >> Request.Hasura.backendTask)
|
||||
|> Maybe.map
|
||||
(\sessionId ->
|
||||
BackendTask.Custom.run
|
||||
"getEmailBySessionId"
|
||||
(Encode.string sessionId)
|
||||
(Decode.maybe Decode.string)
|
||||
)
|
||||
|> Maybe.withDefault (BackendTask.succeed Nothing)
|
||||
|> BackendTask.allowFatal
|
||||
|> BackendTask.map
|
||||
(\maybeUserSession ->
|
||||
(\maybeEmail ->
|
||||
( okSessionThing
|
||||
, maybeUserSession
|
||||
|> Maybe.map .emailAddress
|
||||
, maybeEmail
|
||||
|> Data
|
||||
|> Server.Response.render
|
||||
)
|
||||
|
@ -2,6 +2,7 @@ module Route.Visibility__ exposing (ActionData, Data, Model, Msg, route)
|
||||
|
||||
import Api.Scalar exposing (Uuid(..))
|
||||
import BackendTask exposing (BackendTask)
|
||||
import BackendTask.Custom
|
||||
import Data.Session
|
||||
import Data.Todo
|
||||
import Dict exposing (Dict)
|
||||
@ -18,6 +19,8 @@ import Html.Attributes exposing (..)
|
||||
import Html.Keyed as Keyed
|
||||
import Html.Lazy exposing (lazy, lazy2)
|
||||
import Icon
|
||||
import Json.Decode as Decode
|
||||
import Json.Encode as Encode
|
||||
import LoadingSpinner
|
||||
import MySession
|
||||
import Pages.Msg
|
||||
@ -214,17 +217,15 @@ data routeParams =
|
||||
(\parsedSession requestTime session ->
|
||||
case visibilityFromRouteParams routeParams of
|
||||
Just visibility ->
|
||||
Data.Todo.findAllBySession parsedSession
|
||||
|> Request.Hasura.backendTask
|
||||
BackendTask.Custom.run "getTodosBySession"
|
||||
(Encode.string parsedSession)
|
||||
(Decode.list todoDecoder)
|
||||
|> BackendTask.allowFatal
|
||||
|> BackendTask.map
|
||||
(\todos ->
|
||||
( session
|
||||
, Response.render
|
||||
{ entries =
|
||||
todos
|
||||
-- TODO add error handling for Nothing case
|
||||
|> Maybe.withDefault []
|
||||
|> List.map toOptimisticTodo
|
||||
{ entries = todos |> List.map toOptimisticTodo
|
||||
, visibility = visibility
|
||||
, requestTime = requestTime
|
||||
}
|
||||
@ -240,6 +241,21 @@ data routeParams =
|
||||
)
|
||||
|
||||
|
||||
type alias Todo =
|
||||
{ description : String
|
||||
, completed : Bool
|
||||
, id : Uuid
|
||||
}
|
||||
|
||||
|
||||
todoDecoder : Decode.Decoder Todo
|
||||
todoDecoder =
|
||||
Decode.map3 Todo
|
||||
(Decode.field "title" Decode.string)
|
||||
(Decode.field "complete" Decode.bool)
|
||||
(Decode.field "id" (Decode.string |> Decode.map Uuid))
|
||||
|
||||
|
||||
action : RouteParams -> Request.Parser (BackendTask FatalError (Response ActionData ErrorPage))
|
||||
action routeParams =
|
||||
Request.map2 Tuple.pair
|
||||
|
@ -1,8 +1,83 @@
|
||||
import kleur from "kleur";
|
||||
import crypto from "crypto";
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
kleur.enabled = true;
|
||||
|
||||
export async function users() {
|
||||
const users = await prisma.user.findMany();
|
||||
}
|
||||
|
||||
export async function getTodosBySession(sessionId) {
|
||||
try {
|
||||
return (
|
||||
await prisma.session.findUnique({
|
||||
where: { id: sessionId },
|
||||
include: {
|
||||
user: {
|
||||
select: {
|
||||
todos: {
|
||||
select: {
|
||||
complete: true,
|
||||
// , createdAt: true
|
||||
|
||||
id: true,
|
||||
title: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)?.user.todos;
|
||||
} catch (e) {
|
||||
console.trace(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getEmailBySessionId(sessionId: string) {
|
||||
try {
|
||||
return (
|
||||
await prisma.session.findUnique({
|
||||
where: { id: sessionId },
|
||||
include: {
|
||||
user: {
|
||||
select: { email: true },
|
||||
},
|
||||
},
|
||||
})
|
||||
)?.user.email;
|
||||
} catch (e) {
|
||||
console.trace(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function findOrCreateUserAndSession({
|
||||
confirmedEmail,
|
||||
expirationTime,
|
||||
}) {
|
||||
try {
|
||||
const expirationDate = new Date(expirationTime);
|
||||
const result = await prisma.user.upsert({
|
||||
where: { email: confirmedEmail },
|
||||
create: {
|
||||
email: confirmedEmail,
|
||||
sessions: { create: { expirationDate } },
|
||||
},
|
||||
update: { sessions: { create: { expirationDate } } },
|
||||
// TODO should this be descending? Or is `asc` correct?
|
||||
include: { sessions: { take: 1, orderBy: { createdAt: "asc" } } },
|
||||
});
|
||||
return result.sessions[0].id;
|
||||
} catch (e) {
|
||||
console.trace(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/* Encrypt/decrypt code source: https://github.com/kentcdodds/kentcdodds.com/blob/43130b0d9033219920a46bb8a4f009781afa02f1/app/utils/encryption.server.ts */
|
||||
|
||||
const algorithm = "aes-256-ctr";
|
||||
|
79
examples/todos/package-lock.json
generated
79
examples/todos/package-lock.json
generated
@ -9,6 +9,7 @@
|
||||
"version": "1.0.0",
|
||||
"license": "BSD-3",
|
||||
"dependencies": {
|
||||
"@prisma/client": "^4.9.0",
|
||||
"bcryptjs": "^2.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -21,6 +22,7 @@
|
||||
"elm-tailwind-modules": "^0.3.2",
|
||||
"elm-tooling": "^1.3.0",
|
||||
"postcss": "^8.4.5",
|
||||
"prisma": "^4.9.0",
|
||||
"tailwindcss": "^2.2.19"
|
||||
}
|
||||
},
|
||||
@ -592,6 +594,38 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@prisma/client": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.9.0.tgz",
|
||||
"integrity": "sha512-bz6QARw54sWcbyR1lLnF2QHvRW5R/Jxnbbmwh3u+969vUKXtBkXgSgjDA85nji31ZBlf7+FrHDy5x+5ydGyQDg==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@prisma/engines-version": "4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"prisma": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"prisma": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@prisma/engines": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.9.0.tgz",
|
||||
"integrity": "sha512-t1pt0Gsp+HcgPJrHFc+d/ZSAaKKWar2G/iakrE07yeKPNavDP3iVKPpfXP22OTCHZUWf7OelwKJxQgKAm5hkgw==",
|
||||
"devOptional": true,
|
||||
"hasInstallScript": true
|
||||
},
|
||||
"node_modules/@prisma/engines-version": {
|
||||
"version": "4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5.tgz",
|
||||
"integrity": "sha512-M16aibbxi/FhW7z1sJCX8u+0DriyQYY5AyeTH7plQm9MLnURoiyn3CZBqAyIoQ+Z1pS77usCIibYJWSgleBMBA=="
|
||||
},
|
||||
"node_modules/@sindresorhus/is": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-2.1.1.tgz",
|
||||
@ -4906,6 +4940,23 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/prisma": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/prisma/-/prisma-4.9.0.tgz",
|
||||
"integrity": "sha512-bS96oZ5oDFXYgoF2l7PJ3Mp1wWWfLOo8B/jAfbA2Pn0Wm5Z/owBHzaMQKS3i1CzVBDWWPVnOohmbJmjvkcHS5w==",
|
||||
"devOptional": true,
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@prisma/engines": "4.9.0"
|
||||
},
|
||||
"bin": {
|
||||
"prisma": "build/index.js",
|
||||
"prisma2": "build/index.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/prompts": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
|
||||
@ -6611,6 +6662,25 @@
|
||||
"fastq": "^1.6.0"
|
||||
}
|
||||
},
|
||||
"@prisma/client": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.9.0.tgz",
|
||||
"integrity": "sha512-bz6QARw54sWcbyR1lLnF2QHvRW5R/Jxnbbmwh3u+969vUKXtBkXgSgjDA85nji31ZBlf7+FrHDy5x+5ydGyQDg==",
|
||||
"requires": {
|
||||
"@prisma/engines-version": "4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5"
|
||||
}
|
||||
},
|
||||
"@prisma/engines": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.9.0.tgz",
|
||||
"integrity": "sha512-t1pt0Gsp+HcgPJrHFc+d/ZSAaKKWar2G/iakrE07yeKPNavDP3iVKPpfXP22OTCHZUWf7OelwKJxQgKAm5hkgw==",
|
||||
"devOptional": true
|
||||
},
|
||||
"@prisma/engines-version": {
|
||||
"version": "4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5",
|
||||
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.9.0-42.ceb5c99003b99c9ee2c1d2e618e359c14aef2ea5.tgz",
|
||||
"integrity": "sha512-M16aibbxi/FhW7z1sJCX8u+0DriyQYY5AyeTH7plQm9MLnURoiyn3CZBqAyIoQ+Z1pS77usCIibYJWSgleBMBA=="
|
||||
},
|
||||
"@sindresorhus/is": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-2.1.1.tgz",
|
||||
@ -9746,6 +9816,15 @@
|
||||
"integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=",
|
||||
"dev": true
|
||||
},
|
||||
"prisma": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/prisma/-/prisma-4.9.0.tgz",
|
||||
"integrity": "sha512-bS96oZ5oDFXYgoF2l7PJ3Mp1wWWfLOo8B/jAfbA2Pn0Wm5Z/owBHzaMQKS3i1CzVBDWWPVnOohmbJmjvkcHS5w==",
|
||||
"devOptional": true,
|
||||
"requires": {
|
||||
"@prisma/engines": "4.9.0"
|
||||
}
|
||||
},
|
||||
"prompts": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
|
||||
|
@ -21,9 +21,11 @@
|
||||
"elm-tailwind-modules": "^0.3.2",
|
||||
"elm-tooling": "^1.3.0",
|
||||
"postcss": "^8.4.5",
|
||||
"prisma": "^4.9.0",
|
||||
"tailwindcss": "^2.2.19"
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "^4.9.0",
|
||||
"bcryptjs": "^2.4.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
46
examples/todos/prisma/schema.prisma
Normal file
46
examples/todos/prisma/schema.prisma
Normal file
@ -0,0 +1,46 @@
|
||||
// datasource db {
|
||||
// provider = "sqlite"
|
||||
// url = env("DATABASE_URL")
|
||||
// }
|
||||
|
||||
// generator client {
|
||||
// provider = "prisma-client-js"
|
||||
// }
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
binaryTargets = ["native", "rhel-openssl-1.0.x"]
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(uuid())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
email String @unique(map: "User.email_unique")
|
||||
sessions Session[]
|
||||
todos Todo[]
|
||||
}
|
||||
|
||||
model Session {
|
||||
id String @id @default(uuid())
|
||||
createdAt DateTime @default(now())
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
userId String
|
||||
expirationDate DateTime
|
||||
}
|
||||
|
||||
model Todo {
|
||||
id String @id @default(cuid())
|
||||
title String
|
||||
complete Boolean
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: Cascade)
|
||||
userId String
|
||||
}
|
Loading…
Reference in New Issue
Block a user