├── .gitignore ├── 00_cli_calculator ├── .npmrc ├── README.md ├── index.d.ts ├── index.js ├── index.ts ├── package-lock.json ├── package.json └── tsconfig.json ├── 01_cli_number_guessing_game ├── README.md ├── index.js ├── index.ts ├── package-lock.json ├── package.json └── tsconfig.json ├── 02_cli_atm ├── README.md ├── index.js ├── index.ts ├── package-lock.json ├── package.json ├── tsconfig.json └── yarn.lock └── 06_SMS ├── README.md ├── lib ├── Course.js ├── Instructor.js ├── Person.js ├── SMS.js ├── Student.js ├── UMS.js ├── helpers.js ├── index.js ├── questions.js └── types.js ├── package-lock.json ├── package.json ├── src ├── Course.ts ├── Instructor.ts ├── Person.ts ├── SMS.ts ├── Student.ts ├── index.ts ├── questions.ts └── types.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | **/node_modules -------------------------------------------------------------------------------- /00_cli_calculator/.npmrc: -------------------------------------------------------------------------------- 1 | ;;;; 2 | ; npm projectconfig file: C:\Users\ZAIN\Documents\Study\classProjects\00_cli_calculator\.npmrc 3 | ; this is a simple ini-formatted file 4 | ; lines that start with semi-colons are comments 5 | ; run `npm help 7 config` for documentation of the various options 6 | ; 7 | ; Configs like `@scope:registry` map a scope to a given registry url. 8 | ; 9 | ; Configs like `///:_authToken` are auth that is restricted 10 | ; to the registry host specified. 11 | 12 | 13 | 14 | ;;;; 15 | ; all available options shown below with default values 16 | ;;;; 17 | 18 | 19 | ; _auth=null 20 | ; access=null 21 | ; all=false 22 | ; allow-same-version=false 23 | ; also=null 24 | ; audit=true 25 | ; audit-level=null 26 | ; auth-type=web 27 | ; before=null 28 | ; bin-links=true 29 | ; browser=null 30 | ; ca=null 31 | ; cache=C:\Users\ZAIN\AppData\Local/npm-cache 32 | ; cache-max=null 33 | ; cache-min=0 34 | ; cafile=null 35 | ; call= 36 | ; cert=null 37 | ; ci-name=null 38 | ; cidr=null 39 | ; color=true 40 | ; commit-hooks=true 41 | ; depth=null 42 | ; description=true 43 | ; dev=false 44 | ; 45 | ; diff-ignore-all-space=false 46 | ; diff-name-only=false 47 | ; diff-no-prefix=false 48 | ; diff-dst-prefix=b/ 49 | ; diff-src-prefix=a/ 50 | ; diff-text=false 51 | ; diff-unified=3 52 | ; dry-run=false 53 | ; editor=C:\WINDOWS\notepad.exe 54 | ; engine-strict=false 55 | ; fetch-retries=2 56 | ; fetch-retry-factor=10 57 | ; fetch-retry-maxtimeout=60000 58 | ; fetch-retry-mintimeout=10000 59 | ; fetch-timeout=300000 60 | ; force=false 61 | ; foreground-scripts=false 62 | ; format-package-lock=true 63 | ; fund=true 64 | ; git=git 65 | ; git-tag-version=true 66 | ; global=false 67 | ; globalconfig= 68 | ; global-style=false 69 | ; heading=npm 70 | ; https-proxy=null 71 | ; if-present=false 72 | ; ignore-scripts=false 73 | ; 74 | ; include-staged=false 75 | ; include-workspace-root=false 76 | ; init-author-email= 77 | ; init-author-name= 78 | ; init-author-url= 79 | ; init-license=ISC 80 | ; init-module=~/.npm-init.js 81 | ; init-version=1.0.0 82 | ; init.author.email= 83 | ; init.author.name= 84 | ; init.author.url= 85 | ; init.license=ISC 86 | ; init.module=~/.npm-init.js 87 | ; init.version=1.0.0 88 | ; install-links=true 89 | ; install-strategy=hoisted 90 | ; json=false 91 | ; key=null 92 | ; legacy-bundling=false 93 | ; legacy-peer-deps=false 94 | ; link=false 95 | ; local-address=null 96 | ; location=user 97 | ; lockfile-version=null 98 | ; loglevel=notice 99 | ; logs-dir=null 100 | ; logs-max=10 101 | ; long=false 102 | ; maxsockets=15 103 | ; message=%s 104 | ; node-options=null 105 | ; noproxy= 106 | ; offline=false 107 | ; 108 | ; omit-lockfile-registry-resolved=false 109 | ; only=null 110 | ; optional=null 111 | ; otp=null 112 | ; 113 | ; package-lock=true 114 | ; package-lock-only=false 115 | ; pack-destination=. 116 | ; parseable=false 117 | ; prefer-offline=false 118 | ; prefer-online=false 119 | ; prefix=C:\Users\ZAIN\AppData\Roaming\npm 120 | ; preid= 121 | ; production=null 122 | ; progress=true 123 | ; proxy=null 124 | ; read-only=false 125 | ; rebuild-bundle=true 126 | ; registry=https://registry.npmjs.org/ 127 | ; replace-registry-host=npmjs 128 | ; save=true 129 | ; save-bundle=false 130 | ; save-dev=false 131 | ; save-exact=false 132 | ; save-optional=false 133 | ; save-peer=false 134 | ; save-prefix=^ 135 | ; save-prod=false 136 | ; scope= 137 | ; script-shell=null 138 | ; searchexclude= 139 | ; searchlimit=20 140 | ; searchopts= 141 | ; searchstaleness=900 142 | ; shell=C:\WINDOWS\system32\cmd.exe 143 | ; shrinkwrap=true 144 | ; sign-git-commit=false 145 | ; sign-git-tag=false 146 | ; strict-peer-deps=false 147 | ; strict-ssl=true 148 | ; tag=latest 149 | ; tag-version-prefix=v 150 | ; timing=false 151 | ; tmp=C:\Users\ZAIN\AppData\Local\Temp 152 | ; umask=0 153 | ; unicode=false 154 | ; update-notifier=true 155 | ; usage=false 156 | ; user-agent=npm/{npm-version} node/{node-version} {platform} {arch} workspaces/{workspaces} {ci} 157 | ; userconfig=~/.npmrc 158 | ; version=false 159 | ; versions=false 160 | ; viewer=browser 161 | ; which=null 162 | ; 163 | ; workspaces=null 164 | ; workspaces-update=true 165 | ; yes=null 166 | -------------------------------------------------------------------------------- /00_cli_calculator/README.md: -------------------------------------------------------------------------------- 1 | Find this project on NPM: [class_project_calculator](https://www.npmjs.com/package/class_project_calculator) 2 | 3 | Use it in your own terminal by: npx class_project_calculator -------------------------------------------------------------------------------- /00_cli_calculator/index.d.ts: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | export {}; 3 | -------------------------------------------------------------------------------- /00_cli_calculator/index.js: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | import inquirer from 'inquirer'; 3 | 4 | 5 | // Weclome users 6 | // take inputs and operation 7 | // validate user input 8 | // compute results and show them 9 | // try again? 10 | 11 | 12 | let again = false; 13 | 14 | function welcomeMsg(msg) { 15 | console.log(msg + "\n"); 16 | } 17 | async function getInputFromUser() { 18 | const answers = await inquirer.prompt([ 19 | { 20 | name: "firstNumber", 21 | message: "Enter first number", 22 | type: "input", 23 | validate: function (input) { 24 | if (isNaN(input) || input === "") { 25 | return "Not a valid input"; 26 | } 27 | else { 28 | return true; 29 | } 30 | } 31 | }, 32 | { 33 | name: "operation", 34 | message: "Choose an operation", 35 | type: "list", 36 | choices: ["+", "-", "x", "/", "^", "%"] 37 | }, 38 | { 39 | name: "secondNumber", 40 | message: "Enter second number", 41 | type: "input", 42 | validate: function (input) { 43 | if (isNaN(input) || input === "") { 44 | return "Not a valid input"; 45 | } 46 | else { 47 | return true; 48 | } 49 | } 50 | } 51 | ]); 52 | const firstNumber = Number(answers.firstNumber); 53 | const secondNumber = Number(answers.secondNumber); 54 | switch (answers.operation) { 55 | case "+": 56 | console.log(`Result: ${firstNumber + secondNumber}`); 57 | break; 58 | case "-": 59 | console.log(`Result: ${firstNumber - secondNumber}`); 60 | break; 61 | case "x": 62 | console.log(`Result: ${firstNumber * secondNumber}`); 63 | break; 64 | case "/": 65 | console.log(`Result: ${firstNumber / secondNumber}`); 66 | break; 67 | case "%": 68 | console.log(`Result: ${firstNumber % secondNumber}`); 69 | break; 70 | case "^": 71 | console.log(`Result: ${firstNumber ** secondNumber}`); 72 | break; 73 | default: 74 | break; 75 | } 76 | const { confirm } = await inquirer.prompt([ 77 | { 78 | name: "confirm", 79 | message: "Do you want to do another calculation?", 80 | type: "confirm", 81 | } 82 | ]); 83 | again = confirm; 84 | console.log("\n\n"); 85 | } 86 | 87 | welcomeMsg("Welcome to the class2 Calculator"); 88 | do { 89 | getInputFromUser(); 90 | } while (again); 91 | -------------------------------------------------------------------------------- /00_cli_calculator/index.ts: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | 3 | import inquirer from 'inquirer'; 4 | 5 | // Weclome users 6 | // take inputs and operation 7 | // validate user input 8 | // compute results and show them 9 | // try again? 10 | 11 | let again = false; 12 | 13 | function welcomeMsg(msg: string): void { 14 | console.log(msg + "\n"); 15 | } 16 | 17 | type Answer = { 18 | firstNumber: string; 19 | operation: "+" | "-" | "x" | "/" | "^" | "%"; 20 | secondNumber: string; 21 | } 22 | 23 | 24 | async function getInputFromUser(): Promise { 25 | const answers: Answer = await inquirer.prompt([ 26 | { 27 | name: "firstNumber", 28 | message: "Enter first number", 29 | type: "input", 30 | validate: function (input) { 31 | if (isNaN(input) || input === "") { 32 | return "Not a valid input" 33 | } 34 | else { 35 | return true; 36 | } 37 | } 38 | }, 39 | { 40 | name: "operation", 41 | message: "Choose an operation", 42 | type: "list", 43 | choices: ["+", "-", "x", "/", "^", "%"] 44 | }, 45 | { 46 | name: "secondNumber", 47 | message: "Enter second number", 48 | type: "input", 49 | validate: function (input) { 50 | if (isNaN(input) || input === "") { 51 | return "Not a valid input" 52 | } 53 | else { 54 | return true; 55 | } 56 | } 57 | } 58 | 59 | ]) 60 | 61 | const firstNumber = Number(answers.firstNumber); 62 | const secondNumber = Number(answers.secondNumber); 63 | 64 | switch (answers.operation) { 65 | case "+": 66 | console.log(`Result: ${firstNumber + secondNumber}`); 67 | break; 68 | case "-": 69 | console.log(`Result: ${firstNumber - secondNumber}`); 70 | break; 71 | case "x": 72 | console.log(`Result: ${firstNumber * secondNumber}`); 73 | break; 74 | case "/": 75 | console.log(`Result: ${firstNumber / secondNumber}`); 76 | break; 77 | case "%": 78 | console.log(`Result: ${firstNumber % secondNumber}`); 79 | break; 80 | case "^": 81 | console.log(`Result: ${firstNumber ** secondNumber}`); 82 | break; 83 | default: 84 | break; 85 | } 86 | 87 | 88 | const { confirm } = await inquirer.prompt([ 89 | { 90 | name: "confirm", 91 | message: "Do you want to do another calculation?", 92 | type: "confirm", 93 | } 94 | ]) 95 | 96 | again = confirm; 97 | console.log("\n\n") 98 | 99 | } 100 | 101 | 102 | 103 | welcomeMsg("Welcome to the class2 Calculator"); 104 | 105 | do{ 106 | getInputFromUser(); 107 | } while(again) -------------------------------------------------------------------------------- /00_cli_calculator/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "class2", 3 | "version": "2.0.1", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "class2", 9 | "version": "2.0.1", 10 | "license": "ISC", 11 | "dependencies": { 12 | "inquirer": "^9.1.4" 13 | }, 14 | "devDependencies": { 15 | "@types/inquirer": "^9.0.3" 16 | } 17 | }, 18 | "node_modules/@types/inquirer": { 19 | "version": "9.0.3", 20 | "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.3.tgz", 21 | "integrity": "sha512-CzNkWqQftcmk2jaCWdBTf9Sm7xSw4rkI1zpU/Udw3HX5//adEZUIm9STtoRP1qgWj0CWQtJ9UTvqmO2NNjhMJw==", 22 | "dev": true, 23 | "dependencies": { 24 | "@types/through": "*", 25 | "rxjs": "^7.2.0" 26 | } 27 | }, 28 | "node_modules/@types/node": { 29 | "version": "18.11.9", 30 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", 31 | "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==", 32 | "dev": true 33 | }, 34 | "node_modules/@types/through": { 35 | "version": "0.0.30", 36 | "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz", 37 | "integrity": "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==", 38 | "dev": true, 39 | "dependencies": { 40 | "@types/node": "*" 41 | } 42 | }, 43 | "node_modules/ansi-escapes": { 44 | "version": "6.0.0", 45 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.0.0.tgz", 46 | "integrity": "sha512-IG23inYII3dWlU2EyiAiGj6Bwal5GzsgPMwjYGvc1HPE2dgbj4ZB5ToWBKSquKw74nB3TIuOwaI6/jSULzfgrw==", 47 | "dependencies": { 48 | "type-fest": "^3.0.0" 49 | }, 50 | "engines": { 51 | "node": ">=14.16" 52 | }, 53 | "funding": { 54 | "url": "https://github.com/sponsors/sindresorhus" 55 | } 56 | }, 57 | "node_modules/ansi-regex": { 58 | "version": "6.0.1", 59 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", 60 | "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", 61 | "engines": { 62 | "node": ">=12" 63 | }, 64 | "funding": { 65 | "url": "https://github.com/chalk/ansi-regex?sponsor=1" 66 | } 67 | }, 68 | "node_modules/ansi-styles": { 69 | "version": "6.2.1", 70 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", 71 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", 72 | "engines": { 73 | "node": ">=12" 74 | }, 75 | "funding": { 76 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 77 | } 78 | }, 79 | "node_modules/base64-js": { 80 | "version": "1.5.1", 81 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 82 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 83 | "funding": [ 84 | { 85 | "type": "github", 86 | "url": "https://github.com/sponsors/feross" 87 | }, 88 | { 89 | "type": "patreon", 90 | "url": "https://www.patreon.com/feross" 91 | }, 92 | { 93 | "type": "consulting", 94 | "url": "https://feross.org/support" 95 | } 96 | ] 97 | }, 98 | "node_modules/bl": { 99 | "version": "5.1.0", 100 | "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", 101 | "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", 102 | "dependencies": { 103 | "buffer": "^6.0.3", 104 | "inherits": "^2.0.4", 105 | "readable-stream": "^3.4.0" 106 | } 107 | }, 108 | "node_modules/buffer": { 109 | "version": "6.0.3", 110 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", 111 | "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", 112 | "funding": [ 113 | { 114 | "type": "github", 115 | "url": "https://github.com/sponsors/feross" 116 | }, 117 | { 118 | "type": "patreon", 119 | "url": "https://www.patreon.com/feross" 120 | }, 121 | { 122 | "type": "consulting", 123 | "url": "https://feross.org/support" 124 | } 125 | ], 126 | "dependencies": { 127 | "base64-js": "^1.3.1", 128 | "ieee754": "^1.2.1" 129 | } 130 | }, 131 | "node_modules/chalk": { 132 | "version": "5.1.2", 133 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.1.2.tgz", 134 | "integrity": "sha512-E5CkT4jWURs1Vy5qGJye+XwCkNj7Od3Af7CP6SujMetSMkLs8Do2RWJK5yx1wamHV/op8Rz+9rltjaTQWDnEFQ==", 135 | "engines": { 136 | "node": "^12.17.0 || ^14.13 || >=16.0.0" 137 | }, 138 | "funding": { 139 | "url": "https://github.com/chalk/chalk?sponsor=1" 140 | } 141 | }, 142 | "node_modules/chardet": { 143 | "version": "0.7.0", 144 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", 145 | "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" 146 | }, 147 | "node_modules/cli-cursor": { 148 | "version": "4.0.0", 149 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", 150 | "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", 151 | "dependencies": { 152 | "restore-cursor": "^4.0.0" 153 | }, 154 | "engines": { 155 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 156 | }, 157 | "funding": { 158 | "url": "https://github.com/sponsors/sindresorhus" 159 | } 160 | }, 161 | "node_modules/cli-spinners": { 162 | "version": "2.7.0", 163 | "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", 164 | "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", 165 | "engines": { 166 | "node": ">=6" 167 | }, 168 | "funding": { 169 | "url": "https://github.com/sponsors/sindresorhus" 170 | } 171 | }, 172 | "node_modules/cli-width": { 173 | "version": "4.0.0", 174 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.0.0.tgz", 175 | "integrity": "sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==", 176 | "engines": { 177 | "node": ">= 12" 178 | } 179 | }, 180 | "node_modules/clone": { 181 | "version": "1.0.4", 182 | "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", 183 | "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", 184 | "engines": { 185 | "node": ">=0.8" 186 | } 187 | }, 188 | "node_modules/defaults": { 189 | "version": "1.0.4", 190 | "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", 191 | "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", 192 | "dependencies": { 193 | "clone": "^1.0.2" 194 | }, 195 | "funding": { 196 | "url": "https://github.com/sponsors/sindresorhus" 197 | } 198 | }, 199 | "node_modules/eastasianwidth": { 200 | "version": "0.2.0", 201 | "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", 202 | "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" 203 | }, 204 | "node_modules/emoji-regex": { 205 | "version": "9.2.2", 206 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 207 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" 208 | }, 209 | "node_modules/escape-string-regexp": { 210 | "version": "5.0.0", 211 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", 212 | "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", 213 | "engines": { 214 | "node": ">=12" 215 | }, 216 | "funding": { 217 | "url": "https://github.com/sponsors/sindresorhus" 218 | } 219 | }, 220 | "node_modules/external-editor": { 221 | "version": "3.1.0", 222 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", 223 | "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", 224 | "dependencies": { 225 | "chardet": "^0.7.0", 226 | "iconv-lite": "^0.4.24", 227 | "tmp": "^0.0.33" 228 | }, 229 | "engines": { 230 | "node": ">=4" 231 | } 232 | }, 233 | "node_modules/figures": { 234 | "version": "5.0.0", 235 | "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", 236 | "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", 237 | "dependencies": { 238 | "escape-string-regexp": "^5.0.0", 239 | "is-unicode-supported": "^1.2.0" 240 | }, 241 | "engines": { 242 | "node": ">=14" 243 | }, 244 | "funding": { 245 | "url": "https://github.com/sponsors/sindresorhus" 246 | } 247 | }, 248 | "node_modules/iconv-lite": { 249 | "version": "0.4.24", 250 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 251 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 252 | "dependencies": { 253 | "safer-buffer": ">= 2.1.2 < 3" 254 | }, 255 | "engines": { 256 | "node": ">=0.10.0" 257 | } 258 | }, 259 | "node_modules/ieee754": { 260 | "version": "1.2.1", 261 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 262 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 263 | "funding": [ 264 | { 265 | "type": "github", 266 | "url": "https://github.com/sponsors/feross" 267 | }, 268 | { 269 | "type": "patreon", 270 | "url": "https://www.patreon.com/feross" 271 | }, 272 | { 273 | "type": "consulting", 274 | "url": "https://feross.org/support" 275 | } 276 | ] 277 | }, 278 | "node_modules/inherits": { 279 | "version": "2.0.4", 280 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 281 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 282 | }, 283 | "node_modules/inquirer": { 284 | "version": "9.1.4", 285 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.1.4.tgz", 286 | "integrity": "sha512-9hiJxE5gkK/cM2d1mTEnuurGTAoHebbkX0BYl3h7iEg7FYfuNIom+nDfBCSWtvSnoSrWCeBxqqBZu26xdlJlXA==", 287 | "dependencies": { 288 | "ansi-escapes": "^6.0.0", 289 | "chalk": "^5.1.2", 290 | "cli-cursor": "^4.0.0", 291 | "cli-width": "^4.0.0", 292 | "external-editor": "^3.0.3", 293 | "figures": "^5.0.0", 294 | "lodash": "^4.17.21", 295 | "mute-stream": "0.0.8", 296 | "ora": "^6.1.2", 297 | "run-async": "^2.4.0", 298 | "rxjs": "^7.5.7", 299 | "string-width": "^5.1.2", 300 | "strip-ansi": "^7.0.1", 301 | "through": "^2.3.6", 302 | "wrap-ansi": "^8.0.1" 303 | }, 304 | "engines": { 305 | "node": ">=12.0.0" 306 | } 307 | }, 308 | "node_modules/is-interactive": { 309 | "version": "2.0.0", 310 | "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", 311 | "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", 312 | "engines": { 313 | "node": ">=12" 314 | }, 315 | "funding": { 316 | "url": "https://github.com/sponsors/sindresorhus" 317 | } 318 | }, 319 | "node_modules/is-unicode-supported": { 320 | "version": "1.3.0", 321 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", 322 | "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", 323 | "engines": { 324 | "node": ">=12" 325 | }, 326 | "funding": { 327 | "url": "https://github.com/sponsors/sindresorhus" 328 | } 329 | }, 330 | "node_modules/lodash": { 331 | "version": "4.17.21", 332 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 333 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 334 | }, 335 | "node_modules/log-symbols": { 336 | "version": "5.1.0", 337 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", 338 | "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", 339 | "dependencies": { 340 | "chalk": "^5.0.0", 341 | "is-unicode-supported": "^1.1.0" 342 | }, 343 | "engines": { 344 | "node": ">=12" 345 | }, 346 | "funding": { 347 | "url": "https://github.com/sponsors/sindresorhus" 348 | } 349 | }, 350 | "node_modules/mimic-fn": { 351 | "version": "2.1.0", 352 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 353 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", 354 | "engines": { 355 | "node": ">=6" 356 | } 357 | }, 358 | "node_modules/mute-stream": { 359 | "version": "0.0.8", 360 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", 361 | "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" 362 | }, 363 | "node_modules/onetime": { 364 | "version": "5.1.2", 365 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", 366 | "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", 367 | "dependencies": { 368 | "mimic-fn": "^2.1.0" 369 | }, 370 | "engines": { 371 | "node": ">=6" 372 | }, 373 | "funding": { 374 | "url": "https://github.com/sponsors/sindresorhus" 375 | } 376 | }, 377 | "node_modules/ora": { 378 | "version": "6.1.2", 379 | "resolved": "https://registry.npmjs.org/ora/-/ora-6.1.2.tgz", 380 | "integrity": "sha512-EJQ3NiP5Xo94wJXIzAyOtSb0QEIAUu7m8t6UZ9krbz0vAJqr92JpcK/lEXg91q6B9pEGqrykkd2EQplnifDSBw==", 381 | "dependencies": { 382 | "bl": "^5.0.0", 383 | "chalk": "^5.0.0", 384 | "cli-cursor": "^4.0.0", 385 | "cli-spinners": "^2.6.1", 386 | "is-interactive": "^2.0.0", 387 | "is-unicode-supported": "^1.1.0", 388 | "log-symbols": "^5.1.0", 389 | "strip-ansi": "^7.0.1", 390 | "wcwidth": "^1.0.1" 391 | }, 392 | "engines": { 393 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 394 | }, 395 | "funding": { 396 | "url": "https://github.com/sponsors/sindresorhus" 397 | } 398 | }, 399 | "node_modules/os-tmpdir": { 400 | "version": "1.0.2", 401 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 402 | "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", 403 | "engines": { 404 | "node": ">=0.10.0" 405 | } 406 | }, 407 | "node_modules/readable-stream": { 408 | "version": "3.6.0", 409 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 410 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 411 | "dependencies": { 412 | "inherits": "^2.0.3", 413 | "string_decoder": "^1.1.1", 414 | "util-deprecate": "^1.0.1" 415 | }, 416 | "engines": { 417 | "node": ">= 6" 418 | } 419 | }, 420 | "node_modules/restore-cursor": { 421 | "version": "4.0.0", 422 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", 423 | "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", 424 | "dependencies": { 425 | "onetime": "^5.1.0", 426 | "signal-exit": "^3.0.2" 427 | }, 428 | "engines": { 429 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 430 | }, 431 | "funding": { 432 | "url": "https://github.com/sponsors/sindresorhus" 433 | } 434 | }, 435 | "node_modules/run-async": { 436 | "version": "2.4.1", 437 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", 438 | "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", 439 | "engines": { 440 | "node": ">=0.12.0" 441 | } 442 | }, 443 | "node_modules/rxjs": { 444 | "version": "7.5.7", 445 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", 446 | "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", 447 | "dependencies": { 448 | "tslib": "^2.1.0" 449 | } 450 | }, 451 | "node_modules/safe-buffer": { 452 | "version": "5.2.1", 453 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 454 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 455 | "funding": [ 456 | { 457 | "type": "github", 458 | "url": "https://github.com/sponsors/feross" 459 | }, 460 | { 461 | "type": "patreon", 462 | "url": "https://www.patreon.com/feross" 463 | }, 464 | { 465 | "type": "consulting", 466 | "url": "https://feross.org/support" 467 | } 468 | ] 469 | }, 470 | "node_modules/safer-buffer": { 471 | "version": "2.1.2", 472 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 473 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 474 | }, 475 | "node_modules/signal-exit": { 476 | "version": "3.0.7", 477 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", 478 | "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" 479 | }, 480 | "node_modules/string_decoder": { 481 | "version": "1.3.0", 482 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 483 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 484 | "dependencies": { 485 | "safe-buffer": "~5.2.0" 486 | } 487 | }, 488 | "node_modules/string-width": { 489 | "version": "5.1.2", 490 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", 491 | "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", 492 | "dependencies": { 493 | "eastasianwidth": "^0.2.0", 494 | "emoji-regex": "^9.2.2", 495 | "strip-ansi": "^7.0.1" 496 | }, 497 | "engines": { 498 | "node": ">=12" 499 | }, 500 | "funding": { 501 | "url": "https://github.com/sponsors/sindresorhus" 502 | } 503 | }, 504 | "node_modules/strip-ansi": { 505 | "version": "7.0.1", 506 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", 507 | "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", 508 | "dependencies": { 509 | "ansi-regex": "^6.0.1" 510 | }, 511 | "engines": { 512 | "node": ">=12" 513 | }, 514 | "funding": { 515 | "url": "https://github.com/chalk/strip-ansi?sponsor=1" 516 | } 517 | }, 518 | "node_modules/through": { 519 | "version": "2.3.8", 520 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 521 | "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" 522 | }, 523 | "node_modules/tmp": { 524 | "version": "0.0.33", 525 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 526 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 527 | "dependencies": { 528 | "os-tmpdir": "~1.0.2" 529 | }, 530 | "engines": { 531 | "node": ">=0.6.0" 532 | } 533 | }, 534 | "node_modules/tslib": { 535 | "version": "2.4.1", 536 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", 537 | "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" 538 | }, 539 | "node_modules/type-fest": { 540 | "version": "3.2.0", 541 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.2.0.tgz", 542 | "integrity": "sha512-Il3wdLRzWvbAEtocgxGQA9YOoRVeVUGOMBtel5LdEpNeEAol6GJTLw8GbX6Z8EIMfvfhoOXs2bwOijtAZdK5og==", 543 | "engines": { 544 | "node": ">=14.16" 545 | }, 546 | "funding": { 547 | "url": "https://github.com/sponsors/sindresorhus" 548 | } 549 | }, 550 | "node_modules/util-deprecate": { 551 | "version": "1.0.2", 552 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 553 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" 554 | }, 555 | "node_modules/wcwidth": { 556 | "version": "1.0.1", 557 | "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", 558 | "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", 559 | "dependencies": { 560 | "defaults": "^1.0.3" 561 | } 562 | }, 563 | "node_modules/wrap-ansi": { 564 | "version": "8.0.1", 565 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.0.1.tgz", 566 | "integrity": "sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==", 567 | "dependencies": { 568 | "ansi-styles": "^6.1.0", 569 | "string-width": "^5.0.1", 570 | "strip-ansi": "^7.0.1" 571 | }, 572 | "engines": { 573 | "node": ">=12" 574 | }, 575 | "funding": { 576 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 577 | } 578 | } 579 | }, 580 | "dependencies": { 581 | "@types/inquirer": { 582 | "version": "9.0.3", 583 | "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.3.tgz", 584 | "integrity": "sha512-CzNkWqQftcmk2jaCWdBTf9Sm7xSw4rkI1zpU/Udw3HX5//adEZUIm9STtoRP1qgWj0CWQtJ9UTvqmO2NNjhMJw==", 585 | "dev": true, 586 | "requires": { 587 | "@types/through": "*", 588 | "rxjs": "^7.2.0" 589 | } 590 | }, 591 | "@types/node": { 592 | "version": "18.11.9", 593 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", 594 | "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==", 595 | "dev": true 596 | }, 597 | "@types/through": { 598 | "version": "0.0.30", 599 | "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz", 600 | "integrity": "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==", 601 | "dev": true, 602 | "requires": { 603 | "@types/node": "*" 604 | } 605 | }, 606 | "ansi-escapes": { 607 | "version": "6.0.0", 608 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.0.0.tgz", 609 | "integrity": "sha512-IG23inYII3dWlU2EyiAiGj6Bwal5GzsgPMwjYGvc1HPE2dgbj4ZB5ToWBKSquKw74nB3TIuOwaI6/jSULzfgrw==", 610 | "requires": { 611 | "type-fest": "^3.0.0" 612 | } 613 | }, 614 | "ansi-regex": { 615 | "version": "6.0.1", 616 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", 617 | "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" 618 | }, 619 | "ansi-styles": { 620 | "version": "6.2.1", 621 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", 622 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" 623 | }, 624 | "base64-js": { 625 | "version": "1.5.1", 626 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 627 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" 628 | }, 629 | "bl": { 630 | "version": "5.1.0", 631 | "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", 632 | "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", 633 | "requires": { 634 | "buffer": "^6.0.3", 635 | "inherits": "^2.0.4", 636 | "readable-stream": "^3.4.0" 637 | } 638 | }, 639 | "buffer": { 640 | "version": "6.0.3", 641 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", 642 | "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", 643 | "requires": { 644 | "base64-js": "^1.3.1", 645 | "ieee754": "^1.2.1" 646 | } 647 | }, 648 | "chalk": { 649 | "version": "5.1.2", 650 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.1.2.tgz", 651 | "integrity": "sha512-E5CkT4jWURs1Vy5qGJye+XwCkNj7Od3Af7CP6SujMetSMkLs8Do2RWJK5yx1wamHV/op8Rz+9rltjaTQWDnEFQ==" 652 | }, 653 | "chardet": { 654 | "version": "0.7.0", 655 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", 656 | "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" 657 | }, 658 | "cli-cursor": { 659 | "version": "4.0.0", 660 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", 661 | "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", 662 | "requires": { 663 | "restore-cursor": "^4.0.0" 664 | } 665 | }, 666 | "cli-spinners": { 667 | "version": "2.7.0", 668 | "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", 669 | "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==" 670 | }, 671 | "cli-width": { 672 | "version": "4.0.0", 673 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.0.0.tgz", 674 | "integrity": "sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==" 675 | }, 676 | "clone": { 677 | "version": "1.0.4", 678 | "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", 679 | "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" 680 | }, 681 | "defaults": { 682 | "version": "1.0.4", 683 | "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", 684 | "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", 685 | "requires": { 686 | "clone": "^1.0.2" 687 | } 688 | }, 689 | "eastasianwidth": { 690 | "version": "0.2.0", 691 | "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", 692 | "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" 693 | }, 694 | "emoji-regex": { 695 | "version": "9.2.2", 696 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 697 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" 698 | }, 699 | "escape-string-regexp": { 700 | "version": "5.0.0", 701 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", 702 | "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==" 703 | }, 704 | "external-editor": { 705 | "version": "3.1.0", 706 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", 707 | "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", 708 | "requires": { 709 | "chardet": "^0.7.0", 710 | "iconv-lite": "^0.4.24", 711 | "tmp": "^0.0.33" 712 | } 713 | }, 714 | "figures": { 715 | "version": "5.0.0", 716 | "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", 717 | "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", 718 | "requires": { 719 | "escape-string-regexp": "^5.0.0", 720 | "is-unicode-supported": "^1.2.0" 721 | } 722 | }, 723 | "iconv-lite": { 724 | "version": "0.4.24", 725 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 726 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 727 | "requires": { 728 | "safer-buffer": ">= 2.1.2 < 3" 729 | } 730 | }, 731 | "ieee754": { 732 | "version": "1.2.1", 733 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 734 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" 735 | }, 736 | "inherits": { 737 | "version": "2.0.4", 738 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 739 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 740 | }, 741 | "inquirer": { 742 | "version": "9.1.4", 743 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.1.4.tgz", 744 | "integrity": "sha512-9hiJxE5gkK/cM2d1mTEnuurGTAoHebbkX0BYl3h7iEg7FYfuNIom+nDfBCSWtvSnoSrWCeBxqqBZu26xdlJlXA==", 745 | "requires": { 746 | "ansi-escapes": "^6.0.0", 747 | "chalk": "^5.1.2", 748 | "cli-cursor": "^4.0.0", 749 | "cli-width": "^4.0.0", 750 | "external-editor": "^3.0.3", 751 | "figures": "^5.0.0", 752 | "lodash": "^4.17.21", 753 | "mute-stream": "0.0.8", 754 | "ora": "^6.1.2", 755 | "run-async": "^2.4.0", 756 | "rxjs": "^7.5.7", 757 | "string-width": "^5.1.2", 758 | "strip-ansi": "^7.0.1", 759 | "through": "^2.3.6", 760 | "wrap-ansi": "^8.0.1" 761 | } 762 | }, 763 | "is-interactive": { 764 | "version": "2.0.0", 765 | "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", 766 | "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==" 767 | }, 768 | "is-unicode-supported": { 769 | "version": "1.3.0", 770 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", 771 | "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==" 772 | }, 773 | "lodash": { 774 | "version": "4.17.21", 775 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 776 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 777 | }, 778 | "log-symbols": { 779 | "version": "5.1.0", 780 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", 781 | "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", 782 | "requires": { 783 | "chalk": "^5.0.0", 784 | "is-unicode-supported": "^1.1.0" 785 | } 786 | }, 787 | "mimic-fn": { 788 | "version": "2.1.0", 789 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 790 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" 791 | }, 792 | "mute-stream": { 793 | "version": "0.0.8", 794 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", 795 | "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" 796 | }, 797 | "onetime": { 798 | "version": "5.1.2", 799 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", 800 | "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", 801 | "requires": { 802 | "mimic-fn": "^2.1.0" 803 | } 804 | }, 805 | "ora": { 806 | "version": "6.1.2", 807 | "resolved": "https://registry.npmjs.org/ora/-/ora-6.1.2.tgz", 808 | "integrity": "sha512-EJQ3NiP5Xo94wJXIzAyOtSb0QEIAUu7m8t6UZ9krbz0vAJqr92JpcK/lEXg91q6B9pEGqrykkd2EQplnifDSBw==", 809 | "requires": { 810 | "bl": "^5.0.0", 811 | "chalk": "^5.0.0", 812 | "cli-cursor": "^4.0.0", 813 | "cli-spinners": "^2.6.1", 814 | "is-interactive": "^2.0.0", 815 | "is-unicode-supported": "^1.1.0", 816 | "log-symbols": "^5.1.0", 817 | "strip-ansi": "^7.0.1", 818 | "wcwidth": "^1.0.1" 819 | } 820 | }, 821 | "os-tmpdir": { 822 | "version": "1.0.2", 823 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 824 | "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==" 825 | }, 826 | "readable-stream": { 827 | "version": "3.6.0", 828 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 829 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 830 | "requires": { 831 | "inherits": "^2.0.3", 832 | "string_decoder": "^1.1.1", 833 | "util-deprecate": "^1.0.1" 834 | } 835 | }, 836 | "restore-cursor": { 837 | "version": "4.0.0", 838 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", 839 | "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", 840 | "requires": { 841 | "onetime": "^5.1.0", 842 | "signal-exit": "^3.0.2" 843 | } 844 | }, 845 | "run-async": { 846 | "version": "2.4.1", 847 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", 848 | "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" 849 | }, 850 | "rxjs": { 851 | "version": "7.5.7", 852 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", 853 | "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", 854 | "requires": { 855 | "tslib": "^2.1.0" 856 | } 857 | }, 858 | "safe-buffer": { 859 | "version": "5.2.1", 860 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 861 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 862 | }, 863 | "safer-buffer": { 864 | "version": "2.1.2", 865 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 866 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 867 | }, 868 | "signal-exit": { 869 | "version": "3.0.7", 870 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", 871 | "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" 872 | }, 873 | "string_decoder": { 874 | "version": "1.3.0", 875 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 876 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 877 | "requires": { 878 | "safe-buffer": "~5.2.0" 879 | } 880 | }, 881 | "string-width": { 882 | "version": "5.1.2", 883 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", 884 | "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", 885 | "requires": { 886 | "eastasianwidth": "^0.2.0", 887 | "emoji-regex": "^9.2.2", 888 | "strip-ansi": "^7.0.1" 889 | } 890 | }, 891 | "strip-ansi": { 892 | "version": "7.0.1", 893 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", 894 | "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", 895 | "requires": { 896 | "ansi-regex": "^6.0.1" 897 | } 898 | }, 899 | "through": { 900 | "version": "2.3.8", 901 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 902 | "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" 903 | }, 904 | "tmp": { 905 | "version": "0.0.33", 906 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 907 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 908 | "requires": { 909 | "os-tmpdir": "~1.0.2" 910 | } 911 | }, 912 | "tslib": { 913 | "version": "2.4.1", 914 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", 915 | "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" 916 | }, 917 | "type-fest": { 918 | "version": "3.2.0", 919 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.2.0.tgz", 920 | "integrity": "sha512-Il3wdLRzWvbAEtocgxGQA9YOoRVeVUGOMBtel5LdEpNeEAol6GJTLw8GbX6Z8EIMfvfhoOXs2bwOijtAZdK5og==" 921 | }, 922 | "util-deprecate": { 923 | "version": "1.0.2", 924 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 925 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" 926 | }, 927 | "wcwidth": { 928 | "version": "1.0.1", 929 | "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", 930 | "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", 931 | "requires": { 932 | "defaults": "^1.0.3" 933 | } 934 | }, 935 | "wrap-ansi": { 936 | "version": "8.0.1", 937 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.0.1.tgz", 938 | "integrity": "sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==", 939 | "requires": { 940 | "ansi-styles": "^6.1.0", 941 | "string-width": "^5.0.1", 942 | "strip-ansi": "^7.0.1" 943 | } 944 | } 945 | } 946 | } 947 | -------------------------------------------------------------------------------- /00_cli_calculator/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "class_project_calculator", 3 | "version": "2.0.1", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "bin": { 8 | "calculator": "index.js" 9 | }, 10 | "scripts": { 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "dependencies": { 17 | "inquirer": "^9.1.4" 18 | }, 19 | "devDependencies": { 20 | "@types/inquirer": "^9.0.3" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /00_cli_calculator/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "ES2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "NodeNext", /* Specify what module code is generated. */ 29 | // "rootDir": "./", /* Specify the root folder within your source files. */ 30 | "moduleResolution": "NodeNext", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | // "resolveJsonModule": true, /* Enable importing .json files. */ 39 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 40 | 41 | /* JavaScript Support */ 42 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 43 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 44 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 45 | 46 | /* Emit */ 47 | "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 48 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 49 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 50 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 51 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 52 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 53 | // "removeComments": true, /* Disable emitting comments. */ 54 | // "noEmit": true, /* Disable emitting files from a compilation. */ 55 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 56 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 57 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 58 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 59 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 60 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 61 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 62 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 63 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 64 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 65 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 66 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 67 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 68 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 69 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 70 | 71 | /* Interop Constraints */ 72 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 73 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 74 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 75 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 76 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 77 | 78 | /* Type Checking */ 79 | "strict": true, /* Enable all strict type-checking options. */ 80 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 81 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 82 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 83 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 84 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 85 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 86 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 87 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 88 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 89 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 90 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 91 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 92 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 93 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 94 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 95 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 96 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 97 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 98 | 99 | /* Completeness */ 100 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 101 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /01_cli_number_guessing_game/README.md: -------------------------------------------------------------------------------- 1 | Find this project on NPM: [class-number-guessing-game](https://www.npmjs.com/package/ class-number-guessing-game) 2 | 3 | Use it in your own terminal by: npx class-number-guessing-game -------------------------------------------------------------------------------- /01_cli_number_guessing_game/index.js: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | import inquirer from "inquirer"; 3 | const generateARandomNumber = (min = 1, max = 10) => { 4 | return Number(Math.floor(Math.random() * (max - min + 1)) + min); 5 | }; 6 | const TOTAL_ROUNDS = 5; 7 | let rounds = TOTAL_ROUNDS; 8 | let secretNumber = generateARandomNumber(); 9 | let wantToContinue = true; 10 | let record = { total: 0, won: 0, lost: 0 }; 11 | const askIfWantsToPlayAgain = async (win) => { 12 | if (win) { 13 | console.log("You won."); 14 | } 15 | else { 16 | console.log(`You loose. Secret number was ${secretNumber}`); 17 | } 18 | console.log(""); 19 | const again = await inquirer.prompt([{ 20 | name: "again", 21 | type: "confirm", 22 | message: "Want to play again? ", 23 | }]); 24 | if (again.again) { 25 | rounds = TOTAL_ROUNDS; 26 | secretNumber = generateARandomNumber(); 27 | } 28 | else { 29 | wantToContinue = false; 30 | console.log("Die in hell"); 31 | } 32 | }; 33 | const welcomeMessage = () => { 34 | console.clear(); 35 | console.log("************** Record **************"); 36 | console.log(`Total Played: ${record.total}, Won: ${record.won}, Lost: ${record.lost}`); 37 | console.log("************************************"); 38 | console.log("\nWelcome to the secret number guessing game."); 39 | console.log(`You will have ${TOTAL_ROUNDS} rounds to guess the number \n`); 40 | }; 41 | const playARound = async () => { 42 | const answer = await inquirer.prompt([{ 43 | name: "guess", 44 | type: "input", 45 | message: "Your guess: ", 46 | askAnswered: true, 47 | validate: (input) => { 48 | if (isNaN(input)) { 49 | return "Pleaee enter a number"; 50 | } 51 | if (Number(input) > 10) { 52 | return "Pleaee enter a number less than 10"; 53 | } 54 | return true; 55 | } 56 | }]); 57 | rounds--; 58 | if (Number(answer.guess) === secretNumber) { 59 | record.total++; 60 | record.won++; 61 | await askIfWantsToPlayAgain(true); 62 | } 63 | else if (rounds >= 1) { 64 | console.log(`Wrong guess. You have ${rounds} left. Try Again`); 65 | } 66 | else { 67 | record.total++; 68 | record.lost++; 69 | await askIfWantsToPlayAgain(false); 70 | } 71 | }; 72 | do { 73 | if (rounds === TOTAL_ROUNDS) { 74 | welcomeMessage(); 75 | } 76 | await playARound(); 77 | } while (rounds > 0 || wantToContinue); 78 | -------------------------------------------------------------------------------- /01_cli_number_guessing_game/index.ts: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | 3 | import inquirer from "inquirer"; 4 | 5 | 6 | const generateARandomNumber = (min: number = 1, max: number = 10): number => { 7 | return Number(Math.floor(Math.random() * (max - min + 1)) + min); 8 | } 9 | 10 | 11 | const TOTAL_ROUNDS = 5; 12 | let rounds = TOTAL_ROUNDS; 13 | let secretNumber = generateARandomNumber(); 14 | let wantToContinue = true; 15 | let record = { total: 0, won: 0, lost: 0 } 16 | 17 | 18 | const askIfWantsToPlayAgain = async (win: boolean) => { 19 | 20 | if (win) { 21 | console.log("You won."); 22 | } 23 | else { 24 | console.log(`You loose. Secret number was ${secretNumber}`); 25 | } 26 | 27 | console.log(""); 28 | 29 | const again = await inquirer.prompt([{ 30 | name: "again", 31 | type: "confirm", 32 | message: "Want to play again? ", 33 | }]) 34 | 35 | if (again.again) { 36 | rounds = TOTAL_ROUNDS; 37 | secretNumber = generateARandomNumber(); 38 | } 39 | else { 40 | wantToContinue = false; 41 | console.log("Die in hell"); 42 | } 43 | 44 | } 45 | 46 | const welcomeMessage = () => { 47 | console.clear(); 48 | 49 | console.log("************** Record **************"); 50 | console.log(`Total Played: ${record.total}, Won: ${record.won}, Lost: ${record.lost}`); 51 | console.log("************************************"); 52 | 53 | console.log("\nWelcome to the secret number guessing game."); 54 | console.log(`You will have ${TOTAL_ROUNDS} rounds to guess the number \n`); 55 | 56 | } 57 | 58 | const playARound = async () => { 59 | 60 | const answer = await inquirer.prompt([{ 61 | name: "guess", 62 | type: "input", 63 | message: "Your guess: ", 64 | askAnswered: true, 65 | validate: (input) => { 66 | if (isNaN(input)) { 67 | return "Pleaee enter a number" 68 | } 69 | if (Number(input) > 10) { 70 | return "Pleaee enter a number less than 10" 71 | } 72 | return true; 73 | } 74 | }]) 75 | 76 | rounds--; 77 | 78 | if (Number(answer.guess) === secretNumber) { 79 | record.total++; 80 | record.won++; 81 | await askIfWantsToPlayAgain(true); 82 | } 83 | 84 | else if (rounds >= 1) { 85 | console.log(`Wrong guess. You have ${rounds} left. Try Again`) 86 | } 87 | else { 88 | record.total++; 89 | record.lost++; 90 | await askIfWantsToPlayAgain(false); 91 | } 92 | 93 | } 94 | 95 | 96 | do { 97 | if (rounds === TOTAL_ROUNDS) { 98 | welcomeMessage(); 99 | } 100 | await playARound() 101 | } while (rounds > 0 || wantToContinue) 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /01_cli_number_guessing_game/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "class-number-guessing-game", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "bin": { 8 | "guess": "index.js" 9 | }, 10 | "scripts": { 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "dependencies": { 17 | "g": "^2.0.1", 18 | "inquirer": "^9.1.4", 19 | "loading-cli": "^1.1.0" 20 | }, 21 | "devDependencies": { 22 | "@types/inquirer": "^9.0.3" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /01_cli_number_guessing_game/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "ES2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "NodeNext", /* Specify what module code is generated. */ 29 | // "rootDir": "./", /* Specify the root folder within your source files. */ 30 | "moduleResolution": "NodeNext", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | // "resolveJsonModule": true, /* Enable importing .json files. */ 39 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 40 | 41 | /* JavaScript Support */ 42 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 43 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 44 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 45 | 46 | /* Emit */ 47 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 48 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 49 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 50 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 51 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 52 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 53 | // "removeComments": true, /* Disable emitting comments. */ 54 | // "noEmit": true, /* Disable emitting files from a compilation. */ 55 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 56 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 57 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 58 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 59 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 60 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 61 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 62 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 63 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 64 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 65 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 66 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 67 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 68 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 69 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 70 | 71 | /* Interop Constraints */ 72 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 73 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 74 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 75 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 76 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 77 | 78 | /* Type Checking */ 79 | "strict": true, /* Enable all strict type-checking options. */ 80 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 81 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 82 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 83 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 84 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 85 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 86 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 87 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 88 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 89 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 90 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 91 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 92 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 93 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 94 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 95 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 96 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 97 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 98 | 99 | /* Completeness */ 100 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 101 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /02_cli_atm/README.md: -------------------------------------------------------------------------------- 1 | Find this project on NPM: [class-atm-machine](https://www.npmjs.com/package/class-atm-machine) 2 | 3 | Use it in your own terminal by: npx class-atm-machine -------------------------------------------------------------------------------- /02_cli_atm/index.js: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | import inquirer from "inquirer"; 3 | // Enter the ATM; 4 | let isLoggedIn = false; 5 | let quit = false; 6 | const account = { 7 | balance: 1000000, 8 | transactionCount: 0, 9 | userName: "", 10 | password: "", 11 | }; 12 | const welcomeMsg = (loggedIn = false) => { 13 | console.clear(); 14 | console.log("*********************************"); 15 | if (loggedIn) { 16 | console.log(`Welcome ${account.userName} to the PIAIC ATM Machine.`); 17 | console.log(`Balance ${account.balance}. Transaction Count: ${account.transactionCount}`); 18 | } 19 | else { 20 | console.log("Welcome to the PIAIC ATM Machine."); 21 | } 22 | console.log("*********************************"); 23 | }; 24 | const setUsernamePassword = async () => { 25 | const details = await inquirer.prompt([ 26 | { 27 | name: "userName", 28 | type: "input", 29 | message: "Set a username" 30 | }, 31 | { 32 | name: "password", 33 | type: "password", 34 | mask: true, 35 | message: "Set a password" 36 | }, 37 | ]); 38 | account.userName = details.userName; 39 | account.password = details.password; 40 | }; 41 | const login = async () => { 42 | const tx = await inquirer.prompt([ 43 | { 44 | name: "userName", 45 | type: "input", 46 | message: "Enter User name" 47 | }, 48 | { 49 | name: "password", 50 | type: "input", 51 | message: "Enter Password" 52 | } 53 | ]); 54 | if (tx.userName === account.userName && tx.password === account.password) { 55 | isLoggedIn = true; 56 | console.log("Logged in Successfully"); 57 | } 58 | else { 59 | console.log("Incorrect username or password"); 60 | } 61 | }; 62 | const accounts = { 63 | "ABL": ["Zia", "Zeeshan"], 64 | "HBL": ["Ali", "Umar", "Zeeshan"], 65 | "IPL": ["Ali", "Zia", "Zeeshan"], 66 | }; 67 | const options = async () => { 68 | const tx = await inquirer.prompt([ 69 | { 70 | name: "transaction", 71 | type: "list", 72 | choices: ["Transfer", "quit"], 73 | message: "Choose a transaction type" 74 | } 75 | ]); 76 | switch (tx.transaction) { 77 | case "Transfer": 78 | const bank = await inquirer.prompt([ 79 | { 80 | name: "bank", 81 | type: "list", 82 | choices: ["ABL", "HBL", "IPL"], 83 | message: "Choose a bank to transfer", 84 | }, 85 | ]); 86 | const transfer = await inquirer.prompt([ 87 | { 88 | name: "transfer", 89 | type: "list", 90 | choices: accounts[bank.bank], 91 | message: "Choose an account" 92 | }, 93 | ]); 94 | // console.log("transfer: ", tx2.transfer) 95 | console.log("Your Balance: ", account.balance + " Rs"); 96 | const amount = await inquirer.prompt([ 97 | { 98 | name: "amount", 99 | type: "input", 100 | message: "Enter an amount", 101 | validate: (input) => { 102 | if (isNaN(input) || input === "") { 103 | return "Please enter a number"; 104 | } 105 | if (Number(input) > account.balance) { 106 | return "Insiffucient Balance"; 107 | } 108 | return true; 109 | } 110 | }, 111 | ]); 112 | console.log("amount: ", amount.amount); 113 | account.balance -= Number(amount.amount); 114 | account.transactionCount++; 115 | console.log("Transaction completed"); 116 | break; 117 | case "quit": 118 | quit = true; 119 | break; 120 | } 121 | }; 122 | const process = async () => { 123 | welcomeMsg(); 124 | await setUsernamePassword(); 125 | welcomeMsg(); 126 | do { 127 | await login(); 128 | } while (!isLoggedIn); 129 | do { 130 | welcomeMsg(true); 131 | console.log("\n\n"); 132 | await options(); 133 | } while (!quit); 134 | }; 135 | process(); 136 | -------------------------------------------------------------------------------- /02_cli_atm/index.ts: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | 3 | import inquirer from "inquirer"; 4 | 5 | 6 | // Enter the ATM; 7 | let isLoggedIn = false; 8 | let quit = false; 9 | const account = { 10 | balance: 1_000_000, 11 | transactionCount: 0, 12 | userName: "", 13 | password: "", 14 | } 15 | 16 | const welcomeMsg = (loggedIn: boolean = false) => { 17 | console.clear(); 18 | console.log("*********************************"); 19 | if(loggedIn){ 20 | console.log(`Welcome ${account.userName} to the PIAIC ATM Machine.`); 21 | console.log(`Balance ${account.balance}. Transaction Count: ${account.transactionCount}`); 22 | } 23 | else{ 24 | console.log("Welcome to the PIAIC ATM Machine."); 25 | } 26 | console.log("*********************************"); 27 | } 28 | 29 | 30 | const setUsernamePassword = async () => { 31 | 32 | 33 | const details = await inquirer.prompt([ 34 | { 35 | name: "userName", 36 | type: "input", 37 | message: "Set a username" 38 | }, 39 | { 40 | name: "password", 41 | type: "password", 42 | mask: true, 43 | message: "Set a password" 44 | }, 45 | ]) 46 | 47 | account.userName = details.userName; 48 | account.password = details.password; 49 | 50 | } 51 | 52 | const login = async () => { 53 | 54 | const tx = await inquirer.prompt([ 55 | { 56 | name: "userName", 57 | type: "input", 58 | message: "Enter User name" 59 | }, 60 | { 61 | name: "password", 62 | type: "input", 63 | message: "Enter Password" 64 | } 65 | ]); 66 | 67 | 68 | 69 | if (tx.userName === account.userName && tx.password === account.password) { 70 | isLoggedIn = true; 71 | console.log("Logged in Successfully"); 72 | 73 | } 74 | else { 75 | console.log("Incorrect username or password"); 76 | } 77 | } 78 | 79 | const accounts = { 80 | "ABL": ["Zia", "Zeeshan"], 81 | "HBL": ["Ali", "Umar", "Zeeshan"], 82 | "IPL": ["Ali", "Zia", "Zeeshan"], 83 | } 84 | 85 | const options = async () => { 86 | 87 | const tx = await inquirer.prompt([ 88 | { 89 | name: "transaction", 90 | type: "list", 91 | choices: ["Transfer", "quit"], 92 | message: "Choose a transaction type" 93 | } 94 | ]); 95 | 96 | switch(tx.transaction){ 97 | case "Transfer": 98 | const bank = await inquirer.prompt([ 99 | { 100 | name: "bank", 101 | type: "list", 102 | choices: ["ABL", "HBL", "IPL"], 103 | message: "Choose a bank to transfer", 104 | }, 105 | ]); 106 | const transfer = await inquirer.prompt([ 107 | { 108 | name: "transfer", 109 | type: "list", 110 | choices: accounts[bank.bank as "ABL"|"HBL"|"IPL"], 111 | message: "Choose an account" 112 | }, 113 | ]); 114 | // console.log("transfer: ", tx2.transfer) 115 | console.log("Your Balance: ", account.balance + " Rs"); 116 | const amount = await inquirer.prompt([ 117 | { 118 | name: "amount", 119 | type: "input", 120 | message: "Enter an amount", 121 | validate: (input) => { 122 | if (isNaN(input) || input === "") { 123 | return "Please enter a number" 124 | } 125 | if (Number(input) > account.balance) { 126 | return "Insiffucient Balance"; 127 | } 128 | return true; 129 | } 130 | }, 131 | ]); 132 | 133 | console.log("amount: ", amount.amount); 134 | account.balance -= Number(amount.amount); 135 | account.transactionCount++; 136 | 137 | console.log("Transaction completed"); 138 | break; 139 | 140 | case "quit": 141 | quit = true; 142 | break; 143 | } 144 | 145 | 146 | } 147 | 148 | 149 | const process = async () => { 150 | 151 | welcomeMsg(); 152 | await setUsernamePassword(); 153 | welcomeMsg(); 154 | 155 | do { 156 | await login(); 157 | } while (!isLoggedIn) 158 | 159 | do { 160 | welcomeMsg(true); 161 | console.log("\n\n"); 162 | await options(); 163 | } while (!quit) 164 | 165 | } 166 | 167 | process(); 168 | 169 | 170 | -------------------------------------------------------------------------------- /02_cli_atm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "class-atm-machine", 3 | "version": "2.3.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "bin": { 8 | "atm-machine": "index.js" 9 | }, 10 | "scripts": { 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "dependencies": { 17 | "chalk": "^5.1.2", 18 | "g": "^2.0.1", 19 | "inquirer": "^9.1.4", 20 | "loading-cli": "^1.1.0" 21 | }, 22 | "devDependencies": { 23 | "@types/inquirer": "^9.0.3" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /02_cli_atm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "ES2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "NodeNext", /* Specify what module code is generated. */ 29 | // "rootDir": "./", /* Specify the root folder within your source files. */ 30 | "moduleResolution": "NodeNext", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | // "resolveJsonModule": true, /* Enable importing .json files. */ 39 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 40 | 41 | /* JavaScript Support */ 42 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 43 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 44 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 45 | 46 | /* Emit */ 47 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 48 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 49 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 50 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 51 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 52 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 53 | // "removeComments": true, /* Disable emitting comments. */ 54 | // "noEmit": true, /* Disable emitting files from a compilation. */ 55 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 56 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 57 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 58 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 59 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 60 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 61 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 62 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 63 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 64 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 65 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 66 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 67 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 68 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 69 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 70 | 71 | /* Interop Constraints */ 72 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 73 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 74 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 75 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 76 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 77 | 78 | /* Type Checking */ 79 | "strict": true, /* Enable all strict type-checking options. */ 80 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 81 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 82 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 83 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 84 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 85 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 86 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 87 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 88 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 89 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 90 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 91 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 92 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 93 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 94 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 95 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 96 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 97 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 98 | 99 | /* Completeness */ 100 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 101 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /02_cli_atm/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@types/inquirer@^9.0.3": 6 | "integrity" "sha512-CzNkWqQftcmk2jaCWdBTf9Sm7xSw4rkI1zpU/Udw3HX5//adEZUIm9STtoRP1qgWj0CWQtJ9UTvqmO2NNjhMJw==" 7 | "resolved" "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.3.tgz" 8 | "version" "9.0.3" 9 | dependencies: 10 | "@types/through" "*" 11 | "rxjs" "^7.2.0" 12 | 13 | "@types/node@*": 14 | "integrity" "sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ==" 15 | "resolved" "https://registry.npmjs.org/@types/node/-/node-18.11.10.tgz" 16 | "version" "18.11.10" 17 | 18 | "@types/through@*": 19 | "integrity" "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==" 20 | "resolved" "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz" 21 | "version" "0.0.30" 22 | dependencies: 23 | "@types/node" "*" 24 | 25 | "ansi-escapes@^6.0.0": 26 | "integrity" "sha512-IG23inYII3dWlU2EyiAiGj6Bwal5GzsgPMwjYGvc1HPE2dgbj4ZB5ToWBKSquKw74nB3TIuOwaI6/jSULzfgrw==" 27 | "resolved" "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.0.0.tgz" 28 | "version" "6.0.0" 29 | dependencies: 30 | "type-fest" "^3.0.0" 31 | 32 | "ansi-regex@^6.0.1": 33 | "integrity" "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" 34 | "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz" 35 | "version" "6.0.1" 36 | 37 | "ansi-styles@^6.1.0": 38 | "integrity" "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" 39 | "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz" 40 | "version" "6.2.1" 41 | 42 | "base64-js@^1.3.1": 43 | "integrity" "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" 44 | "resolved" "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" 45 | "version" "1.5.1" 46 | 47 | "bl@^5.0.0": 48 | "integrity" "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==" 49 | "resolved" "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz" 50 | "version" "5.1.0" 51 | dependencies: 52 | "buffer" "^6.0.3" 53 | "inherits" "^2.0.4" 54 | "readable-stream" "^3.4.0" 55 | 56 | "buffer@^6.0.3": 57 | "integrity" "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==" 58 | "resolved" "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz" 59 | "version" "6.0.3" 60 | dependencies: 61 | "base64-js" "^1.3.1" 62 | "ieee754" "^1.2.1" 63 | 64 | "chalk@^5.0.0", "chalk@^5.1.2": 65 | "integrity" "sha512-E5CkT4jWURs1Vy5qGJye+XwCkNj7Od3Af7CP6SujMetSMkLs8Do2RWJK5yx1wamHV/op8Rz+9rltjaTQWDnEFQ==" 66 | "resolved" "https://registry.npmjs.org/chalk/-/chalk-5.1.2.tgz" 67 | "version" "5.1.2" 68 | 69 | "chardet@^0.7.0": 70 | "integrity" "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" 71 | "resolved" "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz" 72 | "version" "0.7.0" 73 | 74 | "cli-cursor@^4.0.0": 75 | "integrity" "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==" 76 | "resolved" "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz" 77 | "version" "4.0.0" 78 | dependencies: 79 | "restore-cursor" "^4.0.0" 80 | 81 | "cli-spinners@^2.6.1": 82 | "integrity" "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==" 83 | "resolved" "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz" 84 | "version" "2.7.0" 85 | 86 | "cli-width@^4.0.0": 87 | "integrity" "sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==" 88 | "resolved" "https://registry.npmjs.org/cli-width/-/cli-width-4.0.0.tgz" 89 | "version" "4.0.0" 90 | 91 | "clone@^1.0.2": 92 | "integrity" "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" 93 | "resolved" "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz" 94 | "version" "1.0.4" 95 | 96 | "colors-cli@^1.0.26": 97 | "integrity" "sha512-2XE8s1mB3Jr5rvirk/fFzhWY2m9S2dpZ0mWz3Yl/mzMM8hDVBawL0Rsal5hR1gJP4lgqhQfFfEmaGZpUZgEKrA==" 98 | "resolved" "https://registry.npmjs.org/colors-cli/-/colors-cli-1.0.28.tgz" 99 | "version" "1.0.28" 100 | 101 | "defaults@^1.0.3": 102 | "integrity" "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==" 103 | "resolved" "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz" 104 | "version" "1.0.4" 105 | dependencies: 106 | "clone" "^1.0.2" 107 | 108 | "eastasianwidth@^0.2.0": 109 | "integrity" "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" 110 | "resolved" "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz" 111 | "version" "0.2.0" 112 | 113 | "emoji-regex@^9.2.2": 114 | "integrity" "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" 115 | "resolved" "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz" 116 | "version" "9.2.2" 117 | 118 | "escape-string-regexp@^5.0.0": 119 | "integrity" "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==" 120 | "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz" 121 | "version" "5.0.0" 122 | 123 | "external-editor@^3.0.3": 124 | "integrity" "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==" 125 | "resolved" "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz" 126 | "version" "3.1.0" 127 | dependencies: 128 | "chardet" "^0.7.0" 129 | "iconv-lite" "^0.4.24" 130 | "tmp" "^0.0.33" 131 | 132 | "figures@^5.0.0": 133 | "integrity" "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==" 134 | "resolved" "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz" 135 | "version" "5.0.0" 136 | dependencies: 137 | "escape-string-regexp" "^5.0.0" 138 | "is-unicode-supported" "^1.2.0" 139 | 140 | "g@^2.0.1": 141 | "integrity" "sha512-Fi6Ng5fZ/ANLQ15H11hCe+09sgUoNvDEBevVgx3KoYOhsH5iLNPn54hx0jPZ+3oSWr+xajnp2Qau9VmPsc7hTA==" 142 | "resolved" "https://registry.npmjs.org/g/-/g-2.0.1.tgz" 143 | "version" "2.0.1" 144 | 145 | "iconv-lite@^0.4.24": 146 | "integrity" "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==" 147 | "resolved" "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" 148 | "version" "0.4.24" 149 | dependencies: 150 | "safer-buffer" ">= 2.1.2 < 3" 151 | 152 | "ieee754@^1.2.1": 153 | "integrity" "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" 154 | "resolved" "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" 155 | "version" "1.2.1" 156 | 157 | "inherits@^2.0.3", "inherits@^2.0.4": 158 | "integrity" "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 159 | "resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" 160 | "version" "2.0.4" 161 | 162 | "inquirer@^9.1.4": 163 | "integrity" "sha512-9hiJxE5gkK/cM2d1mTEnuurGTAoHebbkX0BYl3h7iEg7FYfuNIom+nDfBCSWtvSnoSrWCeBxqqBZu26xdlJlXA==" 164 | "resolved" "https://registry.npmjs.org/inquirer/-/inquirer-9.1.4.tgz" 165 | "version" "9.1.4" 166 | dependencies: 167 | "ansi-escapes" "^6.0.0" 168 | "chalk" "^5.1.2" 169 | "cli-cursor" "^4.0.0" 170 | "cli-width" "^4.0.0" 171 | "external-editor" "^3.0.3" 172 | "figures" "^5.0.0" 173 | "lodash" "^4.17.21" 174 | "mute-stream" "0.0.8" 175 | "ora" "^6.1.2" 176 | "run-async" "^2.4.0" 177 | "rxjs" "^7.5.7" 178 | "string-width" "^5.1.2" 179 | "strip-ansi" "^7.0.1" 180 | "through" "^2.3.6" 181 | "wrap-ansi" "^8.0.1" 182 | 183 | "is-interactive@^2.0.0": 184 | "integrity" "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==" 185 | "resolved" "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz" 186 | "version" "2.0.0" 187 | 188 | "is-unicode-supported@^1.1.0", "is-unicode-supported@^1.2.0": 189 | "integrity" "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==" 190 | "resolved" "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz" 191 | "version" "1.3.0" 192 | 193 | "loading-cli@^1.1.0": 194 | "integrity" "sha512-r6Kj0Y3d3isT4vvJ0tFlND1CcLkpatWmlgQs/PEfnSofJSHZwAbsqexnpQEDj4nlxSXEqFWh/Wu2iQXAAZRPNQ==" 195 | "resolved" "https://registry.npmjs.org/loading-cli/-/loading-cli-1.1.0.tgz" 196 | "version" "1.1.0" 197 | dependencies: 198 | "colors-cli" "^1.0.26" 199 | 200 | "lodash@^4.17.21": 201 | "integrity" "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 202 | "resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" 203 | "version" "4.17.21" 204 | 205 | "log-symbols@^5.1.0": 206 | "integrity" "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==" 207 | "resolved" "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz" 208 | "version" "5.1.0" 209 | dependencies: 210 | "chalk" "^5.0.0" 211 | "is-unicode-supported" "^1.1.0" 212 | 213 | "mimic-fn@^2.1.0": 214 | "integrity" "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" 215 | "resolved" "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" 216 | "version" "2.1.0" 217 | 218 | "mute-stream@0.0.8": 219 | "integrity" "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" 220 | "resolved" "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz" 221 | "version" "0.0.8" 222 | 223 | "onetime@^5.1.0": 224 | "integrity" "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==" 225 | "resolved" "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" 226 | "version" "5.1.2" 227 | dependencies: 228 | "mimic-fn" "^2.1.0" 229 | 230 | "ora@^6.1.2": 231 | "integrity" "sha512-EJQ3NiP5Xo94wJXIzAyOtSb0QEIAUu7m8t6UZ9krbz0vAJqr92JpcK/lEXg91q6B9pEGqrykkd2EQplnifDSBw==" 232 | "resolved" "https://registry.npmjs.org/ora/-/ora-6.1.2.tgz" 233 | "version" "6.1.2" 234 | dependencies: 235 | "bl" "^5.0.0" 236 | "chalk" "^5.0.0" 237 | "cli-cursor" "^4.0.0" 238 | "cli-spinners" "^2.6.1" 239 | "is-interactive" "^2.0.0" 240 | "is-unicode-supported" "^1.1.0" 241 | "log-symbols" "^5.1.0" 242 | "strip-ansi" "^7.0.1" 243 | "wcwidth" "^1.0.1" 244 | 245 | "os-tmpdir@~1.0.2": 246 | "integrity" "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==" 247 | "resolved" "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" 248 | "version" "1.0.2" 249 | 250 | "readable-stream@^3.4.0": 251 | "integrity" "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==" 252 | "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" 253 | "version" "3.6.0" 254 | dependencies: 255 | "inherits" "^2.0.3" 256 | "string_decoder" "^1.1.1" 257 | "util-deprecate" "^1.0.1" 258 | 259 | "restore-cursor@^4.0.0": 260 | "integrity" "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==" 261 | "resolved" "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz" 262 | "version" "4.0.0" 263 | dependencies: 264 | "onetime" "^5.1.0" 265 | "signal-exit" "^3.0.2" 266 | 267 | "run-async@^2.4.0": 268 | "integrity" "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" 269 | "resolved" "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz" 270 | "version" "2.4.1" 271 | 272 | "rxjs@^7.2.0", "rxjs@^7.5.7": 273 | "integrity" "sha512-DDa7d8TFNUalGC9VqXvQ1euWNN7sc63TrUCuM9J998+ViviahMIjKSOU7rfcgFOF+FCD71BhDRv4hrFz+ImDLQ==" 274 | "resolved" "https://registry.npmjs.org/rxjs/-/rxjs-7.6.0.tgz" 275 | "version" "7.6.0" 276 | dependencies: 277 | "tslib" "^2.1.0" 278 | 279 | "safe-buffer@~5.2.0": 280 | "integrity" "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 281 | "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" 282 | "version" "5.2.1" 283 | 284 | "safer-buffer@>= 2.1.2 < 3": 285 | "integrity" "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 286 | "resolved" "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" 287 | "version" "2.1.2" 288 | 289 | "signal-exit@^3.0.2": 290 | "integrity" "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" 291 | "resolved" "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" 292 | "version" "3.0.7" 293 | 294 | "string_decoder@^1.1.1": 295 | "integrity" "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==" 296 | "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" 297 | "version" "1.3.0" 298 | dependencies: 299 | "safe-buffer" "~5.2.0" 300 | 301 | "string-width@^5.0.1", "string-width@^5.1.2": 302 | "integrity" "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==" 303 | "resolved" "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" 304 | "version" "5.1.2" 305 | dependencies: 306 | "eastasianwidth" "^0.2.0" 307 | "emoji-regex" "^9.2.2" 308 | "strip-ansi" "^7.0.1" 309 | 310 | "strip-ansi@^7.0.1": 311 | "integrity" "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==" 312 | "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz" 313 | "version" "7.0.1" 314 | dependencies: 315 | "ansi-regex" "^6.0.1" 316 | 317 | "through@^2.3.6": 318 | "integrity" "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" 319 | "resolved" "https://registry.npmjs.org/through/-/through-2.3.8.tgz" 320 | "version" "2.3.8" 321 | 322 | "tmp@^0.0.33": 323 | "integrity" "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==" 324 | "resolved" "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" 325 | "version" "0.0.33" 326 | dependencies: 327 | "os-tmpdir" "~1.0.2" 328 | 329 | "tslib@^2.1.0": 330 | "integrity" "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" 331 | "resolved" "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz" 332 | "version" "2.4.1" 333 | 334 | "type-fest@^3.0.0": 335 | "integrity" "sha512-gezeeOIZyQLGW5uuCeEnXF1aXmtt2afKspXz3YqoOcZ3l/YMJq1pujvgT+cz/Nw1O/7q/kSav5fihJHsC/AOUg==" 336 | "resolved" "https://registry.npmjs.org/type-fest/-/type-fest-3.3.0.tgz" 337 | "version" "3.3.0" 338 | 339 | "util-deprecate@^1.0.1": 340 | "integrity" "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" 341 | "resolved" "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" 342 | "version" "1.0.2" 343 | 344 | "wcwidth@^1.0.1": 345 | "integrity" "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==" 346 | "resolved" "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz" 347 | "version" "1.0.1" 348 | dependencies: 349 | "defaults" "^1.0.3" 350 | 351 | "wrap-ansi@^8.0.1": 352 | "integrity" "sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==" 353 | "resolved" "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.0.1.tgz" 354 | "version" "8.0.1" 355 | dependencies: 356 | "ansi-styles" "^6.1.0" 357 | "string-width" "^5.0.1" 358 | "strip-ansi" "^7.0.1" 359 | -------------------------------------------------------------------------------- /06_SMS/README.md: -------------------------------------------------------------------------------- 1 | Find this project on NPM: [student_management_system](https://www.npmjs.com/package/student_management_system) 2 | 3 | Use it in your own terminal by: npx student_management_system -------------------------------------------------------------------------------- /06_SMS/lib/Course.js: -------------------------------------------------------------------------------- 1 | export class Course { 2 | course_code; 3 | course_name; 4 | course_description; 5 | course_instructor; 6 | tuition_fee; 7 | constructor(code, name, description, course_instructor, tuition_fee) { 8 | this.course_code = code; 9 | this.course_name = name; 10 | this.course_description = description; 11 | this.course_instructor = course_instructor; 12 | this.tuition_fee = tuition_fee; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /06_SMS/lib/Instructor.js: -------------------------------------------------------------------------------- 1 | export class Instructor { 2 | name; 3 | course_codes = []; 4 | constructor(name, course_codes) { 5 | this.name = name; 6 | if (course_codes) { 7 | this.course_codes.push(...course_codes); 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /06_SMS/lib/Person.js: -------------------------------------------------------------------------------- 1 | export class Person { 2 | _id; 3 | _name; 4 | _age; 5 | _gender; 6 | constructor(name) { 7 | this._name = name; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /06_SMS/lib/SMS.js: -------------------------------------------------------------------------------- 1 | import { Course } from "./Course.js"; 2 | import { Instructor } from "./Instructor.js"; 3 | import { Student } from "./Student.js"; 4 | class SMS { 5 | _idsGenetor = 0; 6 | name; 7 | students = new Map(); 8 | courses = new Map(); 9 | instructors = new Map(); 10 | balance = 0; 11 | constructor(_name) { 12 | this.name = _name; 13 | } 14 | AddInstructorsInUMS(_instructors) { 15 | _instructors.map((instructor) => { 16 | let newIstructor = new Instructor(instructor.instructor_name, instructor.course_codes); 17 | this.instructors.set(instructor.instructor_name, newIstructor); 18 | }); 19 | } 20 | AddCoursesinUMS(_courses) { 21 | _courses.map((course) => { 22 | const { course_code, course_name, des, instructor, tuition_fee } = course; 23 | const newCourse = new Course(course_code, course_name, des, instructor, tuition_fee); 24 | this.courses.set(course.course_code, newCourse); 25 | }); 26 | } 27 | getAllCourseInUMS() { 28 | return [...this.courses.values()]; 29 | } 30 | getCourseById(code) { 31 | return this.courses.get(code); 32 | } 33 | getAllInstructorsInUMS() { 34 | return [...this.instructors.values()]; 35 | } 36 | getInstructorByName(name) { 37 | return this.instructors.get(name); 38 | } 39 | enrollStudentinUMS(name, cnic, section) { 40 | const newId = ++this._idsGenetor; 41 | var password = (Math.floor(Math.random() * 10000) + 10000).toString().substring(1); 42 | const student = new Student(name, cnic, section, newId, password); 43 | this.students.set(newId, student); 44 | return { id: newId, password: password }; 45 | } 46 | getAllStudents() { 47 | return [...this.students.values()]; 48 | } 49 | getStudentById(id) { 50 | return this.students.get(id); 51 | } 52 | /** 53 | Student related Methods 54 | 55 | * Student set and reset a password 56 | * Student should be able to sign in the system 57 | * Student should read enrolled courses, enroll in or drop off one or many courses using courseId 58 | 59 | */ 60 | logIn(studentId, password) { 61 | let student = this.students.get(studentId); 62 | if (!student) { 63 | return { 64 | status: false, 65 | msg: "Student do not exist" 66 | }; 67 | } 68 | if (student.password == password) { 69 | student.loginStatus = true; 70 | this.students.set(studentId, student); 71 | return { 72 | status: true, 73 | msg: "Successfully Logged In" 74 | }; 75 | } 76 | else { 77 | return { 78 | status: false, 79 | msg: "Incorrect password" 80 | }; 81 | } 82 | } 83 | setPassword(studentId, newPassword, oldPassword) { 84 | let student = this.students.get(studentId); 85 | if (!student) 86 | throw Error("Student do not exist"); 87 | if (!student.loginStatus) 88 | throw Error("Not logged In"); 89 | if (student.password === oldPassword) { 90 | student.password = newPassword; 91 | this.students.set(studentId, student); 92 | } 93 | else { 94 | throw Error("Incorrect password"); 95 | } 96 | } 97 | setProfile(studentId, name, age, address, cnic) { 98 | let student = this.students.get(studentId); 99 | if (!student) 100 | throw Error("Student do not exist"); 101 | if (!student.loginStatus) 102 | throw Error("Not logged In"); 103 | student.name = name; 104 | student.age = age; 105 | student.address = address; 106 | student.cnic = cnic; 107 | } 108 | enrollInCourses(studentId, courseCodes) { 109 | let student = this.students.get(studentId); 110 | if (!student) 111 | throw Error("Student do not exist"); 112 | if (!student.loginStatus) 113 | throw Error("You are not logged In"); 114 | let totalFeeToPay = 0; 115 | courseCodes.map((code) => { 116 | const course = this.courses.get(code); 117 | if (course) { 118 | totalFeeToPay = totalFeeToPay + course.tuition_fee; 119 | } 120 | }); 121 | if (student.balance < Number(totalFeeToPay)) { 122 | throw Error("You don't have enough balance to enroll in these courses"); 123 | } 124 | courseCodes.forEach((code) => { 125 | const course = this.courses.get(code); 126 | if (!course) 127 | throw Error(`course do not exist ${code}`); 128 | if (student) { 129 | this.balance += course.tuition_fee; 130 | student.balance -= course.tuition_fee; 131 | student.courses_enrolled.push(course.course_code); 132 | } 133 | }); 134 | this.students.set(studentId, student); 135 | } 136 | dropOffCourses(studentId, courseCodes) { 137 | let student = this.students.get(studentId); 138 | if (!student) 139 | throw Error("Student do not exist"); 140 | if (!student.loginStatus) 141 | throw Error("You are not logged In"); 142 | courseCodes.forEach((code) => { 143 | if (student) { 144 | const course = this.courses.get(code); 145 | if (course) { 146 | this.balance -= (course.tuition_fee * 0.5); 147 | student.balance += (course.tuition_fee * 0.5); 148 | student.courses_enrolled = student.courses_enrolled 149 | .filter((course_code) => course_code !== code); 150 | } 151 | } 152 | }); 153 | this.students.set(studentId, student); 154 | } 155 | } 156 | export default new SMS("PIAIC STUDENT MANAGEMENT SYSTEM"); 157 | -------------------------------------------------------------------------------- /06_SMS/lib/Student.js: -------------------------------------------------------------------------------- 1 | export class Student { 2 | name; 3 | cnic; 4 | studentId; 5 | student_section; 6 | password; 7 | // Default parameters 8 | courses_enrolled = []; 9 | loginStatus = false; 10 | balance = 10000; 11 | // Optional parameters 12 | age; 13 | address; 14 | constructor(_name, _cnic, _student_section, _studentId, _password) { 15 | this.name = _name; 16 | this.cnic = _cnic; 17 | this.student_section = _student_section; 18 | this.studentId = _studentId; 19 | this.password = _password; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /06_SMS/lib/UMS.js: -------------------------------------------------------------------------------- 1 | import { Course } from "./Course.js"; 2 | import { Instructor } from "./Instructor.js"; 3 | import { Student } from "./Student.js"; 4 | export class UMS { 5 | _idsGenetor = 0; 6 | name; 7 | students = new Map(); 8 | courses = new Map(); 9 | instructors = new Map(); 10 | constructor(_name) { 11 | this.name = _name; 12 | } 13 | AddInstructorsInUMS(_instructors) { 14 | _instructors.map((instructor) => { 15 | let newIstructor = new Instructor(instructor.name, instructor.course_codes); 16 | this.instructors.set(instructor.name, newIstructor); 17 | }); 18 | } 19 | AddCoursesinUMS(_courses) { 20 | _courses.map((course) => { 21 | const newCourse = new Course(course.code, course.name, course.des, course.instructor); 22 | this.courses.set(course.code, newCourse); 23 | }); 24 | } 25 | getAllCourseInUMS() { 26 | return [...this.courses.values()]; 27 | } 28 | getCourseById(code) { 29 | return this.courses.get(code); 30 | } 31 | getAllInstructorsInUMS() { 32 | return [...this.instructors.values()]; 33 | } 34 | getInstructorByName(name) { 35 | return this.instructors.get(name); 36 | } 37 | enrollStudentinUMS(name, cnic, section) { 38 | const newId = ++this._idsGenetor; 39 | var password = (Math.floor(Math.random() * 10000) + 10000).toString().substring(1); 40 | const student = new Student(name, cnic, section, newId, password); 41 | this.students.set(newId, student); 42 | return { id: newId, password: password }; 43 | } 44 | getAllStudents() { 45 | return [...this.students.values()]; 46 | } 47 | getStudentById(id) { 48 | return this.students.get(id); 49 | } 50 | /** 51 | Student related Methods 52 | 53 | * Student set and reset a password 54 | * Student should be able to sign in the system 55 | * Student should read enrolled courses, enroll in or drop off one or many courses using courseId 56 | 57 | */ 58 | logIn(studentId, password) { 59 | let student = this.students.get(studentId); 60 | if (!student) 61 | throw Error("Student do not exist"); 62 | if (student.password === password) { 63 | student.loginStatus = true; 64 | this.students.set(studentId, student); 65 | } 66 | else { 67 | throw Error("Incorrect password"); 68 | } 69 | } 70 | setPassword(studentId, newPassword, oldPassword) { 71 | let student = this.students.get(studentId); 72 | if (!student) 73 | throw Error("Student do not exist"); 74 | if (!student.loginStatus) 75 | throw Error("Not logged In"); 76 | if (student.password === oldPassword) { 77 | student.password = newPassword; 78 | this.students.set(studentId, student); 79 | } 80 | else { 81 | throw Error("Incorrect password"); 82 | } 83 | } 84 | enrollInCourses(studentId, courseCodes) { 85 | let student = this.students.get(studentId); 86 | if (!student) 87 | throw Error("Student do not exist"); 88 | courseCodes.forEach((code) => { 89 | const course = this.courses.get(code); 90 | if (!course) 91 | throw Error(`course do not exist ${code}`); 92 | if (student) { 93 | student.courses_enrolled.push(course.course_code); 94 | } 95 | }); 96 | this.students.set(studentId, student); 97 | } 98 | dropOffCourses(studentId, courseCodes) { 99 | let student = this.students.get(studentId); 100 | if (!student) 101 | throw Error("Student do not exist"); 102 | courseCodes.forEach((code) => { 103 | if (student) { 104 | student.courses_enrolled = student.courses_enrolled 105 | .filter((course_code) => course_code !== code); 106 | } 107 | }); 108 | this.students.set(studentId, student); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /06_SMS/lib/helpers.js: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /06_SMS/lib/index.js: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | import { coursesList, instructorsList } from "./types.js"; 3 | import PIAIC_SMS from "./SMS.js"; 4 | import inquirer from "inquirer"; 5 | let studentData; 6 | let quit = false; 7 | PIAIC_SMS.AddCoursesinUMS(coursesList); 8 | PIAIC_SMS.AddInstructorsInUMS(instructorsList); 9 | const dummyStudent = PIAIC_SMS.enrollStudentinUMS("Ali", 33102, "Morning"); 10 | PIAIC_SMS.logIn(dummyStudent.id, dummyStudent.password); 11 | PIAIC_SMS.setPassword(dummyStudent.id, "1234", dummyStudent.password); 12 | const student = PIAIC_SMS.getStudentById(dummyStudent.id); 13 | studentData = student; 14 | const delay = async (ms = 2000) => { 15 | return new Promise((res) => setTimeout(res, ms)); 16 | }; 17 | const updatingComponent = async (msg) => { 18 | for (let i = 1; i < 100; i++) { 19 | const show = "=".repeat(i); 20 | console.clear(); 21 | console.log(); 22 | console.log(msg); 23 | console.log(show); 24 | console.log(); 25 | await delay(10); 26 | } 27 | }; 28 | const welcomeMsg = () => { 29 | console.log("Welcome to", PIAIC_SMS.name + "\n"); 30 | }; 31 | const handleLoggedOutUser = async () => { 32 | welcomeMsg(); 33 | const answers = await inquirer.prompt([ 34 | { 35 | name: "LogIn", 36 | type: "list", 37 | choices: ["Log In", "Sign Up", "Quit"], 38 | message: "Log in or create a new account" 39 | } 40 | ]); 41 | switch (answers.LogIn) { 42 | case "Log In": 43 | await handleLogin(); 44 | break; 45 | case "Sign Up": 46 | await handleSingUp(); 47 | break; 48 | case "Quit": 49 | handleQuit(); 50 | break; 51 | } 52 | }; 53 | const handleSingUp = async () => { 54 | const ans = await inquirer.prompt([ 55 | { 56 | name: "name", 57 | message: "enter you name", 58 | type: "input" 59 | }, 60 | { 61 | name: "CNIC", 62 | message: "enter your CNIC", 63 | type: "number" 64 | }, 65 | { 66 | name: "secion", 67 | message: "Choose a section", 68 | type: "list", 69 | choices: ["Morning", "Evening"] 70 | } 71 | ]); 72 | const newStudent = PIAIC_SMS.enrollStudentinUMS(ans.name, ans.CNIC, ans.secion); 73 | console.clear(); 74 | console.log(""); 75 | console.log("Student Id: ", newStudent.id); 76 | console.log("Password: ", newStudent.password + "\n"); 77 | console.log(""); 78 | }; 79 | const handleLogin = async () => { 80 | const ans = await inquirer.prompt([ 81 | { 82 | name: "id", 83 | message: "enter your student Id", 84 | type: "number" 85 | }, 86 | { 87 | name: "password", 88 | message: "enter your password", 89 | type: "password", 90 | masked: true 91 | } 92 | ]); 93 | const res = PIAIC_SMS.logIn(ans.id, ans.password); 94 | if (res.status) { 95 | let student = PIAIC_SMS.getStudentById(ans.id); 96 | studentData = student; 97 | } 98 | else { 99 | console.log(""); 100 | console.log(res.msg); 101 | console.log(""); 102 | } 103 | }; 104 | const handleQuit = () => { 105 | quit = true; 106 | console.log("Bye. See you later"); 107 | }; 108 | const handleLogOut = () => { 109 | console.clear(); 110 | studentData = undefined; 111 | }; 112 | const loggedInWelcomMsg = () => { 113 | if (studentData) { 114 | console.clear(); 115 | console.log("Welcome to PIAIC Student Management System"); 116 | console.log(""); 117 | console.table([ 118 | { 119 | "Name": studentData?.name, 120 | "Student Id": studentData?.studentId, 121 | "Balance": studentData?.balance 122 | } 123 | ]); 124 | console.log(""); 125 | } 126 | }; 127 | const availabelCoursesList = () => { 128 | if (studentData) { 129 | loggedInWelcomMsg(); 130 | const allCourses = PIAIC_SMS.getAllCourseInUMS(); 131 | console.table(allCourses); 132 | console.log(""); 133 | } 134 | }; 135 | const availabelInstructorsList = () => { 136 | if (studentData) { 137 | loggedInWelcomMsg(); 138 | const allInstructors = PIAIC_SMS.getAllInstructorsInUMS(); 139 | const formatedData = []; 140 | allInstructors.forEach((instructor) => { 141 | const coursesName = instructor.course_codes.map((code) => PIAIC_SMS.getCourseById(code)?.course_name).join(", "); 142 | formatedData.push({ 143 | "Name": instructor.name, 144 | "Courses Teaching": coursesName 145 | }); 146 | }); 147 | console.table(formatedData); 148 | console.log(""); 149 | } 150 | }; 151 | const studentCompleteProfile = () => { 152 | if (studentData) { 153 | loggedInWelcomMsg(); 154 | console.table([studentData]); 155 | console.log(""); 156 | } 157 | }; 158 | const editProfile = async () => { 159 | loggedInWelcomMsg(); 160 | const ans = await inquirer.prompt([ 161 | { 162 | name: "name", 163 | type: "input", 164 | message: "Your name", 165 | default: studentData?.name 166 | }, 167 | { 168 | name: "age", 169 | type: "number", 170 | message: "Your Age", 171 | default: studentData?.age 172 | }, 173 | { 174 | name: "address", 175 | type: "input", 176 | message: "Your Address", 177 | default: studentData?.address 178 | }, 179 | { 180 | name: "cnic", 181 | type: "number", 182 | message: "Your CNIC", 183 | default: studentData?.cnic 184 | }, 185 | ]); 186 | const { name, age, address, cnic } = ans; 187 | if (studentData) { 188 | PIAIC_SMS.setProfile(studentData.studentId, name, age, address, cnic); 189 | } 190 | await updatingComponent("Updating Profile"); 191 | loggedInWelcomMsg(); 192 | }; 193 | const enrollInACourse = async () => { 194 | if (studentData) { 195 | loggedInWelcomMsg(); 196 | // console.log("Your Balance: ", studentData.balance); 197 | console.log("Already Enrolled In Courses:"); 198 | // console.table(studentData.courses_enrolled) 199 | if (studentData.courses_enrolled.length === 0) { 200 | console.log("None"); 201 | console.log(""); 202 | } 203 | else { 204 | const coursesNames = studentData.courses_enrolled.map((course) => { 205 | return PIAIC_SMS.getCourseById(course)?.course_name; 206 | }); 207 | console.table(coursesNames); 208 | console.log(""); 209 | } 210 | // console.log("=".repeat(100)); 211 | // console.log(""); 212 | console.log("(See detail in courses section) Available Courses:"); 213 | let allCourses = PIAIC_SMS.getAllCourseInUMS(); 214 | let allAvailabeCourses = []; 215 | allCourses.map((course) => { 216 | if (studentData && !studentData.courses_enrolled.includes(course.course_code)) { 217 | allAvailabeCourses.push(course); 218 | } 219 | }); 220 | const listOfCourseNames = allAvailabeCourses.map((course) => course.course_name); 221 | const ans = await inquirer.prompt([{ 222 | name: "course", 223 | type: "checkbox", 224 | choices: listOfCourseNames, 225 | message: "Select A Course" 226 | }]); 227 | let totalfee = 0; 228 | let allSelectedCorseCodes = []; 229 | allAvailabeCourses.map((course) => { 230 | if (ans.course.includes(course.course_name)) { 231 | totalfee = totalfee + Number(course.tuition_fee); 232 | allSelectedCorseCodes.push(course.course_code); 233 | } 234 | }); 235 | console.log("Total Fee for selected courses: ", totalfee); 236 | console.log(""); 237 | if (totalfee > studentData.balance) { 238 | console.log("You don't have enough Balance for this transaction"); 239 | } 240 | else { 241 | const ans = await inquirer.prompt([{ 242 | name: "course", 243 | type: "confirm", 244 | message: `Your balance is ${studentData.balance} and this will cost you ${totalfee}` 245 | }]); 246 | if (ans.course) { 247 | PIAIC_SMS.enrollInCourses(studentData.studentId, allSelectedCorseCodes); 248 | await updatingComponent(`Enrolling in following courses: ${allSelectedCorseCodes}`); 249 | loggedInWelcomMsg(); 250 | } 251 | } 252 | } 253 | }; 254 | const updatePassword = async () => { 255 | if (!studentData) 256 | return; 257 | loggedInWelcomMsg(); 258 | const ans = await inquirer.prompt([ 259 | { 260 | name: "oldPassword", 261 | type: "input", 262 | message: "Enter Your old password", 263 | }, 264 | { 265 | name: "newPassword", 266 | type: "input", 267 | message: "Enter Your new password", 268 | }, 269 | { 270 | name: "confimredNewPassword", 271 | type: "input", 272 | message: "Enter Your confirmed new password", 273 | }, 274 | ]); 275 | console.log("ans: ", ans); 276 | console.log("studentData.password: ", studentData.password); 277 | if (ans.oldPassword !== studentData.password) { 278 | console.log("Password not matched with old password"); 279 | } 280 | else if (ans.newPassword !== ans.confimredNewPassword) { 281 | console.log("Confirmed password not matched with new password"); 282 | } 283 | else { 284 | PIAIC_SMS.setPassword(studentData.studentId, ans.newPassword, studentData.password); 285 | await updatingComponent(`Updating Password`); 286 | loggedInWelcomMsg(); 287 | } 288 | }; 289 | const handleLoggedInUser = async () => { 290 | const options = await inquirer.prompt([ 291 | { 292 | name: "Options", 293 | type: "list", 294 | choices: ["My Profile", "Edit Profile", "Update Password", "Enroll In a Course", "All Courses", "All Instructors", "Log Out"] 295 | } 296 | ]); 297 | switch (options.Options) { 298 | case "My Profile": 299 | studentCompleteProfile(); 300 | break; 301 | case "Edit Profile": 302 | await editProfile(); 303 | break; 304 | case "Update Password": 305 | await updatePassword(); 306 | break; 307 | case "Enroll In a Course": 308 | await enrollInACourse(); 309 | break; 310 | case "All Courses": 311 | availabelCoursesList(); 312 | break; 313 | case "All Instructors": 314 | availabelInstructorsList(); 315 | break; 316 | case "Log Out": 317 | handleLogOut(); 318 | break; 319 | } 320 | }; 321 | console.clear(); 322 | do { 323 | if (!studentData || !studentData.loginStatus) { 324 | await handleLoggedOutUser(); 325 | } 326 | else { 327 | await handleLoggedInUser(); 328 | } 329 | } while (!quit); 330 | -------------------------------------------------------------------------------- /06_SMS/lib/questions.js: -------------------------------------------------------------------------------- 1 | export const logInOrSignUpQ = { 2 | name: "logInOrSignUp", 3 | type: "list", 4 | choices: ["LogIn", "signUp", "quit"], 5 | message: "Log in or create a new account" 6 | }; 7 | -------------------------------------------------------------------------------- /06_SMS/lib/types.js: -------------------------------------------------------------------------------- 1 | // Types 2 | // Dummy Data 3 | export const coursesList = [ 4 | { 5 | course_code: "01MD", 6 | course_name: "Meraverse Development", 7 | des: "Meraverse Development", 8 | instructor: "Zia Khan", 9 | tuition_fee: 3000 10 | }, 11 | { 12 | course_code: "02BC", 13 | course_name: "Blockchain", 14 | des: "Blockchian", 15 | instructor: "Zeeshan Hanif", 16 | tuition_fee: 5000 17 | }, 18 | { 19 | course_code: "03CC", 20 | course_name: "Cloud Computing", 21 | des: "Cloud Computing", 22 | instructor: "Daniyal Nagori", 23 | tuition_fee: 4000 24 | }, 25 | { 26 | course_code: "04AI", 27 | course_name: "Artificial Intelligence", 28 | des: "Artificial Intelligence", 29 | instructor: "Zia Khan", 30 | tuition_fee: 2500 31 | }, 32 | { 33 | course_code: "05IOT", 34 | course_name: "Internet of things", 35 | des: "Internet of things", 36 | instructor: "Zia Khan", 37 | tuition_fee: 2800 38 | } 39 | ]; 40 | export const instructorsList = [ 41 | { 42 | instructor_name: "Zia Khan", 43 | course_codes: ["01MD", "04AI", "05IOT"] 44 | }, 45 | { 46 | instructor_name: "Daniyal Nagori", 47 | course_codes: ["03CC"] 48 | }, 49 | { 50 | instructor_name: "Zeeshan Hanif", 51 | course_codes: ["02BC"] 52 | } 53 | ]; 54 | -------------------------------------------------------------------------------- /06_SMS/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lms", 3 | "version": "1.1.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "lms", 9 | "version": "1.1.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "inquirer": "^9.1.4" 13 | }, 14 | "devDependencies": { 15 | "@types/inquirer": "^9.0.3" 16 | } 17 | }, 18 | "node_modules/@types/inquirer": { 19 | "version": "9.0.3", 20 | "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.3.tgz", 21 | "integrity": "sha512-CzNkWqQftcmk2jaCWdBTf9Sm7xSw4rkI1zpU/Udw3HX5//adEZUIm9STtoRP1qgWj0CWQtJ9UTvqmO2NNjhMJw==", 22 | "dev": true, 23 | "dependencies": { 24 | "@types/through": "*", 25 | "rxjs": "^7.2.0" 26 | } 27 | }, 28 | "node_modules/@types/node": { 29 | "version": "18.11.17", 30 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.17.tgz", 31 | "integrity": "sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng==", 32 | "dev": true 33 | }, 34 | "node_modules/@types/through": { 35 | "version": "0.0.30", 36 | "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz", 37 | "integrity": "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==", 38 | "dev": true, 39 | "dependencies": { 40 | "@types/node": "*" 41 | } 42 | }, 43 | "node_modules/ansi-escapes": { 44 | "version": "6.0.0", 45 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.0.0.tgz", 46 | "integrity": "sha512-IG23inYII3dWlU2EyiAiGj6Bwal5GzsgPMwjYGvc1HPE2dgbj4ZB5ToWBKSquKw74nB3TIuOwaI6/jSULzfgrw==", 47 | "dependencies": { 48 | "type-fest": "^3.0.0" 49 | }, 50 | "engines": { 51 | "node": ">=14.16" 52 | }, 53 | "funding": { 54 | "url": "https://github.com/sponsors/sindresorhus" 55 | } 56 | }, 57 | "node_modules/ansi-regex": { 58 | "version": "6.0.1", 59 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", 60 | "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", 61 | "engines": { 62 | "node": ">=12" 63 | }, 64 | "funding": { 65 | "url": "https://github.com/chalk/ansi-regex?sponsor=1" 66 | } 67 | }, 68 | "node_modules/ansi-styles": { 69 | "version": "6.2.1", 70 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", 71 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", 72 | "engines": { 73 | "node": ">=12" 74 | }, 75 | "funding": { 76 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 77 | } 78 | }, 79 | "node_modules/base64-js": { 80 | "version": "1.5.1", 81 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 82 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 83 | "funding": [ 84 | { 85 | "type": "github", 86 | "url": "https://github.com/sponsors/feross" 87 | }, 88 | { 89 | "type": "patreon", 90 | "url": "https://www.patreon.com/feross" 91 | }, 92 | { 93 | "type": "consulting", 94 | "url": "https://feross.org/support" 95 | } 96 | ] 97 | }, 98 | "node_modules/bl": { 99 | "version": "5.1.0", 100 | "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", 101 | "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", 102 | "dependencies": { 103 | "buffer": "^6.0.3", 104 | "inherits": "^2.0.4", 105 | "readable-stream": "^3.4.0" 106 | } 107 | }, 108 | "node_modules/buffer": { 109 | "version": "6.0.3", 110 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", 111 | "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", 112 | "funding": [ 113 | { 114 | "type": "github", 115 | "url": "https://github.com/sponsors/feross" 116 | }, 117 | { 118 | "type": "patreon", 119 | "url": "https://www.patreon.com/feross" 120 | }, 121 | { 122 | "type": "consulting", 123 | "url": "https://feross.org/support" 124 | } 125 | ], 126 | "dependencies": { 127 | "base64-js": "^1.3.1", 128 | "ieee754": "^1.2.1" 129 | } 130 | }, 131 | "node_modules/chalk": { 132 | "version": "5.2.0", 133 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", 134 | "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", 135 | "engines": { 136 | "node": "^12.17.0 || ^14.13 || >=16.0.0" 137 | }, 138 | "funding": { 139 | "url": "https://github.com/chalk/chalk?sponsor=1" 140 | } 141 | }, 142 | "node_modules/chardet": { 143 | "version": "0.7.0", 144 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", 145 | "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" 146 | }, 147 | "node_modules/cli-cursor": { 148 | "version": "4.0.0", 149 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", 150 | "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", 151 | "dependencies": { 152 | "restore-cursor": "^4.0.0" 153 | }, 154 | "engines": { 155 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 156 | }, 157 | "funding": { 158 | "url": "https://github.com/sponsors/sindresorhus" 159 | } 160 | }, 161 | "node_modules/cli-spinners": { 162 | "version": "2.7.0", 163 | "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", 164 | "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", 165 | "engines": { 166 | "node": ">=6" 167 | }, 168 | "funding": { 169 | "url": "https://github.com/sponsors/sindresorhus" 170 | } 171 | }, 172 | "node_modules/cli-width": { 173 | "version": "4.0.0", 174 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.0.0.tgz", 175 | "integrity": "sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==", 176 | "engines": { 177 | "node": ">= 12" 178 | } 179 | }, 180 | "node_modules/clone": { 181 | "version": "1.0.4", 182 | "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", 183 | "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", 184 | "engines": { 185 | "node": ">=0.8" 186 | } 187 | }, 188 | "node_modules/defaults": { 189 | "version": "1.0.4", 190 | "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", 191 | "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", 192 | "dependencies": { 193 | "clone": "^1.0.2" 194 | }, 195 | "funding": { 196 | "url": "https://github.com/sponsors/sindresorhus" 197 | } 198 | }, 199 | "node_modules/eastasianwidth": { 200 | "version": "0.2.0", 201 | "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", 202 | "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" 203 | }, 204 | "node_modules/emoji-regex": { 205 | "version": "9.2.2", 206 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 207 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" 208 | }, 209 | "node_modules/escape-string-regexp": { 210 | "version": "5.0.0", 211 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", 212 | "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", 213 | "engines": { 214 | "node": ">=12" 215 | }, 216 | "funding": { 217 | "url": "https://github.com/sponsors/sindresorhus" 218 | } 219 | }, 220 | "node_modules/external-editor": { 221 | "version": "3.1.0", 222 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", 223 | "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", 224 | "dependencies": { 225 | "chardet": "^0.7.0", 226 | "iconv-lite": "^0.4.24", 227 | "tmp": "^0.0.33" 228 | }, 229 | "engines": { 230 | "node": ">=4" 231 | } 232 | }, 233 | "node_modules/figures": { 234 | "version": "5.0.0", 235 | "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", 236 | "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", 237 | "dependencies": { 238 | "escape-string-regexp": "^5.0.0", 239 | "is-unicode-supported": "^1.2.0" 240 | }, 241 | "engines": { 242 | "node": ">=14" 243 | }, 244 | "funding": { 245 | "url": "https://github.com/sponsors/sindresorhus" 246 | } 247 | }, 248 | "node_modules/iconv-lite": { 249 | "version": "0.4.24", 250 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 251 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 252 | "dependencies": { 253 | "safer-buffer": ">= 2.1.2 < 3" 254 | }, 255 | "engines": { 256 | "node": ">=0.10.0" 257 | } 258 | }, 259 | "node_modules/ieee754": { 260 | "version": "1.2.1", 261 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 262 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 263 | "funding": [ 264 | { 265 | "type": "github", 266 | "url": "https://github.com/sponsors/feross" 267 | }, 268 | { 269 | "type": "patreon", 270 | "url": "https://www.patreon.com/feross" 271 | }, 272 | { 273 | "type": "consulting", 274 | "url": "https://feross.org/support" 275 | } 276 | ] 277 | }, 278 | "node_modules/inherits": { 279 | "version": "2.0.4", 280 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 281 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 282 | }, 283 | "node_modules/inquirer": { 284 | "version": "9.1.4", 285 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.1.4.tgz", 286 | "integrity": "sha512-9hiJxE5gkK/cM2d1mTEnuurGTAoHebbkX0BYl3h7iEg7FYfuNIom+nDfBCSWtvSnoSrWCeBxqqBZu26xdlJlXA==", 287 | "dependencies": { 288 | "ansi-escapes": "^6.0.0", 289 | "chalk": "^5.1.2", 290 | "cli-cursor": "^4.0.0", 291 | "cli-width": "^4.0.0", 292 | "external-editor": "^3.0.3", 293 | "figures": "^5.0.0", 294 | "lodash": "^4.17.21", 295 | "mute-stream": "0.0.8", 296 | "ora": "^6.1.2", 297 | "run-async": "^2.4.0", 298 | "rxjs": "^7.5.7", 299 | "string-width": "^5.1.2", 300 | "strip-ansi": "^7.0.1", 301 | "through": "^2.3.6", 302 | "wrap-ansi": "^8.0.1" 303 | }, 304 | "engines": { 305 | "node": ">=12.0.0" 306 | } 307 | }, 308 | "node_modules/is-interactive": { 309 | "version": "2.0.0", 310 | "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", 311 | "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", 312 | "engines": { 313 | "node": ">=12" 314 | }, 315 | "funding": { 316 | "url": "https://github.com/sponsors/sindresorhus" 317 | } 318 | }, 319 | "node_modules/is-unicode-supported": { 320 | "version": "1.3.0", 321 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", 322 | "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", 323 | "engines": { 324 | "node": ">=12" 325 | }, 326 | "funding": { 327 | "url": "https://github.com/sponsors/sindresorhus" 328 | } 329 | }, 330 | "node_modules/lodash": { 331 | "version": "4.17.21", 332 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 333 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 334 | }, 335 | "node_modules/log-symbols": { 336 | "version": "5.1.0", 337 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", 338 | "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", 339 | "dependencies": { 340 | "chalk": "^5.0.0", 341 | "is-unicode-supported": "^1.1.0" 342 | }, 343 | "engines": { 344 | "node": ">=12" 345 | }, 346 | "funding": { 347 | "url": "https://github.com/sponsors/sindresorhus" 348 | } 349 | }, 350 | "node_modules/mimic-fn": { 351 | "version": "2.1.0", 352 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 353 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", 354 | "engines": { 355 | "node": ">=6" 356 | } 357 | }, 358 | "node_modules/mute-stream": { 359 | "version": "0.0.8", 360 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", 361 | "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" 362 | }, 363 | "node_modules/onetime": { 364 | "version": "5.1.2", 365 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", 366 | "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", 367 | "dependencies": { 368 | "mimic-fn": "^2.1.0" 369 | }, 370 | "engines": { 371 | "node": ">=6" 372 | }, 373 | "funding": { 374 | "url": "https://github.com/sponsors/sindresorhus" 375 | } 376 | }, 377 | "node_modules/ora": { 378 | "version": "6.1.2", 379 | "resolved": "https://registry.npmjs.org/ora/-/ora-6.1.2.tgz", 380 | "integrity": "sha512-EJQ3NiP5Xo94wJXIzAyOtSb0QEIAUu7m8t6UZ9krbz0vAJqr92JpcK/lEXg91q6B9pEGqrykkd2EQplnifDSBw==", 381 | "dependencies": { 382 | "bl": "^5.0.0", 383 | "chalk": "^5.0.0", 384 | "cli-cursor": "^4.0.0", 385 | "cli-spinners": "^2.6.1", 386 | "is-interactive": "^2.0.0", 387 | "is-unicode-supported": "^1.1.0", 388 | "log-symbols": "^5.1.0", 389 | "strip-ansi": "^7.0.1", 390 | "wcwidth": "^1.0.1" 391 | }, 392 | "engines": { 393 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 394 | }, 395 | "funding": { 396 | "url": "https://github.com/sponsors/sindresorhus" 397 | } 398 | }, 399 | "node_modules/os-tmpdir": { 400 | "version": "1.0.2", 401 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 402 | "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", 403 | "engines": { 404 | "node": ">=0.10.0" 405 | } 406 | }, 407 | "node_modules/readable-stream": { 408 | "version": "3.6.0", 409 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 410 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 411 | "dependencies": { 412 | "inherits": "^2.0.3", 413 | "string_decoder": "^1.1.1", 414 | "util-deprecate": "^1.0.1" 415 | }, 416 | "engines": { 417 | "node": ">= 6" 418 | } 419 | }, 420 | "node_modules/restore-cursor": { 421 | "version": "4.0.0", 422 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", 423 | "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", 424 | "dependencies": { 425 | "onetime": "^5.1.0", 426 | "signal-exit": "^3.0.2" 427 | }, 428 | "engines": { 429 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 430 | }, 431 | "funding": { 432 | "url": "https://github.com/sponsors/sindresorhus" 433 | } 434 | }, 435 | "node_modules/run-async": { 436 | "version": "2.4.1", 437 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", 438 | "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", 439 | "engines": { 440 | "node": ">=0.12.0" 441 | } 442 | }, 443 | "node_modules/rxjs": { 444 | "version": "7.8.0", 445 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", 446 | "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", 447 | "dependencies": { 448 | "tslib": "^2.1.0" 449 | } 450 | }, 451 | "node_modules/safe-buffer": { 452 | "version": "5.2.1", 453 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 454 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 455 | "funding": [ 456 | { 457 | "type": "github", 458 | "url": "https://github.com/sponsors/feross" 459 | }, 460 | { 461 | "type": "patreon", 462 | "url": "https://www.patreon.com/feross" 463 | }, 464 | { 465 | "type": "consulting", 466 | "url": "https://feross.org/support" 467 | } 468 | ] 469 | }, 470 | "node_modules/safer-buffer": { 471 | "version": "2.1.2", 472 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 473 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 474 | }, 475 | "node_modules/signal-exit": { 476 | "version": "3.0.7", 477 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", 478 | "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" 479 | }, 480 | "node_modules/string_decoder": { 481 | "version": "1.3.0", 482 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 483 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 484 | "dependencies": { 485 | "safe-buffer": "~5.2.0" 486 | } 487 | }, 488 | "node_modules/string-width": { 489 | "version": "5.1.2", 490 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", 491 | "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", 492 | "dependencies": { 493 | "eastasianwidth": "^0.2.0", 494 | "emoji-regex": "^9.2.2", 495 | "strip-ansi": "^7.0.1" 496 | }, 497 | "engines": { 498 | "node": ">=12" 499 | }, 500 | "funding": { 501 | "url": "https://github.com/sponsors/sindresorhus" 502 | } 503 | }, 504 | "node_modules/strip-ansi": { 505 | "version": "7.0.1", 506 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", 507 | "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", 508 | "dependencies": { 509 | "ansi-regex": "^6.0.1" 510 | }, 511 | "engines": { 512 | "node": ">=12" 513 | }, 514 | "funding": { 515 | "url": "https://github.com/chalk/strip-ansi?sponsor=1" 516 | } 517 | }, 518 | "node_modules/through": { 519 | "version": "2.3.8", 520 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 521 | "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" 522 | }, 523 | "node_modules/tmp": { 524 | "version": "0.0.33", 525 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 526 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 527 | "dependencies": { 528 | "os-tmpdir": "~1.0.2" 529 | }, 530 | "engines": { 531 | "node": ">=0.6.0" 532 | } 533 | }, 534 | "node_modules/tslib": { 535 | "version": "2.4.1", 536 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", 537 | "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" 538 | }, 539 | "node_modules/type-fest": { 540 | "version": "3.4.0", 541 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.4.0.tgz", 542 | "integrity": "sha512-PEPg6RHlB9cFwoTMNENNrQFL0cXX04voWr2UPwQBJ3pVs7Mt8Y1oLWdUeMdGEwZE8HFFlujq8gS9enmyiQ8pLg==", 543 | "engines": { 544 | "node": ">=14.16" 545 | }, 546 | "funding": { 547 | "url": "https://github.com/sponsors/sindresorhus" 548 | } 549 | }, 550 | "node_modules/util-deprecate": { 551 | "version": "1.0.2", 552 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 553 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" 554 | }, 555 | "node_modules/wcwidth": { 556 | "version": "1.0.1", 557 | "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", 558 | "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", 559 | "dependencies": { 560 | "defaults": "^1.0.3" 561 | } 562 | }, 563 | "node_modules/wrap-ansi": { 564 | "version": "8.0.1", 565 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.0.1.tgz", 566 | "integrity": "sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==", 567 | "dependencies": { 568 | "ansi-styles": "^6.1.0", 569 | "string-width": "^5.0.1", 570 | "strip-ansi": "^7.0.1" 571 | }, 572 | "engines": { 573 | "node": ">=12" 574 | }, 575 | "funding": { 576 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 577 | } 578 | } 579 | }, 580 | "dependencies": { 581 | "@types/inquirer": { 582 | "version": "9.0.3", 583 | "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.3.tgz", 584 | "integrity": "sha512-CzNkWqQftcmk2jaCWdBTf9Sm7xSw4rkI1zpU/Udw3HX5//adEZUIm9STtoRP1qgWj0CWQtJ9UTvqmO2NNjhMJw==", 585 | "dev": true, 586 | "requires": { 587 | "@types/through": "*", 588 | "rxjs": "^7.2.0" 589 | } 590 | }, 591 | "@types/node": { 592 | "version": "18.11.17", 593 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.17.tgz", 594 | "integrity": "sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng==", 595 | "dev": true 596 | }, 597 | "@types/through": { 598 | "version": "0.0.30", 599 | "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz", 600 | "integrity": "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==", 601 | "dev": true, 602 | "requires": { 603 | "@types/node": "*" 604 | } 605 | }, 606 | "ansi-escapes": { 607 | "version": "6.0.0", 608 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.0.0.tgz", 609 | "integrity": "sha512-IG23inYII3dWlU2EyiAiGj6Bwal5GzsgPMwjYGvc1HPE2dgbj4ZB5ToWBKSquKw74nB3TIuOwaI6/jSULzfgrw==", 610 | "requires": { 611 | "type-fest": "^3.0.0" 612 | } 613 | }, 614 | "ansi-regex": { 615 | "version": "6.0.1", 616 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", 617 | "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" 618 | }, 619 | "ansi-styles": { 620 | "version": "6.2.1", 621 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", 622 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" 623 | }, 624 | "base64-js": { 625 | "version": "1.5.1", 626 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 627 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" 628 | }, 629 | "bl": { 630 | "version": "5.1.0", 631 | "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", 632 | "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", 633 | "requires": { 634 | "buffer": "^6.0.3", 635 | "inherits": "^2.0.4", 636 | "readable-stream": "^3.4.0" 637 | } 638 | }, 639 | "buffer": { 640 | "version": "6.0.3", 641 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", 642 | "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", 643 | "requires": { 644 | "base64-js": "^1.3.1", 645 | "ieee754": "^1.2.1" 646 | } 647 | }, 648 | "chalk": { 649 | "version": "5.2.0", 650 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", 651 | "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==" 652 | }, 653 | "chardet": { 654 | "version": "0.7.0", 655 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", 656 | "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" 657 | }, 658 | "cli-cursor": { 659 | "version": "4.0.0", 660 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", 661 | "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", 662 | "requires": { 663 | "restore-cursor": "^4.0.0" 664 | } 665 | }, 666 | "cli-spinners": { 667 | "version": "2.7.0", 668 | "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", 669 | "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==" 670 | }, 671 | "cli-width": { 672 | "version": "4.0.0", 673 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.0.0.tgz", 674 | "integrity": "sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==" 675 | }, 676 | "clone": { 677 | "version": "1.0.4", 678 | "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", 679 | "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" 680 | }, 681 | "defaults": { 682 | "version": "1.0.4", 683 | "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", 684 | "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", 685 | "requires": { 686 | "clone": "^1.0.2" 687 | } 688 | }, 689 | "eastasianwidth": { 690 | "version": "0.2.0", 691 | "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", 692 | "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" 693 | }, 694 | "emoji-regex": { 695 | "version": "9.2.2", 696 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 697 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" 698 | }, 699 | "escape-string-regexp": { 700 | "version": "5.0.0", 701 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", 702 | "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==" 703 | }, 704 | "external-editor": { 705 | "version": "3.1.0", 706 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", 707 | "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", 708 | "requires": { 709 | "chardet": "^0.7.0", 710 | "iconv-lite": "^0.4.24", 711 | "tmp": "^0.0.33" 712 | } 713 | }, 714 | "figures": { 715 | "version": "5.0.0", 716 | "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", 717 | "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", 718 | "requires": { 719 | "escape-string-regexp": "^5.0.0", 720 | "is-unicode-supported": "^1.2.0" 721 | } 722 | }, 723 | "iconv-lite": { 724 | "version": "0.4.24", 725 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 726 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 727 | "requires": { 728 | "safer-buffer": ">= 2.1.2 < 3" 729 | } 730 | }, 731 | "ieee754": { 732 | "version": "1.2.1", 733 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 734 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" 735 | }, 736 | "inherits": { 737 | "version": "2.0.4", 738 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 739 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 740 | }, 741 | "inquirer": { 742 | "version": "9.1.4", 743 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.1.4.tgz", 744 | "integrity": "sha512-9hiJxE5gkK/cM2d1mTEnuurGTAoHebbkX0BYl3h7iEg7FYfuNIom+nDfBCSWtvSnoSrWCeBxqqBZu26xdlJlXA==", 745 | "requires": { 746 | "ansi-escapes": "^6.0.0", 747 | "chalk": "^5.1.2", 748 | "cli-cursor": "^4.0.0", 749 | "cli-width": "^4.0.0", 750 | "external-editor": "^3.0.3", 751 | "figures": "^5.0.0", 752 | "lodash": "^4.17.21", 753 | "mute-stream": "0.0.8", 754 | "ora": "^6.1.2", 755 | "run-async": "^2.4.0", 756 | "rxjs": "^7.5.7", 757 | "string-width": "^5.1.2", 758 | "strip-ansi": "^7.0.1", 759 | "through": "^2.3.6", 760 | "wrap-ansi": "^8.0.1" 761 | } 762 | }, 763 | "is-interactive": { 764 | "version": "2.0.0", 765 | "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", 766 | "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==" 767 | }, 768 | "is-unicode-supported": { 769 | "version": "1.3.0", 770 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", 771 | "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==" 772 | }, 773 | "lodash": { 774 | "version": "4.17.21", 775 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 776 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 777 | }, 778 | "log-symbols": { 779 | "version": "5.1.0", 780 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", 781 | "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", 782 | "requires": { 783 | "chalk": "^5.0.0", 784 | "is-unicode-supported": "^1.1.0" 785 | } 786 | }, 787 | "mimic-fn": { 788 | "version": "2.1.0", 789 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 790 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" 791 | }, 792 | "mute-stream": { 793 | "version": "0.0.8", 794 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", 795 | "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" 796 | }, 797 | "onetime": { 798 | "version": "5.1.2", 799 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", 800 | "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", 801 | "requires": { 802 | "mimic-fn": "^2.1.0" 803 | } 804 | }, 805 | "ora": { 806 | "version": "6.1.2", 807 | "resolved": "https://registry.npmjs.org/ora/-/ora-6.1.2.tgz", 808 | "integrity": "sha512-EJQ3NiP5Xo94wJXIzAyOtSb0QEIAUu7m8t6UZ9krbz0vAJqr92JpcK/lEXg91q6B9pEGqrykkd2EQplnifDSBw==", 809 | "requires": { 810 | "bl": "^5.0.0", 811 | "chalk": "^5.0.0", 812 | "cli-cursor": "^4.0.0", 813 | "cli-spinners": "^2.6.1", 814 | "is-interactive": "^2.0.0", 815 | "is-unicode-supported": "^1.1.0", 816 | "log-symbols": "^5.1.0", 817 | "strip-ansi": "^7.0.1", 818 | "wcwidth": "^1.0.1" 819 | } 820 | }, 821 | "os-tmpdir": { 822 | "version": "1.0.2", 823 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 824 | "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==" 825 | }, 826 | "readable-stream": { 827 | "version": "3.6.0", 828 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 829 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 830 | "requires": { 831 | "inherits": "^2.0.3", 832 | "string_decoder": "^1.1.1", 833 | "util-deprecate": "^1.0.1" 834 | } 835 | }, 836 | "restore-cursor": { 837 | "version": "4.0.0", 838 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", 839 | "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", 840 | "requires": { 841 | "onetime": "^5.1.0", 842 | "signal-exit": "^3.0.2" 843 | } 844 | }, 845 | "run-async": { 846 | "version": "2.4.1", 847 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", 848 | "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" 849 | }, 850 | "rxjs": { 851 | "version": "7.8.0", 852 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", 853 | "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", 854 | "requires": { 855 | "tslib": "^2.1.0" 856 | } 857 | }, 858 | "safe-buffer": { 859 | "version": "5.2.1", 860 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 861 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 862 | }, 863 | "safer-buffer": { 864 | "version": "2.1.2", 865 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 866 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 867 | }, 868 | "signal-exit": { 869 | "version": "3.0.7", 870 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", 871 | "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" 872 | }, 873 | "string_decoder": { 874 | "version": "1.3.0", 875 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 876 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 877 | "requires": { 878 | "safe-buffer": "~5.2.0" 879 | } 880 | }, 881 | "string-width": { 882 | "version": "5.1.2", 883 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", 884 | "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", 885 | "requires": { 886 | "eastasianwidth": "^0.2.0", 887 | "emoji-regex": "^9.2.2", 888 | "strip-ansi": "^7.0.1" 889 | } 890 | }, 891 | "strip-ansi": { 892 | "version": "7.0.1", 893 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", 894 | "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", 895 | "requires": { 896 | "ansi-regex": "^6.0.1" 897 | } 898 | }, 899 | "through": { 900 | "version": "2.3.8", 901 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 902 | "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" 903 | }, 904 | "tmp": { 905 | "version": "0.0.33", 906 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 907 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 908 | "requires": { 909 | "os-tmpdir": "~1.0.2" 910 | } 911 | }, 912 | "tslib": { 913 | "version": "2.4.1", 914 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", 915 | "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" 916 | }, 917 | "type-fest": { 918 | "version": "3.4.0", 919 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.4.0.tgz", 920 | "integrity": "sha512-PEPg6RHlB9cFwoTMNENNrQFL0cXX04voWr2UPwQBJ3pVs7Mt8Y1oLWdUeMdGEwZE8HFFlujq8gS9enmyiQ8pLg==" 921 | }, 922 | "util-deprecate": { 923 | "version": "1.0.2", 924 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 925 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" 926 | }, 927 | "wcwidth": { 928 | "version": "1.0.1", 929 | "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", 930 | "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", 931 | "requires": { 932 | "defaults": "^1.0.3" 933 | } 934 | }, 935 | "wrap-ansi": { 936 | "version": "8.0.1", 937 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.0.1.tgz", 938 | "integrity": "sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==", 939 | "requires": { 940 | "ansi-styles": "^6.1.0", 941 | "string-width": "^5.0.1", 942 | "strip-ansi": "^7.0.1" 943 | } 944 | } 945 | } 946 | } 947 | -------------------------------------------------------------------------------- /06_SMS/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "student_management_system", 3 | "version": "1.1.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "bin": { 8 | "sms": "lib/index.js" 9 | }, 10 | "scripts": { 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "dependencies": { 17 | "inquirer": "^9.1.4" 18 | }, 19 | "devDependencies": { 20 | "@types/inquirer": "^9.0.3" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /06_SMS/src/Course.ts: -------------------------------------------------------------------------------- 1 | export class Course { 2 | course_code: string; 3 | course_name: string; 4 | course_description: string; 5 | course_instructor: string; 6 | tuition_fee: number; 7 | 8 | 9 | constructor( 10 | code: string, 11 | name: string, 12 | description: string, 13 | course_instructor: string, 14 | tuition_fee: number 15 | ) { 16 | this.course_code = code; 17 | this.course_name = name; 18 | this.course_description = description; 19 | this.course_instructor = course_instructor; 20 | this.tuition_fee = tuition_fee; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /06_SMS/src/Instructor.ts: -------------------------------------------------------------------------------- 1 | export class Instructor { 2 | name: string; 3 | course_codes: string[] = []; 4 | 5 | constructor(name: string, course_codes?: string[]) { 6 | this.name = name; 7 | 8 | if (course_codes) { 9 | this.course_codes.push(...course_codes) 10 | } 11 | 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /06_SMS/src/Person.ts: -------------------------------------------------------------------------------- 1 | export class Person { 2 | _id?: number; 3 | _name: string; 4 | _age?: number; 5 | _gender?: string; 6 | constructor(name: string) { 7 | this._name = name; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /06_SMS/src/SMS.ts: -------------------------------------------------------------------------------- 1 | import { Course } from "./Course.js"; 2 | import { Instructor } from "./Instructor.js"; 3 | import { Student } from "./Student.js"; 4 | import { CourseInput, InstructorInput } from "./types.js"; 5 | 6 | 7 | class SMS { 8 | 9 | private _idsGenetor = 0; 10 | name: string; 11 | students = new Map(); 12 | courses = new Map(); 13 | instructors = new Map(); 14 | balance = 0; 15 | 16 | 17 | constructor(_name: string) { 18 | this.name = _name; 19 | } 20 | 21 | AddInstructorsInUMS(_instructors: InstructorInput[]) { 22 | _instructors.map((instructor) => { 23 | let newIstructor = new Instructor(instructor.instructor_name, instructor.course_codes) 24 | this.instructors.set(instructor.instructor_name, newIstructor); 25 | }) 26 | } 27 | 28 | AddCoursesinUMS(_courses: CourseInput[]) { 29 | _courses.map((course) => { 30 | const {course_code, course_name, des, instructor, tuition_fee} = course; 31 | const newCourse = new Course(course_code, course_name, des, instructor, tuition_fee) 32 | this.courses.set(course.course_code, newCourse); 33 | }) 34 | } 35 | 36 | getAllCourseInUMS(): Course[] { 37 | return [...this.courses.values()] 38 | } 39 | 40 | getCourseById(code: string): Course | undefined { 41 | return this.courses.get(code); 42 | } 43 | 44 | getAllInstructorsInUMS(): Instructor[] { 45 | return [...this.instructors.values()] 46 | } 47 | 48 | getInstructorByName(name: string): Instructor | undefined { 49 | return this.instructors.get(name); 50 | } 51 | 52 | enrollStudentinUMS(name: string, cnic: number, section: "Morning"|"Evening") { 53 | const newId = ++this._idsGenetor; 54 | var password = (Math.floor(Math.random() * 10000) + 10000).toString().substring(1); 55 | const student = new Student(name, cnic, section, newId, password); 56 | this.students.set(newId, student); 57 | return { id: newId, password: password }; 58 | } 59 | 60 | getAllStudents(): Student[] { 61 | return [...this.students.values()] 62 | } 63 | 64 | getStudentById(id: number): Student | undefined { 65 | return this.students.get(id); 66 | } 67 | 68 | 69 | 70 | /** 71 | Student related Methods 72 | 73 | * Student set and reset a password 74 | * Student should be able to sign in the system 75 | * Student should read enrolled courses, enroll in or drop off one or many courses using courseId 76 | 77 | */ 78 | 79 | logIn(studentId: number, password: string): {status: boolean, msg: string} { 80 | 81 | let student = this.students.get(studentId); 82 | 83 | if (!student) { 84 | return { 85 | status: false, 86 | msg: "Student do not exist" 87 | } 88 | } 89 | 90 | if (student.password == password) { 91 | student.loginStatus = true; 92 | this.students.set(studentId, student); 93 | return { 94 | status: true, 95 | msg: "Successfully Logged In" 96 | } 97 | } 98 | else { 99 | return { 100 | status: false, 101 | msg: "Incorrect password" 102 | } 103 | 104 | } 105 | 106 | 107 | } 108 | 109 | setPassword(studentId: number, newPassword: string, oldPassword: string) { 110 | let student = this.students.get(studentId); 111 | 112 | if (!student) throw Error("Student do not exist"); 113 | if (!student.loginStatus) throw Error("Not logged In"); 114 | 115 | if (student.password === oldPassword) { 116 | student.password = newPassword; 117 | this.students.set(studentId, student); 118 | } 119 | else { 120 | throw Error("Incorrect password"); 121 | } 122 | 123 | } 124 | 125 | setProfile(studentId: number, name: string, age: number, address: string, cnic: number){ 126 | let student = this.students.get(studentId); 127 | 128 | if (!student) throw Error("Student do not exist"); 129 | if (!student.loginStatus) throw Error("Not logged In"); 130 | 131 | student.name = name; 132 | student.age = age; 133 | student.address = address; 134 | student.cnic = cnic; 135 | } 136 | 137 | enrollInCourses(studentId: number, courseCodes: string[]) { 138 | 139 | let student = this.students.get(studentId); 140 | if (!student) throw Error("Student do not exist"); 141 | if (!student.loginStatus) throw Error("You are not logged In"); 142 | 143 | let totalFeeToPay = 0 144 | courseCodes.map((code: string) => { 145 | const course = this.courses.get(code); 146 | if(course){ 147 | totalFeeToPay = totalFeeToPay + course.tuition_fee; 148 | } 149 | }) 150 | 151 | if(student.balance < Number(totalFeeToPay)){ 152 | throw Error("You don't have enough balance to enroll in these courses"); 153 | } 154 | 155 | courseCodes.forEach((code) => { 156 | const course = this.courses.get(code) 157 | if (!course) throw Error(`course do not exist ${code}`); 158 | 159 | if (student) { 160 | this.balance += course.tuition_fee; 161 | student.balance -= course.tuition_fee; 162 | student.courses_enrolled.push(course.course_code); 163 | } 164 | }) 165 | 166 | this.students.set(studentId, student); 167 | } 168 | 169 | dropOffCourses(studentId: number, courseCodes: string[]) { 170 | let student = this.students.get(studentId); 171 | if (!student) throw Error("Student do not exist"); 172 | if (!student.loginStatus) throw Error("You are not logged In"); 173 | 174 | courseCodes.forEach((code) => { 175 | if (student) { 176 | const course = this.courses.get(code); 177 | if(course){ 178 | 179 | this.balance -= (course.tuition_fee * 0.5); 180 | student.balance += (course.tuition_fee * 0.5); 181 | 182 | student.courses_enrolled = student.courses_enrolled 183 | .filter((course_code) => course_code !== code); 184 | 185 | } 186 | } 187 | 188 | }) 189 | 190 | this.students.set(studentId, student); 191 | } 192 | 193 | } 194 | 195 | export default new SMS("PIAIC STUDENT MANAGEMENT SYSTEM"); 196 | -------------------------------------------------------------------------------- /06_SMS/src/Student.ts: -------------------------------------------------------------------------------- 1 | export class Student { 2 | name: string; 3 | cnic: number; 4 | studentId: number; 5 | student_section: "Morning" | "Evening"; 6 | password: string; 7 | 8 | // Default parameters 9 | courses_enrolled: string[] = []; 10 | loginStatus = false; 11 | balance = 10_000; 12 | 13 | // Optional parameters 14 | age?: number; 15 | address?: string; 16 | 17 | 18 | constructor( 19 | _name: string, 20 | _cnic: number, 21 | _student_section: "Morning" | "Evening", 22 | _studentId: number, 23 | _password: string, 24 | ) { 25 | 26 | this.name = _name; 27 | this.cnic = _cnic; 28 | this.student_section = _student_section; 29 | this.studentId = _studentId; 30 | this.password = _password; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /06_SMS/src/index.ts: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | 3 | import { coursesList, instructorsList } from "./types.js"; 4 | import { Student } from "./Student.js"; 5 | import { Course } from "./Course.js"; 6 | import PIAIC_SMS from "./SMS.js"; 7 | 8 | import inquirer from "inquirer"; 9 | 10 | let studentData: Student | undefined; 11 | let quit = false; 12 | 13 | 14 | PIAIC_SMS.AddCoursesinUMS(coursesList); 15 | PIAIC_SMS.AddInstructorsInUMS(instructorsList); 16 | // const dummyStudent = PIAIC_SMS.enrollStudentinUMS("Ali", 33102, "Morning"); 17 | // PIAIC_SMS.logIn(dummyStudent.id, dummyStudent.password); 18 | // PIAIC_SMS.setPassword(dummyStudent.id, "1234", dummyStudent.password); 19 | // const student = PIAIC_SMS.getStudentById(dummyStudent.id); 20 | // studentData = student 21 | 22 | 23 | const delay = async (ms = 2000) => { 24 | return new Promise((res) => setTimeout(res, ms)); 25 | } 26 | 27 | const updatingComponent = async (msg: string) => { 28 | for (let i = 1; i < 100; i++) { 29 | const show = "=".repeat(i); 30 | console.clear(); 31 | console.log(); 32 | console.log(msg); 33 | console.log(show); 34 | console.log(); 35 | await delay(10); 36 | } 37 | } 38 | 39 | const welcomeMsg = () => { 40 | console.log("Welcome to", PIAIC_SMS.name + "\n"); 41 | } 42 | 43 | const handleLoggedOutUser = async () => { 44 | 45 | welcomeMsg(); 46 | 47 | const answers = await inquirer.prompt([ 48 | { 49 | name: "LogIn", 50 | type: "list", 51 | choices: ["Log In", "Sign Up", "Quit"], 52 | message: "Log in or create a new account" 53 | } 54 | ]) 55 | 56 | switch (answers.LogIn) { 57 | case "Log In": 58 | await handleLogin(); 59 | break; 60 | case "Sign Up": 61 | await handleSingUp(); 62 | break; 63 | case "Quit": 64 | handleQuit(); 65 | break; 66 | } 67 | } 68 | 69 | const handleSingUp = async () => { 70 | 71 | const ans = await inquirer.prompt([ 72 | { 73 | name: "name", 74 | message: "enter you name", 75 | type: "input" 76 | }, 77 | { 78 | name: "CNIC", 79 | message: "enter your CNIC", 80 | type: "number" 81 | }, 82 | { 83 | name: "secion", 84 | message: "Choose a section", 85 | type: "list", 86 | choices: ["Morning", "Evening"] 87 | } 88 | ]) 89 | 90 | const newStudent = PIAIC_SMS.enrollStudentinUMS(ans.name, ans.CNIC, ans.secion); 91 | 92 | console.clear(); 93 | console.log(""); 94 | console.log("Student Id: ", newStudent.id); 95 | console.log("Password: ", newStudent.password + "\n"); 96 | console.log(""); 97 | 98 | } 99 | 100 | const handleLogin = async () => { 101 | 102 | const ans = await inquirer.prompt([ 103 | { 104 | name: "id", 105 | message: "enter your student Id", 106 | type: "number" 107 | }, 108 | { 109 | name: "password", 110 | message: "enter your password", 111 | type: "password", 112 | masked: true 113 | } 114 | ]) 115 | 116 | const res = PIAIC_SMS.logIn(ans.id, ans.password); 117 | if (res.status) { 118 | let student = PIAIC_SMS.getStudentById(ans.id); 119 | studentData = student! 120 | } 121 | else { 122 | console.log(""); 123 | console.log(res.msg); 124 | console.log(""); 125 | } 126 | 127 | } 128 | 129 | const handleQuit = () => { 130 | quit = true; 131 | console.log("Bye. See you later") 132 | } 133 | 134 | const handleLogOut = () => { 135 | console.clear() 136 | studentData = undefined; 137 | } 138 | 139 | const loggedInWelcomMsg = () => { 140 | if (studentData) { 141 | 142 | console.clear(); 143 | console.log("Welcome to PIAIC Student Management System"); 144 | console.log(""); 145 | console.table([ 146 | { 147 | "Name": studentData?.name, 148 | "Student Id": studentData?.studentId, 149 | "Balance": studentData?.balance 150 | } 151 | ]) 152 | console.log(""); 153 | } 154 | } 155 | 156 | const availabelCoursesList = () => { 157 | if (studentData) { 158 | loggedInWelcomMsg(); 159 | 160 | const allCourses = PIAIC_SMS.getAllCourseInUMS(); 161 | console.table(allCourses); 162 | console.log(""); 163 | 164 | } 165 | } 166 | 167 | const availabelInstructorsList = () => { 168 | if (studentData) { 169 | loggedInWelcomMsg(); 170 | 171 | const allInstructors = PIAIC_SMS.getAllInstructorsInUMS(); 172 | const formatedData: any = []; 173 | 174 | allInstructors.forEach((instructor) => { 175 | const coursesName = instructor.course_codes.map((code) => PIAIC_SMS.getCourseById(code)?.course_name).join(", "); 176 | formatedData.push({ 177 | "Name": instructor.name, 178 | "Courses Teaching": coursesName 179 | }) 180 | }) 181 | 182 | console.table(formatedData); 183 | console.log(""); 184 | 185 | } 186 | } 187 | 188 | const studentCompleteProfile = () => { 189 | if (studentData) { 190 | loggedInWelcomMsg(); 191 | console.table([studentData]) 192 | console.log(""); 193 | } 194 | 195 | } 196 | 197 | const editProfile = async () => { 198 | 199 | loggedInWelcomMsg(); 200 | 201 | const ans = await inquirer.prompt([ 202 | { 203 | name: "name", 204 | type: "input", 205 | message: "Your name", 206 | default: studentData?.name 207 | }, 208 | { 209 | name: "age", 210 | type: "number", 211 | message: "Your Age", 212 | default: studentData?.age 213 | }, 214 | { 215 | name: "address", 216 | type: "input", 217 | message: "Your Address", 218 | default: studentData?.address 219 | }, 220 | { 221 | name: "cnic", 222 | type: "number", 223 | message: "Your CNIC", 224 | default: studentData?.cnic 225 | }, 226 | ]) 227 | 228 | const { name, age, address, cnic } = ans; 229 | 230 | if (studentData) { 231 | PIAIC_SMS.setProfile(studentData.studentId, name, age, address, cnic) 232 | } 233 | 234 | await updatingComponent("Updating Profile"); 235 | loggedInWelcomMsg(); 236 | 237 | 238 | 239 | } 240 | 241 | const enrollInACourse = async () => { 242 | if (studentData) { 243 | loggedInWelcomMsg(); 244 | 245 | console.log("Already Enrolled In Courses:") 246 | 247 | if (studentData.courses_enrolled.length === 0) { 248 | console.log("None"); 249 | console.log(""); 250 | } 251 | else { 252 | const coursesNames = studentData.courses_enrolled.map((course) => { 253 | return PIAIC_SMS.getCourseById(course)?.course_name; 254 | }) 255 | console.table(coursesNames) 256 | console.log(""); 257 | } 258 | 259 | console.log("(See detail in courses section) Available Courses:") 260 | 261 | let allCourses = PIAIC_SMS.getAllCourseInUMS(); 262 | 263 | let allAvailabeCourses: Course[] = []; 264 | allCourses.map((course) => { 265 | if (studentData && !studentData.courses_enrolled.includes(course.course_code)) { 266 | allAvailabeCourses.push(course); 267 | } 268 | }) 269 | 270 | const listOfCourseNames = allAvailabeCourses.map((course) => course.course_name); 271 | 272 | const ans = await inquirer.prompt([{ 273 | name: "course", 274 | type: "checkbox", 275 | choices: listOfCourseNames, 276 | message: "Select A Course" 277 | }]) 278 | 279 | let totalfee = 0; 280 | let allSelectedCorseCodes: string[] = []; 281 | 282 | allAvailabeCourses.map((course) => { 283 | if (ans.course.includes(course.course_name)) { 284 | totalfee = totalfee + Number(course.tuition_fee) 285 | allSelectedCorseCodes.push(course.course_code) 286 | } 287 | }) 288 | 289 | console.log("Total Fee for selected courses: ", totalfee); 290 | console.log(""); 291 | 292 | if (totalfee > studentData.balance) { 293 | console.log("You don't have enough Balance for this transaction"); 294 | } 295 | else { 296 | const ans = await inquirer.prompt([{ 297 | name: "course", 298 | type: "confirm", 299 | message: `Your balance is ${studentData.balance} and this will cost you ${totalfee}` 300 | }]) 301 | if (ans.course) { 302 | PIAIC_SMS.enrollInCourses(studentData.studentId, allSelectedCorseCodes); 303 | await updatingComponent(`Enrolling in following courses: ${allSelectedCorseCodes}`); 304 | loggedInWelcomMsg(); 305 | } 306 | 307 | } 308 | 309 | } 310 | 311 | } 312 | 313 | const updatePassword = async () => { 314 | if (!studentData) return; 315 | 316 | loggedInWelcomMsg(); 317 | 318 | const ans = await inquirer.prompt([ 319 | { 320 | name: "oldPassword", 321 | type: "input", 322 | message: "Enter Your old password", 323 | }, 324 | { 325 | name: "newPassword", 326 | type: "input", 327 | message: "Enter Your new password", 328 | }, 329 | { 330 | name: "confimredNewPassword", 331 | type: "input", 332 | message: "Enter Your confirmed new password", 333 | }, 334 | ]) 335 | 336 | console.log("ans: ", ans); 337 | console.log("studentData.password: ", studentData.password); 338 | 339 | if (ans.oldPassword !== studentData.password) { 340 | console.log("Password not matched with old password"); 341 | } 342 | else if (ans.newPassword !== ans.confimredNewPassword) { 343 | console.log("Confirmed password not matched with new password"); 344 | } 345 | else { 346 | 347 | PIAIC_SMS.setPassword(studentData.studentId, ans.newPassword, studentData.password); 348 | await updatingComponent(`Updating Password`); 349 | loggedInWelcomMsg(); 350 | 351 | } 352 | 353 | 354 | } 355 | 356 | 357 | const handleLoggedInUser = async () => { 358 | 359 | const options = await inquirer.prompt([ 360 | { 361 | name: "Options", 362 | type: "list", 363 | choices: ["My Profile", "Edit Profile", "Update Password", "Enroll In a Course", "All Courses", "All Instructors", "Log Out"] 364 | } 365 | ]) 366 | 367 | 368 | switch (options.Options) { 369 | case "My Profile": 370 | studentCompleteProfile(); 371 | break; 372 | case "Edit Profile": 373 | await editProfile(); 374 | break; 375 | case "Update Password": 376 | await updatePassword(); 377 | break; 378 | case "Enroll In a Course": 379 | await enrollInACourse(); 380 | break; 381 | case "All Courses": 382 | availabelCoursesList(); 383 | break; 384 | case "All Instructors": 385 | availabelInstructorsList(); 386 | break; 387 | case "Log Out": 388 | handleLogOut(); 389 | break; 390 | 391 | } 392 | 393 | 394 | } 395 | 396 | 397 | console.clear(); 398 | 399 | 400 | 401 | 402 | do { 403 | 404 | if (!studentData || !studentData.loginStatus) { 405 | await handleLoggedOutUser(); 406 | } 407 | else { 408 | await handleLoggedInUser(); 409 | } 410 | 411 | } while (!quit); -------------------------------------------------------------------------------- /06_SMS/src/questions.ts: -------------------------------------------------------------------------------- 1 | export const logInOrSignUpQ = { 2 | name: "logInOrSignUp", 3 | type: "list", 4 | choices: ["LogIn", "signUp", "quit"], 5 | message: "Log in or create a new account" 6 | } 7 | -------------------------------------------------------------------------------- /06_SMS/src/types.ts: -------------------------------------------------------------------------------- 1 | // Types 2 | 3 | export type CourseInput = { 4 | course_code: string, 5 | course_name: string, 6 | des: string, 7 | instructor: string, 8 | tuition_fee: number 9 | } 10 | 11 | export type InstructorInput = { 12 | course_codes: string[], 13 | instructor_name: string, 14 | } 15 | 16 | 17 | // Dummy Data 18 | 19 | export const coursesList: CourseInput[] = [ 20 | { 21 | course_code: "01MD", 22 | course_name: "Meraverse Development", 23 | des: "Meraverse Development", 24 | instructor: "Zia Khan", 25 | tuition_fee: 3000 26 | }, 27 | { 28 | course_code: "02BC", 29 | course_name: "Blockchain", 30 | des: "Blockchian", 31 | instructor: "Zeeshan Hanif", 32 | tuition_fee: 5000 33 | 34 | }, 35 | { 36 | course_code: "03CC", 37 | course_name: "Cloud Computing", 38 | des: "Cloud Computing", 39 | instructor: "Daniyal Nagori", 40 | tuition_fee: 4000 41 | 42 | }, 43 | { 44 | course_code: "04AI", 45 | course_name: "Artificial Intelligence", 46 | des: "Artificial Intelligence", 47 | instructor: "Zia Khan", 48 | tuition_fee: 2500 49 | 50 | }, 51 | { 52 | course_code: "05IOT", 53 | course_name: "Internet of things", 54 | des: "Internet of things", 55 | instructor: "Zia Khan", 56 | tuition_fee: 2800 57 | 58 | } 59 | ] 60 | 61 | export const instructorsList: InstructorInput[] = [ 62 | { 63 | instructor_name: "Zia Khan", 64 | course_codes: ["01MD", "04AI", "05IOT"] 65 | }, 66 | { 67 | instructor_name: "Daniyal Nagori", 68 | course_codes: ["03CC"] 69 | }, 70 | { 71 | instructor_name: "Zeeshan Hanif", 72 | course_codes: ["02BC"] 73 | } 74 | ] -------------------------------------------------------------------------------- /06_SMS/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "NodeNext", 4 | "moduleResolution": "NodeNext", 5 | "target": "ES2022", 6 | "allowJs": true, 7 | "baseUrl": ".", 8 | "outDir": "lib", 9 | "rootDir": "src", 10 | "strict": true, 11 | "noImplicitAny": true, 12 | "esModuleInterop": true, 13 | "resolveJsonModule": true 14 | }, 15 | "exclude": ["node_modules"], 16 | "include": ["./src/**/*"], 17 | "compileOnSave": true 18 | } 19 | --------------------------------------------------------------------------------