elm-pages 3.0.12 → 3.0.14
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.
- package/README.md +2 -26
- package/codegen/elm-pages-codegen.cjs +10741 -10302
- package/generator/src/build.js +15 -5
- package/generator/src/cli.js +3 -5
- package/generator/src/compatibility-key.js +2 -2
- package/generator/src/dev-server.js +3 -0
- package/generator/src/render.js +681 -50
- package/generator/src/request-cache.js +13 -6
- package/generator/src/spinnies/index.js +200 -0
- package/generator/src/spinnies/utils.js +123 -0
- package/generator/src/validate-stream.js +25 -0
- package/generator/template/elm.json +4 -4
- package/generator/template/package.json +6 -6
- package/generator/template/script/elm.json +7 -8
- package/package.json +4 -3
- package/src/BackendTask/Custom.elm +38 -0
- package/src/BackendTask/Do.elm +233 -0
- package/src/BackendTask/File.elm +24 -9
- package/src/BackendTask/Glob.elm +208 -25
- package/src/BackendTask/Http.elm +32 -21
- package/src/BackendTask/Internal/Glob.elm +16 -4
- package/src/BackendTask/Stream.elm +1179 -0
- package/src/BackendTask.elm +214 -7
- package/src/Pages/Internal/Platform/CompatibilityKey.elm +1 -1
- package/src/Pages/Internal/Platform.elm +11 -2
- package/src/Pages/Script/Spinner.elm +505 -0
- package/src/Pages/Script.elm +199 -2
- package/src/Pages/StaticHttp/Request.elm +7 -0
- package/src/RequestsAndPending.elm +1 -1
- package/src/Scaffold/Form.elm +2 -3
- package/src/TerminalText.elm +8 -0
- package/src/Vendored/Result/Extra.elm +75 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmi +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmo +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmi +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmo +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmi +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmo +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmi +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmo +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/lock +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm.json +0 -1
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +0 -7900
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +0 -28657
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +0 -110
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +0 -187
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/package.json +0 -1
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/src/Reporter.elm +0 -26
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/src/Runner.elm +0 -62
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolationsTest.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolationsTest.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/lock +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm.json +0 -1
- package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +0 -7900
- package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +0 -30511
- package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +0 -110
- package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +0 -187
- package/generator/review/elm-stuff/tests-0.19.1/js/package.json +0 -1
- package/generator/review/elm-stuff/tests-0.19.1/src/Reporter.elm +0 -26
- package/generator/review/elm-stuff/tests-0.19.1/src/Runner.elm +0 -62
- package/src/Result/Extra.elm +0 -26
package/src/BackendTask/Glob.elm
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
module BackendTask.Glob exposing
|
|
2
2
|
( Glob
|
|
3
3
|
, capture, match
|
|
4
|
+
, fromString, fromStringWithOptions
|
|
4
5
|
, captureFilePath
|
|
5
6
|
, wildcard, recursiveWildcard
|
|
6
7
|
, int, digits
|
|
8
|
+
, FileStats, captureStats
|
|
7
9
|
, expectUniqueMatch, expectUniqueMatchFromList
|
|
8
10
|
, literal
|
|
9
11
|
, map, succeed
|
|
@@ -97,7 +99,8 @@ Let's try our blogPostsGlob from before, but change every `match` to `capture`.
|
|
|
97
99
|
import BackendTask exposing (BackendTask)
|
|
98
100
|
|
|
99
101
|
blogPostsGlob :
|
|
100
|
-
BackendTask
|
|
102
|
+
BackendTask
|
|
103
|
+
error
|
|
101
104
|
(List
|
|
102
105
|
{ filePath : String
|
|
103
106
|
, slug : String
|
|
@@ -136,6 +139,12 @@ and error prone. That's what the [`captureFilePath`](#captureFilePath) helper is
|
|
|
136
139
|
|
|
137
140
|
## Reading matching files
|
|
138
141
|
|
|
142
|
+
You can use the less powerful but more familiar and terse `fromString` helpers if you only need to find matching file paths
|
|
143
|
+
(but don't care about parsing out parts of the paths). This is helpful when you need a reference to matching files and
|
|
144
|
+
you are only using the file paths to then read or do scripting tasks with those paths.
|
|
145
|
+
|
|
146
|
+
@docs fromString, fromStringWithOptions
|
|
147
|
+
|
|
139
148
|
@docs captureFilePath
|
|
140
149
|
|
|
141
150
|
In many cases you will want to take the matching files from a `Glob` and then read the body or frontmatter from matching files.
|
|
@@ -198,6 +207,13 @@ That will give us
|
|
|
198
207
|
@docs int, digits
|
|
199
208
|
|
|
200
209
|
|
|
210
|
+
## Capturing File Stats
|
|
211
|
+
|
|
212
|
+
You can access a file's stats including timestamps when the file was created and modified, and file size.
|
|
213
|
+
|
|
214
|
+
@docs FileStats, captureStats
|
|
215
|
+
|
|
216
|
+
|
|
201
217
|
## Matching a Specific Number of Files
|
|
202
218
|
|
|
203
219
|
@docs expectUniqueMatch, expectUniqueMatchFromList
|
|
@@ -235,6 +251,7 @@ import FatalError exposing (FatalError)
|
|
|
235
251
|
import Json.Decode as Decode
|
|
236
252
|
import Json.Encode as Encode
|
|
237
253
|
import List.Extra
|
|
254
|
+
import Time
|
|
238
255
|
|
|
239
256
|
|
|
240
257
|
{-| A pattern to match local files and capture parts of the path into a nice Elm data type.
|
|
@@ -296,9 +313,9 @@ For example, you could take a date and parse it.
|
|
|
296
313
|
map : (a -> b) -> Glob a -> Glob b
|
|
297
314
|
map mapFn (Glob pattern applyCapture) =
|
|
298
315
|
Glob pattern
|
|
299
|
-
(\fullPath captures ->
|
|
316
|
+
(\fileStats fullPath captures ->
|
|
300
317
|
captures
|
|
301
|
-
|> applyCapture fullPath
|
|
318
|
+
|> applyCapture fileStats fullPath
|
|
302
319
|
|> Tuple.mapFirst mapFn
|
|
303
320
|
)
|
|
304
321
|
|
|
@@ -307,13 +324,13 @@ map mapFn (Glob pattern applyCapture) =
|
|
|
307
324
|
-}
|
|
308
325
|
succeed : constructor -> Glob constructor
|
|
309
326
|
succeed constructor =
|
|
310
|
-
Glob "" (\_ captures -> ( constructor, captures ))
|
|
327
|
+
Glob "" (\_ _ captures -> ( constructor, captures ))
|
|
311
328
|
|
|
312
329
|
|
|
313
330
|
fullFilePath : Glob String
|
|
314
331
|
fullFilePath =
|
|
315
332
|
Glob ""
|
|
316
|
-
(\fullPath captures ->
|
|
333
|
+
(\_ fullPath captures ->
|
|
317
334
|
( fullPath, captures )
|
|
318
335
|
)
|
|
319
336
|
|
|
@@ -324,7 +341,8 @@ fullFilePath =
|
|
|
324
341
|
import BackendTask.Glob as Glob
|
|
325
342
|
|
|
326
343
|
blogPosts :
|
|
327
|
-
BackendTask
|
|
344
|
+
BackendTask
|
|
345
|
+
error
|
|
328
346
|
(List
|
|
329
347
|
{ filePath : String
|
|
330
348
|
, slug : String
|
|
@@ -354,6 +372,75 @@ captureFilePath =
|
|
|
354
372
|
capture fullFilePath
|
|
355
373
|
|
|
356
374
|
|
|
375
|
+
{-| The information about a file that you can access when you use [`captureStats`](#captureStats).
|
|
376
|
+
-}
|
|
377
|
+
type alias FileStats =
|
|
378
|
+
{ fullPath : String
|
|
379
|
+
, sizeInBytes : Int
|
|
380
|
+
, lastContentChange : Time.Posix
|
|
381
|
+
, lastAccess : Time.Posix
|
|
382
|
+
, lastFileChange : Time.Posix
|
|
383
|
+
, createdAt : Time.Posix
|
|
384
|
+
, isDirectory : Bool
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
{-|
|
|
389
|
+
|
|
390
|
+
import BackendTask.Glob as Glob
|
|
391
|
+
|
|
392
|
+
recentlyChangedRouteModules : BackendTask error (List ( Time.Posix, List String ))
|
|
393
|
+
recentlyChangedRouteModules =
|
|
394
|
+
Glob.succeed
|
|
395
|
+
(\fileStats directoryName fileName ->
|
|
396
|
+
( fileStats.lastContentChange
|
|
397
|
+
, directoryName ++ [ fileName ]
|
|
398
|
+
)
|
|
399
|
+
)
|
|
400
|
+
|> Glob.captureStats
|
|
401
|
+
|> Glob.match (Glob.literal "app/Route/")
|
|
402
|
+
|> Glob.capture Glob.recursiveWildcard
|
|
403
|
+
|> Glob.match (Glob.literal "/")
|
|
404
|
+
|> Glob.capture Glob.wildcard
|
|
405
|
+
|> Glob.match (Glob.literal ".elm")
|
|
406
|
+
|> Glob.toBackendTask
|
|
407
|
+
|> BackendTask.map
|
|
408
|
+
(\entries ->
|
|
409
|
+
entries
|
|
410
|
+
|> List.sortBy (\( lastChanged, _ ) -> Time.posixToMillis lastChanged)
|
|
411
|
+
|> List.reverse
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
-}
|
|
415
|
+
captureStats : Glob (FileStats -> value) -> Glob value
|
|
416
|
+
captureStats =
|
|
417
|
+
capture
|
|
418
|
+
(Glob ""
|
|
419
|
+
(\fileStats _ captures ->
|
|
420
|
+
( fileStats
|
|
421
|
+
|> Maybe.withDefault
|
|
422
|
+
{ fullPath = "ERROR"
|
|
423
|
+
, sizeInBytes = -1
|
|
424
|
+
, lastContentChange = Time.millisToPosix 0
|
|
425
|
+
, lastAccess = Time.millisToPosix 0
|
|
426
|
+
, lastFileChange = Time.millisToPosix 0
|
|
427
|
+
, createdAt = Time.millisToPosix 0
|
|
428
|
+
, isDirectory = True
|
|
429
|
+
}
|
|
430
|
+
, captures
|
|
431
|
+
)
|
|
432
|
+
)
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
fullStats : Glob String
|
|
437
|
+
fullStats =
|
|
438
|
+
Glob ""
|
|
439
|
+
(\_ fullPath captures ->
|
|
440
|
+
( fullPath, captures )
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
|
|
357
444
|
{-| Matches anything except for a `/` in a file path. You may be familiar with this syntax from shells like bash
|
|
358
445
|
where you can run commands like `rm client/*.js` to remove all `.js` files in the `client` directory.
|
|
359
446
|
|
|
@@ -410,7 +497,7 @@ will match _within_ a path part (think between the slashes of a file path). `rec
|
|
|
410
497
|
wildcard : Glob String
|
|
411
498
|
wildcard =
|
|
412
499
|
Glob "*"
|
|
413
|
-
(\_ captures ->
|
|
500
|
+
(\_ _ captures ->
|
|
414
501
|
case captures of
|
|
415
502
|
first :: rest ->
|
|
416
503
|
( first, rest )
|
|
@@ -428,7 +515,7 @@ See [`int`](#int) for a convenience function to get an Int value instead of a St
|
|
|
428
515
|
digits : Glob String
|
|
429
516
|
digits =
|
|
430
517
|
Glob "([0-9]+)"
|
|
431
|
-
(\_ captures ->
|
|
518
|
+
(\_ _ captures ->
|
|
432
519
|
case captures of
|
|
433
520
|
first :: rest ->
|
|
434
521
|
( first, rest )
|
|
@@ -573,7 +660,7 @@ This is usually not what is intended. Using `recursiveWildcard` is usually follo
|
|
|
573
660
|
recursiveWildcard : Glob (List String)
|
|
574
661
|
recursiveWildcard =
|
|
575
662
|
Glob "**"
|
|
576
|
-
(\_ captures ->
|
|
663
|
+
(\_ _ captures ->
|
|
577
664
|
case captures of
|
|
578
665
|
first :: rest ->
|
|
579
666
|
( first, rest )
|
|
@@ -593,7 +680,7 @@ zeroOrMore matchers =
|
|
|
593
680
|
++ (matchers |> String.join "|")
|
|
594
681
|
++ ")"
|
|
595
682
|
)
|
|
596
|
-
(\_ captures ->
|
|
683
|
+
(\_ _ captures ->
|
|
597
684
|
case captures of
|
|
598
685
|
first :: rest ->
|
|
599
686
|
( if first == "" then
|
|
@@ -636,7 +723,7 @@ blogPosts =
|
|
|
636
723
|
-}
|
|
637
724
|
literal : String -> Glob String
|
|
638
725
|
literal string =
|
|
639
|
-
Glob string (\_ captures -> ( string, captures ))
|
|
726
|
+
Glob string (\_ _ captures -> ( string, captures ))
|
|
640
727
|
|
|
641
728
|
|
|
642
729
|
{-| Adds on to the glob pattern, but does not capture it in the resulting Elm match value. That means this changes which
|
|
@@ -649,17 +736,17 @@ match : Glob a -> Glob value -> Glob value
|
|
|
649
736
|
match (Glob matcherPattern apply1) (Glob pattern apply2) =
|
|
650
737
|
Glob
|
|
651
738
|
(pattern ++ matcherPattern)
|
|
652
|
-
(\fullPath captures ->
|
|
739
|
+
(\fileStats_ fullPath captures ->
|
|
653
740
|
let
|
|
654
741
|
( _, captured1 ) =
|
|
655
742
|
-- apply to make sure we drop from the captures list for all capturing patterns
|
|
656
743
|
-- but don't change the return value
|
|
657
744
|
captures
|
|
658
|
-
|> apply1 fullPath
|
|
745
|
+
|> apply1 fileStats_ fullPath
|
|
659
746
|
|
|
660
747
|
( applied2, captured2 ) =
|
|
661
748
|
captured1
|
|
662
|
-
|> apply2 fullPath
|
|
749
|
+
|> apply2 fileStats_ fullPath
|
|
663
750
|
in
|
|
664
751
|
( applied2
|
|
665
752
|
, captured2
|
|
@@ -717,15 +804,15 @@ capture : Glob a -> Glob (a -> value) -> Glob value
|
|
|
717
804
|
capture (Glob matcherPattern apply1) (Glob pattern apply2) =
|
|
718
805
|
Glob
|
|
719
806
|
(pattern ++ matcherPattern)
|
|
720
|
-
(\fullPath captures ->
|
|
807
|
+
(\fileStats fullPath captures ->
|
|
721
808
|
let
|
|
722
809
|
( applied1, captured1 ) =
|
|
723
810
|
captures
|
|
724
|
-
|> apply1 fullPath
|
|
811
|
+
|> apply1 fileStats fullPath
|
|
725
812
|
|
|
726
813
|
( applied2, captured2 ) =
|
|
727
814
|
captured1
|
|
728
|
-
|> apply2 fullPath
|
|
815
|
+
|> apply2 fileStats fullPath
|
|
729
816
|
in
|
|
730
817
|
( applied1 |> applied2
|
|
731
818
|
, captured2
|
|
@@ -828,7 +915,7 @@ oneOf ( defaultMatch, otherMatchers ) =
|
|
|
828
915
|
++ (allMatchers |> List.map Tuple.first |> String.join ",")
|
|
829
916
|
++ "}"
|
|
830
917
|
)
|
|
831
|
-
(\_ captures ->
|
|
918
|
+
(\_ _ captures ->
|
|
832
919
|
case captures of
|
|
833
920
|
match_ :: rest ->
|
|
834
921
|
( allMatchers
|
|
@@ -862,7 +949,7 @@ atLeastOne ( defaultMatch, otherMatchers ) =
|
|
|
862
949
|
++ (allMatchers |> List.map Tuple.first |> String.join "|")
|
|
863
950
|
++ ")"
|
|
864
951
|
)
|
|
865
|
-
(\_ captures ->
|
|
952
|
+
(\_ _ captures ->
|
|
866
953
|
case captures of
|
|
867
954
|
match_ :: rest ->
|
|
868
955
|
( --( allMatchers
|
|
@@ -956,8 +1043,27 @@ encodeOptions options =
|
|
|
956
1043
|
, ( "caseSensitiveMatch", Encode.bool options.caseSensitiveMatch ) |> Just
|
|
957
1044
|
, ( "gitignore", Encode.bool options.gitignore ) |> Just
|
|
958
1045
|
, options.maxDepth |> Maybe.map (\depth -> ( "deep", Encode.int depth ))
|
|
959
|
-
, ( "onlyFiles"
|
|
960
|
-
|
|
1046
|
+
, ( "onlyFiles"
|
|
1047
|
+
, (if options.include == FilesAndFolders then
|
|
1048
|
+
False
|
|
1049
|
+
|
|
1050
|
+
else
|
|
1051
|
+
options.include == OnlyFiles
|
|
1052
|
+
)
|
|
1053
|
+
|> Encode.bool
|
|
1054
|
+
)
|
|
1055
|
+
|> Just
|
|
1056
|
+
, ( "onlyDirectories"
|
|
1057
|
+
, (if options.include == FilesAndFolders then
|
|
1058
|
+
False
|
|
1059
|
+
|
|
1060
|
+
else
|
|
1061
|
+
options.include == OnlyFolders
|
|
1062
|
+
)
|
|
1063
|
+
|> Encode.bool
|
|
1064
|
+
)
|
|
1065
|
+
|> Just
|
|
1066
|
+
, ( "stats", Encode.bool True ) |> Just
|
|
961
1067
|
]
|
|
962
1068
|
|> List.filterMap identity
|
|
963
1069
|
|> Encode.object
|
|
@@ -975,16 +1081,30 @@ encodeOptions options =
|
|
|
975
1081
|
-}
|
|
976
1082
|
toBackendTaskWithOptions : Options -> Glob a -> BackendTask error (List a)
|
|
977
1083
|
toBackendTaskWithOptions options glob =
|
|
1084
|
+
let
|
|
1085
|
+
pattern : String
|
|
1086
|
+
pattern =
|
|
1087
|
+
BackendTask.Internal.Glob.toPattern glob
|
|
1088
|
+
in
|
|
978
1089
|
BackendTask.Internal.Request.request
|
|
979
1090
|
{ name = "glob"
|
|
980
1091
|
, body =
|
|
981
1092
|
Encode.object
|
|
982
|
-
[ ( "pattern"
|
|
1093
|
+
[ ( "pattern"
|
|
1094
|
+
, Encode.string <|
|
|
1095
|
+
-- workaround for https://github.com/micromatch/micromatch/issues/217
|
|
1096
|
+
if String.startsWith "./" pattern then
|
|
1097
|
+
String.dropLeft 2 pattern
|
|
1098
|
+
|
|
1099
|
+
else
|
|
1100
|
+
pattern
|
|
1101
|
+
)
|
|
983
1102
|
, ( "options", encodeOptions options )
|
|
984
1103
|
]
|
|
985
1104
|
|> BackendTask.Http.jsonBody
|
|
986
1105
|
, expect =
|
|
987
|
-
Decode.
|
|
1106
|
+
Decode.map3 (\fileStats fullPath captures -> { fileStats = fileStats, fullPath = fullPath, captures = captures })
|
|
1107
|
+
(Decode.field "fileStats" (Decode.maybe fileStatsDecoder))
|
|
988
1108
|
(Decode.field "fullPath" Decode.string)
|
|
989
1109
|
(Decode.field "captures" (Decode.list Decode.string))
|
|
990
1110
|
|> Decode.list
|
|
@@ -992,8 +1112,8 @@ toBackendTaskWithOptions options glob =
|
|
|
992
1112
|
(\rawGlob ->
|
|
993
1113
|
rawGlob
|
|
994
1114
|
|> List.map
|
|
995
|
-
(\{ fullPath, captures } ->
|
|
996
|
-
BackendTask.Internal.Glob.run fullPath captures glob
|
|
1115
|
+
(\{ fileStats, fullPath, captures } ->
|
|
1116
|
+
BackendTask.Internal.Glob.run fileStats fullPath captures glob
|
|
997
1117
|
|> .match
|
|
998
1118
|
)
|
|
999
1119
|
)
|
|
@@ -1003,6 +1123,18 @@ toBackendTaskWithOptions options glob =
|
|
|
1003
1123
|
(\_ -> BackendTask.succeed [])
|
|
1004
1124
|
|
|
1005
1125
|
|
|
1126
|
+
fileStatsDecoder : Decode.Decoder FileStats
|
|
1127
|
+
fileStatsDecoder =
|
|
1128
|
+
Decode.map7 FileStats
|
|
1129
|
+
(Decode.field "fullPath" Decode.string)
|
|
1130
|
+
(Decode.field "size" Decode.int)
|
|
1131
|
+
(Decode.field "mtime" Decode.int |> Decode.map Time.millisToPosix)
|
|
1132
|
+
(Decode.field "atime" Decode.int |> Decode.map Time.millisToPosix)
|
|
1133
|
+
(Decode.field "ctime" Decode.int |> Decode.map Time.millisToPosix)
|
|
1134
|
+
(Decode.field "birthtime" Decode.int |> Decode.map Time.millisToPosix)
|
|
1135
|
+
(Decode.field "isDirectory" Decode.bool)
|
|
1136
|
+
|
|
1137
|
+
|
|
1006
1138
|
{-| Sometimes you want to make sure there is a unique file matching a particular pattern.
|
|
1007
1139
|
This is a simple helper that will give you a `BackendTask` error if there isn't exactly 1 matching file.
|
|
1008
1140
|
If there is exactly 1, then you successfully get back that single match.
|
|
@@ -1108,3 +1240,54 @@ toPatternString glob =
|
|
|
1108
1240
|
case glob of
|
|
1109
1241
|
Glob pattern_ _ ->
|
|
1110
1242
|
pattern_
|
|
1243
|
+
|
|
1244
|
+
|
|
1245
|
+
{-| Runs a glob string directly, with `include = FilesAndFolders`. Behavior is similar to using glob patterns in a shell.
|
|
1246
|
+
|
|
1247
|
+
If you need to capture specific parts of the path, you can use `capture` and `match` functions instead. `fromString`
|
|
1248
|
+
only allows you to capture a list of matching file paths.
|
|
1249
|
+
|
|
1250
|
+
The following glob syntax is supported:
|
|
1251
|
+
|
|
1252
|
+
- `*` matches any number of characters except for `/`
|
|
1253
|
+
- `**` matches any number of characters including `/`
|
|
1254
|
+
|
|
1255
|
+
For example, if we have the following files:
|
|
1256
|
+
|
|
1257
|
+
```shell
|
|
1258
|
+
- src/
|
|
1259
|
+
- Main.elm
|
|
1260
|
+
- Ui/
|
|
1261
|
+
- Icon.elm
|
|
1262
|
+
- content/
|
|
1263
|
+
- blog/
|
|
1264
|
+
- first-post.md
|
|
1265
|
+
- second-post.md
|
|
1266
|
+
```
|
|
1267
|
+
|
|
1268
|
+
import BackendTask.Glob as Glob
|
|
1269
|
+
|
|
1270
|
+
blogPosts : BackendTask error (List String)
|
|
1271
|
+
blogPosts =
|
|
1272
|
+
Glob.fromString "content/blog/*.md"
|
|
1273
|
+
|
|
1274
|
+
--> BackendTask.succeed [ "content/blog/first-post.md", "content/blog/second-post.md" ]
|
|
1275
|
+
elmFiles : BackendTask error (List String)
|
|
1276
|
+
elmFiles =
|
|
1277
|
+
Glob.fromString "src/**/*.elm"
|
|
1278
|
+
|
|
1279
|
+
--> BackendTask.succeed [ "src/Main.elm", "src/Ui", "src/Ui/Icon.elm" ]
|
|
1280
|
+
|
|
1281
|
+
-}
|
|
1282
|
+
fromString : String -> BackendTask error (List String)
|
|
1283
|
+
fromString pattern_ =
|
|
1284
|
+
fromStringWithOptions { defaultOptions | include = FilesAndFolders } pattern_
|
|
1285
|
+
|
|
1286
|
+
|
|
1287
|
+
{-| Same as [`fromString`](#fromString), but with custom [`Options`](#Options).
|
|
1288
|
+
-}
|
|
1289
|
+
fromStringWithOptions : Options -> String -> BackendTask error (List String)
|
|
1290
|
+
fromStringWithOptions options pattern_ =
|
|
1291
|
+
Glob pattern_ (\_ _ _ -> ( identity, [] ))
|
|
1292
|
+
|> captureFilePath
|
|
1293
|
+
|> toBackendTaskWithOptions options
|
package/src/BackendTask/Http.elm
CHANGED
|
@@ -240,6 +240,9 @@ getWithOptions request__ =
|
|
|
240
240
|
, headers = request__.headers
|
|
241
241
|
, body = emptyBody
|
|
242
242
|
, method = "GET"
|
|
243
|
+
, dir = []
|
|
244
|
+
, env = Dict.empty
|
|
245
|
+
, quiet = False
|
|
243
246
|
, cacheOptions =
|
|
244
247
|
{ cacheStrategy = request__.cacheStrategy
|
|
245
248
|
, retries = request__.retries
|
|
@@ -406,6 +409,9 @@ request request__ expect =
|
|
|
406
409
|
, headers = request__.headers
|
|
407
410
|
, method = request__.method
|
|
408
411
|
, body = request__.body
|
|
412
|
+
, dir = []
|
|
413
|
+
, env = Dict.empty
|
|
414
|
+
, quiet = False
|
|
409
415
|
, cacheOptions =
|
|
410
416
|
{ cacheStrategy = Nothing -- cache strategy only applies to GET and HEAD, need to use getWithOptions to customize
|
|
411
417
|
, cachePath = Nothing
|
|
@@ -486,6 +492,9 @@ requestRaw request__ expect =
|
|
|
486
492
|
:: request__.headers
|
|
487
493
|
, method = request__.method
|
|
488
494
|
, body = request__.body
|
|
495
|
+
, dir = []
|
|
496
|
+
, env = Dict.empty
|
|
497
|
+
, quiet = False
|
|
489
498
|
, cacheOptions = request__.cacheOptions
|
|
490
499
|
}
|
|
491
500
|
in
|
|
@@ -506,7 +515,7 @@ requestRaw request__ expect =
|
|
|
506
515
|
|
|
507
516
|
Nothing ->
|
|
508
517
|
--Err (Pages.StaticHttpRequest.UserCalledStaticHttpFail ("INTERNAL ERROR - expected request" ++ request_.url))
|
|
509
|
-
Err (BadBody Nothing ("INTERNAL ERROR - expected request" ++ request_.url))
|
|
518
|
+
Err (BadBody Nothing ("INTERNAL ERROR - expected request " ++ request_.url))
|
|
510
519
|
|
|
511
520
|
Just (Err RequestsAndPending.NetworkError) ->
|
|
512
521
|
Err NetworkError
|
|
@@ -632,6 +641,24 @@ toResultThing ( expect, body, maybeResponse ) =
|
|
|
632
641
|
Err (BadBody Nothing "Unexpected combination, internal error")
|
|
633
642
|
|
|
634
643
|
|
|
644
|
+
{-| -}
|
|
645
|
+
type alias Metadata =
|
|
646
|
+
{ url : String
|
|
647
|
+
, statusCode : Int
|
|
648
|
+
, statusText : String
|
|
649
|
+
, headers : Dict String String
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
{-| -}
|
|
654
|
+
type Error
|
|
655
|
+
= BadUrl String
|
|
656
|
+
| Timeout
|
|
657
|
+
| NetworkError
|
|
658
|
+
| BadStatus Metadata String
|
|
659
|
+
| BadBody (Maybe Json.Decode.Error) String
|
|
660
|
+
|
|
661
|
+
|
|
635
662
|
errorToString : Error -> { title : String, body : String }
|
|
636
663
|
errorToString error =
|
|
637
664
|
{ title = "HTTP Error"
|
|
@@ -649,8 +676,10 @@ errorToString error =
|
|
|
649
676
|
[ TerminalText.text "NetworkError"
|
|
650
677
|
]
|
|
651
678
|
|
|
652
|
-
BadStatus _
|
|
653
|
-
[ TerminalText.text
|
|
679
|
+
BadStatus metadata _ ->
|
|
680
|
+
[ TerminalText.text "BadStatus: "
|
|
681
|
+
, TerminalText.red (String.fromInt metadata.statusCode)
|
|
682
|
+
, TerminalText.text (" " ++ metadata.statusText)
|
|
654
683
|
]
|
|
655
684
|
|
|
656
685
|
BadBody _ string ->
|
|
@@ -659,21 +688,3 @@ errorToString error =
|
|
|
659
688
|
)
|
|
660
689
|
|> TerminalText.toString
|
|
661
690
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
{-| -}
|
|
665
|
-
type alias Metadata =
|
|
666
|
-
{ url : String
|
|
667
|
-
, statusCode : Int
|
|
668
|
-
, statusText : String
|
|
669
|
-
, headers : Dict String String
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
{-| -}
|
|
674
|
-
type Error
|
|
675
|
-
= BadUrl String
|
|
676
|
-
| Timeout
|
|
677
|
-
| NetworkError
|
|
678
|
-
| BadStatus Metadata String
|
|
679
|
-
| BadBody (Maybe Json.Decode.Error) String
|
|
@@ -6,19 +6,31 @@ module BackendTask.Internal.Glob exposing
|
|
|
6
6
|
)
|
|
7
7
|
|
|
8
8
|
import List.Extra
|
|
9
|
+
import Time
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
{-| -}
|
|
12
13
|
type Glob a
|
|
13
|
-
= Glob String (String -> List String -> ( a, List String ))
|
|
14
|
+
= Glob String (Maybe FileStats -> String -> List String -> ( a, List String ))
|
|
14
15
|
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
type alias FileStats =
|
|
18
|
+
{ fullPath : String
|
|
19
|
+
, sizeInBytes : Int
|
|
20
|
+
, lastContentChange : Time.Posix
|
|
21
|
+
, lastAccess : Time.Posix
|
|
22
|
+
, lastFileChange : Time.Posix
|
|
23
|
+
, createdAt : Time.Posix
|
|
24
|
+
, isDirectory : Bool
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
run : Maybe FileStats -> String -> List String -> Glob a -> { match : a, pattern : String }
|
|
29
|
+
run fileStats rawInput captures (Glob pattern applyCapture) =
|
|
18
30
|
{ match =
|
|
19
31
|
captures
|
|
20
32
|
|> List.reverse
|
|
21
|
-
|> applyCapture rawInput
|
|
33
|
+
|> applyCapture fileStats rawInput
|
|
22
34
|
|> Tuple.first
|
|
23
35
|
, pattern = pattern
|
|
24
36
|
}
|