Initial commit
This commit is contained in:
		
						commit
						3dc1cf3f02
					
				| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
out/
 | 
			
		||||
db/
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
db/
 | 
			
		||||
.env
 | 
			
		||||
node_modules/
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
FROM node:20-alpine3.19
 | 
			
		||||
 | 
			
		||||
WORKDIR /usr/src/app
 | 
			
		||||
 | 
			
		||||
COPY package*.json ./
 | 
			
		||||
 | 
			
		||||
RUN npm install
 | 
			
		||||
 | 
			
		||||
COPY . .
 | 
			
		||||
 | 
			
		||||
RUN npm install -g typescript
 | 
			
		||||
 | 
			
		||||
RUN tsc
 | 
			
		||||
 | 
			
		||||
# WORKDIR /usr/src/app/out
 | 
			
		||||
 | 
			
		||||
EXPOSE 3000
 | 
			
		||||
 | 
			
		||||
# CMD [ "node", "--env-file=../.env", "." ]
 | 
			
		||||
CMD [ "sh", "./run.sh" ]
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
version: "3"
 | 
			
		||||
services:
 | 
			
		||||
  kawaiilingo-api:
 | 
			
		||||
    hostname: kawaiilingo-api
 | 
			
		||||
    image: aelita4/kawaiilingo-api
 | 
			
		||||
    ports:
 | 
			
		||||
      - "3002:3000"
 | 
			
		||||
    depends_on:
 | 
			
		||||
      - kawaiilingo-db
 | 
			
		||||
    networks:
 | 
			
		||||
      - kawaiilingo-network
 | 
			
		||||
      - proxy
 | 
			
		||||
    restart: always
 | 
			
		||||
  kawaiilingo-db:
 | 
			
		||||
    image: mysql
 | 
			
		||||
    environment:
 | 
			
		||||
      MYSQL_ROOT_PASSWORD: root
 | 
			
		||||
      MYSQL_DATABASE: kawaiilingo
 | 
			
		||||
    ports:
 | 
			
		||||
      - "3306:3306"
 | 
			
		||||
    hostname: kawaiilingo-db
 | 
			
		||||
    networks:
 | 
			
		||||
      - kawaiilingo-network
 | 
			
		||||
    volumes:
 | 
			
		||||
      - ./db:/var/lib/mysql
 | 
			
		||||
networks:
 | 
			
		||||
  kawaiilingo-network:
 | 
			
		||||
    external: false
 | 
			
		||||
  proxy:
 | 
			
		||||
    external: 
 | 
			
		||||
      name: proxy-network
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,294 @@
 | 
			
		|||
-- phpMyAdmin SQL Dump
 | 
			
		||||
-- version 5.2.1
 | 
			
		||||
-- https://www.phpmyadmin.net/
 | 
			
		||||
--
 | 
			
		||||
-- Host: 127.0.0.1
 | 
			
		||||
-- Generation Time: Jul 02, 2024 at 04:46 PM
 | 
			
		||||
-- Server version: 10.4.32-MariaDB
 | 
			
		||||
-- PHP Version: 8.2.12
 | 
			
		||||
 | 
			
		||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
 | 
			
		||||
START TRANSACTION;
 | 
			
		||||
SET time_zone = "+00:00";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
 | 
			
		||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
 | 
			
		||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
 | 
			
		||||
/*!40101 SET NAMES utf8mb4 */;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Database: `kawaiilingo`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Table structure for table `categories`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
CREATE TABLE `categories` (
 | 
			
		||||
  `categoryId` int(11) NOT NULL,
 | 
			
		||||
  `englishName` varchar(255) DEFAULT NULL,
 | 
			
		||||
  `polishName` varchar(255) DEFAULT NULL
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Dumping data for table `categories`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
INSERT INTO `categories` (`categoryId`, `englishName`, `polishName`) VALUES
 | 
			
		||||
(1, 'numbers', 'Liczby'),
 | 
			
		||||
(2, 'weekDays', 'Dni tygodnia'),
 | 
			
		||||
(3, 'colors', 'Kolory'),
 | 
			
		||||
(4, 'weather', 'Pogoda'),
 | 
			
		||||
(5, 'food', 'Jedzenie'),
 | 
			
		||||
(6, 'family', 'Rodzina'),
 | 
			
		||||
(7, 'months', 'Miesiące'),
 | 
			
		||||
(8, 'animals', 'Zwierzęta');
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Table structure for table `learnedwords`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
CREATE TABLE `learnedwords` (
 | 
			
		||||
  `learnedID` int(11) NOT NULL,
 | 
			
		||||
  `userID` int(11) NOT NULL,
 | 
			
		||||
  `wordID` int(11) NOT NULL,
 | 
			
		||||
  `percentage` int(11) NOT NULL DEFAULT 0
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Table structure for table `scores`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
CREATE TABLE `scores` (
 | 
			
		||||
  `scoreId` int(11) NOT NULL,
 | 
			
		||||
  `userId` int(11) NOT NULL,
 | 
			
		||||
  `time` int(11) NOT NULL DEFAULT 0,
 | 
			
		||||
  `xp` int(11) NOT NULL DEFAULT 0,
 | 
			
		||||
  `mistakes` int(11) NOT NULL DEFAULT 0
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Table structure for table `users`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
CREATE TABLE `users` (
 | 
			
		||||
  `userId` int(10) NOT NULL,
 | 
			
		||||
  `username` varchar(255) NOT NULL,
 | 
			
		||||
  `password` varchar(255) NOT NULL,
 | 
			
		||||
  `email` varchar(255) NOT NULL,
 | 
			
		||||
  `xp` int(11) NOT NULL DEFAULT 0,
 | 
			
		||||
  `level` int(11) NOT NULL DEFAULT 0,
 | 
			
		||||
  `dateJoined` datetime NOT NULL DEFAULT current_timestamp()
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Table structure for table `words`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
CREATE TABLE `words` (
 | 
			
		||||
  `wordID` int(11) NOT NULL,
 | 
			
		||||
  `polishWord` varchar(255) NOT NULL,
 | 
			
		||||
  `japaneseWord` varchar(255) NOT NULL,
 | 
			
		||||
  `romaji` varchar(255) NOT NULL,
 | 
			
		||||
  `categoryId` int(11) NOT NULL
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Dumping data for table `words`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
INSERT INTO `words` (`wordID`, `polishWord`, `japaneseWord`, `romaji`, `categoryId`) VALUES
 | 
			
		||||
(6, 'zero', 'ぜろ', 'zero', 1),
 | 
			
		||||
(7, 'jeden', 'いち', 'ichi', 1),
 | 
			
		||||
(8, 'dwa', 'に', 'ni', 1),
 | 
			
		||||
(9, 'trzy', 'さん', 'san', 1),
 | 
			
		||||
(10, 'cztery', 'よん|し', 'yon|shi', 1),
 | 
			
		||||
(12, 'pięć', 'ご', 'go', 1),
 | 
			
		||||
(13, 'sześć', 'ろく', 'roku', 1),
 | 
			
		||||
(14, 'siedem', 'なな|しち', 'nana|shichi', 1),
 | 
			
		||||
(16, 'osiem', 'はち', 'hachi', 1),
 | 
			
		||||
(17, 'dziewięć', 'きゅう', 'kyuu', 1),
 | 
			
		||||
(18, 'dziesięć', 'じゅう', 'juu', 1),
 | 
			
		||||
(19, 'sto', 'ひゃく', 'hyaku', 1),
 | 
			
		||||
(20, 'tysiąc', 'せん', 'sen', 1),
 | 
			
		||||
(21, 'poniedziałek', 'げつようび', 'getsuyoubi', 2),
 | 
			
		||||
(22, 'wtorek', 'かようび', 'kayoubi', 2),
 | 
			
		||||
(23, 'środa', 'すいようび', 'suiyoubi', 2),
 | 
			
		||||
(24, 'czwartek', 'もくようび', 'mokuyoubi', 2),
 | 
			
		||||
(25, 'piątek', 'きんようび', 'kinyoubi', 2),
 | 
			
		||||
(26, 'sobota', 'どようび\r\n', 'doyoubi', 2),
 | 
			
		||||
(27, 'niedziela', 'にちようび', 'nichiyoubi', 2),
 | 
			
		||||
(28, 'kolor', 'いろ', 'iro', 3),
 | 
			
		||||
(29, 'czarny', 'くろ', 'kuro', 3),
 | 
			
		||||
(30, 'czerwony', 'あか', 'aka', 3),
 | 
			
		||||
(31, 'niebieski', 'あお', 'ao', 3),
 | 
			
		||||
(32, 'fieletowy', 'むらさき', 'murasaki', 3),
 | 
			
		||||
(33, 'biały', 'しろ', 'shiro', 3),
 | 
			
		||||
(34, 'zielony', 'みどり', 'midori', 3),
 | 
			
		||||
(35, 'pomarańczowy', 'おれんじ', 'orenji', 3),
 | 
			
		||||
(36, 'żółty', 'きいろ', 'kiiro', 3),
 | 
			
		||||
(37, 'brązowy', 'ちゃいろ', 'chairo', 3),
 | 
			
		||||
(38, 'pogoda', 'てんき', 'Tenki', 4),
 | 
			
		||||
(39, 'słonecznie', 'はれ\r\n\r\n', 'hare', 4),
 | 
			
		||||
(40, 'zachmurzenie', 'くもり', 'kumori', 4),
 | 
			
		||||
(41, 'deszcz', 'あめ', 'ame', 4),
 | 
			
		||||
(42, 'śnieg', 'ゆき', 'yuki', 4),
 | 
			
		||||
(43, 'gorąco', 'あつい', 'atsui', 4),
 | 
			
		||||
(44, 'zimno', 'さむい', 'samui', 4),
 | 
			
		||||
(45, 'ciepło', 'あたたかい', 'atatakai', 4),
 | 
			
		||||
(46, 'chłodno', 'すずしい', 'suzushii', 4),
 | 
			
		||||
(47, 'burza', 'らあいう', 'raiu', 4),
 | 
			
		||||
(48, 'ryż', 'ごはん', 'gohan', 5),
 | 
			
		||||
(49, 'zielona herbata', 'おちゃ', 'ocha', 5),
 | 
			
		||||
(50, 'czarna herbata', 'こうちゃ', 'koucha', 5),
 | 
			
		||||
(51, 'chleb', 'ぱん', 'pan', 5),
 | 
			
		||||
(52, 'mięso', 'にく', 'niku', 5),
 | 
			
		||||
(53, 'warzywa', 'やさい', 'yasai', 5),
 | 
			
		||||
(54, 'jajko', 'たまご', 'tamago', 5),
 | 
			
		||||
(55, 'ryba', 'さかな', 'sakana', 5),
 | 
			
		||||
(56, 'mleko', 'ぎゅにゅ', 'gyunyu', 5),
 | 
			
		||||
(57, 'woda', 'みず', 'mizu', 5),
 | 
			
		||||
(58, 'pizza', 'ぴざ', 'piza', 5),
 | 
			
		||||
(59, 'ciasto', 'けーき', 'keeki', 5),
 | 
			
		||||
(60, 'mama', 'はは', 'haha', 6),
 | 
			
		||||
(61, 'tata', 'ちち', 'chichi', 6),
 | 
			
		||||
(62, 'starszy brat', 'あに', 'ani', 6),
 | 
			
		||||
(63, 'młodszy brat', 'おとうと', 'otouto', 6),
 | 
			
		||||
(64, 'starsza siostra', 'あね', 'ane', 6),
 | 
			
		||||
(65, 'młodsza siostra', 'いもうと', 'imouto', 6),
 | 
			
		||||
(66, 'córka', 'むすめ', 'musume', 6),
 | 
			
		||||
(67, 'syn', 'むすこ', 'musuko', 6),
 | 
			
		||||
(68, 'mąż', 'おっと', 'otto', 6),
 | 
			
		||||
(69, 'żona', 'つま', 'tsuma', 6),
 | 
			
		||||
(70, 'babcia', 'そぼ', 'sobo', 6),
 | 
			
		||||
(71, 'dziadek', 'そふ', 'sofu', 6),
 | 
			
		||||
(72, 'styczeń', 'いちがつ', 'ichigatsu', 7),
 | 
			
		||||
(73, 'luty', 'にがつ', 'nigatsu', 7),
 | 
			
		||||
(74, 'marzed', 'さんがつ', 'sangatsu', 7),
 | 
			
		||||
(75, 'kwiecień', 'しがつ', 'shigatsu', 7),
 | 
			
		||||
(76, 'maj', 'ごがつ', 'gogatsu', 7),
 | 
			
		||||
(77, 'czerwiec', 'ろくがつ', 'rokugatsu', 7),
 | 
			
		||||
(78, 'lipiec', 'しちがつ', 'shichigatsu', 7),
 | 
			
		||||
(79, 'sierpień', 'はちがつ', 'hachigatsu', 7),
 | 
			
		||||
(80, 'wrzesień', 'くがつ', 'kugatsu', 7),
 | 
			
		||||
(81, 'październik', 'じゅうがつ', 'juugatsu', 7),
 | 
			
		||||
(82, 'listopad', 'じゅういちがつ', 'juuichigatsu', 7),
 | 
			
		||||
(83, 'grudzień', 'じゅうにがつ', 'juunigatsu', 7),
 | 
			
		||||
(84, 'zwierzęta', 'どうぶつ', 'doubutsu', 8),
 | 
			
		||||
(85, 'świnia', 'ぶた', 'buta', 8),
 | 
			
		||||
(86, 'pies', 'いぬ', 'inu', 8),
 | 
			
		||||
(87, 'kot', 'ねこ', 'neko', 8),
 | 
			
		||||
(88, 'lis', 'きつね', 'kitsune', 8),
 | 
			
		||||
(89, 'niedźwieź', 'くま', 'kuma', 8),
 | 
			
		||||
(90, 'żyrafa', 'きりん', 'kirin', 8),
 | 
			
		||||
(91, 'małpa', 'さる', 'saru', 8),
 | 
			
		||||
(92, 'mysz', 'ねずみ', 'nezumi', 8),
 | 
			
		||||
(93, 'ptak', 'とり', 'tori', 8),
 | 
			
		||||
(94, 'królik', 'うさぎ', 'usagi', 8),
 | 
			
		||||
(95, 'krowa', 'うし', 'ushi', 8),
 | 
			
		||||
(96, 'koza', 'やぎ', 'yagi', 8);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Indexes for dumped tables
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Indexes for table `categories`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `categories`
 | 
			
		||||
  ADD PRIMARY KEY (`categoryId`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Indexes for table `learnedwords`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `learnedwords`
 | 
			
		||||
  ADD PRIMARY KEY (`learnedID`),
 | 
			
		||||
  ADD KEY `FK_LearnedUser` (`userID`),
 | 
			
		||||
  ADD KEY `FK_LearnedWord` (`wordID`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Indexes for table `scores`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `scores`
 | 
			
		||||
  ADD PRIMARY KEY (`scoreId`),
 | 
			
		||||
  ADD KEY `FK_UserScore` (`userId`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Indexes for table `users`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `users`
 | 
			
		||||
  ADD PRIMARY KEY (`userId`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Indexes for table `words`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `words`
 | 
			
		||||
  ADD PRIMARY KEY (`wordID`),
 | 
			
		||||
  ADD KEY `FK_WordCategory` (`categoryId`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- AUTO_INCREMENT for dumped tables
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- AUTO_INCREMENT for table `learnedwords`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `learnedwords`
 | 
			
		||||
  MODIFY `learnedID` int(11) NOT NULL AUTO_INCREMENT;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- AUTO_INCREMENT for table `scores`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `scores`
 | 
			
		||||
  MODIFY `scoreId` int(11) NOT NULL AUTO_INCREMENT;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- AUTO_INCREMENT for table `users`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `users`
 | 
			
		||||
  MODIFY `userId` int(10) NOT NULL AUTO_INCREMENT;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- AUTO_INCREMENT for table `words`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `words`
 | 
			
		||||
  MODIFY `wordID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=97;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Constraints for dumped tables
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Constraints for table `learnedwords`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `learnedwords`
 | 
			
		||||
  ADD CONSTRAINT `FK_LearnedUser` FOREIGN KEY (`userID`) REFERENCES `users` (`userId`) ON DELETE CASCADE ON UPDATE CASCADE,
 | 
			
		||||
  ADD CONSTRAINT `FK_LearnedWord` FOREIGN KEY (`wordID`) REFERENCES `words` (`wordID`) ON DELETE CASCADE ON UPDATE CASCADE;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Constraints for table `scores`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `scores`
 | 
			
		||||
  ADD CONSTRAINT `FK_UserScore` FOREIGN KEY (`userId`) REFERENCES `users` (`userId`) ON DELETE CASCADE ON UPDATE CASCADE;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- Constraints for table `words`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `words`
 | 
			
		||||
  ADD CONSTRAINT `FK_WordCategory` FOREIGN KEY (`categoryId`) REFERENCES `categories` (`categoryId`) ON DELETE CASCADE ON UPDATE CASCADE;
 | 
			
		||||
COMMIT;
 | 
			
		||||
 | 
			
		||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
 | 
			
		||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
 | 
			
		||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "kawaiilingo",
 | 
			
		||||
  "version": "1.0.0",
 | 
			
		||||
  "description": "",
 | 
			
		||||
  "main": "index.js",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "test": "echo \"Error: no test specified\" && exit 1"
 | 
			
		||||
  },
 | 
			
		||||
  "keywords": [],
 | 
			
		||||
  "author": "",
 | 
			
		||||
  "license": "ISC",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "body-parser": "^1.20.2",
 | 
			
		||||
    "express": "^4.19.2",
 | 
			
		||||
    "jsonwebtoken": "^9.0.2",
 | 
			
		||||
    "mysql2": "^3.10.2"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@types/express": "^4.17.21",
 | 
			
		||||
    "@types/jsonwebtoken": "^9.0.6"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,56 @@
 | 
			
		|||
import express from 'express';
 | 
			
		||||
import bodyParser from 'body-parser';
 | 
			
		||||
import Database from './db/database';
 | 
			
		||||
import fs from 'fs';
 | 
			
		||||
import authenticateJWT from './lib/authenticateJWT';
 | 
			
		||||
 | 
			
		||||
const app = express();
 | 
			
		||||
 | 
			
		||||
app.use(bodyParser.urlencoded({extended : true}));
 | 
			
		||||
app.use(bodyParser.json());
 | 
			
		||||
 | 
			
		||||
// const db = new Database();
 | 
			
		||||
 | 
			
		||||
// type User = {
 | 
			
		||||
//     username: string,
 | 
			
		||||
//     password: string,
 | 
			
		||||
//     role: string,
 | 
			
		||||
//     xp: number
 | 
			
		||||
// };
 | 
			
		||||
 | 
			
		||||
const routes = 'routes';
 | 
			
		||||
 | 
			
		||||
fs.readdirSync(routes).forEach((file: string) => {
 | 
			
		||||
    const route = require(`./${routes}/${file}`);
 | 
			
		||||
    app.use(`/${file.split('.')[0]}`, route.default);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
app.get('/', (req, res) => {
 | 
			
		||||
    res.json({ message: 'Hello World!' });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
app.get('/test', authenticateJWT, (req, res) => {
 | 
			
		||||
    //@ts-ignore
 | 
			
		||||
    res.json({ code: 200, message: `O chuj, zalogowałeś się ${req.user.username}!` });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
app.get('/db', (req, res) => {
 | 
			
		||||
    const db = new Database();
 | 
			
		||||
    db.query('INSERT INTO words VALUES (NULL, "kot", "猫", "animals", "neko")', []);
 | 
			
		||||
 | 
			
		||||
    res.sendStatus(200);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
app.listen(3000, () => {
 | 
			
		||||
    console.log('Running on http://localhost:3000');
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
import { Request, Response, NextFunction } from 'express';
 | 
			
		||||
import jwt from 'jsonwebtoken';
 | 
			
		||||
 | 
			
		||||
const authenticateJWT = (req: Request, res: Response, next: NextFunction) => {
 | 
			
		||||
    const authHeader = req.headers.authorization;
 | 
			
		||||
 | 
			
		||||
    if (authHeader) {
 | 
			
		||||
        const token = authHeader.split(' ')[1];
 | 
			
		||||
 | 
			
		||||
        jwt.verify(token, process.env.ACCESS_TOKEN_SECRET ?? "", (err: any, user: any) => {
 | 
			
		||||
            if (err) {
 | 
			
		||||
                return res.status(403).json({ code: 403, error: 'Forbidden' })
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //@ts-ignore
 | 
			
		||||
            req.user = user;
 | 
			
		||||
            next();
 | 
			
		||||
        });
 | 
			
		||||
    } else {
 | 
			
		||||
        res.status(401).json({ code: 401, error: 'Unauthorized' });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default authenticateJWT;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
import { Router } from "express";
 | 
			
		||||
import jwt from 'jsonwebtoken';
 | 
			
		||||
import Database from "../db/database";
 | 
			
		||||
import User from "../types/User";
 | 
			
		||||
 | 
			
		||||
const db = new Database();
 | 
			
		||||
const router = Router();
 | 
			
		||||
 | 
			
		||||
router.post('/login', async (req, res) => {
 | 
			
		||||
    const { username, password } = req.body;
 | 
			
		||||
 | 
			
		||||
    const user = (await db.query('SELECT * FROM users WHERE username = ? AND password = ?', [username, password]))[0] as User | undefined;
 | 
			
		||||
 | 
			
		||||
    if (user) {
 | 
			
		||||
        const accessToken = jwt.sign({ userId: user.userId }, process.env.ACCESS_TOKEN_SECRET ?? "", { expiresIn: '7d' });
 | 
			
		||||
 | 
			
		||||
        res.json({
 | 
			
		||||
            code: 200,
 | 
			
		||||
            accessToken
 | 
			
		||||
        });
 | 
			
		||||
    } else {
 | 
			
		||||
        res.status(401).json({ code: 401, error: 'Username or password incorrect' });
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
router.post('/register', async (req, res) => {
 | 
			
		||||
    const { username, email, password } = req.body;
 | 
			
		||||
 | 
			
		||||
    const user = (await db.query('SELECT * FROM users WHERE username = ? OR email = ?', [username, email]))[0] as User | undefined;
 | 
			
		||||
 | 
			
		||||
    if (user) {
 | 
			
		||||
        return res.status(409).json({ code: 409, error: 'Username already exists' });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    await db.query('INSERT INTO users VALUES (NULL, ?, ?, ?, ?, ?, ?)', [username, password, email, 0, 0, new Date()]);
 | 
			
		||||
 | 
			
		||||
    res.status(201).json({ code: 201, message: 'User created' });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
router.get('/users', async (req, res) => {
 | 
			
		||||
    const users = await db.query('SELECT * FROM users', []);
 | 
			
		||||
 | 
			
		||||
    res.json({ code: 200, users });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export default router;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,152 @@
 | 
			
		|||
import { Router } from "express";
 | 
			
		||||
import Database from "../db/database";
 | 
			
		||||
import authenticateJWT from "../lib/authenticateJWT";
 | 
			
		||||
import Word from "../types/Word";
 | 
			
		||||
 | 
			
		||||
const db = new Database();
 | 
			
		||||
const router = Router();
 | 
			
		||||
 | 
			
		||||
const times: { start: number, userId: number }[] = [];
 | 
			
		||||
 | 
			
		||||
const mapMultipleWords = async (words: Word[]) => {
 | 
			
		||||
    const categories = await db.query('SELECT * FROM categories', []);
 | 
			
		||||
    // console.log(categories)
 | 
			
		||||
 | 
			
		||||
    return words.map((word) => {
 | 
			
		||||
        if(word.japaneseWord.includes("|")) {
 | 
			
		||||
            const japaneseWords = word.japaneseWord.split("|");
 | 
			
		||||
            const romajiWords = word.romaji.split("|");
 | 
			
		||||
            return {
 | 
			
		||||
                wordID: word.wordID,
 | 
			
		||||
                polishWord: word.polishWord,
 | 
			
		||||
                japaneseWord: japaneseWords,
 | 
			
		||||
                romaji: romajiWords,
 | 
			
		||||
                category: {
 | 
			
		||||
                    categoryId: word.categoryId,
 | 
			
		||||
                    categoryEnglishName: categories.find((category: any) => category.categoryId === word.categoryId).englishName,
 | 
			
		||||
                    categoryPolishName: categories.find((category: any) => category.categoryId === word.categoryId).polishName
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else return {
 | 
			
		||||
            wordID: word.wordID,
 | 
			
		||||
            polishWord: word.polishWord,
 | 
			
		||||
            japaneseWord: word.japaneseWord,
 | 
			
		||||
            romaji: word.romaji,
 | 
			
		||||
            category: {
 | 
			
		||||
                categoryId: word.categoryId,
 | 
			
		||||
                categoryEnglishName: categories.find((category: any) => category.categoryId === word.categoryId).englishName,
 | 
			
		||||
                categoryPolishName: categories.find((category: any) => category.categoryId === word.categoryId).polishName
 | 
			
		||||
            }
 | 
			
		||||
        
 | 
			
		||||
        };
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
router.get('/all', (req, res) => {
 | 
			
		||||
    db.query('SELECT * FROM words', [])
 | 
			
		||||
        .then(async (result: Word[]) => {           
 | 
			
		||||
            res.json({ code: 200, words: await mapMultipleWords(result) });
 | 
			
		||||
        })
 | 
			
		||||
        .catch((err: any) => {
 | 
			
		||||
            console.log(err);
 | 
			
		||||
            res.sendStatus(500);
 | 
			
		||||
        });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
router.get('/id/:id', (req, res) => {
 | 
			
		||||
    db.query('SELECT * FROM words WHERE wordId = ?', [req.params.id])
 | 
			
		||||
        .then(async (result: Word[]) => {
 | 
			
		||||
            if(result.length === 0) return res.status(404).json({ code: 404, error: 'Word not found' });
 | 
			
		||||
            res.json({ code: 200, word: await mapMultipleWords(result) });
 | 
			
		||||
        })
 | 
			
		||||
        .catch((err: any) => {
 | 
			
		||||
            console.log(err);
 | 
			
		||||
            res.status(500).json({ code: 500, error: 'Internal server error' });
 | 
			
		||||
        });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
router.get('/category/:categoryId', (req, res) => {
 | 
			
		||||
    db.query('SELECT * FROM words WHERE categoryId = ?', [req.params.categoryId])
 | 
			
		||||
        .then(async (result: Word[]) => {
 | 
			
		||||
            if(result.length === 0) return res.status(404).json({ code: 404, error: 'Category not found' });    
 | 
			
		||||
            res.json({ code: 200, words: await mapMultipleWords(result) });
 | 
			
		||||
        })
 | 
			
		||||
        .catch((err: any) => {
 | 
			
		||||
            console.log(err);
 | 
			
		||||
            res.status(500).json({ code: 500, error: 'Internal server error' });
 | 
			
		||||
        });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
router.get('/pickRandom/', (req, res) => {
 | 
			
		||||
    let { categoryId, amount } = req.query;
 | 
			
		||||
 | 
			
		||||
    if(!amount) amount = "1";
 | 
			
		||||
    
 | 
			
		||||
    const sql = `SELECT * FROM words ${categoryId ? `WHERE categoryId = ? ` : ""}ORDER BY RAND() LIMIT ${amount}`;
 | 
			
		||||
 | 
			
		||||
    db.query(sql, [categoryId])
 | 
			
		||||
        .then(async (result: any) => {
 | 
			
		||||
            if(result.length === 0) return res.status(404).json({ code: 404, error: 'Category not found' });
 | 
			
		||||
            res.json({ code: 200, words: await mapMultipleWords(result) });
 | 
			
		||||
        })
 | 
			
		||||
        .catch((err: any) => {
 | 
			
		||||
            console.log(err);
 | 
			
		||||
            res.status(500).json({ code: 500, error: 'Internal server error' });
 | 
			
		||||
        });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
router.post('/startTest', authenticateJWT, async (req, res) => {
 | 
			
		||||
    times.push({
 | 
			
		||||
        start: Date.now(),
 | 
			
		||||
        // @ts-ignore
 | 
			
		||||
        userId: req.user.userId
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    return res.json({ code: 200, message: 'Test started' });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
router.post('/submitAnswer', authenticateJWT, (req, res) => {
 | 
			
		||||
    const answers = req.body as { id: number, answer: string }[];
 | 
			
		||||
    const promises = answers.map(answer => db.query('SELECT * FROM words WHERE wordId = ?', [answer.id]));
 | 
			
		||||
    
 | 
			
		||||
    Promise.all(promises)
 | 
			
		||||
        .then(async (results: Word[][]) => {
 | 
			
		||||
            const verified = results.map((result, index) => {
 | 
			
		||||
                if(result[0].romaji.includes("|")) {
 | 
			
		||||
                    const romajiWords = result[0].romaji.split("|");
 | 
			
		||||
                    return {id: result[0].wordID, correct: romajiWords.includes(answers[index].answer) }
 | 
			
		||||
                }
 | 
			
		||||
                return {id: result[0].wordID, correct: result[0].romaji === answers[index].answer }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            const accuracy = verified.filter((v) => v.correct).length / verified.length;
 | 
			
		||||
            const xp = accuracy * 10 + (accuracy === 1 ? 10 : 0);
 | 
			
		||||
 | 
			
		||||
            // @ts-ignore
 | 
			
		||||
            const time = times.find((time) => time.userId === req.user.userId);
 | 
			
		||||
            if(!time) return res.status(404).json({ code: 404, error: 'Test not started' });
 | 
			
		||||
 | 
			
		||||
            times.splice(times.indexOf(time), 1);
 | 
			
		||||
 | 
			
		||||
            // @ts-ignore
 | 
			
		||||
            await db.updateUserXP(req.user.userId, xp);
 | 
			
		||||
 | 
			
		||||
            // @ts-ignore
 | 
			
		||||
            await db.addScore(req.user.userId, Math.floor((Date.now() - time.start) / 1000), xp, verified.filter((v) => !v.correct).length);
 | 
			
		||||
 | 
			
		||||
            res.json({ code: 200, results: {
 | 
			
		||||
                questions: verified,
 | 
			
		||||
                timeElapsed: Math.floor((Date.now() - time.start) / 1000),
 | 
			
		||||
                accuracy,
 | 
			
		||||
                experienceEarned: xp
 | 
			
		||||
            }});
 | 
			
		||||
        })
 | 
			
		||||
        .catch((err: any) => {
 | 
			
		||||
            console.log(err);
 | 
			
		||||
            res.status(500).json({ code: 500, error: 'Internal server error' });
 | 
			
		||||
        });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export default router;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
import { Router } from "express";
 | 
			
		||||
import Database from "../db/database";
 | 
			
		||||
 | 
			
		||||
const router = Router();
 | 
			
		||||
const db = new Database();
 | 
			
		||||
 | 
			
		||||
router.get('/', async (req, res) => {
 | 
			
		||||
    const scores = await db.query('SELECT userId, sum(time) AS totalTime, sum(xp) AS totalXP, sum(mistakes) AS totalMistakes FROM scores GROUP BY userId ORDER BY totalXP DESC', []);
 | 
			
		||||
    res.json({ code: 200, scores });    
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export default router;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
import { Router } from "express";
 | 
			
		||||
import authenticateJWT from "../lib/authenticateJWT";
 | 
			
		||||
import Database from "../db/database";
 | 
			
		||||
 | 
			
		||||
const router = Router();
 | 
			
		||||
const db = new Database();
 | 
			
		||||
 | 
			
		||||
router.get('/', authenticateJWT, async (req, res) => {
 | 
			
		||||
    // @ts-ignore
 | 
			
		||||
    const userDB = (await db.query('SELECT * FROM users WHERE userId = ?', [req.user.userId]))[0];
 | 
			
		||||
 | 
			
		||||
    return res.json({
 | 
			
		||||
        code: 200,
 | 
			
		||||
        user: {
 | 
			
		||||
            username: userDB.username,
 | 
			
		||||
            xp: userDB.xp,
 | 
			
		||||
            level: userDB.level,
 | 
			
		||||
            dateJoined: userDB.dateJoined
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export default router;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
export default interface User {
 | 
			
		||||
    userId: number,
 | 
			
		||||
    username: string,
 | 
			
		||||
    password: string,
 | 
			
		||||
    role: string,
 | 
			
		||||
    xp: number
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
export default interface Word {
 | 
			
		||||
    wordID: number,
 | 
			
		||||
    polishWord: string,
 | 
			
		||||
    japaneseWord: string,
 | 
			
		||||
    romaji: string,
 | 
			
		||||
    categoryId: string
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,109 @@
 | 
			
		|||
{
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    /* Visit https://aka.ms/tsconfig to read more about this file */
 | 
			
		||||
 | 
			
		||||
    /* Projects */
 | 
			
		||||
    // "incremental": true,                              /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
 | 
			
		||||
    // "composite": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */
 | 
			
		||||
    // "tsBuildInfoFile": "./.tsbuildinfo",              /* Specify the path to .tsbuildinfo incremental compilation file. */
 | 
			
		||||
    // "disableSourceOfProjectReferenceRedirect": true,  /* Disable preferring source files instead of declaration files when referencing composite projects. */
 | 
			
		||||
    // "disableSolutionSearching": true,                 /* Opt a project out of multi-project reference checking when editing. */
 | 
			
		||||
    // "disableReferencedProjectLoad": true,             /* Reduce the number of projects loaded automatically by TypeScript. */
 | 
			
		||||
 | 
			
		||||
    /* Language and Environment */
 | 
			
		||||
    "target": "es2016",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
 | 
			
		||||
    // "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
 | 
			
		||||
    // "jsx": "preserve",                                /* Specify what JSX code is generated. */
 | 
			
		||||
    // "experimentalDecorators": true,                   /* Enable experimental support for legacy experimental decorators. */
 | 
			
		||||
    // "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */
 | 
			
		||||
    // "jsxFactory": "",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
 | 
			
		||||
    // "jsxFragmentFactory": "",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
 | 
			
		||||
    // "jsxImportSource": "",                            /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
 | 
			
		||||
    // "reactNamespace": "",                             /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
 | 
			
		||||
    // "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
 | 
			
		||||
    // "useDefineForClassFields": true,                  /* Emit ECMAScript-standard-compliant class fields. */
 | 
			
		||||
    // "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */
 | 
			
		||||
 | 
			
		||||
    /* Modules */
 | 
			
		||||
    "module": "commonjs",                                /* Specify what module code is generated. */
 | 
			
		||||
    "rootDir": "./src/",                                 /* Specify the root folder within your source files. */
 | 
			
		||||
    // "moduleResolution": "node10",                     /* Specify how TypeScript looks up a file from a given module specifier. */
 | 
			
		||||
    // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
 | 
			
		||||
    // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
 | 
			
		||||
    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
 | 
			
		||||
    // "typeRoots": [],                                  /* Specify multiple folders that act like './node_modules/@types'. */
 | 
			
		||||
    // "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */
 | 
			
		||||
    // "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */
 | 
			
		||||
    // "moduleSuffixes": [],                             /* List of file name suffixes to search when resolving a module. */
 | 
			
		||||
    // "allowImportingTsExtensions": true,               /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
 | 
			
		||||
    // "resolvePackageJsonExports": true,                /* Use the package.json 'exports' field when resolving package imports. */
 | 
			
		||||
    // "resolvePackageJsonImports": true,                /* Use the package.json 'imports' field when resolving imports. */
 | 
			
		||||
    // "customConditions": [],                           /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
 | 
			
		||||
    // "resolveJsonModule": true,                        /* Enable importing .json files. */
 | 
			
		||||
    // "allowArbitraryExtensions": true,                 /* Enable importing files with any extension, provided a declaration file is present. */
 | 
			
		||||
    // "noResolve": true,                                /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
 | 
			
		||||
 | 
			
		||||
    /* JavaScript Support */
 | 
			
		||||
    // "allowJs": true,                                  /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
 | 
			
		||||
    // "checkJs": true,                                  /* Enable error reporting in type-checked JavaScript files. */
 | 
			
		||||
    // "maxNodeModuleJsDepth": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
 | 
			
		||||
 | 
			
		||||
    /* Emit */
 | 
			
		||||
    // "declaration": true,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
 | 
			
		||||
    // "declarationMap": true,                           /* Create sourcemaps for d.ts files. */
 | 
			
		||||
    // "emitDeclarationOnly": true,                      /* Only output d.ts files and not JavaScript files. */
 | 
			
		||||
    // "sourceMap": true,                                /* Create source map files for emitted JavaScript files. */
 | 
			
		||||
    // "inlineSourceMap": true,                          /* Include sourcemap files inside the emitted JavaScript. */
 | 
			
		||||
    // "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. */
 | 
			
		||||
    "outDir": "./out/",                                  /* Specify an output folder for all emitted files. */
 | 
			
		||||
    // "removeComments": true,                           /* Disable emitting comments. */
 | 
			
		||||
    // "noEmit": true,                                   /* Disable emitting files from a compilation. */
 | 
			
		||||
    // "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
 | 
			
		||||
    // "importsNotUsedAsValues": "remove",               /* Specify emit/checking behavior for imports that are only used for types. */
 | 
			
		||||
    // "downlevelIteration": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
 | 
			
		||||
    // "sourceRoot": "",                                 /* Specify the root path for debuggers to find the reference source code. */
 | 
			
		||||
    // "mapRoot": "",                                    /* Specify the location where debugger should locate map files instead of generated locations. */
 | 
			
		||||
    // "inlineSources": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */
 | 
			
		||||
    // "emitBOM": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
 | 
			
		||||
    // "newLine": "crlf",                                /* Set the newline character for emitting files. */
 | 
			
		||||
    // "stripInternal": true,                            /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
 | 
			
		||||
    // "noEmitHelpers": true,                            /* Disable generating custom helper functions like '__extends' in compiled output. */
 | 
			
		||||
    // "noEmitOnError": true,                            /* Disable emitting files if any type checking errors are reported. */
 | 
			
		||||
    // "preserveConstEnums": true,                       /* Disable erasing 'const enum' declarations in generated code. */
 | 
			
		||||
    // "declarationDir": "./",                           /* Specify the output directory for generated declaration files. */
 | 
			
		||||
    // "preserveValueImports": true,                     /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
 | 
			
		||||
 | 
			
		||||
    /* Interop Constraints */
 | 
			
		||||
    // "isolatedModules": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */
 | 
			
		||||
    // "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. */
 | 
			
		||||
    // "allowSyntheticDefaultImports": true,             /* Allow 'import x from y' when a module doesn't have a default export. */
 | 
			
		||||
    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
 | 
			
		||||
    // "preserveSymlinks": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
 | 
			
		||||
    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */
 | 
			
		||||
 | 
			
		||||
    /* Type Checking */
 | 
			
		||||
    "strict": true,                                      /* Enable all strict type-checking options. */
 | 
			
		||||
    // "noImplicitAny": true,                            /* Enable error reporting for expressions and declarations with an implied 'any' type. */
 | 
			
		||||
    // "strictNullChecks": true,                         /* When type checking, take into account 'null' and 'undefined'. */
 | 
			
		||||
    // "strictFunctionTypes": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
 | 
			
		||||
    // "strictBindCallApply": true,                      /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
 | 
			
		||||
    // "strictPropertyInitialization": true,             /* Check for class properties that are declared but not set in the constructor. */
 | 
			
		||||
    // "noImplicitThis": true,                           /* Enable error reporting when 'this' is given the type 'any'. */
 | 
			
		||||
    // "useUnknownInCatchVariables": true,               /* Default catch clause variables as 'unknown' instead of 'any'. */
 | 
			
		||||
    // "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */
 | 
			
		||||
    // "noUnusedLocals": true,                           /* Enable error reporting when local variables aren't read. */
 | 
			
		||||
    // "noUnusedParameters": true,                       /* Raise an error when a function parameter isn't read. */
 | 
			
		||||
    // "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */
 | 
			
		||||
    // "noImplicitReturns": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */
 | 
			
		||||
    // "noFallthroughCasesInSwitch": true,               /* Enable error reporting for fallthrough cases in switch statements. */
 | 
			
		||||
    // "noUncheckedIndexedAccess": true,                 /* Add 'undefined' to a type when accessed using an index. */
 | 
			
		||||
    // "noImplicitOverride": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */
 | 
			
		||||
    // "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type. */
 | 
			
		||||
    // "allowUnusedLabels": true,                        /* Disable error reporting for unused labels. */
 | 
			
		||||
    // "allowUnreachableCode": true,                     /* Disable error reporting for unreachable code. */
 | 
			
		||||
 | 
			
		||||
    /* Completeness */
 | 
			
		||||
    // "skipDefaultLibCheck": true,                      /* Skip type checking .d.ts files that are included with TypeScript. */
 | 
			
		||||
    "skipLibCheck": true                                 /* Skip type checking all .d.ts files. */
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue