├── .eslintrc.yaml ├── .gitignore ├── .prettierrc.yml ├── .vscode └── settings.json ├── README.md ├── docker-compose.yml ├── jest.config.js ├── package-lock.json ├── package.json ├── renovate.json ├── src ├── abstraction-polymorph │ ├── abstracting-file-service.ts │ ├── abstraction-polymorph.ts │ ├── minio-test.ts │ ├── naive-version.ts │ └── shared.ts ├── basic-of-class │ ├── abstract-class.ts │ ├── access-levels.ts │ ├── class-and-object.ts │ ├── class-is-prototyping.ts │ ├── extends.ts │ ├── interface.ts │ ├── readline.ts │ ├── static-method.ts │ ├── subclass-superclass.ts │ └── super.ts ├── encapsulation │ ├── card.ts │ ├── hand.test.ts │ ├── hand.ts │ ├── handPower.test.ts │ ├── handPower.ts │ ├── main.ts │ └── utils │ │ └── patternMatcher.ts └── inheritance │ ├── composition-over-inheritance.ts │ ├── if-moving.ts │ ├── inheritance-2.ts │ └── inheritance.ts ├── tsconfig.json └── yarn.lock /.eslintrc.yaml: -------------------------------------------------------------------------------- 1 | env: 2 | node: true 3 | extends: 4 | - plugin:@typescript-eslint/recommended 5 | - prettier/@typescript-eslint 6 | - plugin:prettier/recommended 7 | parser: '@typescript-eslint/parser' 8 | parserOptions: 9 | ecmaVersion: 9 10 | project: ./tsconfig.json 11 | plugins: 12 | - '@typescript-eslint' 13 | rules: 14 | semi: 15 | - error 16 | - never -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Intellijn 2 | .idea 3 | 4 | # Logs 5 | logs 6 | *.log 7 | npm-debug.log* 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | 12 | # Diagnostic reports (https://nodejs.org/api/report.html) 13 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 14 | 15 | # Runtime data 16 | pids 17 | *.pid 18 | *.seed 19 | *.pid.lock 20 | 21 | # Directory for instrumented libs generated by jscoverage/JSCover 22 | lib-cov 23 | 24 | # Coverage directory used by tools like istanbul 25 | coverage 26 | *.lcov 27 | 28 | # nyc test coverage 29 | .nyc_output 30 | 31 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 32 | .grunt 33 | 34 | # Bower dependency directory (https://bower.io/) 35 | bower_components 36 | 37 | # node-waf configuration 38 | .lock-wscript 39 | 40 | # Compiled binary addons (https://nodejs.org/api/addons.html) 41 | build/Release 42 | 43 | # Dependency directories 44 | node_modules/ 45 | jspm_packages/ 46 | 47 | # Snowpack dependency directory (https://snowpack.dev/) 48 | web_modules/ 49 | 50 | # TypeScript cache 51 | *.tsbuildinfo 52 | 53 | # Optional npm cache directory 54 | .npm 55 | 56 | # Optional eslint cache 57 | .eslintcache 58 | 59 | # Microbundle cache 60 | .rpt2_cache/ 61 | .rts2_cache_cjs/ 62 | .rts2_cache_es/ 63 | .rts2_cache_umd/ 64 | 65 | # Optional REPL history 66 | .node_repl_history 67 | 68 | # Output of 'npm pack' 69 | *.tgz 70 | 71 | # Yarn Integrity file 72 | .yarn-integrity 73 | 74 | # dotenv environment variables file 75 | .env 76 | .env.test 77 | 78 | # parcel-bundler cache (https://parceljs.org/) 79 | .cache 80 | .parcel-cache 81 | 82 | # Next.js build output 83 | .next 84 | out 85 | 86 | # Nuxt.js build / generate output 87 | .nuxt 88 | dist 89 | 90 | # Gatsby files 91 | .cache/ 92 | # Comment in the public line in if your project uses Gatsby and not Next.js 93 | # https://nextjs.org/blog/next-9-1#public-directory-support 94 | # public 95 | 96 | # vuepress build output 97 | .vuepress/dist 98 | 99 | # Serverless directories 100 | .serverless/ 101 | 102 | # FuseBox cache 103 | .fusebox/ 104 | 105 | # DynamoDB Local files 106 | .dynamodb/ 107 | 108 | # TernJS port file 109 | .tern-port 110 | 111 | # Stores VSCode versions used for testing VSCode extensions 112 | .vscode-test 113 | 114 | # yarn v2 115 | .yarn/cache 116 | .yarn/unplugged 117 | .yarn/build-state.yml 118 | .yarn/install-state.gz 119 | .pnp.* 120 | -------------------------------------------------------------------------------- /.prettierrc.yml: -------------------------------------------------------------------------------- 1 | tabWidth: 2 2 | singleQuote: true 3 | semi: false 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": false 3 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TS-OOP 2 | 3 | ใช้สำหรับประกอบการเรียนการสอน คอร์ส OOP The right way 4 | 5 | Learning Material for OOP The right way class. 6 | 7 | Disclaimer: We refined this codebase. Some code, filename and structure might have some difference with the original learning content. 8 | 9 | ## How to use 10 | 11 | โค้ดส่วนมากใน Repository นี้ใช้ประกอบการสอน สามารถอ่านเป็นตัวอย่างหรือลอกไปเป็นต้นแบบในงานจริงได้ 12 | 13 | โค้ดบางส่วนที่สามารถรันเพื่อทดลองเล่นได้ 14 | 15 | ## Dependencies 16 | 17 | ติดตั้ง dependencies โดยใช้ [Yarn](https://yarnpkg.com/) 18 | ``` 19 | yarn 20 | ``` 21 | 22 | ส่วนที่รันได้จะมีสองส่วน 23 | 24 | ### Encapsulation 25 | 26 | โค้ด Encapsulation สามารถรันเทสได้ 27 | 28 | ``` 29 | yarn test 30 | ``` 31 | 32 | รันไฟล์ test สำหรับบทเรียน Encapsulation 33 | 34 | ### Minio 35 | 36 | ในส่วนของบทเรียน Abstraction-Polymorph มีการใช้งาน Minio เป็นระบบจัดเก็บไฟล์ สามารถรันขึ้นมาได้ด้วยคำสั่ง 37 | 38 | ``` 39 | docker-compose up -d 40 | ``` 41 | 42 | และสามารถทดสอบว่า Minio ทำงานถูกต้องหรือไม่ได้โดย 43 | 44 | ``` 45 | yarn script ./src/abstraction-polymorph/minio-test.ts 46 | ``` 47 | 48 | ถ้าการติดตั้งสำเร็จ ระบบจะแสดงคำว่า Minio tested! -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | # starts 4 docker containers running minio server instances. 4 | # using nginx reverse proxy, load balancing, you can access 5 | # it through port 9000. 6 | services: 7 | minio: 8 | image: minio/minio 9 | volumes: 10 | - data 11 | ports: 12 | - '9000:9000' 13 | expose: 14 | - '9000' 15 | environment: 16 | MINIO_ROOT_USER: minio 17 | MINIO_ROOT_PASSWORD: minio123 18 | command: server /data 19 | volumes: 20 | data: {} 21 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | }; -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-eslint-prettier-starter", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.10.3", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.3.tgz", 10 | "integrity": "sha512-fDx9eNW0qz0WkUeqL6tXEXzVlPh6Y5aCDEZesl0xBGA8ndRukX91Uk44ZqnkECp01NAZUdCAl+aiQNGi0k88Eg==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.10.3" 14 | } 15 | }, 16 | "@babel/helper-validator-identifier": { 17 | "version": "7.10.3", 18 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.3.tgz", 19 | "integrity": "sha512-bU8JvtlYpJSBPuj1VUmKpFGaDZuLxASky3LhaKj3bmpSTY6VWooSM8msk+Z0CZoErFye2tlABF6yDkT3FOPAXw==", 20 | "dev": true 21 | }, 22 | "@babel/highlight": { 23 | "version": "7.10.3", 24 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.3.tgz", 25 | "integrity": "sha512-Ih9B/u7AtgEnySE2L2F0Xm0GaM729XqqLfHkalTsbjXGyqmf/6M0Cu0WpvqueUlW+xk88BHw9Nkpj49naU+vWw==", 26 | "dev": true, 27 | "requires": { 28 | "@babel/helper-validator-identifier": "^7.10.3", 29 | "chalk": "^2.0.0", 30 | "js-tokens": "^4.0.0" 31 | }, 32 | "dependencies": { 33 | "ansi-styles": { 34 | "version": "3.2.1", 35 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 36 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 37 | "dev": true, 38 | "requires": { 39 | "color-convert": "^1.9.0" 40 | } 41 | }, 42 | "chalk": { 43 | "version": "2.4.2", 44 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 45 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 46 | "dev": true, 47 | "requires": { 48 | "ansi-styles": "^3.2.1", 49 | "escape-string-regexp": "^1.0.5", 50 | "supports-color": "^5.3.0" 51 | } 52 | }, 53 | "color-convert": { 54 | "version": "1.9.3", 55 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 56 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 57 | "dev": true, 58 | "requires": { 59 | "color-name": "1.1.3" 60 | } 61 | }, 62 | "color-name": { 63 | "version": "1.1.3", 64 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 65 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 66 | "dev": true 67 | } 68 | } 69 | }, 70 | "@sindresorhus/is": { 71 | "version": "0.14.0", 72 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", 73 | "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", 74 | "dev": true 75 | }, 76 | "@szmarczak/http-timer": { 77 | "version": "1.1.2", 78 | "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", 79 | "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", 80 | "dev": true, 81 | "requires": { 82 | "defer-to-connect": "^1.0.1" 83 | } 84 | }, 85 | "@types/color-name": { 86 | "version": "1.1.1", 87 | "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", 88 | "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", 89 | "dev": true 90 | }, 91 | "@types/eslint-visitor-keys": { 92 | "version": "1.0.0", 93 | "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", 94 | "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", 95 | "dev": true 96 | }, 97 | "@types/json-schema": { 98 | "version": "7.0.5", 99 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", 100 | "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==", 101 | "dev": true 102 | }, 103 | "@typescript-eslint/eslint-plugin": { 104 | "version": "3.3.0", 105 | "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.3.0.tgz", 106 | "integrity": "sha512-Ybx/wU75Tazz6nU2d7nN6ll0B98odoiYLXwcuwS5WSttGzK46t0n7TPRQ4ozwcTv82UY6TQoIvI+sJfTzqK9dQ==", 107 | "dev": true, 108 | "requires": { 109 | "@typescript-eslint/experimental-utils": "3.3.0", 110 | "functional-red-black-tree": "^1.0.1", 111 | "regexpp": "^3.0.0", 112 | "semver": "^7.3.2", 113 | "tsutils": "^3.17.1" 114 | }, 115 | "dependencies": { 116 | "semver": { 117 | "version": "7.3.2", 118 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", 119 | "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", 120 | "dev": true 121 | } 122 | } 123 | }, 124 | "@typescript-eslint/experimental-utils": { 125 | "version": "3.3.0", 126 | "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.3.0.tgz", 127 | "integrity": "sha512-d4pGIAbu/tYsrPrdHCQ5xfadJGvlkUxbeBB56nO/VGmEDi/sKmfa5fGty5t5veL1OyJBrUmSiRn1R1qfVDydrg==", 128 | "dev": true, 129 | "requires": { 130 | "@types/json-schema": "^7.0.3", 131 | "@typescript-eslint/typescript-estree": "3.3.0", 132 | "eslint-scope": "^5.0.0", 133 | "eslint-utils": "^2.0.0" 134 | } 135 | }, 136 | "@typescript-eslint/parser": { 137 | "version": "3.3.0", 138 | "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.3.0.tgz", 139 | "integrity": "sha512-a7S0Sqn/+RpOOWTcaLw6RD4obsharzxmgMfdK24l364VxuBODXjuJM7ImCkSXEN7oz52aiZbXSbc76+2EsE91w==", 140 | "dev": true, 141 | "requires": { 142 | "@types/eslint-visitor-keys": "^1.0.0", 143 | "@typescript-eslint/experimental-utils": "3.3.0", 144 | "@typescript-eslint/typescript-estree": "3.3.0", 145 | "eslint-visitor-keys": "^1.1.0" 146 | } 147 | }, 148 | "@typescript-eslint/typescript-estree": { 149 | "version": "3.3.0", 150 | "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.3.0.tgz", 151 | "integrity": "sha512-3SqxylENltEvJsjjMSDCUx/edZNSC7wAqifUU1Ywp//0OWEZwMZJfecJud9XxJ/40rAKEbJMKBOQzeOjrLJFzQ==", 152 | "dev": true, 153 | "requires": { 154 | "debug": "^4.1.1", 155 | "eslint-visitor-keys": "^1.1.0", 156 | "glob": "^7.1.6", 157 | "is-glob": "^4.0.1", 158 | "lodash": "^4.17.15", 159 | "semver": "^7.3.2", 160 | "tsutils": "^3.17.1" 161 | }, 162 | "dependencies": { 163 | "debug": { 164 | "version": "4.1.1", 165 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 166 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 167 | "dev": true, 168 | "requires": { 169 | "ms": "^2.1.1" 170 | } 171 | }, 172 | "semver": { 173 | "version": "7.3.2", 174 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", 175 | "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", 176 | "dev": true 177 | } 178 | } 179 | }, 180 | "abbrev": { 181 | "version": "1.1.1", 182 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 183 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", 184 | "dev": true 185 | }, 186 | "acorn": { 187 | "version": "7.3.1", 188 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz", 189 | "integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==", 190 | "dev": true 191 | }, 192 | "acorn-jsx": { 193 | "version": "5.2.0", 194 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", 195 | "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", 196 | "dev": true 197 | }, 198 | "ajv": { 199 | "version": "6.12.2", 200 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", 201 | "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", 202 | "dev": true, 203 | "requires": { 204 | "fast-deep-equal": "^3.1.1", 205 | "fast-json-stable-stringify": "^2.0.0", 206 | "json-schema-traverse": "^0.4.1", 207 | "uri-js": "^4.2.2" 208 | } 209 | }, 210 | "ansi-align": { 211 | "version": "3.0.0", 212 | "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", 213 | "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", 214 | "dev": true, 215 | "requires": { 216 | "string-width": "^3.0.0" 217 | }, 218 | "dependencies": { 219 | "string-width": { 220 | "version": "3.1.0", 221 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 222 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 223 | "dev": true, 224 | "requires": { 225 | "emoji-regex": "^7.0.1", 226 | "is-fullwidth-code-point": "^2.0.0", 227 | "strip-ansi": "^5.1.0" 228 | } 229 | } 230 | } 231 | }, 232 | "ansi-colors": { 233 | "version": "3.2.4", 234 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", 235 | "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", 236 | "dev": true 237 | }, 238 | "ansi-regex": { 239 | "version": "4.1.0", 240 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 241 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 242 | "dev": true 243 | }, 244 | "ansi-styles": { 245 | "version": "4.2.1", 246 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", 247 | "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", 248 | "dev": true, 249 | "requires": { 250 | "@types/color-name": "^1.1.1", 251 | "color-convert": "^2.0.1" 252 | } 253 | }, 254 | "anymatch": { 255 | "version": "3.1.1", 256 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", 257 | "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", 258 | "dev": true, 259 | "requires": { 260 | "normalize-path": "^3.0.0", 261 | "picomatch": "^2.0.4" 262 | } 263 | }, 264 | "arg": { 265 | "version": "4.1.3", 266 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", 267 | "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", 268 | "dev": true 269 | }, 270 | "argparse": { 271 | "version": "1.0.10", 272 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 273 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 274 | "dev": true, 275 | "requires": { 276 | "sprintf-js": "~1.0.2" 277 | } 278 | }, 279 | "astral-regex": { 280 | "version": "1.0.0", 281 | "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", 282 | "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", 283 | "dev": true 284 | }, 285 | "balanced-match": { 286 | "version": "1.0.0", 287 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 288 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 289 | "dev": true 290 | }, 291 | "binary-extensions": { 292 | "version": "2.0.0", 293 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", 294 | "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", 295 | "dev": true 296 | }, 297 | "boxen": { 298 | "version": "4.2.0", 299 | "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", 300 | "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", 301 | "dev": true, 302 | "requires": { 303 | "ansi-align": "^3.0.0", 304 | "camelcase": "^5.3.1", 305 | "chalk": "^3.0.0", 306 | "cli-boxes": "^2.2.0", 307 | "string-width": "^4.1.0", 308 | "term-size": "^2.1.0", 309 | "type-fest": "^0.8.1", 310 | "widest-line": "^3.1.0" 311 | } 312 | }, 313 | "brace-expansion": { 314 | "version": "1.1.11", 315 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 316 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 317 | "dev": true, 318 | "requires": { 319 | "balanced-match": "^1.0.0", 320 | "concat-map": "0.0.1" 321 | } 322 | }, 323 | "braces": { 324 | "version": "3.0.2", 325 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 326 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 327 | "dev": true, 328 | "requires": { 329 | "fill-range": "^7.0.1" 330 | } 331 | }, 332 | "buffer-from": { 333 | "version": "1.1.1", 334 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 335 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", 336 | "dev": true 337 | }, 338 | "cacheable-request": { 339 | "version": "6.1.0", 340 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", 341 | "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", 342 | "dev": true, 343 | "requires": { 344 | "clone-response": "^1.0.2", 345 | "get-stream": "^5.1.0", 346 | "http-cache-semantics": "^4.0.0", 347 | "keyv": "^3.0.0", 348 | "lowercase-keys": "^2.0.0", 349 | "normalize-url": "^4.1.0", 350 | "responselike": "^1.0.2" 351 | }, 352 | "dependencies": { 353 | "get-stream": { 354 | "version": "5.1.0", 355 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", 356 | "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", 357 | "dev": true, 358 | "requires": { 359 | "pump": "^3.0.0" 360 | } 361 | }, 362 | "lowercase-keys": { 363 | "version": "2.0.0", 364 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", 365 | "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", 366 | "dev": true 367 | } 368 | } 369 | }, 370 | "callsites": { 371 | "version": "3.1.0", 372 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 373 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 374 | "dev": true 375 | }, 376 | "camelcase": { 377 | "version": "5.3.1", 378 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 379 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 380 | "dev": true 381 | }, 382 | "chalk": { 383 | "version": "3.0.0", 384 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", 385 | "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", 386 | "dev": true, 387 | "requires": { 388 | "ansi-styles": "^4.1.0", 389 | "supports-color": "^7.1.0" 390 | }, 391 | "dependencies": { 392 | "has-flag": { 393 | "version": "4.0.0", 394 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 395 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 396 | "dev": true 397 | }, 398 | "supports-color": { 399 | "version": "7.1.0", 400 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", 401 | "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", 402 | "dev": true, 403 | "requires": { 404 | "has-flag": "^4.0.0" 405 | } 406 | } 407 | } 408 | }, 409 | "chokidar": { 410 | "version": "3.4.0", 411 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", 412 | "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==", 413 | "dev": true, 414 | "requires": { 415 | "anymatch": "~3.1.1", 416 | "braces": "~3.0.2", 417 | "fsevents": "~2.1.2", 418 | "glob-parent": "~5.1.0", 419 | "is-binary-path": "~2.1.0", 420 | "is-glob": "~4.0.1", 421 | "normalize-path": "~3.0.0", 422 | "readdirp": "~3.4.0" 423 | } 424 | }, 425 | "ci-info": { 426 | "version": "2.0.0", 427 | "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", 428 | "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", 429 | "dev": true 430 | }, 431 | "cli-boxes": { 432 | "version": "2.2.0", 433 | "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", 434 | "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", 435 | "dev": true 436 | }, 437 | "clone-response": { 438 | "version": "1.0.2", 439 | "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", 440 | "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", 441 | "dev": true, 442 | "requires": { 443 | "mimic-response": "^1.0.0" 444 | } 445 | }, 446 | "color-convert": { 447 | "version": "2.0.1", 448 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 449 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 450 | "dev": true, 451 | "requires": { 452 | "color-name": "~1.1.4" 453 | } 454 | }, 455 | "color-name": { 456 | "version": "1.1.4", 457 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 458 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 459 | "dev": true 460 | }, 461 | "concat-map": { 462 | "version": "0.0.1", 463 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 464 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 465 | "dev": true 466 | }, 467 | "configstore": { 468 | "version": "5.0.1", 469 | "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", 470 | "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", 471 | "dev": true, 472 | "requires": { 473 | "dot-prop": "^5.2.0", 474 | "graceful-fs": "^4.1.2", 475 | "make-dir": "^3.0.0", 476 | "unique-string": "^2.0.0", 477 | "write-file-atomic": "^3.0.0", 478 | "xdg-basedir": "^4.0.0" 479 | } 480 | }, 481 | "cross-spawn": { 482 | "version": "7.0.3", 483 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 484 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 485 | "dev": true, 486 | "requires": { 487 | "path-key": "^3.1.0", 488 | "shebang-command": "^2.0.0", 489 | "which": "^2.0.1" 490 | } 491 | }, 492 | "crypto-random-string": { 493 | "version": "2.0.0", 494 | "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", 495 | "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", 496 | "dev": true 497 | }, 498 | "debug": { 499 | "version": "3.2.6", 500 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 501 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 502 | "dev": true, 503 | "requires": { 504 | "ms": "^2.1.1" 505 | } 506 | }, 507 | "decompress-response": { 508 | "version": "3.3.0", 509 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", 510 | "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", 511 | "dev": true, 512 | "requires": { 513 | "mimic-response": "^1.0.0" 514 | } 515 | }, 516 | "deep-extend": { 517 | "version": "0.6.0", 518 | "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", 519 | "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", 520 | "dev": true 521 | }, 522 | "deep-is": { 523 | "version": "0.1.3", 524 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 525 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 526 | "dev": true 527 | }, 528 | "defer-to-connect": { 529 | "version": "1.1.3", 530 | "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", 531 | "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", 532 | "dev": true 533 | }, 534 | "diff": { 535 | "version": "4.0.2", 536 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 537 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 538 | "dev": true 539 | }, 540 | "doctrine": { 541 | "version": "3.0.0", 542 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 543 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 544 | "dev": true, 545 | "requires": { 546 | "esutils": "^2.0.2" 547 | } 548 | }, 549 | "dot-prop": { 550 | "version": "5.2.0", 551 | "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", 552 | "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==", 553 | "dev": true, 554 | "requires": { 555 | "is-obj": "^2.0.0" 556 | } 557 | }, 558 | "duplexer3": { 559 | "version": "0.1.4", 560 | "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", 561 | "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", 562 | "dev": true 563 | }, 564 | "emoji-regex": { 565 | "version": "7.0.3", 566 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 567 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 568 | "dev": true 569 | }, 570 | "end-of-stream": { 571 | "version": "1.4.4", 572 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 573 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 574 | "dev": true, 575 | "requires": { 576 | "once": "^1.4.0" 577 | } 578 | }, 579 | "enquirer": { 580 | "version": "2.3.5", 581 | "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.5.tgz", 582 | "integrity": "sha512-BNT1C08P9XD0vNg3J475yIUG+mVdp9T6towYFHUv897X0KoHBjB1shyrNmhmtHWKP17iSWgo7Gqh7BBuzLZMSA==", 583 | "dev": true, 584 | "requires": { 585 | "ansi-colors": "^3.2.1" 586 | } 587 | }, 588 | "escape-goat": { 589 | "version": "2.1.1", 590 | "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", 591 | "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", 592 | "dev": true 593 | }, 594 | "escape-string-regexp": { 595 | "version": "1.0.5", 596 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 597 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 598 | "dev": true 599 | }, 600 | "eslint": { 601 | "version": "7.3.0", 602 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.3.0.tgz", 603 | "integrity": "sha512-dJMVXwfU5PT1cj2Nv2VPPrKahKTGdX+5Dh0Q3YuKt+Y2UhdL2YbzsVaBMyG9HC0tBismlv/r1+eZqs6SMIV38Q==", 604 | "dev": true, 605 | "requires": { 606 | "@babel/code-frame": "^7.0.0", 607 | "ajv": "^6.10.0", 608 | "chalk": "^4.0.0", 609 | "cross-spawn": "^7.0.2", 610 | "debug": "^4.0.1", 611 | "doctrine": "^3.0.0", 612 | "enquirer": "^2.3.5", 613 | "eslint-scope": "^5.1.0", 614 | "eslint-utils": "^2.0.0", 615 | "eslint-visitor-keys": "^1.2.0", 616 | "espree": "^7.1.0", 617 | "esquery": "^1.2.0", 618 | "esutils": "^2.0.2", 619 | "file-entry-cache": "^5.0.1", 620 | "functional-red-black-tree": "^1.0.1", 621 | "glob-parent": "^5.0.0", 622 | "globals": "^12.1.0", 623 | "ignore": "^4.0.6", 624 | "import-fresh": "^3.0.0", 625 | "imurmurhash": "^0.1.4", 626 | "is-glob": "^4.0.0", 627 | "js-yaml": "^3.13.1", 628 | "json-stable-stringify-without-jsonify": "^1.0.1", 629 | "levn": "^0.4.1", 630 | "lodash": "^4.17.14", 631 | "minimatch": "^3.0.4", 632 | "natural-compare": "^1.4.0", 633 | "optionator": "^0.9.1", 634 | "progress": "^2.0.0", 635 | "regexpp": "^3.1.0", 636 | "semver": "^7.2.1", 637 | "strip-ansi": "^6.0.0", 638 | "strip-json-comments": "^3.1.0", 639 | "table": "^5.2.3", 640 | "text-table": "^0.2.0", 641 | "v8-compile-cache": "^2.0.3" 642 | }, 643 | "dependencies": { 644 | "ansi-regex": { 645 | "version": "5.0.0", 646 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 647 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 648 | "dev": true 649 | }, 650 | "chalk": { 651 | "version": "4.1.0", 652 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", 653 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", 654 | "dev": true, 655 | "requires": { 656 | "ansi-styles": "^4.1.0", 657 | "supports-color": "^7.1.0" 658 | } 659 | }, 660 | "debug": { 661 | "version": "4.1.1", 662 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 663 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 664 | "dev": true, 665 | "requires": { 666 | "ms": "^2.1.1" 667 | } 668 | }, 669 | "has-flag": { 670 | "version": "4.0.0", 671 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 672 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 673 | "dev": true 674 | }, 675 | "semver": { 676 | "version": "7.3.2", 677 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", 678 | "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", 679 | "dev": true 680 | }, 681 | "strip-ansi": { 682 | "version": "6.0.0", 683 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 684 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 685 | "dev": true, 686 | "requires": { 687 | "ansi-regex": "^5.0.0" 688 | } 689 | }, 690 | "strip-json-comments": { 691 | "version": "3.1.0", 692 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", 693 | "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==", 694 | "dev": true 695 | }, 696 | "supports-color": { 697 | "version": "7.1.0", 698 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", 699 | "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", 700 | "dev": true, 701 | "requires": { 702 | "has-flag": "^4.0.0" 703 | } 704 | } 705 | } 706 | }, 707 | "eslint-config-prettier": { 708 | "version": "6.11.0", 709 | "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz", 710 | "integrity": "sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA==", 711 | "dev": true, 712 | "requires": { 713 | "get-stdin": "^6.0.0" 714 | } 715 | }, 716 | "eslint-plugin-prettier": { 717 | "version": "3.1.4", 718 | "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz", 719 | "integrity": "sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==", 720 | "dev": true, 721 | "requires": { 722 | "prettier-linter-helpers": "^1.0.0" 723 | } 724 | }, 725 | "eslint-scope": { 726 | "version": "5.1.0", 727 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", 728 | "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==", 729 | "dev": true, 730 | "requires": { 731 | "esrecurse": "^4.1.0", 732 | "estraverse": "^4.1.1" 733 | } 734 | }, 735 | "eslint-utils": { 736 | "version": "2.1.0", 737 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", 738 | "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", 739 | "dev": true, 740 | "requires": { 741 | "eslint-visitor-keys": "^1.1.0" 742 | } 743 | }, 744 | "eslint-visitor-keys": { 745 | "version": "1.3.0", 746 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", 747 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", 748 | "dev": true 749 | }, 750 | "espree": { 751 | "version": "7.1.0", 752 | "resolved": "https://registry.npmjs.org/espree/-/espree-7.1.0.tgz", 753 | "integrity": "sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw==", 754 | "dev": true, 755 | "requires": { 756 | "acorn": "^7.2.0", 757 | "acorn-jsx": "^5.2.0", 758 | "eslint-visitor-keys": "^1.2.0" 759 | } 760 | }, 761 | "esprima": { 762 | "version": "4.0.1", 763 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 764 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 765 | "dev": true 766 | }, 767 | "esquery": { 768 | "version": "1.3.1", 769 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", 770 | "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", 771 | "dev": true, 772 | "requires": { 773 | "estraverse": "^5.1.0" 774 | }, 775 | "dependencies": { 776 | "estraverse": { 777 | "version": "5.1.0", 778 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz", 779 | "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==", 780 | "dev": true 781 | } 782 | } 783 | }, 784 | "esrecurse": { 785 | "version": "4.2.1", 786 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", 787 | "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", 788 | "dev": true, 789 | "requires": { 790 | "estraverse": "^4.1.0" 791 | } 792 | }, 793 | "estraverse": { 794 | "version": "4.3.0", 795 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 796 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 797 | "dev": true 798 | }, 799 | "esutils": { 800 | "version": "2.0.3", 801 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 802 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 803 | "dev": true 804 | }, 805 | "fast-deep-equal": { 806 | "version": "3.1.3", 807 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 808 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 809 | "dev": true 810 | }, 811 | "fast-diff": { 812 | "version": "1.2.0", 813 | "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", 814 | "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", 815 | "dev": true 816 | }, 817 | "fast-json-stable-stringify": { 818 | "version": "2.1.0", 819 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 820 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 821 | "dev": true 822 | }, 823 | "fast-levenshtein": { 824 | "version": "2.0.6", 825 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 826 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 827 | "dev": true 828 | }, 829 | "file-entry-cache": { 830 | "version": "5.0.1", 831 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", 832 | "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", 833 | "dev": true, 834 | "requires": { 835 | "flat-cache": "^2.0.1" 836 | } 837 | }, 838 | "fill-range": { 839 | "version": "7.0.1", 840 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 841 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 842 | "dev": true, 843 | "requires": { 844 | "to-regex-range": "^5.0.1" 845 | } 846 | }, 847 | "flat-cache": { 848 | "version": "2.0.1", 849 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", 850 | "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", 851 | "dev": true, 852 | "requires": { 853 | "flatted": "^2.0.0", 854 | "rimraf": "2.6.3", 855 | "write": "1.0.3" 856 | } 857 | }, 858 | "flatted": { 859 | "version": "2.0.2", 860 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", 861 | "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", 862 | "dev": true 863 | }, 864 | "fs.realpath": { 865 | "version": "1.0.0", 866 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 867 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 868 | "dev": true 869 | }, 870 | "fsevents": { 871 | "version": "2.1.3", 872 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", 873 | "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", 874 | "dev": true, 875 | "optional": true 876 | }, 877 | "functional-red-black-tree": { 878 | "version": "1.0.1", 879 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 880 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 881 | "dev": true 882 | }, 883 | "get-stdin": { 884 | "version": "6.0.0", 885 | "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", 886 | "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", 887 | "dev": true 888 | }, 889 | "get-stream": { 890 | "version": "4.1.0", 891 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", 892 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", 893 | "dev": true, 894 | "requires": { 895 | "pump": "^3.0.0" 896 | } 897 | }, 898 | "glob": { 899 | "version": "7.1.6", 900 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 901 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 902 | "dev": true, 903 | "requires": { 904 | "fs.realpath": "^1.0.0", 905 | "inflight": "^1.0.4", 906 | "inherits": "2", 907 | "minimatch": "^3.0.4", 908 | "once": "^1.3.0", 909 | "path-is-absolute": "^1.0.0" 910 | } 911 | }, 912 | "glob-parent": { 913 | "version": "5.1.1", 914 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", 915 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", 916 | "dev": true, 917 | "requires": { 918 | "is-glob": "^4.0.1" 919 | } 920 | }, 921 | "global-dirs": { 922 | "version": "2.0.1", 923 | "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", 924 | "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", 925 | "dev": true, 926 | "requires": { 927 | "ini": "^1.3.5" 928 | } 929 | }, 930 | "globals": { 931 | "version": "12.4.0", 932 | "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", 933 | "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", 934 | "dev": true, 935 | "requires": { 936 | "type-fest": "^0.8.1" 937 | } 938 | }, 939 | "got": { 940 | "version": "9.6.0", 941 | "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", 942 | "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", 943 | "dev": true, 944 | "requires": { 945 | "@sindresorhus/is": "^0.14.0", 946 | "@szmarczak/http-timer": "^1.1.2", 947 | "cacheable-request": "^6.0.0", 948 | "decompress-response": "^3.3.0", 949 | "duplexer3": "^0.1.4", 950 | "get-stream": "^4.1.0", 951 | "lowercase-keys": "^1.0.1", 952 | "mimic-response": "^1.0.1", 953 | "p-cancelable": "^1.0.0", 954 | "to-readable-stream": "^1.0.0", 955 | "url-parse-lax": "^3.0.0" 956 | } 957 | }, 958 | "graceful-fs": { 959 | "version": "4.2.4", 960 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", 961 | "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", 962 | "dev": true 963 | }, 964 | "has-flag": { 965 | "version": "3.0.0", 966 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 967 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 968 | "dev": true 969 | }, 970 | "has-yarn": { 971 | "version": "2.1.0", 972 | "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", 973 | "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", 974 | "dev": true 975 | }, 976 | "http-cache-semantics": { 977 | "version": "4.1.0", 978 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", 979 | "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", 980 | "dev": true 981 | }, 982 | "ignore": { 983 | "version": "4.0.6", 984 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 985 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 986 | "dev": true 987 | }, 988 | "ignore-by-default": { 989 | "version": "1.0.1", 990 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 991 | "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", 992 | "dev": true 993 | }, 994 | "import-fresh": { 995 | "version": "3.2.1", 996 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", 997 | "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", 998 | "dev": true, 999 | "requires": { 1000 | "parent-module": "^1.0.0", 1001 | "resolve-from": "^4.0.0" 1002 | } 1003 | }, 1004 | "import-lazy": { 1005 | "version": "2.1.0", 1006 | "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", 1007 | "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", 1008 | "dev": true 1009 | }, 1010 | "imurmurhash": { 1011 | "version": "0.1.4", 1012 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1013 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 1014 | "dev": true 1015 | }, 1016 | "inflight": { 1017 | "version": "1.0.6", 1018 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1019 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1020 | "dev": true, 1021 | "requires": { 1022 | "once": "^1.3.0", 1023 | "wrappy": "1" 1024 | } 1025 | }, 1026 | "inherits": { 1027 | "version": "2.0.4", 1028 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1029 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1030 | "dev": true 1031 | }, 1032 | "ini": { 1033 | "version": "1.3.5", 1034 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", 1035 | "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", 1036 | "dev": true 1037 | }, 1038 | "is-binary-path": { 1039 | "version": "2.1.0", 1040 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 1041 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 1042 | "dev": true, 1043 | "requires": { 1044 | "binary-extensions": "^2.0.0" 1045 | } 1046 | }, 1047 | "is-ci": { 1048 | "version": "2.0.0", 1049 | "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", 1050 | "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", 1051 | "dev": true, 1052 | "requires": { 1053 | "ci-info": "^2.0.0" 1054 | } 1055 | }, 1056 | "is-extglob": { 1057 | "version": "2.1.1", 1058 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1059 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 1060 | "dev": true 1061 | }, 1062 | "is-fullwidth-code-point": { 1063 | "version": "2.0.0", 1064 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 1065 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 1066 | "dev": true 1067 | }, 1068 | "is-glob": { 1069 | "version": "4.0.1", 1070 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 1071 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 1072 | "dev": true, 1073 | "requires": { 1074 | "is-extglob": "^2.1.1" 1075 | } 1076 | }, 1077 | "is-installed-globally": { 1078 | "version": "0.3.2", 1079 | "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", 1080 | "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", 1081 | "dev": true, 1082 | "requires": { 1083 | "global-dirs": "^2.0.1", 1084 | "is-path-inside": "^3.0.1" 1085 | } 1086 | }, 1087 | "is-npm": { 1088 | "version": "4.0.0", 1089 | "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", 1090 | "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", 1091 | "dev": true 1092 | }, 1093 | "is-number": { 1094 | "version": "7.0.0", 1095 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1096 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1097 | "dev": true 1098 | }, 1099 | "is-obj": { 1100 | "version": "2.0.0", 1101 | "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", 1102 | "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", 1103 | "dev": true 1104 | }, 1105 | "is-path-inside": { 1106 | "version": "3.0.2", 1107 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", 1108 | "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==", 1109 | "dev": true 1110 | }, 1111 | "is-typedarray": { 1112 | "version": "1.0.0", 1113 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 1114 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 1115 | "dev": true 1116 | }, 1117 | "is-yarn-global": { 1118 | "version": "0.3.0", 1119 | "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", 1120 | "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", 1121 | "dev": true 1122 | }, 1123 | "isexe": { 1124 | "version": "2.0.0", 1125 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1126 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 1127 | "dev": true 1128 | }, 1129 | "js-tokens": { 1130 | "version": "4.0.0", 1131 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 1132 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 1133 | "dev": true 1134 | }, 1135 | "js-yaml": { 1136 | "version": "3.14.0", 1137 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", 1138 | "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", 1139 | "dev": true, 1140 | "requires": { 1141 | "argparse": "^1.0.7", 1142 | "esprima": "^4.0.0" 1143 | } 1144 | }, 1145 | "json-buffer": { 1146 | "version": "3.0.0", 1147 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", 1148 | "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", 1149 | "dev": true 1150 | }, 1151 | "json-schema-traverse": { 1152 | "version": "0.4.1", 1153 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1154 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1155 | "dev": true 1156 | }, 1157 | "json-stable-stringify-without-jsonify": { 1158 | "version": "1.0.1", 1159 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1160 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 1161 | "dev": true 1162 | }, 1163 | "keyv": { 1164 | "version": "3.1.0", 1165 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", 1166 | "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", 1167 | "dev": true, 1168 | "requires": { 1169 | "json-buffer": "3.0.0" 1170 | } 1171 | }, 1172 | "latest-version": { 1173 | "version": "5.1.0", 1174 | "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", 1175 | "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", 1176 | "dev": true, 1177 | "requires": { 1178 | "package-json": "^6.3.0" 1179 | } 1180 | }, 1181 | "levn": { 1182 | "version": "0.4.1", 1183 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 1184 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 1185 | "dev": true, 1186 | "requires": { 1187 | "prelude-ls": "^1.2.1", 1188 | "type-check": "~0.4.0" 1189 | } 1190 | }, 1191 | "lodash": { 1192 | "version": "4.17.15", 1193 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 1194 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", 1195 | "dev": true 1196 | }, 1197 | "lowercase-keys": { 1198 | "version": "1.0.1", 1199 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", 1200 | "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", 1201 | "dev": true 1202 | }, 1203 | "make-dir": { 1204 | "version": "3.1.0", 1205 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", 1206 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", 1207 | "dev": true, 1208 | "requires": { 1209 | "semver": "^6.0.0" 1210 | }, 1211 | "dependencies": { 1212 | "semver": { 1213 | "version": "6.3.0", 1214 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1215 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 1216 | "dev": true 1217 | } 1218 | } 1219 | }, 1220 | "make-error": { 1221 | "version": "1.3.6", 1222 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", 1223 | "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", 1224 | "dev": true 1225 | }, 1226 | "mimic-response": { 1227 | "version": "1.0.1", 1228 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", 1229 | "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", 1230 | "dev": true 1231 | }, 1232 | "minimatch": { 1233 | "version": "3.0.4", 1234 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1235 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1236 | "dev": true, 1237 | "requires": { 1238 | "brace-expansion": "^1.1.7" 1239 | } 1240 | }, 1241 | "minimist": { 1242 | "version": "1.2.5", 1243 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 1244 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 1245 | "dev": true 1246 | }, 1247 | "mkdirp": { 1248 | "version": "0.5.5", 1249 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 1250 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 1251 | "dev": true, 1252 | "requires": { 1253 | "minimist": "^1.2.5" 1254 | } 1255 | }, 1256 | "ms": { 1257 | "version": "2.1.2", 1258 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1259 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1260 | "dev": true 1261 | }, 1262 | "natural-compare": { 1263 | "version": "1.4.0", 1264 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1265 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 1266 | "dev": true 1267 | }, 1268 | "nodemon": { 1269 | "version": "2.0.4", 1270 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.4.tgz", 1271 | "integrity": "sha512-Ltced+hIfTmaS28Zjv1BM552oQ3dbwPqI4+zI0SLgq+wpJhSyqgYude/aZa/3i31VCQWMfXJVxvu86abcam3uQ==", 1272 | "dev": true, 1273 | "requires": { 1274 | "chokidar": "^3.2.2", 1275 | "debug": "^3.2.6", 1276 | "ignore-by-default": "^1.0.1", 1277 | "minimatch": "^3.0.4", 1278 | "pstree.remy": "^1.1.7", 1279 | "semver": "^5.7.1", 1280 | "supports-color": "^5.5.0", 1281 | "touch": "^3.1.0", 1282 | "undefsafe": "^2.0.2", 1283 | "update-notifier": "^4.0.0" 1284 | } 1285 | }, 1286 | "nopt": { 1287 | "version": "1.0.10", 1288 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", 1289 | "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", 1290 | "dev": true, 1291 | "requires": { 1292 | "abbrev": "1" 1293 | } 1294 | }, 1295 | "normalize-path": { 1296 | "version": "3.0.0", 1297 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1298 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1299 | "dev": true 1300 | }, 1301 | "normalize-url": { 1302 | "version": "4.5.0", 1303 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", 1304 | "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", 1305 | "dev": true 1306 | }, 1307 | "once": { 1308 | "version": "1.4.0", 1309 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1310 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1311 | "dev": true, 1312 | "requires": { 1313 | "wrappy": "1" 1314 | } 1315 | }, 1316 | "optionator": { 1317 | "version": "0.9.1", 1318 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", 1319 | "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", 1320 | "dev": true, 1321 | "requires": { 1322 | "deep-is": "^0.1.3", 1323 | "fast-levenshtein": "^2.0.6", 1324 | "levn": "^0.4.1", 1325 | "prelude-ls": "^1.2.1", 1326 | "type-check": "^0.4.0", 1327 | "word-wrap": "^1.2.3" 1328 | } 1329 | }, 1330 | "p-cancelable": { 1331 | "version": "1.1.0", 1332 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", 1333 | "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", 1334 | "dev": true 1335 | }, 1336 | "package-json": { 1337 | "version": "6.5.0", 1338 | "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", 1339 | "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", 1340 | "dev": true, 1341 | "requires": { 1342 | "got": "^9.6.0", 1343 | "registry-auth-token": "^4.0.0", 1344 | "registry-url": "^5.0.0", 1345 | "semver": "^6.2.0" 1346 | }, 1347 | "dependencies": { 1348 | "semver": { 1349 | "version": "6.3.0", 1350 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1351 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 1352 | "dev": true 1353 | } 1354 | } 1355 | }, 1356 | "parent-module": { 1357 | "version": "1.0.1", 1358 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 1359 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 1360 | "dev": true, 1361 | "requires": { 1362 | "callsites": "^3.0.0" 1363 | } 1364 | }, 1365 | "path-is-absolute": { 1366 | "version": "1.0.1", 1367 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1368 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1369 | "dev": true 1370 | }, 1371 | "path-key": { 1372 | "version": "3.1.1", 1373 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1374 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1375 | "dev": true 1376 | }, 1377 | "picomatch": { 1378 | "version": "2.2.2", 1379 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", 1380 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", 1381 | "dev": true 1382 | }, 1383 | "prelude-ls": { 1384 | "version": "1.2.1", 1385 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 1386 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 1387 | "dev": true 1388 | }, 1389 | "prepend-http": { 1390 | "version": "2.0.0", 1391 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", 1392 | "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", 1393 | "dev": true 1394 | }, 1395 | "prettier": { 1396 | "version": "2.0.5", 1397 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz", 1398 | "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==", 1399 | "dev": true 1400 | }, 1401 | "prettier-linter-helpers": { 1402 | "version": "1.0.0", 1403 | "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", 1404 | "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", 1405 | "dev": true, 1406 | "requires": { 1407 | "fast-diff": "^1.1.2" 1408 | } 1409 | }, 1410 | "progress": { 1411 | "version": "2.0.3", 1412 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 1413 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 1414 | "dev": true 1415 | }, 1416 | "pstree.remy": { 1417 | "version": "1.1.8", 1418 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", 1419 | "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", 1420 | "dev": true 1421 | }, 1422 | "pump": { 1423 | "version": "3.0.0", 1424 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 1425 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 1426 | "dev": true, 1427 | "requires": { 1428 | "end-of-stream": "^1.1.0", 1429 | "once": "^1.3.1" 1430 | } 1431 | }, 1432 | "punycode": { 1433 | "version": "2.1.1", 1434 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1435 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 1436 | "dev": true 1437 | }, 1438 | "pupa": { 1439 | "version": "2.0.1", 1440 | "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz", 1441 | "integrity": "sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==", 1442 | "dev": true, 1443 | "requires": { 1444 | "escape-goat": "^2.0.0" 1445 | } 1446 | }, 1447 | "rc": { 1448 | "version": "1.2.8", 1449 | "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", 1450 | "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", 1451 | "dev": true, 1452 | "requires": { 1453 | "deep-extend": "^0.6.0", 1454 | "ini": "~1.3.0", 1455 | "minimist": "^1.2.0", 1456 | "strip-json-comments": "~2.0.1" 1457 | } 1458 | }, 1459 | "readdirp": { 1460 | "version": "3.4.0", 1461 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", 1462 | "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", 1463 | "dev": true, 1464 | "requires": { 1465 | "picomatch": "^2.2.1" 1466 | } 1467 | }, 1468 | "regexpp": { 1469 | "version": "3.1.0", 1470 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", 1471 | "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", 1472 | "dev": true 1473 | }, 1474 | "registry-auth-token": { 1475 | "version": "4.1.1", 1476 | "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.1.1.tgz", 1477 | "integrity": "sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==", 1478 | "dev": true, 1479 | "requires": { 1480 | "rc": "^1.2.8" 1481 | } 1482 | }, 1483 | "registry-url": { 1484 | "version": "5.1.0", 1485 | "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", 1486 | "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", 1487 | "dev": true, 1488 | "requires": { 1489 | "rc": "^1.2.8" 1490 | } 1491 | }, 1492 | "resolve-from": { 1493 | "version": "4.0.0", 1494 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1495 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1496 | "dev": true 1497 | }, 1498 | "responselike": { 1499 | "version": "1.0.2", 1500 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", 1501 | "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", 1502 | "dev": true, 1503 | "requires": { 1504 | "lowercase-keys": "^1.0.0" 1505 | } 1506 | }, 1507 | "rimraf": { 1508 | "version": "2.6.3", 1509 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", 1510 | "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", 1511 | "dev": true, 1512 | "requires": { 1513 | "glob": "^7.1.3" 1514 | } 1515 | }, 1516 | "semver": { 1517 | "version": "5.7.1", 1518 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1519 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1520 | "dev": true 1521 | }, 1522 | "semver-diff": { 1523 | "version": "3.1.1", 1524 | "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", 1525 | "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", 1526 | "dev": true, 1527 | "requires": { 1528 | "semver": "^6.3.0" 1529 | }, 1530 | "dependencies": { 1531 | "semver": { 1532 | "version": "6.3.0", 1533 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1534 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 1535 | "dev": true 1536 | } 1537 | } 1538 | }, 1539 | "shebang-command": { 1540 | "version": "2.0.0", 1541 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1542 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1543 | "dev": true, 1544 | "requires": { 1545 | "shebang-regex": "^3.0.0" 1546 | } 1547 | }, 1548 | "shebang-regex": { 1549 | "version": "3.0.0", 1550 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1551 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1552 | "dev": true 1553 | }, 1554 | "signal-exit": { 1555 | "version": "3.0.3", 1556 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", 1557 | "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", 1558 | "dev": true 1559 | }, 1560 | "slice-ansi": { 1561 | "version": "2.1.0", 1562 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", 1563 | "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", 1564 | "dev": true, 1565 | "requires": { 1566 | "ansi-styles": "^3.2.0", 1567 | "astral-regex": "^1.0.0", 1568 | "is-fullwidth-code-point": "^2.0.0" 1569 | }, 1570 | "dependencies": { 1571 | "ansi-styles": { 1572 | "version": "3.2.1", 1573 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 1574 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 1575 | "dev": true, 1576 | "requires": { 1577 | "color-convert": "^1.9.0" 1578 | } 1579 | }, 1580 | "color-convert": { 1581 | "version": "1.9.3", 1582 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 1583 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 1584 | "dev": true, 1585 | "requires": { 1586 | "color-name": "1.1.3" 1587 | } 1588 | }, 1589 | "color-name": { 1590 | "version": "1.1.3", 1591 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 1592 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 1593 | "dev": true 1594 | } 1595 | } 1596 | }, 1597 | "source-map": { 1598 | "version": "0.6.1", 1599 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1600 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1601 | "dev": true 1602 | }, 1603 | "source-map-support": { 1604 | "version": "0.5.19", 1605 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", 1606 | "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", 1607 | "dev": true, 1608 | "requires": { 1609 | "buffer-from": "^1.0.0", 1610 | "source-map": "^0.6.0" 1611 | } 1612 | }, 1613 | "sprintf-js": { 1614 | "version": "1.0.3", 1615 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1616 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 1617 | "dev": true 1618 | }, 1619 | "string-width": { 1620 | "version": "4.2.0", 1621 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 1622 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 1623 | "dev": true, 1624 | "requires": { 1625 | "emoji-regex": "^8.0.0", 1626 | "is-fullwidth-code-point": "^3.0.0", 1627 | "strip-ansi": "^6.0.0" 1628 | }, 1629 | "dependencies": { 1630 | "ansi-regex": { 1631 | "version": "5.0.0", 1632 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 1633 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 1634 | "dev": true 1635 | }, 1636 | "emoji-regex": { 1637 | "version": "8.0.0", 1638 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1639 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1640 | "dev": true 1641 | }, 1642 | "is-fullwidth-code-point": { 1643 | "version": "3.0.0", 1644 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1645 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 1646 | "dev": true 1647 | }, 1648 | "strip-ansi": { 1649 | "version": "6.0.0", 1650 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 1651 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 1652 | "dev": true, 1653 | "requires": { 1654 | "ansi-regex": "^5.0.0" 1655 | } 1656 | } 1657 | } 1658 | }, 1659 | "strip-ansi": { 1660 | "version": "5.2.0", 1661 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1662 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1663 | "dev": true, 1664 | "requires": { 1665 | "ansi-regex": "^4.1.0" 1666 | } 1667 | }, 1668 | "strip-json-comments": { 1669 | "version": "2.0.1", 1670 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1671 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 1672 | "dev": true 1673 | }, 1674 | "supports-color": { 1675 | "version": "5.5.0", 1676 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1677 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1678 | "dev": true, 1679 | "requires": { 1680 | "has-flag": "^3.0.0" 1681 | } 1682 | }, 1683 | "table": { 1684 | "version": "5.4.6", 1685 | "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", 1686 | "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", 1687 | "dev": true, 1688 | "requires": { 1689 | "ajv": "^6.10.2", 1690 | "lodash": "^4.17.14", 1691 | "slice-ansi": "^2.1.0", 1692 | "string-width": "^3.0.0" 1693 | }, 1694 | "dependencies": { 1695 | "string-width": { 1696 | "version": "3.1.0", 1697 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 1698 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 1699 | "dev": true, 1700 | "requires": { 1701 | "emoji-regex": "^7.0.1", 1702 | "is-fullwidth-code-point": "^2.0.0", 1703 | "strip-ansi": "^5.1.0" 1704 | } 1705 | } 1706 | } 1707 | }, 1708 | "term-size": { 1709 | "version": "2.2.0", 1710 | "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz", 1711 | "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==", 1712 | "dev": true 1713 | }, 1714 | "text-table": { 1715 | "version": "0.2.0", 1716 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1717 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 1718 | "dev": true 1719 | }, 1720 | "to-readable-stream": { 1721 | "version": "1.0.0", 1722 | "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", 1723 | "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", 1724 | "dev": true 1725 | }, 1726 | "to-regex-range": { 1727 | "version": "5.0.1", 1728 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1729 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1730 | "dev": true, 1731 | "requires": { 1732 | "is-number": "^7.0.0" 1733 | } 1734 | }, 1735 | "touch": { 1736 | "version": "3.1.0", 1737 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", 1738 | "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", 1739 | "dev": true, 1740 | "requires": { 1741 | "nopt": "~1.0.10" 1742 | } 1743 | }, 1744 | "ts-node": { 1745 | "version": "8.10.2", 1746 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", 1747 | "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", 1748 | "dev": true, 1749 | "requires": { 1750 | "arg": "^4.1.0", 1751 | "diff": "^4.0.1", 1752 | "make-error": "^1.1.1", 1753 | "source-map-support": "^0.5.17", 1754 | "yn": "3.1.1" 1755 | } 1756 | }, 1757 | "tslib": { 1758 | "version": "1.13.0", 1759 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", 1760 | "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", 1761 | "dev": true 1762 | }, 1763 | "tsutils": { 1764 | "version": "3.17.1", 1765 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", 1766 | "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", 1767 | "dev": true, 1768 | "requires": { 1769 | "tslib": "^1.8.1" 1770 | } 1771 | }, 1772 | "type-check": { 1773 | "version": "0.4.0", 1774 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 1775 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 1776 | "dev": true, 1777 | "requires": { 1778 | "prelude-ls": "^1.2.1" 1779 | } 1780 | }, 1781 | "type-fest": { 1782 | "version": "0.8.1", 1783 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", 1784 | "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", 1785 | "dev": true 1786 | }, 1787 | "typedarray-to-buffer": { 1788 | "version": "3.1.5", 1789 | "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", 1790 | "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", 1791 | "dev": true, 1792 | "requires": { 1793 | "is-typedarray": "^1.0.0" 1794 | } 1795 | }, 1796 | "typescript": { 1797 | "version": "3.9.5", 1798 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz", 1799 | "integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==", 1800 | "dev": true 1801 | }, 1802 | "undefsafe": { 1803 | "version": "2.0.3", 1804 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", 1805 | "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==", 1806 | "dev": true, 1807 | "requires": { 1808 | "debug": "^2.2.0" 1809 | }, 1810 | "dependencies": { 1811 | "debug": { 1812 | "version": "2.6.9", 1813 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1814 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1815 | "dev": true, 1816 | "requires": { 1817 | "ms": "2.0.0" 1818 | } 1819 | }, 1820 | "ms": { 1821 | "version": "2.0.0", 1822 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1823 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 1824 | "dev": true 1825 | } 1826 | } 1827 | }, 1828 | "unique-string": { 1829 | "version": "2.0.0", 1830 | "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", 1831 | "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", 1832 | "dev": true, 1833 | "requires": { 1834 | "crypto-random-string": "^2.0.0" 1835 | } 1836 | }, 1837 | "update-notifier": { 1838 | "version": "4.1.0", 1839 | "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.0.tgz", 1840 | "integrity": "sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew==", 1841 | "dev": true, 1842 | "requires": { 1843 | "boxen": "^4.2.0", 1844 | "chalk": "^3.0.0", 1845 | "configstore": "^5.0.1", 1846 | "has-yarn": "^2.1.0", 1847 | "import-lazy": "^2.1.0", 1848 | "is-ci": "^2.0.0", 1849 | "is-installed-globally": "^0.3.1", 1850 | "is-npm": "^4.0.0", 1851 | "is-yarn-global": "^0.3.0", 1852 | "latest-version": "^5.0.0", 1853 | "pupa": "^2.0.1", 1854 | "semver-diff": "^3.1.1", 1855 | "xdg-basedir": "^4.0.0" 1856 | } 1857 | }, 1858 | "uri-js": { 1859 | "version": "4.2.2", 1860 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 1861 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 1862 | "dev": true, 1863 | "requires": { 1864 | "punycode": "^2.1.0" 1865 | } 1866 | }, 1867 | "url-parse-lax": { 1868 | "version": "3.0.0", 1869 | "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", 1870 | "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", 1871 | "dev": true, 1872 | "requires": { 1873 | "prepend-http": "^2.0.0" 1874 | } 1875 | }, 1876 | "v8-compile-cache": { 1877 | "version": "2.1.1", 1878 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", 1879 | "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", 1880 | "dev": true 1881 | }, 1882 | "which": { 1883 | "version": "2.0.2", 1884 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1885 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1886 | "dev": true, 1887 | "requires": { 1888 | "isexe": "^2.0.0" 1889 | } 1890 | }, 1891 | "widest-line": { 1892 | "version": "3.1.0", 1893 | "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", 1894 | "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", 1895 | "dev": true, 1896 | "requires": { 1897 | "string-width": "^4.0.0" 1898 | } 1899 | }, 1900 | "word-wrap": { 1901 | "version": "1.2.3", 1902 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 1903 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 1904 | "dev": true 1905 | }, 1906 | "wrappy": { 1907 | "version": "1.0.2", 1908 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1909 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1910 | "dev": true 1911 | }, 1912 | "write": { 1913 | "version": "1.0.3", 1914 | "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", 1915 | "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", 1916 | "dev": true, 1917 | "requires": { 1918 | "mkdirp": "^0.5.1" 1919 | } 1920 | }, 1921 | "write-file-atomic": { 1922 | "version": "3.0.3", 1923 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", 1924 | "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", 1925 | "dev": true, 1926 | "requires": { 1927 | "imurmurhash": "^0.1.4", 1928 | "is-typedarray": "^1.0.0", 1929 | "signal-exit": "^3.0.2", 1930 | "typedarray-to-buffer": "^3.1.5" 1931 | } 1932 | }, 1933 | "xdg-basedir": { 1934 | "version": "4.0.0", 1935 | "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", 1936 | "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", 1937 | "dev": true 1938 | }, 1939 | "yn": { 1940 | "version": "3.1.1", 1941 | "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", 1942 | "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", 1943 | "dev": true 1944 | } 1945 | } 1946 | } 1947 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-eslint-prettier-starter", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "tsc && node dist/index.js", 9 | "dev": "nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts", 10 | "script": "ts-node", 11 | "lint": "eslint .", 12 | "lint:fix": "eslint . --fix" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@babel/core": "^7.12.10", 19 | "@babel/preset-env": "^7.12.10", 20 | "@babel/preset-typescript": "^7.12.7", 21 | "@types/chalk": "^2.2.0", 22 | "@types/jest": "^26.0.19", 23 | "@types/minio": "^7.0.7", 24 | "@typescript-eslint/eslint-plugin": "3.3.0", 25 | "@typescript-eslint/parser": "3.3.0", 26 | "eslint": "7.3.0", 27 | "eslint-config-prettier": "6.11.0", 28 | "eslint-plugin-prettier": "3.1.4", 29 | "nodemon": "2.0.4", 30 | "prettier": "2.0.5", 31 | "ts-jest": "^26.4.4", 32 | "ts-node": "8.10.2", 33 | "typescript": "3.9.5" 34 | }, 35 | "dependencies": { 36 | "@types/uuid": "^8.3.0", 37 | "chalk": "^4.1.0", 38 | "jest": "^26.6.3", 39 | "minio": "^7.0.18", 40 | "uuid": "^8.3.2" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /src/abstraction-polymorph/abstracting-file-service.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import * as uuid from 'uuid' 3 | import * as Minio from 'minio' 4 | 5 | const Env = process.env['NODE_ENV'] 6 | 7 | enum Role { 8 | Manager, 9 | Employee, 10 | CLevel, 11 | } 12 | class Employee { 13 | Role: Role 14 | 15 | public isRoleHigherThan(role: Role): boolean { 16 | return true 17 | } 18 | } 19 | 20 | export class PurchaseRequest { 21 | private description: string 22 | private owner: Employee 23 | private amount: number 24 | private fileContent: Buffer 25 | private filePath: string 26 | private originalFileName: string 27 | 28 | public async Approve(approver: Employee): Promise { 29 | if ( 30 | this.amount > 10000 || 31 | approver.isRoleHigherThan(Role.Manager) || 32 | !this.owner.isRoleHigherThan(Role.Manager) 33 | ) { 34 | throw new Error( 35 | 'The amount in purchase request is higher than what you can requested' 36 | ) 37 | } 38 | 39 | const filePath = `${uuid.v4()}-${this.originalFileName}` 40 | const fileService: FileService = getFileService() 41 | await fileService.save(filePath, this.fileContent) 42 | } 43 | } 44 | 45 | interface FileService { 46 | save(filePath: string, fileContent: Buffer): Promise 47 | } 48 | function getFileService() { 49 | // นี่เรียกว่า Factory Pattern 50 | if (Env === 'local') { 51 | return new LocalFileService() 52 | } 53 | return new ProductionFileService() 54 | } 55 | class LocalFileService { 56 | async save(filePath: string, fileContent: Buffer) { 57 | fs.writeFileSync(`/tmp/${filePath}`, fileContent) 58 | } 59 | } 60 | 61 | class ProductionFileService { 62 | client: Minio.Client 63 | constructor() { 64 | this.client = new Minio.Client({ 65 | endPoint: 'localhost', 66 | port: 9000, 67 | useSSL: true, 68 | accessKey: 'minio', // Bad practice, but not sensitive in this context 69 | secretKey: 'minio123', // Bad practice, but not sensitive in this context 70 | }) 71 | } 72 | async save(filePath: string, fileContent: Buffer) { 73 | await this.client.putObject('myBucket', filePath, fileContent) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/abstraction-polymorph/abstraction-polymorph.ts: -------------------------------------------------------------------------------- 1 | interface DrawableEntity { 2 | draw(x: number, y: number): void 3 | } 4 | 5 | // ========================================= 6 | // ทีมทำงานระบบเกม 7 | // ========================================= 8 | class GameRenderer { 9 | private x: number = 0 10 | private y: number = 0 11 | 12 | constructor(private entities: DrawableEntity[]) {} 13 | 14 | public render() { 15 | for (const entity of this.entities) { 16 | entity.draw(this.x, this.y) 17 | } 18 | } 19 | } 20 | 21 | // ========================================= 22 | // ทีมทำงานศิลป์ 23 | // ========================================= 24 | class CharacterSkin1 implements DrawableEntity { 25 | draw(x: number, y: number) { 26 | // วาดตัวเอก 27 | } 28 | } 29 | 30 | class CharacterSkin2 implements DrawableEntity { 31 | draw(x: number, y: number) { 32 | // วาดตัวเอก 33 | } 34 | } 35 | 36 | // ========================================= 37 | // ประกอบร่าง 38 | // ========================================= 39 | 40 | const gameEntities: DrawableEntity[] = [new CharacterSkin1(), new CharacterSkin2()] 41 | // ทั้งสองสกินสามารถใช้แทน DrawableEntity ได้ เรียกว่า Polymorphism 42 | const renderEngine = new GameRenderer(gameEntities) 43 | renderEngine.render() 44 | -------------------------------------------------------------------------------- /src/abstraction-polymorph/minio-test.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk' 2 | import * as Minio from 'minio' 3 | import * as uuid from 'uuid' 4 | 5 | function assert(cond: boolean, msg: string) { 6 | if (!cond) { 7 | console.log(chalk.red('Assertion failed')) 8 | throw Error(msg) 9 | } 10 | } 11 | 12 | async function testMinio() { 13 | const client = new Minio.Client({ 14 | endPoint: 'localhost', 15 | port: 9000, 16 | useSSL: false, 17 | accessKey: 'minio', // Bad practice, but not sensitive in this context 18 | secretKey: 'minio123', // Bad practice, but not sensitive in this context 19 | }) 20 | const bucketName = 'mybucket' 21 | const fileUploadName = `${uuid.v4()}-hello.txt` 22 | if (!(await client.bucketExists(bucketName))) { 23 | await client.makeBucket(bucketName, 'us-east-1') 24 | } 25 | const contentToSave = `Hello world - ${uuid.v4()}` 26 | await client.putObject(bucketName, fileUploadName, contentToSave) 27 | const download = await client.getObject(bucketName, fileUploadName) 28 | const contentFromFile: Buffer = download.read() 29 | assert(contentFromFile.toString('utf8') == contentToSave, 'Content mismatch') 30 | 31 | console.log(chalk.green('Minio tested!')) 32 | } 33 | 34 | testMinio().catch((err) => console.log(err)) 35 | -------------------------------------------------------------------------------- /src/abstraction-polymorph/naive-version.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import * as uuid from 'uuid' 3 | import * as Minio from 'minio' 4 | import { Role, Employee } from './shared' 5 | 6 | const Env = process.env['NODE_ENV'] 7 | 8 | export class PurchaseRequest { 9 | private description: string 10 | private owner: Employee 11 | private amount: number 12 | private fileContent: Buffer 13 | private filePath: string 14 | private originalFileName: string 15 | 16 | public async Approve(approver: Employee): Promise { 17 | if ( 18 | this.amount > 10000 || 19 | !approver.isRoleHigherThan(Role.Manager) || 20 | !this.owner.isRoleHigherThan(Role.Manager) 21 | ) { 22 | throw new Error( 23 | 'The amount in purchase request is higher than what you can requested' 24 | ) 25 | } 26 | 27 | const filePath = `${uuid.v4()}-${this.originalFileName}` 28 | const fileService = getUploadService() 29 | fileService.save(filePath, this.fileContent) 30 | } 31 | } 32 | 33 | interface FileService { 34 | save(filePath: string, fileContent: Buffer): Promise 35 | } 36 | 37 | // Infra 38 | function getUploadService() { 39 | if (Env === 'local') { 40 | return new LocalUploadService() 41 | } 42 | if (Env === 'production') { 43 | return new ProductionUploadService() 44 | } 45 | } 46 | 47 | class LocalUploadService implements FileService { 48 | async save(filePath: string, fileContent: Buffer) { 49 | fs.writeFileSync(`/tmp/${filePath}`, fileContent) 50 | } 51 | } 52 | 53 | class ProductionUploadService implements FileService { 54 | async save(filePath: string, fileContent: Buffer) { 55 | const client = new Minio.Client({ 56 | endPoint: 'localhost', 57 | port: 9000, 58 | useSSL: true, 59 | accessKey: 'minio', // Bad practice, but not sensitive in this context 60 | secretKey: 'minio123', // Bad practice, but not sensitive in this context 61 | }) 62 | await client.putObject('myBucket', filePath, fileContent) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/abstraction-polymorph/shared.ts: -------------------------------------------------------------------------------- 1 | export enum Role { 2 | Manager, 3 | Employee, 4 | CLevel, 5 | } 6 | export class Employee { 7 | Role: Role 8 | 9 | public isRoleHigherThan(role: Role): boolean { 10 | return true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/basic-of-class/abstract-class.ts: -------------------------------------------------------------------------------- 1 | abstract class AbstractDocument { 2 | public View() { 3 | console.log('Document Viewed') 4 | } 5 | 6 | abstract Print() 7 | } 8 | -------------------------------------------------------------------------------- /src/basic-of-class/access-levels.ts: -------------------------------------------------------------------------------- 1 | // Access level 2 | 3 | // Public, Private, Protected 4 | 5 | class A { 6 | public data = 'My data' 7 | public hello() { 8 | 9 | } 10 | 11 | public greetingMessage() { 12 | return 'Hello world' 13 | } 14 | } 15 | 16 | class B extends A { 17 | method() { 18 | this.data 19 | } 20 | } 21 | 22 | const object = new A() 23 | -------------------------------------------------------------------------------- /src/basic-of-class/class-and-object.ts: -------------------------------------------------------------------------------- 1 | class Greeting { 2 | name = 'This is just a placeholder' 3 | 4 | constructor(initialName: string) { 5 | this.name = initialName 6 | } 7 | 8 | greetingMessage(): void { 9 | console.log(`Hello, ${this.name}`) 10 | } 11 | 12 | changeNameToCelebrity(to: string) { 13 | this.name = to 14 | } 15 | } 16 | 17 | class Main { 18 | public run() { 19 | const g1 = new Greeting("RealUser") 20 | g1.greetingMessage() 21 | g1.name = "SomeName" 22 | g1.greetingMessage() 23 | 24 | g1.changeNameToCelebrity('Mark Zuckerberg') 25 | g1.greetingMessage() 26 | 27 | const g2 = new Greeting("Skooldio") 28 | g2.changeNameToCelebrity('Skooldio') 29 | g2.greetingMessage() 30 | 31 | g1.greetingMessage() 32 | } 33 | } 34 | 35 | new Main().run() 36 | -------------------------------------------------------------------------------- /src/basic-of-class/class-is-prototyping.ts: -------------------------------------------------------------------------------- 1 | class User { 2 | username: string 3 | id: number 4 | email: string 5 | position: string 6 | 7 | constructor(id: number, username: string, position: string) { 8 | this.id = id 9 | this.username = username 10 | this.position = position 11 | } 12 | 13 | canManageSomethingSensitive(): boolean { 14 | if (this.position === 'CEO') { 15 | return true 16 | } 17 | return false 18 | } 19 | } 20 | 21 | const normalUser = new User(1, 'Chris', 'random employee') 22 | const superUser = new User(2, 'Mark', 'CEO') 23 | 24 | if (superUser.canManageSomethingSensitive()) { 25 | console.log(`${superUser.username} can manage sensitive stuff`) 26 | } else { 27 | console.log(`${superUser.username} cannot manage sensitive stuff`) 28 | } 29 | 30 | if (normalUser.canManageSomethingSensitive()) { 31 | console.log(`${normalUser.username} can manage sensitive stuff`) 32 | } else { 33 | console.log(`${normalUser.username} cannot manage sensitive stuff`) 34 | } 35 | 36 | // ดังนั้น ไม่ว่า User ทุกคนในระบบ จะมี Logic ในการเช็ค canManageSomethingSensitive แบบเดียวกันหมด 37 | 38 | // Class เกิดขึ้นจากความต้องการในการทำ Prototype code 39 | // Class จะล้อมข้อมูลไว้ ทำให้คนเข้าถึงข้อมูลได้ผ่าน Method เท่านั้น 40 | // Method ก็คือการส่ง Message หากันนั่นเอง 41 | -------------------------------------------------------------------------------- /src/basic-of-class/extends.ts: -------------------------------------------------------------------------------- 1 | // สมมติว่าเรามี Class 2 | export class Logger { 3 | protected logBuffer: string[] = [] 4 | 5 | appendLog(msg: string): void { 6 | this.logBuffer.push(msg) 7 | } 8 | 9 | flush() { 10 | for (const msg of this.logBuffer) { 11 | console.log(msg) 12 | } 13 | this.logBuffer = [] 14 | } 15 | } 16 | 17 | const logger = new Logger() 18 | logger.appendLog('Hello world') 19 | logger.flush() 20 | 21 | export class TimedLogger extends Logger { 22 | appendLog(msg: string): void { 23 | this.logBuffer.push(`${new Date().toISOString()}: ${msg}`) 24 | } 25 | 26 | logColor(msg: string): void { 27 | console.log('\x1b[36m%s\x1b[0m', msg) 28 | } 29 | } 30 | 31 | const timeLogger = new TimedLogger() 32 | timeLogger.appendLog('Hello world') 33 | timeLogger.appendLog('Nice to meet you') 34 | timeLogger.flush() 35 | timeLogger.logColor('Colorful log') 36 | 37 | // logColor(msg: string): void { 38 | // console.log('\x1b[36m%s\x1b[0m', msg) 39 | // } 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/basic-of-class/interface.ts: -------------------------------------------------------------------------------- 1 | interface Approvable { 2 | Approve(approverName: string): void 3 | } 4 | interface Printable { 5 | Print(): void 6 | } 7 | 8 | function confirm(doc: Approvable) { 9 | doc.Approve('Chris') 10 | } 11 | 12 | class Receipt { 13 | Approve(approverName: string): void { 14 | console.log('Receipt approved') 15 | } 16 | Print() { 17 | console.log('Receipt printed') 18 | } 19 | } 20 | 21 | class Invoice implements Approvable { 22 | Approve(approverName: string): void { 23 | console.log('Invoice approved') 24 | } 25 | } 26 | 27 | confirm(new Receipt()) 28 | confirm(new Invoice()) -------------------------------------------------------------------------------- /src/basic-of-class/readline.ts: -------------------------------------------------------------------------------- 1 | import * as readline from 'readline' 2 | 3 | const readlineInterface = readline.createInterface( 4 | process.stdin, 5 | process.stdout 6 | ) 7 | 8 | export async function readLine(query: string): Promise { 9 | return new Promise((resolve) => { 10 | readlineInterface.question(query, (val) => resolve(val)) 11 | }) 12 | } 13 | 14 | export function close() { 15 | readlineInterface.close() 16 | } 17 | -------------------------------------------------------------------------------- /src/basic-of-class/static-method.ts: -------------------------------------------------------------------------------- 1 | class StringUtils { 2 | static StaticMethod(str: string[]) { 3 | console.log('Static method called', str.join(', ')) 4 | } 5 | 6 | NormalMethod() { 7 | console.log('Method called') 8 | } 9 | } 10 | 11 | StringUtils.StaticMethod(['a', 'b']) 12 | const obj2 = new StringUtils() 13 | obj2.NormalMethod() 14 | -------------------------------------------------------------------------------- /src/basic-of-class/subclass-superclass.ts: -------------------------------------------------------------------------------- 1 | import { TimedLogger, Logger } from './extends' 2 | 3 | // TimedLogger extends Logger 4 | // Logger เป็น Superclass ของ TimedLogger 5 | // TimedLogger เป็น Subclass ของ Logger 6 | 7 | // Subclass ใช้แทน Superclass ได้ 8 | // Superclass ใช้แทน Subclass ไม่ได้ 9 | 10 | function iUseTimedLogger(log: TimedLogger) { 11 | log.appendLog('This log have a timestamp') 12 | log.flush() 13 | log.logColor('This is a colorful log') 14 | } 15 | 16 | function iUseJustALogger(log: Logger) { 17 | log.appendLog(`This log should be raw, shouldn't it?`) 18 | log.flush() 19 | } 20 | const log = new Logger() 21 | const timeLogger = new TimedLogger() 22 | iUseTimedLogger(timeLogger) 23 | -------------------------------------------------------------------------------- /src/basic-of-class/super.ts: -------------------------------------------------------------------------------- 1 | class MySpecialFormulaCalculator { 2 | protected a: number 3 | protected b: number 4 | 5 | constructor(a: number, b: number) { 6 | this.a = a 7 | this.b = b 8 | } 9 | 10 | calculate(): number { 11 | return this.a * this.b 12 | } 13 | } 14 | 15 | class FormulaAndLog extends MySpecialFormulaCalculator { 16 | calculate(): number { 17 | console.log('Calculating this special formula') 18 | return super.calculate() 19 | } 20 | } 21 | 22 | const f = new FormulaAndLog(1, 2) 23 | console.log(f.calculate()) -------------------------------------------------------------------------------- /src/encapsulation/card.ts: -------------------------------------------------------------------------------- 1 | export enum Suits { 2 | Spade, 3 | Diamond, 4 | Heart, 5 | Club, 6 | } 7 | 8 | export class Card { 9 | constructor(public number: number, public suits: Suits) {} 10 | } 11 | -------------------------------------------------------------------------------- /src/encapsulation/hand.test.ts: -------------------------------------------------------------------------------- 1 | import { Card, Suits } from './card' 2 | import { CardFrequency, Hand } from './hand' 3 | import { ComparisonResult, Rank } from './handPower' 4 | 5 | describe('Hand', () => { 6 | const straighFlushCards = [ 7 | new Card(14, Suits.Club), 8 | new Card(13, Suits.Club), 9 | new Card(12, Suits.Club), 10 | new Card(10, Suits.Club), 11 | new Card(11, Suits.Club), 12 | ] 13 | const onePairCards = [ 14 | new Card(10, Suits.Club), 15 | new Card(10, Suits.Diamond), 16 | new Card(14, Suits.Club), 17 | new Card(12, Suits.Club), 18 | new Card(11, Suits.Club), 19 | ] 20 | 21 | it('Can determined no pair', () => { 22 | const noPairCards = [ 23 | new Card(10, Suits.Club), 24 | new Card(5, Suits.Diamond), 25 | new Card(14, Suits.Club), 26 | new Card(12, Suits.Club), 27 | new Card(11, Suits.Club), 28 | ] 29 | const hand = new Hand(noPairCards) 30 | const result = hand.power() 31 | expect(result.rank).toEqual(Rank.Nothing) 32 | expect(result.highs).toEqual([14, 12, 11, 10, 5]) 33 | }) 34 | 35 | it('Can determined one pair', () => { 36 | const hand = new Hand(onePairCards) 37 | const result = hand.power() 38 | expect(result.rank).toEqual(Rank.OnePair) 39 | expect(result.highs).toEqual([10, 14, 12, 11]) 40 | }) 41 | 42 | it('Can determined two pair', () => { 43 | const cards = [ 44 | new Card(10, Suits.Club), 45 | new Card(10, Suits.Diamond), 46 | new Card(11, Suits.Club), 47 | new Card(12, Suits.Club), 48 | new Card(11, Suits.Club), 49 | ] 50 | const hand = new Hand(cards) 51 | const result = hand.power() 52 | expect(result.rank).toEqual(Rank.TwoPairs) 53 | expect(result.highs).toEqual([11, 10, 12]) 54 | }) 55 | 56 | it('Can determined three of a kind', () => { 57 | const cards = [ 58 | new Card(10, Suits.Club), 59 | new Card(12, Suits.Diamond), 60 | new Card(11, Suits.Club), 61 | new Card(11, Suits.Club), 62 | new Card(11, Suits.Club), 63 | ] 64 | const hand = new Hand(cards) 65 | const result = hand.power() 66 | expect(result.rank).toEqual(Rank.ThreeOfAKind) 67 | expect(result.highs).toEqual([11, 12, 10]) 68 | }) 69 | 70 | it('Can determined straight', () => { 71 | const cards = [ 72 | new Card(10, Suits.Club), 73 | new Card(11, Suits.Diamond), 74 | new Card(12, Suits.Club), 75 | new Card(13, Suits.Club), 76 | new Card(14, Suits.Club), 77 | ] 78 | const hand = new Hand(cards) 79 | const result = hand.power() 80 | expect(result.rank).toEqual(Rank.Straight) 81 | expect(result.highs).toEqual([14, 13, 12, 11, 10]) 82 | }) 83 | 84 | it('Can determined straight ace first', () => { 85 | const cards = [ 86 | new Card(14, Suits.Club), 87 | new Card(2, Suits.Diamond), 88 | new Card(3, Suits.Club), 89 | new Card(4, Suits.Club), 90 | new Card(5, Suits.Club), 91 | ] 92 | const hand = new Hand(cards) 93 | const result = hand.power() 94 | expect(result.rank).toEqual(Rank.Straight) 95 | expect(result.highs).toEqual([5, 4, 3, 2, 1]) 96 | }) 97 | 98 | it('Can determined flush', () => { 99 | const cards = [ 100 | new Card(14, Suits.Club), 101 | new Card(2, Suits.Club), 102 | new Card(5, Suits.Club), 103 | new Card(3, Suits.Club), 104 | new Card(10, Suits.Club), 105 | ] 106 | const hand = new Hand(cards) 107 | const result = hand.power() 108 | expect(result.rank).toEqual(Rank.Flush) 109 | expect(result.highs).toEqual([14, 10, 5, 3, 2]) 110 | }) 111 | 112 | it('Can determined Full-house', () => { 113 | const cards = [ 114 | new Card(14, Suits.Club), 115 | new Card(14, Suits.Diamond), 116 | new Card(11, Suits.Club), 117 | new Card(11, Suits.Diamond), 118 | new Card(11, Suits.Heart), 119 | ] 120 | const hand = new Hand(cards) 121 | const result = hand.power() 122 | expect(result.rank).toEqual(Rank.FullHouse) 123 | expect(result.highs).toEqual([11, 14]) 124 | }) 125 | 126 | it('Can determined Four of a kind', () => { 127 | const cards = [ 128 | new Card(14, Suits.Club), 129 | new Card(11, Suits.Diamond), 130 | new Card(11, Suits.Club), 131 | new Card(11, Suits.Diamond), 132 | new Card(11, Suits.Heart), 133 | ] 134 | const hand = new Hand(cards) 135 | const result = hand.power() 136 | expect(result.rank).toEqual(Rank.FourOfAKind) 137 | expect(result.highs).toEqual([11, 14]) 138 | }) 139 | 140 | it('Can determined Straight Flush', () => { 141 | const cards = straighFlushCards 142 | const hand = new Hand(cards) 143 | const result = hand.power() 144 | expect(result.rank).toEqual(Rank.StraightFlush) 145 | expect(result.highs).toEqual([14, 13, 12, 11, 10]) 146 | }) 147 | 148 | it('Can determined Straight Flush ace first', () => { 149 | const cards = [ 150 | new Card(14, Suits.Club), 151 | new Card(2, Suits.Club), 152 | new Card(5, Suits.Club), 153 | new Card(3, Suits.Club), 154 | new Card(4, Suits.Club), 155 | ] 156 | const hand = new Hand(cards) 157 | const result = hand.power() 158 | expect(result.rank).toEqual(Rank.StraightFlush) 159 | expect(result.highs).toEqual([5, 4, 3, 2, 1]) 160 | }) 161 | 162 | it('Straight flush win One Hand', () => { 163 | const hand1 = new Hand(straighFlushCards) 164 | const hand2 = new Hand(onePairCards) 165 | expect(hand1.compareWith(hand2)).toEqual(ComparisonResult.Win) 166 | }) 167 | }) 168 | 169 | describe('Card frequencies', () => { 170 | it('Can calculate frequency and card values', () => { 171 | const card1 = [ 172 | new Card(14, Suits.Club), 173 | new Card(14, Suits.Diamond), 174 | new Card(11, Suits.Club), 175 | new Card(11, Suits.Diamond), 176 | new Card(11, Suits.Heart), 177 | ] 178 | const card2 = [ 179 | new Card(14, Suits.Club), 180 | new Card(2, Suits.Club), 181 | new Card(5, Suits.Club), 182 | new Card(3, Suits.Club), 183 | new Card(10, Suits.Club), 184 | ] 185 | 186 | const card3 = [ 187 | new Card(10, Suits.Club), 188 | new Card(12, Suits.Diamond), 189 | new Card(11, Suits.Club), 190 | new Card(11, Suits.Club), 191 | new Card(11, Suits.Club), 192 | ] 193 | 194 | const result1 = new CardFrequency(card1) 195 | expect(result1.cardFrequencySorted()).toEqual([3, 2]) 196 | expect(result1.cardValueSortedByFrequency()).toEqual([11, 14]) 197 | 198 | const result2 = new CardFrequency(card2) 199 | expect(result2.cardFrequencySorted()).toEqual([1, 1, 1, 1, 1]) 200 | expect(result2.cardValueSortedByFrequency()).toEqual([14, 10, 5, 3, 2]) 201 | 202 | const result3 = new CardFrequency(card3) 203 | expect(result3.cardFrequencySorted()).toEqual([3, 1, 1]) 204 | expect(result3.cardValueSortedByFrequency()).toEqual([11, 12, 10]) 205 | }) 206 | 207 | it('Can match frequency pattern', () => { 208 | const card1 = [ 209 | new Card(14, Suits.Club), 210 | new Card(14, Suits.Diamond), 211 | new Card(11, Suits.Club), 212 | new Card(11, Suits.Diamond), 213 | new Card(11, Suits.Heart), 214 | ] 215 | const card2 = [ 216 | new Card(14, Suits.Club), 217 | new Card(2, Suits.Club), 218 | new Card(5, Suits.Club), 219 | new Card(3, Suits.Club), 220 | new Card(10, Suits.Club), 221 | ] 222 | 223 | const card3 = [ 224 | new Card(10, Suits.Club), 225 | new Card(12, Suits.Diamond), 226 | new Card(11, Suits.Club), 227 | new Card(11, Suits.Club), 228 | new Card(11, Suits.Club), 229 | ] 230 | 231 | const result1 = new CardFrequency(card1) 232 | const result2 = new CardFrequency(card2) 233 | const result3 = new CardFrequency(card3) 234 | 235 | expect(result1.isFrequencyMatch([3, 2])).toBeTruthy() 236 | expect(result1.isFrequencyMatch([3, 1, 1])).toBeFalsy() 237 | 238 | expect(result2.isFrequencyMatch([1, 1, 1, 1, 1])).toBeTruthy() 239 | expect(result2.isFrequencyMatch([2, 1, 1, 1])).toBeFalsy() 240 | 241 | expect(result3.isFrequencyMatch([3, 1, 1])).toBeTruthy() 242 | expect(result3.isFrequencyMatch([4, 1])).toBeFalsy() 243 | }) 244 | }) 245 | -------------------------------------------------------------------------------- /src/encapsulation/hand.ts: -------------------------------------------------------------------------------- 1 | import { Card } from './card' 2 | import { ComparisonResult, Rank, HandPower } from './handPower' 3 | import PatternMatcher from './utils/patternMatcher' 4 | 5 | type StraightResult = { 6 | straight: boolean 7 | highs: number[] 8 | } 9 | 10 | export class CardFrequency { 11 | private cardFrequencyMap: { [key: number]: number } 12 | constructor(cards: Card[]) { 13 | const cardFrequencyMap = {} 14 | for (const card of cards) { 15 | cardFrequencyMap[card.number] = (cardFrequencyMap[card.number] || 0) + 1 16 | } 17 | this.cardFrequencyMap = cardFrequencyMap 18 | } 19 | 20 | cardFrequencySorted(): number[] { 21 | return Object.values(this.cardFrequencyMap).sort().reverse() 22 | } 23 | 24 | private getCardValues() { 25 | return Object.keys(this.cardFrequencyMap).map((a) => parseInt(a)) 26 | } 27 | 28 | cardValueSortedByFrequency(): number[] { 29 | return this.getCardValues().sort((b, a) => { 30 | if (this.cardFrequencyMap[a] < this.cardFrequencyMap[b]) return -1 31 | if (this.cardFrequencyMap[a] > this.cardFrequencyMap[b]) return 1 32 | if (a < b) return -1 33 | if (b > a) return 1 34 | return 0 35 | }) 36 | } 37 | 38 | isFrequencyMatch(pattern: number[]): boolean { 39 | return new PatternMatcher( 40 | this.cardFrequencySorted(), 41 | pattern 42 | ).isSamePattern() 43 | } 44 | } 45 | 46 | export class Hand { 47 | private cards: Card[] 48 | 49 | constructor(cards: Card[]) { 50 | this.cards = cards 51 | } 52 | 53 | private isStraight(highs: number[]): StraightResult { 54 | function isBackwardConsequtive(cardValues: number[]): boolean { 55 | for (let index = 0; index < cardValues.length - 1; index++) { 56 | const thisCardValue = cardValues[index] 57 | const nextCardValue = cardValues[index + 1] 58 | if (thisCardValue - 1 !== nextCardValue) { 59 | return false 60 | } 61 | } 62 | return true 63 | } 64 | 65 | if (highs.length !== 5) { 66 | return { straight: false, highs } 67 | } 68 | if (isBackwardConsequtive(highs)) { 69 | return { straight: true, highs } 70 | } 71 | const highsAceFirst = highs 72 | .map((h) => (h === 14 ? 1 : h)) 73 | .sort() 74 | .reverse() 75 | if (isBackwardConsequtive(highsAceFirst)) { 76 | return { straight: true, highs: highsAceFirst } 77 | } 78 | return { straight: false, highs } 79 | } 80 | 81 | private isFlush(): boolean { 82 | return new Set(this.cards.map((c) => c.suits)).size === 1 83 | } 84 | 85 | public compareWith(anotherHand: Hand): ComparisonResult { 86 | return this.power().compareWith(anotherHand.power()) 87 | } 88 | 89 | public power(): HandPower { 90 | const cardFrequency = new CardFrequency(this.cards) 91 | const initialHighs = cardFrequency.cardValueSortedByFrequency() 92 | const flush = this.isFlush() 93 | const { straight, highs } = this.isStraight(initialHighs) 94 | 95 | if (straight && flush) { 96 | return new HandPower(Rank.StraightFlush, highs) 97 | } 98 | if (cardFrequency.isFrequencyMatch([4, 1])) { 99 | return new HandPower(Rank.FourOfAKind, highs) 100 | } 101 | if (cardFrequency.isFrequencyMatch([3, 2])) { 102 | return new HandPower(Rank.FullHouse, highs) 103 | } 104 | if (flush) { 105 | return new HandPower(Rank.Flush, highs) 106 | } 107 | if (straight) { 108 | return new HandPower(Rank.Straight, highs) 109 | } 110 | if (cardFrequency.isFrequencyMatch([3, 1, 1])) { 111 | return new HandPower(Rank.ThreeOfAKind, highs) 112 | } 113 | if (cardFrequency.isFrequencyMatch([2, 2, 1])) { 114 | return new HandPower(Rank.TwoPairs, highs) 115 | } 116 | if (cardFrequency.isFrequencyMatch([2, 1, 1, 1])) { 117 | return new HandPower(Rank.OnePair, highs) 118 | } 119 | if (cardFrequency.isFrequencyMatch([1, 1, 1, 1, 1])) { 120 | return new HandPower(Rank.Nothing, highs) 121 | } 122 | throw Error( 123 | `Unexpected pattern ${JSON.stringify( 124 | cardFrequency.cardFrequencySorted(), 125 | null, 126 | 2 127 | )}` 128 | ) 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/encapsulation/handPower.test.ts: -------------------------------------------------------------------------------- 1 | import { ComparisonResult, HandPower, Rank } from './handPower' 2 | 3 | describe('Hand power', () => { 4 | it('Determined winner and loser in various cases', () => { 5 | const hands = [ 6 | { 7 | hand1: new HandPower(Rank.FourOfAKind, [13, 3]), 8 | hand2: new HandPower(Rank.Flush, [13, 12, 11, 5, 3]), 9 | }, 10 | { 11 | hand1: new HandPower(Rank.Flush, [13, 12, 11, 5, 2]), 12 | hand2: new HandPower(Rank.Flush, [13, 12, 10, 5, 3]), 13 | }, 14 | { 15 | hand1: new HandPower(Rank.TwoPairs, [12, 11, 3]), 16 | hand2: new HandPower(Rank.TwoPairs, [12, 11, 2]), 17 | }, 18 | ] 19 | hands.forEach(({ hand1, hand2 }) => { 20 | expect(hand1.compareWith(hand2)).toEqual(ComparisonResult.Win) 21 | }) 22 | hands.forEach(({ hand1, hand2 }) => { 23 | expect(hand2.compareWith(hand1)).toEqual(ComparisonResult.Lose) 24 | }) 25 | }) 26 | 27 | it('Determined draw', () => { 28 | const hands = [ 29 | { 30 | hand1: new HandPower(Rank.Flush, [13, 12, 11, 5, 2]), 31 | hand2: new HandPower(Rank.Flush, [13, 12, 11, 5, 2]), 32 | }, 33 | { 34 | hand1: new HandPower(Rank.TwoPairs, [12, 11, 3]), 35 | hand2: new HandPower(Rank.TwoPairs, [12, 11, 3]), 36 | }, 37 | ] 38 | hands.forEach(({ hand1, hand2 }) => { 39 | expect(hand1.compareWith(hand2)).toEqual(ComparisonResult.Draw) 40 | }) 41 | }) 42 | }) 43 | -------------------------------------------------------------------------------- /src/encapsulation/handPower.ts: -------------------------------------------------------------------------------- 1 | export enum ComparisonResult { 2 | Win, 3 | Lose, 4 | Draw, 5 | } 6 | 7 | export enum Rank { 8 | Nothing = 0, 9 | OnePair = 1, 10 | TwoPairs = 2, 11 | ThreeOfAKind = 3, 12 | Straight = 4, 13 | Flush = 5, 14 | FullHouse = 6, 15 | FourOfAKind = 7, 16 | StraightFlush = 8, 17 | } 18 | 19 | export class HandPower { 20 | constructor(public readonly rank: Rank, public readonly highs: number[]) {} 21 | 22 | private compareHighs(handPower: HandPower): ComparisonResult { 23 | for (let index = 0; index < this.highs.length; index++) { 24 | if (this.highs[index] > handPower.highs[index]) { 25 | return ComparisonResult.Win 26 | } 27 | if (this.highs[index] < handPower.highs[index]) { 28 | return ComparisonResult.Lose 29 | } 30 | } 31 | 32 | return ComparisonResult.Draw 33 | } 34 | 35 | public compareWith(handPower: HandPower): ComparisonResult { 36 | if (this.rank > handPower.rank) { 37 | return ComparisonResult.Win 38 | } 39 | if (this.rank < handPower.rank) { 40 | return ComparisonResult.Lose 41 | } 42 | 43 | return this.compareHighs(handPower) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/encapsulation/main.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisza4/ts-oop/50fb8c2268b6327f11f09a60b1cc5eeb89bd910f/src/encapsulation/main.ts -------------------------------------------------------------------------------- /src/encapsulation/utils/patternMatcher.ts: -------------------------------------------------------------------------------- 1 | export default class PatternMatcher { 2 | constructor(private src: number[], private dest: number[]) {} 3 | 4 | public isSamePattern(): boolean { 5 | if (this.src.length !== this.dest.length) { 6 | return false 7 | } 8 | for (let i = 0; i < this.src.length; i++) { 9 | if (this.src[i] !== this.dest[i]) { 10 | return false 11 | } 12 | } 13 | return true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/inheritance/composition-over-inheritance.ts: -------------------------------------------------------------------------------- 1 | import { Employee } from '../abstraction-polymorph/shared' 2 | 3 | interface Approvable { 4 | Approve(owner: Employee) 5 | } 6 | 7 | interface Persistable { 8 | Save() 9 | } 10 | 11 | class StandardApprover { 12 | constructor(private doc: Approvable) {} 13 | 14 | public ApproveDocument(owner: Employee) { 15 | // Complicated logic in standard approve 16 | // ------------------------------------ 17 | console.log('Do things here') 18 | } 19 | } 20 | 21 | class DocumentSaver { 22 | constructor(private doc: Persistable) {} 23 | public Save() { 24 | console.log('Document saved') 25 | } 26 | } 27 | 28 | class Invoice implements Approvable, Persistable { 29 | public Approve(owner: Employee) { 30 | new StandardApprover(this).ApproveDocument(owner) 31 | } 32 | 33 | public Save() { 34 | return new DocumentSaver(this).Save() 35 | } 36 | } 37 | 38 | class Receipt implements Persistable { 39 | public Save() { 40 | return new DocumentSaver(this).Save() 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/inheritance/if-moving.ts: -------------------------------------------------------------------------------- 1 | function doThis() { 2 | console.log('doThis') 3 | } 4 | function doThat() { 5 | console.log('doThat') 6 | } 7 | 8 | function doStuffOriginal(a: number, b:number) { 9 | if (a > b) { 10 | doThis() 11 | } else { 12 | doThat() 13 | } 14 | } 15 | 16 | // แม้แต่ if พื้นๆ เราก็สามารถย้ายมาใช้ Factory/Polymorphism ได้ 17 | 18 | class DoThisRunner { 19 | run() { 20 | console.log('doThis') 21 | } 22 | } 23 | class DoThatRunner { 24 | run() { 25 | console.log('doThat') 26 | } 27 | } 28 | 29 | function DoFactory (a: number, b: number) { 30 | if (a > b) return new DoThisRunner() 31 | return new DoThatRunner() 32 | } 33 | 34 | function doStuffWithFactoryAndInheritance(a: number, b: number) { 35 | const runner = DoFactory(a, b) 36 | runner.run() 37 | } -------------------------------------------------------------------------------- /src/inheritance/inheritance-2.ts: -------------------------------------------------------------------------------- 1 | import { BaseDocument } from './inheritance' 2 | import { Role, Employee } from '../abstraction-polymorph/shared' 3 | 4 | class BaseBaseDocument extends BaseDocument { 5 | public Save() { 6 | console.log('Extra save') 7 | super.Save() 8 | } 9 | } 10 | 11 | class Invoice extends BaseBaseDocument { 12 | name = 'Invoice' 13 | private amount = 20 14 | 15 | public Approve(owner: Employee): void { 16 | if (this.amount <= 0) { 17 | throw Error('Cannot approve invoice without amount') 18 | } 19 | super.Approve(owner) 20 | } 21 | } 22 | 23 | class Receipt extends BaseBaseDocument { 24 | name = 'Receipt' 25 | } 26 | 27 | const invoice = new Invoice('Hello') 28 | const receipt = new Receipt('Receipt') 29 | invoice.Approve(new Employee()) 30 | receipt.Approve(new Employee()) 31 | 32 | -------------------------------------------------------------------------------- /src/inheritance/inheritance.ts: -------------------------------------------------------------------------------- 1 | import { Role, Employee } from '../abstraction-polymorph/shared' 2 | 3 | export abstract class BaseDocument { 4 | constructor(private description: string) {} 5 | protected name = 'Nothing' 6 | 7 | protected Save(): void { 8 | // Save to database 9 | // ...... 10 | console.log(`Document ${this.name} saved at ${new Date().toISOString()}`) 11 | } 12 | 13 | public Approve(owner: Employee): void { 14 | this.Save() 15 | console.log(`${this.name} approved`) 16 | } 17 | } 18 | 19 | class Invoice extends BaseDocument { 20 | name = 'Invoice' 21 | private amount = 20 22 | } 23 | 24 | class Receipt extends BaseDocument { 25 | name = 'Receipt' 26 | } 27 | 28 | class Memo extends BaseDocument { 29 | public Approve() { 30 | throw Error('Approve not support') 31 | } 32 | } 33 | 34 | const invoice = new Invoice('Hello') 35 | const receipt = new Receipt('Receipt') 36 | invoice.Approve(new Employee()) 37 | receipt.Approve(new Employee()) 38 | 39 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "rootDir": "src", 6 | "outDir": "dist", 7 | "sourceMap": true, 8 | "resolveJsonModule": true, 9 | "lib": ["es6", "dom"], 10 | "esModuleInterop": true 11 | }, 12 | "include": [ 13 | "src/**/*.ts" 14 | ], 15 | "exclude": [ 16 | "node_modules" 17 | ] 18 | } 19 | --------------------------------------------------------------------------------