mirror of
https://github.com/ryan-haskell/elm-spa.git
synced 2024-11-22 03:12:01 +03:00
tweak auth api
This commit is contained in:
parent
79546c51bf
commit
fffcad03f1
5
examples/04-demo/.gitignore
vendored
Normal file
5
examples/04-demo/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.DS_Store
|
||||
.elm-spa
|
||||
elm-stuff
|
||||
node_modules
|
||||
dist
|
28
examples/04-demo/README.md
Normal file
28
examples/04-demo/README.md
Normal file
@ -0,0 +1,28 @@
|
||||
# my new project
|
||||
> 🌳 built with [elm-spa](https://elm-spa.dev)
|
||||
|
||||
## dependencies
|
||||
|
||||
This project requires the latest LTS version of [Node.js](https://nodejs.org/)
|
||||
|
||||
```bash
|
||||
npm install -g elm elm-spa
|
||||
```
|
||||
|
||||
## running locally
|
||||
|
||||
```bash
|
||||
elm-spa server # starts this app at http:/localhost:1234
|
||||
```
|
||||
|
||||
### other commands
|
||||
|
||||
```bash
|
||||
elm-spa add # add a new page to the application
|
||||
elm-spa build # production build
|
||||
elm-spa watch # runs build as you code (without the server)
|
||||
```
|
||||
|
||||
## learn more
|
||||
|
||||
You can learn more at [elm-spa.dev](https://elm-spa.dev)
|
27
examples/04-demo/elm.json
Normal file
27
examples/04-demo/elm.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"type": "application",
|
||||
"source-directories": [
|
||||
"src",
|
||||
".elm-spa/defaults",
|
||||
".elm-spa/generated"
|
||||
],
|
||||
"elm-version": "0.19.1",
|
||||
"dependencies": {
|
||||
"direct": {
|
||||
"elm/browser": "1.0.2",
|
||||
"elm/core": "1.0.5",
|
||||
"elm/html": "1.0.0",
|
||||
"elm/json": "1.1.3",
|
||||
"elm/url": "1.0.0",
|
||||
"ryannhg/elm-spa": "5.2.0"
|
||||
},
|
||||
"indirect": {
|
||||
"elm/time": "1.0.0",
|
||||
"elm/virtual-dom": "1.0.2"
|
||||
}
|
||||
},
|
||||
"test-dependencies": {
|
||||
"direct": {},
|
||||
"indirect": {}
|
||||
}
|
||||
}
|
11
examples/04-demo/public/index.html
Normal file
11
examples/04-demo/public/index.html
Normal file
@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
</head>
|
||||
<body>
|
||||
<script src="/dist/elm.js"></script>
|
||||
<script> Elm.Main.init() </script>
|
||||
</body>
|
||||
</html>
|
30
examples/04-demo/src/Auth.elm
Normal file
30
examples/04-demo/src/Auth.elm
Normal file
@ -0,0 +1,30 @@
|
||||
module Auth exposing
|
||||
( User
|
||||
, beforeProtectedInit
|
||||
)
|
||||
|
||||
{-|
|
||||
|
||||
@docs User
|
||||
@docs beforeProtectedInit
|
||||
|
||||
-}
|
||||
|
||||
import ElmSpa.Internals.Page as ElmSpa
|
||||
import Gen.Route exposing (Route)
|
||||
import Request exposing (Request)
|
||||
import Shared
|
||||
|
||||
|
||||
type alias User =
|
||||
Shared.User
|
||||
|
||||
|
||||
beforeProtectedInit : Shared.Model -> Request -> ElmSpa.Protected User Route
|
||||
beforeProtectedInit shared req =
|
||||
case shared.user of
|
||||
Just user ->
|
||||
ElmSpa.Provide user
|
||||
|
||||
Nothing ->
|
||||
ElmSpa.RedirectTo Gen.Route.SignIn
|
59
examples/04-demo/src/Pages/Home_.elm
Normal file
59
examples/04-demo/src/Pages/Home_.elm
Normal file
@ -0,0 +1,59 @@
|
||||
module Pages.Home_ exposing (Model, Msg, page, view)
|
||||
|
||||
import Auth
|
||||
import Effect exposing (Effect)
|
||||
import Html
|
||||
import Page
|
||||
import Request exposing (Request)
|
||||
import Shared
|
||||
import View exposing (View)
|
||||
|
||||
|
||||
page : Shared.Model -> Request -> Page.With Model Msg
|
||||
page _ _ =
|
||||
Page.protected.advanced
|
||||
{ init = always init
|
||||
, update = always update
|
||||
, view = view
|
||||
, subscriptions = \_ _ -> Sub.none
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- INIT
|
||||
|
||||
|
||||
type alias Model =
|
||||
{}
|
||||
|
||||
|
||||
init : ( Model, Effect Msg )
|
||||
init =
|
||||
( {}, Effect.none )
|
||||
|
||||
|
||||
|
||||
-- UPDATE
|
||||
|
||||
|
||||
type Msg
|
||||
= ClickedSignOut
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Effect Msg )
|
||||
update msg model =
|
||||
case msg of
|
||||
ClickedSignOut ->
|
||||
( model
|
||||
, Effect.fromShared Shared.SignedOut
|
||||
)
|
||||
|
||||
|
||||
view : Auth.User -> Model -> View msg
|
||||
view user _ =
|
||||
{ title = "Homepage"
|
||||
, body =
|
||||
[ Html.h1 [] [ Html.text ("Hello, " ++ user.name ++ "!") ]
|
||||
, Html.button [] [ Html.text "Sign out" ]
|
||||
]
|
||||
}
|
93
examples/04-demo/src/Pages/SignIn.elm
Normal file
93
examples/04-demo/src/Pages/SignIn.elm
Normal file
@ -0,0 +1,93 @@
|
||||
module Pages.SignIn exposing (Model, Msg, page)
|
||||
|
||||
import Effect exposing (Effect)
|
||||
import Gen.Params.SignIn exposing (Params)
|
||||
import Html
|
||||
import Html.Attributes as Attr
|
||||
import Html.Events as Events
|
||||
import Page
|
||||
import Request
|
||||
import Shared
|
||||
import View exposing (View)
|
||||
|
||||
|
||||
page : Shared.Model -> Request.With Params -> Page.With Model Msg
|
||||
page shared req =
|
||||
Page.advanced
|
||||
{ init = init
|
||||
, update = update
|
||||
, view = view
|
||||
, subscriptions = subscriptions
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- INIT
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ name : String }
|
||||
|
||||
|
||||
init : ( Model, Effect Msg )
|
||||
init =
|
||||
( { name = "" }
|
||||
, Effect.none
|
||||
)
|
||||
|
||||
|
||||
|
||||
-- UPDATE
|
||||
|
||||
|
||||
type Msg
|
||||
= UpdatedName String
|
||||
| SubmittedSignInForm
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Effect Msg )
|
||||
update msg model =
|
||||
case msg of
|
||||
UpdatedName name ->
|
||||
( { model | name = name }
|
||||
, Effect.none
|
||||
)
|
||||
|
||||
SubmittedSignInForm ->
|
||||
( model
|
||||
, Effect.fromShared (Shared.SignedIn model.name)
|
||||
)
|
||||
|
||||
|
||||
|
||||
-- SUBSCRIPTIONS
|
||||
|
||||
|
||||
subscriptions : Model -> Sub Msg
|
||||
subscriptions model =
|
||||
Sub.none
|
||||
|
||||
|
||||
|
||||
-- VIEW
|
||||
|
||||
|
||||
view : Model -> View Msg
|
||||
view model =
|
||||
{ title = "Sign in"
|
||||
, body =
|
||||
[ Html.form [ Events.onSubmit SubmittedSignInForm ]
|
||||
[ Html.label []
|
||||
[ Html.span [] [ Html.text "Name" ]
|
||||
, Html.input
|
||||
[ Attr.type_ "text"
|
||||
, Attr.value model.name
|
||||
, Events.onInput UpdatedName
|
||||
]
|
||||
[]
|
||||
]
|
||||
, Html.button [ Attr.disabled (String.isEmpty model.name) ]
|
||||
[ Html.text "Sign in" ]
|
||||
]
|
||||
]
|
||||
}
|
66
examples/04-demo/src/Shared.elm
Normal file
66
examples/04-demo/src/Shared.elm
Normal file
@ -0,0 +1,66 @@
|
||||
module Shared exposing
|
||||
( Flags
|
||||
, Model
|
||||
, Msg(..)
|
||||
, User
|
||||
, init
|
||||
, subscriptions
|
||||
, update
|
||||
)
|
||||
|
||||
import Gen.Route
|
||||
import Json.Decode as Json
|
||||
import Request exposing (Request)
|
||||
|
||||
|
||||
type alias User =
|
||||
{ name : String
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- INIT
|
||||
|
||||
|
||||
type alias Flags =
|
||||
Json.Value
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ user : Maybe User
|
||||
}
|
||||
|
||||
|
||||
init : Request -> Flags -> ( Model, Cmd Msg )
|
||||
init _ _ =
|
||||
( { user = Nothing }
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
|
||||
|
||||
-- UPDATE
|
||||
|
||||
|
||||
type Msg
|
||||
= SignedIn String
|
||||
| SignedOut
|
||||
|
||||
|
||||
update : Request -> Msg -> Model -> ( Model, Cmd Msg )
|
||||
update req msg model =
|
||||
case msg of
|
||||
SignedIn name ->
|
||||
( { model | user = Just { name = name } }
|
||||
, Request.pushRoute Gen.Route.Home_ req
|
||||
)
|
||||
|
||||
SignedOut ->
|
||||
( { model | user = Nothing }
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
|
||||
subscriptions : Request -> Model -> Sub Msg
|
||||
subscriptions _ _ =
|
||||
Sub.none
|
2
src/cli/package-lock.json
generated
2
src/cli/package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "elm-spa",
|
||||
"version": "6.0.8--beta",
|
||||
"version": "6.0.9--beta",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "elm-spa",
|
||||
"version": "6.0.8--beta",
|
||||
"version": "6.0.9--beta",
|
||||
"description": "single page apps made easy",
|
||||
"bin": "dist/src/index.js",
|
||||
"scripts": {
|
||||
|
@ -4,6 +4,8 @@ import config from '../config'
|
||||
import * as File from '../file'
|
||||
import RouteTemplate from '../templates/routes'
|
||||
import PagesTemplate from '../templates/pages'
|
||||
import PageTemplate from '../templates/page'
|
||||
import RequestTemplate from '../templates/request'
|
||||
import ModelTemplate from '../templates/model'
|
||||
import MsgTemplate from '../templates/msg'
|
||||
import ParamsTemplate from '../templates/params'
|
||||
@ -114,6 +116,9 @@ const createGeneratedFiles = async () => {
|
||||
|
||||
const filesToCreate = [
|
||||
...paramFiles,
|
||||
{ filepath: [ 'Page' ], contents: PageTemplate() },
|
||||
{ filepath: [ 'Request' ], contents: RequestTemplate() },
|
||||
{ filepath: [ 'Gen', 'Route' ], contents: RouteTemplate(segments, options(kindForPage)) },
|
||||
{ filepath: [ 'Gen', 'Route' ], contents: RouteTemplate(segments, options(kindForPage)) },
|
||||
{ filepath: [ 'Gen', 'Pages' ], contents: PagesTemplate(segments, options(kindForPage)) },
|
||||
{ filepath: [ 'Gen', 'Model' ], contents: ModelTemplate(segments, options(kindForPage)) },
|
||||
|
@ -36,12 +36,11 @@ const config = {
|
||||
terser: `npx terser`
|
||||
},
|
||||
defaults: [
|
||||
[ 'Auth.elm' ],
|
||||
[ 'Effect.elm' ],
|
||||
[ 'Main.elm' ],
|
||||
[ 'Shared.elm' ],
|
||||
[ `Pages`, `${reserved.notFound}.elm` ],
|
||||
[ 'Page.elm' ],
|
||||
[ 'Request.elm' ],
|
||||
[ 'View.elm' ]
|
||||
]
|
||||
}
|
||||
|
39
src/cli/src/defaults/Auth.elm
Normal file
39
src/cli/src/defaults/Auth.elm
Normal file
@ -0,0 +1,39 @@
|
||||
module Auth exposing
|
||||
( User
|
||||
, beforeProtectedInit
|
||||
)
|
||||
|
||||
{-|
|
||||
|
||||
@docs User
|
||||
@docs beforeProtectedInit
|
||||
|
||||
-}
|
||||
|
||||
import ElmSpa.Internals.Page as ElmSpa
|
||||
import Gen.Route exposing (Route)
|
||||
import Request exposing (Request)
|
||||
import Shared
|
||||
|
||||
|
||||
{-| Replace the "()" with your actual User type
|
||||
-}
|
||||
type alias User =
|
||||
()
|
||||
|
||||
|
||||
{-| This function will run before any `protected` pages.
|
||||
|
||||
Here, you can provide logic on where to redirect if a user is not signed in. Here's an example:
|
||||
|
||||
case shared.user of
|
||||
Just user ->
|
||||
ElmSpa.Provide user
|
||||
|
||||
Nothing ->
|
||||
ElmSpa.RedirectTo Gen.Route.SignIn
|
||||
|
||||
-}
|
||||
beforeProtectedInit : Shared.Model -> Request -> ElmSpa.Protected User Route
|
||||
beforeProtectedInit shared req =
|
||||
ElmSpa.RedirectTo Gen.Route.NotFound
|
@ -1,3 +1,4 @@
|
||||
export default (): string => `
|
||||
module Page exposing
|
||||
( Page, With
|
||||
, static, sandbox, element, advanced
|
||||
@ -12,6 +13,7 @@ module Page exposing
|
||||
|
||||
-}
|
||||
|
||||
import Auth exposing (User)
|
||||
import Effect exposing (Effect)
|
||||
import ElmSpa.Internals.Page as ElmSpa
|
||||
import Gen.Route exposing (Route)
|
||||
@ -76,29 +78,6 @@ advanced =
|
||||
-- PROTECTED PAGES
|
||||
|
||||
|
||||
{-| Replace "()" with your actual User type
|
||||
-}
|
||||
type alias User =
|
||||
()
|
||||
|
||||
|
||||
{-| This function will run before any `protected` pages.
|
||||
|
||||
Here, you can provide logic on where to redirect if a user is not signed in. Here's an example:
|
||||
|
||||
case shared.user of
|
||||
Just user ->
|
||||
ElmSpa.Provide user
|
||||
|
||||
Nothing ->
|
||||
ElmSpa.RedirectTo Gen.Route.SignIn
|
||||
|
||||
-}
|
||||
beforeProtectedInit : Shared.Model -> Request -> ElmSpa.Protected User Route
|
||||
beforeProtectedInit shared req =
|
||||
ElmSpa.RedirectTo Gen.Route.NotFound
|
||||
|
||||
|
||||
protected :
|
||||
{ static :
|
||||
{ view : User -> View msg
|
||||
@ -129,5 +108,7 @@ protected =
|
||||
ElmSpa.protected2
|
||||
{ effectNone = Effect.none
|
||||
, fromCmd = Effect.fromCmd
|
||||
, beforeInit = beforeProtectedInit
|
||||
, beforeInit = Auth.beforeProtectedInit
|
||||
}
|
||||
|
||||
`.trimLeft()
|
@ -1,3 +1,4 @@
|
||||
export default (): string => `
|
||||
module Request exposing
|
||||
( Request, With
|
||||
, create
|
||||
@ -39,3 +40,5 @@ pushRoute route req =
|
||||
replaceRoute : Route -> With params -> Cmd msg
|
||||
replaceRoute route req =
|
||||
Browser.Navigation.replaceUrl req.key (Route.toHref route)
|
||||
|
||||
`.trimLeft()
|
Loading…
Reference in New Issue
Block a user