├── .gitignore ├── package.json ├── README.md ├── elm.json ├── LICENSE ├── review ├── elm.json └── src │ └── ReviewConfig.elm ├── src ├── IntDict │ └── Safe.elm └── IntDict.elm ├── tests └── Tests │ └── IntDict.elm └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | elm-stuff/ 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "elm-review": "^2.12.0" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IntDict 2 | 3 | `IntDict` is an optimized version of a `Dict` with `Int` as key type. 4 | 5 | Its API is the same as `Dict`'s, so it can be regarded as a drop-in replacement. 6 | If you are comfortable with `Dict`, working with `IntDict` should be a breeze! 7 | 8 | For details about runtimes and important caveats with respect to JavaScript's number type, see the module documentation for [`IntDict`](https://package.elm-lang.org/packages/elm-community/intdict/3.0.0/IntDict/). 9 | -------------------------------------------------------------------------------- /elm.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "package", 3 | "name": "elm-community/intdict", 4 | "summary": "Optimized dictionary specialization for Integers. Mirrors the dictionary API.", 5 | "license": "MIT", 6 | "version": "3.1.0", 7 | "exposed-modules": [ 8 | "IntDict", 9 | "IntDict.Safe" 10 | ], 11 | "elm-version": "0.19.0 <= v < 0.20.0", 12 | "dependencies": { 13 | "elm/core": "1.0.0 <= v < 2.0.0" 14 | }, 15 | "test-dependencies": { 16 | "elm-explorations/test": "2.0.0 <= v < 3.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Sebastian Graf 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. -------------------------------------------------------------------------------- /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.14.0", 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.5", 18 | "jfmengels/elm-review-unused": "1.2.3", 19 | "stil4m/elm-syntax": "7.3.4" 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.2.0", 30 | "miniBill/elm-unicode": "1.1.1", 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 | "elm-explorations/test": "2.2.0" 39 | }, 40 | "indirect": {} 41 | } 42 | } -------------------------------------------------------------------------------- /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/IntDict/Safe.elm: -------------------------------------------------------------------------------- 1 | module IntDict.Safe exposing 2 | ( InvalidKey(..), SafeKeyResult 3 | , safeInsert, safeUpdate, safeRemove 4 | , safeMember, safeGet 5 | ) 6 | 7 | {-| Safe API wrappers for `IntDict`s build and query operators 8 | to prevent integer overflows with JavaScripts number type. 9 | 10 | Prior to delegating to their 'unsafe' equivalent, these functions verify 11 | the validity of the key via `IntDict.isValidKey`. 12 | 13 | 14 | # Return type 15 | 16 | @docs InvalidKey, SafeKeyResult 17 | 18 | 19 | # Build 20 | 21 | @docs safeInsert, safeUpdate, safeRemove 22 | 23 | 24 | # Query 25 | 26 | @docs safeMember, safeGet 27 | 28 | -} 29 | 30 | import IntDict exposing (IntDict) 31 | 32 | 33 | {-| An error type signaling an invalid key. 34 | -} 35 | type InvalidKey 36 | = InvalidKey 37 | 38 | 39 | {-| A value of this type is returned by all functions in this module. 40 | See the core libraries' `Result` documentation for how to cope with it. 41 | -} 42 | type alias SafeKeyResult a = 43 | Result InvalidKey a 44 | 45 | 46 | safeWrapper : Int -> (() -> a) -> SafeKeyResult a 47 | safeWrapper k f = 48 | if not (IntDict.isValidKey k) then 49 | Err InvalidKey 50 | 51 | else 52 | Ok (f ()) 53 | 54 | 55 | {-| Version of `IntDict.insert` that validates the key. 56 | -} 57 | safeInsert : Int -> v -> IntDict v -> SafeKeyResult (IntDict v) 58 | safeInsert k v dict = 59 | safeWrapper k <| \() -> IntDict.insert k v dict 60 | 61 | 62 | {-| Version of `IntDict.remove` that validates the key. 63 | -} 64 | safeRemove : Int -> IntDict v -> SafeKeyResult (IntDict v) 65 | safeRemove k dict = 66 | safeWrapper k <| \() -> IntDict.remove k dict 67 | 68 | 69 | {-| Version of `IntDict.update` that validates the key. 70 | -} 71 | safeUpdate : Int -> (Maybe v -> Maybe v) -> IntDict v -> SafeKeyResult (IntDict v) 72 | safeUpdate k alter dict = 73 | safeWrapper k <| \() -> IntDict.update k alter dict 74 | 75 | 76 | {-| Version of `IntDict.get` that validates the key. 77 | -} 78 | safeGet : Int -> IntDict v -> SafeKeyResult (Maybe v) 79 | safeGet k dict = 80 | safeWrapper k <| \() -> IntDict.get k dict 81 | 82 | 83 | {-| Version of `IntDict.member` that validates the key. 84 | -} 85 | safeMember : Int -> IntDict v -> SafeKeyResult Bool 86 | safeMember k dict = 87 | safeWrapper k <| \() -> IntDict.member k dict 88 | -------------------------------------------------------------------------------- /tests/Tests/IntDict.elm: -------------------------------------------------------------------------------- 1 | module Tests.IntDict exposing (build, combine, merge, query, range, regressions, split, transform) 2 | 3 | {-| Copied and modified from `Dict`s test suite. 4 | -} 5 | 6 | import Expect 7 | import Fuzz 8 | import IntDict exposing (IntDict) 9 | import List 10 | import Test exposing (Test, describe, fuzz2, test) 11 | 12 | 13 | numbers : IntDict String 14 | numbers = 15 | IntDict.fromList [ ( 2, "2" ), ( 3, "3" ) ] 16 | 17 | 18 | moreNumbers : IntDict String 19 | moreNumbers = 20 | IntDict.fromList [ ( -5, "-5" ), ( -1, "-1" ), ( 2, "2" ), ( 5, "5" ), ( 7, "7" ), ( 45, "45" ) ] 21 | 22 | 23 | build : Test 24 | build = 25 | describe "build" 26 | [ test "empty" <| \() -> Expect.equal (IntDict.fromList []) IntDict.empty 27 | , test "singleton" <| \() -> Expect.equal (IntDict.fromList [ ( 1, "v" ) ]) (IntDict.singleton 1 "v") 28 | , test "insert" <| \() -> Expect.equal (IntDict.fromList [ ( 1, "v" ) ]) (IntDict.insert 1 "v" IntDict.empty) 29 | , test "insert replace" <| \() -> Expect.equal (IntDict.fromList [ ( 1, "vv" ) ]) (IntDict.insert 1 "vv" (IntDict.singleton 1 "v")) 30 | , test "update" <| \() -> Expect.equal (IntDict.fromList [ ( 1, "vv" ) ]) (IntDict.update 1 (\_ -> Just "vv") (IntDict.singleton 1 "v")) 31 | , test "update Nothing" <| \() -> Expect.equal IntDict.empty (IntDict.update 1 (\_ -> Nothing) (IntDict.singleton 1 "v")) 32 | , test "remove" <| \() -> Expect.equal IntDict.empty (IntDict.remove 1 (IntDict.singleton 1 "v")) 33 | , test "remove not found" <| \() -> Expect.equal (IntDict.singleton 1 "v") (IntDict.remove 342 (IntDict.singleton 1 "v")) 34 | ] 35 | 36 | 37 | query : Test 38 | query = 39 | describe "query" 40 | [ test "isEmpty - empty is empty" <| \() -> Expect.equal True (IntDict.isEmpty IntDict.empty) 41 | , test "isEmpty - non-empty dict is not empty" <| \() -> Expect.equal False (IntDict.isEmpty numbers) 42 | , test "size 1" <| \() -> Expect.equal 0 (IntDict.size IntDict.empty) 43 | , test "size 2" <| \() -> Expect.equal 2 (IntDict.size numbers) 44 | , test "size 3" <| \() -> Expect.equal 7 (IntDict.size (IntDict.union numbers moreNumbers)) 45 | , test "member 1" <| \() -> Expect.equal True (IntDict.member 2 numbers) 46 | , test "member 2" <| \() -> Expect.equal False (IntDict.member 5234 numbers) 47 | , test "get 1" <| \() -> Expect.equal (Just "2") (IntDict.get 2 numbers) 48 | , test "get 2" <| \() -> Expect.equal Nothing (IntDict.get 5234 numbers) 49 | , test "findMin" <| \() -> Expect.equal (Just ( 2, "2" )) (IntDict.findMin numbers) 50 | , test "findMax" <| \() -> Expect.equal (Just ( 3, "3" )) (IntDict.findMax numbers) 51 | , test "before 2 empty" <| \() -> Expect.equal Nothing (IntDict.before 2 IntDict.empty) 52 | , test "before 2" <| \() -> Expect.equal Nothing (IntDict.before 2 numbers) 53 | , test "before 3" <| \() -> Expect.equal (Just ( 2, "2" )) (IntDict.before 3 numbers) 54 | , test "before 4" <| \() -> Expect.equal (Just ( 3, "3" )) (IntDict.before 4 numbers) 55 | , test "before -1'" <| \() -> Expect.equal (Just ( -5, "-5" )) (IntDict.before -1 moreNumbers) 56 | , test "before 2'" <| \() -> Expect.equal (Just ( -1, "-1" )) (IntDict.before 2 moreNumbers) 57 | , test "before 5" <| \() -> Expect.equal (Just ( 2, "2" )) (IntDict.before 5 moreNumbers) 58 | , test "before 6" <| \() -> Expect.equal (Just ( 5, "5" )) (IntDict.before 6 moreNumbers) 59 | , test "before 7" <| \() -> Expect.equal (Just ( 5, "5" )) (IntDict.before 7 moreNumbers) 60 | , test "before 44" <| \() -> Expect.equal (Just ( 7, "7" )) (IntDict.before 44 moreNumbers) 61 | , test "before 45" <| \() -> Expect.equal (Just ( 7, "7" )) (IntDict.before 45 moreNumbers) 62 | , test "before 46" <| \() -> Expect.equal (Just ( 45, "45" )) (IntDict.before 46 moreNumbers) 63 | , test "after 2 empty" <| \() -> Expect.equal Nothing (IntDict.after 2 IntDict.empty) 64 | , test "after 2" <| \() -> Expect.equal (Just ( 3, "3" )) (IntDict.after 2 numbers) 65 | , test "after 3" <| \() -> Expect.equal Nothing (IntDict.after 3 numbers) 66 | , test "after 1" <| \() -> Expect.equal (Just ( 2, "2" )) (IntDict.after 1 numbers) 67 | , test "after -6'" <| \() -> Expect.equal (Just ( -5, "-5" )) (IntDict.after -6 moreNumbers) 68 | , test "after -1'" <| \() -> Expect.equal (Just ( 2, "2" )) (IntDict.after -1 moreNumbers) 69 | , test "after 1'" <| \() -> Expect.equal (Just ( 2, "2" )) (IntDict.after 1 moreNumbers) 70 | , test "after 2'" <| \() -> Expect.equal (Just ( 5, "5" )) (IntDict.after 2 moreNumbers) 71 | , test "after 5" <| \() -> Expect.equal (Just ( 7, "7" )) (IntDict.after 5 moreNumbers) 72 | , test "after 6" <| \() -> Expect.equal (Just ( 7, "7" )) (IntDict.after 6 moreNumbers) 73 | , test "after 7" <| \() -> Expect.equal (Just ( 45, "45" )) (IntDict.after 7 moreNumbers) 74 | , test "after 44" <| \() -> Expect.equal (Just ( 45, "45" )) (IntDict.after 44 moreNumbers) 75 | , test "after 45" <| \() -> Expect.equal Nothing (IntDict.after 45 moreNumbers) 76 | ] 77 | 78 | 79 | combine : Test 80 | combine = 81 | describe "combine" 82 | [ test "union" <| \() -> Expect.equal numbers (IntDict.union (IntDict.singleton 3 "3") (IntDict.singleton 2 "2")) 83 | , test "union collison" <| \() -> Expect.equal (IntDict.singleton 2 "2") (IntDict.union (IntDict.singleton 2 "2") (IntDict.singleton 2 "3")) 84 | , test "intersect" <| \() -> Expect.equal (IntDict.singleton 2 "2") (IntDict.intersect numbers (IntDict.singleton 2 "2")) 85 | , test "diff" <| \() -> Expect.equal (IntDict.singleton 3 "3") (IntDict.diff numbers (IntDict.singleton 2 "2")) 86 | ] 87 | 88 | 89 | transform : Test 90 | transform = 91 | describe "transform" 92 | [ test "filter" <| \() -> Expect.equal (IntDict.singleton 2 "2") (IntDict.filter (\k _ -> k == 2) numbers) 93 | , test "partition" <| \() -> Expect.equal ( IntDict.singleton 2 "2", IntDict.singleton 3 "3" ) (IntDict.partition (\k _ -> k == 2) numbers) 94 | ] 95 | 96 | 97 | merge : Test 98 | merge = 99 | let 100 | insertBoth : Int -> List Int -> List Int -> IntDict (List Int) -> IntDict (List Int) 101 | insertBoth key leftVal rightVal dict = 102 | IntDict.insert key (leftVal ++ rightVal) dict 103 | 104 | s1 : IntDict (List Int) 105 | s1 = 106 | IntDict.empty |> IntDict.insert 1 [ 1 ] 107 | 108 | s2 : IntDict (List Int) 109 | s2 = 110 | IntDict.empty |> IntDict.insert 2 [ 2 ] 111 | 112 | s23 : IntDict (List Int) 113 | s23 = 114 | IntDict.empty |> IntDict.insert 2 [ 3 ] 115 | 116 | b1 : IntDict (List Int) 117 | b1 = 118 | List.range 1 10 |> List.map (\i -> ( i, [ i ] )) |> IntDict.fromList 119 | 120 | b2 : IntDict (List Int) 121 | b2 = 122 | List.range 5 15 |> List.map (\i -> ( i, [ i ] )) |> IntDict.fromList 123 | 124 | bExpected : List ( Int, List Int ) 125 | bExpected = 126 | [ ( 1, [ 1 ] ), ( 2, [ 2 ] ), ( 3, [ 3 ] ), ( 4, [ 4 ] ), ( 5, [ 5, 5 ] ), ( 6, [ 6, 6 ] ), ( 7, [ 7, 7 ] ), ( 8, [ 8, 8 ] ), ( 9, [ 9, 9 ] ), ( 10, [ 10, 10 ] ), ( 11, [ 11 ] ), ( 12, [ 12 ] ), ( 13, [ 13 ] ), ( 14, [ 14 ] ), ( 15, [ 15 ] ) ] 127 | in 128 | describe "merge" <| 129 | [ test "merge empties" <| 130 | \() -> 131 | Expect.equal IntDict.empty 132 | (IntDict.merge IntDict.insert insertBoth IntDict.insert IntDict.empty IntDict.empty IntDict.empty) 133 | , test "merge singletons in order" <| 134 | \() -> 135 | Expect.equal [ ( 1, [ 1 ] ), ( 2, [ 2 ] ) ] 136 | (IntDict.merge IntDict.insert insertBoth IntDict.insert s1 s2 IntDict.empty |> IntDict.toList) 137 | , test "merge singletons out of order" <| 138 | \() -> 139 | Expect.equal [ ( 1, [ 1 ] ), ( 2, [ 2 ] ) ] 140 | (IntDict.merge IntDict.insert insertBoth IntDict.insert s2 s1 IntDict.empty |> IntDict.toList) 141 | , test "merge with duplicate key" <| 142 | \() -> 143 | Expect.equal [ ( 2, [ 2, 3 ] ) ] 144 | (IntDict.merge IntDict.insert insertBoth IntDict.insert s2 s23 IntDict.empty |> IntDict.toList) 145 | , test "partially overlapping" <| 146 | \() -> 147 | Expect.equal bExpected 148 | (IntDict.merge IntDict.insert insertBoth IntDict.insert b1 b2 IntDict.empty |> IntDict.toList) 149 | ] 150 | 151 | 152 | validKey : Fuzz.Fuzzer Int 153 | validKey = 154 | Fuzz.filter IntDict.isValidKey Fuzz.int 155 | 156 | 157 | randomDict : Fuzz.Fuzzer (IntDict Int) 158 | randomDict = 159 | Fuzz.list validKey 160 | |> Fuzz.map (List.map (\x -> ( x, x ))) 161 | |> Fuzz.map IntDict.fromList 162 | 163 | 164 | split : Test 165 | split = 166 | let 167 | empty : IntDict Int 168 | empty = 169 | IntDict.empty 170 | 171 | s1 : IntDict Int 172 | s1 = 173 | IntDict.fromList [ ( 1, 1 ), ( 2, 2 ) ] 174 | 175 | s2 : IntDict Int 176 | s2 = 177 | IntDict.fromList [ ( 1, 1 ), ( 2, 2 ), ( 3, 3 ), ( 100, 100 ), ( -10, -10 ), ( 0, 0 ) ] 178 | 179 | toLists : ( IntDict v, IntDict a ) -> ( List ( Int, v ), List ( Int, a ) ) 180 | toLists ( d1, d2 ) = 181 | ( IntDict.toList d1, IntDict.toList d2 ) 182 | in 183 | describe "split" <| 184 | [ test "split empty" <| 185 | \() -> 186 | Expect.equal ( IntDict.empty, IntDict.empty ) (IntDict.split 1 empty) 187 | , test "split under" <| 188 | \() -> 189 | Expect.equal ( IntDict.empty, s1 ) (IntDict.split 1 s1) 190 | , test "split over" <| 191 | \() -> 192 | Expect.equal ( s1, IntDict.empty ) (IntDict.split 3 s1) 193 | , test "split in middle" <| 194 | \() -> 195 | Expect.equal ( IntDict.fromList [ ( 1, 1 ) ], IntDict.fromList [ ( 2, 2 ) ] ) (IntDict.split 2 s1) 196 | 197 | -- This is a good candidate for fuzz testing 198 | , test "split larger dict" <| 199 | \() -> 200 | Expect.equal ( IntDict.fromList [ ( -10, -10 ) ], IntDict.fromList [ ( 0, 0 ), ( 1, 1 ), ( 2, 2 ), ( 3, 3 ), ( 100, 100 ) ] ) 201 | (IntDict.split 0 s2) 202 | , test "split on missing key continuous dict" <| 203 | \() -> 204 | Expect.equal ( [ ( 0, 0 ), ( 1, 1 ) ], [ ( 2, 2 ), ( 3, 3 ) ] ) 205 | (IntDict.split 2 (IntDict.fromList [ ( 0, 0 ), ( 1, 1 ), ( 2, 2 ), ( 3, 3 ) ]) |> toLists) 206 | , test "split on missing key" <| 207 | \() -> 208 | Expect.equal ( [ ( -10, -10 ), ( 0, 0 ), ( 1, 1 ), ( 2, 2 ), ( 3, 3 ) ], [ ( 100, 100 ) ] ) 209 | (IntDict.split 5 s2 |> toLists) 210 | , fuzz2 validKey randomDict "split on random dictionaries" <| 211 | \key dict -> 212 | let 213 | items : List ( Int, Int ) 214 | items = 215 | IntDict.toList dict 216 | 217 | ( expectedLessThan, expectedGreaterEq ) = 218 | List.partition (\( a, _ ) -> a < key) items 219 | in 220 | Expect.equal ( expectedLessThan, expectedGreaterEq ) 221 | (IntDict.split key dict |> toLists) 222 | ] 223 | 224 | 225 | orderedTuple : Fuzz.Fuzzer ( Int, Int ) 226 | orderedTuple = 227 | Fuzz.pair validKey validKey 228 | |> Fuzz.map (\( a, b ) -> ( min a b, max a b )) 229 | 230 | 231 | range : Test 232 | range = 233 | describe "range" <| 234 | [ fuzz2 orderedTuple randomDict "range on random dictionaries" <| 235 | \( low, high ) dict -> 236 | let 237 | items : List ( Int, Int ) 238 | items = 239 | IntDict.toList dict 240 | 241 | expected : List ( Int, Int ) 242 | expected = 243 | List.filter (\( a, _ ) -> a >= low && a < high) items 244 | in 245 | Expect.equal expected (IntDict.range low high dict |> IntDict.toList) 246 | ] 247 | 248 | 249 | regressions : Test 250 | regressions = 251 | describe "regressions" 252 | [ describe "issue #1" <| 253 | let 254 | a : IntDict Int 255 | a = 256 | IntDict.fromList [ ( 4, 20 ), ( 6, 11 ) ] 257 | 258 | b : IntDict Int 259 | b = 260 | IntDict.fromList [ ( 1, 0 ), ( 2, 7 ), ( 3, 9 ), ( 4, 22 ), ( 6, 14 ) ] 261 | in 262 | [ test "a union b" <| 263 | \() -> 264 | Expect.equal 265 | (IntDict.union a b) 266 | (IntDict.fromList [ ( 1, 0 ), ( 2, 7 ), ( 3, 9 ), ( 4, 20 ), ( 6, 11 ) ]) 267 | , test "b union a" <| 268 | \() -> 269 | Expect.equal 270 | (IntDict.union b a) 271 | (IntDict.fromList [ ( 1, 0 ), ( 2, 7 ), ( 3, 9 ), ( 4, 22 ), ( 6, 14 ) ]) 272 | ] 273 | , describe "issue #5" <| 274 | let 275 | a : IntDict () 276 | a = 277 | IntDict.fromList [ ( -1, () ), ( 2, () ) ] 278 | 279 | b : IntDict () 280 | b = 281 | IntDict.fromList [ ( 2, () ), ( 3, () ) ] 282 | in 283 | [ test "a union b" <| 284 | \() -> 285 | Expect.equal 286 | (IntDict.union a b) 287 | (IntDict.fromList [ ( -1, () ), ( 2, () ), ( 3, () ) ]) 288 | , test "b union a" <| 289 | \() -> 290 | Expect.equal 291 | (IntDict.union b a) 292 | (IntDict.fromList [ ( -1, () ), ( 2, () ), ( 3, () ) ]) 293 | ] 294 | ] 295 | -------------------------------------------------------------------------------- /src/IntDict.elm: -------------------------------------------------------------------------------- 1 | module IntDict exposing 2 | ( IntDict, isValidKey 3 | , empty, singleton, insert, update, remove 4 | , isEmpty, size, member, get, before, after, findMin, findMax 5 | , uniteWith, union, intersect, diff, merge 6 | , keys, values, toList, fromList 7 | , map, foldl, foldr, filter, partition, split, range 8 | , toString 9 | ) 10 | 11 | {-| 12 | 13 | 14 | # IntDict 15 | 16 | This module exposes the same API as [`Dict`](http://package.elm-lang.org/packages/elm-lang/core/latest/Dict). 17 | 18 | 19 | # Technicalities 20 | 21 | Since JavaScript's number type is kind of messed up, Elm's `Int` is not particularly 22 | well-behaved wrt. bitwise operations. Currently, JS supports 32 bit integers, so there is 23 | probably enough room for key picks. **However, when sanitizing user input, it is mandatory 24 | that a prior `isValidKey` or one of the safe versions in `IntDict.Safe` is used!** This is 25 | to prevent the overflow behavior. 26 | 27 | This library is inspired by Haskell's [IntMap](http://hackage.haskell.org/package/containers-0.2.0.1/docs/Data-IntMap.html), 28 | which in turn implements Okasaki and Gill's [Fast mergable integer maps](http://ittc.ku.edu/~andygill/papers/IntMap98.pdf). 29 | 30 | As noted in the [references](http://ittc.ku.edu/~andygill/papers/IntMap98.pdf), here are some runtimes: 31 | 32 | _O(min(n, W))_: `insert`, `update`, `remove`, `get`, `member` 33 | 34 | _O(n + m)_: `uniteWith`, `union`, `intersection`, `diff`, `merge` 35 | 36 | where _n_ and _m_ are the sizes of the first and second dictionary respectively and _W_ 37 | is the number of bits in `Int` (so a constant with current value 32). 38 | 39 | Dictionary equality with `(==)` is unreliable and should not be used. 40 | 41 | 42 | # Data 43 | 44 | @docs IntDict, isValidKey 45 | 46 | 47 | # Build 48 | 49 | @docs empty, singleton, insert, update, remove 50 | 51 | 52 | # Query 53 | 54 | @docs isEmpty, size, member, get, before, after, findMin, findMax 55 | 56 | 57 | # Combine 58 | 59 | @docs uniteWith, union, intersect, diff, merge 60 | 61 | 62 | # Lists 63 | 64 | @docs keys, values, toList, fromList 65 | 66 | 67 | # Transform 68 | 69 | @docs map, foldl, foldr, filter, partition, split, range 70 | 71 | 72 | # String representation 73 | 74 | @docs toString 75 | 76 | -} 77 | 78 | import Bitwise 79 | import List 80 | import Maybe exposing (Maybe(..)) 81 | 82 | 83 | type alias KeyPrefix = 84 | { prefixBits : Int -- higher key prefix excluding the branching bit 85 | , branchingBit : Int -- already in 2^i form -> always > 0 (except when the sign bit is set, then it's < 0) 86 | } 87 | 88 | 89 | 90 | -- only so that we don't repeat ourselves 91 | 92 | 93 | type alias InnerType v = 94 | { prefix : KeyPrefix 95 | , left : IntDict v 96 | , right : IntDict v 97 | , size : Int 98 | } 99 | 100 | 101 | {-| A dictionary mapping `Int`s to values of a type `v`. Analogous to 102 | `Dict Int v`. 103 | -} 104 | type IntDict v 105 | = Empty -- Invariant: Never child of an `Inner` node 106 | | Leaf { key : Int, value : v } 107 | | Inner (InnerType v) 108 | 109 | 110 | {-| Validates that a given integer is usable as a key. 111 | This is necessary due to JavaScript's weird number type. 112 | Basically this assures that we can use the functions 113 | from `Bitwise` without risking integer overflow. 114 | 115 | **This function is a necessity for sanitizing user input!** Alternatively, 116 | use the safe functions from `IntDict.Safe` which perform the check for you. 117 | 118 | As with the current version of JavaScript (2015), only 32 bit signed integers are supported. 119 | If this ever changes, contact me! Certain parts of the implementation depend on this! 120 | 121 | -} 122 | isValidKey : Int -> Bool 123 | isValidKey k = 124 | -- perform some dirty JS magic to turn the double 125 | Bitwise.or k 0 - k == 0 126 | 127 | 128 | 129 | -- into an integer. We can then check for overflow. 130 | -- This seems easier than checking for 32 bits. 131 | -- `or` 0 is similar to `mod` <32bits> 132 | -- SMART CONSTRUCTORS 133 | -- not exported 134 | 135 | 136 | inner : KeyPrefix -> IntDict v -> IntDict v -> IntDict v 137 | inner p l r = 138 | case ( l, r ) of 139 | ( Empty, _ ) -> 140 | r 141 | 142 | ( _, Empty ) -> 143 | l 144 | 145 | _ -> 146 | Inner 147 | { prefix = p 148 | , left = l 149 | , right = r 150 | , size = size l + size r 151 | } 152 | 153 | 154 | 155 | -- exported as the singleton alias 156 | 157 | 158 | leaf : Int -> v -> IntDict v 159 | leaf k v = 160 | Leaf 161 | { key = k 162 | , value = v 163 | } 164 | 165 | 166 | 167 | -- SOME PRIMITIVES 168 | 169 | 170 | {-| Consider a branchingBit of 2^4 = 16 = 0b00010000. 171 | Then branchingBit-1 = 15 = 0b00001111, 172 | Now apply bitwise NOT to get the mask 0b11110000. 173 | Finally, we clear out the branchingBit itself with `Bitwise.xor`. 174 | -} 175 | higherBitMask : Int -> Int 176 | higherBitMask branchingBit = 177 | branchingBit 178 | - 1 179 | |> Bitwise.complement 180 | |> Bitwise.xor branchingBit 181 | 182 | 183 | prefixMatches : KeyPrefix -> Int -> Bool 184 | prefixMatches p n = 185 | Bitwise.and n (higherBitMask p.branchingBit) - p.prefixBits == 0 186 | 187 | 188 | {-| Clear all bits other than the highest in n. 189 | For implementation notes, see [this]( Significant 1 Bit). 190 | -} 191 | highestBitSet : Int -> Int 192 | highestBitSet n = 193 | let 194 | shiftOr : Int -> Int -> Int 195 | shiftOr i shift = 196 | Bitwise.or i (Bitwise.shiftRightZfBy shift i) 197 | 198 | n1 : Int 199 | n1 = 200 | shiftOr n 1 201 | 202 | n2 : Int 203 | n2 = 204 | shiftOr n1 2 205 | 206 | n3 : Int 207 | n3 = 208 | shiftOr n2 4 209 | 210 | n4 : Int 211 | n4 = 212 | shiftOr n3 8 213 | 214 | n5 : Int 215 | n5 = 216 | shiftOr n4 16 217 | 218 | -- n6 = shiftOr n5 32 -- 64 bit support?! 219 | -- n5 has the same msb set as diff. However, all 220 | -- bits below the msb are also 1! This means we can 221 | -- do the following to get the msb: 222 | in 223 | n5 |> Bitwise.shiftRightZfBy 1 |> Bitwise.complement |> Bitwise.and n5 224 | 225 | 226 | mostSignificantBranchingBit : Int -> Int -> Int 227 | mostSignificantBranchingBit a b = 228 | if a - signBit == 0 || b - signBit == 0 then 229 | signBit 230 | 231 | else 232 | max a b 233 | 234 | 235 | {-| Compute the longest common prefix of two keys. 236 | Returns 0 as branchingBit if equal. 237 | 238 | Find the highest bit not set in 239 | 240 | 241 | diff = 242 | x `xor` y 243 | 244 | -- 0b011001 `xor` 0b011010 = 0b000011 245 | 246 | -} 247 | lcp : Int -> Int -> KeyPrefix 248 | lcp x y = 249 | let 250 | branchingBit : Int 251 | branchingBit = 252 | highestBitSet (Bitwise.xor x y) 253 | 254 | mask : Int 255 | mask = 256 | higherBitMask branchingBit 257 | 258 | prefixBits : Int 259 | prefixBits = 260 | Bitwise.and x mask 261 | 262 | -- should equal y & mask 263 | in 264 | { prefixBits = prefixBits 265 | , branchingBit = branchingBit 266 | } 267 | 268 | 269 | signBit : Int 270 | signBit = 271 | highestBitSet -1 272 | 273 | 274 | isBranchingBitSet : KeyPrefix -> Int -> Bool 275 | isBranchingBitSet p i = 276 | i 277 | |> Bitwise.xor signBit 278 | -- This is a hack that fixes the ordering of keys. 279 | |> Bitwise.and p.branchingBit 280 | |> (/=) 0 281 | 282 | 283 | 284 | -- BUILD 285 | 286 | 287 | {-| Create an empty dictionary. 288 | -} 289 | empty : IntDict v 290 | empty = 291 | Empty 292 | 293 | 294 | {-| Create a dictionary with one key-value pair. 295 | -} 296 | singleton : Int -> v -> IntDict v 297 | singleton key value = 298 | leaf key value 299 | 300 | 301 | {-| Insert a key-value pair into a dictionary. Replaces value when there is 302 | a collision. 303 | -} 304 | insert : Int -> v -> IntDict v -> IntDict v 305 | insert key value dict = 306 | update key (always (Just value)) dict 307 | 308 | 309 | {-| Remove a key-value pair from a dictionary. If the key is not found, 310 | no changes are made. 311 | -} 312 | remove : Int -> IntDict v -> IntDict v 313 | remove key dict = 314 | update key (always Nothing) dict 315 | 316 | 317 | {-| Update the value of a dictionary for a specific key with a given function. 318 | -} 319 | update : Int -> (Maybe v -> Maybe v) -> IntDict v -> IntDict v 320 | update key alter dict = 321 | let 322 | alteredNode : Maybe v -> IntDict v 323 | alteredNode mv = 324 | case alter mv of 325 | -- handle this centrally 326 | Just v -> 327 | leaf key v 328 | 329 | Nothing -> 330 | empty 331 | 332 | -- The inner constructor will do the rest 333 | join : ( Int, IntDict v ) -> ( Int, IntDict v ) -> IntDict v 334 | join ( k1, l ) ( k2, r ) = 335 | -- precondition: k1 /= k2 336 | let 337 | prefix : KeyPrefix 338 | prefix = 339 | lcp k1 k2 340 | in 341 | if 342 | isBranchingBitSet prefix k2 343 | -- if so, r will be the right child 344 | then 345 | inner prefix l r 346 | 347 | else 348 | inner prefix r l 349 | in 350 | case dict of 351 | Empty -> 352 | alteredNode Nothing 353 | 354 | Leaf l -> 355 | if l.key - key == 0 then 356 | alteredNode (Just l.value) 357 | -- This updates or removes the leaf with the same key 358 | 359 | else 360 | join ( key, alteredNode Nothing ) ( l.key, dict ) 361 | 362 | -- This potentially inserts a new node 363 | Inner i -> 364 | if prefixMatches i.prefix key then 365 | if isBranchingBitSet i.prefix key then 366 | inner i.prefix i.left (update key alter i.right) 367 | 368 | else 369 | inner i.prefix (update key alter i.left) i.right 370 | 371 | else 372 | -- we have to join a new leaf with the current diverging Inner node 373 | join ( key, alteredNode Nothing ) ( i.prefix.prefixBits, dict ) 374 | 375 | 376 | 377 | -- QUERY 378 | 379 | 380 | {-| Check if the dictionary contains no items. 381 | -} 382 | isEmpty : IntDict v -> Bool 383 | isEmpty dict = 384 | case dict of 385 | Empty -> 386 | True 387 | 388 | _ -> 389 | False 390 | 391 | 392 | {-| The number of items in the dictionary. `O(1)`. 393 | -} 394 | size : IntDict v -> Int 395 | size dict = 396 | case dict of 397 | Empty -> 398 | 0 399 | 400 | Leaf _ -> 401 | 1 402 | 403 | Inner i -> 404 | i.size 405 | 406 | 407 | {-| Determine if a key is in a dictionary. 408 | -} 409 | member : Int -> IntDict v -> Bool 410 | member key dict = 411 | case get key dict of 412 | Just _ -> 413 | True 414 | 415 | Nothing -> 416 | False 417 | 418 | 419 | {-| Get the value associated with a key. If the key is not found, return 420 | `Nothing`. This is useful when you are not sure if a key will be in the 421 | dictionary. 422 | -} 423 | get : Int -> IntDict v -> Maybe v 424 | get key dict = 425 | case dict of 426 | Empty -> 427 | Nothing 428 | 429 | Leaf l -> 430 | if l.key - key == 0 then 431 | Just l.value 432 | 433 | else 434 | Nothing 435 | 436 | Inner i -> 437 | if not (prefixMatches i.prefix key) then 438 | Nothing 439 | 440 | else if 441 | -- continue in left or right branch 442 | isBranchingBitSet i.prefix key 443 | then 444 | -- depending on whether the branching 445 | get key i.right 446 | 447 | else 448 | -- bit is set in the key 449 | get key i.left 450 | 451 | 452 | {-| Find the key and value in the dictionary before the given key. 453 | -} 454 | before : Int -> IntDict v -> Maybe ( Int, v ) 455 | before key dict = 456 | let 457 | go : IntDict v -> IntDict v -> Maybe ( Int, v ) 458 | go def currentDict = 459 | case currentDict of 460 | Empty -> 461 | findMax def 462 | 463 | Leaf l -> 464 | if l.key >= key then 465 | findMax def 466 | 467 | else 468 | Just ( l.key, l.value ) 469 | 470 | Inner i -> 471 | if not (prefixMatches i.prefix key) then 472 | if i.prefix.prefixBits > key then 473 | findMax def 474 | 475 | else 476 | -- right must always be non-empty 477 | findMax i.right 478 | 479 | else if isBranchingBitSet i.prefix key then 480 | go i.left i.right 481 | 482 | else 483 | go def i.left 484 | in 485 | go Empty dict 486 | 487 | 488 | {-| Find the key and value in the dictionary after the given key. 489 | -} 490 | after : Int -> IntDict v -> Maybe ( Int, v ) 491 | after key dict = 492 | let 493 | go : IntDict v -> IntDict v -> Maybe ( Int, v ) 494 | go def currentDict = 495 | case currentDict of 496 | Empty -> 497 | findMin def 498 | 499 | Leaf l -> 500 | if l.key <= key then 501 | findMin def 502 | 503 | else 504 | Just ( l.key, l.value ) 505 | 506 | Inner i -> 507 | if not (prefixMatches i.prefix key) then 508 | if i.prefix.prefixBits < key then 509 | findMin def 510 | 511 | else 512 | -- left must always be non-empty 513 | findMin i.left 514 | 515 | else if isBranchingBitSet i.prefix key then 516 | go def i.right 517 | 518 | else 519 | go i.right i.left 520 | in 521 | go Empty dict 522 | 523 | 524 | {-| Find the minimum key and value in the dictionary. 525 | -} 526 | findMin : IntDict v -> Maybe ( Int, v ) 527 | findMin dict = 528 | case dict of 529 | Empty -> 530 | Nothing 531 | 532 | Leaf l -> 533 | Just ( l.key, l.value ) 534 | 535 | Inner i -> 536 | findMin i.left 537 | 538 | 539 | {-| Find the maximum key and value in the dictionary. 540 | -} 541 | findMax : IntDict v -> Maybe ( Int, v ) 542 | findMax dict = 543 | case dict of 544 | Empty -> 545 | Nothing 546 | 547 | Leaf l -> 548 | Just ( l.key, l.value ) 549 | 550 | Inner i -> 551 | findMax i.right 552 | 553 | 554 | 555 | -- TRANSFORM 556 | 557 | 558 | {-| Keep a key-value pair when it satisfies a predicate. 559 | -} 560 | filter : (Int -> v -> Bool) -> IntDict v -> IntDict v 561 | filter predicate dict = 562 | let 563 | add : Int -> v -> IntDict v -> IntDict v 564 | add k v d = 565 | if predicate k v then 566 | insert k v d 567 | 568 | else 569 | d 570 | in 571 | foldl add empty dict 572 | 573 | 574 | {-| Apply a function to all values in a dictionary. 575 | -} 576 | map : (Int -> a -> b) -> IntDict a -> IntDict b 577 | map f dict = 578 | case dict of 579 | Empty -> 580 | empty 581 | 582 | Leaf l -> 583 | leaf l.key (f l.key l.value) 584 | 585 | Inner i -> 586 | inner i.prefix (map f i.left) (map f i.right) 587 | 588 | 589 | {-| Fold over the key-value pairs in a dictionary, in order from lowest 590 | key to highest key. 591 | -} 592 | foldl : (Int -> v -> a -> a) -> a -> IntDict v -> a 593 | foldl f acc dict = 594 | case dict of 595 | Empty -> 596 | acc 597 | 598 | Leaf l -> 599 | f l.key l.value acc 600 | 601 | Inner i -> 602 | foldl f (foldl f acc i.left) i.right 603 | 604 | 605 | {-| Fold over the key-value pairs in a dictionary, in order from highest 606 | key to lowest key. 607 | -} 608 | foldr : (Int -> v -> a -> a) -> a -> IntDict v -> a 609 | foldr f acc dict = 610 | case dict of 611 | Empty -> 612 | acc 613 | 614 | Leaf l -> 615 | f l.key l.value acc 616 | 617 | Inner i -> 618 | foldr f (foldr f acc i.right) i.left 619 | 620 | 621 | {-| Partition a dictionary according to a predicate. The first dictionary 622 | contains all key-value pairs which satisfy the predicate, and the second 623 | contains the rest. 624 | -} 625 | partition : (Int -> v -> Bool) -> IntDict v -> ( IntDict v, IntDict v ) 626 | partition predicate dict = 627 | let 628 | add : Int -> v -> ( IntDict v, IntDict v ) -> ( IntDict v, IntDict v ) 629 | add key value ( l, r ) = 630 | if predicate key value then 631 | ( insert key value l, r ) 632 | 633 | else 634 | ( l, insert key value r ) 635 | in 636 | foldl add ( empty, empty ) dict 637 | 638 | 639 | {-| Split a dictionary around a pivot key. The first dictionary contains 640 | values whose key is less than the pivot, the second dictionary all values 641 | greater or equal the pivot. 642 | 643 | 644 | dict = 645 | fromList [ ( 0, "a" ), ( 1, "b" ), ( 2, "c" ), ( 5, "d" ) ] 646 | 647 | ( lower, higher ) = 648 | split 2 dict 649 | 650 | -- toList lower == [ (0, "a"), (1, "b") ] 651 | -- toList higher == [ (2, "c"), (5, "d") ] 652 | 653 | -} 654 | split : Int -> IntDict v -> ( IntDict v, IntDict v ) 655 | split key dict = 656 | case dict of 657 | Empty -> 658 | ( empty, empty ) 659 | 660 | Leaf l -> 661 | if l.key < key then 662 | ( dict, empty ) 663 | 664 | else 665 | ( empty, dict ) 666 | 667 | Inner i -> 668 | if prefixMatches i.prefix key then 669 | if isBranchingBitSet i.prefix key then 670 | let 671 | ( lt, ge ) = 672 | split key i.right 673 | in 674 | ( union i.left lt, ge ) 675 | 676 | else 677 | let 678 | ( lt, ge ) = 679 | split key i.left 680 | in 681 | ( lt, union ge i.right ) 682 | 683 | else if i.prefix.prefixBits < key then 684 | ( dict, empty ) 685 | 686 | else 687 | ( empty, dict ) 688 | 689 | 690 | {-| Extract a range of keys. The returned dictionary has only items whose keys 691 | are between low (inclusive) and high (exclusive). 692 | 693 | 694 | dict = 695 | fromList [ ( 0, "a" ), ( 1, "b" ), ( 2, "c" ), ( 5, "d" ) ] 696 | 697 | inRange = 698 | range 1 5 dict 699 | 700 | -- toList inRange == [ (1, "b"), (2, "c") ] 701 | 702 | -} 703 | range : Int -> Int -> IntDict v -> IntDict v 704 | range low high dict = 705 | let 706 | low_ : Int 707 | low_ = 708 | min low high 709 | 710 | high_ : Int 711 | high_ = 712 | max low high 713 | 714 | ( lessThanHigh, _ ) = 715 | split high_ dict 716 | 717 | ( _, greaterThanLow ) = 718 | split low_ lessThanHigh 719 | in 720 | greaterThanLow 721 | 722 | 723 | 724 | -- COMBINE 725 | 726 | 727 | type Choice 728 | = Left 729 | | Right 730 | 731 | 732 | type BranchRelation 733 | = SamePrefix 734 | | Parent Choice Choice -- which is the parent and which child the other is of the parent 735 | | Disjunct KeyPrefix Choice -- the longest common prefix and which child would be the left edge 736 | 737 | 738 | 739 | {- Take bits from a or b, depending on the value of the bit in that position in mask. 740 | 0 -> a, 1 -> b. Implemented as a & ~mask | b & mask 741 | -} 742 | 743 | 744 | combineBits : Int -> Int -> Int -> Int 745 | combineBits a b mask = 746 | Bitwise.or 747 | (Bitwise.and a (Bitwise.complement mask)) 748 | (Bitwise.and b mask) 749 | 750 | 751 | 752 | {- While merging/uniting 2 inner nodes, we encounter the 4 possible base cases 753 | represented by BranchRelation. This function computes that relation. 754 | -} 755 | 756 | 757 | determineBranchRelation : InnerType l -> InnerType r -> BranchRelation 758 | determineBranchRelation l r = 759 | let 760 | lp : KeyPrefix 761 | lp = 762 | l.prefix 763 | 764 | rp : KeyPrefix 765 | rp = 766 | r.prefix 767 | in 768 | if lp.prefixBits - rp.prefixBits == 0 && lp.branchingBit - rp.branchingBit == 0 then 769 | SamePrefix 770 | 771 | else 772 | let 773 | mask : Int 774 | mask = 775 | -- this is the region where we want to force different bits 776 | highestBitSet (mostSignificantBranchingBit lp.branchingBit rp.branchingBit) 777 | 778 | modifiedRightPrefix : Int 779 | modifiedRightPrefix = 780 | combineBits rp.prefixBits (Bitwise.complement lp.prefixBits) mask 781 | 782 | prefix : KeyPrefix 783 | prefix = 784 | lcp lp.prefixBits modifiedRightPrefix 785 | 786 | -- l.prefixBits and modifiedRightPrefix are guaranteed to be different 787 | childEdge : KeyPrefix -> InnerType q -> Choice 788 | childEdge branchPrefix c = 789 | if isBranchingBitSet branchPrefix c.prefix.prefixBits then 790 | Right 791 | 792 | else 793 | Left 794 | in 795 | if prefix.prefixBits - lp.prefixBits == 0 && prefix.branchingBit - lp.branchingBit == 0 then 796 | Parent Left (childEdge l.prefix r) 797 | 798 | else if prefix.prefixBits - rp.prefixBits == 0 && prefix.branchingBit - rp.branchingBit == 0 then 799 | Parent Right (childEdge r.prefix l) 800 | 801 | else 802 | Disjunct prefix (childEdge prefix l) 803 | 804 | 805 | {-| `uniteWith merger l r` combines two dictionaries. If there is a collision, `merger` 806 | is called with the conflicting key, the value from `l` and that from `r`. 807 | -} 808 | uniteWith : (Int -> v -> v -> v) -> IntDict v -> IntDict v -> IntDict v 809 | uniteWith merger l r = 810 | let 811 | mergeWith : Int -> Maybe v -> Maybe v -> Maybe v 812 | mergeWith key left right = 813 | case ( left, right ) of 814 | ( Just l2, Just r2 ) -> 815 | Just (merger key l2 r2) 816 | 817 | ( Just _, _ ) -> 818 | left 819 | 820 | ( _, Just _ ) -> 821 | right 822 | 823 | ( Nothing, Nothing ) -> 824 | -- This is a bug in the implementation, please file a bug report! 825 | Nothing 826 | in 827 | case ( l, r ) of 828 | ( Empty, _ ) -> 829 | r 830 | 831 | ( _, Empty ) -> 832 | l 833 | 834 | ( Leaf l2, _ ) -> 835 | update l2.key (\r_ -> mergeWith l2.key (Just l2.value) r_) r 836 | 837 | ( _, Leaf r2 ) -> 838 | update r2.key (\l_ -> mergeWith r2.key l_ (Just r2.value)) l 839 | 840 | ( Inner il, Inner ir ) -> 841 | case determineBranchRelation il ir of 842 | SamePrefix -> 843 | -- Merge both left and right sub trees 844 | inner il.prefix (uniteWith merger il.left ir.left) (uniteWith merger il.right ir.right) 845 | 846 | Parent Left Right -> 847 | -- Merge the right sub tree 848 | inner il.prefix il.left (uniteWith merger il.right r) 849 | 850 | Parent Right Right -> 851 | inner ir.prefix ir.left (uniteWith merger l ir.right) 852 | 853 | Parent Left Left -> 854 | -- Merge the left sub tree 855 | inner il.prefix (uniteWith merger il.left r) il.right 856 | 857 | Parent Right Left -> 858 | inner ir.prefix (uniteWith merger l ir.left) ir.right 859 | 860 | Disjunct parentPrefix Left -> 861 | -- Create a new inner node with l and r as sub trees 862 | inner parentPrefix l r 863 | 864 | -- `Left` --> `l` is the left child. 865 | Disjunct parentPrefix Right -> 866 | -- Create a new inner node with l and r as sub trees 867 | inner parentPrefix r l 868 | 869 | 870 | 871 | -- `Right` --> `r` is the left child. 872 | 873 | 874 | {-| Combine two dictionaries. If there is a collision, preference is given 875 | to the first dictionary. 876 | -} 877 | union : IntDict v -> IntDict v -> IntDict v 878 | union = 879 | uniteWith (\_ old _ -> old) 880 | 881 | 882 | {-| Keep a key-value pair when its key appears in the second dictionary. 883 | Preference is given to values in the first dictionary. 884 | -} 885 | intersect : IntDict a -> IntDict b -> IntDict a 886 | intersect l r = 887 | case ( l, r ) of 888 | ( Empty, _ ) -> 889 | Empty 890 | 891 | ( _, Empty ) -> 892 | Empty 893 | 894 | ( Leaf ll, _ ) -> 895 | if member ll.key r then 896 | l 897 | 898 | else 899 | Empty 900 | 901 | ( _, Leaf lr ) -> 902 | case get lr.key l of 903 | Just v -> 904 | leaf lr.key v 905 | 906 | Nothing -> 907 | Empty 908 | 909 | ( Inner il, Inner ir ) -> 910 | case determineBranchRelation il ir of 911 | SamePrefix -> 912 | -- Intersect both left and right sub trees 913 | inner il.prefix (intersect il.left ir.left) (intersect il.right ir.right) 914 | 915 | Parent Left Right -> 916 | intersect il.right r 917 | 918 | Parent Right Right -> 919 | intersect l ir.right 920 | 921 | Parent Left Left -> 922 | intersect il.left r 923 | 924 | Parent Right Left -> 925 | intersect l ir.left 926 | 927 | Disjunct _ _ -> 928 | Empty 929 | 930 | 931 | 932 | -- We have no common keys 933 | 934 | 935 | {-| Keep a key-value pair when its key does not appear in the second dictionary. 936 | -} 937 | diff : IntDict a -> IntDict b -> IntDict a 938 | diff l r = 939 | case ( l, r ) of 940 | ( Empty, _ ) -> 941 | Empty 942 | 943 | ( _, Empty ) -> 944 | l 945 | 946 | ( Leaf ll, _ ) -> 947 | if member ll.key r then 948 | Empty 949 | 950 | else 951 | l 952 | 953 | ( _, Leaf lr ) -> 954 | remove lr.key l 955 | 956 | ( Inner il, Inner ir ) -> 957 | case determineBranchRelation il ir of 958 | SamePrefix -> 959 | -- Diff both left and right sub trees 960 | inner il.prefix (diff il.left ir.left) (diff il.right ir.right) 961 | 962 | Parent Left Left -> 963 | inner il.prefix (diff il.left r) il.right 964 | 965 | Parent Left Right -> 966 | inner il.prefix il.left (diff il.right r) 967 | 968 | Parent Right Left -> 969 | diff l ir.left 970 | 971 | Parent Right Right -> 972 | diff l ir.right 973 | 974 | Disjunct _ _ -> 975 | l 976 | 977 | 978 | 979 | -- l and r contain different keys 980 | 981 | 982 | {-| The most general way of combining two dictionaries. You provide three 983 | accumulators for when a given key appears: 984 | 985 | 1. Only in the left dictionary. 986 | 2. In both dictionaries. 987 | 3. Only in the right dictionary. 988 | 989 | You then traverse all the keys from lowest to highest, building up whatever 990 | you want. 991 | 992 | Note that `uniteWith`, `union`, `intersect` and `diff` could all be implemented 993 | in terms of this function. The only reason that's not the case is to have more 994 | sharing of substructure. 995 | 996 | uniteWith merger l r = 997 | merge insert merger insert l r empty 998 | 999 | union l r = 1000 | merge insert (\k a _ d -> insert k a d) insert l r empty 1001 | 1002 | intersect l r = 1003 | merge (\_ _ d -> d) (\k a _ d -> insert k a d) (\_ _ d -> d) l r empty 1004 | 1005 | diff l r = 1006 | merge insert (\_ _ _ d -> d) (\_ _ d -> d) l r empty 1007 | 1008 | -} 1009 | merge : 1010 | (Int -> a -> result -> result) 1011 | -> (Int -> a -> b -> result -> result) 1012 | -> (Int -> b -> result -> result) 1013 | -> IntDict a 1014 | -> IntDict b 1015 | -> result 1016 | -> result 1017 | merge left both right l r acc = 1018 | let 1019 | m : IntDict a -> IntDict b -> result -> result 1020 | m = 1021 | merge left both right 1022 | in 1023 | case ( l, r ) of 1024 | ( Empty, _ ) -> 1025 | foldl right acc r 1026 | 1027 | ( _, Empty ) -> 1028 | foldl left acc l 1029 | 1030 | ( Leaf l2, _ ) -> 1031 | case get l2.key r of 1032 | Nothing -> 1033 | m Empty r (left l2.key l2.value acc) 1034 | 1035 | Just v -> 1036 | m Empty (remove l2.key r) (both l2.key l2.value v acc) 1037 | 1038 | ( _, Leaf r2 ) -> 1039 | case get r2.key l of 1040 | Nothing -> 1041 | m l Empty (right r2.key r2.value acc) 1042 | 1043 | Just v -> 1044 | m (remove r2.key l) Empty (both r2.key v r2.value acc) 1045 | 1046 | ( Inner il, Inner ir ) -> 1047 | case determineBranchRelation il ir of 1048 | SamePrefix -> 1049 | acc |> m il.left ir.left |> m il.right ir.right 1050 | 1051 | Parent Left Left -> 1052 | acc |> m il.left r |> m il.right Empty 1053 | 1054 | Parent Left Right -> 1055 | acc |> m il.left Empty |> m il.right r 1056 | 1057 | Parent Right Left -> 1058 | acc |> m l ir.left |> m Empty ir.right 1059 | 1060 | Parent Right Right -> 1061 | acc |> m Empty ir.left |> m l ir.right 1062 | 1063 | Disjunct _ Left -> 1064 | -- left and right dict are disjunct; left child would be the left edge in the merged dict 1065 | acc |> m l Empty |> m Empty r 1066 | 1067 | Disjunct _ Right -> 1068 | -- left and right dict are disjunct; left child would be the left edge in the merged dict 1069 | acc |> m Empty r |> m l Empty 1070 | 1071 | 1072 | 1073 | -- LISTS 1074 | 1075 | 1076 | {-| Get all of the keys in a dictionary, sorted from lowest to highest. 1077 | -} 1078 | keys : IntDict v -> List Int 1079 | keys dict = 1080 | foldr (\key _ keyList -> key :: keyList) [] dict 1081 | 1082 | 1083 | {-| Get all of the values in a dictionary, in the order of their keys. 1084 | -} 1085 | values : IntDict v -> List v 1086 | values dict = 1087 | foldr (\_ value valueList -> value :: valueList) [] dict 1088 | 1089 | 1090 | {-| Convert a dictionary into an association list of key-value pairs, sorted by keys. 1091 | -} 1092 | toList : IntDict v -> List ( Int, v ) 1093 | toList dict = 1094 | foldr (\key value list -> ( key, value ) :: list) [] dict 1095 | 1096 | 1097 | {-| Convert an association list into a dictionary. 1098 | -} 1099 | fromList : List ( Int, v ) -> IntDict v 1100 | fromList pairs = 1101 | List.foldl (\( a, b ) -> insert a b) empty pairs 1102 | 1103 | 1104 | 1105 | -- STRING REPRESENTATION 1106 | 1107 | 1108 | {-| Generates a string representation similar to what `toString` 1109 | generates for `Dict`. You must provide a function to convert 1110 | your value type into a string. 1111 | -} 1112 | toString : IntDict v -> (v -> String) -> String 1113 | toString dict valueToStr = 1114 | let 1115 | pairToStr : ( Int, v ) -> String 1116 | pairToStr ( k, v ) = 1117 | "(" ++ String.fromInt k ++ ", \"" ++ valueToStr v ++ "\")" 1118 | in 1119 | "IntDict.fromList " ++ String.join ", " (List.map pairToStr (toList dict)) 1120 | -------------------------------------------------------------------------------- /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 | "@nodelib/fs.scandir@2.1.5": 18 | version "2.1.5" 19 | resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" 20 | integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== 21 | dependencies: 22 | "@nodelib/fs.stat" "2.0.5" 23 | run-parallel "^1.1.9" 24 | 25 | "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": 26 | version "2.0.5" 27 | resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" 28 | integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== 29 | 30 | "@nodelib/fs.walk@^1.2.3": 31 | version "1.2.8" 32 | resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" 33 | integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== 34 | dependencies: 35 | "@nodelib/fs.scandir" "2.1.5" 36 | fastq "^1.6.0" 37 | 38 | "@pkgjs/parseargs@^0.11.0": 39 | version "0.11.0" 40 | resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" 41 | integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== 42 | 43 | "@sindresorhus/is@^4.0.0": 44 | version "4.6.0" 45 | resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" 46 | integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== 47 | 48 | "@szmarczak/http-timer@^4.0.5": 49 | version "4.0.6" 50 | resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" 51 | integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== 52 | dependencies: 53 | defer-to-connect "^2.0.0" 54 | 55 | "@types/cacheable-request@^6.0.1": 56 | version "6.0.3" 57 | resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" 58 | integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw== 59 | dependencies: 60 | "@types/http-cache-semantics" "*" 61 | "@types/keyv" "^3.1.4" 62 | "@types/node" "*" 63 | "@types/responselike" "^1.0.0" 64 | 65 | "@types/http-cache-semantics@*": 66 | version "4.0.4" 67 | resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz#b979ebad3919799c979b17c72621c0bc0a31c6c4" 68 | integrity sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA== 69 | 70 | "@types/keyv@^3.1.4": 71 | version "3.1.4" 72 | resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" 73 | integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== 74 | dependencies: 75 | "@types/node" "*" 76 | 77 | "@types/node@*": 78 | version "22.2.0" 79 | resolved "https://registry.yarnpkg.com/@types/node/-/node-22.2.0.tgz#7cf046a99f0ba4d628ad3088cb21f790df9b0c5b" 80 | integrity sha512-bm6EG6/pCpkxDf/0gDNDdtDILMOHgaQBVOJGdwsqClnxA3xL6jtMv76rLBc006RVMWbmaf0xbmom4Z/5o2nRkQ== 81 | dependencies: 82 | undici-types "~6.13.0" 83 | 84 | "@types/responselike@^1.0.0": 85 | version "1.0.3" 86 | resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.3.tgz#cc29706f0a397cfe6df89debfe4bf5cea159db50" 87 | integrity sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw== 88 | dependencies: 89 | "@types/node" "*" 90 | 91 | ansi-escapes@^4.2.1: 92 | version "4.3.2" 93 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" 94 | integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== 95 | dependencies: 96 | type-fest "^0.21.3" 97 | 98 | ansi-regex@^5.0.1: 99 | version "5.0.1" 100 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 101 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 102 | 103 | ansi-regex@^6.0.1: 104 | version "6.0.1" 105 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" 106 | integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== 107 | 108 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 109 | version "4.3.0" 110 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 111 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 112 | dependencies: 113 | color-convert "^2.0.1" 114 | 115 | ansi-styles@^6.1.0: 116 | version "6.2.1" 117 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" 118 | integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== 119 | 120 | anymatch@~3.1.2: 121 | version "3.1.3" 122 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" 123 | integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== 124 | dependencies: 125 | normalize-path "^3.0.0" 126 | picomatch "^2.0.4" 127 | 128 | at-least-node@^1.0.0: 129 | version "1.0.0" 130 | resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" 131 | integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== 132 | 133 | balanced-match@^1.0.0: 134 | version "1.0.2" 135 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 136 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 137 | 138 | base64-js@^1.3.1: 139 | version "1.5.1" 140 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" 141 | integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== 142 | 143 | binary-extensions@^2.0.0: 144 | version "2.3.0" 145 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" 146 | integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== 147 | 148 | bl@^4.1.0: 149 | version "4.1.0" 150 | resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" 151 | integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== 152 | dependencies: 153 | buffer "^5.5.0" 154 | inherits "^2.0.4" 155 | readable-stream "^3.4.0" 156 | 157 | brace-expansion@^1.1.7: 158 | version "1.1.11" 159 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 160 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 161 | dependencies: 162 | balanced-match "^1.0.0" 163 | concat-map "0.0.1" 164 | 165 | brace-expansion@^2.0.1: 166 | version "2.0.1" 167 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" 168 | integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== 169 | dependencies: 170 | balanced-match "^1.0.0" 171 | 172 | braces@^3.0.3, braces@~3.0.2: 173 | version "3.0.3" 174 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" 175 | integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== 176 | dependencies: 177 | fill-range "^7.1.1" 178 | 179 | buffer@^5.5.0: 180 | version "5.7.1" 181 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" 182 | integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== 183 | dependencies: 184 | base64-js "^1.3.1" 185 | ieee754 "^1.1.13" 186 | 187 | cacheable-lookup@^5.0.3: 188 | version "5.0.4" 189 | resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" 190 | integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== 191 | 192 | cacheable-request@^7.0.2: 193 | version "7.0.4" 194 | resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.4.tgz#7a33ebf08613178b403635be7b899d3e69bbe817" 195 | integrity sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg== 196 | dependencies: 197 | clone-response "^1.0.2" 198 | get-stream "^5.1.0" 199 | http-cache-semantics "^4.0.0" 200 | keyv "^4.0.0" 201 | lowercase-keys "^2.0.0" 202 | normalize-url "^6.0.1" 203 | responselike "^2.0.0" 204 | 205 | chalk@^4.0.0, chalk@^4.1.0: 206 | version "4.1.2" 207 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 208 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 209 | dependencies: 210 | ansi-styles "^4.1.0" 211 | supports-color "^7.1.0" 212 | 213 | chokidar@^3.5.2: 214 | version "3.6.0" 215 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" 216 | integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== 217 | dependencies: 218 | anymatch "~3.1.2" 219 | braces "~3.0.2" 220 | glob-parent "~5.1.2" 221 | is-binary-path "~2.1.0" 222 | is-glob "~4.0.1" 223 | normalize-path "~3.0.0" 224 | readdirp "~3.6.0" 225 | optionalDependencies: 226 | fsevents "~2.3.2" 227 | 228 | cli-cursor@^3.1.0: 229 | version "3.1.0" 230 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" 231 | integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== 232 | dependencies: 233 | restore-cursor "^3.1.0" 234 | 235 | cli-spinners@^2.5.0: 236 | version "2.9.2" 237 | resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" 238 | integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== 239 | 240 | clone-response@^1.0.2: 241 | version "1.0.3" 242 | resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" 243 | integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== 244 | dependencies: 245 | mimic-response "^1.0.0" 246 | 247 | clone@^1.0.2: 248 | version "1.0.4" 249 | resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" 250 | integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== 251 | 252 | color-convert@^2.0.1: 253 | version "2.0.1" 254 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 255 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 256 | dependencies: 257 | color-name "~1.1.4" 258 | 259 | color-name@~1.1.4: 260 | version "1.1.4" 261 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 262 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 263 | 264 | concat-map@0.0.1: 265 | version "0.0.1" 266 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 267 | integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== 268 | 269 | cross-spawn@^7.0.0, cross-spawn@^7.0.3: 270 | version "7.0.3" 271 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" 272 | integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== 273 | dependencies: 274 | path-key "^3.1.0" 275 | shebang-command "^2.0.0" 276 | which "^2.0.1" 277 | 278 | debug@^4.1.1: 279 | version "4.3.6" 280 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" 281 | integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== 282 | dependencies: 283 | ms "2.1.2" 284 | 285 | decompress-response@^6.0.0: 286 | version "6.0.0" 287 | resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" 288 | integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== 289 | dependencies: 290 | mimic-response "^3.1.0" 291 | 292 | defaults@^1.0.3: 293 | version "1.0.4" 294 | resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" 295 | integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== 296 | dependencies: 297 | clone "^1.0.2" 298 | 299 | defer-to-connect@^2.0.0: 300 | version "2.0.1" 301 | resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" 302 | integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== 303 | 304 | dir-glob@^3.0.1: 305 | version "3.0.1" 306 | resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" 307 | integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== 308 | dependencies: 309 | path-type "^4.0.0" 310 | 311 | eastasianwidth@^0.2.0: 312 | version "0.2.0" 313 | resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" 314 | integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== 315 | 316 | elm-review@^2.12.0: 317 | version "2.12.0" 318 | resolved "https://registry.yarnpkg.com/elm-review/-/elm-review-2.12.0.tgz#79d05d2b399a03981eebe60073fdf8152c934729" 319 | integrity sha512-so+G1hvCV85A63sQQzEhCNFNYyQVWDexXrz0TNEYg3/IIGHzN1bcRN+W4KJSvvFcmfEImzMSJ9AN20bvemU+4Q== 320 | dependencies: 321 | chalk "^4.0.0" 322 | chokidar "^3.5.2" 323 | cross-spawn "^7.0.3" 324 | elm-solve-deps-wasm "^1.0.2" 325 | fastest-levenshtein "^1.0.16" 326 | find-up "^4.1.0" 327 | folder-hash "^3.3.0" 328 | fs-extra "^9.0.0" 329 | glob "^10.2.6" 330 | globby "^13.2.2" 331 | got "^11.8.5" 332 | graceful-fs "^4.2.11" 333 | minimist "^1.2.6" 334 | ora "^5.4.0" 335 | path-key "^3.1.1" 336 | prompts "^2.2.1" 337 | rimraf "^5.0.0" 338 | strip-ansi "^6.0.0" 339 | terminal-link "^2.1.1" 340 | which "^2.0.2" 341 | wrap-ansi "^7.0.0" 342 | 343 | elm-solve-deps-wasm@^1.0.2: 344 | version "1.0.2" 345 | resolved "https://registry.yarnpkg.com/elm-solve-deps-wasm/-/elm-solve-deps-wasm-1.0.2.tgz#cabd3cadf344295944b8d046a857b6ee05e12aaf" 346 | integrity sha512-qnwo7RO9IO7jd9SLHvIy0rSOEIlc/tNMTE9Cras0kl+b161PVidW4FvXo0MtXU8GAKi/2s/HYvhcnpR/NNQ1zw== 347 | 348 | emoji-regex@^8.0.0: 349 | version "8.0.0" 350 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 351 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 352 | 353 | emoji-regex@^9.2.2: 354 | version "9.2.2" 355 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" 356 | integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== 357 | 358 | end-of-stream@^1.1.0: 359 | version "1.4.4" 360 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" 361 | integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== 362 | dependencies: 363 | once "^1.4.0" 364 | 365 | fast-glob@^3.3.0: 366 | version "3.3.2" 367 | resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" 368 | integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== 369 | dependencies: 370 | "@nodelib/fs.stat" "^2.0.2" 371 | "@nodelib/fs.walk" "^1.2.3" 372 | glob-parent "^5.1.2" 373 | merge2 "^1.3.0" 374 | micromatch "^4.0.4" 375 | 376 | fastest-levenshtein@^1.0.16: 377 | version "1.0.16" 378 | resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" 379 | integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== 380 | 381 | fastq@^1.6.0: 382 | version "1.17.1" 383 | resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" 384 | integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== 385 | dependencies: 386 | reusify "^1.0.4" 387 | 388 | fill-range@^7.1.1: 389 | version "7.1.1" 390 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" 391 | integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== 392 | dependencies: 393 | to-regex-range "^5.0.1" 394 | 395 | find-up@^4.1.0: 396 | version "4.1.0" 397 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" 398 | integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== 399 | dependencies: 400 | locate-path "^5.0.0" 401 | path-exists "^4.0.0" 402 | 403 | folder-hash@^3.3.0: 404 | version "3.3.3" 405 | resolved "https://registry.yarnpkg.com/folder-hash/-/folder-hash-3.3.3.tgz#883c8359d54f91b3f02c1a646c00c30e5831365b" 406 | integrity sha512-SDgHBgV+RCjrYs8aUwCb9rTgbTVuSdzvFmLaChsLre1yf+D64khCW++VYciaByZ8Rm0uKF8R/XEpXuTRSGUM1A== 407 | dependencies: 408 | debug "^4.1.1" 409 | graceful-fs "~4.2.0" 410 | minimatch "~3.0.4" 411 | 412 | foreground-child@^3.1.0: 413 | version "3.3.0" 414 | resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77" 415 | integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg== 416 | dependencies: 417 | cross-spawn "^7.0.0" 418 | signal-exit "^4.0.1" 419 | 420 | fs-extra@^9.0.0: 421 | version "9.1.0" 422 | resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" 423 | integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== 424 | dependencies: 425 | at-least-node "^1.0.0" 426 | graceful-fs "^4.2.0" 427 | jsonfile "^6.0.1" 428 | universalify "^2.0.0" 429 | 430 | fsevents@~2.3.2: 431 | version "2.3.3" 432 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" 433 | integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== 434 | 435 | get-stream@^5.1.0: 436 | version "5.2.0" 437 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" 438 | integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== 439 | dependencies: 440 | pump "^3.0.0" 441 | 442 | glob-parent@^5.1.2, glob-parent@~5.1.2: 443 | version "5.1.2" 444 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 445 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 446 | dependencies: 447 | is-glob "^4.0.1" 448 | 449 | glob@^10.2.6, glob@^10.3.7: 450 | version "10.4.5" 451 | resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" 452 | integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== 453 | dependencies: 454 | foreground-child "^3.1.0" 455 | jackspeak "^3.1.2" 456 | minimatch "^9.0.4" 457 | minipass "^7.1.2" 458 | package-json-from-dist "^1.0.0" 459 | path-scurry "^1.11.1" 460 | 461 | globby@^13.2.2: 462 | version "13.2.2" 463 | resolved "https://registry.yarnpkg.com/globby/-/globby-13.2.2.tgz#63b90b1bf68619c2135475cbd4e71e66aa090592" 464 | integrity sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w== 465 | dependencies: 466 | dir-glob "^3.0.1" 467 | fast-glob "^3.3.0" 468 | ignore "^5.2.4" 469 | merge2 "^1.4.1" 470 | slash "^4.0.0" 471 | 472 | got@^11.8.5: 473 | version "11.8.6" 474 | resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" 475 | integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== 476 | dependencies: 477 | "@sindresorhus/is" "^4.0.0" 478 | "@szmarczak/http-timer" "^4.0.5" 479 | "@types/cacheable-request" "^6.0.1" 480 | "@types/responselike" "^1.0.0" 481 | cacheable-lookup "^5.0.3" 482 | cacheable-request "^7.0.2" 483 | decompress-response "^6.0.0" 484 | http2-wrapper "^1.0.0-beta.5.2" 485 | lowercase-keys "^2.0.0" 486 | p-cancelable "^2.0.0" 487 | responselike "^2.0.0" 488 | 489 | graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@~4.2.0: 490 | version "4.2.11" 491 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" 492 | integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== 493 | 494 | has-flag@^4.0.0: 495 | version "4.0.0" 496 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 497 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 498 | 499 | http-cache-semantics@^4.0.0: 500 | version "4.1.1" 501 | resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" 502 | integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== 503 | 504 | http2-wrapper@^1.0.0-beta.5.2: 505 | version "1.0.3" 506 | resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" 507 | integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== 508 | dependencies: 509 | quick-lru "^5.1.1" 510 | resolve-alpn "^1.0.0" 511 | 512 | ieee754@^1.1.13: 513 | version "1.2.1" 514 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" 515 | integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== 516 | 517 | ignore@^5.2.4: 518 | version "5.3.2" 519 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" 520 | integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== 521 | 522 | inherits@^2.0.3, inherits@^2.0.4: 523 | version "2.0.4" 524 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 525 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 526 | 527 | is-binary-path@~2.1.0: 528 | version "2.1.0" 529 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 530 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 531 | dependencies: 532 | binary-extensions "^2.0.0" 533 | 534 | is-extglob@^2.1.1: 535 | version "2.1.1" 536 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 537 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 538 | 539 | is-fullwidth-code-point@^3.0.0: 540 | version "3.0.0" 541 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 542 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 543 | 544 | is-glob@^4.0.1, is-glob@~4.0.1: 545 | version "4.0.3" 546 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 547 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 548 | dependencies: 549 | is-extglob "^2.1.1" 550 | 551 | is-interactive@^1.0.0: 552 | version "1.0.0" 553 | resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" 554 | integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== 555 | 556 | is-number@^7.0.0: 557 | version "7.0.0" 558 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 559 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 560 | 561 | is-unicode-supported@^0.1.0: 562 | version "0.1.0" 563 | resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" 564 | integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== 565 | 566 | isexe@^2.0.0: 567 | version "2.0.0" 568 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 569 | integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== 570 | 571 | jackspeak@^3.1.2: 572 | version "3.4.3" 573 | resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" 574 | integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== 575 | dependencies: 576 | "@isaacs/cliui" "^8.0.2" 577 | optionalDependencies: 578 | "@pkgjs/parseargs" "^0.11.0" 579 | 580 | json-buffer@3.0.1: 581 | version "3.0.1" 582 | resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" 583 | integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== 584 | 585 | jsonfile@^6.0.1: 586 | version "6.1.0" 587 | resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" 588 | integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== 589 | dependencies: 590 | universalify "^2.0.0" 591 | optionalDependencies: 592 | graceful-fs "^4.1.6" 593 | 594 | keyv@^4.0.0: 595 | version "4.5.4" 596 | resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" 597 | integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== 598 | dependencies: 599 | json-buffer "3.0.1" 600 | 601 | kleur@^3.0.3: 602 | version "3.0.3" 603 | resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" 604 | integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== 605 | 606 | locate-path@^5.0.0: 607 | version "5.0.0" 608 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" 609 | integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== 610 | dependencies: 611 | p-locate "^4.1.0" 612 | 613 | log-symbols@^4.1.0: 614 | version "4.1.0" 615 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" 616 | integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== 617 | dependencies: 618 | chalk "^4.1.0" 619 | is-unicode-supported "^0.1.0" 620 | 621 | lowercase-keys@^2.0.0: 622 | version "2.0.0" 623 | resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" 624 | integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== 625 | 626 | lru-cache@^10.2.0: 627 | version "10.4.3" 628 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" 629 | integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== 630 | 631 | merge2@^1.3.0, merge2@^1.4.1: 632 | version "1.4.1" 633 | resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" 634 | integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== 635 | 636 | micromatch@^4.0.4: 637 | version "4.0.7" 638 | resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" 639 | integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== 640 | dependencies: 641 | braces "^3.0.3" 642 | picomatch "^2.3.1" 643 | 644 | mimic-fn@^2.1.0: 645 | version "2.1.0" 646 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" 647 | integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== 648 | 649 | mimic-response@^1.0.0: 650 | version "1.0.1" 651 | resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" 652 | integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== 653 | 654 | mimic-response@^3.1.0: 655 | version "3.1.0" 656 | resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" 657 | integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== 658 | 659 | minimatch@^9.0.4: 660 | version "9.0.5" 661 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" 662 | integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== 663 | dependencies: 664 | brace-expansion "^2.0.1" 665 | 666 | minimatch@~3.0.4: 667 | version "3.0.8" 668 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1" 669 | integrity sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q== 670 | dependencies: 671 | brace-expansion "^1.1.7" 672 | 673 | minimist@^1.2.6: 674 | version "1.2.8" 675 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" 676 | integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== 677 | 678 | "minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: 679 | version "7.1.2" 680 | resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" 681 | integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== 682 | 683 | ms@2.1.2: 684 | version "2.1.2" 685 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 686 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 687 | 688 | normalize-path@^3.0.0, normalize-path@~3.0.0: 689 | version "3.0.0" 690 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 691 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 692 | 693 | normalize-url@^6.0.1: 694 | version "6.1.0" 695 | resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" 696 | integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== 697 | 698 | once@^1.3.1, once@^1.4.0: 699 | version "1.4.0" 700 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 701 | integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== 702 | dependencies: 703 | wrappy "1" 704 | 705 | onetime@^5.1.0: 706 | version "5.1.2" 707 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" 708 | integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== 709 | dependencies: 710 | mimic-fn "^2.1.0" 711 | 712 | ora@^5.4.0: 713 | version "5.4.1" 714 | resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" 715 | integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== 716 | dependencies: 717 | bl "^4.1.0" 718 | chalk "^4.1.0" 719 | cli-cursor "^3.1.0" 720 | cli-spinners "^2.5.0" 721 | is-interactive "^1.0.0" 722 | is-unicode-supported "^0.1.0" 723 | log-symbols "^4.1.0" 724 | strip-ansi "^6.0.0" 725 | wcwidth "^1.0.1" 726 | 727 | p-cancelable@^2.0.0: 728 | version "2.1.1" 729 | resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" 730 | integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== 731 | 732 | p-limit@^2.2.0: 733 | version "2.3.0" 734 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" 735 | integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== 736 | dependencies: 737 | p-try "^2.0.0" 738 | 739 | p-locate@^4.1.0: 740 | version "4.1.0" 741 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" 742 | integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== 743 | dependencies: 744 | p-limit "^2.2.0" 745 | 746 | p-try@^2.0.0: 747 | version "2.2.0" 748 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" 749 | integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== 750 | 751 | package-json-from-dist@^1.0.0: 752 | version "1.0.0" 753 | resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz#e501cd3094b278495eb4258d4c9f6d5ac3019f00" 754 | integrity sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw== 755 | 756 | path-exists@^4.0.0: 757 | version "4.0.0" 758 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 759 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 760 | 761 | path-key@^3.1.0, path-key@^3.1.1: 762 | version "3.1.1" 763 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 764 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 765 | 766 | path-scurry@^1.11.1: 767 | version "1.11.1" 768 | resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" 769 | integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== 770 | dependencies: 771 | lru-cache "^10.2.0" 772 | minipass "^5.0.0 || ^6.0.2 || ^7.0.0" 773 | 774 | path-type@^4.0.0: 775 | version "4.0.0" 776 | resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" 777 | integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== 778 | 779 | picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: 780 | version "2.3.1" 781 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 782 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 783 | 784 | prompts@^2.2.1: 785 | version "2.4.2" 786 | resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" 787 | integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== 788 | dependencies: 789 | kleur "^3.0.3" 790 | sisteransi "^1.0.5" 791 | 792 | pump@^3.0.0: 793 | version "3.0.0" 794 | resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" 795 | integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== 796 | dependencies: 797 | end-of-stream "^1.1.0" 798 | once "^1.3.1" 799 | 800 | queue-microtask@^1.2.2: 801 | version "1.2.3" 802 | resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" 803 | integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== 804 | 805 | quick-lru@^5.1.1: 806 | version "5.1.1" 807 | resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" 808 | integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== 809 | 810 | readable-stream@^3.4.0: 811 | version "3.6.2" 812 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" 813 | integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== 814 | dependencies: 815 | inherits "^2.0.3" 816 | string_decoder "^1.1.1" 817 | util-deprecate "^1.0.1" 818 | 819 | readdirp@~3.6.0: 820 | version "3.6.0" 821 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 822 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 823 | dependencies: 824 | picomatch "^2.2.1" 825 | 826 | resolve-alpn@^1.0.0: 827 | version "1.2.1" 828 | resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" 829 | integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== 830 | 831 | responselike@^2.0.0: 832 | version "2.0.1" 833 | resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" 834 | integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw== 835 | dependencies: 836 | lowercase-keys "^2.0.0" 837 | 838 | restore-cursor@^3.1.0: 839 | version "3.1.0" 840 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" 841 | integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== 842 | dependencies: 843 | onetime "^5.1.0" 844 | signal-exit "^3.0.2" 845 | 846 | reusify@^1.0.4: 847 | version "1.0.4" 848 | resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" 849 | integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== 850 | 851 | rimraf@^5.0.0: 852 | version "5.0.10" 853 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.10.tgz#23b9843d3dc92db71f96e1a2ce92e39fd2a8221c" 854 | integrity sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ== 855 | dependencies: 856 | glob "^10.3.7" 857 | 858 | run-parallel@^1.1.9: 859 | version "1.2.0" 860 | resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" 861 | integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== 862 | dependencies: 863 | queue-microtask "^1.2.2" 864 | 865 | safe-buffer@~5.2.0: 866 | version "5.2.1" 867 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 868 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 869 | 870 | shebang-command@^2.0.0: 871 | version "2.0.0" 872 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 873 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 874 | dependencies: 875 | shebang-regex "^3.0.0" 876 | 877 | shebang-regex@^3.0.0: 878 | version "3.0.0" 879 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 880 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 881 | 882 | signal-exit@^3.0.2: 883 | version "3.0.7" 884 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" 885 | integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== 886 | 887 | signal-exit@^4.0.1: 888 | version "4.1.0" 889 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" 890 | integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== 891 | 892 | sisteransi@^1.0.5: 893 | version "1.0.5" 894 | resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" 895 | integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== 896 | 897 | slash@^4.0.0: 898 | version "4.0.0" 899 | resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" 900 | integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== 901 | 902 | "string-width-cjs@npm:string-width@^4.2.0": 903 | version "4.2.3" 904 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 905 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 906 | dependencies: 907 | emoji-regex "^8.0.0" 908 | is-fullwidth-code-point "^3.0.0" 909 | strip-ansi "^6.0.1" 910 | 911 | string-width@^4.1.0: 912 | version "4.2.3" 913 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 914 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 915 | dependencies: 916 | emoji-regex "^8.0.0" 917 | is-fullwidth-code-point "^3.0.0" 918 | strip-ansi "^6.0.1" 919 | 920 | string-width@^5.0.1, string-width@^5.1.2: 921 | version "5.1.2" 922 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" 923 | integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== 924 | dependencies: 925 | eastasianwidth "^0.2.0" 926 | emoji-regex "^9.2.2" 927 | strip-ansi "^7.0.1" 928 | 929 | string_decoder@^1.1.1: 930 | version "1.3.0" 931 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" 932 | integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== 933 | dependencies: 934 | safe-buffer "~5.2.0" 935 | 936 | "strip-ansi-cjs@npm:strip-ansi@^6.0.1": 937 | version "6.0.1" 938 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 939 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 940 | dependencies: 941 | ansi-regex "^5.0.1" 942 | 943 | strip-ansi@^6.0.0, strip-ansi@^6.0.1: 944 | version "6.0.1" 945 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 946 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 947 | dependencies: 948 | ansi-regex "^5.0.1" 949 | 950 | strip-ansi@^7.0.1: 951 | version "7.1.0" 952 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" 953 | integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== 954 | dependencies: 955 | ansi-regex "^6.0.1" 956 | 957 | supports-color@^7.0.0, supports-color@^7.1.0: 958 | version "7.2.0" 959 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 960 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 961 | dependencies: 962 | has-flag "^4.0.0" 963 | 964 | supports-hyperlinks@^2.0.0: 965 | version "2.3.0" 966 | resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" 967 | integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== 968 | dependencies: 969 | has-flag "^4.0.0" 970 | supports-color "^7.0.0" 971 | 972 | terminal-link@^2.1.1: 973 | version "2.1.1" 974 | resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" 975 | integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== 976 | dependencies: 977 | ansi-escapes "^4.2.1" 978 | supports-hyperlinks "^2.0.0" 979 | 980 | to-regex-range@^5.0.1: 981 | version "5.0.1" 982 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 983 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 984 | dependencies: 985 | is-number "^7.0.0" 986 | 987 | type-fest@^0.21.3: 988 | version "0.21.3" 989 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" 990 | integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== 991 | 992 | undici-types@~6.13.0: 993 | version "6.13.0" 994 | resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.13.0.tgz#e3e79220ab8c81ed1496b5812471afd7cf075ea5" 995 | integrity sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg== 996 | 997 | universalify@^2.0.0: 998 | version "2.0.1" 999 | resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" 1000 | integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== 1001 | 1002 | util-deprecate@^1.0.1: 1003 | version "1.0.2" 1004 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 1005 | integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== 1006 | 1007 | wcwidth@^1.0.1: 1008 | version "1.0.1" 1009 | resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" 1010 | integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== 1011 | dependencies: 1012 | defaults "^1.0.3" 1013 | 1014 | which@^2.0.1, which@^2.0.2: 1015 | version "2.0.2" 1016 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 1017 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1018 | dependencies: 1019 | isexe "^2.0.0" 1020 | 1021 | "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": 1022 | version "7.0.0" 1023 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 1024 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 1025 | dependencies: 1026 | ansi-styles "^4.0.0" 1027 | string-width "^4.1.0" 1028 | strip-ansi "^6.0.0" 1029 | 1030 | wrap-ansi@^7.0.0: 1031 | version "7.0.0" 1032 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 1033 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 1034 | dependencies: 1035 | ansi-styles "^4.0.0" 1036 | string-width "^4.1.0" 1037 | strip-ansi "^6.0.0" 1038 | 1039 | wrap-ansi@^8.1.0: 1040 | version "8.1.0" 1041 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" 1042 | integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== 1043 | dependencies: 1044 | ansi-styles "^6.1.0" 1045 | string-width "^5.0.1" 1046 | strip-ansi "^7.0.1" 1047 | 1048 | wrappy@1: 1049 | version "1.0.2" 1050 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1051 | integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== 1052 | --------------------------------------------------------------------------------