diff --git a/.env b/.env index e69de29..3eb78d0 100644 --- a/.env +++ b/.env @@ -0,0 +1 @@ +AUTHTOKEN=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiJmWVlwNF8ybmRaTmxEM1UweWU1eGciLCJleHAiOjE3NjExMjAxNTIuODYzLCJpYXQiOjE3NjExMTkyNTJ9.UDf9OZqqC8uXnkKXnqdXJDrVGbSPo_Q9IT9x2tf8mcJEu9qm3twTcfqNetbLlsw9b4bERyoh1waXIzCJj8hCIWK-oRMenbzdjbSqMl29_36tNV204fnuGXhEMo8-NXS6k9DCQ74-1xd1IOGcACP4rHyDcKvEY46D_ccfJL-TR_TGFIxJrt05SGrBWNr4I2AFQ4I-uq23jInphIkOggw356dNIRvfinhoGYkju8IUiUIGUFTMgXom9rBm-RR2k9MhHm9d0FqMuGGrB5dlFzvGXc7LUIabC4-MIc17g6U2aqPGCuyTSHkmCsWJQE9y4wZZ2m6px7wkyIOtYjbhDnzFhw \ No newline at end of file diff --git a/.gitignore b/.gitignore index 2606ba6..01f9edd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ songs/ json-data/ node_modules/ +dist \ No newline at end of file diff --git a/downloadSong.js b/downloadSong.ts similarity index 63% rename from downloadSong.js rename to downloadSong.ts index 34d947c..c03e81b 100644 --- a/downloadSong.js +++ b/downloadSong.ts @@ -1,7 +1,7 @@ -import https from 'https'; -import fs from 'fs'; +import * as https from 'https'; +import * as fs from 'fs'; -async function downloadSong(downloadLink, folder, filename, songCount) { +async function downloadSong(downloadLink: string, folder: string, filename: string, songCount: number): Promise { console.log(`Downloading song #${songCount} ...`) return new Promise((resolve, reject) => { https.get(downloadLink, (response) => { @@ -10,7 +10,7 @@ async function downloadSong(downloadLink, folder, filename, songCount) { console.log(`${songCount} songs downloaded successfully`); resolve(); }) - .on('error', (error) => { + .on('error', (error: Error) => { console.error('Error downloading song:', error); reject(error); }); @@ -18,8 +18,8 @@ async function downloadSong(downloadLink, folder, filename, songCount) { }); } -process.on('message', async (message) => { +process.on('message', async (message: any) => { const { downloadLink, folder, filename, songCount } = message; await downloadSong(downloadLink, folder, filename, songCount); - process.send(`Song #${songCount} downloaded successfully`); + process.send && process.send(`Song #${songCount} downloaded successfully`); }); \ No newline at end of file diff --git a/genres.http b/genres.http deleted file mode 100644 index ebbce77..0000000 --- a/genres.http +++ /dev/null @@ -1,2 +0,0 @@ -GET https://api.brain.fm/v2/mental-states/6042a1bad80ae028b821e958/genres/ -Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiJGYmd3dndBT1JCTjlibVJmRUxLcHciLCJleHAiOjE2ODE5ODg5MTUuMzU2LCJpYXQiOjE2ODE5ODgwMTV9.hCs0U5Iv5bgaU9oYi9kmSl0A_gt3V9svL0NiCEvtZFr4DXiNQwkt30fUtwOofMmHUnoEKiRt8ER-K8n5vsXKc23gvvcKaYEzY1kipwlAkK_JiYslE1FXDGXBBN1VrunACWLY5sWyRt1og6WP20BaoD0gIvBr0iazN323mlpU_Ls4yOrid2J_veXAwmCkW_26Q2NbhJeEV2rlwnV95CtxmogYHkoDrDz65UncU5AUvl4ae96il9IN7MSI0DvFl3NutVnD3B2wPaNHNAIoMC1_nLwWl5Q5GMbgC2AW3B1U0pozg78ePFVWq-mKYY8IbgjESNKWg1gRF5oknsFq8shxjw \ No newline at end of file diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..5d453d6 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "Bundler", + "target": "ES2024", + "jsx": "react-jsx", + "allowImportingTsExtensions": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strict": true + }, + "exclude": [ + "node_modules", + "**/node_modules/*" + ] +} \ No newline at end of file diff --git a/main.js b/main.ts similarity index 63% rename from main.js rename to main.ts index 2ef487f..eaad75a 100644 --- a/main.js +++ b/main.ts @@ -1,10 +1,8 @@ -// @ts-check - -import fs from 'fs'; -import https from 'https'; +import * as fs from 'fs'; +import * as https from 'https'; import chalk from 'chalk'; -import {config} from 'dotenv'; -config() +import * as dotenv from 'dotenv'; +dotenv.config(); let songCount = 1; @@ -15,15 +13,20 @@ if (!AUTHTOKEN) { process.exit(1); } -/** @typedef {("focus" | "relax" | "sleep" | "meditate")} mentalState */ +type MentalState = "focus" | "relax" | "sleep" | "meditate"; -/** @type {mentalState[]} */ -let mentalStates = ["focus", "relax", "sleep", "meditate"] +type MentalStateArray = MentalState[]; -/** - * @type {Record} - */ -let genres = { +let mentalStates: MentalStateArray = ["focus", "relax", "sleep", "meditate"]; + +type GenreStructure = { + base: string[]; + nature: string[]; +}; + +type GenresMap = Record; + +let genres: GenresMap = { "focus": { base: [ "Acoustic", @@ -104,8 +107,11 @@ let genres = { } }; -// @ts-ignore -let moods = { +// Commenting out moods since it's not used in the code +/* +type MoodsMap = Record; + +let moods: MoodsMap = { "focus": [ "Brooding", "Calm", @@ -195,42 +201,54 @@ let moods = { "Uplifting" ] } +*/ -/** - * @typedef {{url: string, folder: string, filename: string}} QueueEntry - */ +type QueueEntry = { + url: string; + folder: string; + filename: string; +}; class DownloadQueue { - /** @param {number} maxConcurrency */ - constructor(maxConcurrency) { - /** @type {QueueEntry[]} */ - this.queue = []; - this.activeDownloads = 0; - this.maxConcurrency = maxConcurrency; + private queue: QueueEntry[] = []; + private activeDownloads = 0; + private maxConcurrency: number + + constructor(maxConcurrency: number) { + this.maxConcurrency = maxConcurrency } - - /** - * @param {string} url - * @param {string} folder - * @param {string} filename - */ - enqueue(url, folder, filename) { + public enqueue(url: string, folder: string, filename: string) { this.queue.push({ url, folder, filename }); + // Only process the queue if we're not at max capacity this.processQueue(); } - async processQueue() { - if (this.activeDownloads < this.maxConcurrency && this.queue.length > 0) { - // @ts-ignore - const { url, folder, filename } = this.queue.shift(); + private async processQueue(): Promise { + // Keep processing while we have capacity and items in the queue + while (this.activeDownloads < this.maxConcurrency && this.queue.length > 0) { + const { url, folder, filename } = this.queue.shift()!; this.activeDownloads++; - await downloadSong(url, folder, filename); - console.log(`${songCount} songs downloaded successfully \n${this.queue.length} remaining`) - this.activeDownloads--; - this.processQueue(); + + // Process the download asynchronously but continue the loop immediately + // to potentially start more downloads if there's capacity + this.processDownload(url, folder, filename).then(() => { + // After download is complete, decrease activeDownloads and continue processing + this.activeDownloads--; + this.processQueue(); // Process next item in queue + }).catch((error) => { + console.error('Error downloading song:', error); + this.activeDownloads--; + this.processQueue(); // Continue processing queue even if there's an error + }); } } + + private async processDownload(url: string, folder: string, filename: string): Promise { + await downloadSong(url, folder, filename); + console.log(`${songCount} songs downloaded successfully \n${this.queue.length} remaining`); + songCount++; // Increment the song count after completion + } } const downloadQueue = new DownloadQueue(3) @@ -243,15 +261,13 @@ for (const mentalState of mentalStates) { // // Phase 1 : Fetch all song data // - let data = await fetch(`https://api.brain.fm/v3/servings/search?genre=${genre}&dynamicMentalStateId=${mentalState}`, { + const response = await fetch(`https://api.brain.fm/v3/servings/search?genre=${genre}&dynamicMentalStateId=${mentalState}`, { headers: { authorization: `Bearer ${AUTHTOKEN}` } }); - data = await data.json(); - - // @ts-ignore - data = formatAudioData(data.result); + const responseData = await response.json(); + const data = formatAudioData(responseData.result); if (checkIfJsonExists(`./json-data/${mentalState}/${genre}.json`)) continue; ensureDirectory(`./json-data/${mentalState}`); @@ -266,10 +282,8 @@ for (const mentalState of mentalStates) { // console.log(chalk.green(`Started downloading ${genre} ${mentalState}`)) - // @ts-ignore for (const song of data) { - // @ts-ignore - let activity = song.track.tags.filter(x => x.type == 'activity').map(x => x.value).join('/'); + let activity = song.track.tags.filter((x: any) => x.type == 'activity').map((x: any) => x.value).join('/'); let NEL = song.trackVariation.neuralEffectLevel; let level = (NEL > 0.66 ? "high" : NEL > 0.33 ? "medium" : "low"); @@ -284,19 +298,16 @@ for (const mentalState of mentalStates) { }; - -// @ts-ignore -async function downloadSong(downloadLink, folder, filename) { +function downloadSong(downloadLink: string, folder: string, filename: string): Promise { return new Promise((resolve, reject) => { ensureDirectory(folder) https.get(downloadLink, (response) => { response.pipe(fs.createWriteStream(`${folder}/${filename}.mp3`)) .on('finish', () => { songCount++ - // @ts-ignore resolve(); }) - .on('error', (error) => { + .on('error', (error: Error) => { console.error('Error downloading song:', error); reject(error); }); @@ -304,25 +315,19 @@ async function downloadSong(downloadLink, folder, filename) { }); } -// @ts-ignore -function formatAudioData(arr) { - // @ts-ignore +function formatAudioData(arr: any[]) { return arr.map(item => { delete item.track.similarTracks; return item; }); } -// @ts-ignore -function ensureDirectory(directory) { +function ensureDirectory(directory: string) { if (!fs.existsSync(directory)) { fs.mkdirSync(directory, { recursive: true }); } } -// @ts-ignore -function checkIfJsonExists(mentalState, genre) { - const filePath = `./json-data/${mentalState}/${genre}.json`; +function checkIfJsonExists(filePath: string) { return fs.existsSync(filePath); -} - +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8fb92bf..404f61f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,133 @@ "dependencies": { "chalk": "^5.2.0", "dotenv": "^16.0.3" + }, + "devDependencies": { + "@types/chalk": "^0.4.31", + "@types/node": "^24.9.1", + "ts-node": "^10.9.2", + "typescript": "^5.9.3" } }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chalk": { + "version": "0.4.31", + "resolved": "https://registry.npmjs.org/@types/chalk/-/chalk-0.4.31.tgz", + "integrity": "sha512-nF0fisEPYMIyfrFgabFimsz9Lnuu9MwkNrrlATm2E4E46afKDyeelT+8bXfw1VSc7sLBxMxRgT7PxTC2JcqN4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.1.tgz", + "integrity": "sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, "node_modules/chalk": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", @@ -24,6 +149,23 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/dotenv": { "version": "16.0.3", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", @@ -31,6 +173,95 @@ "engines": { "node": ">=12" } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } } } } diff --git a/package.json b/package.json index 240b4af..42ea00e 100644 --- a/package.json +++ b/package.json @@ -2,9 +2,12 @@ "name": "brainfm-extract", "version": "1.0.0", "description": "", - "main": "main.js", + "main": "dist/main.js", "type": "module", "scripts": { + "build": "tsc", + "start": "npm run build && node dist/main.js", + "dev": "ts-node main.ts", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], @@ -13,5 +16,11 @@ "dependencies": { "chalk": "^5.2.0", "dotenv": "^16.0.3" + }, + "devDependencies": { + "@types/chalk": "^0.4.31", + "@types/node": "^24.9.1", + "ts-node": "^10.9.2", + "typescript": "^5.9.3" } } diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..9ee6139 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + "target": "ES2024", + "module": "ESNext", + "moduleResolution": "Bundler", + "outDir": "./dist", + "rootDir": "./", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "removeComments": false, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "noImplicitReturns": true, + "noImplicitOverride": true, + "noUnusedLocals": true, + "noUnusedParameters": true + }, + "include": [ + "./**/*.ts" + ], + "exclude": [ + "node_modules", + "dist", + "**/node_modules/*" + ] +} \ No newline at end of file