├── .editorconfig ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── bin └── elm-outdated ├── elm.json ├── example-output.png ├── package-lock.json ├── package.json └── src ├── Main.elm ├── Old.elm └── index.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | charset = utf-8 11 | indent_style = space 12 | indent_size = 2 13 | 14 | [*.elm] 15 | indent_size = 4 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | node_modules 3 | elm-stuff 4 | src/elm.js 5 | src/old.js 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | elm-stuff 2 | elm-package.json 3 | Main.elm 4 | .vscode 5 | .editorconfig 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017-present Fedor Nezhivoi 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # elm-outdated 2 | 3 | Small tool to help you keep your Elm dependencies up-to-date. Inspired by `npm outdated`. 4 | 5 | ### Installation 6 | 7 | ``` 8 | npm i -g elm-outdated 9 | ``` 10 | 11 | ### Usage 12 | 13 | Just run `elm-outdated` in your project directory where `elm.json` or `elm-package.json` is located. 14 | 15 | ### Example 16 | 17 | ![Example output](example-output.png) 18 | -------------------------------------------------------------------------------- /bin/elm-outdated: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require("../src/index.js"); 4 | -------------------------------------------------------------------------------- /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.1", 12 | "elm/random": "1.0.0" 13 | }, 14 | "indirect": { 15 | "elm/parser": "1.1.0", 16 | "elm/time": "1.0.0" 17 | } 18 | }, 19 | "test-dependencies": { 20 | "direct": {}, 21 | "indirect": {} 22 | } 23 | } -------------------------------------------------------------------------------- /example-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gyzerok/elm-outdated/43d690ab7b91530da0326341f0b896f339fd1757/example-output.png -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "elm-outdated", 3 | "version": "1.1.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ajv": { 8 | "version": "6.12.0", 9 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", 10 | "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", 11 | "dev": true, 12 | "requires": { 13 | "fast-deep-equal": "^3.1.1", 14 | "fast-json-stable-stringify": "^2.0.0", 15 | "json-schema-traverse": "^0.4.1", 16 | "uri-js": "^4.2.2" 17 | } 18 | }, 19 | "ansi-regex": { 20 | "version": "2.1.1", 21 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 22 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 23 | }, 24 | "asn1": { 25 | "version": "0.2.4", 26 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 27 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 28 | "dev": true, 29 | "requires": { 30 | "safer-buffer": "~2.1.0" 31 | } 32 | }, 33 | "assert-plus": { 34 | "version": "1.0.0", 35 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 36 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", 37 | "dev": true 38 | }, 39 | "asynckit": { 40 | "version": "0.4.0", 41 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 42 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", 43 | "dev": true 44 | }, 45 | "aws-sign2": { 46 | "version": "0.7.0", 47 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 48 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", 49 | "dev": true 50 | }, 51 | "aws4": { 52 | "version": "1.9.1", 53 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", 54 | "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", 55 | "dev": true 56 | }, 57 | "bcrypt-pbkdf": { 58 | "version": "1.0.2", 59 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 60 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 61 | "dev": true, 62 | "requires": { 63 | "tweetnacl": "^0.14.3" 64 | } 65 | }, 66 | "caseless": { 67 | "version": "0.12.0", 68 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 69 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", 70 | "dev": true 71 | }, 72 | "cli-color": { 73 | "version": "1.4.0", 74 | "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", 75 | "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", 76 | "requires": { 77 | "ansi-regex": "^2.1.1", 78 | "d": "1", 79 | "es5-ext": "^0.10.46", 80 | "es6-iterator": "^2.0.3", 81 | "memoizee": "^0.4.14", 82 | "timers-ext": "^0.1.5" 83 | } 84 | }, 85 | "combined-stream": { 86 | "version": "1.0.8", 87 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 88 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 89 | "dev": true, 90 | "requires": { 91 | "delayed-stream": "~1.0.0" 92 | } 93 | }, 94 | "core-util-is": { 95 | "version": "1.0.2", 96 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 97 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 98 | "dev": true 99 | }, 100 | "d": { 101 | "version": "1.0.1", 102 | "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", 103 | "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", 104 | "requires": { 105 | "es5-ext": "^0.10.50", 106 | "type": "^1.0.1" 107 | } 108 | }, 109 | "dashdash": { 110 | "version": "1.14.1", 111 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 112 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 113 | "dev": true, 114 | "requires": { 115 | "assert-plus": "^1.0.0" 116 | } 117 | }, 118 | "delayed-stream": { 119 | "version": "1.0.0", 120 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 121 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 122 | "dev": true 123 | }, 124 | "ecc-jsbn": { 125 | "version": "0.1.2", 126 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 127 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 128 | "dev": true, 129 | "requires": { 130 | "jsbn": "~0.1.0", 131 | "safer-buffer": "^2.1.0" 132 | } 133 | }, 134 | "elm": { 135 | "version": "0.19.1-3", 136 | "resolved": "https://registry.npmjs.org/elm/-/elm-0.19.1-3.tgz", 137 | "integrity": "sha512-6y36ewCcVmTOx8lj7cKJs3bhI5qMfoVEigePZ9PhEUNKpwjjML/pU2u2YSpHVAznuCcojoF6KIsrS1Ci7GtVaQ==", 138 | "dev": true, 139 | "requires": { 140 | "request": "^2.88.0" 141 | } 142 | }, 143 | "es5-ext": { 144 | "version": "0.10.53", 145 | "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", 146 | "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", 147 | "requires": { 148 | "es6-iterator": "~2.0.3", 149 | "es6-symbol": "~3.1.3", 150 | "next-tick": "~1.0.0" 151 | } 152 | }, 153 | "es6-iterator": { 154 | "version": "2.0.3", 155 | "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", 156 | "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", 157 | "requires": { 158 | "d": "1", 159 | "es5-ext": "^0.10.35", 160 | "es6-symbol": "^3.1.1" 161 | } 162 | }, 163 | "es6-symbol": { 164 | "version": "3.1.3", 165 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", 166 | "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", 167 | "requires": { 168 | "d": "^1.0.1", 169 | "ext": "^1.1.2" 170 | } 171 | }, 172 | "es6-weak-map": { 173 | "version": "2.0.3", 174 | "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", 175 | "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", 176 | "requires": { 177 | "d": "1", 178 | "es5-ext": "^0.10.46", 179 | "es6-iterator": "^2.0.3", 180 | "es6-symbol": "^3.1.1" 181 | } 182 | }, 183 | "event-emitter": { 184 | "version": "0.3.5", 185 | "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", 186 | "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", 187 | "requires": { 188 | "d": "1", 189 | "es5-ext": "~0.10.14" 190 | } 191 | }, 192 | "ext": { 193 | "version": "1.4.0", 194 | "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", 195 | "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", 196 | "requires": { 197 | "type": "^2.0.0" 198 | }, 199 | "dependencies": { 200 | "type": { 201 | "version": "2.0.0", 202 | "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", 203 | "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==" 204 | } 205 | } 206 | }, 207 | "extend": { 208 | "version": "3.0.2", 209 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 210 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", 211 | "dev": true 212 | }, 213 | "extsprintf": { 214 | "version": "1.3.0", 215 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 216 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", 217 | "dev": true 218 | }, 219 | "fast-deep-equal": { 220 | "version": "3.1.1", 221 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", 222 | "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", 223 | "dev": true 224 | }, 225 | "fast-json-stable-stringify": { 226 | "version": "2.1.0", 227 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 228 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 229 | "dev": true 230 | }, 231 | "forever-agent": { 232 | "version": "0.6.1", 233 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 234 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", 235 | "dev": true 236 | }, 237 | "form-data": { 238 | "version": "2.3.3", 239 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 240 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 241 | "dev": true, 242 | "requires": { 243 | "asynckit": "^0.4.0", 244 | "combined-stream": "^1.0.6", 245 | "mime-types": "^2.1.12" 246 | } 247 | }, 248 | "getpass": { 249 | "version": "0.1.7", 250 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 251 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 252 | "dev": true, 253 | "requires": { 254 | "assert-plus": "^1.0.0" 255 | } 256 | }, 257 | "har-schema": { 258 | "version": "2.0.0", 259 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 260 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", 261 | "dev": true 262 | }, 263 | "har-validator": { 264 | "version": "5.1.3", 265 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", 266 | "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", 267 | "dev": true, 268 | "requires": { 269 | "ajv": "^6.5.5", 270 | "har-schema": "^2.0.0" 271 | } 272 | }, 273 | "http-signature": { 274 | "version": "1.2.0", 275 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 276 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 277 | "dev": true, 278 | "requires": { 279 | "assert-plus": "^1.0.0", 280 | "jsprim": "^1.2.2", 281 | "sshpk": "^1.7.0" 282 | } 283 | }, 284 | "is-promise": { 285 | "version": "2.1.0", 286 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 287 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" 288 | }, 289 | "is-typedarray": { 290 | "version": "1.0.0", 291 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 292 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 293 | "dev": true 294 | }, 295 | "isstream": { 296 | "version": "0.1.2", 297 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 298 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", 299 | "dev": true 300 | }, 301 | "jsbn": { 302 | "version": "0.1.1", 303 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 304 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", 305 | "dev": true 306 | }, 307 | "json-schema": { 308 | "version": "0.2.3", 309 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 310 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", 311 | "dev": true 312 | }, 313 | "json-schema-traverse": { 314 | "version": "0.4.1", 315 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 316 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 317 | "dev": true 318 | }, 319 | "json-stringify-safe": { 320 | "version": "5.0.1", 321 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 322 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 323 | "dev": true 324 | }, 325 | "jsprim": { 326 | "version": "1.4.1", 327 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 328 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 329 | "dev": true, 330 | "requires": { 331 | "assert-plus": "1.0.0", 332 | "extsprintf": "1.3.0", 333 | "json-schema": "0.2.3", 334 | "verror": "1.10.0" 335 | } 336 | }, 337 | "lru-queue": { 338 | "version": "0.1.0", 339 | "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", 340 | "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", 341 | "requires": { 342 | "es5-ext": "~0.10.2" 343 | } 344 | }, 345 | "memoizee": { 346 | "version": "0.4.14", 347 | "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", 348 | "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", 349 | "requires": { 350 | "d": "1", 351 | "es5-ext": "^0.10.45", 352 | "es6-weak-map": "^2.0.2", 353 | "event-emitter": "^0.3.5", 354 | "is-promise": "^2.1", 355 | "lru-queue": "0.1", 356 | "next-tick": "1", 357 | "timers-ext": "^0.1.5" 358 | } 359 | }, 360 | "mime-db": { 361 | "version": "1.43.0", 362 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", 363 | "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", 364 | "dev": true 365 | }, 366 | "mime-types": { 367 | "version": "2.1.26", 368 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", 369 | "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", 370 | "dev": true, 371 | "requires": { 372 | "mime-db": "1.43.0" 373 | } 374 | }, 375 | "next-tick": { 376 | "version": "1.0.0", 377 | "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", 378 | "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" 379 | }, 380 | "oauth-sign": { 381 | "version": "0.9.0", 382 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 383 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", 384 | "dev": true 385 | }, 386 | "performance-now": { 387 | "version": "2.1.0", 388 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 389 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", 390 | "dev": true 391 | }, 392 | "psl": { 393 | "version": "1.7.0", 394 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", 395 | "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==", 396 | "dev": true 397 | }, 398 | "punycode": { 399 | "version": "2.1.1", 400 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 401 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 402 | "dev": true 403 | }, 404 | "qs": { 405 | "version": "6.5.2", 406 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 407 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", 408 | "dev": true 409 | }, 410 | "request": { 411 | "version": "2.88.2", 412 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", 413 | "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", 414 | "dev": true, 415 | "requires": { 416 | "aws-sign2": "~0.7.0", 417 | "aws4": "^1.8.0", 418 | "caseless": "~0.12.0", 419 | "combined-stream": "~1.0.6", 420 | "extend": "~3.0.2", 421 | "forever-agent": "~0.6.1", 422 | "form-data": "~2.3.2", 423 | "har-validator": "~5.1.3", 424 | "http-signature": "~1.2.0", 425 | "is-typedarray": "~1.0.0", 426 | "isstream": "~0.1.2", 427 | "json-stringify-safe": "~5.0.1", 428 | "mime-types": "~2.1.19", 429 | "oauth-sign": "~0.9.0", 430 | "performance-now": "^2.1.0", 431 | "qs": "~6.5.2", 432 | "safe-buffer": "^5.1.2", 433 | "tough-cookie": "~2.5.0", 434 | "tunnel-agent": "^0.6.0", 435 | "uuid": "^3.3.2" 436 | } 437 | }, 438 | "safe-buffer": { 439 | "version": "5.2.0", 440 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", 441 | "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", 442 | "dev": true 443 | }, 444 | "safer-buffer": { 445 | "version": "2.1.2", 446 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 447 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 448 | "dev": true 449 | }, 450 | "sshpk": { 451 | "version": "1.16.1", 452 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", 453 | "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", 454 | "dev": true, 455 | "requires": { 456 | "asn1": "~0.2.3", 457 | "assert-plus": "^1.0.0", 458 | "bcrypt-pbkdf": "^1.0.0", 459 | "dashdash": "^1.12.0", 460 | "ecc-jsbn": "~0.1.1", 461 | "getpass": "^0.1.1", 462 | "jsbn": "~0.1.0", 463 | "safer-buffer": "^2.0.2", 464 | "tweetnacl": "~0.14.0" 465 | } 466 | }, 467 | "text-table": { 468 | "version": "0.2.0", 469 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 470 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" 471 | }, 472 | "timers-ext": { 473 | "version": "0.1.7", 474 | "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", 475 | "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", 476 | "requires": { 477 | "es5-ext": "~0.10.46", 478 | "next-tick": "1" 479 | } 480 | }, 481 | "tough-cookie": { 482 | "version": "2.5.0", 483 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", 484 | "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", 485 | "dev": true, 486 | "requires": { 487 | "psl": "^1.1.28", 488 | "punycode": "^2.1.1" 489 | } 490 | }, 491 | "tunnel-agent": { 492 | "version": "0.6.0", 493 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 494 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 495 | "dev": true, 496 | "requires": { 497 | "safe-buffer": "^5.0.1" 498 | } 499 | }, 500 | "tweetnacl": { 501 | "version": "0.14.5", 502 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 503 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", 504 | "dev": true 505 | }, 506 | "type": { 507 | "version": "1.2.0", 508 | "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", 509 | "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" 510 | }, 511 | "uri-js": { 512 | "version": "4.2.2", 513 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 514 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 515 | "dev": true, 516 | "requires": { 517 | "punycode": "^2.1.0" 518 | } 519 | }, 520 | "uuid": { 521 | "version": "3.4.0", 522 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 523 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", 524 | "dev": true 525 | }, 526 | "verror": { 527 | "version": "1.10.0", 528 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 529 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 530 | "dev": true, 531 | "requires": { 532 | "assert-plus": "^1.0.0", 533 | "core-util-is": "1.0.2", 534 | "extsprintf": "^1.2.0" 535 | } 536 | } 537 | } 538 | } 539 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "elm-outdated", 3 | "version": "1.1.1", 4 | "description": "Keep your Elm dependencies up-to-date", 5 | "repository": "gyzerok/elm-outdated", 6 | "main": "src/index.js", 7 | "bin": { 8 | "elm-outdated": "bin/elm-outdated" 9 | }, 10 | "scripts": { 11 | "prepublish": "npm run build", 12 | "build": "npx elm make src/Main.elm --output=src/elm.js --optimize && npx elm make src/Old.elm --output=src/old.js --optimize", 13 | "test": "echo \"Error: no test specified\" && exit 1" 14 | }, 15 | "keywords": [ 16 | "elm", 17 | "elm-package", 18 | "outdated" 19 | ], 20 | "author": "Fedor Nezhivoi", 21 | "license": "BSD-3-Clause", 22 | "dependencies": { 23 | "cli-color": "^1.4.0", 24 | "text-table": "^0.2.0" 25 | }, 26 | "devDependencies": { 27 | "elm": "^0.19.1-3" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Main.elm: -------------------------------------------------------------------------------- 1 | port module Main exposing (..) 2 | 3 | import Dict 4 | import Elm.Package 5 | import Elm.Project 6 | import Elm.Version 7 | import Json.Decode as Decode 8 | import Platform 9 | 10 | 11 | ---- MODEL 12 | 13 | 14 | type alias Model = 15 | () 16 | 17 | 18 | type alias Registry = 19 | Dict.Dict String (List Elm.Version.Version) 20 | 21 | 22 | type alias Report = 23 | { current : String 24 | , wanted : String 25 | , latest : String 26 | } 27 | 28 | 29 | init : Decode.Value -> ( Model, Cmd msg ) 30 | init flags = 31 | case decodeFlags flags of 32 | Err e -> 33 | ( (), sendError e ) 34 | 35 | Ok ( deps, registry ) -> 36 | ( (), sendReports <| collectReports deps registry ) 37 | 38 | 39 | decodeFlags : Decode.Value -> Result String ( Elm.Project.Deps Elm.Version.Version, Registry ) 40 | decodeFlags flags = 41 | let 42 | decoder = 43 | Decode.map2 (\a b -> ( a, b )) 44 | (Decode.field "elmJson" Elm.Project.decoder) 45 | (Decode.field "registry" <| Decode.dict (Decode.list Elm.Version.decoder)) 46 | in 47 | case Decode.decodeValue decoder flags of 48 | Err e -> 49 | Err "Your elm.json is corrupted" 50 | 51 | Ok ( Elm.Project.Package _, _ ) -> 52 | Err "TODO: packages not supported" 53 | 54 | Ok ( Elm.Project.Application { depsDirect, testDepsDirect }, registry ) -> 55 | Ok ( depsDirect ++ testDepsDirect, registry ) 56 | 57 | 58 | collectReports : Elm.Project.Deps Elm.Version.Version -> Registry -> List ( String, Report ) 59 | collectReports deps registry = 60 | deps 61 | |> List.foldl 62 | (\( name, version ) -> 63 | let 64 | availableVersions = 65 | registry 66 | |> Dict.get (Elm.Package.toString name) 67 | |> Maybe.withDefault [ version ] 68 | in 69 | Dict.insert (Elm.Package.toString name) 70 | { current = Elm.Version.toString version 71 | , wanted = 72 | availableVersions 73 | |> wantedVersion version 74 | |> Elm.Version.toString 75 | , latest = 76 | availableVersions 77 | |> List.reverse 78 | |> List.head 79 | |> Maybe.withDefault version 80 | |> Elm.Version.toString 81 | } 82 | ) 83 | Dict.empty 84 | |> Dict.filter 85 | (\_ report -> 86 | report.current /= report.latest 87 | ) 88 | |> Dict.toList 89 | 90 | 91 | wantedVersion : Elm.Version.Version -> List Elm.Version.Version -> Elm.Version.Version 92 | wantedVersion version versions = 93 | let 94 | ( major, _, _ ) = 95 | Elm.Version.toTuple version 96 | in 97 | versions 98 | |> List.filter 99 | (\checkedVersion -> 100 | let 101 | ( checkedMajor, _, _ ) = 102 | Elm.Version.toTuple checkedVersion 103 | in 104 | major == checkedMajor 105 | ) 106 | |> List.reverse 107 | |> List.head 108 | |> Maybe.withDefault version 109 | 110 | 111 | 112 | ---- PROGRAM 113 | 114 | 115 | main : Program Decode.Value Model msg 116 | main = 117 | Platform.worker 118 | { init = init 119 | , update = \msg model -> ( model, Cmd.none ) 120 | , subscriptions = always Sub.none 121 | } 122 | 123 | 124 | port sendReports : List ( String, Report ) -> Cmd msg 125 | 126 | 127 | port sendError : String -> Cmd msg 128 | -------------------------------------------------------------------------------- /src/Old.elm: -------------------------------------------------------------------------------- 1 | port module Old exposing (..) 2 | 3 | import Dict 4 | import Json.Decode as Decode 5 | import Platform 6 | 7 | 8 | ---- MODEL ---- 9 | 10 | 11 | type alias Model = 12 | () 13 | 14 | 15 | type alias Registry = 16 | Dict.Dict String (List Version) 17 | 18 | 19 | type alias Package = 20 | { name : String 21 | , version : Version 22 | } 23 | 24 | 25 | type alias Version = 26 | { major : String 27 | , minor : String 28 | , patch : String 29 | } 30 | 31 | 32 | type alias Report = 33 | { current : String 34 | , wanted : String 35 | , latest : String 36 | } 37 | 38 | 39 | init : Decode.Value -> ( Model, Cmd msg ) 40 | init flags = 41 | case decodeFlags flags of 42 | Err e -> 43 | ( (), sendError e ) 44 | 45 | Ok ( deps, registry ) -> 46 | let 47 | reports = 48 | deps 49 | |> List.foldl 50 | (\dep -> 51 | let 52 | maybeVersions = 53 | Dict.get dep.name registry 54 | 55 | report = 56 | Maybe.map3 Report 57 | (Just dep.version |> Maybe.map versionToString) 58 | (maybeVersions |> Maybe.andThen (wantedVersion dep.version) |> Maybe.map versionToString) 59 | (maybeVersions |> Maybe.andThen List.head |> Maybe.map versionToString) 60 | in 61 | Dict.insert dep.name report 62 | ) 63 | Dict.empty 64 | |> Dict.filter 65 | (\name maybeReport -> 66 | case maybeReport of 67 | Nothing -> 68 | True 69 | 70 | Just report -> 71 | report.current /= report.latest 72 | ) 73 | in 74 | ( (), sendReports <| Dict.toList reports ) 75 | 76 | 77 | decodeFlags : Decode.Value -> Result String ( List Package, Registry ) 78 | decodeFlags flags = 79 | let 80 | rangeDecoder = 81 | Decode.string 82 | |> Decode.andThen 83 | (\str -> 84 | case List.head <| String.split " " str of 85 | Nothing -> 86 | Decode.fail "Incorrent dependency range format" 87 | 88 | Just versionStr -> 89 | case versionFromString versionStr of 90 | Nothing -> 91 | Decode.fail "Incorrect version format" 92 | 93 | Just version -> 94 | Decode.succeed version 95 | ) 96 | 97 | depsDecoder = 98 | Decode.keyValuePairs rangeDecoder 99 | |> Decode.at [ "dependencies" ] 100 | |> Decode.map (List.map (uncurry Package)) 101 | 102 | decoder = 103 | Decode.map2 Tuple.pair 104 | (Decode.field "elmPackageJson" depsDecoder) 105 | (Decode.field "registry" registryDecoder) 106 | in 107 | case Decode.decodeValue decoder flags of 108 | Err _ -> 109 | Err "Your elm-package.json is corrupted." 110 | 111 | Ok decoded -> 112 | Ok decoded 113 | 114 | 115 | versionFromString : String -> Maybe Version 116 | versionFromString str = 117 | case String.split "." str of 118 | major :: minor :: patch :: [] -> 119 | Just <| Version major minor patch 120 | 121 | _ -> 122 | Nothing 123 | 124 | 125 | versionToString : Version -> String 126 | versionToString { major, minor, patch } = 127 | major ++ "." ++ minor ++ "." ++ patch 128 | 129 | 130 | versionDecoder : Decode.Decoder Version 131 | versionDecoder = 132 | Decode.string 133 | |> Decode.andThen 134 | (\str -> 135 | case versionFromString str of 136 | Nothing -> 137 | Decode.fail "Failed to decode version" 138 | 139 | Just version -> 140 | Decode.succeed version 141 | ) 142 | 143 | 144 | registryDecoder : Decode.Decoder Registry 145 | registryDecoder = 146 | Decode.map Dict.fromList <| 147 | Decode.list <| 148 | Decode.map2 Tuple.pair 149 | (Decode.field "name" Decode.string) 150 | (Decode.field "versions" <| Decode.list versionDecoder) 151 | 152 | 153 | wantedVersion : Version -> List Version -> Maybe Version 154 | wantedVersion version versions = 155 | let 156 | safeVersions = 157 | versions 158 | |> List.filter (\{ major } -> major == version.major) 159 | in 160 | case safeVersions of 161 | [] -> 162 | Nothing 163 | 164 | nonEmptyVersions -> 165 | List.head nonEmptyVersions 166 | 167 | 168 | uncurry : (a -> b -> c) -> ( a, b ) -> c 169 | uncurry f ( a, b ) = 170 | f a b 171 | 172 | 173 | 174 | ---- PROGRAM ---- 175 | 176 | 177 | main : Program Decode.Value Model msg 178 | main = 179 | Platform.worker 180 | { init = init 181 | , update = \msg model -> ( model, Cmd.none ) 182 | , subscriptions = always Sub.none 183 | } 184 | 185 | 186 | port sendReports : List ( String, Maybe Report ) -> Cmd msg 187 | 188 | 189 | port sendError : String -> Cmd msg 190 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const https = require("https"); 3 | const http = require("http"); 4 | const table = require("text-table"); 5 | const clc = require("cli-color"); 6 | 7 | const Main = require("./elm.js").Elm.Main; 8 | const Old = require("./old.js").Elm.Old; 9 | 10 | let elmJson; 11 | let elmPackageJson; 12 | 13 | try { 14 | elmJson = fs.readFileSync("elm.json", { encoding: "utf-8" }); 15 | } catch (e) { 16 | try { 17 | elmPackageJson = fs.readFileSync("elm-package.json", { encoding: "utf-8" }); 18 | } catch (e) {} 19 | } 20 | 21 | if (!elmJson && !elmPackageJson) { 22 | console.error( 23 | "You should run elm-outdated in the directory where your elm.json is located." 24 | ); 25 | console.error( 26 | "If you are using Elm 0.18 then it should be directory with elm-package.json." 27 | ); 28 | process.exit(1); 29 | } else if (elmJson) { 30 | fetch("https://package.elm-lang.org/all-packages") 31 | .then(data => { 32 | let parsedJson; 33 | 34 | try { 35 | parsedJson = JSON.parse(elmJson); 36 | } catch (e) { 37 | console.log("Cannot parse you elm.json. Is it corrupted?"); 38 | process.exit(1); 39 | } 40 | 41 | const app = Main.init({ 42 | flags: { 43 | elmJson: parsedJson, 44 | registry: data 45 | } 46 | }); 47 | 48 | setup(app); 49 | }) 50 | .catch(err => console.error(err)); 51 | } else if (elmPackageJson) { 52 | fetch("http://package.elm-lang.org/all-packages?elm-package-version=0.18") 53 | .then(data => { 54 | let parsedJson; 55 | 56 | try { 57 | parsedJson = JSON.parse(elmPackageJson); 58 | } catch (e) { 59 | console.log("Cannot parse you elm-package.json. Is it corrupted?"); 60 | process.exit(1); 61 | } 62 | 63 | const app = Old.init({ 64 | flags: { 65 | elmPackageJson: parsedJson, 66 | registry: data 67 | } 68 | }); 69 | 70 | setup(app); 71 | }) 72 | .catch(err => console.error(err)); 73 | } else { 74 | console.error("Something wrong happened, please report."); 75 | process.exit(1); 76 | } 77 | 78 | function fetch(url) { 79 | return new Promise((resolve, reject) => { 80 | get = url.indexOf("https:") === 0 ? https.get : http.get; 81 | get(url, res => { 82 | res.setEncoding("utf8"); 83 | let body = ""; 84 | res.on("data", data => { 85 | body += data; 86 | }); 87 | res.on("end", () => { 88 | try { 89 | resolve(JSON.parse(body)); 90 | } catch (e) { 91 | reject(e); 92 | } 93 | }); 94 | res.on("error", reject); 95 | }); 96 | }); 97 | } 98 | 99 | function setup(app) { 100 | app.ports.sendError.subscribe(error => { 101 | console.log(error); 102 | process.exit(1); 103 | }); 104 | 105 | app.ports.sendReports.subscribe(reports => { 106 | if (reports.length === 0) { 107 | console.log("Everything is up to date!"); 108 | } else { 109 | console.log( 110 | table( 111 | [ 112 | ["Package", "Current", "Wanted", "Latest"].map(h => 113 | clc.underline(h) 114 | ), 115 | ...reports.map(([name, report]) => { 116 | return !report 117 | ? [name, "custom", "custom", "custom"] 118 | : [ 119 | name, 120 | report.current, 121 | clc.green(report.wanted), 122 | clc.magenta(report.latest) 123 | ]; 124 | }) 125 | ], 126 | { 127 | align: ["l", "r", "r", "r"], 128 | stringLength: clc.getStrippedLength 129 | } 130 | ) 131 | ); 132 | } 133 | }); 134 | } 135 | --------------------------------------------------------------------------------