elm-pages 3.0.0-beta.4 → 3.0.0-beta.41

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 (148) hide show
  1. package/README.md +10 -1
  2. package/adapter/netlify.js +207 -0
  3. package/codegen/{elm-pages-codegen.js → elm-pages-codegen.cjs} +2828 -2933
  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 +1447 -342
  12. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +17004 -13817
  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 +4 -4
  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 +1447 -342
  27. package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +25025 -21739
  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 +4 -4
  30. package/generator/review/elm.json +10 -10
  31. package/generator/src/RouteBuilder.elm +121 -114
  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 +209 -92
  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 +39 -0
  41. package/generator/src/copy-dir.js +2 -2
  42. package/generator/src/dev-server.js +176 -138
  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 +39 -28
  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 +77 -0
  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 +6 -5
  65. package/generator/template/app/Effect.elm +123 -0
  66. package/generator/template/app/ErrorPage.elm +37 -6
  67. package/generator/template/app/Route/Index.elm +17 -10
  68. package/generator/template/app/Shared.elm +24 -47
  69. package/generator/template/app/Site.elm +19 -6
  70. package/generator/template/app/View.elm +1 -8
  71. package/generator/template/elm-tooling.json +0 -3
  72. package/generator/template/elm.json +32 -24
  73. package/generator/template/package.json +10 -4
  74. package/package.json +30 -27
  75. package/src/ApiRoute.elm +199 -61
  76. package/src/BackendTask/Custom.elm +325 -0
  77. package/src/BackendTask/Env.elm +90 -0
  78. package/src/{DataSource → BackendTask}/File.elm +171 -56
  79. package/src/{DataSource → BackendTask}/Glob.elm +136 -125
  80. package/src/BackendTask/Http.elm +679 -0
  81. package/src/{DataSource → BackendTask}/Internal/Glob.elm +1 -1
  82. package/src/BackendTask/Internal/Request.elm +69 -0
  83. package/src/BackendTask/Random.elm +79 -0
  84. package/src/BackendTask/Time.elm +47 -0
  85. package/src/BackendTask.elm +531 -0
  86. package/src/FatalError.elm +90 -0
  87. package/src/Head/Seo.elm +4 -4
  88. package/src/Head.elm +237 -7
  89. package/src/HtmlPrinter.elm +7 -3
  90. package/src/Internal/ApiRoute.elm +7 -5
  91. package/src/PageServerResponse.elm +6 -1
  92. package/src/Pages/ConcurrentSubmission.elm +127 -0
  93. package/src/Pages/Form.elm +340 -0
  94. package/src/Pages/FormData.elm +18 -0
  95. package/src/Pages/GeneratorProgramConfig.elm +15 -0
  96. package/src/Pages/Internal/FatalError.elm +5 -0
  97. package/src/Pages/Internal/Msg.elm +93 -0
  98. package/src/Pages/Internal/NotFoundReason.elm +4 -4
  99. package/src/Pages/Internal/Platform/Cli.elm +617 -768
  100. package/src/Pages/Internal/Platform/CompatibilityKey.elm +6 -0
  101. package/src/Pages/Internal/Platform/Effect.elm +1 -2
  102. package/src/Pages/Internal/Platform/GeneratorApplication.elm +379 -0
  103. package/src/Pages/Internal/Platform/StaticResponses.elm +65 -276
  104. package/src/Pages/Internal/Platform/ToJsPayload.elm +6 -9
  105. package/src/Pages/Internal/Platform.elm +359 -225
  106. package/src/Pages/Internal/ResponseSketch.elm +2 -2
  107. package/src/Pages/Internal/Script.elm +17 -0
  108. package/src/Pages/Internal/StaticHttpBody.elm +35 -1
  109. package/src/Pages/Manifest.elm +52 -11
  110. package/src/Pages/Navigation.elm +87 -0
  111. package/src/Pages/PageUrl.elm +26 -12
  112. package/src/Pages/ProgramConfig.elm +35 -23
  113. package/src/Pages/Script.elm +166 -0
  114. package/src/Pages/SiteConfig.elm +3 -2
  115. package/src/Pages/StaticHttp/Request.elm +2 -2
  116. package/src/Pages/StaticHttpRequest.elm +23 -99
  117. package/src/Pages/Url.elm +3 -3
  118. package/src/PagesMsg.elm +88 -0
  119. package/src/QueryParams.elm +21 -172
  120. package/src/RenderRequest.elm +7 -7
  121. package/src/RequestsAndPending.elm +37 -20
  122. package/src/Result/Extra.elm +26 -0
  123. package/src/Scaffold/Form.elm +569 -0
  124. package/src/Scaffold/Route.elm +1411 -0
  125. package/src/Server/Request.elm +74 -72
  126. package/src/Server/Session.elm +62 -42
  127. package/src/Server/SetCookie.elm +80 -32
  128. package/src/Stub.elm +53 -0
  129. package/src/Test/Html/Internal/ElmHtml/ToString.elm +8 -9
  130. package/src/{Path.elm → UrlPath.elm} +33 -36
  131. package/src/DataSource/Env.elm +0 -38
  132. package/src/DataSource/Http.elm +0 -446
  133. package/src/DataSource/Internal/Request.elm +0 -20
  134. package/src/DataSource/Port.elm +0 -90
  135. package/src/DataSource.elm +0 -538
  136. package/src/Form/Field.elm +0 -717
  137. package/src/Form/FieldStatus.elm +0 -36
  138. package/src/Form/FieldView.elm +0 -417
  139. package/src/Form/FormData.elm +0 -22
  140. package/src/Form/Validation.elm +0 -391
  141. package/src/Form/Value.elm +0 -118
  142. package/src/Form.elm +0 -1683
  143. package/src/FormDecoder.elm +0 -102
  144. package/src/Pages/FormState.elm +0 -256
  145. package/src/Pages/Generate.elm +0 -800
  146. package/src/Pages/Internal/Form.elm +0 -17
  147. package/src/Pages/Msg.elm +0 -79
  148. 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-v3.netlify.app/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
+ }