Generate fetcher modules

This commit is contained in:
Dillon Kearns 2022-05-03 14:36:08 -07:00
parent ad8e7b9456
commit fa10ce7eaf
4 changed files with 99 additions and 51 deletions

View File

@ -1,49 +0,0 @@
module Fetcher.Route.Signup exposing (load, submit)
import Bytes.Decode
import Effect exposing (Effect)
import FormDecoder
import Http
import Route.Signup
load : Effect (Result Http.Error Route.Signup.Data)
load =
Http.request
{ expect = Http.expectBytes identity decodeData
, tracker = Nothing
, body = Http.emptyBody
, headers = []
, url = "/signup"
, method = "GET"
, timeout = Nothing
}
|> Effect.fromCmd
submit : { headers : List ( String, String ), formFields : List ( String, String ) } -> Effect (Result Http.Error Route.Signup.ActionData)
submit options =
let
{ contentType, body } =
FormDecoder.encodeFormData options.formFields
in
Http.request
{ expect = Http.expectBytes identity decodeActionData
, tracker = Nothing
, body = Http.stringBody contentType body
, headers = options.headers |> List.map (\( key, value ) -> Http.header key value)
, url = "/signup/content.dat"
, method = "POST"
, timeout = Nothing
}
|> Effect.fromCmd
decodeData : Bytes.Decode.Decoder Route.Signup.Data
decodeData =
Route.Signup.w3_decode_Data
decodeActionData : Bytes.Decode.Decoder Route.Signup.ActionData
decodeActionData =
Route.Signup.w3_decode_ActionData

View File

@ -3,7 +3,7 @@ module Route.Hello exposing (ActionData, Data, Model, Msg, route)
import DataSource exposing (DataSource)
import Effect exposing (Effect)
import ErrorPage exposing (ErrorPage)
import Fetcher.Route.Signup
import Fetcher.Signup
import Head
import Head.Seo as Seo
import Html
@ -54,7 +54,7 @@ init :
-> ( Model, Effect Msg )
init maybePageUrl sharedModel static =
( {}
, Fetcher.Route.Signup.submit
, Fetcher.Signup.submit
{ headers = []
, formFields =
[ ( "first", "Jane" )

View File

@ -20,6 +20,7 @@ async function generate(basePath) {
const browserCode = generateTemplateModuleConnector(basePath, "browser");
ensureDirSync("./elm-stuff");
ensureDirSync("./.elm-pages");
ensureDirSync("./gen");
ensureDirSync("./elm-stuff/elm-pages/.elm-pages");
const uiFileContent = elmPagesUiFile();
@ -49,12 +50,27 @@ async function generate(basePath) {
),
fs.promises.writeFile("./.elm-pages/Main.elm", browserCode.mainModule),
fs.promises.writeFile("./.elm-pages/Route.elm", browserCode.routesModule),
writeFetcherModules("./.elm-pages", browserCode.fetcherModules),
writeFetcherModules(
"./elm-stuff/elm-pages/.elm-pages/",
browserCode.fetcherModules
),
// write modified elm.json to elm-stuff/elm-pages/
copyModifiedElmJson(),
...(await listFiles("./Pages/Internal")).map(copyToBoth),
]);
}
function writeFetcherModules(basePath, fetcherData) {
Promise.all(
fetcherData.map(([name, fileContent]) => {
let filePath = path.join(basePath, `/Fetcher/${name.join("/")}.elm`);
ensureDirSync(path.dirname(filePath));
return fs.promises.writeFile(filePath, fileContent);
})
);
}
async function newCopyBoth(modulePath) {
await fs.promises.copyFile(
path.join(__dirname, modulePath),

View File

@ -1036,6 +1036,9 @@ redirectTo route =
|> toString
|> Server.Response.temporaryRedirect
`,
fetcherModules: templates.map((name) => {
return [name, fetcherModule(name)];
}),
};
}
@ -1219,6 +1222,84 @@ function prefixThing(param) {
}
}
function fetcherModule(name) {
let moduleName = name.join(".");
// TODO need to account for splat routes/etc.
let modulePath = name.join("/");
let fetcherPath = routeHelpers
.parseRouteParamsWithStatic(name)
.map((param) => {
switch (param.kind) {
case "static": {
return param.name === "Index"
? `[]`
: `[ "${camelToKebab(param.name)}" ]`;
}
case "optional": {
return `Pages.Internal.Router.maybeToList params.${param.name}`;
}
case "required-splat": {
return `Pages.Internal.Router.nonEmptyToList params.${param.name}`;
}
case "dynamic": {
return `[ params.${param.name} ]`;
}
case "optional-splat": {
return `params.${param.name}`;
}
}
})
.join(", ");
return `module Fetcher.${moduleName} exposing (load, submit)
{-| -}
import Effect exposing (Effect)
import FormDecoder
import Http
import Route.${moduleName}
{-| -}
load : Effect (Result Http.Error Route.${moduleName}.Data)
load =
Http.request
{ expect = Http.expectBytes identity Route.${moduleName}.w3_decode_Data
, tracker = Nothing
, body = Http.emptyBody
, headers = []
, url = ${fetcherPath} |> String.join "/"
, method = "GET"
, timeout = Nothing
}
|> Effect.fromCmd
{-| -}
submit :
{ headers : List ( String, String )
, formFields : List ( String, String )
}
-> Effect (Result Http.Error Route.${moduleName}.ActionData)
submit options =
let
{ contentType, body } =
FormDecoder.encodeFormData options.formFields
in
Http.request
{ expect = Http.expectBytes identity Route.${moduleName}.w3_decode_ActionData
, tracker = Nothing
, body = Http.stringBody contentType body
, headers = options.headers |> List.map (\\( key, value ) -> Http.header key value)
, url = ${fetcherPath} ++ [ "content.dat" ] |> String.join "/"
, method = "POST"
, timeout = Nothing
}
|> Effect.fromCmd
`;
}
/**
* @param {string[]} name
*/