├── .circleci └── config.yml ├── .editorconfig ├── .gitignore ├── BACKEND_INSTRUCTIONS.md ├── Dockerfile ├── FRONTEND_INSTRUCTIONS.md ├── MOBILE_INSTRUCTIONS.md ├── logo.png ├── package-lock.json ├── package.json ├── readme.md ├── requirements.txt ├── serverless.yml └── src ├── api ├── articles │ ├── __init__.py │ ├── comments │ │ ├── __init__.py │ │ ├── handler.py │ │ └── tests.py │ ├── favorite │ │ ├── __init__.py │ │ ├── handler.py │ │ └── tests.py │ ├── handler.py │ └── tests.py ├── profiles │ ├── __init__.py │ ├── handler.py │ └── tests.py ├── tags │ ├── __init__.py │ ├── handler.py │ └── tests.py └── users │ ├── __init__.py │ ├── handler.py │ └── tests.py └── models ├── __init__.py ├── alembic.ini ├── articles.py ├── associations.py ├── comments.py ├── database.py ├── migrations ├── README ├── env.py ├── script.py.mako └── versions │ ├── 060c71f40c75_create_user_table.py │ ├── 187ee66c9910_create_article_comment_relationship.py │ ├── 586ff0a55152_create_profile_table.py │ ├── 6cd1ecc66c36_create_profile_profile_relationship.py │ ├── 738a04ab8395_create_tag_table.py │ ├── 98b2c43d2dbe_create_comment_table.py │ ├── b3711b2a949c_create_article_tag_relationship.py │ ├── ce5457ef45d6_create_profile_article_relationship.py │ └── f5ef6affc65c_create_article_table.py ├── profiles.py ├── tags.py └── users.py /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | jobs: 4 | build: 5 | docker: 6 | - image: choib24/serverless-python-deployment-environment:latest 7 | 8 | working_directory: ~/repo 9 | 10 | steps: 11 | - checkout 12 | - run: 13 | name: install python requirements 14 | command: pip install -r requirements.txt 15 | - run: 16 | name: install node dependencies 17 | command: npm install 18 | 19 | test: 20 | docker: 21 | - image: choib24/serverless-python-deployment-environment:latest 22 | steps: 23 | - checkout 24 | - run: 25 | name: run tests 26 | command: npm test 27 | 28 | deploy-dev: 29 | docker: 30 | - image: choib24/serverless-python-deployment-environment:latest 31 | steps: 32 | - checkout 33 | - run: 34 | name: deploy to development stage 35 | command: npx sls deploy --stage dev --verbose 36 | 37 | deploy-prod: 38 | docker: 39 | - image: choib24/serverless-python-deployment-environment:latest 40 | steps: 41 | - checkout 42 | - run: 43 | name: deploy to production stage 44 | command: npx sls deploy --stage prod --verbose 45 | 46 | workflows: 47 | version: 2 48 | build-test-deployment: 49 | jobs: 50 | - build 51 | - test: 52 | requires: 53 | - build 54 | #- deploy-dev: 55 | # requires: 56 | # - build 57 | # - test 58 | # filters: 59 | # branches: 60 | # only: 61 | # - develop 62 | # - master 63 | #- hold: 64 | # type: approval 65 | # requires: 66 | # - build 67 | # - test 68 | # - deploy-dev 69 | 70 | #- deploy-prod: 71 | # requires: 72 | # - build 73 | # - test 74 | # - deploy-dev 75 | # - hold 76 | # filters: 77 | # branches: 78 | # only: master 79 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset=utf-8 3 | end_of_line=lf 4 | insert_final_newline=true 5 | indent_style=space 6 | indent_size=4 7 | 8 | [{*.sht,*.html,*.shtm,*.shtml,*.ng,*.htm}] 9 | indent_style=space 10 | indent_size=2 11 | 12 | [{.babelrc,.stylelintrc,.eslintrc,jest.config,*.bowerrc,*.jsb3,*.jsb2,*.json}] 13 | indent_style=space 14 | indent_size=2 15 | 16 | [{*.applejs,*.js}] 17 | indent_style=space 18 | indent_size=2 19 | 20 | [{tsconfig.app.json,tsconfig.spec.json,tsconfig.json,tsconfig.e2e.json}] 21 | indent_style=space 22 | indent_size=2 23 | 24 | [{*.yml,*.yaml}] 25 | indent_style=space 26 | indent_size=2 27 | 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # python 4 | __pycache__/ 5 | venv/ 6 | 7 | # dependencies 8 | /node_modules 9 | /bower_components 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | *.launch 16 | .settings/ 17 | 18 | #System Files 19 | .DS_Store 20 | Thumbs.db 21 | 22 | # serverless builds 23 | .serverless/ 24 | -------------------------------------------------------------------------------- /BACKEND_INSTRUCTIONS.md: -------------------------------------------------------------------------------- 1 | > *Note: Delete this file before publishing your app!* 2 | 3 | # [Backend API spec](https://github.com/gothinkster/realworld/tree/master/api) 4 | 5 | For your convenience, we have a [Postman collection](https://github.com/gothinkster/realworld/blob/master/api/Conduit.postman_collection.json) that you can use to test your API endpoints as you build your app. 6 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM lambci/lambda-base:build 2 | 3 | ENV PATH=/var/lang/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \ 4 | LD_LIBRARY_PATH=/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib \ 5 | AWS_EXECUTION_ENV=AWS_Lambda_python3.6 \ 6 | PYTHONPATH=/var/runtime \ 7 | NODE_PATH=/var/runtime:/var/task:/var/runtime/node_modules \ 8 | npm_config_unsafe-perm=true \ 9 | PKG_CONFIG_PATH=/var/lang/lib/pkgconfig:/usr/lib64/pkgconfig:/usr/share/pkgconfig 10 | 11 | RUN rm -rf /var/runtime /var/lang 12 | 13 | RUN curl https://lambci.s3.amazonaws.com/fs/python3.6.tgz | tar -xz -C / && \ 14 | sed -i '/^prefix=/c\prefix=/var/lang' /var/lang/lib/pkgconfig/python-3.6.pc && \ 15 | curl https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tar.xz | tar -xJ && \ 16 | cd Python-3.6.1 && \ 17 | LIBS="$LIBS -lutil -lrt" ./configure --prefix=/var/lang && \ 18 | make -j$(getconf _NPROCESSORS_ONLN) libinstall inclinstall && \ 19 | cd .. && \ 20 | rm -rf Python-3.6.1 && \ 21 | pip3 install -U pip awscli virtualenv --no-cache-dir 22 | 23 | RUN curl https://lambci.s3.amazonaws.com/fs/nodejs8.10.tgz | tar -zx -C / 24 | 25 | ADD . /realworld 26 | 27 | WORKDIR /realworld 28 | 29 | RUN npm install -g npx 30 | 31 | RUN pip3 install -r requirements.txt 32 | RUN npm install 33 | -------------------------------------------------------------------------------- /FRONTEND_INSTRUCTIONS.md: -------------------------------------------------------------------------------- 1 | > *Note: Delete this file before publishing your app!* 2 | 3 | ### Using the hosted API 4 | 5 | Simply point your [API requests](https://github.com/gothinkster/realworld/tree/master/api) to `https://conduit.productionready.io/api` and you're good to go! 6 | 7 | ### Routing Guidelines 8 | 9 | - Home page (URL: /#/ ) 10 | - List of tags 11 | - List of articles pulled from either Feed, Global, or by Tag 12 | - Pagination for list of articles 13 | - Sign in/Sign up pages (URL: /#/login, /#/register ) 14 | - Uses JWT (store the token in localStorage) 15 | - Authentication can be easily switched to session/cookie based 16 | - Settings page (URL: /#/settings ) 17 | - Editor page to create/edit articles (URL: /#/editor, /#/editor/article-slug-here ) 18 | - Article page (URL: /#/article/article-slug-here ) 19 | - Delete article button (only shown to article's author) 20 | - Render markdown from server client side 21 | - Comments section at bottom of page 22 | - Delete comment button (only shown to comment's author) 23 | - Profile page (URL: /#/profile/:username, /#/profile/:username/favorites ) 24 | - Show basic user info 25 | - List of articles populated from author's created articles or author's favorited articles 26 | 27 | # Styles 28 | 29 | Instead of having the Bootstrap theme included locally, we recommend loading the precompiled theme from our CDN (our [header template](#header) does this by default): 30 | 31 | ```html 32 | 33 | ``` 34 | 35 | Alternatively, if you want to make modifications to the theme, check out the [theme's repo](https://github.com/gothinkster/conduit-bootstrap-template). 36 | 37 | 38 | # Templates 39 | 40 | - [Layout](#layout) 41 | - [Header](#header) 42 | - [Footer](#footer) 43 | - [Pages](#pages) 44 | - [Home](#home) 45 | - [Login/Register](#loginregister) 46 | - [Profile](#profile) 47 | - [Settings](#settings) 48 | - [Create/Edit Article](#createedit-article) 49 | - [Article](#article) 50 | 51 | 52 | ## Layout 53 | 54 | 55 | ### Header 56 | 57 | ```html 58 | 59 | 60 | 61 | 62 | Conduit 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 95 | 96 | 97 | ``` 98 | 99 | ### Footer 100 | ```html 101 | 109 | 110 | 111 | 112 | ``` 113 | 114 | ## Pages 115 | 116 | ### Home 117 | ```html 118 |
119 | 120 | 126 | 127 |
128 |
129 | 130 |
131 |
132 | 140 |
141 | 142 |
143 | 153 | 154 |

How to build webapps that scale

155 |

This is the description for the post.

156 | Read more... 157 |
158 |
159 | 160 |
161 | 171 | 172 |

The song you won't ever stop singing. No matter how hard you try.

173 |

This is the description for the post.

174 | Read more... 175 |
176 |
177 | 178 |
179 | 180 |
181 | 195 |
196 | 197 |
198 |
199 | 200 |
201 | ``` 202 | 203 | ### Login/Register 204 | 205 | ```html 206 |
207 |
208 |
209 | 210 |
211 |

Sign up

212 |

213 | Have an account? 214 |

215 | 216 |
    217 |
  • That email is already taken
  • 218 |
219 | 220 |
221 |
222 | 223 |
224 |
225 | 226 |
227 |
228 | 229 |
230 | 233 |
234 |
235 | 236 |
237 |
238 |
239 | ``` 240 | 241 | ### Profile 242 | 243 | ```html 244 |
245 | 246 |
247 |
248 |
249 | 250 |
251 | 252 |

Eric Simons

253 |

254 | Cofounder @GoThinkster, lived in Aol's HQ for a few months, kinda looks like Peeta from the Hunger Games 255 |

256 | 261 |
262 | 263 |
264 |
265 |
266 | 267 |
268 |
269 | 270 |
271 |
272 | 280 |
281 | 282 |
283 | 293 | 294 |

How to build webapps that scale

295 |

This is the description for the post.

296 | Read more... 297 |
298 |
299 | 300 |
301 | 311 | 312 |

The song you won't ever stop singing. No matter how hard you try.

313 |

This is the description for the post.

314 | Read more... 315 |
    316 |
  • Music
  • 317 |
  • Song
  • 318 |
319 |
320 |
321 | 322 | 323 |
324 | 325 |
326 |
327 | 328 |
329 | ``` 330 | 331 | ### Settings 332 | 333 | ```html 334 |
335 |
336 |
337 | 338 |
339 |

Your Settings

340 | 341 |
342 |
343 |
344 | 345 |
346 |
347 | 348 |
349 |
350 | 351 |
352 |
353 | 354 |
355 |
356 | 357 |
358 | 361 |
362 |
363 |
364 | 365 |
366 |
367 |
368 | ``` 369 | 370 | ### Create/Edit Article 371 | 372 | ```html 373 |
374 |
375 |
376 | 377 |
378 |
379 |
380 |
381 | 382 |
383 |
384 | 385 |
386 |
387 | 388 |
389 |
390 |
391 |
392 | 395 |
396 |
397 |
398 | 399 |
400 |
401 |
402 | 403 | 404 | ``` 405 | 406 | ### Article 407 | 408 | ```html 409 |
410 | 411 | 437 | 438 |
439 | 440 |
441 |
442 |

443 | Web development technologies have evolved at an incredible clip over the past few years. 444 |

445 |

Introducing RealWorld.

446 |

It's a great solution for learning how other frameworks work.

447 |
448 |
449 | 450 |
451 | 452 |
453 | 472 |
473 | 474 |
475 | 476 |
477 | 478 |
479 |
480 | 481 |
482 | 488 |
489 | 490 |
491 |
492 |

With supporting text below as a natural lead-in to additional content.

493 |
494 | 502 |
503 | 504 |
505 |
506 |

With supporting text below as a natural lead-in to additional content.

507 |
508 | 520 |
521 | 522 |
523 | 524 |
525 | 526 |
527 | 528 |
529 | ``` 530 | -------------------------------------------------------------------------------- /MOBILE_INSTRUCTIONS.md: -------------------------------------------------------------------------------- 1 | > *Note: Delete this file before publishing your app!* 2 | 3 | # [Mobile Icons (iOS/Android)](https://github.com/gothinkster/realworld/tree/master/spec/mobile_icons) 4 | 5 | ### Using the hosted API 6 | 7 | Simply point your [API requests](https://github.com/gothinkster/realworld/tree/master/api) to `https://conduit.productionready.io/api` and you're good to go! 8 | 9 | ### Styles/Templates 10 | 11 | Unfortunately, there isn't a common way for us to reuse & share styles/templates for cross-platform mobile apps. 12 | 13 | Instead, we recommend using the Medium.com [iOS](https://itunes.apple.com/us/app/medium/id828256236?mt=8) and [Android](https://play.google.com/store/apps/details?id=com.medium.reader&hl=en) apps as a "north star" regarding general UI functionality/layout, but try not to go too overboard otherwise it will unnecessarily complicate your codebase (in other words, [KISS](https://en.wikipedia.org/wiki/KISS_principle) :) 14 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyworld/realworld-serverless-python/05c51cfbd6601f46245ac0c31a5b33629e114c50/logo.png -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "realworld", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@serverless/fdk": { 8 | "version": "0.5.1", 9 | "resolved": "https://registry.npmjs.org/@serverless/fdk/-/fdk-0.5.1.tgz", 10 | "integrity": "sha512-Z/+5R0AohLwDT1E+9BTeUA7NozlyIoTh0iEt6x8x+ZZhIBK5HBMBN6v2LfkI4wmmOOyceTvsN0l8nWfGp4Oh5g==", 11 | "dev": true, 12 | "requires": { 13 | "isomorphic-fetch": "2.2.1", 14 | "ramda": "0.24.1", 15 | "url-parse": "1.4.0" 16 | } 17 | }, 18 | "@types/graphql": { 19 | "version": "0.10.2", 20 | "resolved": "https://registry.npmjs.org/@types/graphql/-/graphql-0.10.2.tgz", 21 | "integrity": "sha512-Ayw0w+kr8vYd8DToiMXjcHxXv1ljWbqX2mnLwXDxkBgog3vywGriC0JZ+npsuohKs3+E88M8OOtobo4g0X3SIA==", 22 | "dev": true, 23 | "optional": true 24 | }, 25 | "agent-base": { 26 | "version": "2.1.1", 27 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", 28 | "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", 29 | "dev": true, 30 | "requires": { 31 | "extend": "3.0.1", 32 | "semver": "5.0.3" 33 | }, 34 | "dependencies": { 35 | "semver": { 36 | "version": "5.0.3", 37 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", 38 | "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", 39 | "dev": true 40 | } 41 | } 42 | }, 43 | "ansi": { 44 | "version": "0.3.1", 45 | "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", 46 | "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=", 47 | "dev": true 48 | }, 49 | "ansi-align": { 50 | "version": "2.0.0", 51 | "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", 52 | "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", 53 | "dev": true, 54 | "requires": { 55 | "string-width": "2.1.1" 56 | }, 57 | "dependencies": { 58 | "ansi-regex": { 59 | "version": "3.0.0", 60 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 61 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 62 | "dev": true 63 | }, 64 | "is-fullwidth-code-point": { 65 | "version": "2.0.0", 66 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 67 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 68 | "dev": true 69 | }, 70 | "string-width": { 71 | "version": "2.1.1", 72 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 73 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 74 | "dev": true, 75 | "requires": { 76 | "is-fullwidth-code-point": "2.0.0", 77 | "strip-ansi": "4.0.0" 78 | } 79 | }, 80 | "strip-ansi": { 81 | "version": "4.0.0", 82 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 83 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 84 | "dev": true, 85 | "requires": { 86 | "ansi-regex": "3.0.0" 87 | } 88 | } 89 | } 90 | }, 91 | "ansi-escapes": { 92 | "version": "1.4.0", 93 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", 94 | "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", 95 | "dev": true 96 | }, 97 | "ansi-regex": { 98 | "version": "2.1.1", 99 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 100 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", 101 | "dev": true 102 | }, 103 | "ansi-styles": { 104 | "version": "3.2.1", 105 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 106 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 107 | "dev": true, 108 | "requires": { 109 | "color-convert": "1.9.1" 110 | } 111 | }, 112 | "apollo-client": { 113 | "version": "1.9.3", 114 | "resolved": "https://registry.npmjs.org/apollo-client/-/apollo-client-1.9.3.tgz", 115 | "integrity": "sha512-JABKKbqvcw8DJm3YUkEmyx1SK74i+/DesEtAtyocJi10LLmeMQYQFpg8W3BG1tZsYEQ3owEmPbsdNGTly+VOQg==", 116 | "dev": true, 117 | "requires": { 118 | "@types/graphql": "0.10.2", 119 | "apollo-link-core": "0.5.4", 120 | "graphql": "0.10.5", 121 | "graphql-anywhere": "3.1.0", 122 | "graphql-tag": "2.9.1", 123 | "redux": "3.7.2", 124 | "symbol-observable": "1.2.0", 125 | "whatwg-fetch": "2.0.4" 126 | } 127 | }, 128 | "apollo-link-core": { 129 | "version": "0.5.4", 130 | "resolved": "https://registry.npmjs.org/apollo-link-core/-/apollo-link-core-0.5.4.tgz", 131 | "integrity": "sha512-OxL0Kjizb0eS2ObldDqJEs/tFN9xI9RZuTJcaszgGy+xudoPXhIMCHMr7hGZhy0mK+U+BbBULZJw4YQU4J0ODQ==", 132 | "dev": true, 133 | "requires": { 134 | "graphql": "0.10.5", 135 | "graphql-tag": "2.9.1", 136 | "zen-observable-ts": "0.4.4" 137 | } 138 | }, 139 | "archiver": { 140 | "version": "1.3.0", 141 | "resolved": "https://registry.npmjs.org/archiver/-/archiver-1.3.0.tgz", 142 | "integrity": "sha1-TyGU1tj5nfP1MeaIHxTxXVX6ryI=", 143 | "dev": true, 144 | "requires": { 145 | "archiver-utils": "1.3.0", 146 | "async": "2.6.0", 147 | "buffer-crc32": "0.2.13", 148 | "glob": "7.1.2", 149 | "lodash": "4.17.5", 150 | "readable-stream": "2.3.6", 151 | "tar-stream": "1.5.5", 152 | "walkdir": "0.0.11", 153 | "zip-stream": "1.2.0" 154 | }, 155 | "dependencies": { 156 | "async": { 157 | "version": "2.6.0", 158 | "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", 159 | "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", 160 | "dev": true, 161 | "requires": { 162 | "lodash": "4.17.5" 163 | } 164 | } 165 | } 166 | }, 167 | "archiver-utils": { 168 | "version": "1.3.0", 169 | "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", 170 | "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", 171 | "dev": true, 172 | "requires": { 173 | "glob": "7.1.2", 174 | "graceful-fs": "4.1.11", 175 | "lazystream": "1.0.0", 176 | "lodash": "4.17.5", 177 | "normalize-path": "2.1.1", 178 | "readable-stream": "2.3.6" 179 | } 180 | }, 181 | "are-we-there-yet": { 182 | "version": "1.1.4", 183 | "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", 184 | "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", 185 | "dev": true, 186 | "requires": { 187 | "delegates": "1.0.0", 188 | "readable-stream": "2.3.6" 189 | } 190 | }, 191 | "argparse": { 192 | "version": "1.0.10", 193 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 194 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 195 | "dev": true, 196 | "requires": { 197 | "sprintf-js": "1.0.3" 198 | } 199 | }, 200 | "array-union": { 201 | "version": "1.0.2", 202 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", 203 | "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", 204 | "dev": true, 205 | "requires": { 206 | "array-uniq": "1.0.3" 207 | } 208 | }, 209 | "array-uniq": { 210 | "version": "1.0.3", 211 | "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", 212 | "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", 213 | "dev": true 214 | }, 215 | "async": { 216 | "version": "1.5.2", 217 | "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", 218 | "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", 219 | "dev": true 220 | }, 221 | "asynckit": { 222 | "version": "0.4.0", 223 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 224 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", 225 | "dev": true 226 | }, 227 | "aws-sdk": { 228 | "version": "2.225.1", 229 | "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.225.1.tgz", 230 | "integrity": "sha1-bsaZSmM38rVTsW9ldt806hrDFNg=", 231 | "dev": true, 232 | "requires": { 233 | "buffer": "4.9.1", 234 | "events": "1.1.1", 235 | "ieee754": "1.1.8", 236 | "jmespath": "0.15.0", 237 | "querystring": "0.2.0", 238 | "sax": "1.2.1", 239 | "url": "0.10.3", 240 | "uuid": "3.1.0", 241 | "xml2js": "0.4.17", 242 | "xmlbuilder": "4.2.1" 243 | }, 244 | "dependencies": { 245 | "uuid": { 246 | "version": "3.1.0", 247 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", 248 | "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", 249 | "dev": true 250 | } 251 | } 252 | }, 253 | "balanced-match": { 254 | "version": "1.0.0", 255 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 256 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 257 | "dev": true 258 | }, 259 | "base64-js": { 260 | "version": "1.3.0", 261 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", 262 | "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", 263 | "dev": true 264 | }, 265 | "bl": { 266 | "version": "1.2.2", 267 | "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", 268 | "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", 269 | "dev": true, 270 | "requires": { 271 | "readable-stream": "2.3.6", 272 | "safe-buffer": "5.1.1" 273 | } 274 | }, 275 | "bluebird": { 276 | "version": "3.5.1", 277 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", 278 | "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", 279 | "dev": true 280 | }, 281 | "boxen": { 282 | "version": "1.3.0", 283 | "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", 284 | "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", 285 | "dev": true, 286 | "requires": { 287 | "ansi-align": "2.0.0", 288 | "camelcase": "4.1.0", 289 | "chalk": "2.4.0", 290 | "cli-boxes": "1.0.0", 291 | "string-width": "2.1.1", 292 | "term-size": "1.2.0", 293 | "widest-line": "2.0.0" 294 | }, 295 | "dependencies": { 296 | "ansi-regex": { 297 | "version": "3.0.0", 298 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 299 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 300 | "dev": true 301 | }, 302 | "is-fullwidth-code-point": { 303 | "version": "2.0.0", 304 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 305 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 306 | "dev": true 307 | }, 308 | "string-width": { 309 | "version": "2.1.1", 310 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 311 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 312 | "dev": true, 313 | "requires": { 314 | "is-fullwidth-code-point": "2.0.0", 315 | "strip-ansi": "4.0.0" 316 | } 317 | }, 318 | "strip-ansi": { 319 | "version": "4.0.0", 320 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 321 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 322 | "dev": true, 323 | "requires": { 324 | "ansi-regex": "3.0.0" 325 | } 326 | } 327 | } 328 | }, 329 | "brace-expansion": { 330 | "version": "1.1.11", 331 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 332 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 333 | "dev": true, 334 | "requires": { 335 | "balanced-match": "1.0.0", 336 | "concat-map": "0.0.1" 337 | } 338 | }, 339 | "buffer": { 340 | "version": "4.9.1", 341 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", 342 | "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", 343 | "dev": true, 344 | "requires": { 345 | "base64-js": "1.3.0", 346 | "ieee754": "1.1.8", 347 | "isarray": "1.0.0" 348 | } 349 | }, 350 | "buffer-crc32": { 351 | "version": "0.2.13", 352 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 353 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", 354 | "dev": true 355 | }, 356 | "buffer-from": { 357 | "version": "1.0.0", 358 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", 359 | "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", 360 | "dev": true 361 | }, 362 | "camelcase": { 363 | "version": "4.1.0", 364 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", 365 | "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", 366 | "dev": true 367 | }, 368 | "capture-stack-trace": { 369 | "version": "1.0.0", 370 | "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", 371 | "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", 372 | "dev": true 373 | }, 374 | "caw": { 375 | "version": "2.0.1", 376 | "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", 377 | "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", 378 | "dev": true, 379 | "requires": { 380 | "get-proxy": "2.1.0", 381 | "isurl": "1.0.0", 382 | "tunnel-agent": "0.6.0", 383 | "url-to-options": "1.0.1" 384 | } 385 | }, 386 | "chalk": { 387 | "version": "2.4.0", 388 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", 389 | "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", 390 | "dev": true, 391 | "requires": { 392 | "ansi-styles": "3.2.1", 393 | "escape-string-regexp": "1.0.5", 394 | "supports-color": "5.4.0" 395 | } 396 | }, 397 | "ci-info": { 398 | "version": "1.1.3", 399 | "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.3.tgz", 400 | "integrity": "sha512-SK/846h/Rcy8q9Z9CAwGBLfCJ6EkjJWdpelWDufQpqVDYq2Wnnv8zlSO6AMQap02jvhVruKKpEtQOufo3pFhLg==", 401 | "dev": true 402 | }, 403 | "cli-boxes": { 404 | "version": "1.0.0", 405 | "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", 406 | "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", 407 | "dev": true 408 | }, 409 | "cli-cursor": { 410 | "version": "1.0.2", 411 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", 412 | "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", 413 | "dev": true, 414 | "requires": { 415 | "restore-cursor": "1.0.1" 416 | } 417 | }, 418 | "cli-width": { 419 | "version": "2.2.0", 420 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", 421 | "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", 422 | "dev": true 423 | }, 424 | "code-point-at": { 425 | "version": "1.1.0", 426 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", 427 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", 428 | "dev": true 429 | }, 430 | "color-convert": { 431 | "version": "1.9.1", 432 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", 433 | "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", 434 | "dev": true, 435 | "requires": { 436 | "color-name": "1.1.3" 437 | } 438 | }, 439 | "color-name": { 440 | "version": "1.1.3", 441 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 442 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 443 | "dev": true 444 | }, 445 | "combined-stream": { 446 | "version": "1.0.6", 447 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", 448 | "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", 449 | "dev": true, 450 | "requires": { 451 | "delayed-stream": "1.0.0" 452 | } 453 | }, 454 | "commander": { 455 | "version": "2.8.1", 456 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", 457 | "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", 458 | "dev": true, 459 | "requires": { 460 | "graceful-readlink": "1.0.1" 461 | } 462 | }, 463 | "component-emitter": { 464 | "version": "1.2.1", 465 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", 466 | "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", 467 | "dev": true 468 | }, 469 | "compress-commons": { 470 | "version": "1.2.2", 471 | "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", 472 | "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", 473 | "dev": true, 474 | "requires": { 475 | "buffer-crc32": "0.2.13", 476 | "crc32-stream": "2.0.0", 477 | "normalize-path": "2.1.1", 478 | "readable-stream": "2.3.6" 479 | } 480 | }, 481 | "concat-map": { 482 | "version": "0.0.1", 483 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 484 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 485 | "dev": true 486 | }, 487 | "concat-stream": { 488 | "version": "1.6.2", 489 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 490 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 491 | "dev": true, 492 | "requires": { 493 | "buffer-from": "1.0.0", 494 | "inherits": "2.0.3", 495 | "readable-stream": "2.3.6", 496 | "typedarray": "0.0.6" 497 | } 498 | }, 499 | "config-chain": { 500 | "version": "1.1.11", 501 | "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz", 502 | "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", 503 | "dev": true, 504 | "requires": { 505 | "ini": "1.3.5", 506 | "proto-list": "1.2.4" 507 | } 508 | }, 509 | "configstore": { 510 | "version": "3.1.2", 511 | "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", 512 | "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", 513 | "dev": true, 514 | "requires": { 515 | "dot-prop": "4.2.0", 516 | "graceful-fs": "4.1.11", 517 | "make-dir": "1.2.0", 518 | "unique-string": "1.0.0", 519 | "write-file-atomic": "2.3.0", 520 | "xdg-basedir": "3.0.0" 521 | } 522 | }, 523 | "cookie": { 524 | "version": "0.3.1", 525 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 526 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", 527 | "dev": true 528 | }, 529 | "cookiejar": { 530 | "version": "2.1.1", 531 | "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.1.tgz", 532 | "integrity": "sha1-Qa1XsbVVlR7BcUEqgZQrHoIA00o=", 533 | "dev": true 534 | }, 535 | "core-util-is": { 536 | "version": "1.0.2", 537 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 538 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 539 | "dev": true 540 | }, 541 | "crc": { 542 | "version": "3.5.0", 543 | "resolved": "https://registry.npmjs.org/crc/-/crc-3.5.0.tgz", 544 | "integrity": "sha1-mLi6fUiWZbo5efWbITgTdBAaGWQ=", 545 | "dev": true 546 | }, 547 | "crc32-stream": { 548 | "version": "2.0.0", 549 | "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", 550 | "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", 551 | "dev": true, 552 | "requires": { 553 | "crc": "3.5.0", 554 | "readable-stream": "2.3.6" 555 | } 556 | }, 557 | "create-error-class": { 558 | "version": "3.0.2", 559 | "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", 560 | "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", 561 | "dev": true, 562 | "requires": { 563 | "capture-stack-trace": "1.0.0" 564 | } 565 | }, 566 | "cross-spawn": { 567 | "version": "5.1.0", 568 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", 569 | "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", 570 | "dev": true, 571 | "requires": { 572 | "lru-cache": "4.1.2", 573 | "shebang-command": "1.2.0", 574 | "which": "1.3.0" 575 | } 576 | }, 577 | "crypto-random-string": { 578 | "version": "1.0.0", 579 | "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", 580 | "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", 581 | "dev": true 582 | }, 583 | "debug": { 584 | "version": "2.6.9", 585 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 586 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 587 | "dev": true, 588 | "requires": { 589 | "ms": "2.0.0" 590 | } 591 | }, 592 | "decompress": { 593 | "version": "4.2.0", 594 | "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz", 595 | "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=", 596 | "dev": true, 597 | "requires": { 598 | "decompress-tar": "4.1.1", 599 | "decompress-tarbz2": "4.1.1", 600 | "decompress-targz": "4.1.1", 601 | "decompress-unzip": "4.0.1", 602 | "graceful-fs": "4.1.11", 603 | "make-dir": "1.2.0", 604 | "pify": "2.3.0", 605 | "strip-dirs": "2.1.0" 606 | } 607 | }, 608 | "decompress-tar": { 609 | "version": "4.1.1", 610 | "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", 611 | "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", 612 | "dev": true, 613 | "requires": { 614 | "file-type": "5.2.0", 615 | "is-stream": "1.1.0", 616 | "tar-stream": "1.5.5" 617 | } 618 | }, 619 | "decompress-tarbz2": { 620 | "version": "4.1.1", 621 | "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", 622 | "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", 623 | "dev": true, 624 | "requires": { 625 | "decompress-tar": "4.1.1", 626 | "file-type": "6.2.0", 627 | "is-stream": "1.1.0", 628 | "seek-bzip": "1.0.5", 629 | "unbzip2-stream": "1.2.5" 630 | }, 631 | "dependencies": { 632 | "file-type": { 633 | "version": "6.2.0", 634 | "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", 635 | "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", 636 | "dev": true 637 | } 638 | } 639 | }, 640 | "decompress-targz": { 641 | "version": "4.1.1", 642 | "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", 643 | "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", 644 | "dev": true, 645 | "requires": { 646 | "decompress-tar": "4.1.1", 647 | "file-type": "5.2.0", 648 | "is-stream": "1.1.0" 649 | } 650 | }, 651 | "decompress-unzip": { 652 | "version": "4.0.1", 653 | "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", 654 | "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", 655 | "dev": true, 656 | "requires": { 657 | "file-type": "3.9.0", 658 | "get-stream": "2.3.1", 659 | "pify": "2.3.0", 660 | "yauzl": "2.9.1" 661 | }, 662 | "dependencies": { 663 | "file-type": { 664 | "version": "3.9.0", 665 | "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", 666 | "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", 667 | "dev": true 668 | }, 669 | "get-stream": { 670 | "version": "2.3.1", 671 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", 672 | "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", 673 | "dev": true, 674 | "requires": { 675 | "object-assign": "4.1.1", 676 | "pinkie-promise": "2.0.1" 677 | } 678 | } 679 | } 680 | }, 681 | "deep-extend": { 682 | "version": "0.4.2", 683 | "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", 684 | "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", 685 | "dev": true 686 | }, 687 | "delayed-stream": { 688 | "version": "1.0.0", 689 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 690 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 691 | "dev": true 692 | }, 693 | "delegates": { 694 | "version": "1.0.0", 695 | "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", 696 | "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", 697 | "dev": true 698 | }, 699 | "dot-prop": { 700 | "version": "4.2.0", 701 | "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", 702 | "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", 703 | "dev": true, 704 | "requires": { 705 | "is-obj": "1.0.1" 706 | } 707 | }, 708 | "download": { 709 | "version": "5.0.3", 710 | "resolved": "https://registry.npmjs.org/download/-/download-5.0.3.tgz", 711 | "integrity": "sha1-Y1N/l3+ZJmow64oqL70fILgAD3o=", 712 | "dev": true, 713 | "requires": { 714 | "caw": "2.0.1", 715 | "decompress": "4.2.0", 716 | "filenamify": "2.0.0", 717 | "get-stream": "3.0.0", 718 | "got": "6.7.1", 719 | "mkdirp": "0.5.1", 720 | "pify": "2.3.0" 721 | } 722 | }, 723 | "duplexer3": { 724 | "version": "0.1.4", 725 | "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", 726 | "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", 727 | "dev": true 728 | }, 729 | "encoding": { 730 | "version": "0.1.12", 731 | "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", 732 | "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", 733 | "dev": true, 734 | "requires": { 735 | "iconv-lite": "0.4.21" 736 | } 737 | }, 738 | "end-of-stream": { 739 | "version": "1.4.1", 740 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", 741 | "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", 742 | "dev": true, 743 | "requires": { 744 | "once": "1.4.0" 745 | } 746 | }, 747 | "escape-string-regexp": { 748 | "version": "1.0.5", 749 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 750 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 751 | "dev": true 752 | }, 753 | "esprima": { 754 | "version": "4.0.0", 755 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", 756 | "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", 757 | "dev": true 758 | }, 759 | "events": { 760 | "version": "1.1.1", 761 | "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", 762 | "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", 763 | "dev": true 764 | }, 765 | "execa": { 766 | "version": "0.7.0", 767 | "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", 768 | "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", 769 | "dev": true, 770 | "requires": { 771 | "cross-spawn": "5.1.0", 772 | "get-stream": "3.0.0", 773 | "is-stream": "1.1.0", 774 | "npm-run-path": "2.0.2", 775 | "p-finally": "1.0.0", 776 | "signal-exit": "3.0.2", 777 | "strip-eof": "1.0.0" 778 | } 779 | }, 780 | "exit-hook": { 781 | "version": "1.1.1", 782 | "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", 783 | "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", 784 | "dev": true 785 | }, 786 | "extend": { 787 | "version": "3.0.1", 788 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", 789 | "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", 790 | "dev": true 791 | }, 792 | "external-editor": { 793 | "version": "1.1.1", 794 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-1.1.1.tgz", 795 | "integrity": "sha1-Etew24UPf/fnCBuvQAVwAGDEYAs=", 796 | "dev": true, 797 | "requires": { 798 | "extend": "3.0.1", 799 | "spawn-sync": "1.0.15", 800 | "tmp": "0.0.29" 801 | } 802 | }, 803 | "fast-levenshtein": { 804 | "version": "2.0.6", 805 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 806 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 807 | "dev": true 808 | }, 809 | "fd-slicer": { 810 | "version": "1.0.1", 811 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", 812 | "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", 813 | "dev": true, 814 | "requires": { 815 | "pend": "1.2.0" 816 | } 817 | }, 818 | "figures": { 819 | "version": "1.7.0", 820 | "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", 821 | "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", 822 | "dev": true, 823 | "requires": { 824 | "escape-string-regexp": "1.0.5", 825 | "object-assign": "4.1.1" 826 | } 827 | }, 828 | "file-type": { 829 | "version": "5.2.0", 830 | "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", 831 | "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", 832 | "dev": true 833 | }, 834 | "filename-reserved-regex": { 835 | "version": "2.0.0", 836 | "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", 837 | "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", 838 | "dev": true 839 | }, 840 | "filenamify": { 841 | "version": "2.0.0", 842 | "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.0.0.tgz", 843 | "integrity": "sha1-vRYiYsC26Uv7zc8Zo7uzdk94VpU=", 844 | "dev": true, 845 | "requires": { 846 | "filename-reserved-regex": "2.0.0", 847 | "strip-outer": "1.0.1", 848 | "trim-repeated": "1.0.0" 849 | } 850 | }, 851 | "filesize": { 852 | "version": "3.6.1", 853 | "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", 854 | "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==", 855 | "dev": true 856 | }, 857 | "form-data": { 858 | "version": "2.3.2", 859 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", 860 | "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", 861 | "dev": true, 862 | "requires": { 863 | "asynckit": "0.4.0", 864 | "combined-stream": "1.0.6", 865 | "mime-types": "2.1.18" 866 | } 867 | }, 868 | "formidable": { 869 | "version": "1.2.1", 870 | "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", 871 | "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==", 872 | "dev": true 873 | }, 874 | "fs-extra": { 875 | "version": "0.26.7", 876 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", 877 | "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", 878 | "dev": true, 879 | "requires": { 880 | "graceful-fs": "4.1.11", 881 | "jsonfile": "2.4.0", 882 | "klaw": "1.3.1", 883 | "path-is-absolute": "1.0.1", 884 | "rimraf": "2.6.2" 885 | } 886 | }, 887 | "fs.realpath": { 888 | "version": "1.0.0", 889 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 890 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 891 | "dev": true 892 | }, 893 | "gauge": { 894 | "version": "1.2.7", 895 | "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", 896 | "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", 897 | "dev": true, 898 | "requires": { 899 | "ansi": "0.3.1", 900 | "has-unicode": "2.0.1", 901 | "lodash.pad": "4.5.1", 902 | "lodash.padend": "4.6.1", 903 | "lodash.padstart": "4.6.1" 904 | } 905 | }, 906 | "get-proxy": { 907 | "version": "2.1.0", 908 | "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", 909 | "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", 910 | "dev": true, 911 | "requires": { 912 | "npm-conf": "1.1.3" 913 | } 914 | }, 915 | "get-stdin": { 916 | "version": "5.0.1", 917 | "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", 918 | "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", 919 | "dev": true 920 | }, 921 | "get-stream": { 922 | "version": "3.0.0", 923 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", 924 | "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", 925 | "dev": true 926 | }, 927 | "glob": { 928 | "version": "7.1.2", 929 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", 930 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", 931 | "dev": true, 932 | "requires": { 933 | "fs.realpath": "1.0.0", 934 | "inflight": "1.0.6", 935 | "inherits": "2.0.3", 936 | "minimatch": "3.0.4", 937 | "once": "1.4.0", 938 | "path-is-absolute": "1.0.1" 939 | } 940 | }, 941 | "glob-all": { 942 | "version": "3.1.0", 943 | "resolved": "https://registry.npmjs.org/glob-all/-/glob-all-3.1.0.tgz", 944 | "integrity": "sha1-iRPd+17hrHgSZWJBsD1SF8ZLAqs=", 945 | "dev": true, 946 | "requires": { 947 | "glob": "7.1.2", 948 | "yargs": "1.2.6" 949 | } 950 | }, 951 | "global-dirs": { 952 | "version": "0.1.1", 953 | "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", 954 | "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", 955 | "dev": true, 956 | "requires": { 957 | "ini": "1.3.5" 958 | } 959 | }, 960 | "globby": { 961 | "version": "6.1.0", 962 | "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", 963 | "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", 964 | "dev": true, 965 | "requires": { 966 | "array-union": "1.0.2", 967 | "glob": "7.1.2", 968 | "object-assign": "4.1.1", 969 | "pify": "2.3.0", 970 | "pinkie-promise": "2.0.1" 971 | } 972 | }, 973 | "got": { 974 | "version": "6.7.1", 975 | "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", 976 | "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", 977 | "dev": true, 978 | "requires": { 979 | "create-error-class": "3.0.2", 980 | "duplexer3": "0.1.4", 981 | "get-stream": "3.0.0", 982 | "is-redirect": "1.0.0", 983 | "is-retry-allowed": "1.1.0", 984 | "is-stream": "1.1.0", 985 | "lowercase-keys": "1.0.1", 986 | "safe-buffer": "5.1.1", 987 | "timed-out": "4.0.1", 988 | "unzip-response": "2.0.1", 989 | "url-parse-lax": "1.0.0" 990 | } 991 | }, 992 | "graceful-fs": { 993 | "version": "4.1.11", 994 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", 995 | "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", 996 | "dev": true 997 | }, 998 | "graceful-readlink": { 999 | "version": "1.0.1", 1000 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", 1001 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", 1002 | "dev": true 1003 | }, 1004 | "graphlib": { 1005 | "version": "2.1.5", 1006 | "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.5.tgz", 1007 | "integrity": "sha512-XvtbqCcw+EM5SqQrIetIKKD+uZVNQtDPD1goIg7K73RuRZtVI5rYMdcCVSHm/AS1sCBZ7vt0p5WgXouucHQaOA==", 1008 | "dev": true, 1009 | "requires": { 1010 | "lodash": "4.17.5" 1011 | } 1012 | }, 1013 | "graphql": { 1014 | "version": "0.10.5", 1015 | "resolved": "https://registry.npmjs.org/graphql/-/graphql-0.10.5.tgz", 1016 | "integrity": "sha512-Q7cx22DiLhwHsEfUnUip1Ww/Vfx7FS0w6+iHItNuN61+XpegHSa3k5U0+6M5BcpavQImBwFiy0z3uYwY7cXMLQ==", 1017 | "dev": true, 1018 | "requires": { 1019 | "iterall": "1.2.2" 1020 | } 1021 | }, 1022 | "graphql-anywhere": { 1023 | "version": "3.1.0", 1024 | "resolved": "https://registry.npmjs.org/graphql-anywhere/-/graphql-anywhere-3.1.0.tgz", 1025 | "integrity": "sha1-PqDY6GRrXO5oA1AWqadVfBXCHpY=", 1026 | "dev": true 1027 | }, 1028 | "graphql-tag": { 1029 | "version": "2.9.1", 1030 | "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.9.1.tgz", 1031 | "integrity": "sha512-JBLpagu/Xbb8N6xU6hZvBeHjdvnWb/GJnA/rrnBy3iSl0bcy+pjT5N1HctAsWNmGoAgY1+ilwv6JJqu0Tk2hHQ==", 1032 | "dev": true 1033 | }, 1034 | "has-ansi": { 1035 | "version": "2.0.0", 1036 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 1037 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 1038 | "dev": true, 1039 | "requires": { 1040 | "ansi-regex": "2.1.1" 1041 | } 1042 | }, 1043 | "has-flag": { 1044 | "version": "3.0.0", 1045 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 1046 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 1047 | "dev": true 1048 | }, 1049 | "has-symbol-support-x": { 1050 | "version": "1.4.2", 1051 | "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", 1052 | "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", 1053 | "dev": true 1054 | }, 1055 | "has-to-string-tag-x": { 1056 | "version": "1.4.1", 1057 | "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", 1058 | "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", 1059 | "dev": true, 1060 | "requires": { 1061 | "has-symbol-support-x": "1.4.2" 1062 | } 1063 | }, 1064 | "has-unicode": { 1065 | "version": "2.0.1", 1066 | "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", 1067 | "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", 1068 | "dev": true 1069 | }, 1070 | "https-proxy-agent": { 1071 | "version": "1.0.0", 1072 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", 1073 | "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", 1074 | "dev": true, 1075 | "requires": { 1076 | "agent-base": "2.1.1", 1077 | "debug": "2.6.9", 1078 | "extend": "3.0.1" 1079 | } 1080 | }, 1081 | "iconv-lite": { 1082 | "version": "0.4.21", 1083 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz", 1084 | "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", 1085 | "dev": true, 1086 | "requires": { 1087 | "safer-buffer": "2.1.2" 1088 | } 1089 | }, 1090 | "ieee754": { 1091 | "version": "1.1.8", 1092 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", 1093 | "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", 1094 | "dev": true 1095 | }, 1096 | "import-lazy": { 1097 | "version": "2.1.0", 1098 | "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", 1099 | "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", 1100 | "dev": true 1101 | }, 1102 | "imurmurhash": { 1103 | "version": "0.1.4", 1104 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1105 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 1106 | "dev": true 1107 | }, 1108 | "inflight": { 1109 | "version": "1.0.6", 1110 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1111 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1112 | "dev": true, 1113 | "requires": { 1114 | "once": "1.4.0", 1115 | "wrappy": "1.0.2" 1116 | } 1117 | }, 1118 | "inherits": { 1119 | "version": "2.0.3", 1120 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 1121 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 1122 | "dev": true 1123 | }, 1124 | "ini": { 1125 | "version": "1.3.5", 1126 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", 1127 | "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", 1128 | "dev": true 1129 | }, 1130 | "inquirer": { 1131 | "version": "1.2.3", 1132 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-1.2.3.tgz", 1133 | "integrity": "sha1-TexvMvN+97sLLtPx0aXD9UUHSRg=", 1134 | "dev": true, 1135 | "requires": { 1136 | "ansi-escapes": "1.4.0", 1137 | "chalk": "1.1.3", 1138 | "cli-cursor": "1.0.2", 1139 | "cli-width": "2.2.0", 1140 | "external-editor": "1.1.1", 1141 | "figures": "1.7.0", 1142 | "lodash": "4.17.5", 1143 | "mute-stream": "0.0.6", 1144 | "pinkie-promise": "2.0.1", 1145 | "run-async": "2.3.0", 1146 | "rx": "4.1.0", 1147 | "string-width": "1.0.2", 1148 | "strip-ansi": "3.0.1", 1149 | "through": "2.3.8" 1150 | }, 1151 | "dependencies": { 1152 | "ansi-styles": { 1153 | "version": "2.2.1", 1154 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 1155 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", 1156 | "dev": true 1157 | }, 1158 | "chalk": { 1159 | "version": "1.1.3", 1160 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 1161 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 1162 | "dev": true, 1163 | "requires": { 1164 | "ansi-styles": "2.2.1", 1165 | "escape-string-regexp": "1.0.5", 1166 | "has-ansi": "2.0.0", 1167 | "strip-ansi": "3.0.1", 1168 | "supports-color": "2.0.0" 1169 | } 1170 | }, 1171 | "supports-color": { 1172 | "version": "2.0.0", 1173 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 1174 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", 1175 | "dev": true 1176 | } 1177 | } 1178 | }, 1179 | "is-ci": { 1180 | "version": "1.1.0", 1181 | "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz", 1182 | "integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==", 1183 | "dev": true, 1184 | "requires": { 1185 | "ci-info": "1.1.3" 1186 | } 1187 | }, 1188 | "is-docker": { 1189 | "version": "1.1.0", 1190 | "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-1.1.0.tgz", 1191 | "integrity": "sha1-8EN01O7lMQ6ajhE78UlUEeRhdqE=", 1192 | "dev": true 1193 | }, 1194 | "is-fullwidth-code-point": { 1195 | "version": "1.0.0", 1196 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 1197 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 1198 | "dev": true, 1199 | "requires": { 1200 | "number-is-nan": "1.0.1" 1201 | } 1202 | }, 1203 | "is-installed-globally": { 1204 | "version": "0.1.0", 1205 | "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", 1206 | "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", 1207 | "dev": true, 1208 | "requires": { 1209 | "global-dirs": "0.1.1", 1210 | "is-path-inside": "1.0.1" 1211 | } 1212 | }, 1213 | "is-natural-number": { 1214 | "version": "4.0.1", 1215 | "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", 1216 | "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", 1217 | "dev": true 1218 | }, 1219 | "is-npm": { 1220 | "version": "1.0.0", 1221 | "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", 1222 | "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", 1223 | "dev": true 1224 | }, 1225 | "is-obj": { 1226 | "version": "1.0.1", 1227 | "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", 1228 | "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", 1229 | "dev": true 1230 | }, 1231 | "is-object": { 1232 | "version": "1.0.1", 1233 | "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", 1234 | "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", 1235 | "dev": true 1236 | }, 1237 | "is-path-inside": { 1238 | "version": "1.0.1", 1239 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", 1240 | "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", 1241 | "dev": true, 1242 | "requires": { 1243 | "path-is-inside": "1.0.2" 1244 | } 1245 | }, 1246 | "is-promise": { 1247 | "version": "2.1.0", 1248 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 1249 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", 1250 | "dev": true 1251 | }, 1252 | "is-redirect": { 1253 | "version": "1.0.0", 1254 | "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", 1255 | "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", 1256 | "dev": true 1257 | }, 1258 | "is-retry-allowed": { 1259 | "version": "1.1.0", 1260 | "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", 1261 | "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", 1262 | "dev": true 1263 | }, 1264 | "is-stream": { 1265 | "version": "1.1.0", 1266 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 1267 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", 1268 | "dev": true 1269 | }, 1270 | "is-wsl": { 1271 | "version": "1.1.0", 1272 | "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", 1273 | "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", 1274 | "dev": true 1275 | }, 1276 | "isarray": { 1277 | "version": "1.0.0", 1278 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1279 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 1280 | "dev": true 1281 | }, 1282 | "isexe": { 1283 | "version": "2.0.0", 1284 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1285 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 1286 | "dev": true 1287 | }, 1288 | "isomorphic-fetch": { 1289 | "version": "2.2.1", 1290 | "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", 1291 | "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", 1292 | "dev": true, 1293 | "requires": { 1294 | "node-fetch": "1.7.3", 1295 | "whatwg-fetch": "2.0.4" 1296 | } 1297 | }, 1298 | "isurl": { 1299 | "version": "1.0.0", 1300 | "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", 1301 | "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", 1302 | "dev": true, 1303 | "requires": { 1304 | "has-to-string-tag-x": "1.4.1", 1305 | "is-object": "1.0.1" 1306 | } 1307 | }, 1308 | "iterall": { 1309 | "version": "1.2.2", 1310 | "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.2.2.tgz", 1311 | "integrity": "sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA==", 1312 | "dev": true 1313 | }, 1314 | "jmespath": { 1315 | "version": "0.15.0", 1316 | "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", 1317 | "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=", 1318 | "dev": true 1319 | }, 1320 | "js-tokens": { 1321 | "version": "3.0.2", 1322 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", 1323 | "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", 1324 | "dev": true 1325 | }, 1326 | "js-yaml": { 1327 | "version": "3.11.0", 1328 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", 1329 | "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", 1330 | "dev": true, 1331 | "requires": { 1332 | "argparse": "1.0.10", 1333 | "esprima": "4.0.0" 1334 | } 1335 | }, 1336 | "json-cycle": { 1337 | "version": "1.3.0", 1338 | "resolved": "https://registry.npmjs.org/json-cycle/-/json-cycle-1.3.0.tgz", 1339 | "integrity": "sha512-FD/SedD78LCdSvJaOUQAXseT8oQBb5z6IVYaQaCrVUlu9zOAr1BDdKyVYQaSD/GDsAMrXpKcOyBD4LIl8nfjHw==", 1340 | "dev": true 1341 | }, 1342 | "json-refs": { 1343 | "version": "2.1.7", 1344 | "resolved": "https://registry.npmjs.org/json-refs/-/json-refs-2.1.7.tgz", 1345 | "integrity": "sha1-uesB/in16j6Sh48VrqEK04taz4k=", 1346 | "dev": true, 1347 | "requires": { 1348 | "commander": "2.15.1", 1349 | "graphlib": "2.1.5", 1350 | "js-yaml": "3.11.0", 1351 | "native-promise-only": "0.8.1", 1352 | "path-loader": "1.0.4", 1353 | "slash": "1.0.0", 1354 | "uri-js": "3.0.2" 1355 | }, 1356 | "dependencies": { 1357 | "commander": { 1358 | "version": "2.15.1", 1359 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", 1360 | "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", 1361 | "dev": true 1362 | } 1363 | } 1364 | }, 1365 | "json-stringify-safe": { 1366 | "version": "5.0.1", 1367 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 1368 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 1369 | "dev": true 1370 | }, 1371 | "jsonfile": { 1372 | "version": "2.4.0", 1373 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", 1374 | "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", 1375 | "dev": true, 1376 | "requires": { 1377 | "graceful-fs": "4.1.11" 1378 | } 1379 | }, 1380 | "jszip": { 1381 | "version": "2.6.1", 1382 | "resolved": "https://registry.npmjs.org/jszip/-/jszip-2.6.1.tgz", 1383 | "integrity": "sha1-uI86ey5noqBIFSmCx6N1bZxIKPA=", 1384 | "dev": true, 1385 | "requires": { 1386 | "pako": "1.0.6" 1387 | } 1388 | }, 1389 | "jwt-decode": { 1390 | "version": "2.2.0", 1391 | "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz", 1392 | "integrity": "sha1-fYa9VmefWM5qhHBKZX3TkruoGnk=", 1393 | "dev": true 1394 | }, 1395 | "klaw": { 1396 | "version": "1.3.1", 1397 | "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", 1398 | "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", 1399 | "dev": true, 1400 | "requires": { 1401 | "graceful-fs": "4.1.11" 1402 | } 1403 | }, 1404 | "latest-version": { 1405 | "version": "3.1.0", 1406 | "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", 1407 | "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", 1408 | "dev": true, 1409 | "requires": { 1410 | "package-json": "4.0.1" 1411 | } 1412 | }, 1413 | "lazystream": { 1414 | "version": "1.0.0", 1415 | "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", 1416 | "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", 1417 | "dev": true, 1418 | "requires": { 1419 | "readable-stream": "2.3.6" 1420 | } 1421 | }, 1422 | "lodash": { 1423 | "version": "4.17.5", 1424 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", 1425 | "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", 1426 | "dev": true 1427 | }, 1428 | "lodash-es": { 1429 | "version": "4.17.8", 1430 | "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.8.tgz", 1431 | "integrity": "sha512-I9mjAxengFAleSThFhhAhvba6fsO0hunb9/0sQ6qQihSZsJRBofv2rYH58WXaOb/O++eUmYpCLywSQ22GfU+sA==", 1432 | "dev": true 1433 | }, 1434 | "lodash.difference": { 1435 | "version": "4.5.0", 1436 | "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", 1437 | "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", 1438 | "dev": true 1439 | }, 1440 | "lodash.get": { 1441 | "version": "4.4.2", 1442 | "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", 1443 | "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", 1444 | "dev": true 1445 | }, 1446 | "lodash.pad": { 1447 | "version": "4.5.1", 1448 | "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz", 1449 | "integrity": "sha1-QzCUmoM6fI2iLMIPaibE1Z3runA=", 1450 | "dev": true 1451 | }, 1452 | "lodash.padend": { 1453 | "version": "4.6.1", 1454 | "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", 1455 | "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", 1456 | "dev": true 1457 | }, 1458 | "lodash.padstart": { 1459 | "version": "4.6.1", 1460 | "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", 1461 | "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=", 1462 | "dev": true 1463 | }, 1464 | "lodash.set": { 1465 | "version": "4.3.2", 1466 | "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", 1467 | "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", 1468 | "dev": true 1469 | }, 1470 | "lodash.uniq": { 1471 | "version": "4.5.0", 1472 | "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", 1473 | "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", 1474 | "dev": true 1475 | }, 1476 | "lodash.values": { 1477 | "version": "4.3.0", 1478 | "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-4.3.0.tgz", 1479 | "integrity": "sha1-o6bCsOvsxcLLocF+bmIP6BtT00c=", 1480 | "dev": true 1481 | }, 1482 | "loose-envify": { 1483 | "version": "1.3.1", 1484 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", 1485 | "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", 1486 | "dev": true, 1487 | "requires": { 1488 | "js-tokens": "3.0.2" 1489 | } 1490 | }, 1491 | "lowercase-keys": { 1492 | "version": "1.0.1", 1493 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", 1494 | "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", 1495 | "dev": true 1496 | }, 1497 | "lru-cache": { 1498 | "version": "4.1.2", 1499 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", 1500 | "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", 1501 | "dev": true, 1502 | "requires": { 1503 | "pseudomap": "1.0.2", 1504 | "yallist": "2.1.2" 1505 | } 1506 | }, 1507 | "lsmod": { 1508 | "version": "1.0.0", 1509 | "resolved": "https://registry.npmjs.org/lsmod/-/lsmod-1.0.0.tgz", 1510 | "integrity": "sha1-mgD3bco26yP6BTUK/htYXUKZ5ks=", 1511 | "dev": true 1512 | }, 1513 | "make-dir": { 1514 | "version": "1.2.0", 1515 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", 1516 | "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", 1517 | "dev": true, 1518 | "requires": { 1519 | "pify": "3.0.0" 1520 | }, 1521 | "dependencies": { 1522 | "pify": { 1523 | "version": "3.0.0", 1524 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 1525 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", 1526 | "dev": true 1527 | } 1528 | } 1529 | }, 1530 | "methods": { 1531 | "version": "1.1.2", 1532 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 1533 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", 1534 | "dev": true 1535 | }, 1536 | "mime": { 1537 | "version": "1.6.0", 1538 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1539 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 1540 | "dev": true 1541 | }, 1542 | "mime-db": { 1543 | "version": "1.33.0", 1544 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", 1545 | "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", 1546 | "dev": true 1547 | }, 1548 | "mime-types": { 1549 | "version": "2.1.18", 1550 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", 1551 | "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", 1552 | "dev": true, 1553 | "requires": { 1554 | "mime-db": "1.33.0" 1555 | } 1556 | }, 1557 | "minimatch": { 1558 | "version": "3.0.4", 1559 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1560 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1561 | "dev": true, 1562 | "requires": { 1563 | "brace-expansion": "1.1.11" 1564 | } 1565 | }, 1566 | "minimist": { 1567 | "version": "1.2.0", 1568 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 1569 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", 1570 | "dev": true 1571 | }, 1572 | "mkdirp": { 1573 | "version": "0.5.1", 1574 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 1575 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 1576 | "dev": true, 1577 | "requires": { 1578 | "minimist": "0.0.8" 1579 | }, 1580 | "dependencies": { 1581 | "minimist": { 1582 | "version": "0.0.8", 1583 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 1584 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 1585 | "dev": true 1586 | } 1587 | } 1588 | }, 1589 | "moment": { 1590 | "version": "2.22.1", 1591 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.1.tgz", 1592 | "integrity": "sha512-shJkRTSebXvsVqk56I+lkb2latjBs8I+pc2TzWc545y2iFnSjm7Wg0QMh+ZWcdSLQyGEau5jI8ocnmkyTgr9YQ==", 1593 | "dev": true 1594 | }, 1595 | "ms": { 1596 | "version": "2.0.0", 1597 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1598 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 1599 | "dev": true 1600 | }, 1601 | "mute-stream": { 1602 | "version": "0.0.6", 1603 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.6.tgz", 1604 | "integrity": "sha1-SJYrGeFp/R38JAs/HnMXYnu8R9s=", 1605 | "dev": true 1606 | }, 1607 | "native-promise-only": { 1608 | "version": "0.8.1", 1609 | "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", 1610 | "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=", 1611 | "dev": true 1612 | }, 1613 | "node-fetch": { 1614 | "version": "1.7.3", 1615 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", 1616 | "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", 1617 | "dev": true, 1618 | "requires": { 1619 | "encoding": "0.1.12", 1620 | "is-stream": "1.1.0" 1621 | } 1622 | }, 1623 | "node-forge": { 1624 | "version": "0.7.5", 1625 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", 1626 | "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==", 1627 | "dev": true 1628 | }, 1629 | "normalize-path": { 1630 | "version": "2.1.1", 1631 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", 1632 | "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", 1633 | "dev": true, 1634 | "requires": { 1635 | "remove-trailing-separator": "1.1.0" 1636 | } 1637 | }, 1638 | "npm-conf": { 1639 | "version": "1.1.3", 1640 | "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", 1641 | "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", 1642 | "dev": true, 1643 | "requires": { 1644 | "config-chain": "1.1.11", 1645 | "pify": "3.0.0" 1646 | }, 1647 | "dependencies": { 1648 | "pify": { 1649 | "version": "3.0.0", 1650 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 1651 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", 1652 | "dev": true 1653 | } 1654 | } 1655 | }, 1656 | "npm-run-path": { 1657 | "version": "2.0.2", 1658 | "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", 1659 | "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", 1660 | "dev": true, 1661 | "requires": { 1662 | "path-key": "2.0.1" 1663 | } 1664 | }, 1665 | "npmlog": { 1666 | "version": "2.0.4", 1667 | "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", 1668 | "integrity": "sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI=", 1669 | "dev": true, 1670 | "requires": { 1671 | "ansi": "0.3.1", 1672 | "are-we-there-yet": "1.1.4", 1673 | "gauge": "1.2.7" 1674 | } 1675 | }, 1676 | "number-is-nan": { 1677 | "version": "1.0.1", 1678 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 1679 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", 1680 | "dev": true 1681 | }, 1682 | "object-assign": { 1683 | "version": "4.1.1", 1684 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1685 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", 1686 | "dev": true 1687 | }, 1688 | "object-hash": { 1689 | "version": "1.3.0", 1690 | "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.0.tgz", 1691 | "integrity": "sha512-05KzQ70lSeGSrZJQXE5wNDiTkBJDlUT/myi6RX9dVIvz7a7Qh4oH93BQdiPMn27nldYvVQCKMUaM83AfizZlsQ==", 1692 | "dev": true 1693 | }, 1694 | "once": { 1695 | "version": "1.4.0", 1696 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1697 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1698 | "dev": true, 1699 | "requires": { 1700 | "wrappy": "1.0.2" 1701 | } 1702 | }, 1703 | "onetime": { 1704 | "version": "1.1.0", 1705 | "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", 1706 | "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", 1707 | "dev": true 1708 | }, 1709 | "opn": { 1710 | "version": "5.3.0", 1711 | "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", 1712 | "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", 1713 | "dev": true, 1714 | "requires": { 1715 | "is-wsl": "1.1.0" 1716 | } 1717 | }, 1718 | "os-shim": { 1719 | "version": "0.1.3", 1720 | "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz", 1721 | "integrity": "sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc=", 1722 | "dev": true 1723 | }, 1724 | "os-tmpdir": { 1725 | "version": "1.0.2", 1726 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 1727 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", 1728 | "dev": true 1729 | }, 1730 | "p-finally": { 1731 | "version": "1.0.0", 1732 | "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", 1733 | "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", 1734 | "dev": true 1735 | }, 1736 | "package-json": { 1737 | "version": "4.0.1", 1738 | "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", 1739 | "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", 1740 | "dev": true, 1741 | "requires": { 1742 | "got": "6.7.1", 1743 | "registry-auth-token": "3.3.2", 1744 | "registry-url": "3.1.0", 1745 | "semver": "5.5.0" 1746 | } 1747 | }, 1748 | "pako": { 1749 | "version": "1.0.6", 1750 | "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", 1751 | "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", 1752 | "dev": true 1753 | }, 1754 | "path-is-absolute": { 1755 | "version": "1.0.1", 1756 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1757 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1758 | "dev": true 1759 | }, 1760 | "path-is-inside": { 1761 | "version": "1.0.2", 1762 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", 1763 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", 1764 | "dev": true 1765 | }, 1766 | "path-key": { 1767 | "version": "2.0.1", 1768 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", 1769 | "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", 1770 | "dev": true 1771 | }, 1772 | "path-loader": { 1773 | "version": "1.0.4", 1774 | "resolved": "https://registry.npmjs.org/path-loader/-/path-loader-1.0.4.tgz", 1775 | "integrity": "sha512-k/IPo9OWyofATP5gwIehHHQoFShS37zsSIsejKe6fjI+tqK+FnRpiSg4ZfWUpxb0g2PfCreWPqBD4ayjqjqkdQ==", 1776 | "dev": true, 1777 | "requires": { 1778 | "native-promise-only": "0.8.1", 1779 | "superagent": "3.8.2" 1780 | } 1781 | }, 1782 | "pend": { 1783 | "version": "1.2.0", 1784 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 1785 | "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", 1786 | "dev": true 1787 | }, 1788 | "pify": { 1789 | "version": "2.3.0", 1790 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 1791 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", 1792 | "dev": true 1793 | }, 1794 | "pinkie": { 1795 | "version": "2.0.4", 1796 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", 1797 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", 1798 | "dev": true 1799 | }, 1800 | "pinkie-promise": { 1801 | "version": "2.0.1", 1802 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", 1803 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", 1804 | "dev": true, 1805 | "requires": { 1806 | "pinkie": "2.0.4" 1807 | } 1808 | }, 1809 | "prepend-http": { 1810 | "version": "1.0.4", 1811 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", 1812 | "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", 1813 | "dev": true 1814 | }, 1815 | "process-nextick-args": { 1816 | "version": "2.0.0", 1817 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", 1818 | "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", 1819 | "dev": true 1820 | }, 1821 | "promise-queue": { 1822 | "version": "2.2.5", 1823 | "resolved": "https://registry.npmjs.org/promise-queue/-/promise-queue-2.2.5.tgz", 1824 | "integrity": "sha1-L29ffA9tCBCelnZZx5uIqe1ek7Q=", 1825 | "dev": true 1826 | }, 1827 | "proto-list": { 1828 | "version": "1.2.4", 1829 | "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", 1830 | "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", 1831 | "dev": true 1832 | }, 1833 | "pseudomap": { 1834 | "version": "1.0.2", 1835 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", 1836 | "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", 1837 | "dev": true 1838 | }, 1839 | "punycode": { 1840 | "version": "1.3.2", 1841 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", 1842 | "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", 1843 | "dev": true 1844 | }, 1845 | "q": { 1846 | "version": "1.5.1", 1847 | "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", 1848 | "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", 1849 | "dev": true 1850 | }, 1851 | "qs": { 1852 | "version": "6.5.1", 1853 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", 1854 | "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", 1855 | "dev": true 1856 | }, 1857 | "querystring": { 1858 | "version": "0.2.0", 1859 | "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", 1860 | "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", 1861 | "dev": true 1862 | }, 1863 | "querystringify": { 1864 | "version": "2.0.0", 1865 | "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz", 1866 | "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==", 1867 | "dev": true 1868 | }, 1869 | "ramda": { 1870 | "version": "0.24.1", 1871 | "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.24.1.tgz", 1872 | "integrity": "sha1-w7d1UZfzW43DUCIoJixMkd22uFc=", 1873 | "dev": true 1874 | }, 1875 | "raven": { 1876 | "version": "1.2.1", 1877 | "resolved": "https://registry.npmjs.org/raven/-/raven-1.2.1.tgz", 1878 | "integrity": "sha1-lJwTTbAooZC3u/j3kKrlQbfAIL0=", 1879 | "dev": true, 1880 | "requires": { 1881 | "cookie": "0.3.1", 1882 | "json-stringify-safe": "5.0.1", 1883 | "lsmod": "1.0.0", 1884 | "stack-trace": "0.0.9", 1885 | "uuid": "3.0.0" 1886 | }, 1887 | "dependencies": { 1888 | "uuid": { 1889 | "version": "3.0.0", 1890 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.0.tgz", 1891 | "integrity": "sha1-Zyj8BFnEUNeWqZwxg3VpvfZy1yg=", 1892 | "dev": true 1893 | } 1894 | } 1895 | }, 1896 | "rc": { 1897 | "version": "1.2.6", 1898 | "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.6.tgz", 1899 | "integrity": "sha1-6xiYnG1PTxYsOZ953dKfODVWgJI=", 1900 | "dev": true, 1901 | "requires": { 1902 | "deep-extend": "0.4.2", 1903 | "ini": "1.3.5", 1904 | "minimist": "1.2.0", 1905 | "strip-json-comments": "2.0.1" 1906 | } 1907 | }, 1908 | "readable-stream": { 1909 | "version": "2.3.6", 1910 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 1911 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 1912 | "dev": true, 1913 | "requires": { 1914 | "core-util-is": "1.0.2", 1915 | "inherits": "2.0.3", 1916 | "isarray": "1.0.0", 1917 | "process-nextick-args": "2.0.0", 1918 | "safe-buffer": "5.1.1", 1919 | "string_decoder": "1.1.1", 1920 | "util-deprecate": "1.0.2" 1921 | } 1922 | }, 1923 | "redux": { 1924 | "version": "3.7.2", 1925 | "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", 1926 | "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==", 1927 | "dev": true, 1928 | "requires": { 1929 | "lodash": "4.17.5", 1930 | "lodash-es": "4.17.8", 1931 | "loose-envify": "1.3.1", 1932 | "symbol-observable": "1.2.0" 1933 | } 1934 | }, 1935 | "registry-auth-token": { 1936 | "version": "3.3.2", 1937 | "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", 1938 | "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", 1939 | "dev": true, 1940 | "requires": { 1941 | "rc": "1.2.6", 1942 | "safe-buffer": "5.1.1" 1943 | } 1944 | }, 1945 | "registry-url": { 1946 | "version": "3.1.0", 1947 | "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", 1948 | "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", 1949 | "dev": true, 1950 | "requires": { 1951 | "rc": "1.2.6" 1952 | } 1953 | }, 1954 | "remove-trailing-separator": { 1955 | "version": "1.1.0", 1956 | "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", 1957 | "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", 1958 | "dev": true 1959 | }, 1960 | "replaceall": { 1961 | "version": "0.1.6", 1962 | "resolved": "https://registry.npmjs.org/replaceall/-/replaceall-0.1.6.tgz", 1963 | "integrity": "sha1-gdgax663LX9cSUKt8ml6MiBojY4=", 1964 | "dev": true 1965 | }, 1966 | "requires-port": { 1967 | "version": "1.0.0", 1968 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 1969 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", 1970 | "dev": true 1971 | }, 1972 | "restore-cursor": { 1973 | "version": "1.0.1", 1974 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", 1975 | "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", 1976 | "dev": true, 1977 | "requires": { 1978 | "exit-hook": "1.1.1", 1979 | "onetime": "1.1.0" 1980 | } 1981 | }, 1982 | "rimraf": { 1983 | "version": "2.6.2", 1984 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", 1985 | "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", 1986 | "dev": true, 1987 | "requires": { 1988 | "glob": "7.1.2" 1989 | } 1990 | }, 1991 | "run-async": { 1992 | "version": "2.3.0", 1993 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", 1994 | "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", 1995 | "dev": true, 1996 | "requires": { 1997 | "is-promise": "2.1.0" 1998 | } 1999 | }, 2000 | "rx": { 2001 | "version": "4.1.0", 2002 | "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", 2003 | "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=", 2004 | "dev": true 2005 | }, 2006 | "safe-buffer": { 2007 | "version": "5.1.1", 2008 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 2009 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", 2010 | "dev": true 2011 | }, 2012 | "safer-buffer": { 2013 | "version": "2.1.2", 2014 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 2015 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 2016 | "dev": true 2017 | }, 2018 | "sax": { 2019 | "version": "1.2.1", 2020 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", 2021 | "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=", 2022 | "dev": true 2023 | }, 2024 | "seek-bzip": { 2025 | "version": "1.0.5", 2026 | "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", 2027 | "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", 2028 | "dev": true, 2029 | "requires": { 2030 | "commander": "2.8.1" 2031 | } 2032 | }, 2033 | "semver": { 2034 | "version": "5.5.0", 2035 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", 2036 | "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", 2037 | "dev": true 2038 | }, 2039 | "semver-diff": { 2040 | "version": "2.1.0", 2041 | "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", 2042 | "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", 2043 | "dev": true, 2044 | "requires": { 2045 | "semver": "5.5.0" 2046 | } 2047 | }, 2048 | "semver-regex": { 2049 | "version": "1.0.0", 2050 | "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz", 2051 | "integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk=", 2052 | "dev": true 2053 | }, 2054 | "serverless": { 2055 | "version": "1.26.1", 2056 | "resolved": "https://registry.npmjs.org/serverless/-/serverless-1.26.1.tgz", 2057 | "integrity": "sha1-IAN7KM42qzgdNpKQgfNrJJ0SZUI=", 2058 | "dev": true, 2059 | "requires": { 2060 | "@serverless/fdk": "0.5.1", 2061 | "apollo-client": "1.9.3", 2062 | "archiver": "1.3.0", 2063 | "async": "1.5.2", 2064 | "aws-sdk": "2.225.1", 2065 | "bluebird": "3.5.1", 2066 | "chalk": "2.4.0", 2067 | "ci-info": "1.1.3", 2068 | "download": "5.0.3", 2069 | "fast-levenshtein": "2.0.6", 2070 | "filesize": "3.6.1", 2071 | "fs-extra": "0.26.7", 2072 | "get-stdin": "5.0.1", 2073 | "globby": "6.1.0", 2074 | "graceful-fs": "4.1.11", 2075 | "graphql": "0.10.5", 2076 | "graphql-tag": "2.9.1", 2077 | "https-proxy-agent": "1.0.0", 2078 | "is-docker": "1.1.0", 2079 | "js-yaml": "3.11.0", 2080 | "json-cycle": "1.3.0", 2081 | "json-refs": "2.1.7", 2082 | "jwt-decode": "2.2.0", 2083 | "lodash": "4.17.5", 2084 | "minimist": "1.2.0", 2085 | "moment": "2.22.1", 2086 | "node-fetch": "1.7.3", 2087 | "node-forge": "0.7.5", 2088 | "object-hash": "1.3.0", 2089 | "opn": "5.3.0", 2090 | "promise-queue": "2.2.5", 2091 | "raven": "1.2.1", 2092 | "rc": "1.2.6", 2093 | "replaceall": "0.1.6", 2094 | "semver": "5.5.0", 2095 | "semver-regex": "1.0.0", 2096 | "tabtab": "2.2.2", 2097 | "update-notifier": "2.5.0", 2098 | "uuid": "2.0.3", 2099 | "write-file-atomic": "2.3.0", 2100 | "yaml-ast-parser": "0.0.34" 2101 | } 2102 | }, 2103 | "serverless-python-requirements": { 2104 | "version": "4.0.1", 2105 | "resolved": "https://registry.npmjs.org/serverless-python-requirements/-/serverless-python-requirements-4.0.1.tgz", 2106 | "integrity": "sha512-ClMCdoaShUGEVKnfAHNrmUSuEvJCZlD/l3CnvgiVorvQJajPrrO4QASc/cCMeieYhkFOU6a34dhRxIN6bOXprA==", 2107 | "dev": true, 2108 | "requires": { 2109 | "bluebird": "3.5.1", 2110 | "fs-extra": "5.0.0", 2111 | "glob-all": "3.1.0", 2112 | "is-wsl": "1.1.0", 2113 | "jszip": "2.6.1", 2114 | "lodash.get": "4.4.2", 2115 | "lodash.set": "4.3.2", 2116 | "lodash.values": "4.3.0", 2117 | "rimraf": "2.6.2", 2118 | "zip-local": "0.3.4" 2119 | }, 2120 | "dependencies": { 2121 | "fs-extra": { 2122 | "version": "5.0.0", 2123 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", 2124 | "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", 2125 | "dev": true, 2126 | "requires": { 2127 | "graceful-fs": "4.1.11", 2128 | "jsonfile": "4.0.0", 2129 | "universalify": "0.1.1" 2130 | } 2131 | }, 2132 | "jsonfile": { 2133 | "version": "4.0.0", 2134 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 2135 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", 2136 | "dev": true, 2137 | "requires": { 2138 | "graceful-fs": "4.1.11" 2139 | } 2140 | } 2141 | } 2142 | }, 2143 | "shebang-command": { 2144 | "version": "1.2.0", 2145 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 2146 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 2147 | "dev": true, 2148 | "requires": { 2149 | "shebang-regex": "1.0.0" 2150 | } 2151 | }, 2152 | "shebang-regex": { 2153 | "version": "1.0.0", 2154 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 2155 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", 2156 | "dev": true 2157 | }, 2158 | "signal-exit": { 2159 | "version": "3.0.2", 2160 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 2161 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", 2162 | "dev": true 2163 | }, 2164 | "slash": { 2165 | "version": "1.0.0", 2166 | "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", 2167 | "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", 2168 | "dev": true 2169 | }, 2170 | "spawn-sync": { 2171 | "version": "1.0.15", 2172 | "resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz", 2173 | "integrity": "sha1-sAeZVX63+wyDdsKdROih6mfldHY=", 2174 | "dev": true, 2175 | "requires": { 2176 | "concat-stream": "1.6.2", 2177 | "os-shim": "0.1.3" 2178 | } 2179 | }, 2180 | "sprintf-js": { 2181 | "version": "1.0.3", 2182 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 2183 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 2184 | "dev": true 2185 | }, 2186 | "stack-trace": { 2187 | "version": "0.0.9", 2188 | "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", 2189 | "integrity": "sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU=", 2190 | "dev": true 2191 | }, 2192 | "string-width": { 2193 | "version": "1.0.2", 2194 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 2195 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 2196 | "dev": true, 2197 | "requires": { 2198 | "code-point-at": "1.1.0", 2199 | "is-fullwidth-code-point": "1.0.0", 2200 | "strip-ansi": "3.0.1" 2201 | } 2202 | }, 2203 | "string_decoder": { 2204 | "version": "1.1.1", 2205 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 2206 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 2207 | "dev": true, 2208 | "requires": { 2209 | "safe-buffer": "5.1.1" 2210 | } 2211 | }, 2212 | "strip-ansi": { 2213 | "version": "3.0.1", 2214 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 2215 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 2216 | "dev": true, 2217 | "requires": { 2218 | "ansi-regex": "2.1.1" 2219 | } 2220 | }, 2221 | "strip-dirs": { 2222 | "version": "2.1.0", 2223 | "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", 2224 | "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", 2225 | "dev": true, 2226 | "requires": { 2227 | "is-natural-number": "4.0.1" 2228 | } 2229 | }, 2230 | "strip-eof": { 2231 | "version": "1.0.0", 2232 | "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", 2233 | "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", 2234 | "dev": true 2235 | }, 2236 | "strip-json-comments": { 2237 | "version": "2.0.1", 2238 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 2239 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 2240 | "dev": true 2241 | }, 2242 | "strip-outer": { 2243 | "version": "1.0.1", 2244 | "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", 2245 | "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", 2246 | "dev": true, 2247 | "requires": { 2248 | "escape-string-regexp": "1.0.5" 2249 | } 2250 | }, 2251 | "superagent": { 2252 | "version": "3.8.2", 2253 | "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.2.tgz", 2254 | "integrity": "sha512-gVH4QfYHcY3P0f/BZzavLreHW3T1v7hG9B+hpMQotGQqurOvhv87GcMCd6LWySmBuf+BDR44TQd0aISjVHLeNQ==", 2255 | "dev": true, 2256 | "requires": { 2257 | "component-emitter": "1.2.1", 2258 | "cookiejar": "2.1.1", 2259 | "debug": "3.1.0", 2260 | "extend": "3.0.1", 2261 | "form-data": "2.3.2", 2262 | "formidable": "1.2.1", 2263 | "methods": "1.1.2", 2264 | "mime": "1.6.0", 2265 | "qs": "6.5.1", 2266 | "readable-stream": "2.3.6" 2267 | }, 2268 | "dependencies": { 2269 | "debug": { 2270 | "version": "3.1.0", 2271 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 2272 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 2273 | "dev": true, 2274 | "requires": { 2275 | "ms": "2.0.0" 2276 | } 2277 | } 2278 | } 2279 | }, 2280 | "supports-color": { 2281 | "version": "5.4.0", 2282 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", 2283 | "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", 2284 | "dev": true, 2285 | "requires": { 2286 | "has-flag": "3.0.0" 2287 | } 2288 | }, 2289 | "symbol-observable": { 2290 | "version": "1.2.0", 2291 | "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", 2292 | "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", 2293 | "dev": true 2294 | }, 2295 | "tabtab": { 2296 | "version": "2.2.2", 2297 | "resolved": "https://registry.npmjs.org/tabtab/-/tabtab-2.2.2.tgz", 2298 | "integrity": "sha1-egR/FDsBC0y9MfhX6ClhUSy/ThQ=", 2299 | "dev": true, 2300 | "requires": { 2301 | "debug": "2.6.9", 2302 | "inquirer": "1.2.3", 2303 | "lodash.difference": "4.5.0", 2304 | "lodash.uniq": "4.5.0", 2305 | "minimist": "1.2.0", 2306 | "mkdirp": "0.5.1", 2307 | "npmlog": "2.0.4", 2308 | "object-assign": "4.1.1" 2309 | } 2310 | }, 2311 | "tar-stream": { 2312 | "version": "1.5.5", 2313 | "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz", 2314 | "integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==", 2315 | "dev": true, 2316 | "requires": { 2317 | "bl": "1.2.2", 2318 | "end-of-stream": "1.4.1", 2319 | "readable-stream": "2.3.6", 2320 | "xtend": "4.0.1" 2321 | } 2322 | }, 2323 | "term-size": { 2324 | "version": "1.2.0", 2325 | "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", 2326 | "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", 2327 | "dev": true, 2328 | "requires": { 2329 | "execa": "0.7.0" 2330 | } 2331 | }, 2332 | "through": { 2333 | "version": "2.3.8", 2334 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 2335 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", 2336 | "dev": true 2337 | }, 2338 | "timed-out": { 2339 | "version": "4.0.1", 2340 | "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", 2341 | "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", 2342 | "dev": true 2343 | }, 2344 | "tmp": { 2345 | "version": "0.0.29", 2346 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.29.tgz", 2347 | "integrity": "sha1-8lEl/w3Z2jzLDC3Tce4SiLuRKMA=", 2348 | "dev": true, 2349 | "requires": { 2350 | "os-tmpdir": "1.0.2" 2351 | } 2352 | }, 2353 | "trim-repeated": { 2354 | "version": "1.0.0", 2355 | "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", 2356 | "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", 2357 | "dev": true, 2358 | "requires": { 2359 | "escape-string-regexp": "1.0.5" 2360 | } 2361 | }, 2362 | "tunnel-agent": { 2363 | "version": "0.6.0", 2364 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 2365 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 2366 | "dev": true, 2367 | "requires": { 2368 | "safe-buffer": "5.1.1" 2369 | } 2370 | }, 2371 | "typedarray": { 2372 | "version": "0.0.6", 2373 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 2374 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 2375 | "dev": true 2376 | }, 2377 | "unbzip2-stream": { 2378 | "version": "1.2.5", 2379 | "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz", 2380 | "integrity": "sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==", 2381 | "dev": true, 2382 | "requires": { 2383 | "buffer": "3.6.0", 2384 | "through": "2.3.8" 2385 | }, 2386 | "dependencies": { 2387 | "base64-js": { 2388 | "version": "0.0.8", 2389 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", 2390 | "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=", 2391 | "dev": true 2392 | }, 2393 | "buffer": { 2394 | "version": "3.6.0", 2395 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", 2396 | "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", 2397 | "dev": true, 2398 | "requires": { 2399 | "base64-js": "0.0.8", 2400 | "ieee754": "1.1.8", 2401 | "isarray": "1.0.0" 2402 | } 2403 | } 2404 | } 2405 | }, 2406 | "unique-string": { 2407 | "version": "1.0.0", 2408 | "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", 2409 | "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", 2410 | "dev": true, 2411 | "requires": { 2412 | "crypto-random-string": "1.0.0" 2413 | } 2414 | }, 2415 | "universalify": { 2416 | "version": "0.1.1", 2417 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", 2418 | "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=", 2419 | "dev": true 2420 | }, 2421 | "unzip-response": { 2422 | "version": "2.0.1", 2423 | "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", 2424 | "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", 2425 | "dev": true 2426 | }, 2427 | "update-notifier": { 2428 | "version": "2.5.0", 2429 | "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", 2430 | "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", 2431 | "dev": true, 2432 | "requires": { 2433 | "boxen": "1.3.0", 2434 | "chalk": "2.4.0", 2435 | "configstore": "3.1.2", 2436 | "import-lazy": "2.1.0", 2437 | "is-ci": "1.1.0", 2438 | "is-installed-globally": "0.1.0", 2439 | "is-npm": "1.0.0", 2440 | "latest-version": "3.1.0", 2441 | "semver-diff": "2.1.0", 2442 | "xdg-basedir": "3.0.0" 2443 | } 2444 | }, 2445 | "uri-js": { 2446 | "version": "3.0.2", 2447 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-3.0.2.tgz", 2448 | "integrity": "sha1-+QuFhQf4HepNz7s8TD2/orVX+qo=", 2449 | "dev": true, 2450 | "requires": { 2451 | "punycode": "2.1.0" 2452 | }, 2453 | "dependencies": { 2454 | "punycode": { 2455 | "version": "2.1.0", 2456 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", 2457 | "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=", 2458 | "dev": true 2459 | } 2460 | } 2461 | }, 2462 | "url": { 2463 | "version": "0.10.3", 2464 | "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", 2465 | "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", 2466 | "dev": true, 2467 | "requires": { 2468 | "punycode": "1.3.2", 2469 | "querystring": "0.2.0" 2470 | } 2471 | }, 2472 | "url-parse": { 2473 | "version": "1.4.0", 2474 | "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.0.tgz", 2475 | "integrity": "sha512-ERuGxDiQ6Xw/agN4tuoCRbmwRuZP0cJ1lJxJubXr5Q/5cDa78+Dc4wfvtxzhzhkm5VvmW6Mf8EVj9SPGN4l8Lg==", 2476 | "dev": true, 2477 | "requires": { 2478 | "querystringify": "2.0.0", 2479 | "requires-port": "1.0.0" 2480 | } 2481 | }, 2482 | "url-parse-lax": { 2483 | "version": "1.0.0", 2484 | "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", 2485 | "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", 2486 | "dev": true, 2487 | "requires": { 2488 | "prepend-http": "1.0.4" 2489 | } 2490 | }, 2491 | "url-to-options": { 2492 | "version": "1.0.1", 2493 | "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", 2494 | "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", 2495 | "dev": true 2496 | }, 2497 | "util-deprecate": { 2498 | "version": "1.0.2", 2499 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2500 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 2501 | "dev": true 2502 | }, 2503 | "uuid": { 2504 | "version": "2.0.3", 2505 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", 2506 | "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", 2507 | "dev": true 2508 | }, 2509 | "walkdir": { 2510 | "version": "0.0.11", 2511 | "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.0.11.tgz", 2512 | "integrity": "sha1-oW0CXrkxvQO1LzCMrtD0D86+lTI=", 2513 | "dev": true 2514 | }, 2515 | "whatwg-fetch": { 2516 | "version": "2.0.4", 2517 | "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", 2518 | "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==", 2519 | "dev": true 2520 | }, 2521 | "which": { 2522 | "version": "1.3.0", 2523 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", 2524 | "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", 2525 | "dev": true, 2526 | "requires": { 2527 | "isexe": "2.0.0" 2528 | } 2529 | }, 2530 | "widest-line": { 2531 | "version": "2.0.0", 2532 | "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.0.tgz", 2533 | "integrity": "sha1-AUKk6KJD+IgsAjOqDgKBqnYVInM=", 2534 | "dev": true, 2535 | "requires": { 2536 | "string-width": "2.1.1" 2537 | }, 2538 | "dependencies": { 2539 | "ansi-regex": { 2540 | "version": "3.0.0", 2541 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 2542 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 2543 | "dev": true 2544 | }, 2545 | "is-fullwidth-code-point": { 2546 | "version": "2.0.0", 2547 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 2548 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 2549 | "dev": true 2550 | }, 2551 | "string-width": { 2552 | "version": "2.1.1", 2553 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 2554 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 2555 | "dev": true, 2556 | "requires": { 2557 | "is-fullwidth-code-point": "2.0.0", 2558 | "strip-ansi": "4.0.0" 2559 | } 2560 | }, 2561 | "strip-ansi": { 2562 | "version": "4.0.0", 2563 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 2564 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 2565 | "dev": true, 2566 | "requires": { 2567 | "ansi-regex": "3.0.0" 2568 | } 2569 | } 2570 | } 2571 | }, 2572 | "wrappy": { 2573 | "version": "1.0.2", 2574 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2575 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 2576 | "dev": true 2577 | }, 2578 | "write-file-atomic": { 2579 | "version": "2.3.0", 2580 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", 2581 | "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", 2582 | "dev": true, 2583 | "requires": { 2584 | "graceful-fs": "4.1.11", 2585 | "imurmurhash": "0.1.4", 2586 | "signal-exit": "3.0.2" 2587 | } 2588 | }, 2589 | "xdg-basedir": { 2590 | "version": "3.0.0", 2591 | "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", 2592 | "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", 2593 | "dev": true 2594 | }, 2595 | "xml2js": { 2596 | "version": "0.4.17", 2597 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz", 2598 | "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=", 2599 | "dev": true, 2600 | "requires": { 2601 | "sax": "1.2.1", 2602 | "xmlbuilder": "4.2.1" 2603 | } 2604 | }, 2605 | "xmlbuilder": { 2606 | "version": "4.2.1", 2607 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz", 2608 | "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=", 2609 | "dev": true, 2610 | "requires": { 2611 | "lodash": "4.17.5" 2612 | } 2613 | }, 2614 | "xtend": { 2615 | "version": "4.0.1", 2616 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", 2617 | "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", 2618 | "dev": true 2619 | }, 2620 | "yallist": { 2621 | "version": "2.1.2", 2622 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", 2623 | "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", 2624 | "dev": true 2625 | }, 2626 | "yaml-ast-parser": { 2627 | "version": "0.0.34", 2628 | "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.34.tgz", 2629 | "integrity": "sha1-0A88+ddztyQUCa6SpnQNHbGfSeY=", 2630 | "dev": true 2631 | }, 2632 | "yargs": { 2633 | "version": "1.2.6", 2634 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.2.6.tgz", 2635 | "integrity": "sha1-nHtKgv1dWVsr8Xq23MQxNUMv40s=", 2636 | "dev": true, 2637 | "requires": { 2638 | "minimist": "0.1.0" 2639 | }, 2640 | "dependencies": { 2641 | "minimist": { 2642 | "version": "0.1.0", 2643 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz", 2644 | "integrity": "sha1-md9lelJXTCHJBXSX33QnkLK0wN4=", 2645 | "dev": true 2646 | } 2647 | } 2648 | }, 2649 | "yauzl": { 2650 | "version": "2.9.1", 2651 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", 2652 | "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=", 2653 | "dev": true, 2654 | "requires": { 2655 | "buffer-crc32": "0.2.13", 2656 | "fd-slicer": "1.0.1" 2657 | } 2658 | }, 2659 | "zen-observable-ts": { 2660 | "version": "0.4.4", 2661 | "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.4.4.tgz", 2662 | "integrity": "sha512-SNVY1sWWhoe7FwFmHpD9ERi+7Mhhj3+JdS0BGy2UxLIg7cY+3zQbyZauQCI6DN6YK4uoKNaIm3S7Qkqi1Lr+Fw==", 2663 | "dev": true 2664 | }, 2665 | "zip-local": { 2666 | "version": "0.3.4", 2667 | "resolved": "https://registry.npmjs.org/zip-local/-/zip-local-0.3.4.tgz", 2668 | "integrity": "sha1-4pMZByV6lGR56lvQ0OIK3+srWgc=", 2669 | "dev": true, 2670 | "requires": { 2671 | "async": "1.5.2", 2672 | "graceful-fs": "4.1.11", 2673 | "jszip": "2.6.1", 2674 | "q": "1.5.1" 2675 | } 2676 | }, 2677 | "zip-stream": { 2678 | "version": "1.2.0", 2679 | "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", 2680 | "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", 2681 | "dev": true, 2682 | "requires": { 2683 | "archiver-utils": "1.3.0", 2684 | "compress-commons": "1.2.2", 2685 | "lodash": "4.17.5", 2686 | "readable-stream": "2.3.6" 2687 | } 2688 | } 2689 | } 2690 | } 2691 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "realworld", 3 | "version": "1.0.0", 4 | "description": "Realworld example app serverless python implementation", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "python -m unittest api/**/tests.py --verbose --locals" 8 | }, 9 | "keywords": [ 10 | "Realworld example app", 11 | "Conduit", 12 | "AWS Lambda", 13 | "Python", 14 | "Serverless" 15 | ], 16 | "author": "gyukebox (Byeong Gyu Choi)", 17 | "license": "MIT", 18 | "devDependencies": { 19 | "serverless": "^1.26.1", 20 | "serverless-python-requirements": "^4.0.1" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ![RealWorld Example App](logo.png) 2 | 3 | > ### Serverless Python(AWS Lambda) codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the [RealWorld](https://github.com/gothinkster/realworld) spec and API. 4 | 5 | 6 | ### [Demo](https://github.com/gothinkster/realworld)    [RealWorld](https://github.com/gothinkster/realworld) 7 | 8 | 9 | This codebase was created to demonstrate a fully fledged fullstack application built with **Serverless Python** including CRUD operations, authentication, routing, pagination, and more. 10 | 11 | We've gone to great lengths to adhere to the **Serverless Python** community styleguides & best practices. 12 | 13 | For more information on how to this works with other frontends/backends, head over to the [RealWorld](https://github.com/gothinkster/realworld) repo. 14 | 15 | 16 | # How it works 17 | 18 | > Describe the general architecture of your app here 19 | 20 | (TODO draw AWS Lambda architecture and paste) 21 | 22 | # Getting started 23 | 24 | ## Installing dependencies 25 | 26 | Create and activate virtual environment. 27 | Since this implemetation uses AWS Lambda python 3.6 runtime, it is recommended to use python 3.6 28 | ``` 29 | $ pip3 install virtualenv 30 | $ python -m venv venv 31 | $ source venv/bin/activate 32 | ``` 33 | 34 | Install python dependencies via `pip`, referencing `requirements.txt` 35 | ``` 36 | (venv) $ pip install -r requirements.txt 37 | ``` 38 | 39 | Head up to `package.json` and install node dependencies via `npm` or `yarn`. Globally installing `npx` is also recommended 40 | 41 | **via npm** 42 | ``` 43 | $ npm install 44 | $ npm install -g npx 45 | ``` 46 | 47 | **via yarn** 48 | ``` 49 | $ yarn 50 | $ yarn global add npx 51 | ``` 52 | 53 | ## Invoke functions locally 54 | 55 | To trigger http events in local machine, use this command. 56 | ``` 57 | $ npx serverless invoke -f 58 | ``` 59 | 60 | You can find function names in `serverless.yml`, including list of events are responsible for, and urls. 61 | 62 | To Test functions in local environment, you can use, 63 | ``` 64 | $ npx serverless invoke local -f 65 | ``` 66 | 67 | ## Deployment 68 | 69 | You can deploy serverless functions via: 70 | ``` 71 | $ npx serverless deploy 72 | ``` 73 | 74 | This will zip up all python dependencies and code into .zip file, and, 75 | 76 | - upload artifacts in `s3` 77 | - create `CloudFormation` stack 78 | - upload lambda function and add to stack 79 | - Trigger `api gateway` event and add to stack 80 | 81 | You can also specify which stage to deploy. Stage will probably be either `dev` or `prod`. Default is `dev` -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | alembic==0.9.9 2 | certifi==2018.1.18 3 | chardet==3.0.4 4 | idna==2.6 5 | Mako==1.0.7 6 | MarkupSafe==1.0 7 | passlib==1.7.1 8 | PyJWT==1.6.1 9 | PyMySQL==0.8.0 10 | python-dateutil==2.7.2 11 | python-editor==1.0.3 12 | requests==2.18.4 13 | six==1.11.0 14 | SQLAlchemy==1.2.7 15 | SQLAlchemy-Utils==0.33.2 16 | urllib3==1.22 17 | -------------------------------------------------------------------------------- /serverless.yml: -------------------------------------------------------------------------------- 1 | # Welcome to Serverless! 2 | # 3 | # This file is the main config file for your service. 4 | # It's very minimal at this point and uses default values. 5 | # You can always add more config options for more control. 6 | # We've included some commented out config examples here. 7 | # Just uncomment any of them to get that config option. 8 | # 9 | # For full config options, check the docs: 10 | # docs.serverless.com 11 | # 12 | # Happy Coding! 13 | 14 | service: realword-serverless-python 15 | 16 | # You can pin your service to only deploy with a specific Serverless version 17 | # Check out our docs for more details 18 | # frameworkVersion: "=X.X.X" 19 | 20 | provider: 21 | name: aws 22 | runtime: python3.6 23 | 24 | # you can overwrite defaults here 25 | # stage: dev 26 | # region: us-east-1 27 | 28 | region: ap-northeast-2 29 | 30 | # you can add statements to the Lambda function's IAM Role here 31 | # iamRoleStatements: 32 | # - Effect: "Allow" 33 | # Action: 34 | # - "s3:ListBucket" 35 | # Resource: { "Fn::Join" : ["", ["arn:aws:s3:::", { "Ref" : "ServerlessDeploymentBucket" } ] ] } 36 | # - Effect: "Allow" 37 | # Action: 38 | # - "s3:PutObject" 39 | # Resource: 40 | # Fn::Join: 41 | # - "" 42 | # - - "arn:aws:s3:::" 43 | # - "Ref" : "ServerlessDeploymentBucket" 44 | # - "/*" 45 | 46 | # you can define service wide environment variables here 47 | # environment: 48 | # variable1: value1 49 | 50 | package: 51 | exclude: 52 | - node_modules/ 53 | - .gitignore 54 | - logo.png 55 | - .circleci/** 56 | 57 | # you can add packaging information here 58 | #package: 59 | # include: 60 | # - include-me.py 61 | # - include-me-dir/** 62 | # exclude: 63 | # - exclude-me.py 64 | # - exclude-me-dir/** 65 | 66 | functions: 67 | authentication: 68 | handler: api/users/handler.login 69 | events: 70 | - http: 71 | path: api/users/login 72 | method: post 73 | 74 | registration: 75 | handler: api/users/handler.register 76 | events: 77 | - http: 78 | path: api/users 79 | method: post 80 | 81 | getCurrentUser: 82 | handler: api/users/handler.get_current_user 83 | events: 84 | - http: 85 | path: api/user 86 | method: get 87 | 88 | updateUser: 89 | handler: api/users/handler.update_user 90 | events: 91 | - http: 92 | path: api/user 93 | method: put 94 | 95 | getProfile: 96 | handler: api/profiles/handler.get_profile 97 | events: 98 | - http: 99 | path: api/profiles/{username} 100 | method: get 101 | 102 | followUser: 103 | handler: api/profiles/handler.follow_user 104 | events: 105 | - http: 106 | path: api/profiles/{username}/follow 107 | method: post 108 | 109 | unfollowUser: 110 | handler: api/profiles/handler.unfollow_user 111 | events: 112 | - http: 113 | path: api/profiles/{username}/follow 114 | method: delete 115 | 116 | listArticles: 117 | handler: api/articles/handler.list_articles 118 | events: 119 | - http: 120 | path: api/articles 121 | method: get 122 | 123 | feedArticles: 124 | handler: api/articles/handler.feed_articles 125 | events: 126 | - http: 127 | path: api/articles/feed 128 | method: get 129 | 130 | getArticle: 131 | handler: api/articles/handler.get_article 132 | events: 133 | - http: 134 | path: api/articles 135 | method: get 136 | 137 | createArticle: 138 | handler: api/articles/handler.create_article 139 | events: 140 | - http: 141 | path: api/articles 142 | method: post 143 | 144 | updateArticle: 145 | handler: api/articles/handler.update_article 146 | events: 147 | - http: 148 | path: api/articles/{slug} 149 | method: put 150 | 151 | deleteArticle: 152 | handler: api/articles/handler.delete_article 153 | events: 154 | - http: 155 | path: api/articles/{slug} 156 | method: delete 157 | 158 | addComment: 159 | handler: api/articles/comments/handler.add_comment 160 | events: 161 | - http: 162 | path: api/articles/{slug}/comments 163 | method: post 164 | 165 | getComments: 166 | handler: api/articles/comments/handler.get_comments 167 | events: 168 | - http: 169 | path: api/articles/{slug}/comments 170 | method: get 171 | 172 | deleteComment: 173 | handler: api/articles/comments/handler.delete_comment 174 | events: 175 | - http: 176 | path: api/articles/{slug}/comments/{id} 177 | method: delete 178 | 179 | favoriteArticle: 180 | handler: api/articles/favorite/handler/favorite_article 181 | events: 182 | - http: 183 | path: api/articles/{slug}/favorite 184 | method: post 185 | 186 | unfavoriteArticle: 187 | handler: api/articles/favorite/handler/unfavorite_article 188 | events: 189 | - http: 190 | path: api/articles/{slug}/favorite 191 | method: delete 192 | 193 | getTags: 194 | handler: api/tags/handler.get_tags 195 | events: 196 | - http: 197 | path: api/tags 198 | method: get 199 | 200 | # The following are a few example events you can configure 201 | # NOTE: Please make sure to change your handler code to work with those events 202 | # Check the event documentation for details 203 | # events: 204 | # - http: 205 | # path: users/create 206 | # method: get 207 | # - s3: ${env:BUCKET} 208 | # - schedule: rate(10 minutes) 209 | # - sns: greeter-topic 210 | # - stream: arn:aws:dynamodb:region:XXXXXX:table/foo/stream/1970-01-01T00:00:00.000 211 | # - alexaSkill 212 | # - alexaSmartHome: amzn1.ask.skill.xx-xx-xx-xx 213 | # - iot: 214 | # sql: "SELECT * FROM 'some_topic'" 215 | # - cloudwatchEvent: 216 | # event: 217 | # source: 218 | # - "aws.ec2" 219 | # detail-type: 220 | # - "EC2 Instance State-change Notification" 221 | # detail: 222 | # state: 223 | # - pending 224 | # - cloudwatchLog: '/aws/lambda/hello' 225 | # - cognitoUserPool: 226 | # pool: MyUserPool 227 | # trigger: PreSignUp 228 | 229 | # Define function environment variables here 230 | # environment: 231 | # variable2: value2 232 | 233 | # you can add CloudFormation resource templates here 234 | #resources: 235 | # Resources: 236 | # NewResource: 237 | # Type: AWS::S3::Bucket 238 | # Properties: 239 | # BucketName: my-new-bucket 240 | # Outputs: 241 | # NewOutput: 242 | # Description: "Description for the output" 243 | # Value: "Some output value" 244 | 245 | plugins: 246 | - serverless-python-requirements 247 | 248 | custom: 249 | pythonRequirements: 250 | dockerizePip: true 251 | -------------------------------------------------------------------------------- /src/api/articles/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyworld/realworld-serverless-python/05c51cfbd6601f46245ac0c31a5b33629e114c50/src/api/articles/__init__.py -------------------------------------------------------------------------------- /src/api/articles/comments/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyworld/realworld-serverless-python/05c51cfbd6601f46245ac0c31a5b33629e114c50/src/api/articles/comments/__init__.py -------------------------------------------------------------------------------- /src/api/articles/comments/handler.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | 4 | def add_comment(event, context): 5 | pass 6 | 7 | 8 | def get_comments(event, context): 9 | pass 10 | 11 | 12 | def delete_comment(event, context): 13 | pass 14 | -------------------------------------------------------------------------------- /src/api/articles/comments/tests.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyworld/realworld-serverless-python/05c51cfbd6601f46245ac0c31a5b33629e114c50/src/api/articles/comments/tests.py -------------------------------------------------------------------------------- /src/api/articles/favorite/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyworld/realworld-serverless-python/05c51cfbd6601f46245ac0c31a5b33629e114c50/src/api/articles/favorite/__init__.py -------------------------------------------------------------------------------- /src/api/articles/favorite/handler.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | 4 | def favorite_article(event, context): 5 | pass 6 | 7 | 8 | def unfavorite_article(event, context): 9 | pass 10 | -------------------------------------------------------------------------------- /src/api/articles/favorite/tests.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyworld/realworld-serverless-python/05c51cfbd6601f46245ac0c31a5b33629e114c50/src/api/articles/favorite/tests.py -------------------------------------------------------------------------------- /src/api/articles/handler.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | 4 | def list_articles(event, context): 5 | pass 6 | 7 | 8 | def feed_articles(event, context): 9 | pass 10 | 11 | 12 | def get_article(event, context): 13 | pass 14 | 15 | 16 | def create_article(event, context): 17 | pass 18 | 19 | 20 | def update_article(event, context): 21 | pass 22 | 23 | 24 | def delete_article(event, context): 25 | pass 26 | -------------------------------------------------------------------------------- /src/api/articles/tests.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyworld/realworld-serverless-python/05c51cfbd6601f46245ac0c31a5b33629e114c50/src/api/articles/tests.py -------------------------------------------------------------------------------- /src/api/profiles/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyworld/realworld-serverless-python/05c51cfbd6601f46245ac0c31a5b33629e114c50/src/api/profiles/__init__.py -------------------------------------------------------------------------------- /src/api/profiles/handler.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | 4 | def get_profile(event, context): 5 | pass 6 | 7 | 8 | def follow_user(event, context): 9 | pass 10 | 11 | 12 | def unfollow_user(event, context): 13 | pass 14 | -------------------------------------------------------------------------------- /src/api/profiles/tests.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyworld/realworld-serverless-python/05c51cfbd6601f46245ac0c31a5b33629e114c50/src/api/profiles/tests.py -------------------------------------------------------------------------------- /src/api/tags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyworld/realworld-serverless-python/05c51cfbd6601f46245ac0c31a5b33629e114c50/src/api/tags/__init__.py -------------------------------------------------------------------------------- /src/api/tags/handler.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | 4 | def get_tags(event, context): 5 | pass 6 | -------------------------------------------------------------------------------- /src/api/tags/tests.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyworld/realworld-serverless-python/05c51cfbd6601f46245ac0c31a5b33629e114c50/src/api/tags/tests.py -------------------------------------------------------------------------------- /src/api/users/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyworld/realworld-serverless-python/05c51cfbd6601f46245ac0c31a5b33629e114c50/src/api/users/__init__.py -------------------------------------------------------------------------------- /src/api/users/handler.py: -------------------------------------------------------------------------------- 1 | import json 2 | import jwt 3 | from models.users import User 4 | 5 | 6 | def login(event, context): 7 | request_body = event['body'] 8 | response = { 9 | 'header': { 10 | 'Content-Type': 'application/json; charset=utf-8', 11 | 'Access-Control-Allow-Origin': '*' 12 | } 13 | } 14 | 15 | try: 16 | response['statusCode'] = 200 17 | response['body'] = User.__manager__.find_one_user( 18 | email=request_body['user']['email'], 19 | password=request_body['user']['password'] 20 | ) 21 | response['body']['token'] = jwt.encode( 22 | { 23 | 'email': request_body['user']['email'], 24 | 'logged_in': True, 25 | }, 26 | key='key' 27 | ) 28 | except KeyError: 29 | response['statusCode'] = 400 30 | except ValueError: 31 | response['statusCode'] = 400 32 | 33 | response['body'] = json.dumps(response['body']) 34 | return response 35 | 36 | 37 | def register(event, context): 38 | request_body = event['body'] 39 | response = { 40 | 'header': { 41 | 'Content-Type': 'application/json; charset=utf-8', 42 | 'Access-Control-Allow-Origin': '*' 43 | } 44 | } 45 | 46 | try: 47 | response['statusCode'] = 200 48 | response['body'] = User.__manager__.create_user( 49 | email=request_body['user']['email'], 50 | username=request_body['user']['username'], 51 | password=request_body['user']['password'] 52 | ) 53 | response['body']['token'] = jwt.encode( 54 | { 55 | 'email': request_body['user']['email'], 56 | 'logged_in': True, 57 | }, 58 | key='key' 59 | ) 60 | except (KeyError, ValueError): 61 | response['statusCode'] = 400 62 | 63 | response['body'] = json.dumps(response['body']) 64 | return response 65 | 66 | 67 | def get_current_user(event, context): 68 | pass 69 | 70 | 71 | def update_user(event, context): 72 | pass 73 | -------------------------------------------------------------------------------- /src/api/users/tests.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyworld/realworld-serverless-python/05c51cfbd6601f46245ac0c31a5b33629e114c50/src/api/users/tests.py -------------------------------------------------------------------------------- /src/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joeyworld/realworld-serverless-python/05c51cfbd6601f46245ac0c31a5b33629e114c50/src/models/__init__.py -------------------------------------------------------------------------------- /src/models/alembic.ini: -------------------------------------------------------------------------------- 1 | # A generic, single database configuration. 2 | 3 | [alembic] 4 | # path to migration scripts 5 | script_location = migrations 6 | 7 | # template used to generate migration files 8 | # file_template = %%(rev)s_%%(slug)s 9 | 10 | # timezone to use when rendering the date 11 | # within the migration file as well as the filename. 12 | # string value is passed to dateutil.tz.gettz() 13 | # leave blank for localtime 14 | # timezone = 15 | 16 | # max length of characters to apply to the 17 | # "slug" field 18 | #truncate_slug_length = 40 19 | 20 | # set to 'true' to run the environment during 21 | # the 'revision' command, regardless of autogenerate 22 | # revision_environment = false 23 | 24 | # set to 'true' to allow .pyc and .pyo files without 25 | # a source .py file to be detected as revisions in the 26 | # versions/ directory 27 | # sourceless = false 28 | 29 | # version location specification; this defaults 30 | # to migrations/versions. When using multiple version 31 | # directories, initial revisions must be specified with --version-path 32 | # version_locations = %(here)s/bar %(here)s/bat migrations/versions 33 | 34 | # the output encoding used when revision files 35 | # are written from script.py.mako 36 | # output_encoding = utf-8 37 | 38 | sqlalchemy.url = mysql+pymysql://$(MYSQL_USERNAME):$(MYSQL_PASSWORD)@$(MYSQL_HOST)/conduit-db 39 | 40 | 41 | # Logging configuration 42 | [loggers] 43 | keys = root,sqlalchemy,alembic 44 | 45 | [handlers] 46 | keys = console 47 | 48 | [formatters] 49 | keys = generic 50 | 51 | [logger_root] 52 | level = WARN 53 | handlers = console 54 | qualname = 55 | 56 | [logger_sqlalchemy] 57 | level = WARN 58 | handlers = 59 | qualname = sqlalchemy.engine 60 | 61 | [logger_alembic] 62 | level = INFO 63 | handlers = 64 | qualname = alembic 65 | 66 | [handler_console] 67 | class = StreamHandler 68 | args = (sys.stderr,) 69 | level = NOTSET 70 | formatter = generic 71 | 72 | [formatter_generic] 73 | format = %(levelname)-5.5s [%(name)s] %(message)s 74 | datefmt = %H:%M:%S 75 | -------------------------------------------------------------------------------- /src/models/articles.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | import sqlalchemy as sa 3 | import sqlalchemy_utils as sau 4 | from sqlalchemy.orm import relationship 5 | from models.associations import \ 6 | profiles_articles_relationship_table, articles_tags_relationship_table 7 | from models.database import Base, Session 8 | 9 | 10 | class ArticleManager(object): 11 | """ 12 | Manager class for model Article 13 | """ 14 | 15 | def __init__(self): 16 | self.session = Session() 17 | 18 | pass 19 | 20 | 21 | class Article(Base, sau.Timestamp): 22 | """ 23 | Article model class 24 | """ 25 | __tablename__ = 'conduit_api_article' 26 | 27 | # base fields 28 | uuid = sa.Column( 29 | 'uuid', 30 | sau.UUIDType(binary=False), 31 | primary_key=True, 32 | nullable=False, 33 | unique=True, 34 | default=uuid.uuid4 35 | ) 36 | title = sa.Column( 37 | 'title', 38 | sa.String(100), 39 | nullable=False 40 | ) 41 | slug = sa.Column( 42 | 'slug', 43 | sa.String(100), 44 | nullable=False 45 | ) 46 | description = sa.Column( 47 | 'description', 48 | sa.String(300), 49 | nullable=False 50 | ) 51 | body = sa.Column( 52 | 'body', 53 | sa.Text, 54 | nullable=False 55 | ) 56 | 57 | author_id = sa.Column( 58 | 'author-id', 59 | sau.UUIDType(binary=False), 60 | sa.ForeignKey('conduit_api_profile.user-id'), 61 | nullable=False, 62 | primary_key=False, 63 | unique=True 64 | ) 65 | 66 | # relationship fields 67 | author = relationship('Profile', back_populates='conduit_api_profile') 68 | favorited_user = relationship( 69 | 'Profile', 70 | secondary=profiles_articles_relationship_table, 71 | back_populates='conduit_api_articles' 72 | ) 73 | tags = relationship( 74 | 'Article', 75 | secondary=articles_tags_relationship_table, 76 | back_populates='conduit_api_tags' 77 | ) 78 | 79 | __manager__ = ArticleManager() 80 | 81 | def __repr__(self): 82 | pass 83 | 84 | def __str__(self): 85 | return 'Conduit API Article Model' 86 | 87 | def serialize(self): 88 | pass 89 | -------------------------------------------------------------------------------- /src/models/associations.py: -------------------------------------------------------------------------------- 1 | """ 2 | defines many-to-many relationship tables 3 | """ 4 | import sqlalchemy as sa 5 | import sqlalchemy_utils as sau 6 | from models.database import Base 7 | 8 | profiles_relationship_table = sa.Table( 9 | 'profile-profile-association', 10 | Base.metadata, 11 | sa.Column( 12 | 'first-person-profile', 13 | sau.UUIDType(binary=False), 14 | sa.ForeignKey('conduit_api_profile.user-id') 15 | ), 16 | sa.Column( 17 | 'second-person-profile', 18 | sau.UUIDType(binary=False), 19 | sa.ForeignKey('conduit_api_profile.user-id') 20 | ) 21 | ) 22 | 23 | profiles_articles_relationship_table = sa.Table( 24 | 'profile-article-association', 25 | Base.metadata, 26 | sa.Column( 27 | 'profile-id', 28 | sau.UUIDType(binary=False), 29 | sa.ForeignKey('conduit_api_profile.user-id') 30 | ), 31 | sa.Column( 32 | 'article-id', 33 | sau.UUIDType(binary=False), 34 | sa.ForeignKey('conduit_api_article.uuid') 35 | ) 36 | ) 37 | 38 | articles_comments_relationship_table = sa.Table( 39 | 'article-comment-association', 40 | Base.metadata, 41 | sa.Column( 42 | 'article-id', 43 | sau.UUIDType(binary=False), 44 | sa.ForeignKey('conduit_api_article.uuid'), 45 | ), 46 | sa.Column( 47 | 'comment-id', 48 | sa.Integer, 49 | sa.ForeignKey('conduit_api_comment.id') 50 | ) 51 | ) 52 | 53 | articles_tags_relationship_table = sa.Table( 54 | 'article-tag-association', 55 | Base.metadata, 56 | sa.Column( 57 | 'article-id', 58 | sau.UUIDType(binary=False), 59 | sa.ForeignKey('conduit_api_article.uuid') 60 | ), 61 | sa.Column( 62 | 'tag-id', 63 | sa.Integer, 64 | sa.ForeignKey('conduit_api_tag.id') 65 | ) 66 | ) 67 | -------------------------------------------------------------------------------- /src/models/comments.py: -------------------------------------------------------------------------------- 1 | import sqlalchemy as sa 2 | import sqlalchemy_utils as sau 3 | from sqlalchemy.orm import relationship 4 | 5 | from associations import articles_comments_relationship_table 6 | from models.database import Base, Session 7 | 8 | 9 | class CommentManager(object): 10 | """ 11 | Manager class for model Comment 12 | """ 13 | 14 | def __init__(self): 15 | self.session = Session() 16 | 17 | pass 18 | 19 | 20 | class Comment(Base, sau.Timestamp): 21 | """ 22 | Comment model class 23 | """ 24 | __tablename__ = 'conduit_api_comment' 25 | 26 | # base fields 27 | id = sa.Column( 28 | 'id', 29 | sa.Integer, 30 | autoincrement=True, 31 | primary_key=True, 32 | nullable=False, 33 | unique=True 34 | ) 35 | body = sa.Column( 36 | 'body', 37 | sa.String(100), 38 | nullable=False 39 | ) 40 | 41 | author_id = sa.Column( 42 | 'author-id', 43 | sau.UUIDType(binary=False), 44 | sa.ForeignKey('conduit_api_profile.user-id'), 45 | nullable=False 46 | ) 47 | article_id = sa.Column( 48 | 'article-id', 49 | sau.UUIDType(binary=False), 50 | sa.ForeignKey('conduit_api_article.uuid'), 51 | nullable=False 52 | ) 53 | 54 | # relationship fields 55 | author = relationship('Profile', back_populates='conduit_api_profile') 56 | article = relationship( 57 | 'Article', 58 | secondary=articles_comments_relationship_table, 59 | back_populates='conduit_api_article' 60 | ) 61 | 62 | __manager__ = CommentManager() 63 | 64 | def __repr__(self): 65 | pass 66 | 67 | def __str__(self): 68 | return 'Conduit API Comment Model' 69 | 70 | def serialize(self): 71 | pass 72 | -------------------------------------------------------------------------------- /src/models/database.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from sqlalchemy import create_engine 4 | from sqlalchemy.ext.declarative import declarative_base 5 | from sqlalchemy.orm import sessionmaker 6 | from sqlalchemy_utils import force_auto_coercion 7 | 8 | MYSQL_USERNAME = os.environ['MYSQL_USERNAME'] 9 | MYSQL_PASSWORD = os.environ['MYSQL_PASSWORD'] 10 | MYSQL_HOST = os.environ['MYSQL_HOST'] 11 | 12 | db_url = 'mysql+pymysql://{}:{}@{}/conduit_db'\ 13 | .format(MYSQL_USERNAME, MYSQL_PASSWORD, MYSQL_HOST) 14 | engine = create_engine(db_url, echo=True) 15 | Base = declarative_base() 16 | force_auto_coercion() 17 | Session = sessionmaker(bind=engine, autoflush=True) 18 | -------------------------------------------------------------------------------- /src/models/migrations/README: -------------------------------------------------------------------------------- 1 | Generic single-database configuration. -------------------------------------------------------------------------------- /src/models/migrations/env.py: -------------------------------------------------------------------------------- 1 | from __future__ import with_statement 2 | from alembic import context 3 | from sqlalchemy import engine_from_config, pool 4 | from logging.config import fileConfig 5 | 6 | # this is the Alembic Config object, which provides 7 | # access to the values within the .ini file in use. 8 | config = context.config 9 | 10 | # Interpret the config file for Python logging. 11 | # This line sets up loggers basically. 12 | fileConfig(config.config_file_name) 13 | 14 | # add your model's MetaData object here 15 | # for 'autogenerate' support 16 | # from myapp import mymodel 17 | # target_metadata = mymodel.Base.metadata 18 | target_metadata = None 19 | 20 | # other values from the config, defined by the needs of env.py, 21 | # can be acquired: 22 | # my_important_option = config.get_main_option("my_important_option") 23 | # ... etc. 24 | 25 | 26 | def run_migrations_offline(): 27 | """Run migrations in 'offline' mode. 28 | 29 | This configures the context with just a URL 30 | and not an Engine, though an Engine is acceptable 31 | here as well. By skipping the Engine creation 32 | we don't even need a DBAPI to be available. 33 | 34 | Calls to context.execute() here emit the given string to the 35 | script output. 36 | 37 | """ 38 | url = config.get_main_option("sqlalchemy.url") 39 | context.configure( 40 | url=url, target_metadata=target_metadata, literal_binds=True) 41 | 42 | with context.begin_transaction(): 43 | context.run_migrations() 44 | 45 | 46 | def run_migrations_online(): 47 | """Run migrations in 'online' mode. 48 | 49 | In this scenario we need to create an Engine 50 | and associate a connection with the context. 51 | 52 | """ 53 | connectable = engine_from_config( 54 | config.get_section(config.config_ini_section), 55 | prefix='sqlalchemy.', 56 | poolclass=pool.NullPool) 57 | 58 | with connectable.connect() as connection: 59 | context.configure( 60 | connection=connection, 61 | target_metadata=target_metadata 62 | ) 63 | 64 | with context.begin_transaction(): 65 | context.run_migrations() 66 | 67 | 68 | if context.is_offline_mode(): 69 | run_migrations_offline() 70 | else: 71 | run_migrations_online() 72 | -------------------------------------------------------------------------------- /src/models/migrations/script.py.mako: -------------------------------------------------------------------------------- 1 | """${message} 2 | 3 | Revision ID: ${up_revision} 4 | Revises: ${down_revision | comma,n} 5 | Create Date: ${create_date} 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | ${imports if imports else ""} 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = ${repr(up_revision)} 14 | down_revision = ${repr(down_revision)} 15 | branch_labels = ${repr(branch_labels)} 16 | depends_on = ${repr(depends_on)} 17 | 18 | 19 | def upgrade(): 20 | ${upgrades if upgrades else "pass"} 21 | 22 | 23 | def downgrade(): 24 | ${downgrades if downgrades else "pass"} 25 | -------------------------------------------------------------------------------- /src/models/migrations/versions/060c71f40c75_create_user_table.py: -------------------------------------------------------------------------------- 1 | """Create user table 2 | 3 | Revision ID: 060c71f40c75 4 | Revises: 5 | Create Date: 2018-04-27 05:10:59.366909 6 | 7 | """ 8 | import uuid 9 | 10 | from alembic import op 11 | import sqlalchemy as sa 12 | 13 | 14 | # revision identifiers, used by Alembic. 15 | from sqlalchemy_utils import UUIDType, URLType, PasswordType, EmailType 16 | 17 | revision = '060c71f40c75' 18 | down_revision = None 19 | branch_labels = None 20 | depends_on = None 21 | 22 | 23 | def upgrade(): 24 | op.create_table( 25 | 'conduit_api_user', 26 | sa.Column( 27 | 'uuid', 28 | UUIDType(binary=False), 29 | primary_key=True, 30 | nullable=False, 31 | unique=True, 32 | default=uuid.uuid4() 33 | ), 34 | sa.Column( 35 | 'email', 36 | EmailType, 37 | nullable=False, 38 | unique=True, 39 | ), 40 | sa.Column( 41 | 'username', 42 | sa.String(20), 43 | nullable=False 44 | ), 45 | sa.Column( 46 | 'password', 47 | PasswordType( 48 | schemes=[ 49 | 'pbkdf2_sha512', 50 | ], 51 | ), 52 | nullable=False 53 | ), 54 | sa. Column( 55 | 'bio', 56 | sa.String(100), 57 | nullable=True 58 | ), 59 | sa.Column( 60 | 'image', 61 | URLType, 62 | nullable=True 63 | ), 64 | ) 65 | 66 | 67 | def downgrade(): 68 | op.drop_table('conduit_api_user') 69 | -------------------------------------------------------------------------------- /src/models/migrations/versions/187ee66c9910_create_article_comment_relationship.py: -------------------------------------------------------------------------------- 1 | """Create article-comment relationship 2 | 3 | Revision ID: 187ee66c9910 4 | Revises: ce5457ef45d6 5 | Create Date: 2018-05-12 05:11:52.940730 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | import sqlalchemy_utils as sau 11 | 12 | 13 | # revision identifiers, used by Alembic. 14 | revision = '187ee66c9910' 15 | down_revision = 'ce5457ef45d6' 16 | branch_labels = None 17 | depends_on = None 18 | 19 | 20 | def upgrade(): 21 | op.create_table( 22 | 'article-comment-association', 23 | sa.Column( 24 | 'article-id', 25 | sau.UUIDType(binary=False), 26 | sa.ForeignKey('conduit_api_article.uuid'), 27 | ), 28 | sa.Column( 29 | 'comment-id', 30 | sa.Integer, 31 | sa.ForeignKey('conduit_api_comment.id') 32 | ) 33 | ) 34 | 35 | 36 | def downgrade(): 37 | op.drop_table('article-comment-association') 38 | -------------------------------------------------------------------------------- /src/models/migrations/versions/586ff0a55152_create_profile_table.py: -------------------------------------------------------------------------------- 1 | """Create profile table 2 | 3 | Revision ID: 586ff0a55152 4 | Revises: 060c71f40c75 5 | Create Date: 2018-05-12 03:39:41.737116 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | import sqlalchemy_utils as sau 11 | 12 | 13 | # revision identifiers, used by Alembic. 14 | revision = '586ff0a55152' 15 | down_revision = '060c71f40c75' 16 | branch_labels = None 17 | depends_on = None 18 | 19 | 20 | def upgrade(): 21 | op.create_table( 22 | 'conduit_api_profile', 23 | sa.Column( 24 | 'user-id', 25 | sau.UUIDType(binary=False), 26 | sa.ForeignKey('conduit_api_user.uuid'), 27 | nullable=False, 28 | ) 29 | ) 30 | 31 | 32 | def downgrade(): 33 | op.drop_table('conduit_api_profile') 34 | -------------------------------------------------------------------------------- /src/models/migrations/versions/6cd1ecc66c36_create_profile_profile_relationship.py: -------------------------------------------------------------------------------- 1 | """Create profile-profile relationship 2 | 3 | Revision ID: 6cd1ecc66c36 4 | Revises: 738a04ab8395 5 | Create Date: 2018-05-12 04:55:21.538463 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | import sqlalchemy_utils as sau 11 | 12 | 13 | # revision identifiers, used by Alembic. 14 | revision = '6cd1ecc66c36' 15 | down_revision = '738a04ab8395' 16 | branch_labels = None 17 | depends_on = None 18 | 19 | 20 | def upgrade(): 21 | op.create_table( 22 | 'profile-profile-association', 23 | sa.Column( 24 | 'first-person-profile', 25 | sau.UUIDType(binary=False), 26 | sa.ForeignKey('conduit_api_profile.user-id') 27 | ), 28 | sa.Column( 29 | 'second-person-profile', 30 | sau.UUIDType(binary=False), 31 | sa.ForeignKey('conduit_api_profile.user-id') 32 | ) 33 | ) 34 | 35 | 36 | def downgrade(): 37 | op.drop_table('profile-profile-association') 38 | -------------------------------------------------------------------------------- /src/models/migrations/versions/738a04ab8395_create_tag_table.py: -------------------------------------------------------------------------------- 1 | """Create tag table 2 | 3 | Revision ID: 738a04ab8395 4 | Revises: 98b2c43d2dbe 5 | Create Date: 2018-05-12 04:51:35.079263 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = '738a04ab8395' 14 | down_revision = '98b2c43d2dbe' 15 | branch_labels = None 16 | depends_on = None 17 | 18 | 19 | def upgrade(): 20 | op.create_table( 21 | 'conduit_api_tag', 22 | sa.Column( 23 | 'id', 24 | sa.Integer, 25 | autoincrement=True, 26 | primary_key=True, 27 | unique=True, 28 | nullable=False 29 | ), 30 | sa.Column( 31 | 'body', 32 | sa.String(20), 33 | nullable=False 34 | ) 35 | ) 36 | 37 | 38 | def downgrade(): 39 | op.drop_table('conduit_api_tag') 40 | -------------------------------------------------------------------------------- /src/models/migrations/versions/98b2c43d2dbe_create_comment_table.py: -------------------------------------------------------------------------------- 1 | """Create comment table 2 | 3 | Revision ID: 98b2c43d2dbe 4 | Revises: f5ef6affc65c 5 | Create Date: 2018-05-12 04:47:36.778387 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | import sqlalchemy_utils as sau 11 | 12 | 13 | # revision identifiers, used by Alembic. 14 | revision = '98b2c43d2dbe' 15 | down_revision = 'f5ef6affc65c' 16 | branch_labels = None 17 | depends_on = None 18 | 19 | 20 | def upgrade(): 21 | op.create_table( 22 | 'conduit_api_comment', 23 | sa.Column( 24 | 'id', 25 | sa.Integer, 26 | autoincrement=True, 27 | primary_key=True, 28 | nullable=False, 29 | unique=True 30 | ), 31 | sa.Column( 32 | 'body', 33 | sa.String(100), 34 | nullable=False 35 | ), 36 | sa.Column( 37 | 'author-id', 38 | sau.UUIDType(binary=False), 39 | sa.ForeignKey('conduit_api_profile.user-id'), 40 | nullable=False 41 | ), 42 | sa.Column( 43 | 'article-id', 44 | sau.UUIDType(binary=False), 45 | sa.ForeignKey('conduit_api_article.uuid'), 46 | nullable=False 47 | ) 48 | ) 49 | 50 | 51 | def downgrade(): 52 | op.drop_table('conduit_api_comment') 53 | -------------------------------------------------------------------------------- /src/models/migrations/versions/b3711b2a949c_create_article_tag_relationship.py: -------------------------------------------------------------------------------- 1 | """Create article-tag relationship 2 | 3 | Revision ID: b3711b2a949c 4 | Revises: 187ee66c9910 5 | Create Date: 2018-05-12 05:16:44.580529 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | import sqlalchemy_utils as sau 11 | 12 | 13 | # revision identifiers, used by Alembic. 14 | revision = 'b3711b2a949c' 15 | down_revision = '187ee66c9910' 16 | branch_labels = None 17 | depends_on = None 18 | 19 | 20 | def upgrade(): 21 | op.create_table( 22 | 'article-tag-association', 23 | sa.Column( 24 | 'article-id', 25 | sau.UUIDType(binary=False), 26 | sa.ForeignKey('conduit_api_article.uuid') 27 | ), 28 | sa.Column( 29 | 'tag-id', 30 | sa.Integer, 31 | sa.ForeignKey('conduit_api_tag.id') 32 | ) 33 | ) 34 | 35 | 36 | def downgrade(): 37 | op.drop_table('article-tag-association') 38 | -------------------------------------------------------------------------------- /src/models/migrations/versions/ce5457ef45d6_create_profile_article_relationship.py: -------------------------------------------------------------------------------- 1 | """Create profile-article relationship 2 | 3 | Revision ID: ce5457ef45d6 4 | Revises: 6cd1ecc66c36 5 | Create Date: 2018-05-12 04:59:18.521528 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | import sqlalchemy_utils as sau 11 | 12 | 13 | # revision identifiers, used by Alembic. 14 | revision = 'ce5457ef45d6' 15 | down_revision = '6cd1ecc66c36' 16 | branch_labels = None 17 | depends_on = None 18 | 19 | 20 | def upgrade(): 21 | op.create_table( 22 | 'profile-article-association', 23 | sa.Column( 24 | 'profile-id', 25 | sau.UUIDType(binary=False), 26 | sa.ForeignKey('conduit_api_profile.user-id') 27 | ), 28 | sa.Column( 29 | 'article-id', 30 | sau.UUIDType(binary=False), 31 | sa.ForeignKey('conduit_api_article.uuid') 32 | ) 33 | ) 34 | 35 | 36 | def downgrade(): 37 | op.drop_table('profile-article-association') 38 | -------------------------------------------------------------------------------- /src/models/migrations/versions/f5ef6affc65c_create_article_table.py: -------------------------------------------------------------------------------- 1 | """Create article table 2 | 3 | Revision ID: f5ef6affc65c 4 | Revises: 586ff0a55152 5 | Create Date: 2018-05-12 04:42:27.751231 6 | 7 | """ 8 | import uuid 9 | 10 | from alembic import op 11 | import sqlalchemy as sa 12 | import sqlalchemy_utils as sau 13 | 14 | 15 | # revision identifiers, used by Alembic. 16 | revision = 'f5ef6affc65c' 17 | down_revision = '586ff0a55152' 18 | branch_labels = None 19 | depends_on = None 20 | 21 | 22 | def upgrade(): 23 | op.create_table( 24 | 'conduit_api_article', 25 | sa.Column( 26 | 'uuid', 27 | sau.UUIDType(binary=False), 28 | primary_key=True, 29 | nullable=False, 30 | unique=True, 31 | default=uuid.uuid4 32 | ), 33 | sa.Column( 34 | 'title', 35 | sa.String(100), 36 | nullable=False 37 | ), 38 | sa.Column( 39 | 'slug', 40 | sa.String(100), 41 | nullable=False 42 | ), 43 | sa.Column( 44 | 'description', 45 | sa.String(300), 46 | nullable=False 47 | ), 48 | sa.Column( 49 | 'body', 50 | sa.Text, 51 | nullable=False 52 | ), 53 | sa.Column( 54 | 'author-id', 55 | sau.UUIDType(binary=False), 56 | sa.ForeignKey('conduit_api_profile.user-id'), 57 | nullable=False, 58 | primary_key=False, 59 | unique=True 60 | ), 61 | ) 62 | 63 | 64 | def downgrade(): 65 | op.drop_table('conduit_api_article') 66 | -------------------------------------------------------------------------------- /src/models/profiles.py: -------------------------------------------------------------------------------- 1 | import sqlalchemy as sa 2 | import sqlalchemy_utils as sau 3 | from sqlalchemy.orm import relationship 4 | from models.database import Base, Session 5 | from models.associations import \ 6 | profiles_articles_relationship_table, profiles_relationship_table 7 | 8 | 9 | class ProfileManager(object): 10 | """ 11 | Manager class for model Profile 12 | """ 13 | def __init__(self): 14 | self.session = Session() 15 | 16 | pass 17 | 18 | 19 | class Profile(Base, sau.Timestamp): 20 | """ 21 | Profile model class 22 | """ 23 | __tablename__ = 'conduit_api_profile' 24 | 25 | # base fields 26 | user_id = sa.Column( 27 | 'user-id', 28 | sau.UUIDType(binary=False), 29 | sa.ForeignKey('conduit_api_user.uuid'), 30 | nullable=False, 31 | primary_key=True, 32 | unique=True 33 | ) 34 | 35 | # relationship fields 36 | user = relationship('User', back_populates='conduit_api_user') 37 | followers = relationship( 38 | 'Profile', 39 | secondary=profiles_relationship_table, 40 | back_populates='conduit_api_profiles' 41 | ) 42 | favorite_articles = relationship( 43 | 'Article', 44 | secondary=profiles_articles_relationship_table, 45 | back_populates='conduit_api_articles' 46 | ) 47 | written_articles = relationship('Article', back_populates='conduit_api_articles') 48 | 49 | __manager__ = ProfileManager() 50 | 51 | def __repr__(self): 52 | pass 53 | 54 | def __str__(self): 55 | return 'Conduit API Profile Model' 56 | 57 | def serialize(self): 58 | """ 59 | returns JSON-serialized format of Model 60 | """ 61 | pass 62 | -------------------------------------------------------------------------------- /src/models/tags.py: -------------------------------------------------------------------------------- 1 | import sqlalchemy as sa 2 | from sqlalchemy.orm import relationship 3 | from models.associations import articles_tags_relationship_table 4 | from models.database import Base, Session 5 | 6 | 7 | class TagManager(object): 8 | """ 9 | Manager class for model Tag 10 | """ 11 | def __init__(self): 12 | self.session = Session() 13 | 14 | pass 15 | 16 | 17 | class Tag(Base): 18 | """ 19 | Tag model class 20 | """ 21 | __tablename__ = 'conduit_api_tag' 22 | 23 | # base fields 24 | id = sa.Column( 25 | 'id', 26 | sa.Integer, 27 | autoincrement=True, 28 | primary_key=True, 29 | unique=True, 30 | nullable=False 31 | ) 32 | body = sa.Column( 33 | 'body', 34 | sa.String(20), 35 | nullable=False 36 | ) 37 | 38 | # relationship fields 39 | articles = relationship( 40 | 'Article', 41 | secondary=articles_tags_relationship_table, 42 | back_populates='conduit_api_articles' 43 | ) 44 | 45 | __manager__ = TagManager() 46 | 47 | def __repr__(self): 48 | pass 49 | 50 | def __str__(self): 51 | return 'Conduit API Tag model' 52 | 53 | def serialize(self): 54 | pass 55 | -------------------------------------------------------------------------------- /src/models/users.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | import sqlalchemy as sa 3 | import sqlalchemy_utils as sau 4 | from sqlalchemy.orm import relationship 5 | from src.models.database import Base, Session 6 | 7 | 8 | class UserManager(object): 9 | def __init__(self): 10 | self.session = Session() 11 | 12 | def create_user(self, username, email, password, **kwargs): 13 | if not username: 14 | raise ValueError('Field {username} cannot be null') 15 | if not email: 16 | raise ValueError('Field {email} cannot be null') 17 | if not password: 18 | raise ValueError('Field {password} cannot be null') 19 | 20 | new_user = User( 21 | username=username, 22 | email=email, 23 | password=password, 24 | bio=kwargs['bio'] if 'bio' in kwargs else None, 25 | image=kwargs['image'] if 'image' in kwargs else None 26 | ) 27 | 28 | self.session.add(new_user) 29 | self.session.commit() 30 | return new_user.serialize() 31 | 32 | def find_one_user(self, email, password): 33 | if not email or not password: 34 | raise ValueError('Both email and password must be provided') 35 | 36 | user = self.session.query(User).filter(User.email == email).one() 37 | assert user.password == password 38 | return user.serialize() 39 | 40 | 41 | class User(Base, sau.Timestamp): 42 | __tablename__ = 'conduit_api_user' 43 | 44 | # base fields 45 | uuid = sa.Column( 46 | 'uuid', 47 | sau.UUIDType(binary=False), 48 | primary_key=True, 49 | nullable=False, 50 | unique=True, 51 | default=uuid.uuid4() 52 | ) 53 | email = sa.Column( 54 | 'email', 55 | sau.EmailType, 56 | nullable=False, 57 | unique=True, 58 | ) 59 | username = sa.Column( 60 | 'username', 61 | sa.String(20), 62 | nullable=False 63 | ) 64 | password = sa.Column( 65 | 'password', 66 | sau.PasswordType( 67 | schemes=[ 68 | 'pbkdf2_sha512', 69 | ], 70 | ), 71 | nullable=False 72 | ) 73 | bio = sa.Column( 74 | 'bio', 75 | sa.String(100), 76 | nullable=True 77 | ) 78 | image = sa.Column( 79 | 'image', 80 | sau.URLType, 81 | nullable=True 82 | ) 83 | 84 | # relationship fields 85 | profile = relationship( 86 | 'Profile', 87 | uselist=False, 88 | back_populates='conduit_api_profile' 89 | ) 90 | 91 | __manager__ = UserManager() 92 | 93 | def __repr__(self): 94 | return ''.format(self.email, self.username) 95 | 96 | def __str__(self): 97 | return 'Conduit API User Model' 98 | 99 | def serialize(self): 100 | """ 101 | returns JSON-serialized format of Model 102 | """ 103 | return { 104 | 'email': self.email, 105 | 'username': self.username, 106 | 'bio': self.bio, 107 | 'image': self.image 108 | } 109 | --------------------------------------------------------------------------------