├── .gitignore
├── README.md
├── examples
├── fractal-architecture
│ ├── README.md
│ ├── elm.json
│ ├── index.html
│ └── src
│ │ ├── App
│ │ ├── Counter
│ │ │ ├── Messages.elm
│ │ │ ├── Model.elm
│ │ │ ├── Subscriptions.elm
│ │ │ ├── Update.elm
│ │ │ └── View.elm
│ │ ├── Messages.elm
│ │ ├── Model.elm
│ │ ├── Subscriptions.elm
│ │ ├── Update.elm
│ │ └── View.elm
│ │ ├── Main.elm
│ │ └── Utils.elm
├── generic-update
│ ├── Main.elm
│ ├── README.md
│ └── elm.json
├── http-get
│ ├── Main.elm
│ ├── README.md
│ └── elm.json
├── http-json-server
│ ├── README.md
│ ├── data.json
│ ├── elm.json
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ └── index.html
│ └── src
│ │ ├── Main.elm
│ │ ├── favicon.ico
│ │ ├── index.js
│ │ ├── main.css
│ │ └── registerServiceWorker.js
├── key-combinations
│ ├── Main.elm
│ ├── README.md
│ └── elm.json
├── module-composition-tagger
│ ├── Form.elm
│ ├── Form
│ │ └── Field.elm
│ ├── Main.elm
│ ├── README.md
│ └── elm.json
├── module-composition
│ ├── Helper.elm
│ ├── Input.elm
│ ├── Main.elm
│ ├── README.md
│ └── elm.json
├── ports
│ ├── Main.elm
│ ├── README.md
│ ├── elm.json
│ ├── index.html
│ └── index.js
├── random-initial-seed
│ ├── elm.json
│ └── src
│ │ └── Main.elm
├── random-user-seed
│ ├── Main.elm
│ ├── README.md
│ └── elm.json
└── select2-integration
│ ├── .gitignore
│ ├── README.md
│ ├── elm.json
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo.svg
│ └── manifest.json
│ └── src
│ ├── App.elm
│ ├── Main.elm
│ ├── favicon.ico
│ ├── index.js
│ ├── main.css
│ └── registerServiceWorker.js
├── package.json
└── tasks
└── publish.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### JetBrains template
3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
4 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
5 |
6 | # User-specific stuff:
7 | .idea/workspace.xml
8 | .idea/tasks.xml
9 | .idea/dictionaries
10 | .idea/vcs.xml
11 | .idea/jsLibraryMappings.xml
12 |
13 | # Sensitive or high-churn files:
14 | .idea/dataSources.ids
15 | .idea/dataSources.xml
16 | .idea/dataSources.local.xml
17 | .idea/sqlDataSources.xml
18 | .idea/dynamic.xml
19 | .idea/uiDesigner.xml
20 |
21 | # Gradle:
22 | .idea/gradle.xml
23 | .idea/libraries
24 |
25 | # Mongo Explorer plugin:
26 | .idea/mongoSettings.xml
27 |
28 | ## File-based project format:
29 | *.iws
30 |
31 | ## Plugin-specific files:
32 |
33 | # IntelliJ
34 | /out/
35 |
36 | # mpeltonen/sbt-idea plugin
37 | .idea_modules/
38 |
39 | # JIRA plugin
40 | atlassian-ide-plugin.xml
41 |
42 | # Crashlytics plugin (for Android Studio and IntelliJ)
43 | com_crashlytics_export_strings.xml
44 | crashlytics.properties
45 | crashlytics-build.properties
46 | fabric.properties
47 | ### Elm template
48 | # elm-package generated files
49 | elm-stuff/
50 | # elm-repl generated files
51 | repl-temp-*
52 | ### Node template
53 | # Logs
54 | logs
55 | *.log
56 | npm-debug.log*
57 |
58 | # Runtime data
59 | pids
60 | *.pid
61 | *.seed
62 |
63 | # Directory for instrumented libs generated by jscoverage/JSCover
64 | lib-cov
65 |
66 | # Coverage directory used by tools like istanbul
67 | coverage
68 |
69 | # nyc test coverage
70 | .nyc_output
71 |
72 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
73 | .grunt
74 |
75 | # node-waf configuration
76 | .lock-wscript
77 |
78 | # Compiled binary addons (http://nodejs.org/api/addons.html)
79 | build/Release
80 |
81 | # Dependency directories
82 | node_modules
83 | jspm_packages
84 |
85 | # Optional npm cache directory
86 | .npm
87 |
88 | # Optional REPL history
89 | .node_repl_history
90 |
91 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Practical examples in Elm
2 |
3 | A collection of examples with advanced techniques for real-world Elm apps.
4 |
5 | *Note:*
6 | Most of these examples haven't been updated for some time. They do not represent the sate-of-art code, but rather a general idea on how you might tackle different problems.
7 |
8 | ## Examples
9 |
10 | - [Elm Fractal Architecture](examples/fractal-architecture)
11 | - [HTTP GET with Elm](examples/http-get)
12 | - [Key combinations with Subscription](examples/key-combinations)
13 | - [Generic update function](examples/generic-update)
14 | - [Module composition in Elm](examples/module-composition)
15 | - [Module composition in Elm with tagger function](examples/module-composition-tagger)
16 | - [JavaScript interop with Elm](examples/ports)
17 | - [Random value with user-specified seed](examples/random-user-seed)
18 | - [Select2 integration into Elm application](examples/select2-integration)
19 | - [Elm SPA using Create Elm App](https://github.com/halfzebra/elm-spa-example)
20 |
21 | ## I want more examples
22 |
23 | Check-out the collection of curated examples at [Awesome Elm - Examples](https://github.com/isRuslan/awesome-elm#examples).
24 |
25 | ## I need help
26 |
27 | Hit me on Twitter with ideas or requests for new examples [@eduardkyvenko](https://twitter.com/eduardkyvenko)
28 |
29 | Don't be a stranger, stop by at [Elm Slack](https://elmlang.slack.com/)!
30 |
--------------------------------------------------------------------------------
/examples/fractal-architecture/README.md:
--------------------------------------------------------------------------------
1 | # Elm Fractal Architecture example
2 |
3 | An example of Elm project organisation with a self-resembling architecture.
4 |
5 | Compose View, Update, Message, Model, Subscriptions and Commands with Fractal Architecture.
6 |
7 | Features:
8 | - Module splitting
9 | - Usage of `Browser.element`
10 | - Module composition
11 | - [Subscription batching](src/App/Subscriptions.elm) for subscribing to `Keyboard` messages from child modules
12 |
13 | ## Building the example
14 |
15 | Since this example features `Browser.element` usage, it is impossible to build it with `elm reactor`.
16 |
17 | You have to explicitly specify the `--output=index.js`
18 |
19 | ```sh
20 | $ elm make src/Main.elm --output=index.js
21 | ```
22 |
--------------------------------------------------------------------------------
/examples/fractal-architecture/elm.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "application",
3 | "source-directories": [
4 | "src/"
5 | ],
6 | "elm-version": "0.19.0",
7 | "dependencies": {
8 | "direct": {
9 | "elm/browser": "1.0.0",
10 | "elm/core": "1.0.0",
11 | "elm/html": "1.0.0",
12 | "elm/json": "1.0.0"
13 | },
14 | "indirect": {
15 | "elm/time": "1.0.0",
16 | "elm/url": "1.0.0",
17 | "elm/virtual-dom": "1.0.0"
18 | }
19 | },
20 | "test-dependencies": {
21 | "direct": {},
22 | "indirect": {}
23 | }
24 | }
--------------------------------------------------------------------------------
/examples/fractal-architecture/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Title
6 |
7 |
8 |
9 |
10 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/examples/fractal-architecture/src/App/Counter/Messages.elm:
--------------------------------------------------------------------------------
1 | module App.Counter.Messages exposing (Msg(..))
2 |
3 |
4 | type Msg
5 | = Up
6 | | Down
7 | | Keydown String
8 |
--------------------------------------------------------------------------------
/examples/fractal-architecture/src/App/Counter/Model.elm:
--------------------------------------------------------------------------------
1 | module App.Counter.Model exposing (Model, init)
2 |
3 |
4 | type alias Model =
5 | Int
6 |
7 |
8 | init : Int -> Model
9 | init start =
10 | start
11 |
--------------------------------------------------------------------------------
/examples/fractal-architecture/src/App/Counter/Subscriptions.elm:
--------------------------------------------------------------------------------
1 | module App.Counter.Subscriptions exposing (subscriptions)
2 |
3 | import App.Counter.Messages exposing (..)
4 | import App.Counter.Model exposing (..)
5 | import Browser.Events as Events
6 | import Json.Decode as Decode
7 |
8 |
9 | subscriptions : Model -> Sub Msg
10 | subscriptions model =
11 | Events.onKeyDown (Decode.map Keydown keyDecoder)
12 |
13 |
14 | keyDecoder : Decode.Decoder String
15 | keyDecoder =
16 | Decode.field "key" Decode.string
17 |
--------------------------------------------------------------------------------
/examples/fractal-architecture/src/App/Counter/Update.elm:
--------------------------------------------------------------------------------
1 | module App.Counter.Update exposing (update)
2 |
3 | import App.Counter.Messages exposing (..)
4 | import App.Counter.Model exposing (..)
5 |
6 |
7 | update : Msg -> Model -> ( Model, Cmd Msg )
8 | update msg model =
9 | case msg of
10 | Up ->
11 | ( model + 1, Cmd.none )
12 |
13 | Down ->
14 | ( model - 1, Cmd.none )
15 |
16 | Keydown code ->
17 | case code of
18 | "ArrowUp" ->
19 | update Up model
20 |
21 | "ArrowDown" ->
22 | update Down model
23 |
24 | _ ->
25 | ( model, Cmd.none )
26 |
--------------------------------------------------------------------------------
/examples/fractal-architecture/src/App/Counter/View.elm:
--------------------------------------------------------------------------------
1 | module App.Counter.View exposing (view)
2 |
3 | import App.Counter.Messages exposing (..)
4 | import App.Counter.Model exposing (..)
5 | import Debug
6 | import Html exposing (Html, button, div, text)
7 | import Html.Events exposing (onClick)
8 |
9 |
10 | view : Model -> Html Msg
11 | view model =
12 | div
13 | []
14 | [ button [ onClick Up ] [ text "+" ]
15 | , text (Debug.toString model)
16 | , button [ onClick Down ] [ text "-" ]
17 | ]
18 |
--------------------------------------------------------------------------------
/examples/fractal-architecture/src/App/Messages.elm:
--------------------------------------------------------------------------------
1 | module App.Messages exposing (Msg(..))
2 |
3 | import App.Counter.Messages
4 |
5 |
6 | type Msg
7 | = NoOp
8 | | CounterMsg App.Counter.Messages.Msg
9 |
--------------------------------------------------------------------------------
/examples/fractal-architecture/src/App/Model.elm:
--------------------------------------------------------------------------------
1 | module App.Model exposing (Flags, Model, init)
2 |
3 | import App.Counter.Model
4 | import App.Messages exposing (Msg)
5 |
6 |
7 | type alias Model =
8 | { dev : Bool
9 | , counter : App.Counter.Model.Model
10 | }
11 |
12 |
13 | {-| We can use abstract type if it is constructed with Elm's primitive values.
14 | -}
15 | type alias Flags =
16 | { dev : Bool
17 | , counter : Int
18 | }
19 |
20 |
21 | init : Flags -> ( Model, Cmd Msg )
22 | init flags =
23 | let
24 | { dev, counter } =
25 | flags
26 | in
27 | ( Model dev counter, Cmd.none )
28 |
--------------------------------------------------------------------------------
/examples/fractal-architecture/src/App/Subscriptions.elm:
--------------------------------------------------------------------------------
1 | module App.Subscriptions exposing (subscriptions)
2 |
3 | import App.Counter.Subscriptions
4 | import App.Messages exposing (..)
5 | import App.Model exposing (Model)
6 |
7 |
8 | {-| This is how you can organize subscribtions from child modules.
9 | -}
10 | subscriptions : Model -> Sub Msg
11 | subscriptions model =
12 | let
13 | counterSub =
14 | App.Counter.Subscriptions.subscriptions model.counter
15 | in
16 | Sub.batch [ Sub.map CounterMsg counterSub ]
17 |
--------------------------------------------------------------------------------
/examples/fractal-architecture/src/App/Update.elm:
--------------------------------------------------------------------------------
1 | module App.Update exposing (update)
2 |
3 | import App.Counter.Messages
4 | import App.Counter.Update
5 | import App.Messages exposing (..)
6 | import App.Model exposing (Model)
7 | import Utils exposing (log)
8 |
9 |
10 | update : Msg -> Model -> ( Model, Cmd Msg )
11 | update msg model =
12 | let
13 | logMsg =
14 | log model.dev "MESSAGE: "
15 | in
16 | case logMsg msg of
17 | NoOp ->
18 | ( model, Cmd.none )
19 |
20 | CounterMsg counterMsg ->
21 | let
22 | ( counterModel, counterCmd ) =
23 | App.Counter.Update.update counterMsg model.counter
24 | in
25 | ( { model | counter = counterModel }
26 | , Cmd.map CounterMsg counterCmd
27 | )
28 |
--------------------------------------------------------------------------------
/examples/fractal-architecture/src/App/View.elm:
--------------------------------------------------------------------------------
1 | module App.View exposing (view)
2 |
3 | import App.Counter.View
4 | import App.Messages exposing (..)
5 | import App.Model exposing (Model)
6 | import Html exposing (Html, div, text)
7 |
8 |
9 | view : Model -> Html Msg
10 | view model =
11 | div []
12 | [ text "Try pressing up & down arrow keys on keyboard"
13 | , Html.map CounterMsg (App.Counter.View.view model.counter)
14 | ]
15 |
--------------------------------------------------------------------------------
/examples/fractal-architecture/src/Main.elm:
--------------------------------------------------------------------------------
1 | module Main exposing (main)
2 |
3 | import App.Messages exposing (Msg)
4 | import App.Model exposing (Flags, Model, init)
5 | import App.Subscriptions exposing (subscriptions)
6 | import App.Update exposing (update)
7 | import App.View exposing (view)
8 | import Browser
9 |
10 |
11 | main : Program Flags Model Msg
12 | main =
13 | Browser.element
14 | { init = init
15 | , update = update
16 | , view = view
17 | , subscriptions = subscriptions
18 | }
19 |
--------------------------------------------------------------------------------
/examples/fractal-architecture/src/Utils.elm:
--------------------------------------------------------------------------------
1 | module Utils exposing (log)
2 |
3 |
4 | log : Bool -> String -> a -> a
5 | log dev label val =
6 | if dev == True then
7 | Debug.log label val
8 |
9 | else
10 | val
11 |
--------------------------------------------------------------------------------
/examples/generic-update/Main.elm:
--------------------------------------------------------------------------------
1 | module Main exposing (Checkbox, Model, Msg(..), init, main, update, view)
2 |
3 | import Browser
4 | import Dict exposing (Dict)
5 | import Html exposing (Html, div, input, label, text)
6 | import Html.Attributes exposing (checked, type_)
7 | import Html.Events exposing (onCheck)
8 |
9 |
10 | main : Program () Model Msg
11 | main =
12 | Browser.sandbox { init = init, view = view, update = update }
13 |
14 |
15 |
16 | -- MODEL
17 |
18 |
19 | type alias Checkbox =
20 | { name : String
21 | , checked : Bool
22 | }
23 |
24 |
25 | type alias Model =
26 | { name : String
27 | , checkboxes : Dict String Checkbox
28 | }
29 |
30 |
31 | init : Model
32 | init =
33 | { name = ""
34 | , checkboxes =
35 | -- We store the the state for modules in a Dictionary
36 | Dict.fromList
37 | [ ( "advertising"
38 | , { name = "Advertising"
39 | , checked = False
40 | }
41 | )
42 | , ( "travel"
43 | , { name = "Travel"
44 | , checked = False
45 | }
46 | )
47 | , ( "utilities"
48 | , { name = "Utilities"
49 | , checked = False
50 | }
51 | )
52 | ]
53 | }
54 |
55 |
56 |
57 | -- UPDATE
58 |
59 |
60 | type Msg
61 | = Check String Bool
62 |
63 |
64 | update msg model =
65 | case msg of
66 | Check checkboxId checked ->
67 | let
68 | updateRecord =
69 | Maybe.map (\checkboxData -> { checkboxData | checked = checked })
70 |
71 | {- Update a single value inside of a dictionary,
72 | using updateRecord function.
73 |
74 | Since we don't know if value with a key checkboxId
75 | is present in the Dictionary,
76 | the updateRecord function is applied to a Maybe value.
77 | -}
78 | checkboxesUpdated =
79 | Dict.update checkboxId
80 | updateRecord
81 | model.checkboxes
82 | in
83 | { model | checkboxes = checkboxesUpdated }
84 |
85 |
86 |
87 | -- VIEW
88 |
89 |
90 | view : Model -> Html Msg
91 | view model =
92 | let
93 | checkbox ( key, data ) =
94 | label []
95 | [ text data.name
96 | , input
97 | [ type_ "checkbox"
98 | , checked data.checked
99 |
100 | -- Pass the key for accesing the state as a Message payload.
101 | , onCheck (Check key)
102 | ]
103 | []
104 | ]
105 | in
106 | div []
107 | (model.checkboxes
108 | |> Dict.toList
109 | |> List.map checkbox
110 | )
111 |
--------------------------------------------------------------------------------
/examples/generic-update/README.md:
--------------------------------------------------------------------------------
1 | # Generic update function
2 |
3 | This example shows, how `update` function of any module might be simplified by using Dictionaries instead of Records.
4 |
5 | This approach is useful, when having many instances of child modules in application.
6 |
7 | ## Building the example
8 |
9 | ```sh
10 | $ elm make Main.elm
11 | ```
12 |
--------------------------------------------------------------------------------
/examples/generic-update/elm.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "application",
3 | "source-directories": [
4 | "."
5 | ],
6 | "elm-version": "0.19.0",
7 | "dependencies": {
8 | "direct": {
9 | "elm/browser": "1.0.0",
10 | "elm/core": "1.0.0",
11 | "elm/html": "1.0.0"
12 | },
13 | "indirect": {
14 | "elm/json": "1.0.0",
15 | "elm/time": "1.0.0",
16 | "elm/url": "1.0.0",
17 | "elm/virtual-dom": "1.0.0"
18 | }
19 | },
20 | "test-dependencies": {
21 | "direct": {},
22 | "indirect": {}
23 | }
24 | }
--------------------------------------------------------------------------------
/examples/http-get/Main.elm:
--------------------------------------------------------------------------------
1 | module Main exposing (Model, Msg(..), Repo, decoder, getRepos, init, main, repoDecoder, sendGet, subscriptions, update, url, view)
2 |
3 | import Browser
4 | import Debug
5 | import Html exposing (Html, button, div, input, p, text)
6 | import Html.Attributes exposing (value)
7 | import Html.Events exposing (onClick, onInput)
8 | import Http exposing (Error(..), Response, get)
9 | import Json.Decode exposing (Decoder, field, int, string)
10 | import Task
11 | import Url.Builder as Url
12 |
13 |
14 | main : Program () Model Msg
15 | main =
16 | Browser.element
17 | { view = view
18 | , init = \() -> init
19 | , update = update
20 | , subscriptions = subscriptions
21 | }
22 |
23 |
24 | subscriptions : Model -> Sub Msg
25 | subscriptions model =
26 | Sub.none
27 |
28 |
29 | type alias Repo =
30 | { id : Int
31 | , full_name : String
32 | }
33 |
34 |
35 | type alias Model =
36 | { query : String
37 | , repos : List Repo
38 | , error : Maybe Error
39 | }
40 |
41 |
42 | init : ( Model, Cmd Msg )
43 | init =
44 | ( Model "evancz" [] Nothing, Cmd.none )
45 |
46 |
47 | decoder : Decoder (List Repo)
48 | decoder =
49 | Json.Decode.list repoDecoder
50 |
51 |
52 | repoDecoder : Decoder Repo
53 | repoDecoder =
54 | Json.Decode.map2 Repo
55 | (field "id" int)
56 | (field "full_name" string)
57 |
58 |
59 | url : String -> String
60 | url query =
61 | Url.crossOrigin "https://api.github.com" [ "users", query, "repos" ] []
62 |
63 |
64 | getRepos : String -> Cmd Msg
65 | getRepos query =
66 | sendGet LoadRepos (url query) decoder
67 |
68 |
69 | type Msg
70 | = UpdateQuery String
71 | | Search
72 | | LoadRepos (Result Http.Error (List Repo))
73 |
74 |
75 | update : Msg -> Model -> ( Model, Cmd Msg )
76 | update msg model =
77 | case msg of
78 | UpdateQuery value ->
79 | ( { model | query = value }, Cmd.none )
80 |
81 | Search ->
82 | ( model, getRepos model.query )
83 |
84 | LoadRepos maybeRepos ->
85 | case maybeRepos of
86 | Ok repos ->
87 | ( { model | repos = repos }, Cmd.none )
88 |
89 | Err err ->
90 | ( { model | repos = [], error = Just err }, Cmd.none )
91 |
92 |
93 | sendGet : (Result Error a -> msg) -> String -> Decoder a -> Cmd msg
94 | sendGet msg theUrl theDecoder =
95 | Http.get theUrl theDecoder
96 | |> Http.send msg
97 |
98 |
99 | view : Model -> Html Msg
100 | view model =
101 | div []
102 | [ input
103 | [ onInput UpdateQuery, value model.query ]
104 | []
105 | , button [ onClick Search ] [ text "Search" ]
106 | , div
107 | []
108 | (List.map (\{ full_name } -> p [] [ text full_name ]) model.repos)
109 | , text
110 | (case model.error of
111 | Nothing ->
112 | ""
113 |
114 | Just error ->
115 | "Error: " ++ Debug.toString error
116 | )
117 | ]
118 |
--------------------------------------------------------------------------------
/examples/http-get/README.md:
--------------------------------------------------------------------------------
1 | # HTTP GET with Elm
2 |
3 | Small example app, which uses public GitHub API
4 | to [List user repositories](https://developer.github.com/v3/repos/#list-user-repositories) by username.
5 |
6 | ## Building the example
7 |
8 | ```sh
9 | $ elm make Main.elm
10 |
11 | or alternatively
12 |
13 | $ elm reactor
14 | ```
15 |
--------------------------------------------------------------------------------
/examples/http-get/elm.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "application",
3 | "source-directories": [
4 | "."
5 | ],
6 | "elm-version": "0.19.0",
7 | "dependencies": {
8 | "direct": {
9 | "elm/browser": "1.0.0",
10 | "elm/core": "1.0.0",
11 | "elm/html": "1.0.0",
12 | "elm/http": "1.0.0",
13 | "elm/json": "1.0.0",
14 | "elm/url": "1.0.0"
15 | },
16 | "indirect": {
17 | "elm/time": "1.0.0",
18 | "elm/virtual-dom": "1.0.0"
19 | }
20 | },
21 | "test-dependencies": {
22 | "direct": {},
23 | "indirect": {}
24 | }
25 | }
--------------------------------------------------------------------------------
/examples/http-json-server/README.md:
--------------------------------------------------------------------------------
1 | # Http with json-server
2 |
3 | ## Running locally
4 |
5 | ```bash
6 | npm i
7 | npm run serve-json
8 | elm-app start
9 | ```
10 |
11 | This project is bootstrapped with [Create Elm App.](https://github.com/halfzebra/create-elm-app)
--------------------------------------------------------------------------------
/examples/http-json-server/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "content": "Hello!"
4 | }
5 | }
--------------------------------------------------------------------------------
/examples/http-json-server/elm.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "application",
3 | "source-directories": [
4 | ".",
5 | "src/"
6 | ],
7 | "elm-version": "0.19.0",
8 | "dependencies": {
9 | "direct": {
10 | "elm/browser": "1.0.0",
11 | "elm/core": "1.0.0",
12 | "elm/html": "1.0.0",
13 | "elm/http": "1.0.0",
14 | "elm/json": "1.0.0"
15 | },
16 | "indirect": {
17 | "elm/time": "1.0.0",
18 | "elm/url": "1.0.0",
19 | "elm/virtual-dom": "1.0.0"
20 | }
21 | },
22 | "test-dependencies": {
23 | "direct": {},
24 | "indirect": {}
25 | }
26 | }
--------------------------------------------------------------------------------
/examples/http-json-server/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "http-json-server",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "accepts": {
8 | "version": "1.3.5",
9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
10 | "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
11 | "requires": {
12 | "mime-types": "~2.1.18",
13 | "negotiator": "0.6.1"
14 | }
15 | },
16 | "ajv": {
17 | "version": "5.5.2",
18 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
19 | "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
20 | "requires": {
21 | "co": "^4.6.0",
22 | "fast-deep-equal": "^1.0.0",
23 | "fast-json-stable-stringify": "^2.0.0",
24 | "json-schema-traverse": "^0.3.0"
25 | }
26 | },
27 | "ansi-align": {
28 | "version": "2.0.0",
29 | "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz",
30 | "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=",
31 | "requires": {
32 | "string-width": "^2.0.0"
33 | }
34 | },
35 | "ansi-regex": {
36 | "version": "3.0.0",
37 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
38 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
39 | },
40 | "ansi-styles": {
41 | "version": "3.2.1",
42 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
43 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
44 | "requires": {
45 | "color-convert": "^1.9.0"
46 | }
47 | },
48 | "array-flatten": {
49 | "version": "1.1.1",
50 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
51 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
52 | },
53 | "asn1": {
54 | "version": "0.2.4",
55 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
56 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
57 | "requires": {
58 | "safer-buffer": "~2.1.0"
59 | }
60 | },
61 | "assert-plus": {
62 | "version": "1.0.0",
63 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
64 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
65 | },
66 | "asynckit": {
67 | "version": "0.4.0",
68 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
69 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
70 | },
71 | "aws-sign2": {
72 | "version": "0.7.0",
73 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
74 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
75 | },
76 | "aws4": {
77 | "version": "1.8.0",
78 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
79 | "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
80 | },
81 | "basic-auth": {
82 | "version": "2.0.0",
83 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.0.tgz",
84 | "integrity": "sha1-AV2z81PgLlY3d1X5YnQuiYHnu7o=",
85 | "requires": {
86 | "safe-buffer": "5.1.1"
87 | },
88 | "dependencies": {
89 | "safe-buffer": {
90 | "version": "5.1.1",
91 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
92 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
93 | }
94 | }
95 | },
96 | "bcrypt-pbkdf": {
97 | "version": "1.0.2",
98 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
99 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
100 | "optional": true,
101 | "requires": {
102 | "tweetnacl": "^0.14.3"
103 | }
104 | },
105 | "body-parser": {
106 | "version": "1.18.3",
107 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
108 | "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
109 | "requires": {
110 | "bytes": "3.0.0",
111 | "content-type": "~1.0.4",
112 | "debug": "2.6.9",
113 | "depd": "~1.1.2",
114 | "http-errors": "~1.6.3",
115 | "iconv-lite": "0.4.23",
116 | "on-finished": "~2.3.0",
117 | "qs": "6.5.2",
118 | "raw-body": "2.3.3",
119 | "type-is": "~1.6.16"
120 | }
121 | },
122 | "boxen": {
123 | "version": "1.3.0",
124 | "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz",
125 | "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==",
126 | "requires": {
127 | "ansi-align": "^2.0.0",
128 | "camelcase": "^4.0.0",
129 | "chalk": "^2.0.1",
130 | "cli-boxes": "^1.0.0",
131 | "string-width": "^2.0.0",
132 | "term-size": "^1.2.0",
133 | "widest-line": "^2.0.0"
134 | }
135 | },
136 | "bytes": {
137 | "version": "3.0.0",
138 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
139 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
140 | },
141 | "camelcase": {
142 | "version": "4.1.0",
143 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
144 | "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
145 | },
146 | "capture-stack-trace": {
147 | "version": "1.0.1",
148 | "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz",
149 | "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw=="
150 | },
151 | "caseless": {
152 | "version": "0.12.0",
153 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
154 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
155 | },
156 | "chalk": {
157 | "version": "2.4.1",
158 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
159 | "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
160 | "requires": {
161 | "ansi-styles": "^3.2.1",
162 | "escape-string-regexp": "^1.0.5",
163 | "supports-color": "^5.3.0"
164 | }
165 | },
166 | "ci-info": {
167 | "version": "1.5.1",
168 | "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.5.1.tgz",
169 | "integrity": "sha512-fKFIKXaYiL1exImwJ0AhR/6jxFPSKQBk2ayV5NiNoruUs2+rxC2kNw0EG+1Z9dugZRdCrppskQ8DN2cyaUM1Hw=="
170 | },
171 | "cli-boxes": {
172 | "version": "1.0.0",
173 | "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
174 | "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM="
175 | },
176 | "cliui": {
177 | "version": "4.1.0",
178 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
179 | "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
180 | "requires": {
181 | "string-width": "^2.1.1",
182 | "strip-ansi": "^4.0.0",
183 | "wrap-ansi": "^2.0.0"
184 | }
185 | },
186 | "co": {
187 | "version": "4.6.0",
188 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
189 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
190 | },
191 | "code-point-at": {
192 | "version": "1.1.0",
193 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
194 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
195 | },
196 | "color-convert": {
197 | "version": "1.9.3",
198 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
199 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
200 | "requires": {
201 | "color-name": "1.1.3"
202 | }
203 | },
204 | "color-name": {
205 | "version": "1.1.3",
206 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
207 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
208 | },
209 | "combined-stream": {
210 | "version": "1.0.7",
211 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
212 | "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
213 | "requires": {
214 | "delayed-stream": "~1.0.0"
215 | }
216 | },
217 | "compressible": {
218 | "version": "2.0.15",
219 | "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.15.tgz",
220 | "integrity": "sha512-4aE67DL33dSW9gw4CI2H/yTxqHLNcxp0yS6jB+4h+wr3e43+1z7vm0HU9qXOH8j+qjKuL8+UtkOxYQSMq60Ylw==",
221 | "requires": {
222 | "mime-db": ">= 1.36.0 < 2"
223 | }
224 | },
225 | "compression": {
226 | "version": "1.7.3",
227 | "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz",
228 | "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==",
229 | "requires": {
230 | "accepts": "~1.3.5",
231 | "bytes": "3.0.0",
232 | "compressible": "~2.0.14",
233 | "debug": "2.6.9",
234 | "on-headers": "~1.0.1",
235 | "safe-buffer": "5.1.2",
236 | "vary": "~1.1.2"
237 | }
238 | },
239 | "configstore": {
240 | "version": "3.1.2",
241 | "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz",
242 | "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==",
243 | "requires": {
244 | "dot-prop": "^4.1.0",
245 | "graceful-fs": "^4.1.2",
246 | "make-dir": "^1.0.0",
247 | "unique-string": "^1.0.0",
248 | "write-file-atomic": "^2.0.0",
249 | "xdg-basedir": "^3.0.0"
250 | }
251 | },
252 | "connect-pause": {
253 | "version": "0.1.1",
254 | "resolved": "https://registry.npmjs.org/connect-pause/-/connect-pause-0.1.1.tgz",
255 | "integrity": "sha1-smmyu4Ldsaw9tQmcD7WCq6mfs3o="
256 | },
257 | "content-disposition": {
258 | "version": "0.5.2",
259 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
260 | "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
261 | },
262 | "content-type": {
263 | "version": "1.0.4",
264 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
265 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
266 | },
267 | "cookie": {
268 | "version": "0.3.1",
269 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
270 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
271 | },
272 | "cookie-signature": {
273 | "version": "1.0.6",
274 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
275 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
276 | },
277 | "core-util-is": {
278 | "version": "1.0.2",
279 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
280 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
281 | },
282 | "cors": {
283 | "version": "2.8.4",
284 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz",
285 | "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=",
286 | "requires": {
287 | "object-assign": "^4",
288 | "vary": "^1"
289 | }
290 | },
291 | "create-error-class": {
292 | "version": "3.0.2",
293 | "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
294 | "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=",
295 | "requires": {
296 | "capture-stack-trace": "^1.0.0"
297 | }
298 | },
299 | "cross-spawn": {
300 | "version": "5.1.0",
301 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
302 | "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
303 | "requires": {
304 | "lru-cache": "^4.0.1",
305 | "shebang-command": "^1.2.0",
306 | "which": "^1.2.9"
307 | }
308 | },
309 | "crypto-random-string": {
310 | "version": "1.0.0",
311 | "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
312 | "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4="
313 | },
314 | "dashdash": {
315 | "version": "1.14.1",
316 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
317 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
318 | "requires": {
319 | "assert-plus": "^1.0.0"
320 | }
321 | },
322 | "debug": {
323 | "version": "2.6.9",
324 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
325 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
326 | "requires": {
327 | "ms": "2.0.0"
328 | }
329 | },
330 | "decamelize": {
331 | "version": "1.2.0",
332 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
333 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
334 | },
335 | "deep-extend": {
336 | "version": "0.6.0",
337 | "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
338 | "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
339 | },
340 | "delayed-stream": {
341 | "version": "1.0.0",
342 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
343 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
344 | },
345 | "depd": {
346 | "version": "1.1.2",
347 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
348 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
349 | },
350 | "destroy": {
351 | "version": "1.0.4",
352 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
353 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
354 | },
355 | "dot-prop": {
356 | "version": "4.2.0",
357 | "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
358 | "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
359 | "requires": {
360 | "is-obj": "^1.0.0"
361 | }
362 | },
363 | "duplexer3": {
364 | "version": "0.1.4",
365 | "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
366 | "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
367 | },
368 | "ecc-jsbn": {
369 | "version": "0.1.2",
370 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
371 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
372 | "optional": true,
373 | "requires": {
374 | "jsbn": "~0.1.0",
375 | "safer-buffer": "^2.1.0"
376 | }
377 | },
378 | "ee-first": {
379 | "version": "1.1.1",
380 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
381 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
382 | },
383 | "encodeurl": {
384 | "version": "1.0.2",
385 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
386 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
387 | },
388 | "errorhandler": {
389 | "version": "1.5.0",
390 | "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.0.tgz",
391 | "integrity": "sha1-6rpkyl1UKjEayUX1gt78M2Fl2fQ=",
392 | "requires": {
393 | "accepts": "~1.3.3",
394 | "escape-html": "~1.0.3"
395 | }
396 | },
397 | "escape-html": {
398 | "version": "1.0.3",
399 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
400 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
401 | },
402 | "escape-string-regexp": {
403 | "version": "1.0.5",
404 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
405 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
406 | },
407 | "etag": {
408 | "version": "1.8.1",
409 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
410 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
411 | },
412 | "execa": {
413 | "version": "0.7.0",
414 | "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
415 | "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
416 | "requires": {
417 | "cross-spawn": "^5.0.1",
418 | "get-stream": "^3.0.0",
419 | "is-stream": "^1.1.0",
420 | "npm-run-path": "^2.0.0",
421 | "p-finally": "^1.0.0",
422 | "signal-exit": "^3.0.0",
423 | "strip-eof": "^1.0.0"
424 | }
425 | },
426 | "express": {
427 | "version": "4.16.3",
428 | "resolved": "http://registry.npmjs.org/express/-/express-4.16.3.tgz",
429 | "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=",
430 | "requires": {
431 | "accepts": "~1.3.5",
432 | "array-flatten": "1.1.1",
433 | "body-parser": "1.18.2",
434 | "content-disposition": "0.5.2",
435 | "content-type": "~1.0.4",
436 | "cookie": "0.3.1",
437 | "cookie-signature": "1.0.6",
438 | "debug": "2.6.9",
439 | "depd": "~1.1.2",
440 | "encodeurl": "~1.0.2",
441 | "escape-html": "~1.0.3",
442 | "etag": "~1.8.1",
443 | "finalhandler": "1.1.1",
444 | "fresh": "0.5.2",
445 | "merge-descriptors": "1.0.1",
446 | "methods": "~1.1.2",
447 | "on-finished": "~2.3.0",
448 | "parseurl": "~1.3.2",
449 | "path-to-regexp": "0.1.7",
450 | "proxy-addr": "~2.0.3",
451 | "qs": "6.5.1",
452 | "range-parser": "~1.2.0",
453 | "safe-buffer": "5.1.1",
454 | "send": "0.16.2",
455 | "serve-static": "1.13.2",
456 | "setprototypeof": "1.1.0",
457 | "statuses": "~1.4.0",
458 | "type-is": "~1.6.16",
459 | "utils-merge": "1.0.1",
460 | "vary": "~1.1.2"
461 | },
462 | "dependencies": {
463 | "body-parser": {
464 | "version": "1.18.2",
465 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz",
466 | "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=",
467 | "requires": {
468 | "bytes": "3.0.0",
469 | "content-type": "~1.0.4",
470 | "debug": "2.6.9",
471 | "depd": "~1.1.1",
472 | "http-errors": "~1.6.2",
473 | "iconv-lite": "0.4.19",
474 | "on-finished": "~2.3.0",
475 | "qs": "6.5.1",
476 | "raw-body": "2.3.2",
477 | "type-is": "~1.6.15"
478 | }
479 | },
480 | "iconv-lite": {
481 | "version": "0.4.19",
482 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
483 | "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ=="
484 | },
485 | "qs": {
486 | "version": "6.5.1",
487 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
488 | "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A=="
489 | },
490 | "raw-body": {
491 | "version": "2.3.2",
492 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz",
493 | "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=",
494 | "requires": {
495 | "bytes": "3.0.0",
496 | "http-errors": "1.6.2",
497 | "iconv-lite": "0.4.19",
498 | "unpipe": "1.0.0"
499 | },
500 | "dependencies": {
501 | "depd": {
502 | "version": "1.1.1",
503 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
504 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k="
505 | },
506 | "http-errors": {
507 | "version": "1.6.2",
508 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
509 | "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=",
510 | "requires": {
511 | "depd": "1.1.1",
512 | "inherits": "2.0.3",
513 | "setprototypeof": "1.0.3",
514 | "statuses": ">= 1.3.1 < 2"
515 | }
516 | },
517 | "setprototypeof": {
518 | "version": "1.0.3",
519 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
520 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ="
521 | }
522 | }
523 | },
524 | "safe-buffer": {
525 | "version": "5.1.1",
526 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
527 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
528 | },
529 | "statuses": {
530 | "version": "1.4.0",
531 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
532 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
533 | }
534 | }
535 | },
536 | "express-urlrewrite": {
537 | "version": "1.2.0",
538 | "resolved": "https://registry.npmjs.org/express-urlrewrite/-/express-urlrewrite-1.2.0.tgz",
539 | "integrity": "sha1-jmZ7d2H/HH/9sO+gXWQDU4fII+s=",
540 | "requires": {
541 | "debug": "*",
542 | "path-to-regexp": "^1.0.3"
543 | },
544 | "dependencies": {
545 | "path-to-regexp": {
546 | "version": "1.7.0",
547 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz",
548 | "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=",
549 | "requires": {
550 | "isarray": "0.0.1"
551 | }
552 | }
553 | }
554 | },
555 | "extend": {
556 | "version": "3.0.2",
557 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
558 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
559 | },
560 | "extsprintf": {
561 | "version": "1.3.0",
562 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
563 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
564 | },
565 | "fast-deep-equal": {
566 | "version": "1.1.0",
567 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
568 | "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
569 | },
570 | "fast-json-stable-stringify": {
571 | "version": "2.0.0",
572 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
573 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
574 | },
575 | "finalhandler": {
576 | "version": "1.1.1",
577 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
578 | "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
579 | "requires": {
580 | "debug": "2.6.9",
581 | "encodeurl": "~1.0.2",
582 | "escape-html": "~1.0.3",
583 | "on-finished": "~2.3.0",
584 | "parseurl": "~1.3.2",
585 | "statuses": "~1.4.0",
586 | "unpipe": "~1.0.0"
587 | },
588 | "dependencies": {
589 | "statuses": {
590 | "version": "1.4.0",
591 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
592 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
593 | }
594 | }
595 | },
596 | "find-up": {
597 | "version": "2.1.0",
598 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
599 | "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
600 | "requires": {
601 | "locate-path": "^2.0.0"
602 | }
603 | },
604 | "forever-agent": {
605 | "version": "0.6.1",
606 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
607 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
608 | },
609 | "form-data": {
610 | "version": "2.3.2",
611 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
612 | "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
613 | "requires": {
614 | "asynckit": "^0.4.0",
615 | "combined-stream": "1.0.6",
616 | "mime-types": "^2.1.12"
617 | },
618 | "dependencies": {
619 | "combined-stream": {
620 | "version": "1.0.6",
621 | "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
622 | "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
623 | "requires": {
624 | "delayed-stream": "~1.0.0"
625 | }
626 | }
627 | }
628 | },
629 | "forwarded": {
630 | "version": "0.1.2",
631 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
632 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
633 | },
634 | "fresh": {
635 | "version": "0.5.2",
636 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
637 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
638 | },
639 | "get-caller-file": {
640 | "version": "1.0.3",
641 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
642 | "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w=="
643 | },
644 | "get-stream": {
645 | "version": "3.0.0",
646 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
647 | "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
648 | },
649 | "getpass": {
650 | "version": "0.1.7",
651 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
652 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
653 | "requires": {
654 | "assert-plus": "^1.0.0"
655 | }
656 | },
657 | "global-dirs": {
658 | "version": "0.1.1",
659 | "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
660 | "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=",
661 | "requires": {
662 | "ini": "^1.3.4"
663 | }
664 | },
665 | "got": {
666 | "version": "6.7.1",
667 | "resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz",
668 | "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
669 | "requires": {
670 | "create-error-class": "^3.0.0",
671 | "duplexer3": "^0.1.4",
672 | "get-stream": "^3.0.0",
673 | "is-redirect": "^1.0.0",
674 | "is-retry-allowed": "^1.0.0",
675 | "is-stream": "^1.0.0",
676 | "lowercase-keys": "^1.0.0",
677 | "safe-buffer": "^5.0.1",
678 | "timed-out": "^4.0.0",
679 | "unzip-response": "^2.0.1",
680 | "url-parse-lax": "^1.0.0"
681 | }
682 | },
683 | "graceful-fs": {
684 | "version": "4.1.11",
685 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
686 | "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
687 | },
688 | "har-schema": {
689 | "version": "2.0.0",
690 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
691 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
692 | },
693 | "har-validator": {
694 | "version": "5.1.0",
695 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz",
696 | "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==",
697 | "requires": {
698 | "ajv": "^5.3.0",
699 | "har-schema": "^2.0.0"
700 | }
701 | },
702 | "has-flag": {
703 | "version": "3.0.0",
704 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
705 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
706 | },
707 | "http-errors": {
708 | "version": "1.6.3",
709 | "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
710 | "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
711 | "requires": {
712 | "depd": "~1.1.2",
713 | "inherits": "2.0.3",
714 | "setprototypeof": "1.1.0",
715 | "statuses": ">= 1.4.0 < 2"
716 | }
717 | },
718 | "http-signature": {
719 | "version": "1.2.0",
720 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
721 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
722 | "requires": {
723 | "assert-plus": "^1.0.0",
724 | "jsprim": "^1.2.2",
725 | "sshpk": "^1.7.0"
726 | }
727 | },
728 | "iconv-lite": {
729 | "version": "0.4.23",
730 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
731 | "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
732 | "requires": {
733 | "safer-buffer": ">= 2.1.2 < 3"
734 | }
735 | },
736 | "import-lazy": {
737 | "version": "2.1.0",
738 | "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
739 | "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM="
740 | },
741 | "imurmurhash": {
742 | "version": "0.1.4",
743 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
744 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
745 | },
746 | "inherits": {
747 | "version": "2.0.3",
748 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
749 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
750 | },
751 | "ini": {
752 | "version": "1.3.5",
753 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
754 | "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
755 | },
756 | "invert-kv": {
757 | "version": "1.0.0",
758 | "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
759 | "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
760 | },
761 | "ipaddr.js": {
762 | "version": "1.8.0",
763 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz",
764 | "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4="
765 | },
766 | "is-ci": {
767 | "version": "1.2.1",
768 | "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
769 | "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
770 | "requires": {
771 | "ci-info": "^1.5.0"
772 | }
773 | },
774 | "is-fullwidth-code-point": {
775 | "version": "2.0.0",
776 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
777 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
778 | },
779 | "is-installed-globally": {
780 | "version": "0.1.0",
781 | "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz",
782 | "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=",
783 | "requires": {
784 | "global-dirs": "^0.1.0",
785 | "is-path-inside": "^1.0.0"
786 | }
787 | },
788 | "is-npm": {
789 | "version": "1.0.0",
790 | "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz",
791 | "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ="
792 | },
793 | "is-obj": {
794 | "version": "1.0.1",
795 | "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
796 | "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
797 | },
798 | "is-path-inside": {
799 | "version": "1.0.1",
800 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
801 | "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
802 | "requires": {
803 | "path-is-inside": "^1.0.1"
804 | }
805 | },
806 | "is-promise": {
807 | "version": "2.1.0",
808 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
809 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
810 | },
811 | "is-redirect": {
812 | "version": "1.0.0",
813 | "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
814 | "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ="
815 | },
816 | "is-retry-allowed": {
817 | "version": "1.1.0",
818 | "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz",
819 | "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ="
820 | },
821 | "is-stream": {
822 | "version": "1.1.0",
823 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
824 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
825 | },
826 | "is-typedarray": {
827 | "version": "1.0.0",
828 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
829 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
830 | },
831 | "isarray": {
832 | "version": "0.0.1",
833 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
834 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
835 | },
836 | "isexe": {
837 | "version": "2.0.0",
838 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
839 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
840 | },
841 | "isstream": {
842 | "version": "0.1.2",
843 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
844 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
845 | },
846 | "jju": {
847 | "version": "1.4.0",
848 | "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz",
849 | "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo="
850 | },
851 | "jsbn": {
852 | "version": "0.1.1",
853 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
854 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
855 | "optional": true
856 | },
857 | "json-parse-helpfulerror": {
858 | "version": "1.0.3",
859 | "resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz",
860 | "integrity": "sha1-E/FM4C7tTpgSl7ZOueO5MuLdE9w=",
861 | "requires": {
862 | "jju": "^1.1.0"
863 | }
864 | },
865 | "json-schema": {
866 | "version": "0.2.3",
867 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
868 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
869 | },
870 | "json-schema-traverse": {
871 | "version": "0.3.1",
872 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
873 | "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
874 | },
875 | "json-server": {
876 | "version": "0.14.0",
877 | "resolved": "https://registry.npmjs.org/json-server/-/json-server-0.14.0.tgz",
878 | "integrity": "sha512-8RVRAb1TO6LlCny6+8GC+sXDsESYv7gv7fSLdVANklVt866I416/7Z5fdqrtzSru92nyreddgavbEk8pjqcWoA==",
879 | "requires": {
880 | "body-parser": "^1.18.3",
881 | "chalk": "^2.4.1",
882 | "compression": "^1.7.2",
883 | "connect-pause": "^0.1.1",
884 | "cors": "^2.8.4",
885 | "errorhandler": "^1.2.0",
886 | "express": "^4.16.3",
887 | "express-urlrewrite": "^1.2.0",
888 | "json-parse-helpfulerror": "^1.0.3",
889 | "lodash": "^4.17.10",
890 | "lodash-id": "^0.14.0",
891 | "lowdb": "^0.15.0",
892 | "method-override": "^2.3.10",
893 | "morgan": "^1.9.0",
894 | "nanoid": "^1.0.2",
895 | "object-assign": "^4.0.1",
896 | "please-upgrade-node": "^3.0.2",
897 | "pluralize": "^7.0.0",
898 | "request": "^2.87.0",
899 | "server-destroy": "^1.0.1",
900 | "update-notifier": "^2.5.0",
901 | "yargs": "^10.1.2"
902 | }
903 | },
904 | "json-stringify-safe": {
905 | "version": "5.0.1",
906 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
907 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
908 | },
909 | "jsprim": {
910 | "version": "1.4.1",
911 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
912 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
913 | "requires": {
914 | "assert-plus": "1.0.0",
915 | "extsprintf": "1.3.0",
916 | "json-schema": "0.2.3",
917 | "verror": "1.10.0"
918 | }
919 | },
920 | "latest-version": {
921 | "version": "3.1.0",
922 | "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz",
923 | "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=",
924 | "requires": {
925 | "package-json": "^4.0.0"
926 | }
927 | },
928 | "lcid": {
929 | "version": "1.0.0",
930 | "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
931 | "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
932 | "requires": {
933 | "invert-kv": "^1.0.0"
934 | }
935 | },
936 | "locate-path": {
937 | "version": "2.0.0",
938 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
939 | "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
940 | "requires": {
941 | "p-locate": "^2.0.0",
942 | "path-exists": "^3.0.0"
943 | }
944 | },
945 | "lodash": {
946 | "version": "4.17.11",
947 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
948 | "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
949 | },
950 | "lodash-id": {
951 | "version": "0.14.0",
952 | "resolved": "https://registry.npmjs.org/lodash-id/-/lodash-id-0.14.0.tgz",
953 | "integrity": "sha1-uvSJNOVDobXWNG+MhGmLGoyAOJY="
954 | },
955 | "lowdb": {
956 | "version": "0.15.5",
957 | "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-0.15.5.tgz",
958 | "integrity": "sha1-mt4QXfiqVzaS0SIWIrhUFPv0+pY=",
959 | "requires": {
960 | "graceful-fs": "^4.1.3",
961 | "is-promise": "^2.1.0",
962 | "json-parse-helpfulerror": "^1.0.3",
963 | "lodash": "4",
964 | "steno": "^0.4.1"
965 | }
966 | },
967 | "lowercase-keys": {
968 | "version": "1.0.1",
969 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
970 | "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA=="
971 | },
972 | "lru-cache": {
973 | "version": "4.1.3",
974 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
975 | "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==",
976 | "requires": {
977 | "pseudomap": "^1.0.2",
978 | "yallist": "^2.1.2"
979 | }
980 | },
981 | "make-dir": {
982 | "version": "1.3.0",
983 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
984 | "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
985 | "requires": {
986 | "pify": "^3.0.0"
987 | }
988 | },
989 | "media-typer": {
990 | "version": "0.3.0",
991 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
992 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
993 | },
994 | "mem": {
995 | "version": "1.1.0",
996 | "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
997 | "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
998 | "requires": {
999 | "mimic-fn": "^1.0.0"
1000 | }
1001 | },
1002 | "merge-descriptors": {
1003 | "version": "1.0.1",
1004 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
1005 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
1006 | },
1007 | "method-override": {
1008 | "version": "2.3.10",
1009 | "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz",
1010 | "integrity": "sha1-49r41d7hDdLc59SuiNYrvud0drQ=",
1011 | "requires": {
1012 | "debug": "2.6.9",
1013 | "methods": "~1.1.2",
1014 | "parseurl": "~1.3.2",
1015 | "vary": "~1.1.2"
1016 | }
1017 | },
1018 | "methods": {
1019 | "version": "1.1.2",
1020 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
1021 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
1022 | },
1023 | "mime": {
1024 | "version": "1.4.1",
1025 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
1026 | "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ=="
1027 | },
1028 | "mime-db": {
1029 | "version": "1.36.0",
1030 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz",
1031 | "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw=="
1032 | },
1033 | "mime-types": {
1034 | "version": "2.1.20",
1035 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz",
1036 | "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==",
1037 | "requires": {
1038 | "mime-db": "~1.36.0"
1039 | }
1040 | },
1041 | "mimic-fn": {
1042 | "version": "1.2.0",
1043 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
1044 | "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="
1045 | },
1046 | "minimist": {
1047 | "version": "1.2.0",
1048 | "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
1049 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
1050 | },
1051 | "morgan": {
1052 | "version": "1.9.1",
1053 | "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz",
1054 | "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==",
1055 | "requires": {
1056 | "basic-auth": "~2.0.0",
1057 | "debug": "2.6.9",
1058 | "depd": "~1.1.2",
1059 | "on-finished": "~2.3.0",
1060 | "on-headers": "~1.0.1"
1061 | }
1062 | },
1063 | "ms": {
1064 | "version": "2.0.0",
1065 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
1066 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
1067 | },
1068 | "nanoid": {
1069 | "version": "1.2.3",
1070 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-1.2.3.tgz",
1071 | "integrity": "sha512-BAnxAdaihzMoszwhqRy8FPOX+dijs7esUEUYTIQ1KsOSKmCVNYnitAMmBDFxYzA6VQYvuUKw7o2K1AcMBTGzIg=="
1072 | },
1073 | "negotiator": {
1074 | "version": "0.6.1",
1075 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
1076 | "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
1077 | },
1078 | "npm-run-path": {
1079 | "version": "2.0.2",
1080 | "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
1081 | "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
1082 | "requires": {
1083 | "path-key": "^2.0.0"
1084 | }
1085 | },
1086 | "number-is-nan": {
1087 | "version": "1.0.1",
1088 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
1089 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
1090 | },
1091 | "oauth-sign": {
1092 | "version": "0.9.0",
1093 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
1094 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
1095 | },
1096 | "object-assign": {
1097 | "version": "4.1.1",
1098 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
1099 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
1100 | },
1101 | "on-finished": {
1102 | "version": "2.3.0",
1103 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
1104 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
1105 | "requires": {
1106 | "ee-first": "1.1.1"
1107 | }
1108 | },
1109 | "on-headers": {
1110 | "version": "1.0.1",
1111 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz",
1112 | "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c="
1113 | },
1114 | "os-locale": {
1115 | "version": "2.1.0",
1116 | "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
1117 | "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
1118 | "requires": {
1119 | "execa": "^0.7.0",
1120 | "lcid": "^1.0.0",
1121 | "mem": "^1.1.0"
1122 | }
1123 | },
1124 | "p-finally": {
1125 | "version": "1.0.0",
1126 | "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
1127 | "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
1128 | },
1129 | "p-limit": {
1130 | "version": "1.3.0",
1131 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
1132 | "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
1133 | "requires": {
1134 | "p-try": "^1.0.0"
1135 | }
1136 | },
1137 | "p-locate": {
1138 | "version": "2.0.0",
1139 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
1140 | "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
1141 | "requires": {
1142 | "p-limit": "^1.1.0"
1143 | }
1144 | },
1145 | "p-try": {
1146 | "version": "1.0.0",
1147 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
1148 | "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
1149 | },
1150 | "package-json": {
1151 | "version": "4.0.1",
1152 | "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz",
1153 | "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=",
1154 | "requires": {
1155 | "got": "^6.7.1",
1156 | "registry-auth-token": "^3.0.1",
1157 | "registry-url": "^3.0.3",
1158 | "semver": "^5.1.0"
1159 | }
1160 | },
1161 | "parseurl": {
1162 | "version": "1.3.2",
1163 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
1164 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
1165 | },
1166 | "path-exists": {
1167 | "version": "3.0.0",
1168 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
1169 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
1170 | },
1171 | "path-is-inside": {
1172 | "version": "1.0.2",
1173 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
1174 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM="
1175 | },
1176 | "path-key": {
1177 | "version": "2.0.1",
1178 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
1179 | "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
1180 | },
1181 | "path-to-regexp": {
1182 | "version": "0.1.7",
1183 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
1184 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
1185 | },
1186 | "performance-now": {
1187 | "version": "2.1.0",
1188 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
1189 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
1190 | },
1191 | "pify": {
1192 | "version": "3.0.0",
1193 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
1194 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
1195 | },
1196 | "please-upgrade-node": {
1197 | "version": "3.1.1",
1198 | "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz",
1199 | "integrity": "sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ==",
1200 | "requires": {
1201 | "semver-compare": "^1.0.0"
1202 | }
1203 | },
1204 | "pluralize": {
1205 | "version": "7.0.0",
1206 | "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
1207 | "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow=="
1208 | },
1209 | "prepend-http": {
1210 | "version": "1.0.4",
1211 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
1212 | "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
1213 | },
1214 | "proxy-addr": {
1215 | "version": "2.0.4",
1216 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
1217 | "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==",
1218 | "requires": {
1219 | "forwarded": "~0.1.2",
1220 | "ipaddr.js": "1.8.0"
1221 | }
1222 | },
1223 | "pseudomap": {
1224 | "version": "1.0.2",
1225 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
1226 | "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
1227 | },
1228 | "psl": {
1229 | "version": "1.1.29",
1230 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz",
1231 | "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ=="
1232 | },
1233 | "punycode": {
1234 | "version": "1.4.1",
1235 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
1236 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
1237 | },
1238 | "qs": {
1239 | "version": "6.5.2",
1240 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
1241 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
1242 | },
1243 | "range-parser": {
1244 | "version": "1.2.0",
1245 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
1246 | "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
1247 | },
1248 | "raw-body": {
1249 | "version": "2.3.3",
1250 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
1251 | "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
1252 | "requires": {
1253 | "bytes": "3.0.0",
1254 | "http-errors": "1.6.3",
1255 | "iconv-lite": "0.4.23",
1256 | "unpipe": "1.0.0"
1257 | }
1258 | },
1259 | "rc": {
1260 | "version": "1.2.8",
1261 | "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
1262 | "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
1263 | "requires": {
1264 | "deep-extend": "^0.6.0",
1265 | "ini": "~1.3.0",
1266 | "minimist": "^1.2.0",
1267 | "strip-json-comments": "~2.0.1"
1268 | }
1269 | },
1270 | "registry-auth-token": {
1271 | "version": "3.3.2",
1272 | "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz",
1273 | "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==",
1274 | "requires": {
1275 | "rc": "^1.1.6",
1276 | "safe-buffer": "^5.0.1"
1277 | }
1278 | },
1279 | "registry-url": {
1280 | "version": "3.1.0",
1281 | "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz",
1282 | "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=",
1283 | "requires": {
1284 | "rc": "^1.0.1"
1285 | }
1286 | },
1287 | "request": {
1288 | "version": "2.88.0",
1289 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
1290 | "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
1291 | "requires": {
1292 | "aws-sign2": "~0.7.0",
1293 | "aws4": "^1.8.0",
1294 | "caseless": "~0.12.0",
1295 | "combined-stream": "~1.0.6",
1296 | "extend": "~3.0.2",
1297 | "forever-agent": "~0.6.1",
1298 | "form-data": "~2.3.2",
1299 | "har-validator": "~5.1.0",
1300 | "http-signature": "~1.2.0",
1301 | "is-typedarray": "~1.0.0",
1302 | "isstream": "~0.1.2",
1303 | "json-stringify-safe": "~5.0.1",
1304 | "mime-types": "~2.1.19",
1305 | "oauth-sign": "~0.9.0",
1306 | "performance-now": "^2.1.0",
1307 | "qs": "~6.5.2",
1308 | "safe-buffer": "^5.1.2",
1309 | "tough-cookie": "~2.4.3",
1310 | "tunnel-agent": "^0.6.0",
1311 | "uuid": "^3.3.2"
1312 | }
1313 | },
1314 | "require-directory": {
1315 | "version": "2.1.1",
1316 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
1317 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
1318 | },
1319 | "require-main-filename": {
1320 | "version": "1.0.1",
1321 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
1322 | "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE="
1323 | },
1324 | "safe-buffer": {
1325 | "version": "5.1.2",
1326 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
1327 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
1328 | },
1329 | "safer-buffer": {
1330 | "version": "2.1.2",
1331 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
1332 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
1333 | },
1334 | "semver": {
1335 | "version": "5.5.1",
1336 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz",
1337 | "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw=="
1338 | },
1339 | "semver-compare": {
1340 | "version": "1.0.0",
1341 | "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
1342 | "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w="
1343 | },
1344 | "semver-diff": {
1345 | "version": "2.1.0",
1346 | "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz",
1347 | "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=",
1348 | "requires": {
1349 | "semver": "^5.0.3"
1350 | }
1351 | },
1352 | "send": {
1353 | "version": "0.16.2",
1354 | "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
1355 | "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
1356 | "requires": {
1357 | "debug": "2.6.9",
1358 | "depd": "~1.1.2",
1359 | "destroy": "~1.0.4",
1360 | "encodeurl": "~1.0.2",
1361 | "escape-html": "~1.0.3",
1362 | "etag": "~1.8.1",
1363 | "fresh": "0.5.2",
1364 | "http-errors": "~1.6.2",
1365 | "mime": "1.4.1",
1366 | "ms": "2.0.0",
1367 | "on-finished": "~2.3.0",
1368 | "range-parser": "~1.2.0",
1369 | "statuses": "~1.4.0"
1370 | },
1371 | "dependencies": {
1372 | "statuses": {
1373 | "version": "1.4.0",
1374 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
1375 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
1376 | }
1377 | }
1378 | },
1379 | "serve-static": {
1380 | "version": "1.13.2",
1381 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
1382 | "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
1383 | "requires": {
1384 | "encodeurl": "~1.0.2",
1385 | "escape-html": "~1.0.3",
1386 | "parseurl": "~1.3.2",
1387 | "send": "0.16.2"
1388 | }
1389 | },
1390 | "server-destroy": {
1391 | "version": "1.0.1",
1392 | "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz",
1393 | "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0="
1394 | },
1395 | "set-blocking": {
1396 | "version": "2.0.0",
1397 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
1398 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
1399 | },
1400 | "setprototypeof": {
1401 | "version": "1.1.0",
1402 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
1403 | "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
1404 | },
1405 | "shebang-command": {
1406 | "version": "1.2.0",
1407 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
1408 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
1409 | "requires": {
1410 | "shebang-regex": "^1.0.0"
1411 | }
1412 | },
1413 | "shebang-regex": {
1414 | "version": "1.0.0",
1415 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
1416 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
1417 | },
1418 | "signal-exit": {
1419 | "version": "3.0.2",
1420 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
1421 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
1422 | },
1423 | "sshpk": {
1424 | "version": "1.14.2",
1425 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
1426 | "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
1427 | "requires": {
1428 | "asn1": "~0.2.3",
1429 | "assert-plus": "^1.0.0",
1430 | "bcrypt-pbkdf": "^1.0.0",
1431 | "dashdash": "^1.12.0",
1432 | "ecc-jsbn": "~0.1.1",
1433 | "getpass": "^0.1.1",
1434 | "jsbn": "~0.1.0",
1435 | "safer-buffer": "^2.0.2",
1436 | "tweetnacl": "~0.14.0"
1437 | }
1438 | },
1439 | "statuses": {
1440 | "version": "1.5.0",
1441 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
1442 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
1443 | },
1444 | "steno": {
1445 | "version": "0.4.4",
1446 | "resolved": "https://registry.npmjs.org/steno/-/steno-0.4.4.tgz",
1447 | "integrity": "sha1-BxEFvfwobmYVwEA8J+nXtdy4Vcs=",
1448 | "requires": {
1449 | "graceful-fs": "^4.1.3"
1450 | }
1451 | },
1452 | "string-width": {
1453 | "version": "2.1.1",
1454 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
1455 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
1456 | "requires": {
1457 | "is-fullwidth-code-point": "^2.0.0",
1458 | "strip-ansi": "^4.0.0"
1459 | }
1460 | },
1461 | "strip-ansi": {
1462 | "version": "4.0.0",
1463 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
1464 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
1465 | "requires": {
1466 | "ansi-regex": "^3.0.0"
1467 | }
1468 | },
1469 | "strip-eof": {
1470 | "version": "1.0.0",
1471 | "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
1472 | "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
1473 | },
1474 | "strip-json-comments": {
1475 | "version": "2.0.1",
1476 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
1477 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
1478 | },
1479 | "supports-color": {
1480 | "version": "5.5.0",
1481 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
1482 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
1483 | "requires": {
1484 | "has-flag": "^3.0.0"
1485 | }
1486 | },
1487 | "term-size": {
1488 | "version": "1.2.0",
1489 | "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz",
1490 | "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=",
1491 | "requires": {
1492 | "execa": "^0.7.0"
1493 | }
1494 | },
1495 | "timed-out": {
1496 | "version": "4.0.1",
1497 | "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
1498 | "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8="
1499 | },
1500 | "tough-cookie": {
1501 | "version": "2.4.3",
1502 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
1503 | "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
1504 | "requires": {
1505 | "psl": "^1.1.24",
1506 | "punycode": "^1.4.1"
1507 | }
1508 | },
1509 | "tunnel-agent": {
1510 | "version": "0.6.0",
1511 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
1512 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
1513 | "requires": {
1514 | "safe-buffer": "^5.0.1"
1515 | }
1516 | },
1517 | "tweetnacl": {
1518 | "version": "0.14.5",
1519 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
1520 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
1521 | "optional": true
1522 | },
1523 | "type-is": {
1524 | "version": "1.6.16",
1525 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
1526 | "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
1527 | "requires": {
1528 | "media-typer": "0.3.0",
1529 | "mime-types": "~2.1.18"
1530 | }
1531 | },
1532 | "unique-string": {
1533 | "version": "1.0.0",
1534 | "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz",
1535 | "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=",
1536 | "requires": {
1537 | "crypto-random-string": "^1.0.0"
1538 | }
1539 | },
1540 | "unpipe": {
1541 | "version": "1.0.0",
1542 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
1543 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
1544 | },
1545 | "unzip-response": {
1546 | "version": "2.0.1",
1547 | "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz",
1548 | "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c="
1549 | },
1550 | "update-notifier": {
1551 | "version": "2.5.0",
1552 | "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz",
1553 | "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==",
1554 | "requires": {
1555 | "boxen": "^1.2.1",
1556 | "chalk": "^2.0.1",
1557 | "configstore": "^3.0.0",
1558 | "import-lazy": "^2.1.0",
1559 | "is-ci": "^1.0.10",
1560 | "is-installed-globally": "^0.1.0",
1561 | "is-npm": "^1.0.0",
1562 | "latest-version": "^3.0.0",
1563 | "semver-diff": "^2.0.0",
1564 | "xdg-basedir": "^3.0.0"
1565 | }
1566 | },
1567 | "url-parse-lax": {
1568 | "version": "1.0.0",
1569 | "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
1570 | "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=",
1571 | "requires": {
1572 | "prepend-http": "^1.0.1"
1573 | }
1574 | },
1575 | "utils-merge": {
1576 | "version": "1.0.1",
1577 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
1578 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
1579 | },
1580 | "uuid": {
1581 | "version": "3.3.2",
1582 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
1583 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
1584 | },
1585 | "vary": {
1586 | "version": "1.1.2",
1587 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
1588 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
1589 | },
1590 | "verror": {
1591 | "version": "1.10.0",
1592 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
1593 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
1594 | "requires": {
1595 | "assert-plus": "^1.0.0",
1596 | "core-util-is": "1.0.2",
1597 | "extsprintf": "^1.2.0"
1598 | }
1599 | },
1600 | "which": {
1601 | "version": "1.3.1",
1602 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
1603 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
1604 | "requires": {
1605 | "isexe": "^2.0.0"
1606 | }
1607 | },
1608 | "which-module": {
1609 | "version": "2.0.0",
1610 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
1611 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
1612 | },
1613 | "widest-line": {
1614 | "version": "2.0.0",
1615 | "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.0.tgz",
1616 | "integrity": "sha1-AUKk6KJD+IgsAjOqDgKBqnYVInM=",
1617 | "requires": {
1618 | "string-width": "^2.1.1"
1619 | }
1620 | },
1621 | "wrap-ansi": {
1622 | "version": "2.1.0",
1623 | "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
1624 | "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
1625 | "requires": {
1626 | "string-width": "^1.0.1",
1627 | "strip-ansi": "^3.0.1"
1628 | },
1629 | "dependencies": {
1630 | "ansi-regex": {
1631 | "version": "2.1.1",
1632 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
1633 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
1634 | },
1635 | "is-fullwidth-code-point": {
1636 | "version": "1.0.0",
1637 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
1638 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
1639 | "requires": {
1640 | "number-is-nan": "^1.0.0"
1641 | }
1642 | },
1643 | "string-width": {
1644 | "version": "1.0.2",
1645 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
1646 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
1647 | "requires": {
1648 | "code-point-at": "^1.0.0",
1649 | "is-fullwidth-code-point": "^1.0.0",
1650 | "strip-ansi": "^3.0.0"
1651 | }
1652 | },
1653 | "strip-ansi": {
1654 | "version": "3.0.1",
1655 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
1656 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
1657 | "requires": {
1658 | "ansi-regex": "^2.0.0"
1659 | }
1660 | }
1661 | }
1662 | },
1663 | "write-file-atomic": {
1664 | "version": "2.3.0",
1665 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz",
1666 | "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==",
1667 | "requires": {
1668 | "graceful-fs": "^4.1.11",
1669 | "imurmurhash": "^0.1.4",
1670 | "signal-exit": "^3.0.2"
1671 | }
1672 | },
1673 | "xdg-basedir": {
1674 | "version": "3.0.0",
1675 | "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz",
1676 | "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ="
1677 | },
1678 | "y18n": {
1679 | "version": "3.2.1",
1680 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
1681 | "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE="
1682 | },
1683 | "yallist": {
1684 | "version": "2.1.2",
1685 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
1686 | "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
1687 | },
1688 | "yargs": {
1689 | "version": "10.1.2",
1690 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.1.2.tgz",
1691 | "integrity": "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==",
1692 | "requires": {
1693 | "cliui": "^4.0.0",
1694 | "decamelize": "^1.1.1",
1695 | "find-up": "^2.1.0",
1696 | "get-caller-file": "^1.0.1",
1697 | "os-locale": "^2.0.0",
1698 | "require-directory": "^2.1.1",
1699 | "require-main-filename": "^1.0.1",
1700 | "set-blocking": "^2.0.0",
1701 | "string-width": "^2.0.0",
1702 | "which-module": "^2.0.0",
1703 | "y18n": "^3.2.1",
1704 | "yargs-parser": "^8.1.0"
1705 | }
1706 | },
1707 | "yargs-parser": {
1708 | "version": "8.1.0",
1709 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz",
1710 | "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==",
1711 | "requires": {
1712 | "camelcase": "^4.1.0"
1713 | }
1714 | }
1715 | }
1716 | }
1717 |
--------------------------------------------------------------------------------
/examples/http-json-server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "http-json-server",
3 | "version": "1.0.0",
4 | "description": "This project is bootstrapped with [Create Elm App](https://github.com/halfzebra/create-elm-app).",
5 | "main": "index.js",
6 | "directories": {
7 | "test": "tests"
8 | },
9 | "scripts": {
10 | "serve-json": "json-server data.json --port 3004"
11 | },
12 | "keywords": [],
13 | "author": "",
14 | "license": "ISC",
15 | "dependencies": {
16 | "json-server": "^0.14.0"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/examples/http-json-server/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/halfzebra/elm-examples/0b79ff2f79717553c9c9e2b7b4e44d78e97ccb9e/examples/http-json-server/public/favicon.ico
--------------------------------------------------------------------------------
/examples/http-json-server/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Elm App
9 |
10 |
11 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/examples/http-json-server/src/Main.elm:
--------------------------------------------------------------------------------
1 | module Main exposing (Data, Model, Msg(..), apiUrl, decoder, encoder, init, main, update, view)
2 |
3 | import Browser
4 | import Debug
5 | import Html exposing (Html, button, div, input, text)
6 | import Html.Events exposing (onClick, onInput)
7 | import Http exposing (Body, Error)
8 | import Json.Decode exposing (Decoder)
9 | import Json.Encode
10 |
11 |
12 |
13 | ---- MODEL ----
14 |
15 |
16 | type alias Data =
17 | { content : String }
18 |
19 |
20 | type alias Model =
21 | { data : Maybe Data
22 | , inputValue : String
23 | }
24 |
25 |
26 | init : ( Model, Cmd Msg )
27 | init =
28 | ( { data = Nothing, inputValue = "" }, Cmd.none )
29 |
30 |
31 |
32 | ---- UPDATE ----
33 |
34 |
35 | decoder : Decoder Data
36 | decoder =
37 | Json.Decode.map Data (Json.Decode.field "content" Json.Decode.string)
38 |
39 |
40 | encoder : String -> Body
41 | encoder inputValue =
42 | [ ( "content", Json.Encode.string inputValue ) ]
43 | |> Json.Encode.object
44 | |> Http.jsonBody
45 |
46 |
47 | type Msg
48 | = Send
49 | | Response (Result Error Data)
50 | | InputUpdate String
51 | | SendData
52 | | SendDataResponse (Result Error Data)
53 |
54 |
55 | apiUrl : String
56 | apiUrl =
57 | "http://localhost:3004/data"
58 |
59 |
60 | update : Msg -> Model -> ( Model, Cmd Msg )
61 | update msg model =
62 | case msg of
63 | Send ->
64 | ( model
65 | , Http.send Response (Http.get apiUrl decoder)
66 | )
67 |
68 | Response res ->
69 | case res of
70 | Ok data ->
71 | ( { model | data = Just data }, Cmd.none )
72 |
73 | Err err ->
74 | ( model, Cmd.none )
75 |
76 | InputUpdate value ->
77 | ( { model | inputValue = value }, Cmd.none )
78 |
79 | SendData ->
80 | ( model
81 | , Http.send Response
82 | (Http.post
83 | apiUrl
84 | (encoder model.inputValue)
85 | decoder
86 | )
87 | )
88 |
89 | SendDataResponse res ->
90 | case res of
91 | Ok data ->
92 | ( { model | data = Just data }, Cmd.none )
93 |
94 | Err err ->
95 | ( model, Cmd.none )
96 |
97 |
98 |
99 | ---- VIEW ----
100 |
101 |
102 | view : Model -> Html Msg
103 | view model =
104 | div []
105 | [ div [] [ text (Debug.toString model.data) ]
106 | , input [ onInput InputUpdate ] []
107 | , button [ onClick Send ] [ text "Get the data" ]
108 | , button [ onClick SendData ] [ text "Send data to server" ]
109 | ]
110 |
111 |
112 |
113 | ---- PROGRAM ----
114 |
115 |
116 | main : Program () Model Msg
117 | main =
118 | Browser.element
119 | { view = view
120 | , init = \() -> init
121 | , update = update
122 | , subscriptions = \_ -> Sub.none
123 | }
124 |
--------------------------------------------------------------------------------
/examples/http-json-server/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/halfzebra/elm-examples/0b79ff2f79717553c9c9e2b7b4e44d78e97ccb9e/examples/http-json-server/src/favicon.ico
--------------------------------------------------------------------------------
/examples/http-json-server/src/index.js:
--------------------------------------------------------------------------------
1 | import './main.css';
2 | import { Elm } from './Main.elm';
3 | import registerServiceWorker from './registerServiceWorker';
4 |
5 | Elm.Main.init({
6 | node: document.getElementById('root')
7 | });
8 |
9 | registerServiceWorker();
10 |
--------------------------------------------------------------------------------
/examples/http-json-server/src/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: 'Source Sans Pro', 'Trebuchet MS', 'Lucida Grande', 'Bitstream Vera Sans', 'Helvetica Neue', sans-serif;
3 | margin: 0;
4 | text-align: center;
5 | color: #293c4b;
6 | }
7 |
8 | h1 {
9 | font-size: 30px;
10 | }
11 |
12 | img {
13 | margin: 20px 0;
14 | max-width: 200px;
15 | }
16 |
--------------------------------------------------------------------------------
/examples/http-json-server/src/registerServiceWorker.js:
--------------------------------------------------------------------------------
1 | // In production, we register a service worker to serve assets from local cache.
2 |
3 | // This lets the app load faster on subsequent visits in production, and gives
4 | // it offline capabilities. However, it also means that developers (and users)
5 | // will only see deployed updates on the "N+1" visit to a page, since previously
6 | // cached resources are updated in the background.
7 |
8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
9 | // This link also includes instructions on opting out of this behavior.
10 |
11 | const isLocalhost = Boolean(
12 | window.location.hostname === 'localhost' ||
13 | // [::1] is the IPv6 localhost address.
14 | window.location.hostname === '[::1]' ||
15 | // 127.0.0.1/8 is considered localhost for IPv4.
16 | window.location.hostname.match(
17 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
18 | )
19 | );
20 |
21 | export default function register() {
22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
23 | // The URL constructor is available in all browsers that support SW.
24 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
25 | if (publicUrl.origin !== window.location.origin) {
26 | // Our service worker won't work if PUBLIC_URL is on a different origin
27 | // from what our page is served on. This might happen if a CDN is used to
28 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
29 | return;
30 | }
31 |
32 | window.addEventListener('load', () => {
33 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
34 |
35 | if (!isLocalhost) {
36 | // Is not local host. Just register service worker
37 | registerValidSW(swUrl);
38 | } else {
39 | // This is running on localhost. Lets check if a service worker still exists or not.
40 | checkValidServiceWorker(swUrl);
41 | }
42 | });
43 | }
44 | }
45 |
46 | function registerValidSW(swUrl) {
47 | navigator.serviceWorker
48 | .register(swUrl)
49 | .then(registration => {
50 | registration.onupdatefound = () => {
51 | const installingWorker = registration.installing;
52 | installingWorker.onstatechange = () => {
53 | if (installingWorker.state === 'installed') {
54 | if (navigator.serviceWorker.controller) {
55 | // At this point, the old content will have been purged and
56 | // the fresh content will have been added to the cache.
57 | // It's the perfect time to display a "New content is
58 | // available; please refresh." message in your web app.
59 | console.log('New content is available; please refresh.');
60 | } else {
61 | // At this point, everything has been precached.
62 | // It's the perfect time to display a
63 | // "Content is cached for offline use." message.
64 | console.log('Content is cached for offline use.');
65 | }
66 | }
67 | };
68 | };
69 | })
70 | .catch(error => {
71 | console.error('Error during service worker registration:', error);
72 | });
73 | }
74 |
75 | function checkValidServiceWorker(swUrl) {
76 | // Check if the service worker can be found. If it can't reload the page.
77 | fetch(swUrl)
78 | .then(response => {
79 | // Ensure service worker exists, and that we really are getting a JS file.
80 | if (
81 | response.status === 404 ||
82 | response.headers.get('content-type').indexOf('javascript') === -1
83 | ) {
84 | // No service worker found. Probably a different app. Reload the page.
85 | navigator.serviceWorker.ready.then(registration => {
86 | registration.unregister().then(() => {
87 | window.location.reload();
88 | });
89 | });
90 | } else {
91 | // Service worker found. Proceed as normal.
92 | registerValidSW(swUrl);
93 | }
94 | })
95 | .catch(() => {
96 | console.log(
97 | 'No internet connection found. App is running in offline mode.'
98 | );
99 | });
100 | }
101 |
102 | export function unregister() {
103 | if ('serviceWorker' in navigator) {
104 | navigator.serviceWorker.ready.then(registration => {
105 | registration.unregister();
106 | });
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/examples/key-combinations/Main.elm:
--------------------------------------------------------------------------------
1 | module Main exposing (Model, Msg(..), init, main, subscriptions, update, view)
2 |
3 | import Browser
4 | import Browser.Events as Events
5 | import Debug
6 | import Html exposing (Html, text)
7 | import Json.Decode as Decode
8 |
9 |
10 | main : Program () Model Msg
11 | main =
12 | Browser.element
13 | { view = view
14 | , init = \() -> init
15 | , subscriptions = subscriptions
16 | , update = update
17 | }
18 |
19 |
20 |
21 | -- See https://github.com/elm/browser/blob/1.0.0/notes/keyboard.md
22 |
23 |
24 | type alias Model =
25 | List String
26 |
27 |
28 | type Msg
29 | = KeyDowns String
30 | | ClearPressed
31 |
32 |
33 | init : ( Model, Cmd Msg )
34 | init =
35 | ( [], Cmd.none )
36 |
37 |
38 | update : Msg -> Model -> ( Model, Cmd Msg )
39 | update msg model =
40 | case msg of
41 | KeyDowns code ->
42 | ( if List.member code model then
43 | model
44 |
45 | else
46 | code :: model
47 | , Cmd.none
48 | )
49 |
50 | -- Flush the whole model on `keyup`, helps to remove not pressed keys, if focus was lost from the window.
51 | ClearPressed ->
52 | ( [], Cmd.none )
53 |
54 |
55 | view : Model -> Html Msg
56 | view model =
57 | text (Debug.toString model)
58 |
59 |
60 | subscriptions : Model -> Sub Msg
61 | subscriptions model =
62 | Sub.batch
63 | [ Events.onKeyDown (Decode.map KeyDowns keyDecoder)
64 | , Events.onKeyUp (Decode.succeed ClearPressed)
65 | ]
66 |
67 |
68 | keyDecoder : Decode.Decoder String
69 | keyDecoder =
70 | Decode.field "key" Decode.string
71 |
--------------------------------------------------------------------------------
/examples/key-combinations/README.md:
--------------------------------------------------------------------------------
1 | # Key combinations with Subscription
2 |
3 | Example with a Subscription setup for tracking pressed key combinations on keybard.
4 |
5 | ## Building the example
6 |
7 | ```sh
8 | $ elm make Main.elm
9 | ```
10 |
--------------------------------------------------------------------------------
/examples/key-combinations/elm.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "application",
3 | "source-directories": [
4 | "."
5 | ],
6 | "elm-version": "0.19.0",
7 | "dependencies": {
8 | "direct": {
9 | "elm/browser": "1.0.0",
10 | "elm/core": "1.0.0",
11 | "elm/html": "1.0.0",
12 | "elm/json": "1.0.0"
13 | },
14 | "indirect": {
15 | "elm/time": "1.0.0",
16 | "elm/url": "1.0.0",
17 | "elm/virtual-dom": "1.0.0"
18 | }
19 | },
20 | "test-dependencies": {
21 | "direct": {},
22 | "indirect": {}
23 | }
24 | }
--------------------------------------------------------------------------------
/examples/module-composition-tagger/Form.elm:
--------------------------------------------------------------------------------
1 | module Form exposing (Model, Msg(..), fieldDictionary, fieldMessageTagger, init, update, view)
2 |
3 | import Form.Field
4 | import Html exposing (Html, text)
5 |
6 |
7 |
8 | -- MODEL
9 |
10 |
11 | type alias Model =
12 | { field : Form.Field.Model
13 | , isSubmitted : Bool
14 | }
15 |
16 |
17 | init : Model
18 | init =
19 | { field = ""
20 | , isSubmitted = False
21 | }
22 |
23 |
24 |
25 | -- Translator wiring for parent module.
26 | -- Define a Record with a shape of a Dictionary from Form.Field
27 |
28 |
29 | fieldDictionary : Form.Field.Dictionary Msg
30 | fieldDictionary =
31 | { onInternalMessage = FieldMsg
32 | , onOutcomingMessageSubmit = Submit
33 | }
34 |
35 |
36 | {-| Partially apply Form.Field.translator function
37 | to carry message mappings from fieldDictionary Record
38 | -}
39 | fieldMessageTagger : Form.Field.Tagger Msg
40 | fieldMessageTagger =
41 | Form.Field.tagger fieldDictionary
42 |
43 |
44 | type Msg
45 | = FieldMsg Form.Field.Internal
46 | | Submit
47 |
48 |
49 | update : Msg -> Model -> Model
50 | update msg model =
51 | case msg of
52 | -- Run update routine for child module as usual.
53 | FieldMsg inMsg ->
54 | { model | field = Form.Field.update inMsg model.field }
55 |
56 | Submit ->
57 | { model | isSubmitted = True }
58 |
59 |
60 | view : Model -> Html Msg
61 | view model =
62 | if model.isSubmitted == False then
63 | Html.map fieldMessageTagger (Form.Field.view model.field)
64 |
65 | else
66 | text
67 | """
68 | Congratulations!
69 | You have succesxfully submitted the form,
70 | written in Elm using tagger.
71 | """
72 |
--------------------------------------------------------------------------------
/examples/module-composition-tagger/Form/Field.elm:
--------------------------------------------------------------------------------
1 | module Form.Field exposing (Dictionary, Internal(..), Model, Msg(..), Outcoming(..), Tagger, tagger, update, view)
2 |
3 | import Html exposing (Html, button, div, input, text)
4 | import Html.Attributes exposing (value)
5 | import Html.Events exposing (onClick, onInput)
6 |
7 |
8 | type alias Model =
9 | String
10 |
11 |
12 | type Internal
13 | = Update String
14 |
15 |
16 | type Outcoming
17 | = Submit
18 |
19 |
20 | type Msg
21 | = InMsg Internal
22 | | OutMsg Outcoming
23 |
24 |
25 | type alias Dictionary parentMsg =
26 | { onInternalMessage : Internal -> parentMsg
27 | , onOutcomingMessageSubmit : parentMsg
28 | }
29 |
30 |
31 | type alias Tagger parentMsg =
32 | Msg -> parentMsg
33 |
34 |
35 | tagger : Dictionary parentMsg -> Tagger parentMsg
36 | tagger { onInternalMessage, onOutcomingMessageSubmit } msg =
37 | case msg of
38 | InMsg internal ->
39 | onInternalMessage internal
40 |
41 | OutMsg Submit ->
42 | onOutcomingMessageSubmit
43 |
44 |
45 | update : Internal -> Model -> Model
46 | update msg model =
47 | case msg of
48 | Update val ->
49 | val
50 |
51 |
52 | view : Model -> Html Msg
53 | view model =
54 | div []
55 | [ input [ onInput (InMsg << Update), value model ] []
56 | , button [ onClick (OutMsg Submit) ] [ text "Submit" ]
57 | ]
58 |
--------------------------------------------------------------------------------
/examples/module-composition-tagger/Main.elm:
--------------------------------------------------------------------------------
1 | module Main exposing (main)
2 |
3 | import Browser
4 | import Form exposing (Model, Msg, init, update, view)
5 |
6 |
7 | main : Program () Model Msg
8 | main =
9 | Browser.sandbox { view = view, update = update, init = init }
10 |
--------------------------------------------------------------------------------
/examples/module-composition-tagger/README.md:
--------------------------------------------------------------------------------
1 | # Module composition in Elm with tagger function
2 |
3 | Example app, featuring the usage of tagger function for message mapping in view composition.
4 |
5 | The term is originated from official docs, where a function with type signature of `a -> msg` is defined as [tagger](http://package.elm-lang.org/packages/elm-lang/html/1.1.0/Html-Events#targetValue)
6 |
7 | It is also often referred as [Translator](https://medium.com/@alex.lew/the-translator-pattern-a-model-for-child-to-parent-communication-in-elm-f4bfaa1d3f98) pattern.
8 |
9 | ## Motivation
10 | The key takeaway of this example is that you can use the second argument of [Html.App.map](http://package.elm-lang.org/packages/elm-lang/html/1.1.0/Html-App#map) to have more control over the message flow in your top-level `update` function.
11 |
12 | The idea, introduced in the article, improves on `tagger` formula and might be used as an inspiration for generic APIs.
13 |
14 | Please consider this example:
15 | ```elm
16 | import Child
17 |
18 |
19 | type Msg
20 | = SomeMsg
21 | | ToChild Child.Msg
22 |
23 |
24 | -- Tagger function, for better control over the message flow.
25 |
26 |
27 | tagger : Child.Msg -> Msg
28 | tagger msg =
29 | case msg of
30 | Child.SomeMsg ->
31 | SomeMsg
32 |
33 | _ ->
34 | ToChild msg
35 |
36 |
37 | -- Top-level view
38 |
39 |
40 | view : Model -> Html Msg
41 | view model =
42 | Cmd.map tagger (Child.view model.childState)
43 |
44 | ```
45 |
46 | ## Building the example
47 |
48 | ```sh
49 | $ elm make Main.elm
50 | ```
51 |
--------------------------------------------------------------------------------
/examples/module-composition-tagger/elm.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "application",
3 | "source-directories": [
4 | "."
5 | ],
6 | "elm-version": "0.19.0",
7 | "dependencies": {
8 | "direct": {
9 | "elm/browser": "1.0.0",
10 | "elm/core": "1.0.0",
11 | "elm/html": "1.0.0"
12 | },
13 | "indirect": {
14 | "elm/json": "1.0.0",
15 | "elm/time": "1.0.0",
16 | "elm/url": "1.0.0",
17 | "elm/virtual-dom": "1.0.0"
18 | }
19 | },
20 | "test-dependencies": {
21 | "direct": {},
22 | "indirect": {}
23 | }
24 | }
--------------------------------------------------------------------------------
/examples/module-composition/Helper.elm:
--------------------------------------------------------------------------------
1 | module Helper exposing (Model, Msg(..), init, update, view)
2 |
3 | {- This module has functions for showing and hiding the text -}
4 |
5 | import Html exposing (Html, div, text)
6 |
7 |
8 | type alias Model =
9 | { text : String
10 | , visible : Bool
11 | }
12 |
13 |
14 | init : String -> ( Model, Cmd Msg )
15 | init text =
16 | {- Returning Cmd Msg from child module is not necessary,
17 | and the signature of init and update function might be simplified to:
18 |
19 | String -> Model
20 | Msg -> Model -> Model
21 |
22 | Here I return Cmd.none just to follow Fractal Architecture pattern.
23 | -}
24 | ( Model text False, Cmd.none )
25 |
26 |
27 | type Msg
28 | = Show
29 | | Hide
30 |
31 |
32 | view : Model -> Html Msg
33 | view model =
34 | if model.visible == True then
35 | div [] [ text model.text ]
36 |
37 | else
38 | text ""
39 |
40 |
41 | update : Msg -> Model -> ( Model, Cmd Msg )
42 | update msg model =
43 | case msg of
44 | Show ->
45 | ( { model | visible = True }, Cmd.none )
46 |
47 | Hide ->
48 | ( { model | visible = False }, Cmd.none )
49 |
--------------------------------------------------------------------------------
/examples/module-composition/Input.elm:
--------------------------------------------------------------------------------
1 | module Input exposing (Model, Msg(..), init, update, view)
2 |
3 | {- This is an input module, which emits messages, when user types anything,
4 | focuses on it, or when focus leaves the field.
5 | -}
6 |
7 | import Html exposing (Html, input)
8 | import Html.Attributes exposing (type_, value)
9 | import Html.Events exposing (onBlur, onFocus, onInput)
10 |
11 |
12 | type alias Model =
13 | String
14 |
15 |
16 | init : Model -> ( Model, Cmd Msg )
17 | init text =
18 | ( text, Cmd.none )
19 |
20 |
21 | type Msg
22 | = Update Model
23 | | Focus
24 | | Blur
25 |
26 |
27 | view : Model -> Html Msg
28 | view model =
29 | input
30 | [ type_ "text"
31 | , onInput Update
32 | , onFocus Focus
33 | , onBlur Blur
34 | , value model
35 | ]
36 | []
37 |
38 |
39 | update : Msg -> Model -> ( Model, Cmd Msg )
40 | update msg model =
41 | case msg of
42 | Update value ->
43 | ( value, Cmd.none )
44 |
45 | -- Ignore the rest of the messages.
46 | _ ->
47 | ( model, Cmd.none )
48 |
--------------------------------------------------------------------------------
/examples/module-composition/Main.elm:
--------------------------------------------------------------------------------
1 | module Main exposing (Model, Msg(..), init, main, subscriptions, update, view)
2 |
3 | import Browser
4 | import Helper
5 | import Html exposing (Html, div, text)
6 | import Input
7 |
8 |
9 | main : Program () Model Msg
10 | main =
11 | Browser.element
12 | { view = view
13 | , init = \() -> init
14 | , update = update
15 | , subscriptions = subscriptions
16 | }
17 |
18 |
19 | subscriptions : Model -> Sub Msg
20 | subscriptions model =
21 | Sub.none
22 |
23 |
24 | type alias Model =
25 | { name : Input.Model
26 | , helper : Helper.Model
27 | }
28 |
29 |
30 | init : ( Model, Cmd Msg )
31 | init =
32 | let
33 | -- Omit the Cmd from child's init, because we know that it's Cmd.none
34 | ( nameModel, _ ) =
35 | Input.init "John"
36 |
37 | ( helperModel, _ ) =
38 | Helper.init "Please enter your name"
39 | in
40 | ( Model nameModel helperModel, Cmd.none )
41 |
42 |
43 | type Msg
44 | = NameMsg Input.Msg
45 | | HelperMsg Helper.Msg
46 |
47 |
48 | view : Model -> Html Msg
49 | view model =
50 | div []
51 | [ text model.name
52 | , Html.map NameMsg (Input.view model.name)
53 | , Html.map HelperMsg (Helper.view model.helper)
54 | ]
55 |
56 |
57 | update : Msg -> Model -> ( Model, Cmd Msg )
58 | update msg model =
59 | case msg of
60 | NameMsg childMsg ->
61 | case childMsg of
62 | {- We have intercepted a message from child module.
63 |
64 | This part of the update function might be moved
65 | to a separate function for better readability.
66 | -}
67 | Input.Focus ->
68 | update (HelperMsg Helper.Show) model
69 |
70 | Input.Blur ->
71 | update (HelperMsg Helper.Hide) model
72 |
73 | -- The default message passing routine.
74 | _ ->
75 | let
76 | ( nameModel, nameCmd ) =
77 | Input.update childMsg model.name
78 | in
79 | ( { model | name = nameModel }
80 | , Cmd.map NameMsg nameCmd
81 | )
82 |
83 | HelperMsg childMsg ->
84 | let
85 | ( helperModel, helperCmd ) =
86 | Helper.update childMsg model.helper
87 | in
88 | ( { model | helper = helperModel }
89 | , Cmd.map HelperMsg helperCmd
90 | )
91 |
--------------------------------------------------------------------------------
/examples/module-composition/README.md:
--------------------------------------------------------------------------------
1 | # Module composition in Elm
2 |
3 | This example features the simplest way for establishing module communication.
4 |
5 | [@rtfeldman](https://github.com/rtfeldman/) on [Design of Large Elm apps](https://groups.google.com/forum/#!msg/elm-discuss/_cfOu88oCx4/6tVXN2TGAgAJ)
6 |
7 | > The first three things you should reach for are, in no particular order:
8 | > - Splitting `view` into smaller functions (without reorganizing `Model` or `update`)
9 | > - Splitting `Model` into smaller values (without reorganizing `view` or `update`)
10 | > - Splitting `update` into smaller functions (without reorganizing `Model` or `view`)
11 | >
12 | > Do one of these 3 things, one at a time, over and over, until either you're thinking "I need to split out some of this to reuse it elsewhere" (in which case you enter the realm of API design, and there is no one-size-fits-all answer to what you should do next), or you find yourself thinking "even after these small refactors, there is a big chunk of code that still feels unwieldy, and it's self-contained enough that I could separate it out into essentially its own little application, and have it communicate with the rest of the application, and that communication overhead sounds like it would be worth it."
13 |
14 | ## Motivation
15 |
16 | Elm implements uni-directional message passing,
17 | so you can not send a message directly from child to parent.
18 |
19 | To mimic child-to-parent message passing, we have to send a message from the
20 | child and [capture it in parent's update](Main.elm#L61) function.
21 |
22 | While [Input](Input.elm#L21) module has defined more than one message, only `Update`
23 | will have effect on the state.
24 |
25 | ```elm
26 | update : Msg -> Model -> ( Model, Cmd Msg )
27 | update msg model =
28 | case msg of
29 | Update value ->
30 | ( value, Cmd.none )
31 |
32 | -- Ignore the rest of the messages.
33 | _ ->
34 | ( model, Cmd.none )
35 | ```
36 |
37 | ## Building the example
38 |
39 | ```sh
40 | $ elm make Main.elm
41 | ```
42 |
43 | ## More information on module composition in Elm
44 |
45 | For more ideas, I highly recommend watching [API Design Session - elm-autocomplete with Greg Ziegan](https://www.youtube.com/watch?v=KSuCYUqY058)
46 |
--------------------------------------------------------------------------------
/examples/module-composition/elm.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "application",
3 | "source-directories": [
4 | "."
5 | ],
6 | "elm-version": "0.19.0",
7 | "dependencies": {
8 | "direct": {
9 | "elm/browser": "1.0.0",
10 | "elm/core": "1.0.0",
11 | "elm/html": "1.0.0",
12 | "elm/virtual-dom": "1.0.0"
13 | },
14 | "indirect": {
15 | "elm/json": "1.0.0",
16 | "elm/time": "1.0.0",
17 | "elm/url": "1.0.0"
18 | }
19 | },
20 | "test-dependencies": {
21 | "direct": {},
22 | "indirect": {}
23 | }
24 | }
--------------------------------------------------------------------------------
/examples/ports/Main.elm:
--------------------------------------------------------------------------------
1 | port module Main exposing (Model, Msg(..), init, input, main, output, subscriptions, update, view)
2 |
3 | import Browser
4 | import Html exposing (..)
5 | import Html.Attributes exposing (..)
6 | import String
7 | import Task
8 |
9 |
10 | main : Program () Model Msg
11 | main =
12 | Browser.element
13 | { init = \() -> init
14 | , view = view
15 | , update = update
16 | , subscriptions = subscriptions
17 | }
18 |
19 |
20 |
21 | -- SUBSCRIPTIONS
22 |
23 |
24 | {-| With an outgoing port, I want to tell JavaScript to send some value to Elm.
25 | That does not require sending data to JavaScript, so I send an empty Tuple.
26 |
27 | Note, that you can not specify the exact message type of port commands.
28 |
29 | Both port functions can be exported and used outside of the module.
30 | Since output does not emit any messages, we have type annotation definition with a generic `msg`,
31 | so it's easier to use it outside of this module
32 | and you don't have to use Cmd.map to re-map a non-existing message type.
33 |
34 | The subscription as well can be used outside of this module,
35 | you can use any message type to receive messages from the port.
36 |
37 | -}
38 | port output : () -> Cmd msg
39 |
40 |
41 | port input : (Int -> msg) -> Sub msg
42 |
43 |
44 | subscriptions : Model -> Sub Msg
45 | subscriptions model =
46 | input Get
47 |
48 |
49 |
50 | -- MODEL
51 |
52 |
53 | type alias Model =
54 | { number : Int }
55 |
56 |
57 |
58 | -- VIEW
59 |
60 |
61 | view : Model -> Html Msg
62 | view model =
63 | text (String.fromInt model.number)
64 |
65 |
66 |
67 | -- UPDATE
68 |
69 |
70 | type Msg
71 | = Get Int
72 |
73 |
74 | update : Msg -> Model -> ( Model, Cmd Msg )
75 | update msg model =
76 | case Debug.log "MESSAGE: " msg of
77 | Get x ->
78 | ( Model x, Cmd.none )
79 |
80 |
81 |
82 | -- INIT
83 |
84 |
85 | init : ( Model, Cmd Msg )
86 | init =
87 | {- Send a message through port upon initialization. -}
88 | ( Model 0, output () )
89 |
--------------------------------------------------------------------------------
/examples/ports/README.md:
--------------------------------------------------------------------------------
1 | # JavaScript interop with Elm
2 |
3 | This is an example of passing messages from Elm to JavaScript and backwards.
4 |
5 | It sends a hole `()` or empty Tuple to JavaScript, as a message and retrieves a numeric value.
6 |
7 | Inspired by [Trouble Connecting Ports and Subscriptions] [question]
8 |
9 | See more on the matter in the official docs for [JavaScript Interop] [ports]
10 |
11 | ## Building the example
12 |
13 | Since this example features port module, it is impossible to build it with `elm reactor`.
14 |
15 | You have to explicitly specify the `--output=index.js`
16 |
17 | ```sh
18 | $ elm make Main.elm --output=index.js
19 | ```
20 |
21 | [ports]:
22 | [question]:
23 |
--------------------------------------------------------------------------------
/examples/ports/elm.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "application",
3 | "source-directories": [
4 | "."
5 | ],
6 | "elm-version": "0.19.0",
7 | "dependencies": {
8 | "direct": {
9 | "elm/browser": "1.0.0",
10 | "elm/core": "1.0.0",
11 | "elm/html": "1.0.0"
12 | },
13 | "indirect": {
14 | "elm/json": "1.0.0",
15 | "elm/time": "1.0.0",
16 | "elm/url": "1.0.0",
17 | "elm/virtual-dom": "1.0.0"
18 | }
19 | },
20 | "test-dependencies": {
21 | "direct": {},
22 | "indirect": {}
23 | }
24 | }
--------------------------------------------------------------------------------
/examples/ports/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Elm Ports
6 |
7 |
8 |
9 |
10 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/examples/random-initial-seed/elm.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "application",
3 | "source-directories": [
4 | "."
5 | ],
6 | "elm-version": "0.19.0",
7 | "dependencies": {
8 | "direct": {
9 | "elm/browser": "1.0.0",
10 | "elm/core": "1.0.0",
11 | "elm/html": "1.0.0",
12 | "elm/random": "1.0.0"
13 | },
14 | "indirect": {
15 | "elm/json": "1.0.0",
16 | "elm/time": "1.0.0",
17 | "elm/url": "1.0.0",
18 | "elm/virtual-dom": "1.0.0"
19 | }
20 | },
21 | "test-dependencies": {
22 | "direct": {},
23 | "indirect": {}
24 | }
25 | }
--------------------------------------------------------------------------------
/examples/random-initial-seed/src/Main.elm:
--------------------------------------------------------------------------------
1 | module Main exposing (Model, Msg(..), main, seedGenerator, update, view)
2 |
3 | import Browser
4 | import Debug
5 | import Html exposing (button, div, text)
6 | import Html.Events exposing (onClick)
7 | import Random exposing (Generator, Seed)
8 |
9 |
10 |
11 | -- TODO
12 |
13 |
14 | main =
15 | Browser.element
16 | { init =
17 | \() ->
18 | ( { seed = Nothing, stack = [] }
19 | -- Initial command to create independent Seed.
20 | , Random.generate Update seedGenerator
21 | )
22 | , view = view
23 | , update = update
24 | , subscriptions = \model -> Sub.none
25 | }
26 |
27 |
28 | view model =
29 | div []
30 | [ button
31 | [ onClick PutRandomNumber ]
32 | [ text "Put a random value on a stack" ]
33 | , text (Debug.toString model.stack)
34 | ]
35 |
36 |
37 | type alias Model =
38 | { seed : Maybe Seed
39 | , stack : List Int
40 | }
41 |
42 |
43 | type Msg
44 | = Update Seed
45 | | PutRandomNumber
46 |
47 |
48 | seedGenerator : Generator Seed
49 | seedGenerator =
50 | Random.int Random.minInt Random.maxInt
51 | |> Random.map Random.initialSeed
52 |
53 |
54 | update msg model =
55 | case msg of
56 | Update seed ->
57 | -- Preserve newly initialized Seed state.
58 | ( { model | seed = Just seed }, Cmd.none )
59 |
60 | PutRandomNumber ->
61 | let
62 | -- In case if seed was present, new model will contain the new value and a new state for the seed.
63 | newModel : Model
64 | newModel =
65 | model.seed
66 | |> Maybe.map (Random.step (Random.int 0 10))
67 | |> Maybe.map
68 | (\( number, seed ) ->
69 | { model | seed = Just seed, stack = number :: model.stack }
70 | )
71 | |> Maybe.withDefault model
72 | in
73 | ( newModel
74 | , Cmd.none
75 | )
76 |
--------------------------------------------------------------------------------
/examples/random-user-seed/Main.elm:
--------------------------------------------------------------------------------
1 | module Main exposing (Model, Msg(..), generator, init, main, update, view)
2 |
3 | import Browser
4 | import Debug
5 | import Html exposing (Html, button, div, input, text)
6 | import Html.Attributes exposing (placeholder, value)
7 | import Html.Events exposing (onClick, onInput)
8 | import Random exposing (Generator, Seed)
9 | import String
10 |
11 |
12 | generator : Int -> Generator (List Int)
13 | generator length =
14 | Random.list length (Random.int 0 100)
15 |
16 |
17 | view : Model -> Html Msg
18 | view model =
19 | div
20 | []
21 | (input [ value model.input, placeholder "Enter numeric seed", onInput Update ] []
22 | :: (case model.state of
23 | Ok state ->
24 | [ button [ onClick Next ] [ text "Next" ], text (Debug.toString (Tuple.first state)) ]
25 |
26 | Err msg ->
27 | [ text msg ]
28 | )
29 | )
30 |
31 |
32 | type Msg
33 | = Update String
34 | | CreateSeed
35 | | Next
36 |
37 |
38 | update : Msg -> Model -> Model
39 | update msg model =
40 | case msg of
41 | Update val ->
42 | update CreateSeed { model | input = val }
43 |
44 | CreateSeed ->
45 | case String.toInt model.input of
46 | Nothing ->
47 | { model | state = Err (model.input ++ " is not a valid Int") }
48 |
49 | Just theInt ->
50 | let
51 | seed =
52 | Random.initialSeed theInt
53 |
54 | newState =
55 | Random.step (generator 10) seed
56 | in
57 | { model | state = Ok newState }
58 |
59 | Next ->
60 | { model | state = Result.map (Random.step (generator 10) << Tuple.second) model.state }
61 |
62 |
63 | type alias Model =
64 | { state : Result String ( List Int, Seed )
65 | , input : String
66 | }
67 |
68 |
69 | init : Model
70 | init =
71 | Model (Err "Seed is not available") ""
72 |
73 |
74 | main : Program () Model Msg
75 | main =
76 | Browser.sandbox
77 | { view = view
78 | , init = init
79 | , update = update
80 | }
81 |
--------------------------------------------------------------------------------
/examples/random-user-seed/README.md:
--------------------------------------------------------------------------------
1 | # Random value with user-specified seed
2 |
3 | Example app for generating a list of 10 integers, using user-specified seed.
4 |
5 | It is also possible to step through generator to get next 10 random values.
6 |
7 | ## Building the example
8 |
9 | ```sh
10 | $ elm make Main.elm
11 | ```
12 |
--------------------------------------------------------------------------------
/examples/random-user-seed/elm.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "application",
3 | "source-directories": [
4 | "."
5 | ],
6 | "elm-version": "0.19.0",
7 | "dependencies": {
8 | "direct": {
9 | "elm/browser": "1.0.0",
10 | "elm/core": "1.0.0",
11 | "elm/html": "1.0.0",
12 | "elm/random": "1.0.0"
13 | },
14 | "indirect": {
15 | "elm/json": "1.0.0",
16 | "elm/time": "1.0.0",
17 | "elm/url": "1.0.0",
18 | "elm/virtual-dom": "1.0.0"
19 | }
20 | },
21 | "test-dependencies": {
22 | "direct": {},
23 | "indirect": {}
24 | }
25 | }
--------------------------------------------------------------------------------
/examples/select2-integration/.gitignore:
--------------------------------------------------------------------------------
1 | # Distribution
2 | build/
3 |
4 | # elm-package generated files
5 | elm-stuff
6 |
7 | # elm-repl generated files
8 | repl-temp-*
9 |
10 | # Dependency directories
11 | node_modules
12 |
13 | # Desktop Services Store on macOS
14 | .DS_Store
15 |
--------------------------------------------------------------------------------
/examples/select2-integration/README.md:
--------------------------------------------------------------------------------
1 | Running demo of this application is available [here.](https://halfzebra.github.io/elm-examples/select2-integration/dist/)
2 |
3 | This project was bootstrapped with [Create Elm App.](https://github.com/halfzebra/create-elm-app)
4 |
5 | Below you will find some information on how to perform common tasks.
6 | You can find the most recent version of this guide [here](https://github.com/halfzebra/create-elm-app/blob/master/template/README.md).
7 |
8 | ## Building the example
9 |
10 | ```sh
11 | $ npm install create-elm-app -g # Install CreateElm App
12 | $ npm install # install local NPM deps
13 | $ elm-app build # Build the example
14 | ```
--------------------------------------------------------------------------------
/examples/select2-integration/elm.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "application",
3 | "source-directories": ["src"],
4 | "elm-version": "0.19.0",
5 | "dependencies": {
6 | "direct": {
7 | "elm/browser": "1.0.0",
8 | "elm/core": "1.0.0",
9 | "elm/html": "1.0.0"
10 | },
11 | "indirect": {
12 | "elm/json": "1.0.0",
13 | "elm/time": "1.0.0",
14 | "elm/url": "1.0.0",
15 | "elm/virtual-dom": "1.0.0"
16 | }
17 | },
18 | "test-dependencies": {
19 | "direct": {
20 | "elm-explorations/test": "1.0.0"
21 | },
22 | "indirect": {
23 | "elm/random": "1.0.0"
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/examples/select2-integration/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "select2-integration",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "almond": {
8 | "version": "0.3.3",
9 | "resolved": "https://registry.npmjs.org/almond/-/almond-0.3.3.tgz",
10 | "integrity": "sha1-oOfJWsdiTWQXtElLHmi/9pMWiiA="
11 | },
12 | "jquery": {
13 | "version": "3.3.1",
14 | "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz",
15 | "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg=="
16 | },
17 | "jquery-mousewheel": {
18 | "version": "3.1.13",
19 | "resolved": "https://registry.npmjs.org/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz",
20 | "integrity": "sha1-BvAzXxbjU6aV5yBr9QUDy1I6buU="
21 | },
22 | "select2": {
23 | "version": "4.0.5",
24 | "resolved": "https://registry.npmjs.org/select2/-/select2-4.0.5.tgz",
25 | "integrity": "sha1-eqxQaSVhmFs007guxV4ib4lg1Ao=",
26 | "requires": {
27 | "almond": "~0.3.1",
28 | "jquery-mousewheel": "~3.1.13"
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/examples/select2-integration/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "select2-integration",
3 | "version": "1.0.0",
4 | "description": "This project was bootstrapped with [Create Elm App](https://github.com/halfzebra/create-elm-app).",
5 | "main": "index.js",
6 | "directories": {
7 | "test": "tests"
8 | },
9 | "scripts": {
10 | "test": "echo \"Error: no test specified\" && exit 1"
11 | },
12 | "keywords": [],
13 | "author": "",
14 | "license": "ISC",
15 | "dependencies": {
16 | "jquery": "^3.3.1",
17 | "select2": "^4.0.5"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/select2-integration/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/halfzebra/elm-examples/0b79ff2f79717553c9c9e2b7b4e44d78e97ccb9e/examples/select2-integration/public/favicon.ico
--------------------------------------------------------------------------------
/examples/select2-integration/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
14 | Elm App
15 |
16 |
17 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/examples/select2-integration/public/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
40 |
--------------------------------------------------------------------------------
/examples/select2-integration/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "Elm App",
3 | "name": "Create Elm App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/examples/select2-integration/src/App.elm:
--------------------------------------------------------------------------------
1 | port module App exposing (Model, Msg(..), init, input, options, output, subscriptions, update, view)
2 |
3 | import Dict exposing (Dict)
4 | import Html exposing (Html, div, text)
5 | import Html.Attributes exposing (id)
6 |
7 |
8 | type alias Model =
9 | { selection : Maybe String }
10 |
11 |
12 | modelToString : Model -> String
13 | modelToString model =
14 | case model.selection of
15 | Nothing ->
16 | "Nothing"
17 |
18 | Just s ->
19 | "Just " ++ s
20 |
21 |
22 | init : ( Model, Cmd Msg )
23 | init =
24 | ( Model Nothing, output (Dict.toList options) )
25 |
26 |
27 | type Msg
28 | = Select String
29 |
30 |
31 | update : Msg -> Model -> ( Model, Cmd Msg )
32 | update msg model =
33 | case msg of
34 | Select val ->
35 | let
36 | option : Maybe String
37 | option =
38 | Dict.get val options
39 | in
40 | ( { model | selection = option }, Cmd.none )
41 |
42 |
43 | view : Model -> Html Msg
44 | view model =
45 | div
46 | []
47 | [ text (modelToString model)
48 | , div [ id "select2-container" ] []
49 | ]
50 |
51 |
52 | port output : List ( String, String ) -> Cmd msg
53 |
54 |
55 | port input : (String -> msg) -> Sub msg
56 |
57 |
58 | options : Dict String String
59 | options =
60 | Dict.fromList
61 | [ ( "US", "United States" )
62 | , ( "UK", "United Kingdom" )
63 | , ( "UY", "Uruguay" )
64 | , ( "UZ", "Uzbekistan" )
65 | ]
66 |
67 |
68 | subscriptions : Model -> Sub Msg
69 | subscriptions model =
70 | input Select
71 |
--------------------------------------------------------------------------------
/examples/select2-integration/src/Main.elm:
--------------------------------------------------------------------------------
1 | module Main exposing (main)
2 |
3 | import App exposing (..)
4 | import Browser
5 |
6 |
7 | main : Program () Model Msg
8 | main =
9 | Browser.element { view = view, init = \() -> init, update = update, subscriptions = subscriptions }
10 |
--------------------------------------------------------------------------------
/examples/select2-integration/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/halfzebra/elm-examples/0b79ff2f79717553c9c9e2b7b4e44d78e97ccb9e/examples/select2-integration/src/favicon.ico
--------------------------------------------------------------------------------
/examples/select2-integration/src/index.js:
--------------------------------------------------------------------------------
1 | import './main.css';
2 | import '../node_modules/select2/dist/css/select2.min.css';
3 |
4 | import { Elm } from './Main.elm';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | import $ from 'jquery';
8 | import select2 from 'select2';
9 |
10 | var app = Elm.Main.init({
11 | node: document.getElementById('root')
12 | });
13 |
14 | registerServiceWorker();
15 |
16 | app.ports.output.subscribe(function (options) {
17 |
18 | var $selectContainer = $('#select2-container');
19 |
20 | // Generate DOM tree with