├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── src ├── index.ts └── subscriber.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | .env 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Real-Time Redis-Driven WebSocket Hub 2 | ![image](https://github.com/skushagra9/RedisWS-Hub/assets/120712705/1eda5867-b401-4e0a-94ca-55ad95b43ce2) 3 | 4 | ## Overview 5 | This project implements a WebSocket server that allows users to connect and send their user IDs without authentication. The WebSocket server is integrated with Redis to subscribe to a pub/sub channel, enabling real-time communication and event broadcasting to relevant users. 6 | 7 | ## Features 8 | - WebSocket server for real-time communication 9 | - Redis integration for pub/sub messaging 10 | - Simple user ID identification without authentication 11 | - Event-based communication to relevant users 12 | 13 | ## Technologies Used 14 | - Node.js for the WebSocket server 15 | - Redis for pub/sub messaging 16 | - JavaScript for scripting 17 | - GitHub for version control and collaboration 18 | 19 | ## Setup 20 | 1. Clone the repository from GitHub. 21 | 2. Install the necessary dependencies using npm. 22 | 3. Configure Redis connection details in the server script. 23 | 4. Start the WebSocket server using Node.js. 24 | 5. Connect clients to the WebSocket server and send user IDs to initiate communication. 25 | 26 | ## Usage 27 | - Users can connect to the WebSocket server and send their user IDs. 28 | - The server subscribes to Redis pub/sub channels for incoming messages. 29 | - Upon receiving messages from users, the server broadcasts relevant events to connected clients based on user IDs. 30 | 31 | ## Contribution 32 | Contributions are welcome! Fork the repository, make your changes, and submit a pull request for review. 33 | 34 | ## License 35 | This project is licensed under the MIT License - see the LICENSE.md file for details. 36 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "websockets", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "websockets", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "@types/uuid": "^9.0.8", 13 | "@types/ws": "^8.5.10", 14 | "redis": "^4.6.13", 15 | "typescript": "^5.4.4", 16 | "uuid": "^9.0.1", 17 | "ws": "^8.16.0" 18 | } 19 | }, 20 | "node_modules/@redis/bloom": { 21 | "version": "1.2.0", 22 | "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", 23 | "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", 24 | "peerDependencies": { 25 | "@redis/client": "^1.0.0" 26 | } 27 | }, 28 | "node_modules/@redis/client": { 29 | "version": "1.5.14", 30 | "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.14.tgz", 31 | "integrity": "sha512-YGn0GqsRBFUQxklhY7v562VMOP0DcmlrHHs3IV1mFE3cbxe31IITUkqhBcIhVSI/2JqtWAJXg5mjV4aU+zD0HA==", 32 | "dependencies": { 33 | "cluster-key-slot": "1.1.2", 34 | "generic-pool": "3.9.0", 35 | "yallist": "4.0.0" 36 | }, 37 | "engines": { 38 | "node": ">=14" 39 | } 40 | }, 41 | "node_modules/@redis/graph": { 42 | "version": "1.1.1", 43 | "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz", 44 | "integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==", 45 | "peerDependencies": { 46 | "@redis/client": "^1.0.0" 47 | } 48 | }, 49 | "node_modules/@redis/json": { 50 | "version": "1.0.6", 51 | "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.6.tgz", 52 | "integrity": "sha512-rcZO3bfQbm2zPRpqo82XbW8zg4G/w4W3tI7X8Mqleq9goQjAGLL7q/1n1ZX4dXEAmORVZ4s1+uKLaUOg7LrUhw==", 53 | "peerDependencies": { 54 | "@redis/client": "^1.0.0" 55 | } 56 | }, 57 | "node_modules/@redis/search": { 58 | "version": "1.1.6", 59 | "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.6.tgz", 60 | "integrity": "sha512-mZXCxbTYKBQ3M2lZnEddwEAks0Kc7nauire8q20oA0oA/LoA+E/b5Y5KZn232ztPb1FkIGqo12vh3Lf+Vw5iTw==", 61 | "peerDependencies": { 62 | "@redis/client": "^1.0.0" 63 | } 64 | }, 65 | "node_modules/@redis/time-series": { 66 | "version": "1.0.5", 67 | "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.5.tgz", 68 | "integrity": "sha512-IFjIgTusQym2B5IZJG3XKr5llka7ey84fw/NOYqESP5WUfQs9zz1ww/9+qoz4ka/S6KcGBodzlCeZ5UImKbscg==", 69 | "peerDependencies": { 70 | "@redis/client": "^1.0.0" 71 | } 72 | }, 73 | "node_modules/@types/node": { 74 | "version": "20.12.6", 75 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.6.tgz", 76 | "integrity": "sha512-3KurE8taB8GCvZBPngVbp0lk5CKi8M9f9k1rsADh0Evdz5SzJ+Q+Hx9uHoFGsLnLnd1xmkDQr2hVhlA0Mn0lKQ==", 77 | "dependencies": { 78 | "undici-types": "~5.26.4" 79 | } 80 | }, 81 | "node_modules/@types/uuid": { 82 | "version": "9.0.8", 83 | "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", 84 | "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==" 85 | }, 86 | "node_modules/@types/ws": { 87 | "version": "8.5.10", 88 | "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", 89 | "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", 90 | "dependencies": { 91 | "@types/node": "*" 92 | } 93 | }, 94 | "node_modules/cluster-key-slot": { 95 | "version": "1.1.2", 96 | "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", 97 | "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", 98 | "engines": { 99 | "node": ">=0.10.0" 100 | } 101 | }, 102 | "node_modules/generic-pool": { 103 | "version": "3.9.0", 104 | "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", 105 | "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", 106 | "engines": { 107 | "node": ">= 4" 108 | } 109 | }, 110 | "node_modules/redis": { 111 | "version": "4.6.13", 112 | "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.13.tgz", 113 | "integrity": "sha512-MHgkS4B+sPjCXpf+HfdetBwbRz6vCtsceTmw1pHNYJAsYxrfpOP6dz+piJWGos8wqG7qb3vj/Rrc5qOlmInUuA==", 114 | "workspaces": [ 115 | "./packages/*" 116 | ], 117 | "dependencies": { 118 | "@redis/bloom": "1.2.0", 119 | "@redis/client": "1.5.14", 120 | "@redis/graph": "1.1.1", 121 | "@redis/json": "1.0.6", 122 | "@redis/search": "1.1.6", 123 | "@redis/time-series": "1.0.5" 124 | } 125 | }, 126 | "node_modules/typescript": { 127 | "version": "5.4.4", 128 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", 129 | "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", 130 | "bin": { 131 | "tsc": "bin/tsc", 132 | "tsserver": "bin/tsserver" 133 | }, 134 | "engines": { 135 | "node": ">=14.17" 136 | } 137 | }, 138 | "node_modules/undici-types": { 139 | "version": "5.26.5", 140 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", 141 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" 142 | }, 143 | "node_modules/uuid": { 144 | "version": "9.0.1", 145 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", 146 | "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", 147 | "funding": [ 148 | "https://github.com/sponsors/broofa", 149 | "https://github.com/sponsors/ctavan" 150 | ], 151 | "bin": { 152 | "uuid": "dist/bin/uuid" 153 | } 154 | }, 155 | "node_modules/ws": { 156 | "version": "8.16.0", 157 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", 158 | "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", 159 | "engines": { 160 | "node": ">=10.0.0" 161 | }, 162 | "peerDependencies": { 163 | "bufferutil": "^4.0.1", 164 | "utf-8-validate": ">=5.0.2" 165 | }, 166 | "peerDependenciesMeta": { 167 | "bufferutil": { 168 | "optional": true 169 | }, 170 | "utf-8-validate": { 171 | "optional": true 172 | } 173 | } 174 | }, 175 | "node_modules/yallist": { 176 | "version": "4.0.0", 177 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 178 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "websockets", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "yarn tsc && node dist/index.js", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "@types/uuid": "^9.0.8", 15 | "@types/ws": "^8.5.10", 16 | "redis": "^4.6.13", 17 | "typescript": "^5.4.4", 18 | "uuid": "^9.0.1", 19 | "ws": "^8.16.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { WebSocketServer } from 'ws'; 2 | import http from 'http'; 3 | import { v4 as uuidv4 } from 'uuid'; 4 | import { RedisClient } from './subscriber'; 5 | 6 | const server = http.createServer(function(request: any, response: any) { 7 | console.log((new Date()) + ' Received request for ' + request.url); 8 | response.end("hi there"); 9 | }); 10 | 11 | const wss = new WebSocketServer({ server }); 12 | 13 | const users: { 14 | [key: string]: { 15 | room: string; 16 | ws: any; 17 | } 18 | } = {}; 19 | 20 | wss.on('connection', async function connection(ws) { 21 | const id = uuidv4() 22 | 23 | ws.on('error', console.error); 24 | 25 | ws.on('message', (message) => { 26 | const data = JSON.parse(message.toString()); 27 | if (data.type === "join") { 28 | users[id] = { 29 | room: data.payload.roomId, 30 | ws 31 | }; 32 | RedisClient.getInstance().subscribe(id, data.payload.roomId, ws); 33 | } 34 | 35 | if (data.type === "message") { 36 | const roomId = users[id].room; 37 | const message = data.payload.message; 38 | RedisClient.getInstance().publish(roomId, message); 39 | } 40 | 41 | }); 42 | 43 | ws.send(`Hello! Message From Server!!. id is ${id}`); 44 | 45 | ws.on('close', () => { 46 | console.log('Client disconnected'); 47 | RedisClient.getInstance().unsubscribe(id, users[id].room); 48 | }); 49 | 50 | }); 51 | server.listen(8080, function() { 52 | console.log((new Date()) + ' Server is listening on port 8080'); 53 | }); 54 | 55 | //v1 - what happening was the response was sent to all the users connected to the ws - now the response would only be sent to the person who has entered the message 56 | -------------------------------------------------------------------------------- /src/subscriber.ts: -------------------------------------------------------------------------------- 1 | import WebSocket from "ws"; 2 | import { createClient, RedisClientType } from "redis"; 3 | 4 | export class RedisClient { 5 | private static instance: RedisClient; 6 | private subscriber: RedisClientType; 7 | public publisher: RedisClientType; 8 | public subscriptions: Map 9 | public reverseSubscriptions: Map 10 | 11 | private constructor() { 12 | this.subscriber = createClient(); 13 | this.publisher = createClient(); 14 | this.publisher.connect() 15 | this.subscriber.connect() 16 | this.subscriptions = new Map 17 | this.reverseSubscriptions = new Map 18 | } 19 | 20 | static getInstance() { 21 | if (!this.instance) { 22 | this.instance = new RedisClient(); 23 | } 24 | return this.instance 25 | } 26 | 27 | subscribe(userId: string, room: string, ws: WebSocket) { 28 | this.subscriptions.set(userId, [ 29 | ...(this.subscriptions.get(userId) || []), 30 | room 31 | ]) 32 | this.reverseSubscriptions.set(room, { 33 | ...(this.reverseSubscriptions.get(room) || {}), 34 | [userId]: { userId, ws } 35 | }) 36 | 37 | if (Object.keys(this.reverseSubscriptions.get(room) || {}).length === 1) { 38 | console.log(`First User came, Now subscribing to the room - ${room}`) 39 | this.subscriber.subscribe(room, (payload) => { 40 | try { 41 | Object.values(this.reverseSubscriptions.get(room) || {}).forEach(({ ws }) => { 42 | ws.send(payload) 43 | }) 44 | } catch (e) { 45 | console.log('error in the payload') 46 | } 47 | }) 48 | } 49 | } 50 | 51 | unsubscribe(userId: string, roomToUnsubscribe: string) { 52 | this.subscriptions.set(userId, 53 | this.subscriptions.get(userId)?.filter((room) => room !== roomToUnsubscribe) || [] 54 | ) 55 | if (this.subscriptions.get(userId)?.length === 0) { 56 | this.subscriptions.delete(userId) 57 | } 58 | delete this.reverseSubscriptions.get(roomToUnsubscribe)?.[userId]; 59 | if (Object.keys(this.reverseSubscriptions.get(roomToUnsubscribe) || []).length === 0) { 60 | console.log(`Deleting this room - ${roomToUnsubscribe} as there are no users left inside it`) 61 | this.subscriber.unsubscribe(roomToUnsubscribe) 62 | this.reverseSubscriptions.delete(roomToUnsubscribe) 63 | } 64 | } 65 | 66 | publish(room: string, message: any) { 67 | console.log(`publishing message to ${room}`); 68 | this.publisher.publish(room, message); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | /* Projects */ 5 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 6 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 7 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 8 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 9 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 10 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 11 | /* Language and Environment */ 12 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 13 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 14 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 15 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ 16 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 17 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 18 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 19 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 20 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 21 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 22 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 23 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 24 | /* Modules */ 25 | "module": "commonjs", /* Specify what module code is generated. */ 26 | "rootDir": "./src", /* Specify the root folder within your source files. */ 27 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ 28 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 29 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 30 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 31 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 32 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 33 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 34 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 35 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ 36 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ 37 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ 38 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ 39 | // "resolveJsonModule": true, /* Enable importing .json files. */ 40 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ 41 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 42 | /* JavaScript Support */ 43 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 44 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 45 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 46 | /* Emit */ 47 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 48 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 49 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 50 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 51 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 52 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 53 | "outDir": "./dist", /* Specify an output folder for all emitted files. */ 54 | // "removeComments": true, /* Disable emitting comments. */ 55 | // "noEmit": true, /* Disable emitting files from a compilation. */ 56 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 57 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 58 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 59 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 60 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 61 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 62 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 63 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 64 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 65 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 66 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 67 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 68 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 69 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 70 | /* Interop Constraints */ 71 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 72 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ 73 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 74 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 75 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 76 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 77 | /* Type Checking */ 78 | "strict": true, /* Enable all strict type-checking options. */ 79 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 80 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 81 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 82 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 83 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 84 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 85 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 86 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 87 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 88 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 89 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 90 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 91 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 92 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 93 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 94 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 95 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 96 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 97 | /* Completeness */ 98 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 99 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 100 | } 101 | } 102 | --------------------------------------------------------------------------------