mirror of
https://github.com/dillonkearns/elm-pages-v3-beta.git
synced 2024-11-23 14:15:33 +03:00
Rename BackendTask.Port -> BackendTask.Custom.
This commit is contained in:
parent
b773557245
commit
ea29d1bbb3
2
elm.json
2
elm.json
@ -17,7 +17,7 @@
|
||||
"BackendTask.Glob",
|
||||
"BackendTask.Http",
|
||||
"BackendTask.File",
|
||||
"BackendTask.Port",
|
||||
"BackendTask.Custom",
|
||||
"BackendTask.Env",
|
||||
"Server.Request",
|
||||
"Server.Session",
|
||||
|
File diff suppressed because one or more lines are too long
@ -76,7 +76,7 @@ routes =
|
||||
(Decode.list (blogPostDecoder |> Decode.map .slug |> Decode.map RouteParams))
|
||||
```
|
||||
|
||||
### BackendTask.Port
|
||||
### BackendTask.Custom
|
||||
|
||||
The core built-in `BackendTask` modules let you pull in
|
||||
|
||||
@ -88,12 +88,12 @@ The core built-in `BackendTask` modules let you pull in
|
||||
|
||||
If that isn't enough to get you the data you need to pull in to your site, then there's an additional module that lets you build your own custom `BackendTask`.
|
||||
|
||||
[`BackendTask.Port`](BackendTask-Port) lets you decode JSON data that you call from custom NodeJS functions. As with any `BackendTask`, you get this data in the build step and then it gets built in to your site, so these NodeJS functions, HTTP requests, file reads, etc. are not happening when a user opens a page in your live site that you built with `elm-pages build`.
|
||||
[`BackendTask.Custom`](BackendTask-Custom) lets you decode JSON data that you call from custom NodeJS functions. As with any `BackendTask`, you get this data in the build step and then it gets built in to your site, so these NodeJS functions, HTTP requests, file reads, etc. are not happening when a user opens a page in your live site that you built with `elm-pages build`.
|
||||
|
||||
```elm
|
||||
data : BackendTask String
|
||||
data =
|
||||
BackendTask.Port.get "environmentVariable"
|
||||
BackendTask.Custom.get "environmentVariable"
|
||||
(Json.Encode.string "EDITOR")
|
||||
Decode.string
|
||||
```
|
||||
|
@ -3,7 +3,7 @@ module Route.Fetcher exposing (ActionData, Data, Model, Msg, RouteParams, route)
|
||||
{-| -}
|
||||
|
||||
import BackendTask exposing (BackendTask)
|
||||
import BackendTask.Port
|
||||
import BackendTask.Custom
|
||||
import Dict
|
||||
import Effect
|
||||
import ErrorPage
|
||||
@ -97,7 +97,7 @@ data :
|
||||
-> Server.Request.Parser (BackendTask FatalError (Server.Response.Response Data ErrorPage.ErrorPage))
|
||||
data routeParams =
|
||||
Server.Request.succeed
|
||||
(BackendTask.Port.get "getItems"
|
||||
(BackendTask.Custom.get "getItems"
|
||||
Encode.null
|
||||
(Decode.list Decode.string)
|
||||
|> BackendTask.allowFatal
|
||||
@ -125,7 +125,7 @@ action routeParams =
|
||||
(\formPost ->
|
||||
case formPost of
|
||||
Ok (AddItem newItem) ->
|
||||
BackendTask.Port.get "addItem"
|
||||
BackendTask.Custom.get "addItem"
|
||||
(Encode.string newItem)
|
||||
(Decode.list Decode.string)
|
||||
|> BackendTask.allowFatal
|
||||
@ -135,7 +135,7 @@ action routeParams =
|
||||
)
|
||||
|
||||
Ok DeleteAll ->
|
||||
BackendTask.Port.get "deleteAllItems"
|
||||
BackendTask.Custom.get "deleteAllItems"
|
||||
Encode.null
|
||||
(Decode.list Decode.string)
|
||||
|> BackendTask.allowFatal
|
||||
|
@ -1,8 +1,8 @@
|
||||
module Route.Index exposing (ActionData, Data, Model, Msg, route)
|
||||
|
||||
import BackendTask exposing (BackendTask)
|
||||
import BackendTask.Custom
|
||||
import BackendTask.File
|
||||
import BackendTask.Port
|
||||
import FatalError exposing (FatalError)
|
||||
import Head
|
||||
import Head.Seo as Seo
|
||||
@ -53,7 +53,7 @@ data : BackendTask FatalError Data
|
||||
data =
|
||||
BackendTask.map2 Data
|
||||
(BackendTask.File.rawFile "greeting.txt" |> BackendTask.allowFatal)
|
||||
(BackendTask.Port.get "hello" (Encode.string "Jane") Decode.string |> BackendTask.allowFatal)
|
||||
(BackendTask.Custom.get "hello" (Encode.string "Jane") Decode.string |> BackendTask.allowFatal)
|
||||
|
||||
|
||||
head :
|
||||
|
@ -2,7 +2,7 @@ module Route.Feed__ exposing (ActionData, Data, Model, Msg, route)
|
||||
|
||||
import BackendTask exposing (BackendTask)
|
||||
import BackendTask.Http
|
||||
import BackendTask.Port
|
||||
import BackendTask.Custom
|
||||
import Effect exposing (Effect)
|
||||
import ErrorPage exposing (ErrorPage)
|
||||
import Head
|
||||
|
@ -1,7 +1,7 @@
|
||||
module Route.PortTest exposing (ActionData, Data, Model, Msg, route)
|
||||
|
||||
import BackendTask exposing (BackendTask)
|
||||
import BackendTask.Port
|
||||
import BackendTask.Custom
|
||||
import FatalError exposing (FatalError)
|
||||
import Head
|
||||
import Head.Seo as Seo
|
||||
@ -49,7 +49,7 @@ type alias ActionData =
|
||||
data : BackendTask FatalError Data
|
||||
data =
|
||||
BackendTask.succeed Data
|
||||
|> BackendTask.andMap (BackendTask.Port.get "hello" (Encode.string "Jane") Decode.string |> BackendTask.allowFatal)
|
||||
|> BackendTask.andMap (BackendTask.Custom.get "hello" (Encode.string "Jane") Decode.string |> BackendTask.allowFatal)
|
||||
|
||||
|
||||
head :
|
||||
|
@ -3,7 +3,7 @@ module Route.Login exposing (ActionData, Data, Model, Msg, route)
|
||||
import Api.Scalar exposing (Uuid(..))
|
||||
import Data.User
|
||||
import BackendTask exposing (BackendTask)
|
||||
import BackendTask.Port
|
||||
import BackendTask.Custom
|
||||
import Dict exposing (Dict)
|
||||
import ErrorPage exposing (ErrorPage)
|
||||
import Form
|
||||
@ -99,7 +99,7 @@ form =
|
||||
|
||||
attemptLogIn : String -> String -> BackendTask (Maybe Uuid)
|
||||
attemptLogIn username password =
|
||||
BackendTask.Port.get "hashPassword"
|
||||
BackendTask.Custom.get "hashPassword"
|
||||
(Json.Encode.string password)
|
||||
Json.Decode.string
|
||||
|> BackendTask.andThen
|
||||
|
@ -2,9 +2,9 @@ module Route.Login exposing (ActionData, Data, Model, Msg, route)
|
||||
|
||||
import Api.Scalar exposing (Uuid(..))
|
||||
import BackendTask exposing (BackendTask)
|
||||
import BackendTask.Custom
|
||||
import BackendTask.Env
|
||||
import BackendTask.Http
|
||||
import BackendTask.Port
|
||||
import Data.Session
|
||||
import Dict exposing (Dict)
|
||||
import EmailAddress exposing (EmailAddress)
|
||||
@ -61,7 +61,7 @@ route =
|
||||
|
||||
now : BackendTask Time.Posix
|
||||
now =
|
||||
BackendTask.Port.get "now"
|
||||
BackendTask.Custom.get "now"
|
||||
Encode.null
|
||||
(Decode.int |> Decode.map Time.millisToPosix)
|
||||
|
||||
@ -71,7 +71,7 @@ emailToMagicLink email baseUrl =
|
||||
now
|
||||
|> BackendTask.andThen
|
||||
(\now_ ->
|
||||
BackendTask.Port.get "encrypt"
|
||||
BackendTask.Custom.get "encrypt"
|
||||
(Encode.object
|
||||
[ ( "text", Encode.string (EmailAddress.toString email) )
|
||||
, ( "expiresAt", (Time.posixToMillis now_ + (1000 * 60 * 30)) |> Encode.int )
|
||||
@ -497,7 +497,7 @@ sendEmail apiKey_ email_ =
|
||||
|
||||
parseMagicHash : String -> BackendTask ( String, Time.Posix )
|
||||
parseMagicHash magicHash =
|
||||
BackendTask.Port.get "decrypt"
|
||||
BackendTask.Custom.get "decrypt"
|
||||
(Encode.string magicHash)
|
||||
(Decode.string
|
||||
|> Decode.map
|
||||
@ -533,6 +533,6 @@ parseMagicHashIfNotExpired magicHash =
|
||||
|
||||
log : String -> BackendTask ()
|
||||
log message =
|
||||
BackendTask.Port.get "log"
|
||||
BackendTask.Custom.get "log"
|
||||
(Encode.string message)
|
||||
(Decode.succeed ())
|
||||
|
@ -43,21 +43,21 @@ function lookupOrPerform(portsFile, mode, rawRequest, hasFsAccess, useCache) {
|
||||
resolve({
|
||||
kind: "response-json",
|
||||
value: jsonResponse({
|
||||
"elm-pages-internal-error": "PortNotDefined",
|
||||
"elm-pages-internal-error": "CustomBackendTaskNotDefined",
|
||||
}),
|
||||
});
|
||||
} else if (portBackendTaskImportError === "missing") {
|
||||
resolve({
|
||||
kind: "response-json",
|
||||
value: jsonResponse({
|
||||
"elm-pages-internal-error": "MissingPortsFile",
|
||||
"elm-pages-internal-error": "MissingCustomBackendTaskFile",
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
resolve({
|
||||
kind: "response-json",
|
||||
value: jsonResponse({
|
||||
"elm-pages-internal-error": "ErrorInPortsFile",
|
||||
"elm-pages-internal-error": "ErrorInCustomBackendTaskFile",
|
||||
error:
|
||||
(portBackendTaskImportError &&
|
||||
portBackendTaskImportError.stack) ||
|
||||
@ -83,7 +83,7 @@ function lookupOrPerform(portsFile, mode, rawRequest, hasFsAccess, useCache) {
|
||||
resolve({
|
||||
kind: "response-json",
|
||||
value: jsonResponse({
|
||||
"elm-pages-internal-error": "PortCallException",
|
||||
"elm-pages-internal-error": "CustomBackendTaskException",
|
||||
error: portCallError,
|
||||
}),
|
||||
});
|
||||
@ -92,7 +92,7 @@ function lookupOrPerform(portsFile, mode, rawRequest, hasFsAccess, useCache) {
|
||||
} catch (error) {
|
||||
console.trace(error);
|
||||
reject({
|
||||
title: "BackendTask.Port Error",
|
||||
title: "BackendTask.Custom Error",
|
||||
message: error.toString(),
|
||||
});
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
module Timestamps exposing (Timestamps, data, format)
|
||||
|
||||
import BackendTask exposing (BackendTask)
|
||||
import BackendTask.Port
|
||||
import BackendTask.Custom
|
||||
import DateFormat
|
||||
import Json.Decode as Decode
|
||||
import Json.Decode.Extra
|
||||
@ -19,7 +19,7 @@ type alias Timestamps =
|
||||
|
||||
data : String -> BackendTask Timestamps
|
||||
data filePath =
|
||||
BackendTask.Port.get "gitTimestamps"
|
||||
BackendTask.Custom.get "gitTimestamps"
|
||||
(Json.Encode.string filePath)
|
||||
(Decode.string
|
||||
|> Decode.map (String.trim >> String.split "\n")
|
||||
|
@ -16,7 +16,7 @@ A `BackendTask` lets you pull in data from:
|
||||
- Local files ([`BackendTask.File`](BackendTask-File))
|
||||
- HTTP requests ([`BackendTask.Http`](BackendTask-Http))
|
||||
- Globs, i.e. listing out local files based on a pattern like `content/*.txt` ([`BackendTask.Glob`](BackendTask-Glob))
|
||||
- Ports, i.e. getting JSON data from running custom NodeJS, similar to a port in a vanilla Elm app except run at build-time in NodeJS, rather than at run-time in the browser ([`BackendTask.Port`](BackendTask-Port))
|
||||
- Ports, i.e. getting JSON data from running custom NodeJS, similar to a port in a vanilla Elm app except run at build-time in NodeJS, rather than at run-time in the browser ([`BackendTask.Custom`](BackendTask-Custom))
|
||||
- Hardcoded data (`BackendTask.succeed "Hello!"`)
|
||||
- Or any combination of the above, using `BackendTask.map2`, `BackendTask.andThen`, or other combining/continuing helpers from this module
|
||||
|
||||
|
@ -1,30 +1,30 @@
|
||||
module BackendTask.Port exposing
|
||||
module BackendTask.Custom exposing
|
||||
( get
|
||||
, Error(..)
|
||||
)
|
||||
|
||||
{-| In a vanilla Elm application, ports let you either send or receive JSON data between your Elm application and the JavaScript context in the user's browser at runtime.
|
||||
|
||||
With `BackendTask.Port`, you send and receive JSON to JavaScript running in NodeJS. As with any `BackendTask`, Port BackendTask's are either run at build-time (for pre-rendered routes) or at request-time (for server-rendered routes). See [`BackendTask`](BackendTask) for more about the
|
||||
With `BackendTask.Custom`, you send and receive JSON to JavaScript running in NodeJS. As with any `BackendTask`, Custom BackendTask's are either run at build-time (for pre-rendered routes) or at request-time (for server-rendered routes). See [`BackendTask`](BackendTask) for more about the
|
||||
lifecycle of `BackendTask`'s.
|
||||
|
||||
This means that you can call shell scripts, run NPM packages that are installed, or anything else you could do with NodeJS to perform custom side-effects, get some data, or both.
|
||||
|
||||
A `BackendTask.Port` will call an async JavaScript function with the given name from the definition in a file called `port-data-source.js` in your project's root directory. The function receives the input JSON value, and the Decoder is used to decode the return value of the async function.
|
||||
A `BackendTask.Custom` will call an async JavaScript function with the given name from the definition in a file called `port-data-source.js` in your project's root directory. The function receives the input JSON value, and the Decoder is used to decode the return value of the async function.
|
||||
|
||||
@docs get
|
||||
|
||||
Here is the Elm code and corresponding JavaScript definition for getting an environment variable (or an `FatalError BackendTask.Port.Error` if it isn't found). In this example,
|
||||
Here is the Elm code and corresponding JavaScript definition for getting an environment variable (or an `FatalError BackendTask.Custom.Error` if it isn't found). In this example,
|
||||
we're using `BackendTask.allowFatal` to let the framework treat that as an unexpected exception, but we could also handle the possible failures of the `FatalError` (see [`FatalError`](FatalError)).
|
||||
|
||||
import BackendTask exposing (BackendTask)
|
||||
import BackendTask.Port
|
||||
import BackendTask.Custom
|
||||
import Json.Encode
|
||||
import OptimizedDecoder as Decode
|
||||
|
||||
data : BackendTask FatalError String
|
||||
data =
|
||||
BackendTask.Port.get "environmentVariable"
|
||||
BackendTask.Custom.get "environmentVariable"
|
||||
(Json.Encode.string "EDITOR")
|
||||
Decode.string
|
||||
|> BackendTask.allowFatal
|
||||
@ -60,18 +60,18 @@ ${Object.keys(process.env).join("\n")}
|
||||
## Performance
|
||||
|
||||
As with any JavaScript or NodeJS code, avoid doing blocking IO operations. For example, avoid using `fs.readFileSync`, because blocking IO can slow down your elm-pages builds and dev server. `elm-pages` performances all `BackendTask`'s in parallel whenever possible.
|
||||
So if you do `BackendTask.map2 Tuple.pair myHttpBackendTask myPortBackendTask`, it will resolve those two in parallel. NodeJS performs best when you take advantage of its ability to do non-blocking I/O (file reads, HTTP requests, etc.). If you use `BackendTask.andThen`,
|
||||
it will need to resolve them in sequence rather than in parallel, but it's still best to avoid blocking IO operations in your BackendTask Port definitions.
|
||||
So if you do `BackendTask.map2 Tuple.pair myHttpBackendTask myCustomBackendTask`, it will resolve those two in parallel. NodeJS performs best when you take advantage of its ability to do non-blocking I/O (file reads, HTTP requests, etc.). If you use `BackendTask.andThen`,
|
||||
it will need to resolve them in sequence rather than in parallel, but it's still best to avoid blocking IO operations in your Custom BackendTask definitions.
|
||||
|
||||
|
||||
## Error Handling
|
||||
|
||||
There are a few different things that can go wrong when running a port-data-source. These possible errors are captured in the `BackendTask.Port.Error` type.
|
||||
There are a few different things that can go wrong when running a port-data-source. These possible errors are captured in the `BackendTask.Custom.Error` type.
|
||||
|
||||
@docs Error
|
||||
|
||||
Any time you throw a JavaScript exception from a BackendTask.Port definition, it will give you a `PortCallException`. It's usually easier to add a `try`/`catch` in your JavaScript code in `port-data-source.js`
|
||||
to handle possible errors, but you can throw a JSON value and handle it in Elm in the `PortCallException` call error.
|
||||
Any time you throw a JavaScript exception from a BackendTask.Custom definition, it will give you a `CustomBackendTaskException`. It's usually easier to add a `try`/`catch` in your JavaScript code in `port-data-source.js`
|
||||
to handle possible errors, but you can throw a JSON value and handle it in Elm in the `CustomBackendTaskException` call error.
|
||||
|
||||
-}
|
||||
|
||||
@ -104,17 +104,17 @@ get portName input decoder =
|
||||
[ Decode.field "elm-pages-internal-error" Decode.string
|
||||
|> Decode.andThen
|
||||
(\errorKind ->
|
||||
if errorKind == "PortNotDefined" then
|
||||
if errorKind == "CustomBackendTaskNotDefined" then
|
||||
FatalError.recoverable
|
||||
{ title = "Port Error"
|
||||
{ title = "Custom BackendTask Error"
|
||||
, body =
|
||||
[ TerminalText.text "Something went wrong in a call to BackendTask.Port.get. I expected to find a port named `"
|
||||
[ TerminalText.text "Something went wrong in a call to BackendTask.Custom.get. I expected to find a port named `"
|
||||
, TerminalText.yellow portName
|
||||
, TerminalText.text "` but I couldn't find it. Is the function exported in your port-data-source file?"
|
||||
]
|
||||
|> TerminalText.toString
|
||||
}
|
||||
(PortNotDefined { name = portName })
|
||||
(CustomBackendTaskNotDefined { name = portName })
|
||||
|> Decode.succeed
|
||||
|
||||
else if errorKind == "ExportIsNotFunction" then
|
||||
@ -122,78 +122,78 @@ get portName input decoder =
|
||||
|> Decode.maybe
|
||||
|> Decode.map (Maybe.withDefault "")
|
||||
|> Decode.map
|
||||
(\incorrectPortType ->
|
||||
(\incorrectType ->
|
||||
FatalError.recoverable
|
||||
{ title = "Port Error"
|
||||
{ title = "Custom BackendTask Error"
|
||||
, body =
|
||||
[ TerminalText.text "Something went wrong in a call to BackendTask.Port.get. I found an export called `"
|
||||
[ TerminalText.text "Something went wrong in a call to BackendTask.Custom.get. I found an export called `"
|
||||
, TerminalText.yellow portName
|
||||
, TerminalText.text "` but I expected its type to be function, but instead its type was: "
|
||||
, TerminalText.red incorrectPortType
|
||||
, TerminalText.red incorrectType
|
||||
]
|
||||
|> TerminalText.toString
|
||||
}
|
||||
ExportIsNotFunction
|
||||
)
|
||||
|
||||
else if errorKind == "MissingPortsFile" then
|
||||
else if errorKind == "MissingCustomBackendTaskFile" then
|
||||
FatalError.recoverable
|
||||
{ title = "Port Error"
|
||||
{ title = "Custom BackendTask Error"
|
||||
, body =
|
||||
[ TerminalText.text "Something went wrong in a call to BackendTask.Port.get. I couldn't find your port-data-source file. Be sure to create a 'port-data-source.ts' or 'port-data-source.js' file."
|
||||
[ TerminalText.text "Something went wrong in a call to BackendTask.Custom.get. I couldn't find your port-data-source file. Be sure to create a 'port-data-source.ts' or 'port-data-source.js' file."
|
||||
]
|
||||
|> TerminalText.toString
|
||||
}
|
||||
MissingPortsFile
|
||||
MissingCustomBackendTaskFile
|
||||
|> Decode.succeed
|
||||
|
||||
else if errorKind == "ErrorInPortsFile" then
|
||||
else if errorKind == "ErrorInCustomBackendTaskFile" then
|
||||
Decode.field "error" Decode.string
|
||||
|> Decode.maybe
|
||||
|> Decode.map (Maybe.withDefault "")
|
||||
|> Decode.map
|
||||
(\errorMessage ->
|
||||
FatalError.recoverable
|
||||
{ title = "Port Error"
|
||||
{ title = "Custom BackendTask Error"
|
||||
, body =
|
||||
[ TerminalText.text "Something went wrong in a call to BackendTask.Port.get. I couldn't import the port definitions file, because of this exception:\n\n"
|
||||
[ TerminalText.text "Something went wrong in a call to BackendTask.Custom.get. I couldn't import the port definitions file, because of this exception:\n\n"
|
||||
, TerminalText.red errorMessage
|
||||
, TerminalText.text "\n\nAre there syntax errors or exceptions thrown during import?"
|
||||
]
|
||||
|> TerminalText.toString
|
||||
}
|
||||
ErrorInPortsFile
|
||||
ErrorInCustomBackendTaskFile
|
||||
)
|
||||
|
||||
else if errorKind == "PortCallException" then
|
||||
else if errorKind == "CustomBackendTaskException" then
|
||||
Decode.field "error" Decode.value
|
||||
|> Decode.maybe
|
||||
|> Decode.map (Maybe.withDefault Encode.null)
|
||||
|> Decode.map
|
||||
(\portCallError ->
|
||||
FatalError.recoverable
|
||||
{ title = "Port Error"
|
||||
{ title = "Custom BackendTask Error"
|
||||
, body =
|
||||
[ TerminalText.text "Something went wrong in a call to BackendTask.Port.get. I was able to import the port definitions file, but when running it I encountered this exception:\n\n"
|
||||
[ TerminalText.text "Something went wrong in a call to BackendTask.Custom.get. I was able to import the port definitions file, but when running it I encountered this exception:\n\n"
|
||||
, TerminalText.red (Encode.encode 2 portCallError)
|
||||
, TerminalText.text "\n\nYou could add a `try`/`catch` in your `port-data-source` JavaScript code to handle that error."
|
||||
]
|
||||
|> TerminalText.toString
|
||||
}
|
||||
(PortCallException portCallError)
|
||||
(CustomBackendTaskException portCallError)
|
||||
)
|
||||
|
||||
else
|
||||
FatalError.recoverable
|
||||
{ title = "Port Error"
|
||||
{ title = "Custom BackendTask Error"
|
||||
, body =
|
||||
[ TerminalText.text "Something went wrong in a call to BackendTask.Port.get. I expected to find a port named `"
|
||||
[ TerminalText.text "Something went wrong in a call to BackendTask.Custom.get. I expected to find a port named `"
|
||||
, TerminalText.yellow portName
|
||||
, TerminalText.text "`."
|
||||
]
|
||||
|> TerminalText.toString
|
||||
}
|
||||
ErrorInPortsFile
|
||||
ErrorInCustomBackendTaskFile
|
||||
|> Decode.succeed
|
||||
)
|
||||
|> Decode.map Err
|
||||
@ -207,8 +207,8 @@ get portName input decoder =
|
||||
{-| -}
|
||||
type Error
|
||||
= Error
|
||||
| ErrorInPortsFile
|
||||
| MissingPortsFile
|
||||
| PortNotDefined { name : String }
|
||||
| PortCallException Decode.Value
|
||||
| ErrorInCustomBackendTaskFile
|
||||
| MissingCustomBackendTaskFile
|
||||
| CustomBackendTaskNotDefined { name : String }
|
||||
| CustomBackendTaskException Decode.Value
|
||||
| ExportIsNotFunction
|
Loading…
Reference in New Issue
Block a user