From d74e547682cfc45d36cd3b033e011d5a2dda0ff4 Mon Sep 17 00:00:00 2001 From: Alex Anderson Date: Mon, 14 Dec 2020 14:11:14 -0500 Subject: [PATCH 1/3] Add TypeScript Configuration. --- package-lock.json | 260 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 7 +- tsconfig.json | 71 +++++++++++++ webpack.config.js | 38 +++---- 4 files changed, 356 insertions(+), 20 deletions(-) create mode 100644 tsconfig.json diff --git a/package-lock.json b/package-lock.json index 689842b..0a18e2a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "github-battle", + "name": "github-battle-hooks", "version": "1.0.0", "lockfileVersion": 1, "requires": true, @@ -252,6 +252,18 @@ "@babel/types": "^7.4.4" } }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz", + "integrity": "sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A==", + "dev": true + }, "@babel/helper-wrap-function": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", @@ -418,6 +430,23 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, + "@babel/plugin-syntax-typescript": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.12.1.tgz", + "integrity": "sha512-UZNEcCY+4Dp9yYRCAHrHDU+9ZXLYaY9MgBXSRLkB9WjYFRR6quJBumfVrEkUxrePPBwFcpWfNKXqVRQQtm7mMA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + } + } + }, "@babel/plugin-transform-arrow-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", @@ -755,6 +784,179 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, + "@babel/plugin-transform-typescript": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.12.1.tgz", + "integrity": "sha512-VrsBByqAIntM+EYMqSm59SiMEf7qkmI9dqMt6RbD/wlwueWmYcI0FFK5Fj47pP6DRZm+3teXjosKlwcZJ5lIMw==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-typescript": "^7.12.1" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/generator": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.10.tgz", + "integrity": "sha512-6mCdfhWgmqLdtTkhXjnIz0LcdVCd26wS2JXRtj2XY0u5klDsXBREA/pG5NVOuVnF2LUrBGNFtQkIqqTbblg0ww==", + "dev": true, + "requires": { + "@babel/types": "^7.12.10", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz", + "integrity": "sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-member-expression-to-functions": "^7.12.1", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-replace-supers": "^7.12.1", + "@babel/helper-split-export-declaration": "^7.10.4" + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz", + "integrity": "sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag==", + "dev": true, + "requires": { + "@babel/types": "^7.12.10" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz", + "integrity": "sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw==", + "dev": true, + "requires": { + "@babel/types": "^7.12.7" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz", + "integrity": "sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ==", + "dev": true, + "requires": { + "@babel/types": "^7.12.10" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + }, + "@babel/helper-replace-supers": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz", + "integrity": "sha512-5YILoed0ZyIpF4gKcpZitEnXEJ9UoDRki1Ey6xz46rxOzfNMAhVIJMoune1hmPVxh40LRv1+oafz7UsWX+vyWA==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.12.1", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.12.5", + "@babel/types": "^7.12.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.10.tgz", + "integrity": "sha512-PJdRPwyoOqFAWfLytxrWwGrAxghCgh/yTNCYciOz8QgjflA7aZhECPZAa2VUedKg2+QMWkI0L9lynh2SNmNEgA==", + "dev": true + }, + "@babel/template": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz", + "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.12.7", + "@babel/types": "^7.12.7" + } + }, + "@babel/traverse": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.10.tgz", + "integrity": "sha512-6aEtf0IeRgbYWzta29lePeYSk+YAFIC3kyqESeft8o5CkFlYIMX+EQDDWEiAQ9LHOA3d0oHdgrSsID/CKqXJlg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.10", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.12.10", + "@babel/types": "^7.12.10", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + } + }, + "@babel/types": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.10.tgz", + "integrity": "sha512-sf6wboJV5mGyip2hIpDSKsr80RszPinEFjsHTalMxZAZkoQ2/2yQzxlcFN52SJqsyPfLtPmenL4g2KB3KJXPDw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } + } + }, "@babel/plugin-transform-unicode-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz", @@ -837,6 +1039,25 @@ "@babel/plugin-transform-react-jsx-source": "^7.0.0" } }, + "@babel/preset-typescript": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.12.7.tgz", + "integrity": "sha512-nOoIqIqBmHBSEgBXWR4Dv/XBehtIFcw9PqZw6rFYuKrzsZmOQm3PR5siLBnKZFEsDb03IegG8nSjU/iXXXYRmw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-validator-option": "^7.12.1", + "@babel/plugin-transform-typescript": "^7.12.1" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + } + } + }, "@babel/runtime": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.5.tgz", @@ -913,6 +1134,31 @@ "integrity": "sha512-aX+gFgA5GHcDi89KG5keey2zf0WfZk/HAQotEamsK2kbey+8yGKcson0hbK8E+v0NArlCJQCqMP161YhV6ZXLg==", "dev": true }, + "@types/prop-types": { + "version": "15.7.3", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", + "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==", + "dev": true + }, + "@types/react": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.0.tgz", + "integrity": "sha512-aj/L7RIMsRlWML3YB6KZiXB3fV2t41+5RBGYF8z+tAKU43Px8C3cYUZsDvf1/+Bm4FK21QWBrDutu8ZJ/70qOw==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-dom": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.0.tgz", + "integrity": "sha512-lUqY7OlkF/RbNtD5nIq7ot8NquXrdFrjSOR6+w9a9RFQevGi1oZO1dcJbXMeONAPKtZ2UrZOEJ5UOCVsxbLk/g==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, "@webassemblyjs/ast": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", @@ -2206,6 +2452,12 @@ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true }, + "csstype": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.5.tgz", + "integrity": "sha512-uVDi8LpBUKQj6sdxNaTetL6FpeCqTjOvAQuQUa/qAqq8oOd4ivkbhgnqayl0dnPal8Tb/yB1tF+gOvCBiicaiQ==", + "dev": true + }, "cyclist": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", @@ -6858,6 +7110,12 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "typescript": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", + "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", + "dev": true + }, "uglify-js": { "version": "3.4.10", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", diff --git a/package.json b/package.json index 7f9e7c3..fa051f2 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "babel": { "presets": [ "@babel/preset-env", - "@babel/preset-react" + "@babel/preset-react", + "@babel/preset-typescript" ], "plugins": [ "@babel/plugin-proposal-class-properties", @@ -34,12 +35,16 @@ "@babel/plugin-proposal-class-properties": "^7.5.5", "@babel/preset-env": "^7.5.5", "@babel/preset-react": "^7.0.0", + "@babel/preset-typescript": "^7.12.7", + "@types/react": "^17.0.0", + "@types/react-dom": "^17.0.0", "babel-loader": "^8.0.6", "babel-plugin-syntax-dynamic-import": "^6.18.0", "copy-webpack-plugin": "^5.0.3", "css-loader": "^3.1.0", "html-webpack-plugin": "^3.2.0", "style-loader": "^0.23.1", + "typescript": "^4.1.3", "webpack": "^4.36.1", "webpack-cli": "^3.3.6", "webpack-dev-server": "^3.7.2" diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..ff47636 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,71 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "ESNext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + "lib": ["DOM","ESNext"], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + "jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + // "outDir": "./", /* Redirect output structure to the directory. */ + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true, /* Skip type checking of declaration files. */ + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + }, + "include": ["app/**/*"] +} diff --git a/webpack.config.js b/webpack.config.js index b376c52..7aa6055 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,30 +1,32 @@ -const path = require('path') -const HtmlWebpackPlugin = require('html-webpack-plugin') -const CopyPlugin = require('copy-webpack-plugin') +const path = require("path"); +const HtmlWebpackPlugin = require("html-webpack-plugin"); +const CopyPlugin = require("copy-webpack-plugin"); module.exports = { - entry: './app/index.js', + entry: "./app/index.tsx", output: { - path: path.resolve(__dirname, 'dist'), - filename: 'index_bundle.js', - publicPath: '/' + path: path.resolve(__dirname, "dist"), + filename: "index_bundle.js", + publicPath: "/", + }, + resolve: { + // Add `.ts` and `.tsx` as a resolvable extension. + extensions: [".ts", ".tsx", ".js"], }, module: { rules: [ - { test: /\.(js)$/, use: 'babel-loader' }, - { test: /\.css$/, use: [ 'style-loader', 'css-loader' ]} - ] + { test: /\.(js|ts|tsx)$/, use: "babel-loader" }, + { test: /\.css$/, use: ["style-loader", "css-loader"] }, + ], }, - mode: process.env.NODE_ENV === 'production' ? 'production' : 'development', + mode: process.env.NODE_ENV === "production" ? "production" : "development", plugins: [ new HtmlWebpackPlugin({ - template: 'app/index.html' + template: "app/index.html", }), - new CopyPlugin([ - { from : '_redirects' } - ]) + new CopyPlugin([{ from: "_redirects" }]), ], devServer: { - historyApiFallback: true - } -} \ No newline at end of file + historyApiFallback: true, + }, +}; From 131c4ea98c255bcfe5b6256ceb6c18e5bbdb0070 Mon Sep 17 00:00:00 2001 From: Alex Anderson Date: Mon, 14 Dec 2020 14:11:58 -0500 Subject: [PATCH 2/3] Convert the API file to TypeScript --- app/utils/api.js | 78 -------------------------------------- app/utils/api.ts | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 78 deletions(-) delete mode 100644 app/utils/api.js create mode 100644 app/utils/api.ts diff --git a/app/utils/api.js b/app/utils/api.js deleted file mode 100644 index 080865b..0000000 --- a/app/utils/api.js +++ /dev/null @@ -1,78 +0,0 @@ -const id = "YOUR_CLIENT_ID" -const sec = "YOUR_SECRET_ID" -const params = `?client_id=${id}&client_secret=${sec}` - -function getErrorMsg (message, username) { - if (message === 'Not Found') { - return `${username} doesn't exist` - } - - return message -} - -function getProfile (username) { - return fetch(`https://api.github.com/users/${username}${params}`) - .then((res) => res.json()) - .then((profile) => { - if (profile.message) { - throw new Error(getErrorMsg(profile.message, username)) - } - - return profile - }) -} - -function getRepos (username) { - return fetch(`https://api.github.com/users/${username}/repos${params}&per_page=100`) - .then((res) => res.json()) - .then((repos) => { - if (repos.message) { - throw new Error(getErrorMsg(repos.message, username)) - } - - return repos - }) -} - -function getStarCount (repos) { - return repos.reduce((count, { stargazers_count }) => count + stargazers_count , 0) -} - -function calculateScore (followers, repos) { - return (followers * 3) + getStarCount(repos) -} - -function getUserData (player) { - return Promise.all([ - getProfile(player), - getRepos(player) - ]).then(([ profile, repos ]) => ({ - profile, - score: calculateScore(profile.followers, repos) - })) -} - -function sortPlayers (players) { - return players.sort((a, b) => b.score - a.score) -} - -export function battle (players) { - return Promise.all([ - getUserData(players[0]), - getUserData(players[1]) - ]).then((results) => sortPlayers(results)) -} - -export function fetchPopularRepos (language) { - const endpoint = window.encodeURI(`https://api.github.com/search/repositories?q=stars:>1+language:${language}&sort=stars&order=desc&type=Repositories`) - - return fetch(endpoint) - .then((res) => res.json()) - .then((data) => { - if (!data.items) { - throw new Error(data.message) - } - - return data.items - }) -} \ No newline at end of file diff --git a/app/utils/api.ts b/app/utils/api.ts new file mode 100644 index 0000000..8f4ec77 --- /dev/null +++ b/app/utils/api.ts @@ -0,0 +1,97 @@ +const id = "YOUR_CLIENT_ID"; +const sec = "YOUR_SECRET_ID"; +const params = `?client_id=${id}&client_secret=${sec}`; + +function getErrorMsg(message: string, username: string) { + if (message === "Not Found") { + return `${username} doesn't exist`; + } + + return message; +} + +export interface User { + id: string; + followers: number; +} +function getProfile(username: string): Promise { + return fetch(`https://api.github.com/users/${username}${params}`) + .then((res) => res.json()) + .then((profile) => { + if (profile.message) { + throw new Error(getErrorMsg(profile.message, username)); + } + + return profile; + }); +} + +export interface Repo { + id: string; + stargazers_count: number; +} + +function getRepos(username: string): Promise { + return fetch( + `https://api.github.com/users/${username}/repos${params}&per_page=100` + ) + .then((res) => res.json()) + .then((repos) => { + if (repos.message) { + throw new Error(getErrorMsg(repos.message, username)); + } + + return repos; + }); +} + +function getStarCount(repos: Repo[]) { + return repos.reduce( + (count, { stargazers_count }) => count + stargazers_count, + 0 + ); +} + +function calculateScore(followers: number, repos: Repo[]) { + return followers * 3 + getStarCount(repos); +} + +export interface Player { + profile: User; + score: number; +} +function getUserData(player: string): Promise { + return Promise.all([getProfile(player), getRepos(player)]).then( + ([profile, repos]) => ({ + profile, + score: calculateScore(profile.followers, repos), + }) + ); +} + +function sortPlayers(players: [Player, Player]) { + return players.sort((a, b) => b.score - a.score); +} + +export function battle(players: [string, string]) { + return Promise.all([ + getUserData(players[0]), + getUserData(players[1]), + ]).then((results) => sortPlayers(results)); +} + +export function fetchPopularRepos(language: string): Promise { + const endpoint = window.encodeURI( + `https://api.github.com/search/repositories?q=stars:>1+language:${language}&sort=stars&order=desc&type=Repositories` + ); + + return fetch(endpoint) + .then((res) => res.json()) + .then((data) => { + if (!data.items) { + throw new Error(data.message); + } + + return data.items; + }); +} From e64a42d0140bb2bc7ce72d9ca727173ad6c04553 Mon Sep 17 00:00:00 2001 From: Alex Anderson Date: Mon, 14 Dec 2020 14:18:46 -0500 Subject: [PATCH 3/3] Convert useHover, Tooltip, and theme context to TypeScript --- app/components/Tooltip.js | 40 ---------------------- app/components/Tooltip.tsx | 46 ++++++++++++++++++++++++++ app/contexts/theme.js | 7 ---- app/contexts/theme.ts | 7 ++++ app/hooks/{useHover.js => useHover.ts} | 0 5 files changed, 53 insertions(+), 47 deletions(-) delete mode 100644 app/components/Tooltip.js create mode 100644 app/components/Tooltip.tsx delete mode 100644 app/contexts/theme.js create mode 100644 app/contexts/theme.ts rename app/hooks/{useHover.js => useHover.ts} (100%) diff --git a/app/components/Tooltip.js b/app/components/Tooltip.js deleted file mode 100644 index 09fce1e..0000000 --- a/app/components/Tooltip.js +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import useHover from '../hooks/useHover' - -const styles = { - container: { - position: 'relative', - display: 'flex' - }, - tooltip: { - boxSizing: 'border-box', - position: 'absolute', - width: '160px', - bottom: '100%', - left: '50%', - marginLeft: '-80px', - borderRadius: '3px', - backgroundColor: 'hsla(0, 0%, 20%, 0.9)', - padding: '7px', - marginBottom: '5px', - color: '#fff', - textAlign: 'center', - fontSize: '14px', - } -} - -export default function Tooltip ({ text, children }) { - const [hovering, attrs] = useHover() - - return ( -
- {hovering === true &&
{text}
} - {children} -
- ) -} - -Tooltip.propTypes = { - text: PropTypes.string.isRequired, -} \ No newline at end of file diff --git a/app/components/Tooltip.tsx b/app/components/Tooltip.tsx new file mode 100644 index 0000000..10523f7 --- /dev/null +++ b/app/components/Tooltip.tsx @@ -0,0 +1,46 @@ +import React, { CSSProperties, ReactNode } from "react"; +import PropTypes from "prop-types"; +import useHover from "../hooks/useHover"; + +const styles = { + container: { + position: "relative", + display: "flex", + } as CSSProperties, + tooltip: { + boxSizing: "border-box", + position: "absolute", + width: "160px", + bottom: "100%", + left: "50%", + marginLeft: "-80px", + borderRadius: "3px", + backgroundColor: "hsla(0, 0%, 20%, 0.9)", + padding: "7px", + marginBottom: "5px", + color: "#fff", + textAlign: "center", + fontSize: "14px", + } as CSSProperties, +}; + +export default function Tooltip({ + text, + children, +}: { + text: ReactNode; + children: ReactNode; +}) { + const [hovering, attrs] = useHover(); + + return ( +
+ {hovering === true &&
{text}
} + {children} +
+ ); +} + +Tooltip.propTypes = { + text: PropTypes.string.isRequired, +}; diff --git a/app/contexts/theme.js b/app/contexts/theme.js deleted file mode 100644 index 9373368..0000000 --- a/app/contexts/theme.js +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react' - -const ThemeContext = React.createContext() - -export default ThemeContext -export const ThemeConsumer = ThemeContext.Consumer -export const ThemeProvider = ThemeContext.Provider diff --git a/app/contexts/theme.ts b/app/contexts/theme.ts new file mode 100644 index 0000000..5f3a2b9 --- /dev/null +++ b/app/contexts/theme.ts @@ -0,0 +1,7 @@ +import React from "react"; + +const ThemeContext = React.createContext("light"); + +export default ThemeContext; +export const ThemeConsumer = ThemeContext.Consumer; +export const ThemeProvider = ThemeContext.Provider; diff --git a/app/hooks/useHover.js b/app/hooks/useHover.ts similarity index 100% rename from app/hooks/useHover.js rename to app/hooks/useHover.ts