From ad897dc1e1a38c3968487937ae6cd906586cc4b2 Mon Sep 17 00:00:00 2001 From: hyoseung Date: Tue, 12 May 2026 13:11:19 +0900 Subject: [PATCH] feat: initial english learning backend --- .gitignore | 4 ++ nest-cli.json | 5 ++ package.json | 29 ++++++++++ src/app.module.ts | 36 +++++++++++++ src/grammar/entities/grammar.entity.ts | 22 ++++++++ src/grammar/grammar.controller.ts | 9 ++++ src/grammar/grammar.module.ts | 12 +++++ src/grammar/grammar.service.ts | 11 ++++ src/main.ts | 11 ++++ src/phrases/entities/phrase.entity.ts | 19 +++++++ src/phrases/phrases.controller.ts | 10 ++++ src/phrases/phrases.module.ts | 13 +++++ src/phrases/phrases.service.ts | 20 +++++++ src/quest/entities/quest.entity.ts | 25 +++++++++ src/quest/entities/streak.entity.ts | 22 ++++++++ src/quest/quest.controller.ts | 27 ++++++++++ src/quest/quest.module.ts | 14 +++++ src/quest/quest.service.ts | 72 +++++++++++++++++++++++++ src/quiz/entities/quiz-result.entity.ts | 19 +++++++ src/quiz/quiz.controller.ts | 11 ++++ src/quiz/quiz.module.ts | 14 +++++ src/quiz/quiz.service.ts | 35 ++++++++++++ src/words/entities/word.entity.ts | 34 ++++++++++++ src/words/words.controller.ts | 27 ++++++++++ src/words/words.module.ts | 13 +++++ src/words/words.service.ts | 44 +++++++++++++++ tsconfig.json | 21 ++++++++ 27 files changed, 579 insertions(+) create mode 100644 .gitignore create mode 100644 nest-cli.json create mode 100644 package.json create mode 100644 src/app.module.ts create mode 100644 src/grammar/entities/grammar.entity.ts create mode 100644 src/grammar/grammar.controller.ts create mode 100644 src/grammar/grammar.module.ts create mode 100644 src/grammar/grammar.service.ts create mode 100644 src/main.ts create mode 100644 src/phrases/entities/phrase.entity.ts create mode 100644 src/phrases/phrases.controller.ts create mode 100644 src/phrases/phrases.module.ts create mode 100644 src/phrases/phrases.service.ts create mode 100644 src/quest/entities/quest.entity.ts create mode 100644 src/quest/entities/streak.entity.ts create mode 100644 src/quest/quest.controller.ts create mode 100644 src/quest/quest.module.ts create mode 100644 src/quest/quest.service.ts create mode 100644 src/quiz/entities/quiz-result.entity.ts create mode 100644 src/quiz/quiz.controller.ts create mode 100644 src/quiz/quiz.module.ts create mode 100644 src/quiz/quiz.service.ts create mode 100644 src/words/entities/word.entity.ts create mode 100644 src/words/words.controller.ts create mode 100644 src/words/words.module.ts create mode 100644 src/words/words.service.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8625bf9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +dist/ +*.js.map +.env diff --git a/nest-cli.json b/nest-cli.json new file mode 100644 index 0000000..2566481 --- /dev/null +++ b/nest-cli.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://json.schemastore.org/nest-cli", + "collection": "@nestjs/schematics", + "sourceRoot": "src" +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..32adcb9 --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "english-back", + "version": "1.0.0", + "scripts": { + "start": "nest start", + "start:dev": "nest start --watch", + "build": "nest build" + }, + "dependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "@nestjs/typeorm": "^10.0.0", + "@nestjs/schedule": "^4.0.0", + "typeorm": "^0.3.0", + "mysql2": "^3.0.0", + "reflect-metadata": "^0.1.13", + "rxjs": "^7.8.0", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.0" + }, + "devDependencies": { + "@nestjs/cli": "^10.0.0", + "@nestjs/schematics": "^10.0.0", + "typescript": "^5.0.0", + "ts-node": "^10.9.1", + "@types/node": "^20.0.0" + } +} diff --git a/src/app.module.ts b/src/app.module.ts new file mode 100644 index 0000000..7bdcd79 --- /dev/null +++ b/src/app.module.ts @@ -0,0 +1,36 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { ScheduleModule } from '@nestjs/schedule'; +import { WordsModule } from './words/words.module'; +import { QuizModule } from './quiz/quiz.module'; +import { QuestModule } from './quest/quest.module'; +import { PhrasesModule } from './phrases/phrases.module'; +import { GrammarModule } from './grammar/grammar.module'; +import { Word } from './words/entities/word.entity'; +import { Phrase } from './phrases/entities/phrase.entity'; +import { GrammarLesson } from './grammar/entities/grammar.entity'; +import { DailyQuest } from './quest/entities/quest.entity'; +import { QuizResult } from './quiz/entities/quiz-result.entity'; +import { Streak } from './quest/entities/streak.entity'; + +@Module({ + imports: [ + TypeOrmModule.forRoot({ + type: 'mysql', + host: 'localhost', + port: 3306, + username: 'kakao', + password: '486251daKWON@', + database: 'english_study', + entities: [Word, Phrase, GrammarLesson, DailyQuest, QuizResult, Streak], + synchronize: true, + }), + ScheduleModule.forRoot(), + WordsModule, + QuizModule, + QuestModule, + PhrasesModule, + GrammarModule, + ], +}) +export class AppModule {} diff --git a/src/grammar/entities/grammar.entity.ts b/src/grammar/entities/grammar.entity.ts new file mode 100644 index 0000000..f5f0b41 --- /dev/null +++ b/src/grammar/entities/grammar.entity.ts @@ -0,0 +1,22 @@ +import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; + +@Entity('grammar_lessons') +export class GrammarLesson { + @PrimaryGeneratedColumn() + id: number; + + @Column() + title: string; + + @Column({ type: 'text' }) + explanation: string; + + @Column({ type: 'json' }) + examples: { en: string; ko: string }[]; + + @Column({ default: 'beginner' }) + level: string; + + @Column({ default: 1 }) + order_num: number; +} diff --git a/src/grammar/grammar.controller.ts b/src/grammar/grammar.controller.ts new file mode 100644 index 0000000..340f9f9 --- /dev/null +++ b/src/grammar/grammar.controller.ts @@ -0,0 +1,9 @@ +import { Controller, Get, Param } from '@nestjs/common'; +import { GrammarService } from './grammar.service'; + +@Controller('grammar') +export class GrammarController { + constructor(private readonly service: GrammarService) {} + @Get() findAll() { return this.service.findAll(); } + @Get(':id') findOne(@Param('id') id: string) { return this.service.findOne(+id); } +} diff --git a/src/grammar/grammar.module.ts b/src/grammar/grammar.module.ts new file mode 100644 index 0000000..93f3cfc --- /dev/null +++ b/src/grammar/grammar.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { GrammarLesson } from './entities/grammar.entity'; +import { GrammarController } from './grammar.controller'; +import { GrammarService } from './grammar.service'; + +@Module({ + imports: [TypeOrmModule.forFeature([GrammarLesson])], + controllers: [GrammarController], + providers: [GrammarService], +}) +export class GrammarModule {} diff --git a/src/grammar/grammar.service.ts b/src/grammar/grammar.service.ts new file mode 100644 index 0000000..6b6b5b4 --- /dev/null +++ b/src/grammar/grammar.service.ts @@ -0,0 +1,11 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { GrammarLesson } from './entities/grammar.entity'; + +@Injectable() +export class GrammarService { + constructor(@InjectRepository(GrammarLesson) private repo: Repository) {} + findAll() { return this.repo.find({ order: { order_num: 'ASC' } }); } + findOne(id: number) { return this.repo.findOne({ where: { id } }); } +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..64befcd --- /dev/null +++ b/src/main.ts @@ -0,0 +1,11 @@ +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; + +async function bootstrap() { + const app = await NestFactory.create(AppModule); + app.enableCors({ origin: '*' }); + app.setGlobalPrefix('api'); + await app.listen(3011); + console.log('English Learning API running on port 3011'); +} +bootstrap(); diff --git a/src/phrases/entities/phrase.entity.ts b/src/phrases/entities/phrase.entity.ts new file mode 100644 index 0000000..e53546a --- /dev/null +++ b/src/phrases/entities/phrase.entity.ts @@ -0,0 +1,19 @@ +import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; + +@Entity('phrases') +export class Phrase { + @PrimaryGeneratedColumn() + id: number; + + @Column() + english: string; + + @Column() + korean: string; + + @Column({ default: 'greeting' }) + category: string; + + @Column({ nullable: true }) + situation: string; +} diff --git a/src/phrases/phrases.controller.ts b/src/phrases/phrases.controller.ts new file mode 100644 index 0000000..1d74796 --- /dev/null +++ b/src/phrases/phrases.controller.ts @@ -0,0 +1,10 @@ +import { Controller, Get, Query } from '@nestjs/common'; +import { PhrasesService } from './phrases.service'; + +@Controller('phrases') +export class PhrasesController { + constructor(private readonly service: PhrasesService) {} + @Get() findAll(@Query('category') category?: string) { return this.service.findAll(category); } + @Get('categories') getCategories() { return this.service.getCategories(); } + @Get('daily') getDaily() { return this.service.getDailyPhrases(); } +} diff --git a/src/phrases/phrases.module.ts b/src/phrases/phrases.module.ts new file mode 100644 index 0000000..afefedf --- /dev/null +++ b/src/phrases/phrases.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { Phrase } from './entities/phrase.entity'; +import { PhrasesController } from './phrases.controller'; +import { PhrasesService } from './phrases.service'; + +@Module({ + imports: [TypeOrmModule.forFeature([Phrase])], + controllers: [PhrasesController], + providers: [PhrasesService], + exports: [PhrasesService], +}) +export class PhrasesModule {} diff --git a/src/phrases/phrases.service.ts b/src/phrases/phrases.service.ts new file mode 100644 index 0000000..11702d9 --- /dev/null +++ b/src/phrases/phrases.service.ts @@ -0,0 +1,20 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { Phrase } from './entities/phrase.entity'; + +@Injectable() +export class PhrasesService { + constructor(@InjectRepository(Phrase) private repo: Repository) {} + findAll(category?: string) { + if (category) return this.repo.find({ where: { category } }); + return this.repo.find(); + } + getCategories() { + return this.repo.createQueryBuilder('p').select('DISTINCT p.category', 'category').getRawMany(); + } + async getDailyPhrases(): Promise { + const all = await this.repo.find(); + return all.sort(() => Math.random() - 0.5).slice(0, 3); + } +} diff --git a/src/quest/entities/quest.entity.ts b/src/quest/entities/quest.entity.ts new file mode 100644 index 0000000..d945c9e --- /dev/null +++ b/src/quest/entities/quest.entity.ts @@ -0,0 +1,25 @@ +import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; + +@Entity('daily_quests') +export class DailyQuest { + @PrimaryGeneratedColumn() + id: number; + + @Column() + session_id: string; + + @Column({ type: 'date' }) + quest_date: string; + + @Column({ default: false }) + word_done: boolean; + + @Column({ default: false }) + phrase_done: boolean; + + @Column({ default: false }) + quiz_done: boolean; + + @Column({ nullable: true }) + quiz_score: number; +} diff --git a/src/quest/entities/streak.entity.ts b/src/quest/entities/streak.entity.ts new file mode 100644 index 0000000..298440d --- /dev/null +++ b/src/quest/entities/streak.entity.ts @@ -0,0 +1,22 @@ +import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; + +@Entity('streaks') +export class Streak { + @PrimaryGeneratedColumn() + id: number; + + @Column({ unique: true }) + session_id: string; + + @Column({ default: 0 }) + current_streak: number; + + @Column({ default: 0 }) + max_streak: number; + + @Column({ type: 'date', nullable: true }) + last_date: string; + + @Column({ type: 'json', nullable: true }) + history: string[]; +} diff --git a/src/quest/quest.controller.ts b/src/quest/quest.controller.ts new file mode 100644 index 0000000..360fca9 --- /dev/null +++ b/src/quest/quest.controller.ts @@ -0,0 +1,27 @@ +import { Controller, Get, Post, Body, Param, Query } from '@nestjs/common'; +import { QuestService } from './quest.service'; + +@Controller('quest') +export class QuestController { + constructor(private readonly service: QuestService) {} + + @Get('today') + getToday(@Query('session') session: string) { + return this.service.getOrCreateQuest(session || 'default'); + } + + @Post('complete') + complete(@Body() body: { session_id: string; type: 'word' | 'phrase' | 'quiz'; score?: number }) { + return this.service.completeQuest(body.session_id, body.type, body.score); + } + + @Get('streak') + getStreak(@Query('session') session: string) { + return this.service.getStreak(session || 'default'); + } + + @Get('history') + getHistory(@Query('session') session: string) { + return this.service.getHistory(session || 'default'); + } +} diff --git a/src/quest/quest.module.ts b/src/quest/quest.module.ts new file mode 100644 index 0000000..689a6ca --- /dev/null +++ b/src/quest/quest.module.ts @@ -0,0 +1,14 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { DailyQuest } from './entities/quest.entity'; +import { Streak } from './entities/streak.entity'; +import { QuestController } from './quest.controller'; +import { QuestService } from './quest.service'; + +@Module({ + imports: [TypeOrmModule.forFeature([DailyQuest, Streak])], + controllers: [QuestController], + providers: [QuestService], + exports: [QuestService], +}) +export class QuestModule {} diff --git a/src/quest/quest.service.ts b/src/quest/quest.service.ts new file mode 100644 index 0000000..d9ea60c --- /dev/null +++ b/src/quest/quest.service.ts @@ -0,0 +1,72 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { DailyQuest } from './entities/quest.entity'; +import { Streak } from './entities/streak.entity'; + +@Injectable() +export class QuestService { + constructor( + @InjectRepository(DailyQuest) private questRepo: Repository, + @InjectRepository(Streak) private streakRepo: Repository, + ) {} + + async getOrCreateQuest(session_id: string): Promise { + const today = new Date().toISOString().split('T')[0]; + let quest = await this.questRepo.findOne({ where: { session_id, quest_date: today } }); + if (!quest) { + quest = this.questRepo.create({ session_id, quest_date: today }); + await this.questRepo.save(quest); + } + return quest; + } + + async completeQuest(session_id: string, type: 'word' | 'phrase' | 'quiz', score?: number): Promise { + const quest = await this.getOrCreateQuest(session_id); + if (type === 'word') quest.word_done = true; + if (type === 'phrase') quest.phrase_done = true; + if (type === 'quiz') { quest.quiz_done = true; if (score !== undefined) quest.quiz_score = score; } + await this.questRepo.save(quest); + + if (quest.word_done && quest.phrase_done && quest.quiz_done) { + await this.updateStreak(session_id); + } + return quest; + } + + async getStreak(session_id: string): Promise { + let streak = await this.streakRepo.findOne({ where: { session_id } }); + if (!streak) { + streak = this.streakRepo.create({ session_id, history: [] }); + await this.streakRepo.save(streak); + } + return streak; + } + + async updateStreak(session_id: string): Promise { + const today = new Date().toISOString().split('T')[0]; + let streak = await this.getStreak(session_id); + if (streak.last_date === today) return streak; + + const yesterday = new Date(); + yesterday.setDate(yesterday.getDate() - 1); + const yest = yesterday.toISOString().split('T')[0]; + + if (streak.last_date === yest) { + streak.current_streak += 1; + } else { + streak.current_streak = 1; + } + streak.max_streak = Math.max(streak.max_streak, streak.current_streak); + streak.last_date = today; + if (!streak.history) streak.history = []; + if (!streak.history.includes(today)) streak.history.push(today); + return this.streakRepo.save(streak); + } + + async getHistory(session_id: string) { + const quests = await this.questRepo.find({ where: { session_id } }); + const streak = await this.getStreak(session_id); + return { quests, streak }; + } +} diff --git a/src/quiz/entities/quiz-result.entity.ts b/src/quiz/entities/quiz-result.entity.ts new file mode 100644 index 0000000..7bd07a0 --- /dev/null +++ b/src/quiz/entities/quiz-result.entity.ts @@ -0,0 +1,19 @@ +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn } from 'typeorm'; + +@Entity('quiz_results') +export class QuizResult { + @PrimaryGeneratedColumn() + id: number; + + @Column() + session_id: string; + + @Column() + score: number; + + @Column() + total: number; + + @CreateDateColumn() + created_at: Date; +} diff --git a/src/quiz/quiz.controller.ts b/src/quiz/quiz.controller.ts new file mode 100644 index 0000000..414ce6f --- /dev/null +++ b/src/quiz/quiz.controller.ts @@ -0,0 +1,11 @@ +import { Controller, Get, Post, Body, Query } from '@nestjs/common'; +import { QuizService } from './quiz.service'; + +@Controller('quiz') +export class QuizController { + constructor(private readonly service: QuizService) {} + @Get('generate') generate(@Query('count') count?: string) { return this.service.generateQuiz(count ? +count : 5); } + @Post('result') saveResult(@Body() body: { session_id: string; score: number; total: number }) { + return this.service.saveResult(body.session_id, body.score, body.total); + } +} diff --git a/src/quiz/quiz.module.ts b/src/quiz/quiz.module.ts new file mode 100644 index 0000000..49498d7 --- /dev/null +++ b/src/quiz/quiz.module.ts @@ -0,0 +1,14 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { QuizResult } from './entities/quiz-result.entity'; +import { QuizController } from './quiz.controller'; +import { QuizService } from './quiz.service'; +import { WordsModule } from '../words/words.module'; + +@Module({ + imports: [TypeOrmModule.forFeature([QuizResult]), WordsModule], + controllers: [QuizController], + providers: [QuizService], + exports: [QuizService], +}) +export class QuizModule {} diff --git a/src/quiz/quiz.service.ts b/src/quiz/quiz.service.ts new file mode 100644 index 0000000..93df5b6 --- /dev/null +++ b/src/quiz/quiz.service.ts @@ -0,0 +1,35 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { QuizResult } from './entities/quiz-result.entity'; +import { WordsService } from '../words/words.service'; + +@Injectable() +export class QuizService { + constructor( + @InjectRepository(QuizResult) private repo: Repository, + private wordsService: WordsService, + ) {} + + async generateQuiz(count = 5) { + const words = await this.wordsService.getQuizWords(count + 12); + const selected = words.slice(0, count); + const pool = words.slice(count); + + return selected.map((word) => { + const wrong = pool.sort(() => Math.random() - 0.5).slice(0, 3); + const choices = [word.korean, ...wrong.map((w) => w.korean)].sort(() => Math.random() - 0.5); + return { + id: word.id, + english: word.english, + pronunciation: word.pronunciation, + answer: word.korean, + choices, + }; + }); + } + + saveResult(session_id: string, score: number, total: number) { + return this.repo.save({ session_id, score, total }); + } +} diff --git a/src/words/entities/word.entity.ts b/src/words/entities/word.entity.ts new file mode 100644 index 0000000..ac3b86a --- /dev/null +++ b/src/words/entities/word.entity.ts @@ -0,0 +1,34 @@ +import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; + +@Entity('words') +export class Word { + @PrimaryGeneratedColumn() + id: number; + + @Column() + english: string; + + @Column() + korean: string; + + @Column({ nullable: true }) + pronunciation: string; + + @Column({ default: 'general' }) + category: string; + + @Column({ default: 'beginner' }) + difficulty: string; + + @Column({ nullable: true, type: 'text' }) + example_en: string; + + @Column({ nullable: true, type: 'text' }) + example_ko: string; + + @Column({ default: false }) + is_daily: boolean; + + @Column({ type: 'date', nullable: true }) + daily_date: string; +} diff --git a/src/words/words.controller.ts b/src/words/words.controller.ts new file mode 100644 index 0000000..a5cf8f5 --- /dev/null +++ b/src/words/words.controller.ts @@ -0,0 +1,27 @@ +import { Controller, Get, Query } from '@nestjs/common'; +import { WordsService } from './words.service'; + +@Controller('words') +export class WordsController { + constructor(private readonly service: WordsService) {} + + @Get() + findAll(@Query('category') category?: string) { + return this.service.findAll(category); + } + + @Get('daily') + getDaily() { + return this.service.getDailyWords(); + } + + @Get('quiz') + getQuizWords(@Query('count') count?: string) { + return this.service.getQuizWords(count ? +count : 10); + } + + @Get('categories') + getCategories() { + return this.service.getCategories(); + } +} diff --git a/src/words/words.module.ts b/src/words/words.module.ts new file mode 100644 index 0000000..823bc7c --- /dev/null +++ b/src/words/words.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { Word } from './entities/word.entity'; +import { WordsController } from './words.controller'; +import { WordsService } from './words.service'; + +@Module({ + imports: [TypeOrmModule.forFeature([Word])], + controllers: [WordsController], + providers: [WordsService], + exports: [WordsService], +}) +export class WordsModule {} diff --git a/src/words/words.service.ts b/src/words/words.service.ts new file mode 100644 index 0000000..3db1bd1 --- /dev/null +++ b/src/words/words.service.ts @@ -0,0 +1,44 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { Word } from './entities/word.entity'; + +@Injectable() +export class WordsService { + constructor(@InjectRepository(Word) private repo: Repository) {} + + findAll(category?: string) { + if (category) return this.repo.find({ where: { category } }); + return this.repo.find(); + } + + findByCategory(category: string) { + return this.repo.find({ where: { category } }); + } + + async getDailyWords(): Promise { + const today = new Date().toISOString().split('T')[0]; + const existing = await this.repo.find({ where: { daily_date: today, is_daily: true } }); + if (existing.length >= 5) return existing; + + const all = await this.repo.find(); + const shuffled = all.sort(() => Math.random() - 0.5).slice(0, 5); + for (const w of shuffled) { + w.is_daily = true; + w.daily_date = today; + } + return this.repo.save(shuffled); + } + + async getQuizWords(count = 10): Promise { + const all = await this.repo.find(); + return all.sort(() => Math.random() - 0.5).slice(0, count); + } + + getCategories() { + return this.repo + .createQueryBuilder('w') + .select('DISTINCT w.category', 'category') + .getRawMany(); + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..65b8a3e --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "ES2017", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": false, + "noImplicitAny": false, + "strictBindCallApply": false, + "forceConsistentCasingInFileNames": false, + "noFallthroughCasesInSwitch": false + } +}