elm-pages 3.0.0-beta.8 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/README.md +11 -2
  2. package/adapter/netlify.js +207 -0
  3. package/codegen/{elm-pages-codegen.js → elm-pages-codegen.cjs} +2730 -2938
  4. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmi +0 -0
  5. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmo +0 -0
  6. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmo +0 -0
  7. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  8. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  9. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  10. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm.json +1 -1
  11. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1527 -422
  12. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +16840 -13653
  13. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  14. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +2 -2
  15. package/generator/dead-code-review/elm.json +9 -7
  16. package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +59 -10
  17. package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +52 -36
  18. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmi +0 -0
  19. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmo +0 -0
  20. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmi +0 -0
  21. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmo +0 -0
  22. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  23. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  24. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  25. package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -1
  26. package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1527 -422
  27. package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +25118 -21832
  28. package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  29. package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +2 -2
  30. package/generator/review/elm.json +10 -10
  31. package/generator/src/RouteBuilder.elm +93 -128
  32. package/generator/src/SharedTemplate.elm +8 -7
  33. package/generator/src/SiteConfig.elm +3 -2
  34. package/generator/src/basepath-middleware.js +3 -3
  35. package/generator/src/build.js +147 -63
  36. package/generator/src/cli.js +292 -88
  37. package/generator/src/codegen.js +29 -27
  38. package/generator/src/compatibility-key.js +3 -0
  39. package/generator/src/compile-elm.js +43 -26
  40. package/generator/src/config.js +2 -4
  41. package/generator/src/copy-dir.js +2 -2
  42. package/generator/src/dev-server.js +159 -92
  43. package/generator/src/dir-helpers.js +9 -26
  44. package/generator/src/elm-codegen.js +5 -4
  45. package/generator/src/elm-file-constants.js +2 -3
  46. package/generator/src/error-formatter.js +12 -11
  47. package/generator/src/file-helpers.js +3 -4
  48. package/generator/src/generate-template-module-connector.js +23 -23
  49. package/generator/src/init.js +9 -8
  50. package/generator/src/pre-render-html.js +10 -13
  51. package/generator/src/render-test.js +109 -0
  52. package/generator/src/render-worker.js +25 -28
  53. package/generator/src/render.js +321 -142
  54. package/generator/src/request-cache.js +265 -162
  55. package/generator/src/resolve-elm-module.js +64 -0
  56. package/generator/src/rewrite-client-elm-json.js +6 -5
  57. package/generator/src/rewrite-elm-json-help.js +56 -0
  58. package/generator/src/rewrite-elm-json.js +17 -7
  59. package/generator/src/route-codegen-helpers.js +16 -31
  60. package/generator/src/seo-renderer.js +12 -7
  61. package/generator/src/vite-utils.js +1 -2
  62. package/generator/static-code/elm-pages.js +10 -0
  63. package/generator/static-code/hmr.js +79 -13
  64. package/generator/template/app/Api.elm +3 -2
  65. package/generator/template/app/Effect.elm +155 -0
  66. package/generator/template/app/ErrorPage.elm +49 -6
  67. package/generator/template/app/Route/Blog/Slug_.elm +86 -0
  68. package/generator/template/app/Route/Greet.elm +107 -0
  69. package/generator/template/app/Route/Hello.elm +119 -0
  70. package/generator/template/app/Route/Index.elm +26 -25
  71. package/generator/template/app/Shared.elm +38 -39
  72. package/generator/template/app/Site.elm +4 -7
  73. package/generator/template/app/View.elm +9 -8
  74. package/generator/template/codegen/elm.codegen.json +18 -0
  75. package/generator/template/custom-backend-task.ts +3 -0
  76. package/generator/template/elm-pages.config.mjs +13 -0
  77. package/generator/template/elm-tooling.json +0 -3
  78. package/generator/template/elm.json +25 -20
  79. package/generator/template/index.ts +1 -2
  80. package/generator/template/netlify.toml +4 -1
  81. package/generator/template/package.json +10 -4
  82. package/generator/template/script/.elm-pages/compiled-ports/custom-backend-task.mjs +7 -0
  83. package/generator/template/script/custom-backend-task.ts +3 -0
  84. package/generator/template/script/elm.json +61 -0
  85. package/generator/template/script/src/AddRoute.elm +312 -0
  86. package/generator/template/script/src/Stars.elm +42 -0
  87. package/package.json +30 -27
  88. package/src/ApiRoute.elm +249 -85
  89. package/src/BackendTask/Custom.elm +325 -0
  90. package/src/BackendTask/Env.elm +90 -0
  91. package/src/{DataSource → BackendTask}/File.elm +171 -56
  92. package/src/{DataSource → BackendTask}/Glob.elm +136 -125
  93. package/src/BackendTask/Http.elm +679 -0
  94. package/src/{DataSource → BackendTask}/Internal/Glob.elm +1 -1
  95. package/src/BackendTask/Internal/Request.elm +69 -0
  96. package/src/BackendTask/Random.elm +79 -0
  97. package/src/BackendTask/Time.elm +47 -0
  98. package/src/BackendTask.elm +531 -0
  99. package/src/FatalError.elm +90 -0
  100. package/src/FormData.elm +21 -18
  101. package/src/Head/Seo.elm +4 -4
  102. package/src/Head.elm +237 -7
  103. package/src/Internal/ApiRoute.elm +7 -5
  104. package/src/Internal/Request.elm +84 -4
  105. package/src/PageServerResponse.elm +6 -1
  106. package/src/Pages/ConcurrentSubmission.elm +127 -0
  107. package/src/Pages/Form.elm +340 -0
  108. package/src/Pages/FormData.elm +19 -0
  109. package/src/Pages/GeneratorProgramConfig.elm +15 -0
  110. package/src/Pages/Internal/FatalError.elm +5 -0
  111. package/src/Pages/Internal/Msg.elm +93 -0
  112. package/src/Pages/Internal/NotFoundReason.elm +4 -4
  113. package/src/Pages/Internal/Platform/Cli.elm +629 -767
  114. package/src/Pages/Internal/Platform/CompatibilityKey.elm +6 -0
  115. package/src/Pages/Internal/Platform/Effect.elm +1 -2
  116. package/src/Pages/Internal/Platform/GeneratorApplication.elm +379 -0
  117. package/src/Pages/Internal/Platform/StaticResponses.elm +65 -276
  118. package/src/Pages/Internal/Platform/ToJsPayload.elm +6 -9
  119. package/src/Pages/Internal/Platform.elm +330 -203
  120. package/src/Pages/Internal/ResponseSketch.elm +2 -2
  121. package/src/Pages/Internal/Script.elm +17 -0
  122. package/src/Pages/Internal/StaticHttpBody.elm +35 -1
  123. package/src/Pages/Manifest.elm +52 -11
  124. package/src/Pages/Navigation.elm +85 -0
  125. package/src/Pages/PageUrl.elm +26 -12
  126. package/src/Pages/ProgramConfig.elm +32 -22
  127. package/src/Pages/Script.elm +166 -0
  128. package/src/Pages/SiteConfig.elm +3 -2
  129. package/src/Pages/StaticHttp/Request.elm +2 -2
  130. package/src/Pages/StaticHttpRequest.elm +23 -99
  131. package/src/Pages/Url.elm +3 -3
  132. package/src/PagesMsg.elm +88 -0
  133. package/src/QueryParams.elm +21 -172
  134. package/src/RenderRequest.elm +7 -7
  135. package/src/RequestsAndPending.elm +37 -20
  136. package/src/Result/Extra.elm +26 -0
  137. package/src/Scaffold/Form.elm +569 -0
  138. package/src/Scaffold/Route.elm +1431 -0
  139. package/src/Server/Request.elm +476 -1001
  140. package/src/Server/Response.elm +130 -36
  141. package/src/Server/Session.elm +181 -111
  142. package/src/Server/SetCookie.elm +80 -32
  143. package/src/Stub.elm +53 -0
  144. package/src/Test/Html/Internal/ElmHtml/ToString.elm +8 -9
  145. package/src/{Path.elm → UrlPath.elm} +33 -36
  146. package/generator/template/public/images/icon-png.png +0 -0
  147. package/src/DataSource/Env.elm +0 -38
  148. package/src/DataSource/Http.elm +0 -446
  149. package/src/DataSource/Internal/Request.elm +0 -20
  150. package/src/DataSource/Port.elm +0 -90
  151. package/src/DataSource.elm +0 -538
  152. package/src/Form/Field.elm +0 -717
  153. package/src/Form/FieldStatus.elm +0 -36
  154. package/src/Form/FieldView.elm +0 -417
  155. package/src/Form/FormData.elm +0 -22
  156. package/src/Form/Validation.elm +0 -391
  157. package/src/Form/Value.elm +0 -118
  158. package/src/Form.elm +0 -1683
  159. package/src/FormDecoder.elm +0 -102
  160. package/src/Pages/FormState.elm +0 -256
  161. package/src/Pages/Generate.elm +0 -1151
  162. package/src/Pages/Internal/Form.elm +0 -17
  163. package/src/Pages/Msg.elm +0 -79
  164. package/src/Pages/Transition.elm +0 -70
@@ -0,0 +1,569 @@
1
+ module Scaffold.Form exposing
2
+ ( Kind(..), provide, restArgsParser
3
+ , Context
4
+ , recordEncoder, fieldEncoder
5
+ )
6
+
7
+ {-| This module helps you with scaffolding a form in `elm-pages`, similar to how rails generators are used to scaffold out forms to
8
+ get up and running quickly with the starting point for a form with different field types. See also [`Scaffold.Route`](Scaffold-Route).
9
+
10
+ See the `AddRoute` script in the starter template for an example. It's usually easiest to modify that script as a starting
11
+ point rather than using this API from scratch.
12
+
13
+ Using the `AddRoute` script from the default starter template, you can run a command like this:
14
+
15
+ `npx elm-pages run AddRoute Profile.Username_.Edit first last bio:textarea dob:date` to generate a Route module `app/Route/Profile/Username_/Edit.elm`
16
+ with the wiring form a `Form`.
17
+
18
+ [Learn more about writing and running elm-pages Scripts for scaffolding](https://elm-pages.com/docs/elm-pages-scripts#scaffolding-a-route-module).
19
+
20
+ @docs Kind, provide, restArgsParser
21
+
22
+ @docs Context
23
+
24
+ @docs recordEncoder, fieldEncoder
25
+
26
+ -}
27
+
28
+ import Cli.Option
29
+ import Elm
30
+ import Elm.Annotation as Type
31
+ import Elm.Declare
32
+ import Elm.Op
33
+ import List.Extra
34
+ import Result.Extra
35
+
36
+
37
+ {-| -}
38
+ type Kind
39
+ = FieldInt
40
+ | FieldText
41
+ | FieldTextarea
42
+ | FieldFloat
43
+ | FieldTime
44
+ | FieldDate
45
+ | FieldCheckbox
46
+
47
+
48
+ {-| -}
49
+ type alias Context =
50
+ { errors : Elm.Expression
51
+ , submitting : Elm.Expression
52
+ , submitAttempted : Elm.Expression
53
+ , data : Elm.Expression
54
+ , expression : Elm.Expression
55
+ }
56
+
57
+
58
+ formWithFields : Bool -> List ( String, Kind ) -> ({ formState : { errors : Elm.Expression, submitting : Elm.Expression, submitAttempted : Elm.Expression, data : Elm.Expression, expression : Elm.Expression }, params : List { name : String, kind : Kind, param : Elm.Expression } } -> Elm.Expression) -> { declaration : Elm.Declaration, call : List Elm.Expression -> Elm.Expression, callFrom : List String -> List Elm.Expression -> Elm.Expression, value : List String -> Elm.Expression }
59
+ formWithFields elmCssView fields viewFn =
60
+ Elm.Declare.function "form"
61
+ []
62
+ (\_ ->
63
+ fields
64
+ |> List.foldl
65
+ (\( fieldName, kind ) chain ->
66
+ chain
67
+ |> Elm.Op.pipe
68
+ (formField fieldName
69
+ (case kind of
70
+ FieldText ->
71
+ formFieldText
72
+ |> Elm.Op.pipe (formFieldRequired (Elm.string "Required"))
73
+
74
+ FieldInt ->
75
+ formFieldInt { invalid = \_ -> Elm.string "" }
76
+ |> Elm.Op.pipe (formFieldRequired (Elm.string "Required"))
77
+
78
+ FieldTextarea ->
79
+ formFieldText
80
+ |> Elm.Op.pipe (formFieldRequired (Elm.string "Required"))
81
+ |> Elm.Op.pipe
82
+ (formFieldTextarea
83
+ { rows = Elm.nothing
84
+ , cols = Elm.nothing
85
+ }
86
+ )
87
+
88
+ FieldFloat ->
89
+ formFieldFloat { invalid = \_ -> Elm.string "" }
90
+ |> Elm.Op.pipe (formFieldRequired (Elm.string "Required"))
91
+
92
+ FieldTime ->
93
+ formFieldTime { invalid = \_ -> Elm.string "" }
94
+ |> Elm.Op.pipe (formFieldRequired (Elm.string "Required"))
95
+
96
+ FieldDate ->
97
+ formFieldDate { invalid = \_ -> Elm.string "" }
98
+ |> Elm.Op.pipe (formFieldRequired (Elm.string "Required"))
99
+
100
+ FieldCheckbox ->
101
+ formFieldCheckbox
102
+ )
103
+ )
104
+ )
105
+ (Elm.function (List.map fieldToParam fields)
106
+ (\params ->
107
+ Elm.record
108
+ [ ( "combine"
109
+ , params
110
+ |> List.foldl
111
+ (\fieldExpression chain ->
112
+ chain
113
+ |> Elm.Op.pipe (validationAndMap fieldExpression)
114
+ )
115
+ (Elm.val "ParsedForm"
116
+ |> Elm.Op.pipe validationSucceed
117
+ )
118
+ )
119
+ , ( "view"
120
+ , Elm.fn ( "formState", Nothing )
121
+ (\formState ->
122
+ let
123
+ mappedParams : List { name : String, kind : Kind, param : Elm.Expression }
124
+ mappedParams =
125
+ params
126
+ |> List.Extra.zip fields
127
+ |> List.map
128
+ (\( ( name, kind ), param ) ->
129
+ { name = name
130
+ , kind = kind
131
+ , param = param
132
+ }
133
+ )
134
+ in
135
+ viewFn
136
+ { formState =
137
+ { errors = formState |> Elm.get "errors"
138
+ , submitting = formState |> Elm.get "submitting"
139
+ , submitAttempted = formState |> Elm.get "submitAttempted"
140
+ , data = formState |> Elm.get "data"
141
+ , expression = formState
142
+ }
143
+ , params = mappedParams
144
+ }
145
+ )
146
+ )
147
+ ]
148
+ )
149
+ |> Elm.Op.pipe formInit
150
+ )
151
+ |> Elm.withType
152
+ (Type.namedWith [ "Form" ]
153
+ (if elmCssView then
154
+ "StyledHtmlForm"
155
+
156
+ else
157
+ "HtmlForm"
158
+ )
159
+ [ Type.string
160
+ , Type.named [] "ParsedForm"
161
+ , Type.var "input"
162
+ , Type.namedWith [ "PagesMsg" ] "PagesMsg" [ Type.named [] "Msg" ]
163
+ ]
164
+ )
165
+ )
166
+
167
+
168
+ fieldToParam : ( String, Kind ) -> ( String, Maybe Type.Annotation )
169
+ fieldToParam ( name, _ ) =
170
+ ( name, Nothing )
171
+
172
+
173
+ {-| This parser handles the following field types (or `text` if none is provided):
174
+
175
+ - `text`
176
+ - `textarea`
177
+ - `checkbox`
178
+ - `time`
179
+ - `date`
180
+
181
+ The naming convention follows the same naming as the HTML form field elements or attributes that are used to represent them.
182
+ In addition to using the appropriate field type, this will also give you an Elm type with the corresponding base type (like `Date` for `date` or `Bool` for `checkbox`).
183
+
184
+ -}
185
+ restArgsParser : Cli.Option.Option (List String) (List ( String, Kind )) Cli.Option.RestArgsOption
186
+ restArgsParser =
187
+ Cli.Option.restArgs "formFields"
188
+ |> Cli.Option.validateMap
189
+ (\items ->
190
+ items
191
+ |> List.map parseField
192
+ |> Result.Extra.combine
193
+ )
194
+
195
+
196
+ parseField : String -> Result String ( String, Kind )
197
+ parseField rawField =
198
+ case String.split ":" rawField of
199
+ [ fieldName ] ->
200
+ Ok ( fieldName, FieldText )
201
+
202
+ [ fieldName, fieldKind ] ->
203
+ (case fieldKind of
204
+ "text" ->
205
+ Ok FieldText
206
+
207
+ "textarea" ->
208
+ Ok FieldTextarea
209
+
210
+ "checkbox" ->
211
+ Ok FieldCheckbox
212
+
213
+ "time" ->
214
+ Ok FieldTime
215
+
216
+ "date" ->
217
+ Ok FieldDate
218
+
219
+ invalidFieldKind ->
220
+ Err ("I wasn't able to interpret the type of the field `" ++ fieldName ++ "` because it has an unexpected field type `" ++ invalidFieldKind ++ "`.")
221
+ )
222
+ |> Result.map (Tuple.pair fieldName)
223
+
224
+ _ ->
225
+ Err ("Unexpected form field format: `" ++ rawField ++ "`. Must be in format `first` or `checkin:date`.")
226
+
227
+
228
+ {-| -}
229
+ provide :
230
+ { fields : List ( String, Kind )
231
+ , elmCssView : Bool
232
+ , view :
233
+ { formState : Context
234
+ , params : List { name : String, kind : Kind, param : Elm.Expression }
235
+ }
236
+ -> Elm.Expression
237
+ }
238
+ ->
239
+ Maybe
240
+ { formHandlers : Elm.Expression
241
+ , form : Elm.Expression
242
+ , declarations : List Elm.Declaration
243
+ }
244
+ provide { fields, view, elmCssView } =
245
+ if List.isEmpty fields then
246
+ Nothing
247
+
248
+ else
249
+ let
250
+ form : { declaration : Elm.Declaration, call : List Elm.Expression -> Elm.Expression, callFrom : List String -> List Elm.Expression -> Elm.Expression, value : List String -> Elm.Expression }
251
+ form =
252
+ formWithFields elmCssView fields view
253
+
254
+ formHandlersDeclaration : { declaration : Elm.Declaration, call : List Elm.Expression -> Elm.Expression, callFrom : List String -> List Elm.Expression -> Elm.Expression, value : List String -> Elm.Expression }
255
+ formHandlersDeclaration =
256
+ -- TODO customizable formHandlers name?
257
+ Elm.Declare.function "formHandlers"
258
+ []
259
+ (\_ ->
260
+ initCombined (Elm.val "Action") (form.call [])
261
+ |> Elm.withType
262
+ (Type.namedWith [ "Form", "Handler" ]
263
+ "Handler"
264
+ [ Type.string
265
+ , Type.named [] "Action"
266
+ ]
267
+ )
268
+ )
269
+ in
270
+ Just
271
+ { formHandlers = formHandlersDeclaration.call []
272
+ , form = form.call []
273
+ , declarations =
274
+ [ formWithFields elmCssView fields view |> .declaration
275
+ , Elm.customType "Action"
276
+ [ Elm.variantWith "Action" [ Type.named [] "ParsedForm" ]
277
+ ]
278
+ , formHandlersDeclaration.declaration
279
+
280
+ -- TODO customize ParsedForm name?
281
+ , Elm.alias "ParsedForm"
282
+ (fields
283
+ |> List.map
284
+ (\( fieldName, kind ) ->
285
+ ( fieldName
286
+ , case kind of
287
+ FieldText ->
288
+ Type.string
289
+
290
+ FieldInt ->
291
+ Type.int
292
+
293
+ FieldTextarea ->
294
+ Type.string
295
+
296
+ FieldFloat ->
297
+ Type.float
298
+
299
+ FieldTime ->
300
+ Type.named [ "Form", "Field" ] "TimeOfDay"
301
+
302
+ FieldDate ->
303
+ Type.named [ "Date" ] "Date"
304
+
305
+ FieldCheckbox ->
306
+ Type.bool
307
+ )
308
+ )
309
+ |> Type.record
310
+ )
311
+ ]
312
+ }
313
+
314
+
315
+ validationAndMap : Elm.Expression -> Elm.Expression
316
+ validationAndMap andMapArg =
317
+ Elm.apply
318
+ (Elm.value
319
+ { importFrom = [ "Form", "Validation" ]
320
+ , name = "andMap"
321
+ , annotation = Nothing
322
+ }
323
+ )
324
+ [ andMapArg ]
325
+
326
+
327
+ validationSucceed : Elm.Expression
328
+ validationSucceed =
329
+ Elm.value
330
+ { importFrom = [ "Form", "Validation" ]
331
+ , name = "succeed"
332
+ , annotation = Nothing
333
+ }
334
+
335
+
336
+ formFieldText : Elm.Expression
337
+ formFieldText =
338
+ Elm.value
339
+ { importFrom = [ "Form", "Field" ]
340
+ , name = "text"
341
+ , annotation = Nothing
342
+ }
343
+
344
+
345
+ formFieldRequired : Elm.Expression -> Elm.Expression
346
+ formFieldRequired requiredArg =
347
+ Elm.apply
348
+ (Elm.value
349
+ { importFrom = [ "Form", "Field" ]
350
+ , name = "required"
351
+ , annotation = Nothing
352
+ }
353
+ )
354
+ [ requiredArg ]
355
+
356
+
357
+ formFieldInt : { invalid : Elm.Expression -> Elm.Expression } -> Elm.Expression
358
+ formFieldInt intArg =
359
+ Elm.apply
360
+ (Elm.value
361
+ { importFrom = [ "Form", "Field" ]
362
+ , name = "int"
363
+ , annotation =
364
+ Nothing
365
+ }
366
+ )
367
+ [ Elm.record
368
+ [ Tuple.pair
369
+ "invalid"
370
+ (Elm.functionReduced "intUnpack" intArg.invalid)
371
+ ]
372
+ ]
373
+
374
+
375
+ formFieldTextarea :
376
+ { rows : Elm.Expression, cols : Elm.Expression }
377
+ -> Elm.Expression
378
+ formFieldTextarea textareaArg =
379
+ Elm.apply
380
+ (Elm.value
381
+ { importFrom = [ "Form", "Field" ]
382
+ , name = "textarea"
383
+ , annotation = Nothing
384
+ }
385
+ )
386
+ [ Elm.record
387
+ [ Tuple.pair "rows" textareaArg.rows
388
+ , Tuple.pair "cols" textareaArg.cols
389
+ ]
390
+ ]
391
+
392
+
393
+ formFieldTime : { invalid : Elm.Expression -> Elm.Expression } -> Elm.Expression
394
+ formFieldTime timeArg =
395
+ Elm.apply
396
+ (Elm.value
397
+ { importFrom = [ "Form", "Field" ]
398
+ , name = "time"
399
+ , annotation = Nothing
400
+ }
401
+ )
402
+ [ Elm.record
403
+ [ Tuple.pair
404
+ "invalid"
405
+ (Elm.functionReduced "timeUnpack" timeArg.invalid)
406
+ ]
407
+ ]
408
+
409
+
410
+ formFieldDate : { invalid : Elm.Expression -> Elm.Expression } -> Elm.Expression
411
+ formFieldDate dateArg =
412
+ Elm.apply
413
+ (Elm.value
414
+ { importFrom = [ "Form", "Field" ]
415
+ , name = "date"
416
+ , annotation = Nothing
417
+ }
418
+ )
419
+ [ Elm.record
420
+ [ Tuple.pair
421
+ "invalid"
422
+ (Elm.functionReduced "dateUnpack" dateArg.invalid)
423
+ ]
424
+ ]
425
+
426
+
427
+ formFieldCheckbox : Elm.Expression
428
+ formFieldCheckbox =
429
+ Elm.value
430
+ { importFrom = [ "Form", "Field" ]
431
+ , name = "checkbox"
432
+ , annotation = Nothing
433
+ }
434
+
435
+
436
+ formFieldFloat : { invalid : Elm.Expression -> Elm.Expression } -> Elm.Expression
437
+ formFieldFloat floatArg =
438
+ Elm.apply
439
+ (Elm.value
440
+ { importFrom = [ "Form", "Field" ]
441
+ , name = "float"
442
+ , annotation = Nothing
443
+ }
444
+ )
445
+ [ Elm.record
446
+ [ Tuple.pair
447
+ "invalid"
448
+ (Elm.functionReduced "floatUnpack" floatArg.invalid)
449
+ ]
450
+ ]
451
+
452
+
453
+ formField : String -> Elm.Expression -> Elm.Expression
454
+ formField fieldArg fieldArg0 =
455
+ Elm.apply
456
+ (Elm.value
457
+ { importFrom = [ "Form" ]
458
+ , name = "field"
459
+ , annotation = Nothing
460
+ }
461
+ )
462
+ [ Elm.string fieldArg, fieldArg0 ]
463
+
464
+
465
+ formInit : Elm.Expression
466
+ formInit =
467
+ Elm.value
468
+ { importFrom = [ "Form" ]
469
+ , name = "form"
470
+ , annotation = Nothing
471
+ }
472
+ |> Elm.Op.pipe
473
+ (Elm.apply
474
+ (Elm.value
475
+ { importFrom = [ "Form" ]
476
+ , name = "hiddenKind"
477
+ , annotation = Nothing
478
+ }
479
+ )
480
+ [ Elm.tuple (Elm.string "kind") (Elm.string "regular")
481
+ , Elm.string "Expected kind."
482
+ ]
483
+ )
484
+
485
+
486
+ initCombined : Elm.Expression -> Elm.Expression -> Elm.Expression
487
+ initCombined initCombinedArg initCombinedArg0 =
488
+ Elm.apply
489
+ (Elm.value
490
+ { importFrom = [ "Form", "Handler" ]
491
+ , name = "init"
492
+ , annotation = Nothing
493
+ }
494
+ )
495
+ [ initCombinedArg, initCombinedArg0 ]
496
+
497
+
498
+ {-| Generate a JSON Encoder for the form fields. This can be helpful for sending the validated form data through a
499
+ BackendTask.Custom or to an external API from your scaffolded Route Module code.
500
+ -}
501
+ recordEncoder : Elm.Expression -> List ( String, Kind ) -> Elm.Expression
502
+ recordEncoder record fields =
503
+ fields
504
+ |> List.map
505
+ (\( field, kind ) ->
506
+ Elm.tuple
507
+ (Elm.string field)
508
+ (fieldEncoder record field kind)
509
+ )
510
+ |> Elm.list
511
+ |> List.singleton
512
+ |> Elm.apply
513
+ (Elm.value
514
+ { importFrom = [ "Json", "Encode" ]
515
+ , name = "object"
516
+ , annotation =
517
+ Just
518
+ (Type.function
519
+ [ Type.list
520
+ (Type.tuple
521
+ Type.string
522
+ (Type.namedWith [ "Json", "Encode" ] "Value" [])
523
+ )
524
+ ]
525
+ (Type.namedWith [ "Json", "Encode" ] "Value" [])
526
+ )
527
+ }
528
+ )
529
+
530
+
531
+ {-| A lower-level, more granular version of `recordEncoder` - lets you generate a JSON Encoder `Expression` for an individual Field rather than a group of Fields.
532
+ -}
533
+ fieldEncoder : Elm.Expression -> String -> Kind -> Elm.Expression
534
+ fieldEncoder record name kind =
535
+ Elm.apply
536
+ (case kind of
537
+ FieldInt ->
538
+ encoder "int"
539
+
540
+ FieldText ->
541
+ encoder "string"
542
+
543
+ FieldTextarea ->
544
+ encoder "string"
545
+
546
+ FieldFloat ->
547
+ encoder "float"
548
+
549
+ FieldTime ->
550
+ -- TODO fix time encoder
551
+ encoder "int"
552
+
553
+ FieldDate ->
554
+ -- TODO fix date encoder
555
+ encoder "int"
556
+
557
+ FieldCheckbox ->
558
+ encoder "bool"
559
+ )
560
+ [ Elm.get name record ]
561
+
562
+
563
+ encoder : String -> Elm.Expression
564
+ encoder name =
565
+ Elm.value
566
+ { importFrom = [ "Json", "Encode" ]
567
+ , name = name
568
+ , annotation = Nothing
569
+ }