├── .gitignore ├── README.md ├── diagrams ├── 10 │ ├── .gitkeep │ └── diagrams.xml ├── 11 │ ├── .gitkeep │ └── diagrams.xml ├── 12 │ ├── .gitkeep │ └── diagrams.xml ├── 13 │ ├── .gitkeep │ └── diagrams.xml ├── 14 │ ├── .gitkeep │ └── diagrams.xml ├── 15 │ ├── .gitkeep │ └── diagrams.xml ├── 16 │ ├── .gitkeep │ └── diagrams.xml ├── 17 │ ├── .gitkeep │ └── diagrams.xml ├── 18 │ ├── .gitkeep │ └── diagrams.xml ├── 01 │ ├── .gitkeep │ └── diagrams.xml ├── 02 │ ├── .gitkeep │ └── diagrams.xml ├── 03 │ ├── .gitkeep │ └── diagrams.xml ├── 04 │ ├── .gitkeep │ └── diagrams.xml ├── 05 │ ├── .gitkeep │ └── diagrams.xml ├── 06 │ ├── .gitkeep │ └── diagrams.xml ├── 07 │ ├── .gitkeep │ └── diagrams.xml ├── 08 │ ├── .gitkeep │ └── diagrams.xml └── 09 │ ├── .gitkeep │ └── diagrams.xml ├── features ├── annotations │ ├── functions.ts │ ├── objects.ts │ └── variables.ts ├── arrays.ts ├── classes.ts ├── decorators.ts ├── generics.ts ├── interfaces.ts ├── metadata.ts ├── package-lock.json ├── package.json ├── tsconfig.json ├── tuples.ts └── types.ts ├── fetchjson ├── index.js ├── index.ts ├── package-lock.json └── package.json ├── maps ├── index.html ├── package-lock.json ├── package.json └── src │ ├── Company.ts │ ├── CustomMap.ts │ ├── User.ts │ └── index.ts ├── rrts ├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ └── manifest.json ├── src │ ├── actions │ │ ├── index.ts │ │ ├── todos.ts │ │ └── types.ts │ ├── components │ │ └── App.tsx │ ├── index.tsx │ ├── react-app-env.d.ts │ └── reducers │ │ ├── index.ts │ │ └── todos.ts └── tsconfig.json ├── server ├── build │ ├── AppRouter.js │ ├── controllers │ │ ├── LoginController.js │ │ ├── RootController.js │ │ └── decorators │ │ │ ├── MetadataKeys.js │ │ │ ├── Methods.js │ │ │ ├── bodyValidator.js │ │ │ ├── controller.js │ │ │ ├── index.js │ │ │ ├── routes.js │ │ │ └── use.js │ ├── index.js │ └── routes │ │ └── loginRoutes.js ├── package-lock.json ├── package.json ├── src │ ├── AppRouter.ts │ ├── controllers │ │ ├── LoginController.ts │ │ ├── RootController.ts │ │ └── decorators │ │ │ ├── MetadataKeys.ts │ │ │ ├── Methods.ts │ │ │ ├── bodyValidator.ts │ │ │ ├── controller.ts │ │ │ ├── index.ts │ │ │ ├── routes.ts │ │ │ └── use.ts │ └── index.ts └── tsconfig.json ├── sort ├── build │ ├── CharactersCollection.js │ ├── LinkedList.js │ ├── NumbersCollection.js │ ├── Sorter.js │ └── index.js ├── package-lock.json ├── package.json ├── src │ ├── CharactersCollection.ts │ ├── LinkedList.ts │ ├── NumbersCollection.ts │ ├── Sorter.ts │ └── index.ts └── tsconfig.json ├── stats ├── build │ ├── CsvFileReader.js │ ├── MatchData.js │ ├── MatchReader.js │ ├── MatchResult.js │ ├── Summary.js │ ├── analyzers │ │ └── WinsAnalysis.js │ ├── index.js │ ├── inheritance │ │ ├── CsvFileReader.js │ │ └── MatchReader.js │ ├── reportTargets │ │ ├── ConsoleReport.js │ │ └── HtmlReport.js │ └── utils.js ├── football.csv ├── package-lock.json ├── package.json ├── report.html ├── src │ ├── CsvFileReader.ts │ ├── MatchData.ts │ ├── MatchReader.ts │ ├── MatchResult.ts │ ├── Summary.ts │ ├── analyzers │ │ └── WinsAnalysis.ts │ ├── index.ts │ ├── inheritance │ │ ├── CsvFileReader.ts │ │ └── MatchReader.ts │ ├── reportTargets │ │ ├── ConsoleReport.ts │ │ └── HtmlReport.ts │ └── utils.ts └── tsconfig.json └── web ├── db.json ├── index.html ├── package-lock.json ├── package.json ├── src ├── index.ts ├── models │ ├── ApiSync.ts │ ├── Attributes.ts │ ├── Collection.ts │ ├── Eventing.ts │ ├── Model.ts │ └── User.ts └── views │ ├── CollectionView.ts │ ├── UserEdit.ts │ ├── UserForm.ts │ ├── UserList.ts │ ├── UserShow.ts │ └── View.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | .DS_Store 3 | .cache 4 | node_modules 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Typescript Casts 2 | 3 | Companion repo to a course hosted on Udemy.com 4 | -------------------------------------------------------------------------------- /diagrams/01/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/typescriptcasts/91fc3e29ce8214766f90ee795fd5685975495932/diagrams/01/.gitkeep -------------------------------------------------------------------------------- /diagrams/01/diagrams.xml: -------------------------------------------------------------------------------- 1 | rZNBc4IwEIV/DUccJIp6bKna6Ux70Y5tbxmykkwDy4Qo0F/fIEuF8dLO9ALJty+7w8vDY3FWbw0v5DMK0F4YiNpjD14YTtlq6V4taToSzecdSI0SJLqCnfoCggHRkxJQjoQWUVtVjGGCeQ6JHTFuDFZj2RH1eGrBU7gBu4TrW3pQwsqOMhYE18IjqFTS6Fm0pCMZ79UkLSUXWA0QW3ssNoi2W2V1DLp1rzfGX+7f5ZP/cbfKXvzwFd+qxve7Zpu/HPn5BgO5/d/WYdf6zPWJDNvhZDI5SG7bo6V77JsCysSowo3ekBO26f01eMoFtCMCj91XUlnYFTxpq5VLlGPSZtrtpm55xNxSRMJ5u1dax6jRXHoxmIo5LBwvrcFPGFRW0YLxqO9A039rC+nOYCzUg1SQTVvADKxpnISqsyXdOGV+0Ye5GiQoIiYH4ZkygpxSm/70vl6MW9Dd9NtrhC61wZ/I1t8=5Vddb9owFP01aE+VEjufjw1tKZWQqsFWbW8mviQWThw55mu/fjaYj5BIK1MZlfYS+Z57beNz7iFOD/eL9UCSKh8JCryHHLru4YceQkEc66cBNjsAo2gHZJLRHeQegTH7BRZ0LLpgFOpGoRKCK1Y1wVSUJaSqgREpxapZNhO8uWtFMmgB45TwNvrGqMrtKbDjHBPPwLLcbu0FkZ1SkH21La1zQsXqBMKPPdyXQqjdqFj3gRvy9sQMnpPXl3w9GaK48L4Nhz/Ch+But9jTJVMOZ5BQqr9eOvhaPL3VznCe1Yn8/sp+TkYjO8VZEr6whE02FdSpZJWyp1abPZdSLEoKZjmnh5NVzhSMK5Ka7Eo3j8ZyVXAduXo4Y5z3BRdyOxeDS30INV4rKeZwkomDEJPAzBClsg2EnH1sd38vBbZuCVLB+qQDLCUDEAUoudElNuvtG8H2NwptvDp2i+tZLD9plMBixDZodlj6qIEeWBkukMRtSWKfDS308VST8CaxpSjhTAULEc6yUoepZhI0nhiymHbMvU0UjFKzTafCzR44kQzrn5lcSyXfc5sqxW2VukRC1xIJtUR6IUtyBd9QAtEs7fJNkEYwnd3KN3702XyD275ByX/umxCdqXRr33gtke7NjUC/c4xMm1pB8bH28SGiXpd9IjTFwc1eO2HwDvuE/9I+fod9zoTQF6DKDNOF5JtEknQO6s+KHOVzOzpfCkUUE8Y/d7FzRStE2G8yHvgtxlEH4QcVPpzxsMX4G3yRxgiZYGW2vSkbASooqQlyk1rlgsP2vryQtRlwILLclZOpWKhtJas//x+f652ZDV3NbH7ckB4HXWZDbe39y6XX4fGLYJs7+a7Cj78B7VdRb9owEP41EU+bEpsEeIV2ZZO6TYOpfZuMcyRuHTtyHCD8+tmJIYQgbe3E9tC9mPN3Zzv+vrtL8PAs290pkqf3MgbuIT/eefjGQyiaTMxogaoBMBo3QKJY3EBBCyzYHhzoO7RkMRSdQC0l1yzvglQKAVR3MKKU3HbD1pJ3T81JAj1gQQnvow8s1qm7Bfb91jEHlqTu6GE0dksycoh2oUVKYrk9gfCth2dKSt1Y2W4G3JJ3IOajoNV29elbef8U7qPH++XX6fRds9mHlyw53kGB0K/e+sfIj1CSPmmePcyLz3iShUu3xN8QXjrClikYYLmwQ5Vbe1EVGjLHga4OzCpZihjs5r6Hp9uUaVjkhFrv1qSSwVKdcTMLjLlmnM8kl6pei+MQxvHQ4IVW8hlOPGO0wlFkV0ihXToh/zB3p/8uIS5uA0rD7iQfHEF3IDPQqjIhzouwI8RlO/JH78MG2bbZE4xcVHqSOJHDiEvY5Lh5q4kxnCwvkCjoSdSTwmRmbk1aKl5NFaHPoH+tSStg0OU7sMpci+Kh36U4CP0ewcML/Aaj8EoEox7B3wvTspA/0E0BECGkJppJUQzq/lVjhFd765WlqvtXDH9YImcCnJcMgfGaXiqZiI5htb6mZOGZZJNRTzKMLmiGryUZ7kk2B55bzUo7UKJpan7BvECUBTwUcVsRzBiJNeJSMZHY9xpsgMs8s5S5IPNEx7gDtlIt8kZEvlCXf1fkYU/kL4LbJyZUsw38l/U1sqIh/seyhj1ZbyQUYqDt/ZXcsLjpufYSOai1VBkRtO60uWYZ29ed+M3oNbleGZpp+/Va+07+A+Dbnw==7Vhdb5w4FP01I+0+dAQYGPrYkDSrfuxmm0hN+1I5cGdwY2xkzMD019cGM+ABpZPdTBtpl0gZfK59be6559qwQHHeXApcZO95CnThOWmzQOcLz3uJPPVfA7sO8NGqAzaCpB3kDsA1+QYGdAxakRRKq6PknEpS2GDCGYNEWhgWgtd2tzWn9qwF3sAEuE4wnaIfSSqzDkXIcQbDH0A2mZnaDyMzJMd9b9O1zHDK6xGELhYoFpzL7i5vYqA6eH1gvrjZTXzjBW8/X376MyPb8Ft6/6Jz9voxQ/bPIIDJp3UdmEeTuz5gkKr4mSYXMuMbzjC9GNAzwSuWgvbqqNbQ5x3nhQJdBX4FKXcmGXAluYIymVNjhYbIWz18GZjWp5HlvDGe28bONNacSePQ81X7yJCY0JW8Egk80M9kucRiAw/587t+Okij/DIBvwSegxQ71UEAxZJs7STEJpc3+34DXerGMPYI9syqt5hWZqabXQFlIkghFR4rMauf397gLd6DNVFprZ5UddRLYoxLtVLOyt8nqWATXWdEwnWB2zjWqljYpB4StCaUxpxy0fpCaQBRqvFSCn4PI0vk3aEw7D2Y2Y9NedNvC0JC8yAjxhr0wjf1zI1Mux6qg7cyWDYqDG4/8MlZXP2vwbG2fqjB8Flp0P+RBvOCUBCnFReGaJ3MiStMIrhb/ypxITc4TlzRqbTlupPA/0RxuSNpDUL7JeJ6ctGYoVecMDlkQOTaGeCvnCUaXyvbYyd24+SA6/2q/jn94UScVxQTpiB9jvSc8c74H9z8fHTk5ncyfUYTgiZEdDHrD+862vuDuGYmxWW2pwlTsmHqPlGBUzXX4kiNKrTLvNnoN51lzpP7qliqFw+pUgJEubzTrxsgPhLWuj8ThlJnyui6vWYrbnvZFq8zOU6UHA5CnSnx9Z8y5WotN9B0cY/1IiCpRKkU+QHK0XL+VbU4PmMO9YxmMgb5Mxmjcu1EKfNyqmn9Dug501L/81IHsyTTGTAmxl2Z9lx29NNRWMvj+Ysey194cNr1Juy57hx74an2Y2fCXial/hbwSjv2Xtd1vUwFrpeEPwc6rRLwvKh1kc1tOFPLgxNx+/nv6vbrlbO9rZxz/y9XxO/ffdgXl4Has66g6nNHo8qYhFJHwuzA47031mvE2sp4Ow1g/SRa1bXgUv+OT9UHeSHbemkxbFVlxhkclHADTbJEh58kmL4yhpykaXsmnDsA2EeEufTod3TvZPoODvQ9c+CeE3gUPDoJVHP41tUd0IYvhujiOw==tVRdj5swEPw1PFIRO0fJY6Dp3bWqqh5Vq+al8mED1hnMGSck/fVdYPlqrtKlUl+MPbveNTNjOzQqTreGVfknzYVyiMdPDn3nEOJvNjC2wLkHKAl6IDOS99BqAmL5SyDoIXqQXNSLRKu1srJagokuS5HYBcaM0c0yLdVq2bVimbgA4oSpS/S75DbHv6CeNwXuhMxybL32A9xSsCEbU+uccd3MILpzaGS0tv2sOEVCteQNxOz3zU/2LXj6cb+Pbz66kfuQbdy+2Ptrtoz/YERp/7l0ZW++3Llil+3ut/HDZ/JMVhS3eEemDkiYPVeiToysrGJl9kabDEpWip0d4ivoHj6algt7Rob950NLQJjq0rp1p/8WEqhXgYXCKQ6zrP+SxX5i9KHkoj2kB+Eml1bEFUvaaAOWBCy3hYLVCrugyWibnkqlIq206WpRzkSQJoDX1ugnMYv4SSAe06ECdn8tsZh3FMaK08xXSPSt0IWwBhjyMLqmSCzeGrLGdTN5cD34Kp/ZbzXcG4a+z8bak7QwQXWvUJpcKD0IKl+jJ1R9Wc+vo1+6qw3DB3ZkIwL3uqPNDN3g8PKvXgB67VLwpZClLsUfqiPElMxKWCagJDSjYdtVwjuwxUAhOW/bvOiwpQdnJmtFDv+bSzZLl1D/0iXjQzV3ydvrTQLL6aXqYrP3nu5+Aw==5VZNc5swEP01PibDRyD2MXHTNJ1+TOu26a0jowVUC4kKEXB+fXdBxhA607qXHHIB7dvVit33FliE66K9NazM32sOchF4vF2ErxZBEK9WeCVg3wNhsOyBzAjeQ/4R2IhHcKDn0FpwqCaBVmtpRTkFE60UJHaCMWN0Mw1LtZyeWrIMZsAmYXKO3gtuc1dF6HlHxxsQWe6OvoiXbkvBDtEutMoZ180ICm8W4dpobftV0a5BUvMOjSn8dnV2pbJ33wuzCfQnDj/UWZ/s9SlbhhoMKPvfqT/f/NyFXy948iW+M8nH6PFbVLst3gOTtWvYvRFWqAzBL/sSqsSI0lKWakFFxxIf4FrgIqOFzYEawwo4uPD8wYt3VpS4UNuKboxyNEP+t+yBDfkbgd3GVJpS0UG/aurrNbTWMNKfTuoCy2dWaHV0O2bs/sC30bXiQCV76G5yYWFTsoS8DQocsdwWEi0fl6lW1knWj8kWUq611KbLFXIGyzRBvLJG72DkiZMlbNPh/L8y4xh8AGOhHQnTMXULWLY1ewxx3ihyzLix81fObo4ivrh0WD7S72Efc3OTDamP0sCFU8cJSvFnSpnoI+/IVRovkKY0yYFHRHk5jgwua9MNOSd2M7AUDC0ktUWuAm9Lpfdi2tLMA0VrunzotrwMkgfyno3kYEby3TD8W6hs9/buqBJqRxSlT98TrA/tJ1yKHVFK85saAYqoroR1878FzELQXtdUdC4kDBY2uxcMxp6/FAGE/nMLIJwJYFMXBXOZxxRgiXba52n/lFbwpNkOYlJkCs0Eu4mDHl5TwwR+sq+coxCc0zF/JHZK/YjbIDrY7iH/9bN5Mm2X3uV5NH09x3Pi/CiaExecThyax3+Mzjf6UwtvfgM=7VbLjtowFP2WLiJWVIkdaFhCeLQaoWmVSlVnU7m2k3ia2MFxJtCv7zWYIZmw6FRlUakLgn3uw/E5xxgPx+V+o0mVbxXjhYd8tvfw0kNoOpvB0wKHE4BRdAIyLdgJCi5AIn5yB/oObQTjdS/RKFUYUfVBqqTk1PQworVq+2mpKvqrViTjAyChpBiiXwQzudsF9v1L4D0XWe6WDqeRKynJOdul1jlhqu1AeOXhWCtlTqNyH/PCkncmZpEl28O3+SZY7vxGFWqZ04fxqdn6NSXPe9Bcmj9u/fD1LqgY/fiIkk88ULs75N+7Ev+JFI0jTFalLZK1IcfycWYlO1S8plpUxk7qsQSbOFLM4Uy1Vo1k3K7me3jR5sLwpCLURlvwFmC5KQuYBTBMlTTOLRjZuSiKGDaij70wIzxKKeC10eoH70SmNOLfU4j8JimOvCeuDd93POFI2nBVcqMPkOKi4dm6zvEIuSPQXvwTvnM5ecc6wbmQOM9mz70vssDAKfMKlYKBSp+7glBVVqLgeqAI7Nj0ae/TKZXkL7h3EClEJmFKgVxojBeWPwHHau4CpWDMLnNV574TOlIDlW7uXhLfTMVw0lMxmE2GKvpXVES3EhENRLwHquE4idJ+1dw01Zt/QMLghYToZhJG6G1fRDzBAxExmtxGxLqN2tk63D0KOc8RXsdLsrjye/khte+nmpG2KioJjy2h94ldXTJ7A3J7Rgl8Rqt5HK+SZARjDncbHNjYhphNG9UNU6Pj9Wgfue2WauD5vyW6p3raM0QYTIeGmEV/xRAwvdztx1jnHxJe/QI=tZRRb5swEMc/DY+LiJ2m6WNLu0yTKk2K1D279gWsGV9kDE766WfKUXDZwyJtL8j3u+OM//8zGS/q896JU/WMCkzGcnXO+GPG2PbuLj57cBkAZ7sBlE6rAa0ncNBvQDAn2moFTVLoEY3XpxRKtBakT5hwDkNadkST7noSJSzAQQqzpD+18hWdguf5lPgGuqxo6812R6/UYqym0qYSCsMM8aeMFw7RD6v6XIDpxRuFubg8f+tef3R+H0Lovne+efkyNPt6zSsfZ3Bg/b9tzYbWnTAtCSbjBKw63bTCNL5VGlcSaxLAX0ZZHbZWQd85z/hDqLSHw0nIPhviHEVW+drEaB2XR7SeJoOzPtbGFGjQvffiSsDuKCNvvMNfMMts5Q5ejzHzlwKQUB04D+eZ/yTIHrAG7y6xhLIbTt7SdLMxDtOsbMZRrmZjsh6hoPksP3pPFsQFuXCFI3zhyMuhiJ5E9ojBGhRq4UY8rU8lT6W0aOGT7oSE0aWNoYzCQuQPvXY6Xp97StRaqX6bP3qcTsHC5j6mj+T/zcFbtrpJPcyXHnJ2s/SQXW9hDKf7/p6b/TX5028=5Zddb9owFIZ/DeKqUxKTEC4LpbRs07qiatulFx8Sq44NzgkJ/fWzwRSydBKdxJjEFT6vj7/e51gxHTLK64mmi+yzYiA6gcfqDrnpBIHv+7H5scp6q4RBbyukmjOXtBdm/AWc6Dm15AyKRiIqJZAvmmKipIQEGxrVWlXNtLkSzVUXNIWWMEuoaKvfOMNsqxLiefuOO+Bp5pbuRbEbktNdtkstMspUdSCRcYeMtFK4beX1CIR1b2fMw/RrtRwjGaqpIup5elfF5dV2stv3DHk9gwaJfz21mDwMVLX+fvXiiX7i33/8sZy6Id6KitIZdi8LpJuBDxoQOWjTHNcIsuBKOidwvfNXq1IysEt4HTKsMo4wW9DE9lamooyWYS5M5JvmXEl0JUICG3MhRkoovZmLMArxPDF6gVo9w0FPlMTwc256jnTCObYCjVAfFIJzZgIqB9Rrk1Lvyto54crcj/vbuNoXTThwOdlBvfSdRl2dpq9T71GYhqPxDjJ+i8yXBRoCVLQYmDNi0+imgVJJ+M1tJ1HBU2nCxNhpQJOhdYyb23PtOnLOmF3mTbJN9i24NnabJKfiFoXBh7BBrh+2wJEgbIMLTgUuaIF7LKU9/P462XvkFXQFl3Kdgig+83UiLSpPBVjvuUyFbSxLheZDZbdodniI6zIQkd7gzIh6f0CElbIErMfF5glgrxA3DCRSvKBvUo94ZyYUtgjNAC2hDPINKQuqO1OCauMoM8Enu6vupRAK/X9IKI7i23zZH8xvsjLDUT0Qj+yNV8M1sxy6iXnZd3eIFvZp+18waXl9LKbjX3JedDImJtw//zd9B/+iyPgX1VZNb5wwEP01HFsB3hD2mP3o7qGpFNGq7alyYQA3BiNjAvTX116GBcIqadpsq71YnufxjP3eDNgi66zZSVqktyICbrl21FhkY7mut1zq0QBtBxDX74BEsqiDnAEI2E9A0Ea0YhGUE0clBFesmIKhyHMI1QSjUop66hYLPs1a0ARmQBBSPkc/s0ileAti28PCHliSYuqF5+OWjPbe6FqmNBL1CCJbi6ylEKqbZc0auCGvJyaI72N355A2t6s8WNyt2M2HN12wdy/ZcryDhFy9bmi3C/1AeYWE7fUVjUZ62IHS4x54gQSotqdViiqPwES2LbKqU6YgKGhoVmtdRxpLVca15ehpzDhfCy7kYS+JKPhxqPFSSXEPoxUv9OF7bHaIXAWYzentrrZckxBPDVJB80jnZzhyjsLpigeRgZKt3odRFgvUGqvdWaJdj2qnL+10VDZXiFEs1+QYelBET1CUFwjkzaiHSBc4mkKqVCQip3w7oKupOIPPeyEKJPQHKNUio7TSak8Eg4apL6P5VxPq7RVamwYjH4wWjdMSmcP+gUD6wqKSITzhd40fEyoTeCqef1pwCZwq9jA93Kurdz1rr481UwrkXzbUf2oHcqIdHO9EO3jnagd/Rqi10DTCN/P3uRRaPfIbtLr/ktbljNZPEWTmyHeW69HMENWNNxrbsDKsypKJXBsrQWVUXgbxj+v5+Nl+7vN+NuL7ZCPmN0yah5Br30JZmteNax+IRkUukWfino9nbQ5PsMPa6CFLtr8A -------------------------------------------------------------------------------- /diagrams/02/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/typescriptcasts/91fc3e29ce8214766f90ee795fd5685975495932/diagrams/02/.gitkeep -------------------------------------------------------------------------------- /diagrams/02/diagrams.xml: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /diagrams/03/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/typescriptcasts/91fc3e29ce8214766f90ee795fd5685975495932/diagrams/03/.gitkeep -------------------------------------------------------------------------------- /diagrams/04/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /diagrams/05/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /diagrams/06/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /diagrams/07/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /diagrams/07/diagrams.xml: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /diagrams/08/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /diagrams/08/diagrams.xml: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /diagrams/09/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /diagrams/09/diagrams.xml: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /diagrams/10/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /diagrams/10/diagrams.xml: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /diagrams/11/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /diagrams/11/diagrams.xml: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /diagrams/12/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /diagrams/13/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /diagrams/14/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /diagrams/14/diagrams.xml: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /diagrams/15/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /diagrams/16/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /diagrams/16/diagrams.xml: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /diagrams/17/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /diagrams/18/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /diagrams/18/diagrams.xml: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /features/annotations/functions.ts: -------------------------------------------------------------------------------- 1 | const add = (a: number, b: number) => { 2 | return a + b; 3 | }; 4 | 5 | const subtract = (a: number, b: number): number => { 6 | return a - b; 7 | }; 8 | 9 | function divide(a: number, b: number): number { 10 | return a / b; 11 | } 12 | 13 | const multiply = function(a: number, b: number): number { 14 | return a * b; 15 | }; 16 | 17 | const logger = (message: string): void => { 18 | console.log(message); 19 | }; 20 | 21 | const throwError = (message: string): void => { 22 | if (!message) { 23 | throw new Error(message); 24 | } 25 | }; 26 | 27 | const todaysWeather = { 28 | date: new Date(), 29 | weather: 'sunny' 30 | }; 31 | 32 | const logWeather = ({ 33 | date, 34 | weather 35 | }: { 36 | date: Date; 37 | weather: string; 38 | }): void => { 39 | console.log(date); 40 | console.log(weather); 41 | }; 42 | 43 | logWeather(todaysWeather); 44 | -------------------------------------------------------------------------------- /features/annotations/objects.ts: -------------------------------------------------------------------------------- 1 | const profile = { 2 | name: 'alex', 3 | age: 20, 4 | coords: { 5 | lat: 0, 6 | lng: 15 7 | }, 8 | setAge(age: number): void { 9 | this.age = age; 10 | } 11 | }; 12 | 13 | const { age, name }: { age: number; name: string } = profile; 14 | const { 15 | coords: { lat, lng } 16 | }: { coords: { lat: number; lng: number } } = profile; 17 | -------------------------------------------------------------------------------- /features/annotations/variables.ts: -------------------------------------------------------------------------------- 1 | let apples = 5; 2 | let speed: string = 'fast'; 3 | let hasName: boolean = true; 4 | 5 | let nothingMuch: null = null; 6 | let nothing: undefined = undefined; 7 | 8 | // built in objects 9 | let now: Date = new Date(); 10 | 11 | // Array 12 | let colors: string[] = ['red', 'green', 'blue']; 13 | let myNumbers: number[] = [1, 2, 3]; 14 | let truths: boolean[] = [true, true, false]; 15 | 16 | // Classes 17 | class Car {} 18 | let car: Car = new Car(); 19 | 20 | // Object literal 21 | let point: { x: number; y: number } = { 22 | x: 10, 23 | y: 20 24 | }; 25 | 26 | // Function 27 | const logNumber: (i: number) => void = (i: number) => { 28 | console.log(i); 29 | }; 30 | 31 | // When to use annotations 32 | // 1) Function that returns the 'any' type 33 | const json = '{"x": 10, "y": 20}'; 34 | const coordinates: { x: number; y: number } = JSON.parse(json); 35 | console.log(coordinates); // {x: 10, y: 20}; 36 | 37 | // 2) When we declare a variable on one line 38 | // and initalizate it later 39 | let words = ['red', 'green', 'blue']; 40 | let foundWord: boolean; 41 | 42 | for (let i = 0; i < words.length; i++) { 43 | if (words[i] === 'green') { 44 | foundWord = true; 45 | } 46 | } 47 | 48 | // 3) Variable whose type cannot be inferred correctly 49 | let numbers = [-10, -1, 12]; 50 | let numberAboveZero: boolean | number = false; 51 | 52 | for (let i = 0; i < numbers.length; i++) { 53 | if (numbers[i] > 0) { 54 | numberAboveZero = numbers[i]; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /features/arrays.ts: -------------------------------------------------------------------------------- 1 | const carMakers = ['ford', 'toyota', 'chevy']; 2 | const dates = [new Date(), new Date()]; 3 | 4 | const carsByMake: string[][] = []; 5 | 6 | // Help with inference when extracting values 7 | const car = carMakers[0]; 8 | const myCar = carMakers.pop(); 9 | 10 | // Prevent incompatible values 11 | carMakers.push(100); 12 | 13 | // Help with 'map' 14 | carMakers.map( 15 | (car: string): string => { 16 | return car.toUpperCase(); 17 | } 18 | ); 19 | 20 | // Flexible types 21 | const importantDates: (Date | string)[] = []; 22 | importantDates.push('2030-10-10'); 23 | importantDates.push(new Date()); 24 | -------------------------------------------------------------------------------- /features/classes.ts: -------------------------------------------------------------------------------- 1 | class Vehicle { 2 | constructor(public color: string) {} 3 | 4 | protected honk(): void { 5 | console.log('beep'); 6 | } 7 | } 8 | 9 | const vehicle = new Vehicle('orange'); 10 | console.log(vehicle.color); 11 | 12 | class Car extends Vehicle { 13 | constructor(public wheels: number, color: string) { 14 | super(color); 15 | } 16 | 17 | private drive(): void { 18 | console.log('vroom'); 19 | } 20 | 21 | startDrivingProcess(): void { 22 | this.drive(); 23 | this.honk(); 24 | } 25 | } 26 | 27 | const car = new Car(4, 'red'); 28 | car.startDrivingProcess(); 29 | -------------------------------------------------------------------------------- /features/decorators.ts: -------------------------------------------------------------------------------- 1 | @classDecorator 2 | class Boat { 3 | @testDecorator 4 | color: string = 'red'; 5 | 6 | @testDecorator 7 | get formattedColor(): string { 8 | return `This boats color is ${this.color}`; 9 | } 10 | 11 | @logError('Something bad!') 12 | pilot( 13 | @parameterDecorator speed: string, 14 | @parameterDecorator generateWake: boolean 15 | ): void { 16 | if (speed === 'fast') { 17 | console.log('swish'); 18 | } else { 19 | console.log('nothing'); 20 | } 21 | } 22 | } 23 | 24 | function classDecorator(constructor: typeof Boat) { 25 | console.log(constructor); 26 | } 27 | 28 | function parameterDecorator(target: any, key: string, index: number) { 29 | console.log(key, index); 30 | } 31 | 32 | function testDecorator(target: any, key: string) { 33 | console.log(key); 34 | } 35 | 36 | function logError(errorMessage: string) { 37 | return function(target: any, key: string, desc: PropertyDescriptor): void { 38 | const method = desc.value; 39 | 40 | desc.value = function() { 41 | try { 42 | method(); 43 | } catch (e) { 44 | console.log(errorMessage); 45 | } 46 | }; 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /features/generics.ts: -------------------------------------------------------------------------------- 1 | class ArrayOfNumbers { 2 | constructor(public collection: number[]) {} 3 | 4 | get(index: number): number { 5 | return this.collection[index]; 6 | } 7 | } 8 | 9 | class ArrayOfStrings { 10 | constructor(public collection: string[]) {} 11 | 12 | get(index: number): string { 13 | return this.collection[index]; 14 | } 15 | } 16 | 17 | class ArrayOfAnything { 18 | constructor(public collection: T[]) {} 19 | 20 | get(index: number): T { 21 | return this.collection[index]; 22 | } 23 | } 24 | 25 | const arr = new ArrayOfAnything(['a', 'b', 'c']); 26 | 27 | // Example of generics with functions 28 | 29 | function printStrings(arr: string[]): void { 30 | for (let i = 0; i < arr.length; i++) { 31 | console.log(arr[i]); 32 | } 33 | } 34 | 35 | function printNumbers(arr: number[]): void { 36 | for (let i = 0; i < arr.length; i++) { 37 | console.log(arr[i]); 38 | } 39 | } 40 | 41 | function printAnything(arr: T[]): void { 42 | for (let i = 0; i < arr.length; i++) { 43 | console.log(arr[i]); 44 | } 45 | } 46 | 47 | printAnything(['a', 'b', 'c']); 48 | 49 | // Genric Constraints 50 | 51 | class Car { 52 | print() { 53 | console.log('I am a car'); 54 | } 55 | } 56 | 57 | class House { 58 | print() { 59 | console.log('I am a house'); 60 | } 61 | } 62 | 63 | interface Printable { 64 | print(): void; 65 | } 66 | 67 | function printHousesOrCars(arr: T[]): void { 68 | for (let i = 0; i < arr.length; i++) { 69 | arr[i].print(); 70 | } 71 | } 72 | 73 | printHousesOrCars([new House(), new House()]); 74 | printHousesOrCars([new Car(), new Car()]); 75 | -------------------------------------------------------------------------------- /features/interfaces.ts: -------------------------------------------------------------------------------- 1 | interface Reportable { 2 | summary(): string; 3 | } 4 | 5 | const oldCivic = { 6 | name: 'civic', 7 | year: new Date(), 8 | broken: true, 9 | summary(): string { 10 | return `Name: ${this.name}`; 11 | } 12 | }; 13 | 14 | const drink = { 15 | color: 'brown', 16 | carbonated: true, 17 | sugar: 40, 18 | summary(): string { 19 | return `My drink has ${this.sugar} grams of sugar`; 20 | } 21 | }; 22 | 23 | const printSummary = (item: Reportable): void => { 24 | console.log(item.summary()); 25 | }; 26 | 27 | printSummary(oldCivic); 28 | printSummary(drink); 29 | -------------------------------------------------------------------------------- /features/metadata.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | 3 | @controller 4 | class Plane { 5 | color: string = 'red'; 6 | 7 | @get('/login') 8 | fly(): void { 9 | console.log('vrrrrrrr'); 10 | } 11 | } 12 | 13 | function get(path: string) { 14 | return function(target: Plane, key: string) { 15 | Reflect.defineMetadata('path', path, target, key); 16 | }; 17 | } 18 | 19 | function controller(target: typeof Plane) { 20 | for (let key in target.prototype) { 21 | const path = Reflect.getMetadata('path', target.prototype, key); 22 | const middleware = Reflect.getMetadata('middleware', target.prototype, key); 23 | 24 | router.get(path, middleware, target.prototype[key]); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /features/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "features", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "reflect-metadata": { 8 | "version": "0.1.13", 9 | "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", 10 | "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /features/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "features", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "reflect-metadata": "^0.1.13" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /features/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, 5 | "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, 6 | // "lib": [], /* Specify library files to be included in the compilation. */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | // "outDir": "./", /* Redirect output structure to the directory. */ 15 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 16 | // "composite": true, /* Enable project compilation */ 17 | // "incremental": true, /* Enable incremental compilation */ 18 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 19 | // "removeComments": true, /* Do not emit comments to output. */ 20 | // "noEmit": true, /* Do not emit outputs. */ 21 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 22 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 23 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 24 | 25 | /* Strict Type-Checking Options */ 26 | "strict": true /* Enable all strict type-checking options. */, 27 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 28 | // "strictNullChecks": true, /* Enable strict null checks. */ 29 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 30 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 31 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 32 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 33 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 34 | 35 | /* Additional Checks */ 36 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 37 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 38 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 39 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 40 | 41 | /* Module Resolution Options */ 42 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 43 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 44 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 45 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 46 | // "typeRoots": [], /* List of folders to include type definitions from. */ 47 | // "types": [], /* Type declaration files to be included in compilation. */ 48 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 49 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, 50 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 51 | 52 | /* Source Map Options */ 53 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 54 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 55 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 56 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 57 | 58 | /* Experimental Options */ 59 | "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, 60 | "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */ 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /features/tuples.ts: -------------------------------------------------------------------------------- 1 | const drink = { 2 | color: 'brown', 3 | carbonated: true, 4 | sugar: 40 5 | }; 6 | 7 | // Type alias 8 | type Drink = [string, boolean, number]; 9 | 10 | const pepsi: Drink = ['brown', true, 40]; 11 | const sprite: Drink = ['clear', true, 40]; 12 | const tea: Drink = ['brown', false, 0]; 13 | 14 | const carSpecs: [number, number] = [400, 3354]; 15 | 16 | const carStats = { 17 | horsepower: 400, 18 | weight: 3354 19 | }; 20 | -------------------------------------------------------------------------------- /features/types.ts: -------------------------------------------------------------------------------- 1 | const today = new Date(); 2 | today.getMonth(); 3 | 4 | const person = { 5 | age: 20 6 | }; 7 | 8 | class Color {} 9 | const red = new Color(); 10 | -------------------------------------------------------------------------------- /fetchjson/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | var axios_1 = require("axios"); 4 | var url = 'https://jsonplaceholder.typicode.com/todos/1'; 5 | axios_1["default"].get(url).then(function (response) { 6 | console.log(response.data); 7 | }); 8 | -------------------------------------------------------------------------------- /fetchjson/index.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const url = 'https://jsonplaceholder.typicode.com/todos/1'; 4 | 5 | interface Todo { 6 | id: number; 7 | title: string; 8 | completed: boolean; 9 | } 10 | 11 | axios.get(url).then(response => { 12 | const todo = response.data as Todo; 13 | 14 | const id = todo.id; 15 | const title = todo.title; 16 | const completed = todo.completed; 17 | 18 | logTodo(id, title, completed); 19 | }); 20 | 21 | const logTodo = (id: number, title: string, completed: boolean) => { 22 | console.log(` 23 | The Todo with ID: ${id} 24 | Has a title of: ${title} 25 | Is it finished? ${completed} 26 | `); 27 | }; 28 | -------------------------------------------------------------------------------- /fetchjson/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fetchjson", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "axios": { 8 | "version": "0.18.0", 9 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", 10 | "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", 11 | "requires": { 12 | "follow-redirects": "^1.3.0", 13 | "is-buffer": "^1.1.5" 14 | } 15 | }, 16 | "debug": { 17 | "version": "3.2.6", 18 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 19 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 20 | "requires": { 21 | "ms": "^2.1.1" 22 | } 23 | }, 24 | "follow-redirects": { 25 | "version": "1.7.0", 26 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", 27 | "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", 28 | "requires": { 29 | "debug": "^3.2.6" 30 | } 31 | }, 32 | "is-buffer": { 33 | "version": "1.1.6", 34 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 35 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 36 | }, 37 | "ms": { 38 | "version": "2.1.1", 39 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 40 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /fetchjson/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fetchjson", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "axios": "^0.18.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /maps/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /maps/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "@types/faker": { 6 | "version": "4.1.5", 7 | "resolved": "https://registry.npmjs.org/@types/faker/-/faker-4.1.5.tgz", 8 | "integrity": "sha512-YSDqoBEWYGdNk53xSkkb6REaUaVSlIjxIAGjj/nbLzlZOit7kUU+nA2zC2qQkIVO4MQ+3zl4Sz7aw+kbpHHHUQ==" 9 | }, 10 | "@types/googlemaps": { 11 | "version": "3.30.20", 12 | "resolved": "https://registry.npmjs.org/@types/googlemaps/-/googlemaps-3.30.20.tgz", 13 | "integrity": "sha512-cTTLBYt6DNKMi359Tg2QndRUbgxvsOcSlFWBDL3OWI/VP7/od4TD6vrmO8ADYdr5elYF/az0frKXi9bddKeMgA==" 14 | }, 15 | "faker": { 16 | "version": "4.1.0", 17 | "resolved": "https://registry.npmjs.org/faker/-/faker-4.1.0.tgz", 18 | "integrity": "sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8=" 19 | }, 20 | "typescript": { 21 | "version": "3.4.5", 22 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.5.tgz", 23 | "integrity": "sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==", 24 | "dev": true 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /maps/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "typescript": "^3.4.5" 4 | }, 5 | "dependencies": { 6 | "@types/faker": "^4.1.5", 7 | "@types/googlemaps": "^3.30.20", 8 | "faker": "^4.1.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /maps/src/Company.ts: -------------------------------------------------------------------------------- 1 | import faker from 'faker'; 2 | import { Mappable } from './CustomMap'; 3 | 4 | export class Company implements Mappable { 5 | companyName: string; 6 | catchPhrase: string; 7 | location: { 8 | lat: number; 9 | lng: number; 10 | }; 11 | color: string = 'red'; 12 | 13 | constructor() { 14 | this.companyName = faker.company.companyName(); 15 | this.catchPhrase = faker.company.catchPhrase(); 16 | this.location = { 17 | lat: parseFloat(faker.address.latitude()), 18 | lng: parseFloat(faker.address.longitude()) 19 | }; 20 | } 21 | 22 | markerContent(): string { 23 | return ` 24 |
25 |

Company Name: ${this.companyName}

26 |

Catchphrase: ${this.catchPhrase}

27 |
28 | `; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /maps/src/CustomMap.ts: -------------------------------------------------------------------------------- 1 | // Instructions to every other class 2 | // on how they can be an argument to 'addMarker' 3 | export interface Mappable { 4 | location: { 5 | lat: number; 6 | lng: number; 7 | }; 8 | markerContent(): string; 9 | color: string; 10 | } 11 | 12 | export class CustomMap { 13 | private googleMap: google.maps.Map; 14 | 15 | constructor(divId: string) { 16 | this.googleMap = new google.maps.Map(document.getElementById(divId), { 17 | zoom: 1, 18 | center: { 19 | lat: 0, 20 | lng: 0 21 | } 22 | }); 23 | } 24 | 25 | addMarker(mappable: Mappable): void { 26 | const marker = new google.maps.Marker({ 27 | map: this.googleMap, 28 | position: { 29 | lat: mappable.location.lat, 30 | lng: mappable.location.lng 31 | } 32 | }); 33 | 34 | marker.addListener('click', () => { 35 | const infoWindow = new google.maps.InfoWindow({ 36 | content: mappable.markerContent() 37 | }); 38 | 39 | infoWindow.open(this.googleMap, marker); 40 | }); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /maps/src/User.ts: -------------------------------------------------------------------------------- 1 | import faker from 'faker'; 2 | import { Mappable } from './CustomMap'; 3 | 4 | export class User implements Mappable { 5 | name: string; 6 | location: { 7 | lat: number; 8 | lng: number; 9 | }; 10 | color: string = 'red'; 11 | 12 | constructor() { 13 | this.name = faker.name.firstName(); 14 | this.location = { 15 | lat: parseFloat(faker.address.latitude()), 16 | lng: parseFloat(faker.address.longitude()) 17 | }; 18 | } 19 | 20 | markerContent(): string { 21 | return `User Name: ${this.name}`; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /maps/src/index.ts: -------------------------------------------------------------------------------- 1 | import { User } from './User'; 2 | import { Company } from './Company'; 3 | import { CustomMap } from './CustomMap'; 4 | 5 | const user = new User(); 6 | const company = new Company(); 7 | const customMap = new CustomMap('map'); 8 | 9 | customMap.addMarker(user); 10 | customMap.addMarker(company); 11 | -------------------------------------------------------------------------------- /rrts/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /rrts/README.md: -------------------------------------------------------------------------------- 1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 2 | 3 | ## Available Scripts 4 | 5 | In the project directory, you can run: 6 | 7 | ### `npm start` 8 | 9 | Runs the app in the development mode.
10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 11 | 12 | The page will reload if you make edits.
13 | You will also see any lint errors in the console. 14 | 15 | ### `npm test` 16 | 17 | Launches the test runner in the interactive watch mode.
18 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 19 | 20 | ### `npm run build` 21 | 22 | Builds the app for production to the `build` folder.
23 | It correctly bundles React in production mode and optimizes the build for the best performance. 24 | 25 | The build is minified and the filenames include the hashes.
26 | Your app is ready to be deployed! 27 | 28 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 29 | 30 | ### `npm run eject` 31 | 32 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 33 | 34 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 35 | 36 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 37 | 38 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 39 | 40 | ## Learn More 41 | 42 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 43 | 44 | To learn React, check out the [React documentation](https://reactjs.org/). 45 | -------------------------------------------------------------------------------- /rrts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rrts", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@types/jest": "24.0.13", 7 | "@types/node": "12.0.7", 8 | "@types/react": "16.8.19", 9 | "@types/react-dom": "16.8.4", 10 | "@types/react-redux": "^7.0.9", 11 | "axios": "^0.19.0", 12 | "react": "^16.8.6", 13 | "react-dom": "^16.8.6", 14 | "react-redux": "^7.0.3", 15 | "react-scripts": "3.0.1", 16 | "redux": "^4.0.1", 17 | "redux-thunk": "^2.3.0", 18 | "typescript": "3.5.1" 19 | }, 20 | "scripts": { 21 | "start": "react-scripts start", 22 | "build": "react-scripts build", 23 | "test": "react-scripts test", 24 | "eject": "react-scripts eject" 25 | }, 26 | "eslintConfig": { 27 | "extends": "react-app" 28 | }, 29 | "browserslist": { 30 | "production": [ 31 | ">0.2%", 32 | "not dead", 33 | "not op_mini all" 34 | ], 35 | "development": [ 36 | "last 1 chrome version", 37 | "last 1 firefox version", 38 | "last 1 safari version" 39 | ] 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /rrts/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/typescriptcasts/91fc3e29ce8214766f90ee795fd5685975495932/rrts/public/favicon.ico -------------------------------------------------------------------------------- /rrts/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 22 | React App 23 | 24 | 25 | 26 |
27 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /rrts/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /rrts/src/actions/index.ts: -------------------------------------------------------------------------------- 1 | export * from './todos'; 2 | export * from './types'; 3 | -------------------------------------------------------------------------------- /rrts/src/actions/todos.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { Dispatch } from 'redux'; 3 | import { ActionTypes } from './types'; 4 | 5 | export interface Todo { 6 | id: number; 7 | title: string; 8 | completed: boolean; 9 | } 10 | 11 | export interface FetchTodosAction { 12 | type: ActionTypes.fetchTodos; 13 | payload: Todo[]; 14 | } 15 | 16 | export interface DeleteTodoAction { 17 | type: ActionTypes.deleteTodo; 18 | payload: number; 19 | } 20 | 21 | const url = 'https://jsonplaceholder.typicode.com/todos'; 22 | 23 | export const fetchTodos = () => { 24 | return async (dispatch: Dispatch) => { 25 | const response = await axios.get(url); 26 | 27 | dispatch({ 28 | type: ActionTypes.fetchTodos, 29 | payload: response.data 30 | }); 31 | }; 32 | }; 33 | 34 | export const deleteTodo = (id: number): DeleteTodoAction => { 35 | return { 36 | type: ActionTypes.deleteTodo, 37 | payload: id 38 | }; 39 | }; 40 | -------------------------------------------------------------------------------- /rrts/src/actions/types.ts: -------------------------------------------------------------------------------- 1 | import { FetchTodosAction, DeleteTodoAction } from './todos'; 2 | 3 | export enum ActionTypes { 4 | fetchTodos, 5 | deleteTodo 6 | } 7 | 8 | export type Action = FetchTodosAction | DeleteTodoAction; 9 | -------------------------------------------------------------------------------- /rrts/src/components/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { Todo, fetchTodos, deleteTodo } from '../actions'; 4 | import { StoreState } from '../reducers'; 5 | 6 | interface AppProps { 7 | todos: Todo[]; 8 | fetchTodos: Function; 9 | deleteTodo: typeof deleteTodo; 10 | } 11 | 12 | interface AppState { 13 | fetching: boolean; 14 | } 15 | 16 | class _App extends React.Component { 17 | constructor(props: AppProps) { 18 | super(props); 19 | 20 | this.state = { fetching: false }; 21 | } 22 | 23 | componentDidUpdate(prevProps: AppProps): void { 24 | if (!prevProps.todos.length && this.props.todos.length) { 25 | this.setState({ fetching: false }); 26 | } 27 | } 28 | 29 | onButtonClick = (): void => { 30 | this.props.fetchTodos(); 31 | this.setState({ fetching: true }); 32 | }; 33 | 34 | onTodoClick = (id: number): void => { 35 | this.props.deleteTodo(id); 36 | }; 37 | 38 | renderList(): JSX.Element[] { 39 | return this.props.todos.map((todo: Todo) => { 40 | return ( 41 |
this.onTodoClick(todo.id)} key={todo.id}> 42 | {todo.title} 43 |
44 | ); 45 | }); 46 | } 47 | 48 | render() { 49 | return ( 50 |
51 | 52 | {this.state.fetching ? 'LOADING' : null} 53 | {this.renderList()} 54 |
55 | ); 56 | } 57 | } 58 | 59 | const mapStateToProps = ({ todos }: StoreState): { todos: Todo[] } => { 60 | return { todos }; 61 | }; 62 | 63 | export const App = connect( 64 | mapStateToProps, 65 | { fetchTodos, deleteTodo } 66 | )(_App); 67 | -------------------------------------------------------------------------------- /rrts/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { createStore, applyMiddleware } from 'redux'; 4 | import { Provider } from 'react-redux'; 5 | import thunk from 'redux-thunk'; 6 | import { App } from './components/App'; 7 | import { reducers } from './reducers'; 8 | 9 | const store = createStore(reducers, applyMiddleware(thunk)); 10 | 11 | ReactDOM.render( 12 | 13 | 14 | , 15 | document.querySelector('#root') 16 | ); 17 | -------------------------------------------------------------------------------- /rrts/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /rrts/src/reducers/index.ts: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import { todosReducer } from './todos'; 3 | import { Todo } from '../actions'; 4 | 5 | export interface StoreState { 6 | todos: Todo[]; 7 | } 8 | 9 | export const reducers = combineReducers({ 10 | todos: todosReducer 11 | }); 12 | -------------------------------------------------------------------------------- /rrts/src/reducers/todos.ts: -------------------------------------------------------------------------------- 1 | import { Todo, Action, ActionTypes } from '../actions'; 2 | 3 | export const todosReducer = (state: Todo[] = [], action: Action) => { 4 | switch (action.type) { 5 | case ActionTypes.fetchTodos: 6 | return action.payload; 7 | case ActionTypes.deleteTodo: 8 | return state.filter((todo: Todo) => todo.id !== action.payload); 9 | default: 10 | return state; 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /rrts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "resolveJsonModule": true, 18 | "isolatedModules": true, 19 | "noEmit": true, 20 | "jsx": "preserve" 21 | }, 22 | "include": [ 23 | "src" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /server/build/AppRouter.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | var express_1 = __importDefault(require("express")); 7 | var AppRouter = /** @class */ (function () { 8 | function AppRouter() { 9 | } 10 | AppRouter.getInstance = function () { 11 | if (!AppRouter.instance) { 12 | AppRouter.instance = express_1.default.Router(); 13 | } 14 | return AppRouter.instance; 15 | }; 16 | return AppRouter; 17 | }()); 18 | exports.AppRouter = AppRouter; 19 | -------------------------------------------------------------------------------- /server/build/controllers/LoginController.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | var decorators_1 = require("./decorators"); 13 | var LoginController = /** @class */ (function () { 14 | function LoginController() { 15 | } 16 | LoginController.prototype.getLogin = function (req, res) { 17 | res.send("\n
\n
\n \n \n
\n
\n \n \n
\n \n
\n "); 18 | }; 19 | LoginController.prototype.postLogin = function (req, res) { 20 | var _a = req.body, email = _a.email, password = _a.password; 21 | if (email === 'hi@hi.com' && password === 'password') { 22 | req.session = { loggedIn: true }; 23 | res.redirect('/'); 24 | } 25 | else { 26 | res.send('Invalid email or password'); 27 | } 28 | }; 29 | LoginController.prototype.getLogout = function (req, res) { 30 | req.session = undefined; 31 | res.redirect('/'); 32 | }; 33 | __decorate([ 34 | decorators_1.get('/login'), 35 | __metadata("design:type", Function), 36 | __metadata("design:paramtypes", [Object, Object]), 37 | __metadata("design:returntype", void 0) 38 | ], LoginController.prototype, "getLogin", null); 39 | __decorate([ 40 | decorators_1.post('/login'), 41 | decorators_1.bodyValidator('email', 'password'), 42 | __metadata("design:type", Function), 43 | __metadata("design:paramtypes", [Object, Object]), 44 | __metadata("design:returntype", void 0) 45 | ], LoginController.prototype, "postLogin", null); 46 | __decorate([ 47 | decorators_1.get('/logout'), 48 | __metadata("design:type", Function), 49 | __metadata("design:paramtypes", [Object, Object]), 50 | __metadata("design:returntype", void 0) 51 | ], LoginController.prototype, "getLogout", null); 52 | LoginController = __decorate([ 53 | decorators_1.controller('/auth') 54 | ], LoginController); 55 | return LoginController; 56 | }()); 57 | -------------------------------------------------------------------------------- /server/build/controllers/RootController.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | var decorators_1 = require("./decorators"); 13 | function requireAuth(req, res, next) { 14 | if (req.session && req.session.loggedIn) { 15 | next(); 16 | return; 17 | } 18 | res.status(403); 19 | res.send('Not permitted'); 20 | } 21 | var RootController = /** @class */ (function () { 22 | function RootController() { 23 | } 24 | RootController.prototype.getRoot = function (req, res) { 25 | if (req.session && req.session.loggedIn) { 26 | res.send("\n
\n
You are logged in
\n Logout\n
\n "); 27 | } 28 | else { 29 | res.send("\n
\n
You are not logged in
\n Login\n
\n "); 30 | } 31 | }; 32 | RootController.prototype.getProtected = function (req, res) { 33 | res.send('Welcome to protected route, logged in user'); 34 | }; 35 | __decorate([ 36 | decorators_1.get('/'), 37 | __metadata("design:type", Function), 38 | __metadata("design:paramtypes", [Object, Object]), 39 | __metadata("design:returntype", void 0) 40 | ], RootController.prototype, "getRoot", null); 41 | __decorate([ 42 | decorators_1.get('/protected'), 43 | decorators_1.use(requireAuth), 44 | __metadata("design:type", Function), 45 | __metadata("design:paramtypes", [Object, Object]), 46 | __metadata("design:returntype", void 0) 47 | ], RootController.prototype, "getProtected", null); 48 | RootController = __decorate([ 49 | decorators_1.controller('') 50 | ], RootController); 51 | return RootController; 52 | }()); 53 | -------------------------------------------------------------------------------- /server/build/controllers/decorators/MetadataKeys.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var MetadataKeys; 4 | (function (MetadataKeys) { 5 | MetadataKeys["method"] = "method"; 6 | MetadataKeys["path"] = "path"; 7 | MetadataKeys["middleware"] = "middleware"; 8 | MetadataKeys["validator"] = "validator"; 9 | })(MetadataKeys = exports.MetadataKeys || (exports.MetadataKeys = {})); 10 | -------------------------------------------------------------------------------- /server/build/controllers/decorators/Methods.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var Methods; 4 | (function (Methods) { 5 | Methods["get"] = "get"; 6 | Methods["post"] = "post"; 7 | Methods["patch"] = "patch"; 8 | Methods["del"] = "delete"; 9 | Methods["put"] = "put"; 10 | })(Methods = exports.Methods || (exports.Methods = {})); 11 | -------------------------------------------------------------------------------- /server/build/controllers/decorators/bodyValidator.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | require("reflect-metadata"); 4 | var MetadataKeys_1 = require("./MetadataKeys"); 5 | function bodyValidator() { 6 | var keys = []; 7 | for (var _i = 0; _i < arguments.length; _i++) { 8 | keys[_i] = arguments[_i]; 9 | } 10 | return function (target, key, desc) { 11 | Reflect.defineMetadata(MetadataKeys_1.MetadataKeys.validator, keys, target, key); 12 | }; 13 | } 14 | exports.bodyValidator = bodyValidator; 15 | -------------------------------------------------------------------------------- /server/build/controllers/decorators/controller.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | require("reflect-metadata"); 4 | var AppRouter_1 = require("../../AppRouter"); 5 | var MetadataKeys_1 = require("./MetadataKeys"); 6 | function bodyValidators(keys) { 7 | return function (req, res, next) { 8 | if (!req.body) { 9 | res.status(422).send('Invalid request'); 10 | return; 11 | } 12 | for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { 13 | var key = keys_1[_i]; 14 | if (!req.body[key]) { 15 | res.status(422).send("Missing property " + key); 16 | return; 17 | } 18 | } 19 | next(); 20 | }; 21 | } 22 | function controller(routePrefix) { 23 | return function (target) { 24 | var router = AppRouter_1.AppRouter.getInstance(); 25 | for (var key in target.prototype) { 26 | var routeHandler = target.prototype[key]; 27 | var path = Reflect.getMetadata(MetadataKeys_1.MetadataKeys.path, target.prototype, key); 28 | var method = Reflect.getMetadata(MetadataKeys_1.MetadataKeys.method, target.prototype, key); 29 | var middlewares = Reflect.getMetadata(MetadataKeys_1.MetadataKeys.middleware, target.prototype, key) || 30 | []; 31 | var requiredBodyProps = Reflect.getMetadata(MetadataKeys_1.MetadataKeys.validator, target.prototype, key) || 32 | []; 33 | var validator = bodyValidators(requiredBodyProps); 34 | if (path) { 35 | router[method].apply(router, ["" + routePrefix + path].concat(middlewares, [validator, 36 | routeHandler])); 37 | } 38 | } 39 | }; 40 | } 41 | exports.controller = controller; 42 | -------------------------------------------------------------------------------- /server/build/controllers/decorators/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | function __export(m) { 3 | for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; 4 | } 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | __export(require("./controller")); 7 | __export(require("./routes")); 8 | __export(require("./use")); 9 | __export(require("./bodyValidator")); 10 | -------------------------------------------------------------------------------- /server/build/controllers/decorators/routes.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | require("reflect-metadata"); 4 | var Methods_1 = require("./Methods"); 5 | var MetadataKeys_1 = require("./MetadataKeys"); 6 | function routeBinder(method) { 7 | return function (path) { 8 | return function (target, key, desc) { 9 | Reflect.defineMetadata(MetadataKeys_1.MetadataKeys.path, path, target, key); 10 | Reflect.defineMetadata(MetadataKeys_1.MetadataKeys.method, method, target, key); 11 | }; 12 | }; 13 | } 14 | exports.get = routeBinder(Methods_1.Methods.get); 15 | exports.put = routeBinder(Methods_1.Methods.put); 16 | exports.post = routeBinder(Methods_1.Methods.post); 17 | exports.del = routeBinder(Methods_1.Methods.del); 18 | exports.patch = routeBinder(Methods_1.Methods.patch); 19 | -------------------------------------------------------------------------------- /server/build/controllers/decorators/use.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | require("reflect-metadata"); 4 | var MetadataKeys_1 = require("./MetadataKeys"); 5 | function use(middleware) { 6 | return function (target, key, desc) { 7 | var middlewares = Reflect.getMetadata(MetadataKeys_1.MetadataKeys.middleware, target, key) || []; 8 | Reflect.defineMetadata(MetadataKeys_1.MetadataKeys.middleware, middlewares.concat([middleware]), target, key); 9 | }; 10 | } 11 | exports.use = use; 12 | -------------------------------------------------------------------------------- /server/build/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | var express_1 = __importDefault(require("express")); 7 | var body_parser_1 = __importDefault(require("body-parser")); 8 | var cookie_session_1 = __importDefault(require("cookie-session")); 9 | var AppRouter_1 = require("./AppRouter"); 10 | require("./controllers/LoginController"); 11 | require("./controllers/RootController"); 12 | var app = express_1.default(); 13 | app.use(body_parser_1.default.urlencoded({ extended: true })); 14 | app.use(cookie_session_1.default({ keys: ['laskdjf'] })); 15 | app.use(AppRouter_1.AppRouter.getInstance()); 16 | app.listen(3000, function () { 17 | console.log('Listening on port 3000'); 18 | }); 19 | -------------------------------------------------------------------------------- /server/build/routes/loginRoutes.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var express_1 = require("express"); 4 | var router = express_1.Router(); 5 | exports.router = router; 6 | -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start:build": "tsc -w", 8 | "start:run": "nodemon build/index.js", 9 | "start": "concurrently npm:start:*" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "@types/body-parser": "^1.17.0", 16 | "@types/cookie-session": "^2.0.37", 17 | "@types/express": "^4.16.1", 18 | "body-parser": "^1.19.0", 19 | "concurrently": "^4.1.0", 20 | "cookie-session": "^1.3.3", 21 | "express": "^4.17.1", 22 | "nodemon": "^1.19.1", 23 | "reflect-metadata": "^0.1.13" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /server/src/AppRouter.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | export class AppRouter { 4 | private static instance: express.Router; 5 | 6 | static getInstance(): express.Router { 7 | if (!AppRouter.instance) { 8 | AppRouter.instance = express.Router(); 9 | } 10 | 11 | return AppRouter.instance; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /server/src/controllers/LoginController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response, NextFunction } from 'express'; 2 | import { get, controller, bodyValidator, post } from './decorators'; 3 | 4 | @controller('/auth') 5 | class LoginController { 6 | @get('/login') 7 | getLogin(req: Request, res: Response): void { 8 | res.send(` 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 | 19 |
20 | `); 21 | } 22 | 23 | @post('/login') 24 | @bodyValidator('email', 'password') 25 | postLogin(req: Request, res: Response) { 26 | const { email, password } = req.body; 27 | 28 | if (email === 'hi@hi.com' && password === 'password') { 29 | req.session = { loggedIn: true }; 30 | res.redirect('/'); 31 | } else { 32 | res.send('Invalid email or password'); 33 | } 34 | } 35 | 36 | @get('/logout') 37 | getLogout(req: Request, res: Response) { 38 | req.session = undefined; 39 | res.redirect('/'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /server/src/controllers/RootController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response, NextFunction } from 'express'; 2 | import { get, controller, use } from './decorators'; 3 | 4 | function requireAuth(req: Request, res: Response, next: NextFunction): void { 5 | if (req.session && req.session.loggedIn) { 6 | next(); 7 | return; 8 | } 9 | 10 | res.status(403); 11 | res.send('Not permitted'); 12 | } 13 | 14 | @controller('') 15 | class RootController { 16 | @get('/') 17 | getRoot(req: Request, res: Response) { 18 | if (req.session && req.session.loggedIn) { 19 | res.send(` 20 |
21 |
You are logged in
22 | Logout 23 |
24 | `); 25 | } else { 26 | res.send(` 27 |
28 |
You are not logged in
29 | Login 30 |
31 | `); 32 | } 33 | } 34 | 35 | @get('/protected') 36 | @use(requireAuth) 37 | getProtected(req: Request, res: Response) { 38 | res.send('Welcome to protected route, logged in user'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /server/src/controllers/decorators/MetadataKeys.ts: -------------------------------------------------------------------------------- 1 | export enum MetadataKeys { 2 | method = 'method', 3 | path = 'path', 4 | middleware = 'middleware', 5 | validator = 'validator' 6 | } 7 | -------------------------------------------------------------------------------- /server/src/controllers/decorators/Methods.ts: -------------------------------------------------------------------------------- 1 | export enum Methods { 2 | get = 'get', 3 | post = 'post', 4 | patch = 'patch', 5 | del = 'delete', 6 | put = 'put' 7 | } 8 | -------------------------------------------------------------------------------- /server/src/controllers/decorators/bodyValidator.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import { MetadataKeys } from './MetadataKeys'; 3 | 4 | export function bodyValidator(...keys: string[]) { 5 | return function(target: any, key: string, desc: PropertyDescriptor) { 6 | Reflect.defineMetadata(MetadataKeys.validator, keys, target, key); 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /server/src/controllers/decorators/controller.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import { Request, Response, RequestHandler, NextFunction } from 'express'; 3 | import { AppRouter } from '../../AppRouter'; 4 | import { Methods } from './Methods'; 5 | import { MetadataKeys } from './MetadataKeys'; 6 | 7 | function bodyValidators(keys: string): RequestHandler { 8 | return function(req: Request, res: Response, next: NextFunction) { 9 | if (!req.body) { 10 | res.status(422).send('Invalid request'); 11 | return; 12 | } 13 | 14 | for (let key of keys) { 15 | if (!req.body[key]) { 16 | res.status(422).send(`Missing property ${key}`); 17 | return; 18 | } 19 | } 20 | 21 | next(); 22 | }; 23 | } 24 | 25 | export function controller(routePrefix: string) { 26 | return function(target: Function) { 27 | const router = AppRouter.getInstance(); 28 | 29 | for (let key in target.prototype) { 30 | const routeHandler = target.prototype[key]; 31 | const path = Reflect.getMetadata( 32 | MetadataKeys.path, 33 | target.prototype, 34 | key 35 | ); 36 | const method: Methods = Reflect.getMetadata( 37 | MetadataKeys.method, 38 | target.prototype, 39 | key 40 | ); 41 | const middlewares = 42 | Reflect.getMetadata(MetadataKeys.middleware, target.prototype, key) || 43 | []; 44 | const requiredBodyProps = 45 | Reflect.getMetadata(MetadataKeys.validator, target.prototype, key) || 46 | []; 47 | 48 | const validator = bodyValidators(requiredBodyProps); 49 | 50 | if (path) { 51 | router[method]( 52 | `${routePrefix}${path}`, 53 | ...middlewares, 54 | validator, 55 | routeHandler 56 | ); 57 | } 58 | } 59 | }; 60 | } 61 | -------------------------------------------------------------------------------- /server/src/controllers/decorators/index.ts: -------------------------------------------------------------------------------- 1 | export * from './controller'; 2 | export * from './routes'; 3 | export * from './use'; 4 | export * from './bodyValidator'; 5 | -------------------------------------------------------------------------------- /server/src/controllers/decorators/routes.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import { RequestHandler } from 'express'; 3 | import { Methods } from './Methods'; 4 | import { MetadataKeys } from './MetadataKeys'; 5 | 6 | interface RouteHandlerDescriptor extends PropertyDescriptor { 7 | value?: RequestHandler; 8 | } 9 | 10 | function routeBinder(method: string) { 11 | return function(path: string) { 12 | return function(target: any, key: string, desc: RouteHandlerDescriptor) { 13 | Reflect.defineMetadata(MetadataKeys.path, path, target, key); 14 | Reflect.defineMetadata(MetadataKeys.method, method, target, key); 15 | }; 16 | }; 17 | } 18 | 19 | export const get = routeBinder(Methods.get); 20 | export const put = routeBinder(Methods.put); 21 | export const post = routeBinder(Methods.post); 22 | export const del = routeBinder(Methods.del); 23 | export const patch = routeBinder(Methods.patch); 24 | -------------------------------------------------------------------------------- /server/src/controllers/decorators/use.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import { RequestHandler } from 'express'; 3 | import { MetadataKeys } from './MetadataKeys'; 4 | 5 | export function use(middleware: RequestHandler) { 6 | return function(target: any, key: string, desc: PropertyDescriptor) { 7 | const middlewares = 8 | Reflect.getMetadata(MetadataKeys.middleware, target, key) || []; 9 | 10 | Reflect.defineMetadata( 11 | MetadataKeys.middleware, 12 | [...middlewares, middleware], 13 | target, 14 | key 15 | ); 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /server/src/index.ts: -------------------------------------------------------------------------------- 1 | import express, { Request, Response } from 'express'; 2 | import bodyParser from 'body-parser'; 3 | import cookieSession from 'cookie-session'; 4 | import { AppRouter } from './AppRouter'; 5 | import './controllers/LoginController'; 6 | import './controllers/RootController'; 7 | 8 | const app = express(); 9 | 10 | app.use(bodyParser.urlencoded({ extended: true })); 11 | app.use(cookieSession({ keys: ['laskdjf'] })); 12 | app.use(AppRouter.getInstance()); 13 | 14 | app.listen(3000, () => { 15 | console.log('Listening on port 3000'); 16 | }); 17 | -------------------------------------------------------------------------------- /server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, 5 | "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, 6 | // "lib": [], /* Specify library files to be included in the compilation. */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | "outDir": "./build" /* Redirect output structure to the directory. */, 15 | "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, 16 | // "composite": true, /* Enable project compilation */ 17 | // "incremental": true, /* Enable incremental compilation */ 18 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 19 | // "removeComments": true, /* Do not emit comments to output. */ 20 | // "noEmit": true, /* Do not emit outputs. */ 21 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 22 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 23 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 24 | 25 | /* Strict Type-Checking Options */ 26 | "strict": true /* Enable all strict type-checking options. */, 27 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 28 | // "strictNullChecks": true /* Enable strict null checks. */, 29 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 30 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 31 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 32 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 33 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 34 | 35 | /* Additional Checks */ 36 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 37 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 38 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 39 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 40 | 41 | /* Module Resolution Options */ 42 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 43 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 44 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 45 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 46 | // "typeRoots": [], /* List of folders to include type definitions from. */ 47 | // "types": [], /* Type declaration files to be included in compilation. */ 48 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 49 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, 50 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 51 | 52 | /* Source Map Options */ 53 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 54 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 55 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 56 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 57 | 58 | /* Experimental Options */ 59 | "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, 60 | "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */ 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /sort/build/CharactersCollection.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __extends = (this && this.__extends) || (function () { 3 | var extendStatics = function (d, b) { 4 | extendStatics = Object.setPrototypeOf || 5 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 6 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 7 | return extendStatics(d, b); 8 | }; 9 | return function (d, b) { 10 | extendStatics(d, b); 11 | function __() { this.constructor = d; } 12 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 13 | }; 14 | })(); 15 | Object.defineProperty(exports, "__esModule", { value: true }); 16 | var Sorter_1 = require("./Sorter"); 17 | var CharactersCollection = /** @class */ (function (_super) { 18 | __extends(CharactersCollection, _super); 19 | function CharactersCollection(data) { 20 | var _this = _super.call(this) || this; 21 | _this.data = data; 22 | return _this; 23 | } 24 | Object.defineProperty(CharactersCollection.prototype, "length", { 25 | get: function () { 26 | return this.data.length; 27 | }, 28 | enumerable: true, 29 | configurable: true 30 | }); 31 | CharactersCollection.prototype.compare = function (leftIndex, rightIndex) { 32 | return (this.data[leftIndex].toLowerCase() > this.data[rightIndex].toLowerCase()); 33 | }; 34 | CharactersCollection.prototype.swap = function (leftIndex, rightIndex) { 35 | var characters = this.data.split(''); 36 | var leftHand = characters[leftIndex]; 37 | characters[leftIndex] = characters[rightIndex]; 38 | characters[rightIndex] = leftHand; 39 | this.data = characters.join(''); 40 | }; 41 | return CharactersCollection; 42 | }(Sorter_1.Sorter)); 43 | exports.CharactersCollection = CharactersCollection; 44 | -------------------------------------------------------------------------------- /sort/build/LinkedList.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __extends = (this && this.__extends) || (function () { 3 | var extendStatics = function (d, b) { 4 | extendStatics = Object.setPrototypeOf || 5 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 6 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 7 | return extendStatics(d, b); 8 | }; 9 | return function (d, b) { 10 | extendStatics(d, b); 11 | function __() { this.constructor = d; } 12 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 13 | }; 14 | })(); 15 | Object.defineProperty(exports, "__esModule", { value: true }); 16 | var Sorter_1 = require("./Sorter"); 17 | var Node = /** @class */ (function () { 18 | function Node(data) { 19 | this.data = data; 20 | this.next = null; 21 | } 22 | return Node; 23 | }()); 24 | var LinkedList = /** @class */ (function (_super) { 25 | __extends(LinkedList, _super); 26 | function LinkedList() { 27 | var _this = _super !== null && _super.apply(this, arguments) || this; 28 | _this.head = null; 29 | return _this; 30 | } 31 | LinkedList.prototype.add = function (data) { 32 | var node = new Node(data); 33 | if (!this.head) { 34 | this.head = node; 35 | return; 36 | } 37 | var tail = this.head; 38 | while (tail.next) { 39 | tail = tail.next; 40 | } 41 | tail.next = node; 42 | }; 43 | Object.defineProperty(LinkedList.prototype, "length", { 44 | get: function () { 45 | if (!this.head) { 46 | return 0; 47 | } 48 | var length = 1; 49 | var node = this.head; 50 | while (node.next) { 51 | length++; 52 | node = node.next; 53 | } 54 | return length; 55 | }, 56 | enumerable: true, 57 | configurable: true 58 | }); 59 | LinkedList.prototype.at = function (index) { 60 | if (!this.head) { 61 | throw new Error('Index out of bounds'); 62 | } 63 | var counter = 0; 64 | var node = this.head; 65 | while (node) { 66 | if (counter === index) { 67 | return node; 68 | } 69 | counter++; 70 | node = node.next; 71 | } 72 | throw new Error('Index out of bounds'); 73 | }; 74 | LinkedList.prototype.compare = function (leftIndex, rightIndex) { 75 | if (!this.head) { 76 | throw new Error('List is empty'); 77 | } 78 | return this.at(leftIndex).data > this.at(rightIndex).data; 79 | }; 80 | LinkedList.prototype.swap = function (leftIndex, rightIndex) { 81 | var leftNode = this.at(leftIndex); 82 | var rightNode = this.at(rightIndex); 83 | var leftHand = leftNode.data; 84 | leftNode.data = rightNode.data; 85 | rightNode.data = leftHand; 86 | }; 87 | LinkedList.prototype.print = function () { 88 | if (!this.head) { 89 | return; 90 | } 91 | var node = this.head; 92 | while (node) { 93 | console.log(node.data); 94 | node = node.next; 95 | } 96 | }; 97 | return LinkedList; 98 | }(Sorter_1.Sorter)); 99 | exports.LinkedList = LinkedList; 100 | -------------------------------------------------------------------------------- /sort/build/NumbersCollection.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __extends = (this && this.__extends) || (function () { 3 | var extendStatics = function (d, b) { 4 | extendStatics = Object.setPrototypeOf || 5 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 6 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 7 | return extendStatics(d, b); 8 | }; 9 | return function (d, b) { 10 | extendStatics(d, b); 11 | function __() { this.constructor = d; } 12 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 13 | }; 14 | })(); 15 | Object.defineProperty(exports, "__esModule", { value: true }); 16 | var Sorter_1 = require("./Sorter"); 17 | var NumbersCollection = /** @class */ (function (_super) { 18 | __extends(NumbersCollection, _super); 19 | function NumbersCollection(data) { 20 | var _this = _super.call(this) || this; 21 | _this.data = data; 22 | return _this; 23 | } 24 | Object.defineProperty(NumbersCollection.prototype, "length", { 25 | get: function () { 26 | return this.data.length; 27 | }, 28 | enumerable: true, 29 | configurable: true 30 | }); 31 | NumbersCollection.prototype.compare = function (leftIndex, rightIndex) { 32 | return this.data[leftIndex] > this.data[rightIndex]; 33 | }; 34 | NumbersCollection.prototype.swap = function (leftIndex, rightIndex) { 35 | var leftHand = this.data[leftIndex]; 36 | this.data[leftIndex] = this.data[rightIndex]; 37 | this.data[rightIndex] = leftHand; 38 | }; 39 | return NumbersCollection; 40 | }(Sorter_1.Sorter)); 41 | exports.NumbersCollection = NumbersCollection; 42 | -------------------------------------------------------------------------------- /sort/build/Sorter.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var Sorter = /** @class */ (function () { 4 | function Sorter() { 5 | } 6 | Sorter.prototype.sort = function () { 7 | var length = this.length; 8 | for (var i = 0; i < length; i++) { 9 | for (var j = 0; j < length - i - 1; j++) { 10 | if (this.compare(j, j + 1)) { 11 | this.swap(j, j + 1); 12 | } 13 | } 14 | } 15 | }; 16 | return Sorter; 17 | }()); 18 | exports.Sorter = Sorter; 19 | -------------------------------------------------------------------------------- /sort/build/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var LinkedList_1 = require("./LinkedList"); 4 | // const numbersCollection = new NumbersCollection([50, 3, -5, 0]); 5 | // numbersCollection.sort(); 6 | // console.log(numbersCollection.data); 7 | // const charactersCollection = new CharactersCollection('Xaayb'); 8 | // charactersCollection.sort(); 9 | // console.log(charactersCollection.data); 10 | var linkedList = new LinkedList_1.LinkedList(); 11 | linkedList.add(500); 12 | linkedList.add(-10); 13 | linkedList.add(-3); 14 | linkedList.add(4); 15 | linkedList.sort(); 16 | linkedList.print(); 17 | -------------------------------------------------------------------------------- /sort/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sort", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start:build": "tsc -w", 8 | "start:run": "nodemon build/index.js", 9 | "start": "concurrently npm:start:*" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "concurrently": "^4.1.0", 16 | "nodemon": "^1.19.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /sort/src/CharactersCollection.ts: -------------------------------------------------------------------------------- 1 | import { Sorter } from './Sorter'; 2 | 3 | export class CharactersCollection extends Sorter { 4 | constructor(public data: string) { 5 | super(); 6 | } 7 | 8 | get length(): number { 9 | return this.data.length; 10 | } 11 | 12 | compare(leftIndex: number, rightIndex: number): boolean { 13 | return ( 14 | this.data[leftIndex].toLowerCase() > this.data[rightIndex].toLowerCase() 15 | ); 16 | } 17 | 18 | swap(leftIndex: number, rightIndex: number): void { 19 | const characters = this.data.split(''); 20 | 21 | const leftHand = characters[leftIndex]; 22 | characters[leftIndex] = characters[rightIndex]; 23 | characters[rightIndex] = leftHand; 24 | 25 | this.data = characters.join(''); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /sort/src/LinkedList.ts: -------------------------------------------------------------------------------- 1 | import { Sorter } from './Sorter'; 2 | 3 | class Node { 4 | next: Node | null = null; 5 | 6 | constructor(public data: number) {} 7 | } 8 | 9 | export class LinkedList extends Sorter { 10 | head: Node | null = null; 11 | 12 | add(data: number): void { 13 | const node = new Node(data); 14 | 15 | if (!this.head) { 16 | this.head = node; 17 | return; 18 | } 19 | 20 | let tail = this.head; 21 | while (tail.next) { 22 | tail = tail.next; 23 | } 24 | 25 | tail.next = node; 26 | } 27 | 28 | get length(): number { 29 | if (!this.head) { 30 | return 0; 31 | } 32 | 33 | let length = 1; 34 | let node = this.head; 35 | while (node.next) { 36 | length++; 37 | node = node.next; 38 | } 39 | 40 | return length; 41 | } 42 | 43 | at(index: number): Node { 44 | if (!this.head) { 45 | throw new Error('Index out of bounds'); 46 | } 47 | 48 | let counter = 0; 49 | let node: Node | null = this.head; 50 | while (node) { 51 | if (counter === index) { 52 | return node; 53 | } 54 | 55 | counter++; 56 | node = node.next; 57 | } 58 | 59 | throw new Error('Index out of bounds'); 60 | } 61 | 62 | compare(leftIndex: number, rightIndex: number): boolean { 63 | if (!this.head) { 64 | throw new Error('List is empty'); 65 | } 66 | 67 | return this.at(leftIndex).data > this.at(rightIndex).data; 68 | } 69 | 70 | swap(leftIndex: number, rightIndex: number): void { 71 | const leftNode = this.at(leftIndex); 72 | const rightNode = this.at(rightIndex); 73 | 74 | const leftHand = leftNode.data; 75 | leftNode.data = rightNode.data; 76 | rightNode.data = leftHand; 77 | } 78 | 79 | print(): void { 80 | if (!this.head) { 81 | return; 82 | } 83 | 84 | let node: Node | null = this.head; 85 | while (node) { 86 | console.log(node.data); 87 | node = node.next; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /sort/src/NumbersCollection.ts: -------------------------------------------------------------------------------- 1 | import { Sorter } from './Sorter'; 2 | 3 | export class NumbersCollection extends Sorter { 4 | constructor(public data: number[]) { 5 | super(); 6 | } 7 | 8 | get length(): number { 9 | return this.data.length; 10 | } 11 | 12 | compare(leftIndex: number, rightIndex: number): boolean { 13 | return this.data[leftIndex] > this.data[rightIndex]; 14 | } 15 | 16 | swap(leftIndex: number, rightIndex: number): void { 17 | const leftHand = this.data[leftIndex]; 18 | this.data[leftIndex] = this.data[rightIndex]; 19 | this.data[rightIndex] = leftHand; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /sort/src/Sorter.ts: -------------------------------------------------------------------------------- 1 | export abstract class Sorter { 2 | abstract compare(leftIndex: number, rightIndex: number): boolean; 3 | abstract swap(leftIndex: number, rightIndex: number): void; 4 | abstract length: number; 5 | 6 | sort(): void { 7 | const { length } = this; 8 | 9 | for (let i = 0; i < length; i++) { 10 | for (let j = 0; j < length - i - 1; j++) { 11 | if (this.compare(j, j + 1)) { 12 | this.swap(j, j + 1); 13 | } 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /sort/src/index.ts: -------------------------------------------------------------------------------- 1 | import { Sorter } from './Sorter'; 2 | import { NumbersCollection } from './NumbersCollection'; 3 | import { CharactersCollection } from './CharactersCollection'; 4 | import { LinkedList } from './LinkedList'; 5 | 6 | // const numbersCollection = new NumbersCollection([50, 3, -5, 0]); 7 | // numbersCollection.sort(); 8 | // console.log(numbersCollection.data); 9 | 10 | // const charactersCollection = new CharactersCollection('Xaayb'); 11 | // charactersCollection.sort(); 12 | // console.log(charactersCollection.data); 13 | 14 | const linkedList = new LinkedList(); 15 | linkedList.add(500); 16 | linkedList.add(-10); 17 | linkedList.add(-3); 18 | linkedList.add(4); 19 | 20 | linkedList.sort(); 21 | linkedList.print(); 22 | -------------------------------------------------------------------------------- /sort/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, 5 | "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, 6 | // "lib": [], /* Specify library files to be included in the compilation. */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | "outDir": "./build" /* Redirect output structure to the directory. */, 15 | "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, 16 | // "composite": true, /* Enable project compilation */ 17 | // "incremental": true, /* Enable incremental compilation */ 18 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 19 | // "removeComments": true, /* Do not emit comments to output. */ 20 | // "noEmit": true, /* Do not emit outputs. */ 21 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 22 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 23 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 24 | 25 | /* Strict Type-Checking Options */ 26 | "strict": true /* Enable all strict type-checking options. */, 27 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 28 | // "strictNullChecks": true, /* Enable strict null checks. */ 29 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 30 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 31 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 32 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 33 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 34 | 35 | /* Additional Checks */ 36 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 37 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 38 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 39 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 40 | 41 | /* Module Resolution Options */ 42 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 43 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 44 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 45 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 46 | // "typeRoots": [], /* List of folders to include type definitions from. */ 47 | // "types": [], /* Type declaration files to be included in compilation. */ 48 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 49 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 50 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 51 | 52 | /* Source Map Options */ 53 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 54 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 55 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 56 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 57 | 58 | /* Experimental Options */ 59 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 60 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /stats/build/CsvFileReader.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | var fs_1 = __importDefault(require("fs")); 7 | var CsvFileReader = /** @class */ (function () { 8 | function CsvFileReader(filename) { 9 | this.filename = filename; 10 | this.data = []; 11 | } 12 | CsvFileReader.prototype.read = function () { 13 | this.data = fs_1.default 14 | .readFileSync(this.filename, { 15 | encoding: 'utf-8' 16 | }) 17 | .split('\n') 18 | .map(function (row) { 19 | return row.split(','); 20 | }); 21 | }; 22 | return CsvFileReader; 23 | }()); 24 | exports.CsvFileReader = CsvFileReader; 25 | -------------------------------------------------------------------------------- /stats/build/MatchData.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /stats/build/MatchReader.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var utils_1 = require("./utils"); 4 | var CsvFileReader_1 = require("./CsvFileReader"); 5 | var MatchReader = /** @class */ (function () { 6 | function MatchReader(reader) { 7 | this.reader = reader; 8 | this.matches = []; 9 | } 10 | MatchReader.fromCsv = function (filename) { 11 | return new MatchReader(new CsvFileReader_1.CsvFileReader(filename)); 12 | }; 13 | MatchReader.prototype.load = function () { 14 | this.reader.read(); 15 | this.matches = this.reader.data.map(function (row) { 16 | return [ 17 | utils_1.dateStringToDate(row[0]), 18 | row[1], 19 | row[2], 20 | parseInt(row[3]), 21 | parseInt(row[4]), 22 | row[5], 23 | row[6] 24 | ]; 25 | }); 26 | }; 27 | return MatchReader; 28 | }()); 29 | exports.MatchReader = MatchReader; 30 | -------------------------------------------------------------------------------- /stats/build/MatchResult.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | // enum - enumeration 4 | var MatchResult; 5 | (function (MatchResult) { 6 | MatchResult["HomeWin"] = "H"; 7 | MatchResult["AwayWin"] = "A"; 8 | MatchResult["Draw"] = "D"; 9 | })(MatchResult = exports.MatchResult || (exports.MatchResult = {})); 10 | -------------------------------------------------------------------------------- /stats/build/Summary.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var WinsAnalysis_1 = require("./analyzers/WinsAnalysis"); 4 | var HtmlReport_1 = require("./reportTargets/HtmlReport"); 5 | var Summary = /** @class */ (function () { 6 | function Summary(analyzer, outputTarget) { 7 | this.analyzer = analyzer; 8 | this.outputTarget = outputTarget; 9 | } 10 | Summary.winsAnalysisWithHtmlReport = function (team) { 11 | return new Summary(new WinsAnalysis_1.WinsAnalysis(team), new HtmlReport_1.HtmlReport()); 12 | }; 13 | Summary.prototype.buildAndPrintReport = function (matches) { 14 | var output = this.analyzer.run(matches); 15 | this.outputTarget.print(output); 16 | }; 17 | return Summary; 18 | }()); 19 | exports.Summary = Summary; 20 | -------------------------------------------------------------------------------- /stats/build/analyzers/WinsAnalysis.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var MatchResult_1 = require("../MatchResult"); 4 | var WinsAnalysis = /** @class */ (function () { 5 | function WinsAnalysis(team) { 6 | this.team = team; 7 | } 8 | WinsAnalysis.prototype.run = function (matches) { 9 | var wins = 0; 10 | for (var _i = 0, matches_1 = matches; _i < matches_1.length; _i++) { 11 | var match = matches_1[_i]; 12 | if (match[1] === 'Man United' && match[5] === MatchResult_1.MatchResult.HomeWin) { 13 | wins++; 14 | } 15 | else if (match[2] === 'Man United' && 16 | match[5] === MatchResult_1.MatchResult.AwayWin) { 17 | wins++; 18 | } 19 | } 20 | return "Team " + this.team + " won " + wins + " games"; 21 | }; 22 | return WinsAnalysis; 23 | }()); 24 | exports.WinsAnalysis = WinsAnalysis; 25 | -------------------------------------------------------------------------------- /stats/build/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var MatchReader_1 = require("./MatchReader"); 4 | var Summary_1 = require("./Summary"); 5 | var matchReader = MatchReader_1.MatchReader.fromCsv('football.csv'); 6 | var summary = Summary_1.Summary.winsAnalysisWithHtmlReport('Man United'); 7 | matchReader.load(); 8 | summary.buildAndPrintReport(matchReader.matches); 9 | -------------------------------------------------------------------------------- /stats/build/inheritance/CsvFileReader.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | var fs_1 = __importDefault(require("fs")); 7 | var CsvFileReader = /** @class */ (function () { 8 | function CsvFileReader(filename) { 9 | this.filename = filename; 10 | this.data = []; 11 | } 12 | CsvFileReader.prototype.read = function () { 13 | this.data = fs_1.default 14 | .readFileSync(this.filename, { 15 | encoding: 'utf-8' 16 | }) 17 | .split('\n') 18 | .map(function (row) { 19 | return row.split(','); 20 | }) 21 | .map(this.mapRow); 22 | }; 23 | return CsvFileReader; 24 | }()); 25 | exports.CsvFileReader = CsvFileReader; 26 | -------------------------------------------------------------------------------- /stats/build/inheritance/MatchReader.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __extends = (this && this.__extends) || (function () { 3 | var extendStatics = function (d, b) { 4 | extendStatics = Object.setPrototypeOf || 5 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 6 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 7 | return extendStatics(d, b); 8 | }; 9 | return function (d, b) { 10 | extendStatics(d, b); 11 | function __() { this.constructor = d; } 12 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 13 | }; 14 | })(); 15 | Object.defineProperty(exports, "__esModule", { value: true }); 16 | var CsvFileReader_1 = require("./CsvFileReader"); 17 | var utils_1 = require("./utils"); 18 | var MatchReader = /** @class */ (function (_super) { 19 | __extends(MatchReader, _super); 20 | function MatchReader() { 21 | return _super !== null && _super.apply(this, arguments) || this; 22 | } 23 | MatchReader.prototype.mapRow = function (row) { 24 | return [ 25 | utils_1.dateStringToDate(row[0]), 26 | row[1], 27 | row[2], 28 | parseInt(row[3]), 29 | parseInt(row[4]), 30 | row[5], 31 | row[6] 32 | ]; 33 | }; 34 | return MatchReader; 35 | }(CsvFileReader_1.CsvFileReader)); 36 | exports.MatchReader = MatchReader; 37 | -------------------------------------------------------------------------------- /stats/build/reportTargets/ConsoleReport.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var ConsoleReport = /** @class */ (function () { 4 | function ConsoleReport() { 5 | } 6 | ConsoleReport.prototype.print = function (report) { 7 | console.log(report); 8 | }; 9 | return ConsoleReport; 10 | }()); 11 | exports.ConsoleReport = ConsoleReport; 12 | -------------------------------------------------------------------------------- /stats/build/reportTargets/HtmlReport.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | var fs_1 = __importDefault(require("fs")); 7 | var HtmlReport = /** @class */ (function () { 8 | function HtmlReport() { 9 | } 10 | HtmlReport.prototype.print = function (report) { 11 | var html = "\n
\n

Analysis Output

\n
" + report + "
\n
\n "; 12 | fs_1.default.writeFileSync('report.html', html); 13 | }; 14 | return HtmlReport; 15 | }()); 16 | exports.HtmlReport = HtmlReport; 17 | -------------------------------------------------------------------------------- /stats/build/utils.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.dateStringToDate = function (dateString) { 4 | var dateParts = dateString.split('/').map(function (value) { 5 | return parseInt(value); 6 | }); 7 | return new Date(dateParts[2], dateParts[1] - 1, dateParts[0]); 8 | }; 9 | -------------------------------------------------------------------------------- /stats/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stats", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start:build": "tsc -w", 8 | "start:run": "nodemon build/index.js", 9 | "start": "concurrently npm:start:*" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "@types/node": "^12.0.2", 16 | "concurrently": "^4.1.0", 17 | "nodemon": "^1.19.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /stats/report.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

Analysis Output

4 |
Team Man United won 18 games
5 |
6 | -------------------------------------------------------------------------------- /stats/src/CsvFileReader.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | 3 | export class CsvFileReader { 4 | data: string[][] = []; 5 | 6 | constructor(public filename: string) {} 7 | 8 | read(): void { 9 | this.data = fs 10 | .readFileSync(this.filename, { 11 | encoding: 'utf-8' 12 | }) 13 | .split('\n') 14 | .map( 15 | (row: string): string[] => { 16 | return row.split(','); 17 | } 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /stats/src/MatchData.ts: -------------------------------------------------------------------------------- 1 | import { MatchResult } from './MatchResult'; 2 | 3 | export type MatchData = [ 4 | Date, 5 | string, 6 | string, 7 | number, 8 | number, 9 | MatchResult, 10 | string 11 | ]; 12 | -------------------------------------------------------------------------------- /stats/src/MatchReader.ts: -------------------------------------------------------------------------------- 1 | import { dateStringToDate } from './utils'; 2 | import { MatchResult } from './MatchResult'; 3 | import { MatchData } from './MatchData'; 4 | import { CsvFileReader } from './CsvFileReader'; 5 | 6 | interface DataReader { 7 | read(): void; 8 | data: string[][]; 9 | } 10 | 11 | export class MatchReader { 12 | static fromCsv(filename: string): MatchReader { 13 | return new MatchReader(new CsvFileReader(filename)); 14 | } 15 | 16 | matches: MatchData[] = []; 17 | 18 | constructor(public reader: DataReader) {} 19 | 20 | load(): void { 21 | this.reader.read(); 22 | this.matches = this.reader.data.map( 23 | (row: string[]): MatchData => { 24 | return [ 25 | dateStringToDate(row[0]), 26 | row[1], 27 | row[2], 28 | parseInt(row[3]), 29 | parseInt(row[4]), 30 | row[5] as MatchResult, 31 | row[6] 32 | ]; 33 | } 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /stats/src/MatchResult.ts: -------------------------------------------------------------------------------- 1 | // enum - enumeration 2 | export enum MatchResult { 3 | HomeWin = 'H', 4 | AwayWin = 'A', 5 | Draw = 'D' 6 | } 7 | -------------------------------------------------------------------------------- /stats/src/Summary.ts: -------------------------------------------------------------------------------- 1 | import { MatchData } from './MatchData'; 2 | import { WinsAnalysis } from './analyzers/WinsAnalysis'; 3 | import { HtmlReport } from './reportTargets/HtmlReport'; 4 | 5 | export interface Analyzer { 6 | run(matches: MatchData[]): string; 7 | } 8 | 9 | export interface OutputTarget { 10 | print(report: string): void; 11 | } 12 | 13 | export class Summary { 14 | static winsAnalysisWithHtmlReport(team: string): Summary { 15 | return new Summary(new WinsAnalysis(team), new HtmlReport()); 16 | } 17 | 18 | constructor(public analyzer: Analyzer, public outputTarget: OutputTarget) {} 19 | 20 | buildAndPrintReport(matches: MatchData[]): void { 21 | const output = this.analyzer.run(matches); 22 | this.outputTarget.print(output); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /stats/src/analyzers/WinsAnalysis.ts: -------------------------------------------------------------------------------- 1 | import { Analyzer } from '../Summary'; 2 | import { MatchData } from '../MatchData'; 3 | import { MatchResult } from '../MatchResult'; 4 | 5 | export class WinsAnalysis implements Analyzer { 6 | constructor(public team: string) {} 7 | 8 | run(matches: MatchData[]): string { 9 | let wins = 0; 10 | 11 | for (let match of matches) { 12 | if (match[1] === 'Man United' && match[5] === MatchResult.HomeWin) { 13 | wins++; 14 | } else if ( 15 | match[2] === 'Man United' && 16 | match[5] === MatchResult.AwayWin 17 | ) { 18 | wins++; 19 | } 20 | } 21 | 22 | return `Team ${this.team} won ${wins} games`; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /stats/src/index.ts: -------------------------------------------------------------------------------- 1 | import { MatchReader } from './MatchReader'; 2 | import { Summary } from './Summary'; 3 | 4 | const matchReader = MatchReader.fromCsv('football.csv'); 5 | const summary = Summary.winsAnalysisWithHtmlReport('Man United'); 6 | 7 | matchReader.load(); 8 | summary.buildAndPrintReport(matchReader.matches); 9 | -------------------------------------------------------------------------------- /stats/src/inheritance/CsvFileReader.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | 3 | export abstract class CsvFileReader { 4 | data: T[] = []; 5 | 6 | constructor(public filename: string) {} 7 | 8 | abstract mapRow(row: string[]): T; 9 | 10 | read(): void { 11 | this.data = fs 12 | .readFileSync(this.filename, { 13 | encoding: 'utf-8' 14 | }) 15 | .split('\n') 16 | .map( 17 | (row: string): string[] => { 18 | return row.split(','); 19 | } 20 | ) 21 | .map(this.mapRow); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /stats/src/inheritance/MatchReader.ts: -------------------------------------------------------------------------------- 1 | import { CsvFileReader } from './CsvFileReader'; 2 | import { dateStringToDate } from './utils'; 3 | import { MatchResult } from './MatchResult'; 4 | 5 | type MatchData = [Date, string, string, number, number, MatchResult, string]; 6 | 7 | export class MatchReader extends CsvFileReader { 8 | mapRow(row: string[]): MatchData { 9 | return [ 10 | dateStringToDate(row[0]), 11 | row[1], 12 | row[2], 13 | parseInt(row[3]), 14 | parseInt(row[4]), 15 | row[5] as MatchResult, 16 | row[6] 17 | ]; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /stats/src/reportTargets/ConsoleReport.ts: -------------------------------------------------------------------------------- 1 | import { OutputTarget } from '../Summary'; 2 | 3 | export class ConsoleReport implements OutputTarget { 4 | print(report: string): void { 5 | console.log(report); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /stats/src/reportTargets/HtmlReport.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import { OutputTarget } from '../Summary'; 3 | 4 | export class HtmlReport implements OutputTarget { 5 | print(report: string): void { 6 | const html = ` 7 |
8 |

Analysis Output

9 |
${report}
10 |
11 | `; 12 | 13 | fs.writeFileSync('report.html', html); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /stats/src/utils.ts: -------------------------------------------------------------------------------- 1 | export const dateStringToDate = (dateString: string): Date => { 2 | const dateParts = dateString.split('/').map( 3 | (value: string): number => { 4 | return parseInt(value); 5 | } 6 | ); 7 | 8 | return new Date(dateParts[2], dateParts[1] - 1, dateParts[0]); 9 | }; 10 | -------------------------------------------------------------------------------- /stats/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, 5 | "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, 6 | // "lib": [], /* Specify library files to be included in the compilation. */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | "outDir": "./build" /* Redirect output structure to the directory. */, 15 | "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, 16 | // "composite": true, /* Enable project compilation */ 17 | // "incremental": true, /* Enable incremental compilation */ 18 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 19 | // "removeComments": true, /* Do not emit comments to output. */ 20 | // "noEmit": true, /* Do not emit outputs. */ 21 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 22 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 23 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 24 | 25 | /* Strict Type-Checking Options */ 26 | "strict": true /* Enable all strict type-checking options. */, 27 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 28 | // "strictNullChecks": true, /* Enable strict null checks. */ 29 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 30 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 31 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 32 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 33 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 34 | 35 | /* Additional Checks */ 36 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 37 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 38 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 39 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 40 | 41 | /* Module Resolution Options */ 42 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 43 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 44 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 45 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 46 | // "typeRoots": [], /* List of folders to include type definitions from. */ 47 | // "types": [], /* Type declaration files to be included in compilation. */ 48 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 49 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 50 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 51 | 52 | /* Source Map Options */ 53 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 54 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 55 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 56 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 57 | 58 | /* Experimental Options */ 59 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 60 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /web/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "users": [ 3 | { 4 | "id": 1, 5 | "name": "User #1", 6 | "age": 0 7 | }, 8 | { 9 | "name": "Bill", 10 | "age": 10, 11 | "id": 2 12 | }, 13 | { 14 | "name": "Jill", 15 | "age": 20, 16 | "id": 3 17 | }, 18 | { 19 | "name": "new record", 20 | "age": 0, 21 | "id": 4 22 | }, 23 | { 24 | "name": "new record", 25 | "age": 0, 26 | "id": 5 27 | }, 28 | { 29 | "name": "new record", 30 | "age": 0, 31 | "id": 6 32 | }, 33 | { 34 | "name": "NAME", 35 | "age": 20, 36 | "id": 7 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /web/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "axios": { 6 | "version": "0.18.0", 7 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", 8 | "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", 9 | "requires": { 10 | "follow-redirects": "^1.3.0", 11 | "is-buffer": "^1.1.5" 12 | }, 13 | "dependencies": { 14 | "is-buffer": { 15 | "version": "1.1.6", 16 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 17 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 18 | } 19 | } 20 | }, 21 | "debug": { 22 | "version": "3.2.6", 23 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 24 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 25 | "requires": { 26 | "ms": "^2.1.1" 27 | } 28 | }, 29 | "follow-redirects": { 30 | "version": "1.7.0", 31 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", 32 | "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", 33 | "requires": { 34 | "debug": "^3.2.6" 35 | } 36 | }, 37 | "ms": { 38 | "version": "2.1.1", 39 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 40 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 41 | }, 42 | "typescript": { 43 | "version": "3.4.5", 44 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.5.tgz", 45 | "integrity": "sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==", 46 | "dev": true 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "typescript": "^3.4.5" 4 | }, 5 | "dependencies": { 6 | "axios": "^0.18.0" 7 | }, 8 | "scripts": { 9 | "start:db": "json-server -w db.json", 10 | "start:parcel": "parcel index.html" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /web/src/index.ts: -------------------------------------------------------------------------------- 1 | import { UserList } from './views/UserList'; 2 | import { Collection } from './models/Collection'; 3 | import { UserProps, User } from './models/User'; 4 | 5 | const users = new Collection( 6 | 'http://localhost:3000/users', 7 | (json: UserProps) => { 8 | return User.buildUser(json); 9 | } 10 | ); 11 | 12 | users.on('change', () => { 13 | const root = document.getElementById('root'); 14 | 15 | if (root) { 16 | new UserList(root, users).render(); 17 | } 18 | }); 19 | 20 | users.fetch(); 21 | -------------------------------------------------------------------------------- /web/src/models/ApiSync.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosPromise } from 'axios'; 2 | 3 | interface HasId { 4 | id?: number; 5 | } 6 | 7 | export class ApiSync { 8 | constructor(public rootUrl: string) {} 9 | 10 | fetch(id: number): AxiosPromise { 11 | return axios.get(`${this.rootUrl}/${id}`); 12 | } 13 | 14 | save(data: T): AxiosPromise { 15 | const { id } = data; 16 | 17 | if (id) { 18 | return axios.put(`${this.rootUrl}/${id}`, data); 19 | } else { 20 | return axios.post(this.rootUrl, data); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /web/src/models/Attributes.ts: -------------------------------------------------------------------------------- 1 | export class Attributes { 2 | constructor(private data: T) {} 3 | 4 | get = (key: K): T[K] => { 5 | return this.data[key]; 6 | }; 7 | 8 | set(update: T): void { 9 | Object.assign(this.data, update); 10 | } 11 | 12 | getAll(): T { 13 | return this.data; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /web/src/models/Collection.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosResponse } from 'axios'; 2 | import { Eventing } from './Eventing'; 3 | 4 | export class Collection { 5 | models: T[] = []; 6 | events: Eventing = new Eventing(); 7 | 8 | constructor(public rootUrl: string, public deserialize: (json: K) => T) {} 9 | 10 | get on() { 11 | return this.events.on; 12 | } 13 | 14 | get trigger() { 15 | return this.events.trigger; 16 | } 17 | 18 | fetch(): void { 19 | axios.get(this.rootUrl).then((response: AxiosResponse) => { 20 | response.data.forEach((value: K) => { 21 | this.models.push(this.deserialize(value)); 22 | }); 23 | 24 | this.trigger('change'); 25 | }); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /web/src/models/Eventing.ts: -------------------------------------------------------------------------------- 1 | type Callback = () => void; 2 | 3 | export class Eventing { 4 | events: { [key: string]: Callback[] } = {}; 5 | 6 | on = (eventName: string, callback: Callback): void => { 7 | const handlers = this.events[eventName] || []; 8 | handlers.push(callback); 9 | this.events[eventName] = handlers; 10 | }; 11 | 12 | trigger = (eventName: string): void => { 13 | const handlers = this.events[eventName]; 14 | 15 | if (!handlers || handlers.length === 0) { 16 | return; 17 | } 18 | 19 | handlers.forEach(callback => { 20 | callback(); 21 | }); 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /web/src/models/Model.ts: -------------------------------------------------------------------------------- 1 | import { AxiosPromise, AxiosResponse } from 'axios'; 2 | 3 | interface ModelAttributes { 4 | set(value: T): void; 5 | getAll(): T; 6 | get(key: K): T[K]; 7 | } 8 | 9 | interface Sync { 10 | fetch(id: number): AxiosPromise; 11 | save(data: T): AxiosPromise; 12 | } 13 | 14 | interface Events { 15 | on(eventName: string, callback: () => void): void; 16 | trigger(eventName: string): void; 17 | } 18 | 19 | interface HasId { 20 | id?: number; 21 | } 22 | 23 | export class Model { 24 | constructor( 25 | private attributes: ModelAttributes, 26 | private events: Events, 27 | private sync: Sync 28 | ) {} 29 | 30 | on = this.events.on; 31 | trigger = this.events.trigger; 32 | get = this.attributes.get; 33 | 34 | set(update: T): void { 35 | this.attributes.set(update); 36 | this.events.trigger('change'); 37 | } 38 | 39 | fetch(): void { 40 | const id = this.get('id'); 41 | 42 | if (typeof id !== 'number') { 43 | throw new Error('Cannot fetch without an id'); 44 | } 45 | 46 | this.sync.fetch(id).then( 47 | (response: AxiosResponse): void => { 48 | this.set(response.data); 49 | } 50 | ); 51 | } 52 | 53 | save(): void { 54 | this.sync 55 | .save(this.attributes.getAll()) 56 | .then( 57 | (response: AxiosResponse): void => { 58 | this.trigger('save'); 59 | } 60 | ) 61 | .catch(() => { 62 | this.trigger('error'); 63 | }); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /web/src/models/User.ts: -------------------------------------------------------------------------------- 1 | import { Model } from './Model'; 2 | import { Attributes } from './Attributes'; 3 | import { ApiSync } from './ApiSync'; 4 | import { Eventing } from './Eventing'; 5 | import { Collection } from './Collection'; 6 | 7 | export interface UserProps { 8 | id?: number; 9 | name?: string; 10 | age?: number; 11 | } 12 | 13 | const rootUrl = 'http://localhost:3000/users'; 14 | 15 | export class User extends Model { 16 | static buildUser(attrs: UserProps): User { 17 | return new User( 18 | new Attributes(attrs), 19 | new Eventing(), 20 | new ApiSync(rootUrl) 21 | ); 22 | } 23 | 24 | static buildUserCollection(): Collection { 25 | return new Collection(rootUrl, (json: UserProps) => 26 | User.buildUser(json) 27 | ); 28 | } 29 | 30 | setRandomAge(): void { 31 | const age = Math.round(Math.random() * 100); 32 | this.set({ age }); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /web/src/views/CollectionView.ts: -------------------------------------------------------------------------------- 1 | import { Collection } from '../models/Collection'; 2 | 3 | export abstract class CollectionView { 4 | constructor(public parent: Element, public collection: Collection) {} 5 | 6 | abstract renderItem(model: T, itemParent: Element): void; 7 | 8 | render(): void { 9 | this.parent.innerHTML = ''; 10 | 11 | const templateElement = document.createElement('template'); 12 | 13 | for (let model of this.collection.models) { 14 | const itemParent = document.createElement('div'); 15 | this.renderItem(model, itemParent); 16 | templateElement.content.append(itemParent); 17 | } 18 | 19 | this.parent.append(templateElement.content); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /web/src/views/UserEdit.ts: -------------------------------------------------------------------------------- 1 | import { View } from './View'; 2 | import { User, UserProps } from '../models/User'; 3 | import { UserForm } from './UserForm'; 4 | import { UserShow } from './UserShow'; 5 | 6 | export class UserEdit extends View { 7 | regionsMap(): { [key: string]: string } { 8 | return { 9 | userShow: '.user-show', 10 | userForm: '.user-form' 11 | }; 12 | } 13 | 14 | onRender(): void { 15 | new UserShow(this.regions.userShow, this.model).render(); 16 | new UserForm(this.regions.userForm, this.model).render(); 17 | } 18 | 19 | template(): string { 20 | return ` 21 |
22 |
23 |
24 |
25 | `; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /web/src/views/UserForm.ts: -------------------------------------------------------------------------------- 1 | import { User, UserProps } from '../models/User'; 2 | import { View } from './View'; 3 | 4 | export class UserForm extends View { 5 | eventsMap(): { [key: string]: () => void } { 6 | return { 7 | 'click:.set-age': this.onSetAgeClick, 8 | 'click:.set-name': this.onSetNameClick, 9 | 'click:.save-model': this.onSaveClick 10 | }; 11 | } 12 | 13 | onSaveClick = (): void => { 14 | this.model.save(); 15 | }; 16 | 17 | onSetNameClick = (): void => { 18 | const input = this.parent.querySelector('input'); 19 | 20 | if (input) { 21 | const name = input.value; 22 | 23 | this.model.set({ name }); 24 | } 25 | }; 26 | 27 | onSetAgeClick = (): void => { 28 | this.model.setRandomAge(); 29 | }; 30 | 31 | template(): string { 32 | return ` 33 |
34 | 35 | 36 | 37 | 38 |
39 | `; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /web/src/views/UserList.ts: -------------------------------------------------------------------------------- 1 | import { CollectionView } from './CollectionView'; 2 | import { User, UserProps } from '../models/User'; 3 | import { UserShow } from './UserShow'; 4 | 5 | export class UserList extends CollectionView { 6 | renderItem(model: User, itemParent: Element): void { 7 | new UserShow(itemParent, model).render(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /web/src/views/UserShow.ts: -------------------------------------------------------------------------------- 1 | import { View } from './View'; 2 | import { User, UserProps } from '../models/User'; 3 | 4 | export class UserShow extends View { 5 | template(): string { 6 | return ` 7 |
8 |

User Detail

9 |
User Name: ${this.model.get('name')}
10 |
User Age: ${this.model.get('age')}
11 |
12 | `; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /web/src/views/View.ts: -------------------------------------------------------------------------------- 1 | import { Model } from '../models/Model'; 2 | 3 | export abstract class View, K> { 4 | regions: { [key: string]: Element } = {}; 5 | 6 | constructor(public parent: Element, public model: T) { 7 | this.bindModel(); 8 | } 9 | 10 | abstract template(): string; 11 | 12 | regionsMap(): { [key: string]: string } { 13 | return {}; 14 | } 15 | 16 | eventsMap(): { [key: string]: () => void } { 17 | return {}; 18 | } 19 | 20 | bindModel(): void { 21 | this.model.on('change', () => { 22 | this.render(); 23 | }); 24 | } 25 | 26 | bindEvents(fragment: DocumentFragment): void { 27 | const eventsMap = this.eventsMap(); 28 | 29 | for (let eventKey in eventsMap) { 30 | const [eventName, selector] = eventKey.split(':'); 31 | 32 | fragment.querySelectorAll(selector).forEach(element => { 33 | element.addEventListener(eventName, eventsMap[eventKey]); 34 | }); 35 | } 36 | } 37 | 38 | mapRegions(fragment: DocumentFragment): void { 39 | const regionsMap = this.regionsMap(); 40 | 41 | for (let key in regionsMap) { 42 | const selector = regionsMap[key]; 43 | const element = fragment.querySelector(selector); 44 | 45 | if (element) { 46 | this.regions[key] = element; 47 | } 48 | } 49 | } 50 | 51 | onRender(): void {} 52 | 53 | render(): void { 54 | this.parent.innerHTML = ''; 55 | 56 | const templateElement = document.createElement('template'); 57 | templateElement.innerHTML = this.template(); 58 | 59 | this.bindEvents(templateElement.content); 60 | this.mapRegions(templateElement.content); 61 | 62 | this.onRender(); 63 | 64 | this.parent.append(templateElement.content); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | // "lib": [], /* Specify library files to be included in the compilation. */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | // "outDir": "./", /* Redirect output structure to the directory. */ 15 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 16 | // "composite": true, /* Enable project compilation */ 17 | // "incremental": true, /* Enable incremental compilation */ 18 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 19 | // "removeComments": true, /* Do not emit comments to output. */ 20 | // "noEmit": true, /* Do not emit outputs. */ 21 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 22 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 23 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 24 | 25 | /* Strict Type-Checking Options */ 26 | "strict": true, /* Enable all strict type-checking options. */ 27 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 28 | // "strictNullChecks": true, /* Enable strict null checks. */ 29 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 30 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 31 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 32 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 33 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 34 | 35 | /* Additional Checks */ 36 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 37 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 38 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 39 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 40 | 41 | /* Module Resolution Options */ 42 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 43 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 44 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 45 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 46 | // "typeRoots": [], /* List of folders to include type definitions from. */ 47 | // "types": [], /* Type declaration files to be included in compilation. */ 48 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 49 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 50 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 51 | 52 | /* Source Map Options */ 53 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 54 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 55 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 56 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 57 | 58 | /* Experimental Options */ 59 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 60 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 61 | } 62 | } 63 | --------------------------------------------------------------------------------