Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .github/workflows/test.yml-template
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Test

on:
pull_request:
branches: [ master ]

jobs:
build:

runs-on: ubuntu-latest

strategy:
matrix:
node-version: [20.x]

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test
24 changes: 24 additions & 0 deletions client/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line appears to contain only a single space character. That creates a gitignore pattern matching a space character filename (probably unintended). Remove this line to avoid unexpected behavior.

node_modules
dist
dist-ssr
*.local

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider explicitly ignoring environment files to prevent accidental commits of secrets/configuration. Add patterns like .env and .env.* (or .env.local) in addition to or instead of *.local to make intent clear and robust across different tools and platforms.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider explicitly ignoring environment files to avoid committing secrets/configuration. Right now you have *.local, but adding explicit entries makes intent clear. For example, add:

  • .env
  • .env.local
  • .env.*
    You can place these entries here (near other local-related ignores).


Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as above — this line appears to contain only a single space character. Remove it to avoid introducing an accidental ignore pattern.

# Editor directories and files
.vscode/*

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The .vscode/* entry with an allow-list for !.vscode/extensions.json is a common pattern to share recommended extensions while ignoring personal editor settings. Ensure that extensions.json does not contain any workspace secrets or credentials before committing.

!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
69 changes: 69 additions & 0 deletions client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# React + TypeScript + Vite

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is a project README and does not contain any implementation. The task requires an implemented client and server for the chat app (username handling, localStorage, room management, persisted messages). Please provide the source code files (client/src/* and server/*) so those requirements can be validated.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The title and opening line read like a generic Vite + React template. If this README is intended to document the chat client for this project, update the title/intro to describe the chat app and its purpose, not the template.


This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines here are documentation about React + Vite and ESLint configuration. They do not implement or document the required server API, socket events, message schema (author, time, text), or room management operations (create/rename/join/delete). Add documentation that explicitly describes the API/contract and persistence strategy for messages per room.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This paragraph describes the template. Replace or augment it with a short project summary that lists main features required by the assignment (username persistence in localStorage, rooms CRUD, message history, server communication via HTTP/WS) so reviewers know what to expect.


Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh

## Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
Comment on lines +10 to +12

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "Expanding the ESLint configuration" section is useful for maintainers but distracts from user-facing setup instructions. Consider moving developer-oriented content (ESLint config, plugin setup) to a CONTRIBUTING.md or DEVELOPER.md, and keep README focused on installation and usage.


```js
export default tseslint.config([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...

// Remove tseslint.configs.recommended and replace with this
...tseslint.configs.recommendedTypeChecked,
// Alternatively, use this for stricter rules
...tseslint.configs.strictTypeChecked,
// Optionally, add this for stylistic rules
...tseslint.configs.stylisticTypeChecked,

// Other configs...
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
```
Comment on lines +14 to +40

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block shows example ESLint config (lines 14-39). While useful, it does not replace the need for the required implementation files. If you intended to submit the code, please attach the implementation files instead of (or in addition to) this README.

Comment on lines +14 to +40

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tseslint.config code block is a developer toolchain example. If you keep it here, clearly label it as "Developer / Linting configuration" and add a short note telling when/how to use it. Otherwise, move it to a developer guide file to keep the main README concise.


You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:

```js
// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'

export default tseslint.config([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...
// Enable lint rules for React
reactX.configs['recommended-typescript'],
// Enable lint rules for React DOM
reactDom.configs.recommended,
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
Comment on lines +42 to +68

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The plugin installation snippet and additional plugin details are also developer-facing. Either move these to a separate developer document or add a dedicated section header (e.g., "For developers: ESLint & plugins") so users aren't confused by advanced configuration details.

```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This README documents ESLint configuration and plugins — useful. Consider adding a short "How to run" / "Development" section (steps to install deps and start the client, and the expected backend URL/port) so reviewers can quickly launch the client and test the chat app. This will make the project easier to evaluate but does not affect functional requirements.

23 changes: 23 additions & 0 deletions client/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import looks suspicious: there is no widely-used package named exactly typescript-eslint. The official TypeScript ESLint packages are scoped under @typescript-eslint (for example @typescript-eslint/eslint-plugin and @typescript-eslint/parser). Confirm you have the correct package installed and update this import accordingly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import on this line uses the module name 'typescript-eslint'. The widely used TypeScript ESLint packages are under the @typescript-eslint scope (for example, '@typescript-eslint/eslint-plugin' and '@typescript-eslint/parser'). Verify that 'typescript-eslint' is an installed package and that it exports what you expect. If not, replace it with the correct package(s) or update how you consume them.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line imports the TypeScript ESLint package using the module name typescript-eslint. That package name is incorrect. The TypeScript ESLint packages are typically scoped under @typescript-eslint (for example @typescript-eslint/eslint-plugin and @typescript-eslint/parser). Also the code later calls tsext.config(...) as if the import exposes a config function — the plugin package does not expose such a helper. Replace this import with the correct plugin (e.g. import tsPlugin from '@typescript-eslint/eslint-plugin') and/or import the parser (@typescript-eslint/parser) depending on your intended usage. Verify the actual exported API of the package you choose.

import { globalIgnores } from 'eslint/config'

export default tseslint.config([

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The call tseslint.config([ ... ]) is not a standard ESLint pattern I recognize. If tseslint is intended to be a helper that composes configs, ensure that helper actually exists on the imported module. Otherwise, for ESLint flat config you should typically export default [ ... ] (an array of config entries) or directly include plugin/config objects. Double-check the intended API and replace this with a valid export if needed.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file calls tseslint.config([...]) to build the exported configuration. That assumes the imported tseslint module exposes a config function. Confirm the package you import here actually provides this API. If it does not, adjust the export to the shape ESLint expects (for example, exporting a plain object or using the proper helper provided by the actual package).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file uses tsext.config([ ... ]) pattern (line 8) which is not a known API for the TypeScript ESLint plugin. ESLint flat config composition is usually an exported array of config items (e.g. export default [ js.configs.recommended, tsPlugin.configs.recommended, ... ]). Do not call a non-existent config() function on the plugin import. Instead, compose configs by exporting an array of configs or include plugin config objects directly.

globalIgnores(['dist']),
Comment on lines +6 to +9

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

globalIgnores is part of ESLint's flat config utilities in newer ESLint versions. Make sure your ESLint version supports import { globalIgnores } from 'eslint/config'. If it does, globalIgnores(['dist']) is acceptable as an array element in a flat config; if not, use the legacy ignorePatterns field in a traditional .eslintrc format.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

globalIgnores(['dist']) is fine and useful, but ensure the overall exported shape (returned by tseslint.config(...)) matches the expected ESLint config structure. If you change the tseslint import to a different package, re-check that globalIgnores is still applied as intended in the final exported object.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using globalIgnores(['dist']) is fine, but in a flat config you should include it as one element in the exported array. If you switch to exporting an array, place globalIgnores(['dist']) as a top-level element. Right now it's being passed into a non-existent tsext.config wrapper which will fail.

{
files: ['**/*.{ts,tsx}'],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs['recommended-latest'],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verify that the plugin actually exports a configs object and that the named config recommended-latest exists. The common export for eslint-plugin-react-hooks is usually rules (and sometimes a recommended config). If recommended-latest does not exist this will throw when ESLint loads the config — check the plugin docs and use the exact exported config name.

reactRefresh.configs.vite,
Comment on lines +12 to +16

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are using an extends array inside a config object. In ESLint's flat config you can include configs as array elements (e.g. js.configs.recommended) or use extends in the classic config format. Make sure you are consistent with the flat-config API for your ESLint version. Also verify that each referenced *.configs.* property actually exists on the imported module objects; otherwise the extend will fail.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check that reactRefresh.configs.vite actually exists on the eslint-plugin-react-refresh package you installed. If the plugin doesn't export a configs.vite property, this will throw when ESLint loads. Consult the plugin docs and use the provided config name or include the plugin's config object appropriately.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reactRefresh.configs.vite is referenced in the extends array. Verify that the eslint-plugin-react-refresh package is installed and that it exposes a configs.vite export. If that plugin doesn't provide such a named config, ESLint will fail to load. If you only need the plugin, consider adding it to plugins and referencing its rules or use a different plugin/config that offers Vite-specific settings.

Comment on lines +15 to +16

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double-check that reactHooks.configs['recommended-latest'] and reactRefresh.configs.vite are actually exported keys from the respective packages. If those plugins do not export configs with those exact keys, the config evaluation will throw. Commonly eslint-plugin-react-hooks exposes configs.recommended (not necessarily 'recommended-latest'). Verify the correct key names in each plugin's README or the package entrypoint.

],
Comment on lines +12 to +17

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block uses an extends property inside an object (lines 12–17). In ESLint's flat config format extends is not used inside an object like this; instead you include the configs as separate items in the exported array. Example flat-config composition:

export default [
globalIgnores(['dist']),
js.configs.recommended,
tsPlugin.configs.recommended,
reactHooks.configs.recommended,
reactRefresh.configs.vite,
{ files: ['**/*.{ts,tsx}'], languageOptions: { ecmaVersion: 2020, globals: globals.browser } }
]

Refactor to compose configs this way rather than relying on extends inside an object.

languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
Comment on lines +18 to +20

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

languageOptions and globals: globals.browser are correct if you intend to lint browser code. Confirm that the globals object imported from the globals package is what you expect. If you need Node globals (or both), include them explicitly.

Comment on lines +19 to +20

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Language options set ecmaVersion: 2020 and globals: globals.browser — these are reasonable defaults for a browser-targeted React app. No change required here, but keep in mind that your TypeScript project settings (tsconfigs) may require aligning parserOptions elsewhere if you switch to a parser-based config for type-aware linting.

},
Comment on lines +18 to +21

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inside your config object you set languageOptions.ecmaVersion and languageOptions.globals which is fine, but if you intend to lint TypeScript you will usually need to configure the parser (e.g., parser: '@typescript-eslint/parser') and parserOptions. For flat config, you may need to set languageOptions.parser to the parser function from @typescript-eslint/parser. Make sure you provide the TypeScript parser so TypeScript files are parsed correctly.

},
])
Comment on lines +8 to +23

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file currently appears to be a hybrid of legacy and flat ESLint config APIs which will not work as written. Decide which format you want (legacy .eslintrc.* vs the flat eslint.config.js) and restructure accordingly. If you choose the flat config, export an array of config items (not a single object wrapped by a non-existent helper). If you choose the legacy format, use module.exports = { extends: [...], parser: ..., plugins: [...] } structure instead.

13 changes: 13 additions & 0 deletions client/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading