├── .gitignore ├── CHANGELOG.md ├── FAQ.md ├── LICENSE ├── README.md ├── elm.json ├── examples └── Example.elm ├── package.json ├── review ├── elm.json └── src │ └── ReviewConfig.elm ├── src └── Codec.elm ├── tests ├── Base.elm ├── Fields.elm ├── Forward.elm └── elm-verify-examples.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | elm-stuff 2 | node_modules 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | ### Added 9 | - First version 10 | 11 | [Unreleased]: https://github.com/miniBill/elm-codec/compare/v1.0.0...HEAD 12 | [1.0.0]: https://github.com/miniBill/elm-codec/releases/tag/v1.0.0 -------------------------------------------------------------------------------- /FAQ.md: -------------------------------------------------------------------------------- 1 | ## How do you use `recursive`? 2 | The trick to understanding the `recursive` codec is: pretend you are already done. 3 | When the function you pass to `recursive` is called the argument is the finished `Codec`. 4 | 5 | An example may be worth a thousand words: 6 | 7 | ```elm 8 | type Peano 9 | = Peano (Maybe Peano) 10 | 11 | 12 | peanoCodec : Codec Peano 13 | peanoCodec = 14 | Codec.recursive 15 | (\finishedCodec -> 16 | Codec.maybe finishedCodec 17 | |> Codec.map Peano (\(Peano p) -> p) 18 | ) 19 | ``` 20 | 21 | ## Why does `map` take two opposite functions? 22 | One is used for the encoder, the other for the decoder 23 | 24 | ## How do I build `Codec`s for custom types? 25 | You start building with `custom` which needs the pattern matcher for your type as an argument. 26 | 27 | The pattern matcher is just the most generic `case ... of` possible for your type. 28 | 29 | You then chain `variantX` calls for every alternative (in the same order as the pattern matcher). 30 | 31 | You end with a call to `buildCustom`. 32 | 33 | An example: 34 | 35 | ```elm 36 | type Semaphore 37 | = Red Int String 38 | | Yellow Float 39 | | Green 40 | 41 | 42 | semaphoreCodec : Codec Semaphore 43 | semaphoreCodec = 44 | Codec.custom 45 | (\fred fyellow fgreen value -> 46 | case value of 47 | Red i s -> 48 | fred i s 49 | 50 | Yellow f -> 51 | fyellow f 52 | 53 | Green -> 54 | fgreen 55 | ) 56 | |> Codec.variant2 "Red" Red Codec.int Codec.string 57 | |> Codec.variant1 "Yellow" Yellow Codec.float 58 | |> Codec.variant0 "Green" Green 59 | |> Codec.buildCustom 60 | ``` 61 | 62 | ## What happens to existing `Value`s if I change my `Codec`s? 63 | Old `Value`s will be parsed fine by new `Codec`s if you: 64 | * add new `variant`s to custom types, 65 | * remove (from the end) parameters from `variant`s, 66 | * change any `Codec` to a `succeed` one or 67 | * add optional fields (`maybeField`) to records. 68 | 69 | New `Value`s will be parsed fine by old `Codec`s if you: 70 | * remove `variant`s from custom types, 71 | * append parameters to `variant`s , 72 | * change a `succeed` `Codec` to any other one or 73 | * remove fields from records. 74 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Leonardo Taglialegne 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # elm-codecs 2 | 3 | This package allows you to build pairs of JSON encoders (`a -> Value`) and decoders (`Decoder a`), collectively called a `Codec a`. 4 | 5 | It supports all of the basic types, collections, records and even custom types! See an example at the bottom of this document. 6 | 7 | ## Design Goals 8 | 9 | The design goal is to be as type safe as possible while keeping a nice API. 10 | Using this package will greatly reduce the risk of unmatched encoders and decoders. 11 | 12 | The packages re-exposes the `Value` and `Decoder` types from `elm/json`, so you don't need to import them too. 13 | 14 | ## Learning Resources 15 | 16 | Ask for help on the [Elm Slack](https://elmlang.herokuapp.com/). 17 | 18 | You can also have a look at the `FAQ.md` file. 19 | 20 | ## Examples 21 | 22 | See the `examples` folder for more examples. 23 | 24 | ### Basic usage 25 | 26 | ```elm 27 | import Codec exposing (Codec, Value) 28 | 29 | codec : Codec (List Int) 30 | codec = 31 | Codec.list Codec.int 32 | 33 | encode : List Int -> Value 34 | encode list = 35 | Codec.encoder codec list 36 | 37 | decodeString : String -> Result Codec.Error (List Int) 38 | decodeString s = 39 | Codec.decodeString codec s 40 | ``` 41 | 42 | ### Custom types 43 | 44 | ```elm 45 | type Semaphore 46 | = Red Int String 47 | | Yellow 48 | | Green Float 49 | 50 | semaphoreCodec : Codec Semaphore 51 | semaphoreCodec = 52 | Codec.custom 53 | (\red yellow green value -> 54 | case value of 55 | Red i s -> 56 | red i s 57 | 58 | Yellow -> 59 | yellow 60 | 61 | Green f -> 62 | green f 63 | ) 64 | |> Codec.variant2 "Red" Red Codec.int Codec.string 65 | |> Codec.variant0 "Yellow" Yellow 66 | |> Codec.variant1 "Green" Green Codec.float 67 | |> Codec.buildCustom 68 | ``` 69 | -------------------------------------------------------------------------------- /elm.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "package", 3 | "name": "miniBill/elm-codec", 4 | "summary": "Build JSON encoders and decoders with minimal boilerplate", 5 | "license": "MIT", 6 | "version": "2.2.0", 7 | "exposed-modules": [ 8 | "Codec" 9 | ], 10 | "elm-version": "0.19.0 <= v < 0.20.0", 11 | "dependencies": { 12 | "elm/core": "1.0.0 <= v < 2.0.0", 13 | "elm/json": "1.0.0 <= v < 2.0.0" 14 | }, 15 | "test-dependencies": { 16 | "elm-explorations/test": "2.1.1 <= v < 3.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/Example.elm: -------------------------------------------------------------------------------- 1 | module Examples exposing (Point, Tree(..), pointCodec, treeCodec) 2 | 3 | import Codec exposing (Codec) 4 | 5 | 6 | type alias Point = 7 | { x : Int 8 | , y : Int 9 | } 10 | 11 | 12 | pointCodec : Codec Point 13 | pointCodec = 14 | Codec.object Point 15 | |> Codec.field "x" .x Codec.int 16 | |> Codec.field "y" .y Codec.int 17 | |> Codec.buildObject 18 | 19 | 20 | type Peano 21 | = Peano (Maybe Peano) 22 | 23 | 24 | peanoCodec : Codec Peano 25 | peanoCodec = 26 | Codec.recursive 27 | (\finishedCodec -> 28 | Codec.maybe finishedCodec 29 | |> Codec.map Peano (\(Peano p) -> p) 30 | ) 31 | 32 | 33 | type Semaphore 34 | = Red Int String 35 | | Yellow Float 36 | | Green 37 | 38 | 39 | semaphoreCodec : Codec Semaphore 40 | semaphoreCodec = 41 | Codec.custom 42 | (\red yellow green value -> 43 | case value of 44 | Red i s -> 45 | red i s 46 | 47 | Yellow f -> 48 | yellow f 49 | 50 | Green -> 51 | green 52 | ) 53 | |> Codec.variant2 "Red" Red Codec.int Codec.string 54 | |> Codec.variant1 "Yellow" Yellow Codec.float 55 | |> Codec.variant0 "Green" Green 56 | |> Codec.buildCustom 57 | 58 | 59 | type Tree a 60 | = Node (List (Tree a)) 61 | | Leaf a 62 | 63 | 64 | treeCodec : Codec a -> Codec (Tree a) 65 | treeCodec meta = 66 | Codec.recursive 67 | (\rmeta -> 68 | let 69 | match fnode fleaf tree = 70 | case tree of 71 | Node cs -> 72 | fnode cs 73 | 74 | Leaf x -> 75 | fleaf x 76 | in 77 | Codec.custom match 78 | |> Codec.variant1 "Node" Node (Codec.list rmeta) 79 | |> Codec.variant1 "Leaf" Leaf meta 80 | |> Codec.buildCustom 81 | ) 82 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "elm-review": "^2.10.2", 4 | "elm-test": "^0.19.1-revision12", 5 | "elm-verify-examples": "^6.0.3" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /review/elm.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "application", 3 | "source-directories": [ 4 | "src" 5 | ], 6 | "elm-version": "0.19.1", 7 | "dependencies": { 8 | "direct": { 9 | "elm/core": "1.0.5", 10 | "elm/json": "1.1.3", 11 | "elm/project-metadata-utils": "1.0.2", 12 | "jfmengels/elm-review": "2.13.1", 13 | "jfmengels/elm-review-code-style": "1.1.4", 14 | "jfmengels/elm-review-common": "1.3.3", 15 | "jfmengels/elm-review-debug": "1.0.8", 16 | "jfmengels/elm-review-documentation": "2.0.4", 17 | "jfmengels/elm-review-simplify": "2.1.0", 18 | "jfmengels/elm-review-unused": "1.2.0", 19 | "stil4m/elm-syntax": "7.3.1" 20 | }, 21 | "indirect": { 22 | "elm/bytes": "1.0.8", 23 | "elm/html": "1.0.0", 24 | "elm/parser": "1.1.0", 25 | "elm/random": "1.0.0", 26 | "elm/regex": "1.0.0", 27 | "elm/time": "1.0.0", 28 | "elm/virtual-dom": "1.0.3", 29 | "elm-explorations/test": "2.1.1", 30 | "miniBill/elm-unicode": "1.0.3", 31 | "pzp1997/assoc-list": "1.0.0", 32 | "rtfeldman/elm-hex": "1.0.0", 33 | "stil4m/structured-writer": "1.0.3" 34 | } 35 | }, 36 | "test-dependencies": { 37 | "direct": {}, 38 | "indirect": {} 39 | } 40 | } -------------------------------------------------------------------------------- /review/src/ReviewConfig.elm: -------------------------------------------------------------------------------- 1 | module ReviewConfig exposing (config) 2 | 3 | {-| Do not rename the ReviewConfig module or the config function, because 4 | `elm-review` will look for these. 5 | 6 | To add packages that contain rules, add them to this review project using 7 | 8 | `elm install author/packagename` 9 | 10 | when inside the directory containing this file. 11 | 12 | -} 13 | 14 | import Docs.NoMissing exposing (exposedModules, onlyExposed) 15 | import Docs.ReviewAtDocs 16 | import Docs.ReviewLinksAndSections 17 | import Docs.UpToDateReadmeLinks 18 | import NoConfusingPrefixOperator 19 | import NoDebug.Log 20 | import NoDebug.TodoOrToString 21 | import NoExposingEverything 22 | import NoImportingEverything 23 | import NoMissingTypeAnnotation 24 | import NoMissingTypeAnnotationInLetIn 25 | import NoMissingTypeExpose 26 | import NoPrematureLetComputation 27 | import NoSimpleLetBody 28 | import NoUnused.CustomTypeConstructorArgs 29 | import NoUnused.CustomTypeConstructors 30 | import NoUnused.Dependencies 31 | import NoUnused.Exports 32 | import NoUnused.Parameters 33 | import NoUnused.Patterns 34 | import NoUnused.Variables 35 | import Review.Rule as Rule exposing (Rule) 36 | import Simplify 37 | 38 | 39 | config : List Rule 40 | config = 41 | [ Docs.NoMissing.rule 42 | { document = onlyExposed 43 | , from = exposedModules 44 | } 45 | , Docs.ReviewLinksAndSections.rule 46 | , Docs.ReviewAtDocs.rule 47 | , Docs.UpToDateReadmeLinks.rule 48 | , NoConfusingPrefixOperator.rule 49 | , NoDebug.Log.rule 50 | , NoDebug.TodoOrToString.rule 51 | |> Rule.ignoreErrorsForDirectories [ "tests/" ] 52 | , NoExposingEverything.rule 53 | , NoImportingEverything.rule [] 54 | , NoMissingTypeAnnotation.rule 55 | , NoMissingTypeAnnotationInLetIn.rule 56 | , NoMissingTypeExpose.rule 57 | , NoSimpleLetBody.rule 58 | , NoPrematureLetComputation.rule 59 | , NoUnused.CustomTypeConstructors.rule [] 60 | , NoUnused.CustomTypeConstructorArgs.rule 61 | , NoUnused.Dependencies.rule 62 | , NoUnused.Exports.rule 63 | , NoUnused.Parameters.rule 64 | , NoUnused.Patterns.rule 65 | , NoUnused.Variables.rule 66 | , Simplify.rule Simplify.defaults 67 | ] 68 | -------------------------------------------------------------------------------- /src/Codec.elm: -------------------------------------------------------------------------------- 1 | module Codec exposing 2 | ( Codec, Value, Error 3 | , Decoder, decoder, decodeString, decodeValue 4 | , encoder, encodeToString, encodeToValue 5 | , string, bool, int, float, char, enum 6 | , maybe, nullable, list, array, dict, set, tuple, triple, result 7 | , ObjectCodec, object, field, optionalField, optionalNullableField, optionalMaybeField, buildObject 8 | , CustomCodec, custom, variant0, variant1, variant2, variant3, variant4, variant5, variant6, variant7, variant8, buildCustom 9 | , oneOf 10 | , map 11 | , succeed, recursive, fail, andThen, lazy, value, build, constant 12 | , nullableField, maybeField 13 | , getFields 14 | ) 15 | 16 | {-| A `Codec a` contain a JSON `Decoder a` and the corresponding `a -> Value` encoder. 17 | 18 | 19 | # Definition 20 | 21 | @docs Codec, Value, Error 22 | 23 | 24 | # Decode 25 | 26 | @docs Decoder, decoder, decodeString, decodeValue 27 | 28 | 29 | # Encode 30 | 31 | @docs encoder, encodeToString, encodeToValue 32 | 33 | 34 | # Primitives 35 | 36 | @docs string, bool, int, float, char, enum 37 | 38 | 39 | # Data Structures 40 | 41 | @docs maybe, nullable, list, array, dict, set, tuple, triple, result 42 | 43 | 44 | # Object Primitives 45 | 46 | @docs ObjectCodec, object, field, optionalField, optionalNullableField, optionalMaybeField, buildObject 47 | 48 | 49 | # Custom Types 50 | 51 | @docs CustomCodec, custom, variant0, variant1, variant2, variant3, variant4, variant5, variant6, variant7, variant8, buildCustom 52 | 53 | 54 | # Inconsistent structure 55 | 56 | @docs oneOf 57 | 58 | 59 | # Mapping 60 | 61 | @docs map 62 | 63 | 64 | # Fancy Codecs 65 | 66 | @docs succeed, recursive, fail, andThen, lazy, value, build, constant 67 | 68 | 69 | # Deprecated 70 | 71 | @docs nullableField, maybeField 72 | 73 | 74 | # Miscellaneous 75 | 76 | @docs getFields 77 | 78 | -} 79 | 80 | import Array exposing (Array) 81 | import Dict exposing (Dict) 82 | import Json.Decode as JD 83 | import Json.Encode as JE 84 | import Set exposing (Set) 85 | 86 | 87 | 88 | -- DEFINITION 89 | 90 | 91 | {-| A value that knows how to encode and decode JSON values. 92 | -} 93 | type Codec a 94 | = Codec 95 | { encoder : a -> Value 96 | , decoder : Decoder a 97 | } 98 | 99 | 100 | {-| Represents a JavaScript value. 101 | -} 102 | type alias Value = 103 | JE.Value 104 | 105 | 106 | {-| A structured error describing exactly how the decoder failed. You can use 107 | this to create more elaborate visualizations of a decoder problem. For example, 108 | you could show the entire JSON object and show the part causing the failure in 109 | red. 110 | -} 111 | type alias Error = 112 | JD.Error 113 | 114 | 115 | 116 | -- DECODE 117 | 118 | 119 | {-| A value that knows how to decode JSON values. 120 | -} 121 | type alias Decoder a = 122 | JD.Decoder a 123 | 124 | 125 | {-| Extracts the `Decoder` contained inside the `Codec`. 126 | -} 127 | decoder : Codec a -> Decoder a 128 | decoder (Codec m) = 129 | m.decoder 130 | 131 | 132 | {-| Parse the given string into a JSON value and then run the `Codec` on it. 133 | This will fail if the string is not well-formed JSON or if the `Codec` 134 | fails for some reason. 135 | -} 136 | decodeString : Codec a -> String -> Result Error a 137 | decodeString codec = 138 | JD.decodeString (decoder codec) 139 | 140 | 141 | {-| Run a `Codec` to decode some JSON `Value`. You can send these JSON values 142 | through ports, so that is probably the main time you would use this function. 143 | -} 144 | decodeValue : Codec a -> Value -> Result Error a 145 | decodeValue codec = 146 | JD.decodeValue (decoder codec) 147 | 148 | 149 | 150 | -- ENCODE 151 | 152 | 153 | {-| Extracts the encoding function contained inside the `Codec`. 154 | -} 155 | encoder : Codec a -> a -> Value 156 | encoder (Codec m) = 157 | m.encoder 158 | 159 | 160 | {-| Convert a value into a prettified JSON string. The first argument specifies 161 | the amount of indentation in the result string. 162 | -} 163 | encodeToString : Int -> Codec a -> a -> String 164 | encodeToString indentation codec = 165 | encoder codec >> JE.encode indentation 166 | 167 | 168 | {-| Convert a value into a Javascript `Value`. 169 | -} 170 | encodeToValue : Codec a -> a -> Value 171 | encodeToValue codec = 172 | encoder codec 173 | 174 | 175 | 176 | -- BASE 177 | 178 | 179 | {-| Build your own custom `Codec`. 180 | Useful if you have pre-existing `Decoder`s you need to use. 181 | -} 182 | build : (a -> Value) -> Decoder a -> Codec a 183 | build encoder_ decoder_ = 184 | Codec 185 | { encoder = encoder_ 186 | , decoder = decoder_ 187 | } 188 | 189 | 190 | {-| `Codec` between a JSON string and an Elm `String` 191 | -} 192 | string : Codec String 193 | string = 194 | build JE.string JD.string 195 | 196 | 197 | {-| `Codec` between a JSON boolean and an Elm `Bool` 198 | -} 199 | bool : Codec Bool 200 | bool = 201 | build JE.bool JD.bool 202 | 203 | 204 | {-| `Codec` between a JSON number and an Elm `Int` 205 | -} 206 | int : Codec Int 207 | int = 208 | build JE.int JD.int 209 | 210 | 211 | {-| `Codec` between a JSON number and an Elm `Float` 212 | -} 213 | float : Codec Float 214 | float = 215 | build JE.float JD.float 216 | 217 | 218 | {-| `Codec` between a JSON string of length 1 and an Elm `Char` 219 | -} 220 | char : Codec Char 221 | char = 222 | build 223 | (String.fromChar >> JE.string) 224 | (JD.string 225 | |> JD.andThen 226 | (\s -> 227 | case String.uncons s of 228 | Just ( h, "" ) -> 229 | JD.succeed h 230 | 231 | _ -> 232 | JD.fail "Expected a single char" 233 | ) 234 | ) 235 | 236 | 237 | {-| `Codec` for a fixed list of Elm values. 238 | 239 | This can be used for custom types, if they are really simple: 240 | 241 | type Semaphore = Red | Yellow | Green 242 | 243 | semaphoreCodec : Codec Semaphore 244 | semaphoreCodec = 245 | enum Codec.string 246 | [ ("Red", Red) 247 | , ("Yellow", Yellow) 248 | , ("Green", Green) 249 | ] 250 | 251 | encodeToString 0 semaphoreCodec Red 252 | --> "\"Red\"" 253 | decodeString semaphoreCodec "\"Red\"" 254 | --> Ok Red 255 | 256 | type Count = One | Two | Three 257 | 258 | countCodec : Codec Count 259 | countCodec = 260 | enum Codec.int 261 | [ (1, One) 262 | , (2, Two) 263 | , (3, Three) 264 | ] 265 | 266 | encodeToString 0 countCodec Two 267 | --> "2" 268 | decodeString countCodec "2" 269 | --> Ok Two 270 | 271 | incompleteCodec : Codec Count 272 | incompleteCodec = 273 | enum Codec.int 274 | [ (1, One) 275 | , (2, Two) 276 | ] 277 | 278 | encodeToString 0 incompleteCodec Three 279 | --> "null" 280 | 281 | decodeString incompleteCodec "3" |> Result.mapError (\_ -> "...") 282 | --> Err "..." 283 | 284 | -} 285 | enum : Codec a -> List ( a, b ) -> Codec b 286 | enum (Codec codec) options = 287 | let 288 | enc : List ( a, b ) -> b -> JE.Value 289 | enc queue val = 290 | case queue of 291 | [] -> 292 | JE.null 293 | 294 | ( k, v ) :: tail -> 295 | if v == val then 296 | codec.encoder k 297 | 298 | else 299 | enc tail val 300 | 301 | dec : List ( a, b ) -> a -> JD.Decoder b 302 | dec queue key = 303 | case queue of 304 | [] -> 305 | JD.fail "Key not found" 306 | 307 | ( k, v ) :: tail -> 308 | if k == key then 309 | JD.succeed v 310 | 311 | else 312 | dec tail key 313 | in 314 | Codec 315 | { encoder = enc options 316 | , decoder = 317 | codec.decoder 318 | |> JD.andThen 319 | (\k -> dec options k) 320 | } 321 | 322 | 323 | 324 | -- DATA STRUCTURES 325 | 326 | 327 | composite : ((b -> Value) -> (a -> Value)) -> (Decoder b -> Decoder a) -> Codec b -> Codec a 328 | composite enc dec (Codec codec) = 329 | Codec 330 | { encoder = enc codec.encoder 331 | , decoder = dec codec.decoder 332 | } 333 | 334 | 335 | {-| Represents an optional value. 336 | 337 | This is encoded as `null` when the input is `Nothing`, and the same as `x` when `Just x`. 338 | 339 | If the decoding using the inner `Codec` fails, it will _succeed_ with `Nothing`. If you want it to fail use `nullable` instead. 340 | 341 | encodeToString 0 (maybe int) (Just 3) 342 | --> "3" 343 | encodeToString 0 (maybe int) Nothing 344 | --> "null" 345 | 346 | decodeString (maybe int) "3" 347 | --> Ok (Just 3) 348 | decodeString (maybe int) "null" 349 | --> Ok Nothing 350 | decodeString (maybe int) "\"hello\"" 351 | --> Ok Nothing 352 | 353 | -} 354 | maybe : Codec a -> Codec (Maybe a) 355 | maybe codec = 356 | Codec 357 | { decoder = JD.maybe <| decoder codec 358 | , encoder = 359 | \v -> 360 | case v of 361 | Nothing -> 362 | JE.null 363 | 364 | Just x -> 365 | encoder codec x 366 | } 367 | 368 | 369 | {-| Represents an optional value. 370 | 371 | This is encoded as `null` when the input is `Nothing`, and the same as `x` when `Just x`. 372 | 373 | When decoding, it decodes `null` to `Nothing`. Otherwise, if the decoding using the inner `Codec` fails, it will fail. If you want it to succeed with `Nothing` use `maybe` instead. 374 | 375 | encodeToString 0 (nullable int) (Just 3) 376 | --> "3" 377 | encodeToString 0 (nullable int) Nothing 378 | --> "null" 379 | 380 | decodeString (nullable int) "3" 381 | --> Ok (Just 3) 382 | decodeString (nullable int) "null" 383 | --> Ok Nothing 384 | decodeString (nullable int) "\"hello\"" |> Result.mapError (\_ -> "...") 385 | --> Err "..." 386 | 387 | -} 388 | nullable : Codec a -> Codec (Maybe a) 389 | nullable codec = 390 | Codec 391 | { decoder = JD.nullable <| decoder codec 392 | , encoder = 393 | \v -> 394 | case v of 395 | Nothing -> 396 | JE.null 397 | 398 | Just x -> 399 | encoder codec x 400 | } 401 | 402 | 403 | {-| `Codec` between a JSON array and an Elm `List`. 404 | -} 405 | list : Codec a -> Codec (List a) 406 | list = 407 | composite JE.list JD.list 408 | 409 | 410 | {-| `Codec` between a JSON array and an Elm `Array`. 411 | -} 412 | array : Codec a -> Codec (Array a) 413 | array = 414 | composite JE.array JD.array 415 | 416 | 417 | {-| `Codec` between a JSON object and an Elm `Dict`. 418 | -} 419 | dict : Codec a -> Codec (Dict String a) 420 | dict = 421 | composite 422 | (\e -> JE.object << Dict.toList << Dict.map (\_ -> e)) 423 | JD.dict 424 | 425 | 426 | {-| `Codec` between a JSON array and an Elm `Set`. 427 | -} 428 | set : Codec comparable -> Codec (Set comparable) 429 | set = 430 | composite 431 | (\e -> JE.list e << Set.toList) 432 | (JD.map Set.fromList << JD.list) 433 | 434 | 435 | {-| `Codec` between a JSON array of length 2 and an Elm `Tuple`. 436 | -} 437 | tuple : Codec a -> Codec b -> Codec ( a, b ) 438 | tuple m1 m2 = 439 | Codec 440 | { encoder = 441 | \( v1, v2 ) -> 442 | JE.list identity 443 | [ encoder m1 v1 444 | , encoder m2 v2 445 | ] 446 | , decoder = 447 | JD.map2 448 | (\a b -> ( a, b )) 449 | (JD.index 0 <| decoder m1) 450 | (JD.index 1 <| decoder m2) 451 | } 452 | 453 | 454 | {-| `Codec` between a JSON array of length 3 and an Elm triple. 455 | -} 456 | triple : Codec a -> Codec b -> Codec c -> Codec ( a, b, c ) 457 | triple m1 m2 m3 = 458 | Codec 459 | { encoder = 460 | \( v1, v2, v3 ) -> 461 | JE.list identity 462 | [ encoder m1 v1 463 | , encoder m2 v2 464 | , encoder m3 v3 465 | ] 466 | , decoder = 467 | JD.map3 468 | (\a b c -> ( a, b, c )) 469 | (JD.index 0 <| decoder m1) 470 | (JD.index 1 <| decoder m2) 471 | (JD.index 2 <| decoder m3) 472 | } 473 | 474 | 475 | {-| `Codec` for `Result` values. 476 | -} 477 | result : Codec error -> Codec value -> Codec (Result error value) 478 | result errorCodec valueCodec = 479 | custom 480 | (\ferr fok v -> 481 | case v of 482 | Err err -> 483 | ferr err 484 | 485 | Ok ok -> 486 | fok ok 487 | ) 488 | |> variant1 "Err" Err errorCodec 489 | |> variant1 "Ok" Ok valueCodec 490 | |> buildCustom 491 | 492 | 493 | 494 | -- OBJECTS 495 | 496 | 497 | {-| A partially built `Codec` for an object. 498 | -} 499 | type ObjectCodec a b 500 | = ObjectCodec 501 | { encoder : a -> List ( String, Value ) 502 | , decoder : Decoder b 503 | , fields : List String 504 | } 505 | 506 | 507 | {-| Start creating a `Codec` for an object. You should pass the main constructor as argument. 508 | If you don't have one (for example it's a simple type with no name), you should pass a function that given the field values builds an object. 509 | 510 | Example with constructor: 511 | 512 | type alias Point = 513 | { x : Float 514 | , y : Float 515 | } 516 | 517 | pointCodec : Codec Point 518 | pointCodec = 519 | Codec.object Point 520 | |> Codec.field "x" .x Codec.float 521 | |> Codec.field "y" .y Codec.float 522 | |> Codec.buildObject 523 | 524 | Example without constructor: 525 | 526 | pointCodec : Codec { x : Int, y : Bool } 527 | pointCodec = 528 | Codec.object (\x y -> { x = x, y = y }) 529 | |> Codec.field "x" .x Codec.int 530 | |> Codec.field "y" .y Codec.bool 531 | |> Codec.buildObject 532 | 533 | -} 534 | object : b -> ObjectCodec a b 535 | object ctor = 536 | ObjectCodec 537 | { encoder = \_ -> [] 538 | , decoder = JD.succeed ctor 539 | , fields = [] 540 | } 541 | 542 | 543 | {-| Get all of the fields present in an ObjectCodec. This might be useful if you are making a request to a database and you want to both decode the response and be able to include in the request a filter so you only receive the fields you intend to decode. 544 | -} 545 | getFields : ObjectCodec a b -> List String 546 | getFields (ObjectCodec ocodec) = 547 | ocodec.fields 548 | 549 | 550 | {-| Specify the name, getter and `Codec` for a field. 551 | 552 | The name is only used as the field name in the resulting JSON, and has no impact on the Elm side. 553 | 554 | -} 555 | field : String -> (a -> f) -> Codec f -> ObjectCodec a (f -> b) -> ObjectCodec a b 556 | field name getter codec (ObjectCodec ocodec) = 557 | ObjectCodec 558 | { encoder = \v -> ( name, encoder codec <| getter v ) :: ocodec.encoder v 559 | , decoder = JD.map2 (\f x -> f x) ocodec.decoder (JD.field name (decoder codec)) 560 | , fields = name :: ocodec.fields 561 | } 562 | 563 | 564 | {-| Specify the name getter and `Codec` for an optional field. 565 | 566 | **Warning! This is a footgun and thus deprecated, you should probably use `optionalField` instead.** 567 | 568 | This is particularly useful for evolving your `Codec`s. 569 | 570 | If the field is not present in the input then it gets decoded to `Nothing`. \_If the field value cannot be decoded by the given `Codec` it also gets decoded to `Nothing`. Even worse, if the input is not an object, this `Codec` still succeeds! 571 | 572 | When encoding, if the optional field's value is `Nothing` then the resulting object will not contain that field. 573 | 574 | -} 575 | maybeField : String -> (a -> Maybe f) -> Codec f -> ObjectCodec a (Maybe f -> b) -> ObjectCodec a b 576 | maybeField name getter codec (ObjectCodec ocodec) = 577 | ObjectCodec 578 | { encoder = 579 | \v -> 580 | case getter v of 581 | Just present -> 582 | ( name, encoder codec present ) :: ocodec.encoder v 583 | 584 | Nothing -> 585 | ocodec.encoder v 586 | , decoder = 587 | decoder codec 588 | |> JD.field name 589 | |> JD.maybe 590 | |> JD.map2 (\f x -> f x) ocodec.decoder 591 | , fields = name :: ocodec.fields 592 | } 593 | 594 | 595 | {-| Specify the name getter and `Codec` for an optional field. 596 | 597 | This is particularly useful for evolving your `Codec`s. 598 | 599 | If the field is not present in the input then it gets decoded to `Nothing`. If the field cannot be decoded this will fail. If the value is `null` then this will fail, use `optionalNullableField` if you want it to succeed instad. 600 | If the optional field's value is `Nothing` then the resulting object will not contain that field. 601 | 602 | -} 603 | optionalField : String -> (a -> Maybe f) -> Codec f -> ObjectCodec a (Maybe f -> b) -> ObjectCodec a b 604 | optionalField name getter codec (ObjectCodec ocodec) = 605 | ObjectCodec 606 | { encoder = 607 | \v -> 608 | case getter v of 609 | Just present -> 610 | ( name, encoder codec present ) :: ocodec.encoder v 611 | 612 | Nothing -> 613 | ocodec.encoder v 614 | , decoder = 615 | -- Decoder inspired by https://github.com/elm-community/json-extra/blob/4.3.0/src/Json/Decode/Extra.elm#L272 616 | JD.keyValuePairs JD.value 617 | |> JD.andThen 618 | (\json -> 619 | if List.any (\( k, _ ) -> k == name) json then 620 | --The field exist, actually run the decoder 621 | JD.map Just (JD.field name (decoder codec)) 622 | 623 | else 624 | -- The field is missing 625 | JD.succeed Nothing 626 | ) 627 | |> JD.map2 (\f x -> f x) ocodec.decoder 628 | , fields = name :: ocodec.fields 629 | } 630 | 631 | 632 | {-| An object field that might not be present or might contain data that maps to Nothing. 633 | This function flattens both into Nothing rather than making you deal with a `Maybe (Maybe a)` type. 634 | When encoding, if the value is Nothing then the field is not included. 635 | -} 636 | optionalMaybeField : String -> (a -> Maybe f) -> Codec (Maybe f) -> ObjectCodec a (Maybe f -> b) -> ObjectCodec a b 637 | optionalMaybeField name getter codec (ObjectCodec ocodec) = 638 | ObjectCodec 639 | { encoder = 640 | \v -> 641 | case getter v of 642 | Just present -> 643 | ( name, encoder codec (Just present) ) :: ocodec.encoder v 644 | 645 | Nothing -> 646 | ocodec.encoder v 647 | , decoder = 648 | -- Decoder inspired by https://github.com/elm-community/json-extra/blob/4.3.0/src/Json/Decode/Extra.elm#L272 649 | JD.keyValuePairs JD.value 650 | |> JD.andThen 651 | (\json -> 652 | if List.any (\( k, _ ) -> k == name) json then 653 | --The field exist, actually run the decoder 654 | JD.field name (decoder codec) 655 | 656 | else 657 | -- The field is missing 658 | JD.succeed Nothing 659 | ) 660 | |> JD.map2 (\f x -> f x) ocodec.decoder 661 | , fields = name :: ocodec.fields 662 | } 663 | 664 | 665 | {-| Specify the name getter and `Codec` for an optional field. 666 | 667 | This is particularly useful for evolving your `Codec`s. 668 | 669 | If the field is not present in the input then it gets decoded to `Nothing`. If the field cannot be decoded this will fail. If the value is `null` then this will succeed with `Nothing`, use `optionalField` if you want it to fail instad. 670 | If the optional field's value is `Nothing` then the resulting object will not contain that field. 671 | 672 | -} 673 | optionalNullableField : String -> (a -> Maybe f) -> Codec f -> ObjectCodec a (Maybe f -> b) -> ObjectCodec a b 674 | optionalNullableField name getter codec (ObjectCodec ocodec) = 675 | ObjectCodec 676 | { encoder = 677 | \v -> 678 | case getter v of 679 | Just present -> 680 | ( name, encoder codec present ) :: ocodec.encoder v 681 | 682 | Nothing -> 683 | ocodec.encoder v 684 | , decoder = 685 | -- Decoder inspired by https://github.com/elm-community/json-extra/blob/4.3.0/src/Json/Decode/Extra.elm#L272 686 | JD.keyValuePairs JD.value 687 | |> JD.andThen 688 | (\json -> 689 | if List.any (\( k, _ ) -> k == name) json then 690 | --The field exist, actually run the decoder 691 | JD.field name (JD.nullable <| decoder codec) 692 | 693 | else 694 | -- The field is missing 695 | JD.succeed Nothing 696 | ) 697 | |> JD.map2 (\f x -> f x) ocodec.decoder 698 | , fields = name :: ocodec.fields 699 | } 700 | 701 | 702 | {-| Specify the name getter and `Codec` for a required field, whose value can be `null`. 703 | 704 | **Warning! This is a footgun and thus deprecated, you should probably use `field` with `nullable` instead.** 705 | 706 | If the field is not present in the input then _the decoding fails_. If the field is present but can't be decoded then _the decoding succeeds with `Nothing`_. 707 | If the field's value is `Nothing` then the resulting object will contain the field with a `null` value. 708 | 709 | This is a shorthand for a field having a `Codec` built using `maybe`. 710 | 711 | -} 712 | nullableField : String -> (a -> Maybe f) -> Codec f -> ObjectCodec a (Maybe f -> b) -> ObjectCodec a b 713 | nullableField name getter codec ocodec = 714 | field name getter (maybe codec) ocodec 715 | 716 | 717 | {-| Create a `Codec` from a fully specified `ObjectCodec`. 718 | -} 719 | buildObject : ObjectCodec a a -> Codec a 720 | buildObject (ObjectCodec om) = 721 | Codec 722 | { encoder = \v -> JE.object <| List.reverse <| om.encoder v 723 | , decoder = om.decoder 724 | } 725 | 726 | 727 | 728 | -- CUSTOM 729 | 730 | 731 | {-| A partially built `Codec` for a custom type. 732 | -} 733 | type CustomCodec match v 734 | = CustomCodec 735 | { match : match 736 | , decoder : Dict String (Decoder v) 737 | } 738 | 739 | 740 | {-| Starts building a `Codec` for a custom type. 741 | 742 | You need to pass a pattern matching function, built like this: 743 | 744 | type Semaphore 745 | = Red Int String 746 | | Yellow 747 | | Green Float 748 | 749 | semaphoreCodec : Codec Semaphore 750 | semaphoreCodec = 751 | Codec.custom 752 | (\red yellow green value -> 753 | case value of 754 | Red i s -> 755 | red i s 756 | 757 | Yellow -> 758 | yellow 759 | 760 | Green f -> 761 | green f 762 | ) 763 | |> Codec.variant2 "Red" Red Codec.int Codec.string 764 | |> Codec.variant0 "Yellow" Yellow 765 | |> Codec.variant1 "Green" Green Codec.float 766 | |> Codec.buildCustom 767 | 768 | -} 769 | custom : match -> CustomCodec match value 770 | custom match = 771 | CustomCodec 772 | { match = match 773 | , decoder = Dict.empty 774 | } 775 | 776 | 777 | variant : 778 | String 779 | -> ((List Value -> Value) -> a) 780 | -> Decoder v 781 | -> CustomCodec (a -> b) v 782 | -> CustomCodec b v 783 | variant name matchPiece decoderPiece (CustomCodec am) = 784 | let 785 | enc : List JE.Value -> JE.Value 786 | enc v = 787 | JE.object 788 | [ ( "tag", JE.string name ) 789 | , ( "args", JE.list identity v ) 790 | ] 791 | in 792 | CustomCodec 793 | { match = am.match <| matchPiece enc 794 | , decoder = Dict.insert name decoderPiece am.decoder 795 | } 796 | 797 | 798 | {-| Define a variant with 0 parameters for a custom type. 799 | -} 800 | variant0 : 801 | String 802 | -> v 803 | -> CustomCodec (Value -> a) v 804 | -> CustomCodec a v 805 | variant0 name ctor = 806 | variant name 807 | (\c -> c []) 808 | (JD.succeed ctor) 809 | 810 | 811 | {-| Define a variant with 1 parameters for a custom type. 812 | -} 813 | variant1 : 814 | String 815 | -> (a -> v) 816 | -> Codec a 817 | -> CustomCodec ((a -> Value) -> b) v 818 | -> CustomCodec b v 819 | variant1 name ctor m1 = 820 | variant name 821 | (\c v -> 822 | c 823 | [ encoder m1 v 824 | ] 825 | ) 826 | (JD.map ctor 827 | (JD.index 0 <| decoder m1) 828 | ) 829 | 830 | 831 | {-| Define a variant with 2 parameters for a custom type. 832 | -} 833 | variant2 : 834 | String 835 | -> (a -> b -> v) 836 | -> Codec a 837 | -> Codec b 838 | -> CustomCodec ((a -> b -> Value) -> c) v 839 | -> CustomCodec c v 840 | variant2 name ctor m1 m2 = 841 | variant name 842 | (\c v1 v2 -> 843 | c 844 | [ encoder m1 v1 845 | , encoder m2 v2 846 | ] 847 | ) 848 | (JD.map2 ctor 849 | (JD.index 0 <| decoder m1) 850 | (JD.index 1 <| decoder m2) 851 | ) 852 | 853 | 854 | {-| Define a variant with 3 parameters for a custom type. 855 | -} 856 | variant3 : 857 | String 858 | -> (a -> b -> c -> v) 859 | -> Codec a 860 | -> Codec b 861 | -> Codec c 862 | -> CustomCodec ((a -> b -> c -> Value) -> partial) v 863 | -> CustomCodec partial v 864 | variant3 name ctor m1 m2 m3 = 865 | variant name 866 | (\c v1 v2 v3 -> 867 | c 868 | [ encoder m1 v1 869 | , encoder m2 v2 870 | , encoder m3 v3 871 | ] 872 | ) 873 | (JD.map3 ctor 874 | (JD.index 0 <| decoder m1) 875 | (JD.index 1 <| decoder m2) 876 | (JD.index 2 <| decoder m3) 877 | ) 878 | 879 | 880 | {-| Define a variant with 4 parameters for a custom type. 881 | -} 882 | variant4 : 883 | String 884 | -> (a -> b -> c -> d -> v) 885 | -> Codec a 886 | -> Codec b 887 | -> Codec c 888 | -> Codec d 889 | -> CustomCodec ((a -> b -> c -> d -> Value) -> partial) v 890 | -> CustomCodec partial v 891 | variant4 name ctor m1 m2 m3 m4 = 892 | variant name 893 | (\c v1 v2 v3 v4 -> 894 | c 895 | [ encoder m1 v1 896 | , encoder m2 v2 897 | , encoder m3 v3 898 | , encoder m4 v4 899 | ] 900 | ) 901 | (JD.map4 ctor 902 | (JD.index 0 <| decoder m1) 903 | (JD.index 1 <| decoder m2) 904 | (JD.index 2 <| decoder m3) 905 | (JD.index 3 <| decoder m4) 906 | ) 907 | 908 | 909 | {-| Define a variant with 5 parameters for a custom type. 910 | -} 911 | variant5 : 912 | String 913 | -> (a -> b -> c -> d -> e -> v) 914 | -> Codec a 915 | -> Codec b 916 | -> Codec c 917 | -> Codec d 918 | -> Codec e 919 | -> CustomCodec ((a -> b -> c -> d -> e -> Value) -> partial) v 920 | -> CustomCodec partial v 921 | variant5 name ctor m1 m2 m3 m4 m5 = 922 | variant name 923 | (\c v1 v2 v3 v4 v5 -> 924 | c 925 | [ encoder m1 v1 926 | , encoder m2 v2 927 | , encoder m3 v3 928 | , encoder m4 v4 929 | , encoder m5 v5 930 | ] 931 | ) 932 | (JD.map5 ctor 933 | (JD.index 0 <| decoder m1) 934 | (JD.index 1 <| decoder m2) 935 | (JD.index 2 <| decoder m3) 936 | (JD.index 3 <| decoder m4) 937 | (JD.index 4 <| decoder m5) 938 | ) 939 | 940 | 941 | {-| Define a variant with 6 parameters for a custom type. 942 | -} 943 | variant6 : 944 | String 945 | -> (a -> b -> c -> d -> e -> f -> v) 946 | -> Codec a 947 | -> Codec b 948 | -> Codec c 949 | -> Codec d 950 | -> Codec e 951 | -> Codec f 952 | -> CustomCodec ((a -> b -> c -> d -> e -> f -> Value) -> partial) v 953 | -> CustomCodec partial v 954 | variant6 name ctor m1 m2 m3 m4 m5 m6 = 955 | variant name 956 | (\c v1 v2 v3 v4 v5 v6 -> 957 | c 958 | [ encoder m1 v1 959 | , encoder m2 v2 960 | , encoder m3 v3 961 | , encoder m4 v4 962 | , encoder m5 v5 963 | , encoder m6 v6 964 | ] 965 | ) 966 | (JD.map6 ctor 967 | (JD.index 0 <| decoder m1) 968 | (JD.index 1 <| decoder m2) 969 | (JD.index 2 <| decoder m3) 970 | (JD.index 3 <| decoder m4) 971 | (JD.index 4 <| decoder m5) 972 | (JD.index 5 <| decoder m6) 973 | ) 974 | 975 | 976 | {-| Define a variant with 7 parameters for a custom type. 977 | -} 978 | variant7 : 979 | String 980 | -> (a -> b -> c -> d -> e -> f -> g -> v) 981 | -> Codec a 982 | -> Codec b 983 | -> Codec c 984 | -> Codec d 985 | -> Codec e 986 | -> Codec f 987 | -> Codec g 988 | -> CustomCodec ((a -> b -> c -> d -> e -> f -> g -> Value) -> partial) v 989 | -> CustomCodec partial v 990 | variant7 name ctor m1 m2 m3 m4 m5 m6 m7 = 991 | variant name 992 | (\c v1 v2 v3 v4 v5 v6 v7 -> 993 | c 994 | [ encoder m1 v1 995 | , encoder m2 v2 996 | , encoder m3 v3 997 | , encoder m4 v4 998 | , encoder m5 v5 999 | , encoder m6 v6 1000 | , encoder m7 v7 1001 | ] 1002 | ) 1003 | (JD.map7 ctor 1004 | (JD.index 0 <| decoder m1) 1005 | (JD.index 1 <| decoder m2) 1006 | (JD.index 2 <| decoder m3) 1007 | (JD.index 3 <| decoder m4) 1008 | (JD.index 4 <| decoder m5) 1009 | (JD.index 5 <| decoder m6) 1010 | (JD.index 6 <| decoder m7) 1011 | ) 1012 | 1013 | 1014 | {-| Define a variant with 8 parameters for a custom type. 1015 | -} 1016 | variant8 : 1017 | String 1018 | -> (a -> b -> c -> d -> e -> f -> g -> h -> v) 1019 | -> Codec a 1020 | -> Codec b 1021 | -> Codec c 1022 | -> Codec d 1023 | -> Codec e 1024 | -> Codec f 1025 | -> Codec g 1026 | -> Codec h 1027 | -> CustomCodec ((a -> b -> c -> d -> e -> f -> g -> h -> Value) -> partial) v 1028 | -> CustomCodec partial v 1029 | variant8 name ctor m1 m2 m3 m4 m5 m6 m7 m8 = 1030 | variant name 1031 | (\c v1 v2 v3 v4 v5 v6 v7 v8 -> 1032 | c 1033 | [ encoder m1 v1 1034 | , encoder m2 v2 1035 | , encoder m3 v3 1036 | , encoder m4 v4 1037 | , encoder m5 v5 1038 | , encoder m6 v6 1039 | , encoder m7 v7 1040 | , encoder m8 v8 1041 | ] 1042 | ) 1043 | (JD.map8 ctor 1044 | (JD.index 0 <| decoder m1) 1045 | (JD.index 1 <| decoder m2) 1046 | (JD.index 2 <| decoder m3) 1047 | (JD.index 3 <| decoder m4) 1048 | (JD.index 4 <| decoder m5) 1049 | (JD.index 5 <| decoder m6) 1050 | (JD.index 6 <| decoder m7) 1051 | (JD.index 7 <| decoder m8) 1052 | ) 1053 | 1054 | 1055 | {-| Build a `Codec` for a fully specified custom type. 1056 | -} 1057 | buildCustom : CustomCodec (a -> Value) a -> Codec a 1058 | buildCustom (CustomCodec am) = 1059 | Codec 1060 | { encoder = \v -> am.match v 1061 | , decoder = 1062 | JD.field "tag" JD.string 1063 | |> JD.andThen 1064 | (\tag -> 1065 | case Dict.get tag am.decoder of 1066 | Nothing -> 1067 | JD.fail <| "tag " ++ tag ++ " did not match" 1068 | 1069 | Just dec -> 1070 | JD.field "args" dec 1071 | ) 1072 | } 1073 | 1074 | 1075 | 1076 | -- INCONSISTENT STRUCTURE 1077 | 1078 | 1079 | {-| Try a set of decoders (in order). 1080 | The first argument is used for encoding and decoding, the list of other codecs is used as a fallback while decoding. 1081 | 1082 | This is particularly useful for backwards compatibility. You would pass the current codec as the first argument, 1083 | and the old ones (eventually `map`ped) as a fallback list to use while decoding. 1084 | 1085 | -} 1086 | oneOf : Codec a -> List (Codec a) -> Codec a 1087 | oneOf main alts = 1088 | Codec 1089 | { encoder = encoder main 1090 | , decoder = JD.oneOf <| decoder main :: List.map decoder alts 1091 | } 1092 | 1093 | 1094 | 1095 | -- MAPPING 1096 | 1097 | 1098 | {-| Transform a `Codec`. 1099 | -} 1100 | map : (a -> b) -> (b -> a) -> Codec a -> Codec b 1101 | map go back codec = 1102 | Codec 1103 | { decoder = JD.map go <| decoder codec 1104 | , encoder = \v -> back v |> encoder codec 1105 | } 1106 | 1107 | 1108 | 1109 | -- FANCY 1110 | 1111 | 1112 | {-| Ignore the JSON and make the decoder fail. This is handy when used with 1113 | `oneOf` or `andThen` where you want to give a custom error message in some 1114 | case. The encoder will produce `null`. 1115 | -} 1116 | fail : String -> Codec a 1117 | fail msg = 1118 | Codec 1119 | { decoder = JD.fail msg 1120 | , encoder = always JE.null 1121 | } 1122 | 1123 | 1124 | {-| Create codecs that depend on previous results. 1125 | -} 1126 | andThen : (a -> Codec b) -> (b -> a) -> Codec a -> Codec b 1127 | andThen dec enc c = 1128 | Codec 1129 | { decoder = decoder c |> JD.andThen (dec >> decoder) 1130 | , encoder = encoder c << enc 1131 | } 1132 | 1133 | 1134 | {-| Create a `Codec` for a recursive data structure. 1135 | The argument to the function you need to pass is the fully formed `Codec`. 1136 | -} 1137 | recursive : (Codec a -> Codec a) -> Codec a 1138 | recursive f = 1139 | f <| lazy (\_ -> recursive f) 1140 | 1141 | 1142 | {-| Create a `Codec` that produces null as JSON and always decodes as the same value. 1143 | -} 1144 | succeed : a -> Codec a 1145 | succeed default_ = 1146 | Codec 1147 | { decoder = JD.succeed default_ 1148 | , encoder = \_ -> JE.null 1149 | } 1150 | 1151 | 1152 | {-| Create a `Codec` that produces null as JSON and always decodes as the same value. Obsolete alias of `succeed`, will be removed in a future version. 1153 | -} 1154 | constant : a -> Codec a 1155 | constant = 1156 | succeed 1157 | 1158 | 1159 | {-| This is useful for recursive structures that are not easily modeled with `recursive`. 1160 | Have a look at the Json.Decode docs for examples. 1161 | -} 1162 | lazy : (() -> Codec a) -> Codec a 1163 | lazy f = 1164 | Codec 1165 | { decoder = JD.lazy (\_ -> decoder <| f ()) 1166 | , encoder = \v -> encoder (f ()) v 1167 | } 1168 | 1169 | 1170 | {-| Create a `Codec` that doesn't transform the JSON value, just brings it to and from Elm as a `Value`. 1171 | -} 1172 | value : Codec Value 1173 | value = 1174 | Codec 1175 | { encoder = identity 1176 | , decoder = JD.value 1177 | } 1178 | -------------------------------------------------------------------------------- /tests/Base.elm: -------------------------------------------------------------------------------- 1 | module Base exposing (roundtrips, suite) 2 | 3 | import Codec exposing (Codec) 4 | import Dict 5 | import Expect 6 | import Fuzz exposing (Fuzzer) 7 | import Set 8 | import Test exposing (Test, describe, fuzz, test) 9 | 10 | 11 | suite : Test 12 | suite = 13 | describe "Testing roundtrips" 14 | [ describe "Basic" basicTests 15 | , describe "Containers" containersTests 16 | , describe "Object" objectTests 17 | , describe "Custom" customTests 18 | , describe "bimap" bimapTests 19 | , describe "maybe" maybeTests 20 | , describe "nullable" nullableTests 21 | , describe "succeed" 22 | [ test "roundtrips" 23 | (\_ -> 24 | let 25 | codec : Codec number 26 | codec = 27 | Codec.succeed 632 28 | in 29 | Codec.decodeString codec "{}" 30 | |> Expect.equal (Ok 632) 31 | ) 32 | ] 33 | , describe "recursive" recursiveTests 34 | , describe "map,andThen" mapAndThenTests 35 | ] 36 | 37 | 38 | roundtrips : Fuzzer a -> Codec a -> Test 39 | roundtrips fuzzer codec = 40 | fuzz fuzzer "is a roundtrip" <| 41 | \value -> 42 | value 43 | |> Codec.encoder codec 44 | |> Codec.decodeValue codec 45 | |> Expect.equal (Ok value) 46 | 47 | 48 | roundtripsWithin : Fuzzer Float -> Codec Float -> Test 49 | roundtripsWithin fuzzer codec = 50 | fuzz fuzzer "is a roundtrip" <| 51 | \value -> 52 | case 53 | value 54 | |> Codec.encoder codec 55 | |> Codec.decodeValue codec 56 | of 57 | Err _ -> 58 | Expect.fail "Decoding failed" 59 | 60 | Ok v -> 61 | if isNaN value then 62 | if isNaN v then 63 | Expect.pass 64 | 65 | else 66 | Expect.fail "NaN decoded to non-NaN" 67 | 68 | else 69 | v 70 | |> Expect.within (Expect.Relative 0.000001) value 71 | 72 | 73 | basicTests : List Test 74 | basicTests = 75 | [ describe "Codec.string" 76 | [ roundtrips Fuzz.string Codec.string 77 | ] 78 | , describe "Codec.int" 79 | [ roundtrips Fuzz.int Codec.int 80 | ] 81 | , describe "Codec.float" 82 | [ roundtrips 83 | (Fuzz.oneOf 84 | [ Fuzz.niceFloat 85 | , Fuzz.constant (1 / 0) 86 | , Fuzz.constant (-1 / 0) 87 | ] 88 | ) 89 | Codec.float 90 | , describe "Works for NaN" 91 | [ roundtripsWithin Fuzz.float Codec.float 92 | ] 93 | ] 94 | , describe "Codec.bool" 95 | [ roundtrips Fuzz.bool Codec.bool 96 | ] 97 | ] 98 | 99 | 100 | containersTests : List Test 101 | containersTests = 102 | [ describe "Codec.array" 103 | [ roundtrips (Fuzz.array Fuzz.int) (Codec.array Codec.int) 104 | ] 105 | , describe "Codec.list" 106 | [ roundtrips (Fuzz.list Fuzz.int) (Codec.list Codec.int) 107 | ] 108 | , describe "Codec.dict" 109 | [ roundtrips 110 | (Fuzz.map2 Tuple.pair Fuzz.string Fuzz.int 111 | |> Fuzz.list 112 | |> Fuzz.map Dict.fromList 113 | ) 114 | (Codec.dict Codec.int) 115 | ] 116 | , describe "Codec.set" 117 | [ roundtrips 118 | (Fuzz.list Fuzz.int |> Fuzz.map Set.fromList) 119 | (Codec.set Codec.int) 120 | ] 121 | , describe "Codec.tuple" 122 | [ roundtrips 123 | (Fuzz.pair Fuzz.int Fuzz.int) 124 | (Codec.tuple Codec.int Codec.int) 125 | ] 126 | ] 127 | 128 | 129 | objectTests : List Test 130 | objectTests = 131 | [ describe "with 0 fields" 132 | [ roundtrips (Fuzz.constant {}) 133 | (Codec.object {} 134 | |> Codec.buildObject 135 | ) 136 | ] 137 | , describe "with 1 field" 138 | [ roundtrips (Fuzz.map (\i -> { fname = i }) Fuzz.int) 139 | (Codec.object (\i -> { fname = i }) 140 | |> Codec.field "fname" .fname Codec.int 141 | |> Codec.buildObject 142 | ) 143 | ] 144 | , describe "with 2 fields" 145 | [ roundtrips 146 | (Fuzz.map2 147 | (\a b -> 148 | { a = a 149 | , b = b 150 | } 151 | ) 152 | Fuzz.int 153 | Fuzz.int 154 | ) 155 | (Codec.object 156 | (\a b -> 157 | { a = a 158 | , b = b 159 | } 160 | ) 161 | |> Codec.field "a" .a Codec.int 162 | |> Codec.field "b" .b Codec.int 163 | |> Codec.buildObject 164 | ) 165 | ] 166 | , describe "nullableField vs maybeField" <| 167 | let 168 | nullableCodec : Codec { f : Maybe Int } 169 | nullableCodec = 170 | Codec.object 171 | (\f -> { f = f }) 172 | |> Codec.nullableField "f" .f Codec.int 173 | |> Codec.buildObject 174 | 175 | maybeCodec : Codec { f : Maybe Int } 176 | maybeCodec = 177 | Codec.object 178 | (\f -> { f = f }) 179 | |> Codec.maybeField "f" .f Codec.int 180 | |> Codec.buildObject 181 | in 182 | [ test "a nullableField is required" <| 183 | \_ -> 184 | "{}" 185 | |> Codec.decodeString nullableCodec 186 | |> (\r -> 187 | case r of 188 | Ok _ -> 189 | Expect.fail "Should have failed" 190 | 191 | Err _ -> 192 | Expect.pass 193 | ) 194 | , test "a nullableField produces a field with a null value on encoding Nothing" <| 195 | \_ -> 196 | { f = Nothing } 197 | |> Codec.encodeToString 0 nullableCodec 198 | |> Expect.equal "{\"f\":null}" 199 | , test "a maybeField is optional" <| 200 | \_ -> 201 | "{}" 202 | |> Codec.decodeString maybeCodec 203 | |> Expect.equal (Ok { f = Nothing }) 204 | , test "a maybeField doesn't produce a field on encoding Nothing" <| 205 | \_ -> 206 | { f = Nothing } 207 | |> Codec.encodeToString 0 maybeCodec 208 | |> Expect.equal "{}" 209 | ] 210 | ] 211 | 212 | 213 | type Empty 214 | = Empty 215 | 216 | 217 | type Newtype a 218 | = Newtype a 219 | 220 | 221 | customTests : List Test 222 | customTests = 223 | [ describe "with 1 ctor, 0 args" 224 | [ roundtrips (Fuzz.constant Empty) 225 | (Codec.custom 226 | (\f v -> 227 | case v of 228 | Empty -> 229 | f 230 | ) 231 | |> Codec.variant0 "Empty" Empty 232 | |> Codec.buildCustom 233 | ) 234 | ] 235 | , describe "with 1 ctor, 1 arg" 236 | [ roundtrips (Fuzz.map Newtype Fuzz.int) 237 | (Codec.custom 238 | (\f v -> 239 | case v of 240 | Newtype a -> 241 | f a 242 | ) 243 | |> Codec.variant1 "Newtype" Newtype Codec.int 244 | |> Codec.buildCustom 245 | ) 246 | ] 247 | , describe "with 2 ctors, 0,1 args" <| 248 | let 249 | match : b -> (a -> b) -> Maybe a -> b 250 | match fnothing fjust value = 251 | case value of 252 | Nothing -> 253 | fnothing 254 | 255 | Just v -> 256 | fjust v 257 | 258 | codec : Codec (Maybe Int) 259 | codec = 260 | Codec.custom match 261 | |> Codec.variant0 "Nothing" Nothing 262 | |> Codec.variant1 "Just" Just Codec.int 263 | |> Codec.buildCustom 264 | 265 | fuzzers : List ( String, Fuzzer (Maybe Int) ) 266 | fuzzers = 267 | [ ( "1st ctor", Fuzz.constant Nothing ) 268 | , ( "2nd ctor", Fuzz.map Just Fuzz.int ) 269 | ] 270 | in 271 | fuzzers 272 | |> List.map 273 | (\( name, fuzz ) -> 274 | describe name 275 | [ roundtrips fuzz codec ] 276 | ) 277 | ] 278 | 279 | 280 | bimapTests : List Test 281 | bimapTests = 282 | [ roundtripsWithin Fuzz.float <| 283 | Codec.map 284 | (\x -> x * 2) 285 | (\x -> x / 2) 286 | Codec.float 287 | ] 288 | 289 | 290 | maybeTests : List Test 291 | maybeTests = 292 | [ describe "single" 293 | [ roundtrips 294 | (Fuzz.oneOf 295 | [ Fuzz.constant Nothing 296 | , Fuzz.map Just Fuzz.int 297 | ] 298 | ) 299 | <| 300 | Codec.maybe Codec.int 301 | ] 302 | , test "Decodes wrong types to Nothing" <| 303 | \_ -> 304 | "3" 305 | |> Codec.decodeString (Codec.maybe Codec.string) 306 | |> Expect.equal (Ok Nothing) 307 | 308 | {- 309 | This is a known limitation: using null as Nothing and identity as Just means that nesting two maybes squashes Just Nothing with Nothing 310 | , describe "double" 311 | [ roundtrips 312 | (Fuzz.oneOf 313 | [ Fuzz.constant Nothing 314 | , Fuzz.constant <| Just Nothing 315 | , Fuzz.map (Just << Just) Fuzz.int 316 | ] 317 | ) 318 | <| 319 | Codec.maybe <| 320 | Codec.maybe Codec.int 321 | ] 322 | -} 323 | ] 324 | 325 | 326 | nullableTests : List Test 327 | nullableTests = 328 | [ describe "single" 329 | [ roundtrips 330 | (Fuzz.oneOf 331 | [ Fuzz.constant Nothing 332 | , Fuzz.map Just Fuzz.int 333 | ] 334 | ) 335 | <| 336 | Codec.nullable Codec.int 337 | ] 338 | , test "Does not decode wrong types" <| 339 | \_ -> 340 | "3" 341 | |> Codec.decodeString (Codec.nullable Codec.string) 342 | |> Expect.notEqual (Ok Nothing) 343 | ] 344 | 345 | 346 | recursiveTests : List Test 347 | recursiveTests = 348 | [ describe "list" 349 | [ roundtrips (Fuzz.list Fuzz.int) <| 350 | Codec.recursive 351 | (\c -> 352 | Codec.custom 353 | (\fempty fcons value -> 354 | case value of 355 | [] -> 356 | fempty 357 | 358 | x :: xs -> 359 | fcons x xs 360 | ) 361 | |> Codec.variant0 "[]" [] 362 | |> Codec.variant2 "(::)" (::) Codec.int c 363 | |> Codec.buildCustom 364 | ) 365 | ] 366 | ] 367 | 368 | 369 | mapAndThenTests : List Test 370 | mapAndThenTests = 371 | [ describe "Codec.map" 372 | [ roundtrips (Fuzz.intRange -10000 10000) <| 373 | Codec.map (\x -> x - 1) (\x -> x + 1) Codec.int 374 | ] 375 | ] 376 | -------------------------------------------------------------------------------- /tests/Fields.elm: -------------------------------------------------------------------------------- 1 | module Fields exposing (suite) 2 | 3 | import Codec 4 | import Expect 5 | import Test exposing (Test, describe, test) 6 | 7 | 8 | suite : Test 9 | suite = 10 | [ testField 11 | "field" 12 | Codec.field 13 | { good = Expect.equal (Ok 3) 14 | , missing = Expect.err 15 | , null = Expect.err 16 | , bad = Expect.err 17 | , notObject = Expect.err 18 | } 19 | , testField 20 | "maybeField" 21 | Codec.maybeField 22 | { good = Expect.equal (Ok (Just 3)) 23 | , missing = Expect.equal (Ok Nothing) 24 | , null = Expect.equal (Ok Nothing) 25 | , bad = Expect.equal (Ok Nothing) 26 | , notObject = Expect.equal (Ok Nothing) 27 | } 28 | , testField 29 | "nullableField" 30 | Codec.nullableField 31 | { good = Expect.equal (Ok (Just 3)) 32 | , missing = Expect.err 33 | , null = Expect.equal (Ok Nothing) 34 | , bad = Expect.equal (Ok Nothing) 35 | , notObject = Expect.err 36 | } 37 | , testField 38 | "optionalField" 39 | Codec.optionalField 40 | { good = Expect.equal (Ok (Just 3)) 41 | , missing = Expect.equal (Ok Nothing) 42 | , null = Expect.err 43 | , bad = Expect.err 44 | , notObject = Expect.err 45 | } 46 | , testField 47 | "optionalNullableField" 48 | Codec.optionalNullableField 49 | { good = Expect.equal (Ok (Just 3)) 50 | , missing = Expect.equal (Ok Nothing) 51 | , null = Expect.equal (Ok Nothing) 52 | , bad = Expect.err 53 | , notObject = Expect.err 54 | } 55 | ] 56 | |> describe "Testing the various field variants" 57 | 58 | 59 | testField : 60 | String 61 | -> (String -> (t -> t) -> Codec.Codec Int -> Codec.ObjectCodec b (c -> c) -> Codec.ObjectCodec t t) 62 | -> 63 | { good : Result Codec.Error t -> Expect.Expectation 64 | , missing : Result Codec.Error t -> Expect.Expectation 65 | , null : Result Codec.Error t -> Expect.Expectation 66 | , bad : Result Codec.Error t -> Expect.Expectation 67 | , notObject : Result Codec.Error t -> Expect.Expectation 68 | } 69 | -> Test 70 | testField label field expects = 71 | let 72 | inner : String -> String -> (Result Codec.Error t -> Expect.Expectation) -> Test 73 | inner testLabel input expect = 74 | test (testLabel ++ ": " ++ input) <| 75 | \_ -> 76 | input 77 | |> Codec.decodeString 78 | (Codec.object identity 79 | |> field "a" identity Codec.int 80 | |> Codec.buildObject 81 | ) 82 | |> expect 83 | in 84 | [ inner "Good field" "{ \"a\": 3 }" expects.good 85 | , inner "Missing field" "{}" expects.missing 86 | , inner "Null field" "{ \"a\": null }" expects.null 87 | , inner "Bad field" "{ \"a\": \"b\" }" expects.bad 88 | , inner "Not object" "3" expects.notObject 89 | ] 90 | |> describe label 91 | -------------------------------------------------------------------------------- /tests/Forward.elm: -------------------------------------------------------------------------------- 1 | module Forward exposing (suite) 2 | 3 | import Base 4 | import Codec exposing (Codec) 5 | import Expect 6 | import Fuzz exposing (Fuzzer) 7 | import Json.Decode as JD 8 | import Test exposing (Test, describe, fuzz) 9 | 10 | 11 | suite : Test 12 | suite = 13 | describe "Testing forward and backward compat" 14 | [ -- describe "Adding a variant" addVariant 15 | --, describe "Remove parameters" removeParameters 16 | describe "Any to succeed" anyToSucceed 17 | , describe "Add optional field" addMaybeField 18 | ] 19 | 20 | 21 | compatible : Fuzzer a -> (a -> b) -> Codec a -> Codec b -> Test 22 | compatible fuzzer map oldCodec newCodec = 23 | fuzz fuzzer "compatible" <| 24 | \value -> 25 | value 26 | |> Codec.encoder oldCodec 27 | |> JD.decodeValue (Codec.decoder newCodec) 28 | |> Expect.equal (Ok <| map value) 29 | 30 | 31 | forward : Fuzzer old -> (old -> new) -> Codec old -> Codec new -> Test 32 | forward fuzzer map oldCodec newCodec = 33 | describe "forward" 34 | [ describe "old" 35 | [ Base.roundtrips fuzzer oldCodec 36 | ] 37 | , describe "new" 38 | [ Base.roundtrips (Fuzz.map map fuzzer) newCodec 39 | ] 40 | , describe "old value with new codec" 41 | [ compatible fuzzer map oldCodec newCodec 42 | ] 43 | ] 44 | 45 | 46 | both : 47 | Fuzzer old 48 | -> (old -> new) 49 | -> Codec old 50 | -> Fuzzer new 51 | -> (new -> old) 52 | -> Codec new 53 | -> List Test 54 | both oldFuzzer oldToNew oldCodec newFuzzer newToOld newCodec = 55 | [ describe "old" 56 | [ Base.roundtrips oldFuzzer oldCodec 57 | ] 58 | , describe "new" 59 | [ Base.roundtrips newFuzzer newCodec 60 | ] 61 | , describe "old value with new codec" 62 | [ compatible oldFuzzer oldToNew oldCodec newCodec 63 | ] 64 | , describe "new value with old codec" 65 | [ compatible newFuzzer newToOld newCodec oldCodec 66 | ] 67 | ] 68 | 69 | 70 | anyToSucceed : List Test 71 | anyToSucceed = 72 | [ forward Fuzz.string (always 3) Codec.string (Codec.succeed 3) 73 | ] 74 | 75 | 76 | type alias Point2 = 77 | { x : Int 78 | , y : Int 79 | } 80 | 81 | 82 | point2Fuzzer : Fuzzer Point2 83 | point2Fuzzer = 84 | Fuzz.map2 Point2 Fuzz.int Fuzz.int 85 | 86 | 87 | point2Codec : Codec Point2 88 | point2Codec = 89 | Codec.object Point2 90 | |> Codec.field "x" .x Codec.int 91 | |> Codec.field "y" .y Codec.int 92 | |> Codec.buildObject 93 | 94 | 95 | type alias Point2_5 = 96 | { x : Int 97 | , y : Int 98 | , z : Maybe Int 99 | } 100 | 101 | 102 | point2_5Fuzzer : Fuzzer Point2_5 103 | point2_5Fuzzer = 104 | Fuzz.map3 Point2_5 Fuzz.int Fuzz.int (Fuzz.maybe Fuzz.int) 105 | 106 | 107 | point2_5Codec : Codec Point2_5 108 | point2_5Codec = 109 | Codec.object Point2_5 110 | |> Codec.field "x" .x Codec.int 111 | |> Codec.field "y" .y Codec.int 112 | |> Codec.maybeField "z" .z Codec.int 113 | |> Codec.buildObject 114 | 115 | 116 | addMaybeField : List Test 117 | addMaybeField = 118 | both 119 | point2Fuzzer 120 | (\{ x, y } -> { x = x, y = y, z = Nothing }) 121 | point2Codec 122 | point2_5Fuzzer 123 | (\{ x, y } -> { x = x, y = y }) 124 | point2_5Codec 125 | -------------------------------------------------------------------------------- /tests/elm-verify-examples.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": "../src", 3 | "tests": [ 4 | "Codec" 5 | ] 6 | } -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@isaacs/cliui@^8.0.2": 6 | version "8.0.2" 7 | resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" 8 | integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== 9 | dependencies: 10 | string-width "^5.1.2" 11 | string-width-cjs "npm:string-width@^4.2.0" 12 | strip-ansi "^7.0.1" 13 | strip-ansi-cjs "npm:strip-ansi@^6.0.1" 14 | wrap-ansi "^8.1.0" 15 | wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" 16 | 17 | "@pkgjs/parseargs@^0.11.0": 18 | version "0.11.0" 19 | resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" 20 | integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== 21 | 22 | "@sindresorhus/is@^4.0.0": 23 | version "4.6.0" 24 | resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" 25 | integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== 26 | 27 | "@szmarczak/http-timer@^4.0.5": 28 | version "4.0.6" 29 | resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" 30 | integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== 31 | dependencies: 32 | defer-to-connect "^2.0.0" 33 | 34 | "@types/cacheable-request@^6.0.1": 35 | version "6.0.3" 36 | resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" 37 | integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw== 38 | dependencies: 39 | "@types/http-cache-semantics" "*" 40 | "@types/keyv" "^3.1.4" 41 | "@types/node" "*" 42 | "@types/responselike" "^1.0.0" 43 | 44 | "@types/http-cache-semantics@*": 45 | version "4.0.1" 46 | resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" 47 | integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== 48 | 49 | "@types/keyv@^3.1.4": 50 | version "3.1.4" 51 | resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" 52 | integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== 53 | dependencies: 54 | "@types/node" "*" 55 | 56 | "@types/node@*": 57 | version "20.5.7" 58 | resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.7.tgz#4b8ecac87fbefbc92f431d09c30e176fc0a7c377" 59 | integrity sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA== 60 | 61 | "@types/responselike@^1.0.0": 62 | version "1.0.0" 63 | resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" 64 | integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== 65 | dependencies: 66 | "@types/node" "*" 67 | 68 | ansi-escapes@^4.2.1: 69 | version "4.3.2" 70 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" 71 | integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== 72 | dependencies: 73 | type-fest "^0.21.3" 74 | 75 | ansi-regex@^5.0.1: 76 | version "5.0.1" 77 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 78 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 79 | 80 | ansi-regex@^6.0.1: 81 | version "6.0.1" 82 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" 83 | integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== 84 | 85 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 86 | version "4.3.0" 87 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 88 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 89 | dependencies: 90 | color-convert "^2.0.1" 91 | 92 | ansi-styles@^6.1.0: 93 | version "6.2.1" 94 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" 95 | integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== 96 | 97 | anymatch@~3.1.2: 98 | version "3.1.3" 99 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" 100 | integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== 101 | dependencies: 102 | normalize-path "^3.0.0" 103 | picomatch "^2.0.4" 104 | 105 | at-least-node@^1.0.0: 106 | version "1.0.0" 107 | resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" 108 | integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== 109 | 110 | balanced-match@^1.0.0: 111 | version "1.0.2" 112 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 113 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 114 | 115 | base64-js@^1.3.1: 116 | version "1.5.1" 117 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" 118 | integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== 119 | 120 | binary-extensions@^2.0.0: 121 | version "2.2.0" 122 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" 123 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== 124 | 125 | bl@^4.1.0: 126 | version "4.1.0" 127 | resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" 128 | integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== 129 | dependencies: 130 | buffer "^5.5.0" 131 | inherits "^2.0.4" 132 | readable-stream "^3.4.0" 133 | 134 | brace-expansion@^1.1.7: 135 | version "1.1.11" 136 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 137 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 138 | dependencies: 139 | balanced-match "^1.0.0" 140 | concat-map "0.0.1" 141 | 142 | brace-expansion@^2.0.1: 143 | version "2.0.1" 144 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" 145 | integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== 146 | dependencies: 147 | balanced-match "^1.0.0" 148 | 149 | braces@~3.0.2: 150 | version "3.0.3" 151 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" 152 | integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== 153 | dependencies: 154 | fill-range "^7.1.1" 155 | 156 | buffer@^5.5.0: 157 | version "5.7.1" 158 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" 159 | integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== 160 | dependencies: 161 | base64-js "^1.3.1" 162 | ieee754 "^1.1.13" 163 | 164 | cacheable-lookup@^5.0.3: 165 | version "5.0.4" 166 | resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" 167 | integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== 168 | 169 | cacheable-request@^7.0.2: 170 | version "7.0.4" 171 | resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.4.tgz#7a33ebf08613178b403635be7b899d3e69bbe817" 172 | integrity sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg== 173 | dependencies: 174 | clone-response "^1.0.2" 175 | get-stream "^5.1.0" 176 | http-cache-semantics "^4.0.0" 177 | keyv "^4.0.0" 178 | lowercase-keys "^2.0.0" 179 | normalize-url "^6.0.1" 180 | responselike "^2.0.0" 181 | 182 | chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: 183 | version "4.1.2" 184 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 185 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 186 | dependencies: 187 | ansi-styles "^4.1.0" 188 | supports-color "^7.1.0" 189 | 190 | chokidar@^3.5.2, chokidar@^3.5.3: 191 | version "3.5.3" 192 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" 193 | integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== 194 | dependencies: 195 | anymatch "~3.1.2" 196 | braces "~3.0.2" 197 | glob-parent "~5.1.2" 198 | is-binary-path "~2.1.0" 199 | is-glob "~4.0.1" 200 | normalize-path "~3.0.0" 201 | readdirp "~3.6.0" 202 | optionalDependencies: 203 | fsevents "~2.3.2" 204 | 205 | cli-cursor@^3.1.0: 206 | version "3.1.0" 207 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" 208 | integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== 209 | dependencies: 210 | restore-cursor "^3.1.0" 211 | 212 | cli-spinners@^2.5.0: 213 | version "2.9.0" 214 | resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.0.tgz#5881d0ad96381e117bbe07ad91f2008fe6ffd8db" 215 | integrity sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g== 216 | 217 | cliui@^8.0.1: 218 | version "8.0.1" 219 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" 220 | integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== 221 | dependencies: 222 | string-width "^4.2.0" 223 | strip-ansi "^6.0.1" 224 | wrap-ansi "^7.0.0" 225 | 226 | clone-response@^1.0.2: 227 | version "1.0.3" 228 | resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" 229 | integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== 230 | dependencies: 231 | mimic-response "^1.0.0" 232 | 233 | clone@^1.0.2: 234 | version "1.0.4" 235 | resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" 236 | integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== 237 | 238 | color-convert@^2.0.1: 239 | version "2.0.1" 240 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 241 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 242 | dependencies: 243 | color-name "~1.1.4" 244 | 245 | color-name@~1.1.4: 246 | version "1.1.4" 247 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 248 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 249 | 250 | commander@^9.4.1: 251 | version "9.5.0" 252 | resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" 253 | integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== 254 | 255 | concat-map@0.0.1: 256 | version "0.0.1" 257 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 258 | integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== 259 | 260 | cross-spawn@^7.0.0, cross-spawn@^7.0.3: 261 | version "7.0.6" 262 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" 263 | integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== 264 | dependencies: 265 | path-key "^3.1.0" 266 | shebang-command "^2.0.0" 267 | which "^2.0.1" 268 | 269 | debug@^4.1.1: 270 | version "4.3.4" 271 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" 272 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 273 | dependencies: 274 | ms "2.1.2" 275 | 276 | decompress-response@^6.0.0: 277 | version "6.0.0" 278 | resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" 279 | integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== 280 | dependencies: 281 | mimic-response "^3.1.0" 282 | 283 | defaults@^1.0.3: 284 | version "1.0.4" 285 | resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" 286 | integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== 287 | dependencies: 288 | clone "^1.0.2" 289 | 290 | defer-to-connect@^2.0.0: 291 | version "2.0.1" 292 | resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" 293 | integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== 294 | 295 | eastasianwidth@^0.2.0: 296 | version "0.2.0" 297 | resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" 298 | integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== 299 | 300 | elm-review@^2.10.2: 301 | version "2.10.2" 302 | resolved "https://registry.yarnpkg.com/elm-review/-/elm-review-2.10.2.tgz#45244ab78aa276ef0353a960f068393c7d7fffce" 303 | integrity sha512-9cgv3ILetV/Gb/cr42ZHYWHK5hrnl1UsGuxah1DL/NI6EZlu+GrwaSng4DvYsETrccaoNzRJMuhfv7JoPCdK/A== 304 | dependencies: 305 | chalk "^4.0.0" 306 | chokidar "^3.5.2" 307 | cross-spawn "^7.0.3" 308 | elm-tooling "^1.6.0" 309 | fast-levenshtein "^3.0.0" 310 | find-up "^4.1.0" 311 | folder-hash "^3.3.0" 312 | fs-extra "^9.0.0" 313 | glob "^7.1.4" 314 | got "^11.8.5" 315 | graceful-fs "^4.2.11" 316 | minimist "^1.2.6" 317 | ora "^5.4.0" 318 | path-key "^3.1.1" 319 | prompts "^2.2.1" 320 | rimraf "^5.0.0" 321 | strip-ansi "^6.0.0" 322 | terminal-link "^2.1.1" 323 | which "^2.0.2" 324 | wrap-ansi "^6.2.0" 325 | 326 | elm-solve-deps-wasm@^1.0.2: 327 | version "1.0.2" 328 | resolved "https://registry.yarnpkg.com/elm-solve-deps-wasm/-/elm-solve-deps-wasm-1.0.2.tgz#cabd3cadf344295944b8d046a857b6ee05e12aaf" 329 | integrity sha512-qnwo7RO9IO7jd9SLHvIy0rSOEIlc/tNMTE9Cras0kl+b161PVidW4FvXo0MtXU8GAKi/2s/HYvhcnpR/NNQ1zw== 330 | 331 | elm-test@^0.19.1-revision12: 332 | version "0.19.1-revision12" 333 | resolved "https://registry.yarnpkg.com/elm-test/-/elm-test-0.19.1-revision12.tgz#8932cf58b388cff8d23c7cf2b80adc66249aa797" 334 | integrity sha512-5GV3WkJ8R/faOP1hwElQdNuCt8tKx2+1lsMrdeIYWSFz01Kp9gJl/R6zGtp4QUyrUtO8KnHsxjHrQNUf2CHkrg== 335 | dependencies: 336 | chalk "^4.1.2" 337 | chokidar "^3.5.3" 338 | commander "^9.4.1" 339 | cross-spawn "^7.0.3" 340 | elm-solve-deps-wasm "^1.0.2" 341 | glob "^8.0.3" 342 | graceful-fs "^4.2.10" 343 | split "^1.0.1" 344 | which "^2.0.2" 345 | xmlbuilder "^15.1.1" 346 | 347 | elm-tooling@^1.6.0: 348 | version "1.14.0" 349 | resolved "https://registry.yarnpkg.com/elm-tooling/-/elm-tooling-1.14.0.tgz#cffe2e3f582e17e50f4bac961588ae92846484c3" 350 | integrity sha512-cIbK3gfYWK086HsqOIGM4reIYcV/FF2R/8jIJ6ZUy1/RSkYFUv2BgPTGYYZo1Io9oymmbwoCWWleNtw7LgGL2w== 351 | 352 | elm-verify-examples@^6.0.3: 353 | version "6.0.3" 354 | resolved "https://registry.yarnpkg.com/elm-verify-examples/-/elm-verify-examples-6.0.3.tgz#8f7ffbb96ac65d193b28a0f65918bcb1ff275320" 355 | integrity sha512-VgZpUwYik+d7u9ZDLhbTEMN/MIE7qJ9OQRtreGmwE9ehr+JSJvnKcpZwGILIHjiNWjZqarx4d6vA2OtLZm48AA== 356 | dependencies: 357 | chalk "^4.1.2" 358 | fs-extra "^11.1.1" 359 | glob "^10.3.10" 360 | mkdirp "^3.0.1" 361 | rimraf "^5.0.5" 362 | yargs "^17.7.2" 363 | 364 | emoji-regex@^8.0.0: 365 | version "8.0.0" 366 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 367 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 368 | 369 | emoji-regex@^9.2.2: 370 | version "9.2.2" 371 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" 372 | integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== 373 | 374 | end-of-stream@^1.1.0: 375 | version "1.4.4" 376 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" 377 | integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== 378 | dependencies: 379 | once "^1.4.0" 380 | 381 | escalade@^3.1.1: 382 | version "3.1.2" 383 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" 384 | integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== 385 | 386 | fast-levenshtein@^3.0.0: 387 | version "3.0.0" 388 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz#37b899ae47e1090e40e3fd2318e4d5f0142ca912" 389 | integrity sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ== 390 | dependencies: 391 | fastest-levenshtein "^1.0.7" 392 | 393 | fastest-levenshtein@^1.0.7: 394 | version "1.0.16" 395 | resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" 396 | integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== 397 | 398 | fill-range@^7.1.1: 399 | version "7.1.1" 400 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" 401 | integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== 402 | dependencies: 403 | to-regex-range "^5.0.1" 404 | 405 | find-up@^4.1.0: 406 | version "4.1.0" 407 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" 408 | integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== 409 | dependencies: 410 | locate-path "^5.0.0" 411 | path-exists "^4.0.0" 412 | 413 | folder-hash@^3.3.0: 414 | version "3.3.3" 415 | resolved "https://registry.yarnpkg.com/folder-hash/-/folder-hash-3.3.3.tgz#883c8359d54f91b3f02c1a646c00c30e5831365b" 416 | integrity sha512-SDgHBgV+RCjrYs8aUwCb9rTgbTVuSdzvFmLaChsLre1yf+D64khCW++VYciaByZ8Rm0uKF8R/XEpXuTRSGUM1A== 417 | dependencies: 418 | debug "^4.1.1" 419 | graceful-fs "~4.2.0" 420 | minimatch "~3.0.4" 421 | 422 | foreground-child@^3.1.0: 423 | version "3.1.1" 424 | resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" 425 | integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== 426 | dependencies: 427 | cross-spawn "^7.0.0" 428 | signal-exit "^4.0.1" 429 | 430 | fs-extra@^11.1.1: 431 | version "11.2.0" 432 | resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" 433 | integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== 434 | dependencies: 435 | graceful-fs "^4.2.0" 436 | jsonfile "^6.0.1" 437 | universalify "^2.0.0" 438 | 439 | fs-extra@^9.0.0: 440 | version "9.1.0" 441 | resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" 442 | integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== 443 | dependencies: 444 | at-least-node "^1.0.0" 445 | graceful-fs "^4.2.0" 446 | jsonfile "^6.0.1" 447 | universalify "^2.0.0" 448 | 449 | fs.realpath@^1.0.0: 450 | version "1.0.0" 451 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 452 | integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== 453 | 454 | fsevents@~2.3.2: 455 | version "2.3.3" 456 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" 457 | integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== 458 | 459 | get-caller-file@^2.0.5: 460 | version "2.0.5" 461 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 462 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 463 | 464 | get-stream@^5.1.0: 465 | version "5.2.0" 466 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" 467 | integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== 468 | dependencies: 469 | pump "^3.0.0" 470 | 471 | glob-parent@~5.1.2: 472 | version "5.1.2" 473 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 474 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 475 | dependencies: 476 | is-glob "^4.0.1" 477 | 478 | glob@^10.2.5: 479 | version "10.3.3" 480 | resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.3.tgz#8360a4ffdd6ed90df84aa8d52f21f452e86a123b" 481 | integrity sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw== 482 | dependencies: 483 | foreground-child "^3.1.0" 484 | jackspeak "^2.0.3" 485 | minimatch "^9.0.1" 486 | minipass "^5.0.0 || ^6.0.2 || ^7.0.0" 487 | path-scurry "^1.10.1" 488 | 489 | glob@^10.3.10, glob@^10.3.7: 490 | version "10.3.12" 491 | resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.12.tgz#3a65c363c2e9998d220338e88a5f6ac97302960b" 492 | integrity sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg== 493 | dependencies: 494 | foreground-child "^3.1.0" 495 | jackspeak "^2.3.6" 496 | minimatch "^9.0.1" 497 | minipass "^7.0.4" 498 | path-scurry "^1.10.2" 499 | 500 | glob@^7.1.4: 501 | version "7.2.3" 502 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" 503 | integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== 504 | dependencies: 505 | fs.realpath "^1.0.0" 506 | inflight "^1.0.4" 507 | inherits "2" 508 | minimatch "^3.1.1" 509 | once "^1.3.0" 510 | path-is-absolute "^1.0.0" 511 | 512 | glob@^8.0.3: 513 | version "8.1.0" 514 | resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" 515 | integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== 516 | dependencies: 517 | fs.realpath "^1.0.0" 518 | inflight "^1.0.4" 519 | inherits "2" 520 | minimatch "^5.0.1" 521 | once "^1.3.0" 522 | 523 | got@^11.8.5: 524 | version "11.8.6" 525 | resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" 526 | integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== 527 | dependencies: 528 | "@sindresorhus/is" "^4.0.0" 529 | "@szmarczak/http-timer" "^4.0.5" 530 | "@types/cacheable-request" "^6.0.1" 531 | "@types/responselike" "^1.0.0" 532 | cacheable-lookup "^5.0.3" 533 | cacheable-request "^7.0.2" 534 | decompress-response "^6.0.0" 535 | http2-wrapper "^1.0.0-beta.5.2" 536 | lowercase-keys "^2.0.0" 537 | p-cancelable "^2.0.0" 538 | responselike "^2.0.0" 539 | 540 | graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@~4.2.0: 541 | version "4.2.11" 542 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" 543 | integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== 544 | 545 | has-flag@^4.0.0: 546 | version "4.0.0" 547 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 548 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 549 | 550 | http-cache-semantics@^4.0.0: 551 | version "4.1.1" 552 | resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" 553 | integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== 554 | 555 | http2-wrapper@^1.0.0-beta.5.2: 556 | version "1.0.3" 557 | resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" 558 | integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== 559 | dependencies: 560 | quick-lru "^5.1.1" 561 | resolve-alpn "^1.0.0" 562 | 563 | ieee754@^1.1.13: 564 | version "1.2.1" 565 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" 566 | integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== 567 | 568 | inflight@^1.0.4: 569 | version "1.0.6" 570 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 571 | integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== 572 | dependencies: 573 | once "^1.3.0" 574 | wrappy "1" 575 | 576 | inherits@2, inherits@^2.0.3, inherits@^2.0.4: 577 | version "2.0.4" 578 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 579 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 580 | 581 | is-binary-path@~2.1.0: 582 | version "2.1.0" 583 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 584 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 585 | dependencies: 586 | binary-extensions "^2.0.0" 587 | 588 | is-extglob@^2.1.1: 589 | version "2.1.1" 590 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 591 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 592 | 593 | is-fullwidth-code-point@^3.0.0: 594 | version "3.0.0" 595 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 596 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 597 | 598 | is-glob@^4.0.1, is-glob@~4.0.1: 599 | version "4.0.3" 600 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 601 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 602 | dependencies: 603 | is-extglob "^2.1.1" 604 | 605 | is-interactive@^1.0.0: 606 | version "1.0.0" 607 | resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" 608 | integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== 609 | 610 | is-number@^7.0.0: 611 | version "7.0.0" 612 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 613 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 614 | 615 | is-unicode-supported@^0.1.0: 616 | version "0.1.0" 617 | resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" 618 | integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== 619 | 620 | isexe@^2.0.0: 621 | version "2.0.0" 622 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 623 | integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== 624 | 625 | jackspeak@^2.0.3: 626 | version "2.3.1" 627 | resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.1.tgz#ce2effa4c458e053640e61938865a5b5fae98456" 628 | integrity sha512-4iSY3Bh1Htv+kLhiiZunUhQ+OYXIn0ze3ulq8JeWrFKmhPAJSySV2+kdtRh2pGcCeF0s6oR8Oc+pYZynJj4t8A== 629 | dependencies: 630 | "@isaacs/cliui" "^8.0.2" 631 | optionalDependencies: 632 | "@pkgjs/parseargs" "^0.11.0" 633 | 634 | jackspeak@^2.3.6: 635 | version "2.3.6" 636 | resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" 637 | integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== 638 | dependencies: 639 | "@isaacs/cliui" "^8.0.2" 640 | optionalDependencies: 641 | "@pkgjs/parseargs" "^0.11.0" 642 | 643 | json-buffer@3.0.1: 644 | version "3.0.1" 645 | resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" 646 | integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== 647 | 648 | jsonfile@^6.0.1: 649 | version "6.1.0" 650 | resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" 651 | integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== 652 | dependencies: 653 | universalify "^2.0.0" 654 | optionalDependencies: 655 | graceful-fs "^4.1.6" 656 | 657 | keyv@^4.0.0: 658 | version "4.5.3" 659 | resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.3.tgz#00873d2b046df737963157bd04f294ca818c9c25" 660 | integrity sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug== 661 | dependencies: 662 | json-buffer "3.0.1" 663 | 664 | kleur@^3.0.3: 665 | version "3.0.3" 666 | resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" 667 | integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== 668 | 669 | locate-path@^5.0.0: 670 | version "5.0.0" 671 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" 672 | integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== 673 | dependencies: 674 | p-locate "^4.1.0" 675 | 676 | log-symbols@^4.1.0: 677 | version "4.1.0" 678 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" 679 | integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== 680 | dependencies: 681 | chalk "^4.1.0" 682 | is-unicode-supported "^0.1.0" 683 | 684 | lowercase-keys@^2.0.0: 685 | version "2.0.0" 686 | resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" 687 | integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== 688 | 689 | lru-cache@^10.2.0: 690 | version "10.2.0" 691 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" 692 | integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== 693 | 694 | "lru-cache@^9.1.1 || ^10.0.0": 695 | version "10.0.1" 696 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.1.tgz#0a3be479df549cca0e5d693ac402ff19537a6b7a" 697 | integrity sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g== 698 | 699 | mimic-fn@^2.1.0: 700 | version "2.1.0" 701 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" 702 | integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== 703 | 704 | mimic-response@^1.0.0: 705 | version "1.0.1" 706 | resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" 707 | integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== 708 | 709 | mimic-response@^3.1.0: 710 | version "3.1.0" 711 | resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" 712 | integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== 713 | 714 | minimatch@^3.1.1: 715 | version "3.1.2" 716 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" 717 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 718 | dependencies: 719 | brace-expansion "^1.1.7" 720 | 721 | minimatch@^5.0.1: 722 | version "5.1.6" 723 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" 724 | integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== 725 | dependencies: 726 | brace-expansion "^2.0.1" 727 | 728 | minimatch@^9.0.1: 729 | version "9.0.3" 730 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" 731 | integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== 732 | dependencies: 733 | brace-expansion "^2.0.1" 734 | 735 | minimatch@~3.0.4: 736 | version "3.0.8" 737 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1" 738 | integrity sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q== 739 | dependencies: 740 | brace-expansion "^1.1.7" 741 | 742 | minimist@^1.2.6: 743 | version "1.2.8" 744 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" 745 | integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== 746 | 747 | "minipass@^5.0.0 || ^6.0.2 || ^7.0.0": 748 | version "7.0.3" 749 | resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.3.tgz#05ea638da44e475037ed94d1c7efcc76a25e1974" 750 | integrity sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg== 751 | 752 | minipass@^7.0.4: 753 | version "7.0.4" 754 | resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" 755 | integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== 756 | 757 | mkdirp@^3.0.1: 758 | version "3.0.1" 759 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" 760 | integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== 761 | 762 | ms@2.1.2: 763 | version "2.1.2" 764 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 765 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 766 | 767 | normalize-path@^3.0.0, normalize-path@~3.0.0: 768 | version "3.0.0" 769 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 770 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 771 | 772 | normalize-url@^6.0.1: 773 | version "6.1.0" 774 | resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" 775 | integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== 776 | 777 | once@^1.3.0, once@^1.3.1, once@^1.4.0: 778 | version "1.4.0" 779 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 780 | integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== 781 | dependencies: 782 | wrappy "1" 783 | 784 | onetime@^5.1.0: 785 | version "5.1.2" 786 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" 787 | integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== 788 | dependencies: 789 | mimic-fn "^2.1.0" 790 | 791 | ora@^5.4.0: 792 | version "5.4.1" 793 | resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" 794 | integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== 795 | dependencies: 796 | bl "^4.1.0" 797 | chalk "^4.1.0" 798 | cli-cursor "^3.1.0" 799 | cli-spinners "^2.5.0" 800 | is-interactive "^1.0.0" 801 | is-unicode-supported "^0.1.0" 802 | log-symbols "^4.1.0" 803 | strip-ansi "^6.0.0" 804 | wcwidth "^1.0.1" 805 | 806 | p-cancelable@^2.0.0: 807 | version "2.1.1" 808 | resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" 809 | integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== 810 | 811 | p-limit@^2.2.0: 812 | version "2.3.0" 813 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" 814 | integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== 815 | dependencies: 816 | p-try "^2.0.0" 817 | 818 | p-locate@^4.1.0: 819 | version "4.1.0" 820 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" 821 | integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== 822 | dependencies: 823 | p-limit "^2.2.0" 824 | 825 | p-try@^2.0.0: 826 | version "2.2.0" 827 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" 828 | integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== 829 | 830 | path-exists@^4.0.0: 831 | version "4.0.0" 832 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 833 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 834 | 835 | path-is-absolute@^1.0.0: 836 | version "1.0.1" 837 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 838 | integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== 839 | 840 | path-key@^3.1.0, path-key@^3.1.1: 841 | version "3.1.1" 842 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 843 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 844 | 845 | path-scurry@^1.10.1: 846 | version "1.10.1" 847 | resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" 848 | integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== 849 | dependencies: 850 | lru-cache "^9.1.1 || ^10.0.0" 851 | minipass "^5.0.0 || ^6.0.2 || ^7.0.0" 852 | 853 | path-scurry@^1.10.2: 854 | version "1.10.2" 855 | resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.2.tgz#8f6357eb1239d5fa1da8b9f70e9c080675458ba7" 856 | integrity sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA== 857 | dependencies: 858 | lru-cache "^10.2.0" 859 | minipass "^5.0.0 || ^6.0.2 || ^7.0.0" 860 | 861 | picomatch@^2.0.4, picomatch@^2.2.1: 862 | version "2.3.1" 863 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 864 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 865 | 866 | prompts@^2.2.1: 867 | version "2.4.2" 868 | resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" 869 | integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== 870 | dependencies: 871 | kleur "^3.0.3" 872 | sisteransi "^1.0.5" 873 | 874 | pump@^3.0.0: 875 | version "3.0.0" 876 | resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" 877 | integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== 878 | dependencies: 879 | end-of-stream "^1.1.0" 880 | once "^1.3.1" 881 | 882 | quick-lru@^5.1.1: 883 | version "5.1.1" 884 | resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" 885 | integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== 886 | 887 | readable-stream@^3.4.0: 888 | version "3.6.2" 889 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" 890 | integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== 891 | dependencies: 892 | inherits "^2.0.3" 893 | string_decoder "^1.1.1" 894 | util-deprecate "^1.0.1" 895 | 896 | readdirp@~3.6.0: 897 | version "3.6.0" 898 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 899 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 900 | dependencies: 901 | picomatch "^2.2.1" 902 | 903 | require-directory@^2.1.1: 904 | version "2.1.1" 905 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 906 | integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== 907 | 908 | resolve-alpn@^1.0.0: 909 | version "1.2.1" 910 | resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" 911 | integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== 912 | 913 | responselike@^2.0.0: 914 | version "2.0.1" 915 | resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" 916 | integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw== 917 | dependencies: 918 | lowercase-keys "^2.0.0" 919 | 920 | restore-cursor@^3.1.0: 921 | version "3.1.0" 922 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" 923 | integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== 924 | dependencies: 925 | onetime "^5.1.0" 926 | signal-exit "^3.0.2" 927 | 928 | rimraf@^5.0.0: 929 | version "5.0.1" 930 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.1.tgz#0881323ab94ad45fec7c0221f27ea1a142f3f0d0" 931 | integrity sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg== 932 | dependencies: 933 | glob "^10.2.5" 934 | 935 | rimraf@^5.0.5: 936 | version "5.0.5" 937 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.5.tgz#9be65d2d6e683447d2e9013da2bf451139a61ccf" 938 | integrity sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A== 939 | dependencies: 940 | glob "^10.3.7" 941 | 942 | safe-buffer@~5.2.0: 943 | version "5.2.1" 944 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 945 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 946 | 947 | shebang-command@^2.0.0: 948 | version "2.0.0" 949 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 950 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 951 | dependencies: 952 | shebang-regex "^3.0.0" 953 | 954 | shebang-regex@^3.0.0: 955 | version "3.0.0" 956 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 957 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 958 | 959 | signal-exit@^3.0.2: 960 | version "3.0.7" 961 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" 962 | integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== 963 | 964 | signal-exit@^4.0.1: 965 | version "4.1.0" 966 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" 967 | integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== 968 | 969 | sisteransi@^1.0.5: 970 | version "1.0.5" 971 | resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" 972 | integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== 973 | 974 | split@^1.0.1: 975 | version "1.0.1" 976 | resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" 977 | integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== 978 | dependencies: 979 | through "2" 980 | 981 | "string-width-cjs@npm:string-width@^4.2.0": 982 | version "4.2.3" 983 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 984 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 985 | dependencies: 986 | emoji-regex "^8.0.0" 987 | is-fullwidth-code-point "^3.0.0" 988 | strip-ansi "^6.0.1" 989 | 990 | string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: 991 | version "4.2.3" 992 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 993 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 994 | dependencies: 995 | emoji-regex "^8.0.0" 996 | is-fullwidth-code-point "^3.0.0" 997 | strip-ansi "^6.0.1" 998 | 999 | string-width@^5.0.1, string-width@^5.1.2: 1000 | version "5.1.2" 1001 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" 1002 | integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== 1003 | dependencies: 1004 | eastasianwidth "^0.2.0" 1005 | emoji-regex "^9.2.2" 1006 | strip-ansi "^7.0.1" 1007 | 1008 | string_decoder@^1.1.1: 1009 | version "1.3.0" 1010 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" 1011 | integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== 1012 | dependencies: 1013 | safe-buffer "~5.2.0" 1014 | 1015 | "strip-ansi-cjs@npm:strip-ansi@^6.0.1": 1016 | version "6.0.1" 1017 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 1018 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 1019 | dependencies: 1020 | ansi-regex "^5.0.1" 1021 | 1022 | strip-ansi@^6.0.0, strip-ansi@^6.0.1: 1023 | version "6.0.1" 1024 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 1025 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 1026 | dependencies: 1027 | ansi-regex "^5.0.1" 1028 | 1029 | strip-ansi@^7.0.1: 1030 | version "7.1.0" 1031 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" 1032 | integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== 1033 | dependencies: 1034 | ansi-regex "^6.0.1" 1035 | 1036 | supports-color@^7.0.0, supports-color@^7.1.0: 1037 | version "7.2.0" 1038 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 1039 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 1040 | dependencies: 1041 | has-flag "^4.0.0" 1042 | 1043 | supports-hyperlinks@^2.0.0: 1044 | version "2.3.0" 1045 | resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" 1046 | integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== 1047 | dependencies: 1048 | has-flag "^4.0.0" 1049 | supports-color "^7.0.0" 1050 | 1051 | terminal-link@^2.1.1: 1052 | version "2.1.1" 1053 | resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" 1054 | integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== 1055 | dependencies: 1056 | ansi-escapes "^4.2.1" 1057 | supports-hyperlinks "^2.0.0" 1058 | 1059 | through@2: 1060 | version "2.3.8" 1061 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 1062 | integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== 1063 | 1064 | to-regex-range@^5.0.1: 1065 | version "5.0.1" 1066 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1067 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1068 | dependencies: 1069 | is-number "^7.0.0" 1070 | 1071 | type-fest@^0.21.3: 1072 | version "0.21.3" 1073 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" 1074 | integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== 1075 | 1076 | universalify@^2.0.0: 1077 | version "2.0.0" 1078 | resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" 1079 | integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== 1080 | 1081 | util-deprecate@^1.0.1: 1082 | version "1.0.2" 1083 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 1084 | integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== 1085 | 1086 | wcwidth@^1.0.1: 1087 | version "1.0.1" 1088 | resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" 1089 | integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== 1090 | dependencies: 1091 | defaults "^1.0.3" 1092 | 1093 | which@^2.0.1, which@^2.0.2: 1094 | version "2.0.2" 1095 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 1096 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1097 | dependencies: 1098 | isexe "^2.0.0" 1099 | 1100 | "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": 1101 | version "7.0.0" 1102 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 1103 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 1104 | dependencies: 1105 | ansi-styles "^4.0.0" 1106 | string-width "^4.1.0" 1107 | strip-ansi "^6.0.0" 1108 | 1109 | wrap-ansi@^6.2.0: 1110 | version "6.2.0" 1111 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" 1112 | integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== 1113 | dependencies: 1114 | ansi-styles "^4.0.0" 1115 | string-width "^4.1.0" 1116 | strip-ansi "^6.0.0" 1117 | 1118 | wrap-ansi@^7.0.0: 1119 | version "7.0.0" 1120 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 1121 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 1122 | dependencies: 1123 | ansi-styles "^4.0.0" 1124 | string-width "^4.1.0" 1125 | strip-ansi "^6.0.0" 1126 | 1127 | wrap-ansi@^8.1.0: 1128 | version "8.1.0" 1129 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" 1130 | integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== 1131 | dependencies: 1132 | ansi-styles "^6.1.0" 1133 | string-width "^5.0.1" 1134 | strip-ansi "^7.0.1" 1135 | 1136 | wrappy@1: 1137 | version "1.0.2" 1138 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1139 | integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== 1140 | 1141 | xmlbuilder@^15.1.1: 1142 | version "15.1.1" 1143 | resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5" 1144 | integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg== 1145 | 1146 | y18n@^5.0.5: 1147 | version "5.0.8" 1148 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" 1149 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== 1150 | 1151 | yargs-parser@^21.1.1: 1152 | version "21.1.1" 1153 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" 1154 | integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== 1155 | 1156 | yargs@^17.7.2: 1157 | version "17.7.2" 1158 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" 1159 | integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== 1160 | dependencies: 1161 | cliui "^8.0.1" 1162 | escalade "^3.1.1" 1163 | get-caller-file "^2.0.5" 1164 | require-directory "^2.1.1" 1165 | string-width "^4.2.3" 1166 | y18n "^5.0.5" 1167 | yargs-parser "^21.1.1" 1168 | --------------------------------------------------------------------------------