refactor: Update import statements and configurations for ES module compatibility

This commit is contained in:
Jose Daniel G. Percy 2025-04-25 00:41:40 +08:00
parent c613ef3f35
commit 1aa97a8a7a
14 changed files with 237 additions and 115 deletions

View File

@ -1,7 +1,7 @@
import { REST, Routes, APIApplicationCommand } from "discord.js"; import { REST, Routes, APIApplicationCommand } from "discord.js";
import fs from "node:fs"; import fs from "node:fs";
import path from "node:path"; import path from "node:path";
import logger from "./src/utils/logger"; // Use default import now import logger from "./src/utils/logger.js"; // Added .js extension for ES modules
import dotenv from "dotenv"; import dotenv from "dotenv";
// --- Setup --- // --- Setup ---
@ -33,8 +33,9 @@ const loadCommandsForDeployment = async () => {
for (const file of commandFiles) { for (const file of commandFiles) {
const filePath = path.join(commandsPath, file); const filePath = path.join(commandsPath, file);
try { try {
// Use dynamic import // Use dynamic import with file:// protocol for ES modules
const commandModule = await import(filePath); const fileUrl = new URL(`file://${filePath}`);
const commandModule = await import(fileUrl.href);
// Assuming commands export default or have a 'default' property // Assuming commands export default or have a 'default' property
const command = commandModule.default || commandModule; const command = commandModule.default || commandModule;

View File

@ -3,6 +3,7 @@
"version": "1.0.0", "version": "1.0.0",
"description": "", "description": "",
"main": "dist/index.js", "main": "dist/index.js",
"type": "module",
"scripts": { "scripts": {
"build": "tsc -p tsconfig.json", "build": "tsc -p tsconfig.json",
"build:deploy": "tsc -p tsconfig.deploy.json", "build:deploy": "tsc -p tsconfig.deploy.json",

60
scripts/fix-imports.cjs Executable file
View File

@ -0,0 +1,60 @@
const fs = require('fs');
const path = require('path');
// Get all TypeScript files in a directory recursively
function getTypeScriptFiles(dir) {
const files = [];
function traverse(currentDir) {
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(currentDir, entry.name);
if (entry.isDirectory()) {
traverse(fullPath);
} else if (entry.isFile() && entry.name.endsWith('.ts')) {
files.push(fullPath);
}
}
}
traverse(dir);
return files;
}
// Fix imports in a file
function fixImportsInFile(filePath) {
console.log(`Processing ${filePath}`);
let content = fs.readFileSync(filePath, 'utf8');
// Regular expression to match relative imports without file extensions
const importRegex = /(import\s+(?:[^'"]*\s+from\s+)?['"])(\.\.[^'"]*?)(['"])/g;
// Add .js extension to relative imports
content = content.replace(importRegex, (match, start, importPath, end) => {
// Don't add extension if it already has one or ends with a directory
if (importPath.endsWith('.js') || importPath.endsWith('/')) {
return match;
}
return `${start}${importPath}.js${end}`;
});
fs.writeFileSync(filePath, content);
}
// Main function
function main() {
const srcDir = path.join(__dirname, '..', 'src');
const files = getTypeScriptFiles(srcDir);
console.log(`Found ${files.length} TypeScript files`);
for (const file of files) {
fixImportsInFile(file);
}
console.log('Done');
}
main();

60
scripts/fix-imports.js Executable file
View File

@ -0,0 +1,60 @@
const fs = require('fs');
const path = require('path');
// Get all TypeScript files in a directory recursively
function getTypeScriptFiles(dir) {
const files = [];
function traverse(currentDir) {
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(currentDir, entry.name);
if (entry.isDirectory()) {
traverse(fullPath);
} else if (entry.isFile() && entry.name.endsWith('.ts')) {
files.push(fullPath);
}
}
}
traverse(dir);
return files;
}
// Fix imports in a file
function fixImportsInFile(filePath) {
console.log(`Processing ${filePath}`);
let content = fs.readFileSync(filePath, 'utf8');
// Regular expression to match relative imports without file extensions
const importRegex = /(import\s+(?:[^'"]*\s+from\s+)?['"])(\.\.[^'"]*?)(['"])/g;
// Add .js extension to relative imports
content = content.replace(importRegex, (match, start, importPath, end) => {
// Don't add extension if it already has one or ends with a directory
if (importPath.endsWith('.js') || importPath.endsWith('/')) {
return match;
}
return `${start}${importPath}.js${end}`;
});
fs.writeFileSync(filePath, content);
}
// Main function
function main() {
const srcDir = path.join(__dirname, '..', 'src');
const files = getTypeScriptFiles(srcDir);
console.log(`Found ${files.length} TypeScript files`);
for (const file of files) {
fixImportsInFile(file);
}
console.log('Done');
}
main();

View File

@ -6,8 +6,8 @@ import {
GuildMember, // Import GuildMember type GuildMember, // Import GuildMember type
VoiceBasedChannel, // Import VoiceBasedChannel type VoiceBasedChannel, // Import VoiceBasedChannel type
} from "discord.js"; } from "discord.js";
import logger from "../utils/logger"; // Use default import import logger from "../utils/logger.js"; // Use default import
import { BotClient } from "../index"; // Import the BotClient interface import { BotClient } from "../index.js"; // Import the BotClient interface
import { Player } from "shoukaku"; // Import the Player type explicitly import { Player } from "shoukaku"; // Import the Player type explicitly
export default { export default {

View File

@ -3,8 +3,8 @@ import {
ChatInputCommandInteraction, // Import the specific _interaction type ChatInputCommandInteraction, // Import the specific _interaction type
GuildMember, // Import GuildMember type GuildMember, // Import GuildMember type
} from "discord.js"; } from "discord.js";
import logger from "../utils/logger"; // Use default import import logger from "../utils/logger.js"; // Use default import
import { BotClient } from "../index"; // Import the BotClient interface import { BotClient } from "../index.js"; // Import the BotClient interface
// No need to import Player explicitly if we just check connection // No need to import Player explicitly if we just check connection
export default { export default {

View File

@ -8,8 +8,8 @@ import {
GuildMember, GuildMember,
VoiceBasedChannel, VoiceBasedChannel,
} from "discord.js"; } from "discord.js";
import logger from "../utils/logger"; import logger from "../utils/logger.js";
import { BotClient } from "../index"; import { BotClient } from "../index.js";
// Import necessary Shoukaku types - LavalinkResponse might need a local definition if not exported // Import necessary Shoukaku types - LavalinkResponse might need a local definition if not exported
import { Player, Node, Track, SearchResult, Connection } from "shoukaku"; import { Player, Node, Track, SearchResult, Connection } from "shoukaku";

View File

@ -1,6 +1,6 @@
import { Events, Interaction } from "discord.js"; import { Events, Interaction } from "discord.js";
import { BotClient } from "../types/botClient"; import { BotClient } from "../types/botClient.js";
import logger from "../utils/logger"; import logger from "../utils/logger.js";
export default { export default {
name: Events.InteractionCreate, name: Events.InteractionCreate,

View File

@ -1,7 +1,7 @@
import { Events, ActivityType, Client } from "discord.js"; // Import base Client type import { Events, ActivityType, Client } from "discord.js"; // Import base Client type
import logger from "../utils/logger"; // Use default import import logger from "../utils/logger.js"; // Use default import
import { initializeShoukaku } from "../structures/ShoukakuEvents"; // Import the correct setup function import { initializeShoukaku } from "../structures/ShoukakuEvents.js"; // Import the correct setup function
import { BotClient } from "../index"; // Import BotClient type import { BotClient } from "../index.js"; // Import BotClient type
export default { export default {
// Use export default // Use export default

View File

@ -1,6 +1,6 @@
import { Events, VoiceState, ChannelType } from "discord.js"; // Added ChannelType import { Events, VoiceState, ChannelType } from "discord.js"; // Added ChannelType
import logger from "../utils/logger"; import logger from "../utils/logger.js";
import { BotClient } from "../index"; // Assuming BotClient is exported from index import { BotClient } from "../index.js"; // Assuming BotClient is exported from index
export default { export default {
// Use export default for ES modules // Use export default for ES modules

View File

@ -4,38 +4,40 @@ import {
GatewayIntentBits, GatewayIntentBits,
Collection, Collection,
Events, Events,
BaseInteraction, // Use a base type for now, refine later if needed BaseInteraction,
SlashCommandBuilder, // Assuming commands use this SlashCommandBuilder,
} from "discord.js"; } from "discord.js";
import { Shoukaku, Connectors, NodeOption, ShoukakuOptions } from "shoukaku"; import { Shoukaku, Connectors, NodeOption, ShoukakuOptions } from "shoukaku";
import logger from "./utils/logger"; // Assuming logger uses export default or similar import logger from "./utils/logger.js"; // Add .js extension
import fs from "fs"; import fs from "fs";
import path from "path"; import path from "path";
// import { fileURLToPath } from 'url'; // Needed for __dirname in ES Modules if module is not CommonJS import { fileURLToPath } from 'url'; // Needed for __dirname in ES Modules
// Get __dirname equivalent in ES Modules
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Define Command structure // Define Command structure
interface Command { interface Command {
data: Omit<SlashCommandBuilder, "addSubcommand" | "addSubcommandGroup">; // Or appropriate type for your command data data: Omit<SlashCommandBuilder, "addSubcommand" | "addSubcommandGroup">;
execute: (_interaction: BaseInteraction, _client: BotClient) => Promise<void>; // Adjust _interaction type if needed execute: (_interaction: BaseInteraction, _client: BotClient) => Promise<void>;
} }
// Define Event structure // Define Event structure
interface BotEvent { interface BotEvent {
name: string; // Should match discord.js event names or custom names name: string;
once?: boolean; once?: boolean;
execute: (..._args: any[]) => void; // Use specific types later if possible execute: (..._args: any[]) => void;
} }
// Extend the discord.js Client class to include custom properties // Extend the discord.js Client class to include custom properties
export interface BotClient extends Client { export interface BotClient extends Client {
// Add export keyword
commands: Collection<string, Command>; commands: Collection<string, Command>;
shoukaku: Shoukaku; shoukaku: Shoukaku;
} }
// --- Setup --- // --- Setup ---
dotenv.config(); dotenv.config();
// __dirname is available in CommonJS modules, which is set in tsconfig.json
// Validate essential environment variables // Validate essential environment variables
if (!process.env.DISCORD_TOKEN) { if (!process.env.DISCORD_TOKEN) {
@ -46,8 +48,6 @@ if (!process.env.LAVALINK_HOST || !process.env.LAVALINK_PORT || !process.env.LAV
logger.warn( logger.warn(
"Lavalink connection details (HOST, PORT, PASSWORD) are missing or incomplete in .env. Music functionality will be limited.", "Lavalink connection details (HOST, PORT, PASSWORD) are missing or incomplete in .env. Music functionality will be limited.",
); );
// Decide if the bot should exit or continue without music
// process.exit(1); // Uncomment to exit if Lavalink is mandatory
} }
// Create a new Discord _client instance with necessary intents // Create a new Discord _client instance with necessary intents
@ -55,28 +55,27 @@ const _client = new Client({
intents: [ intents: [
GatewayIntentBits.Guilds, GatewayIntentBits.Guilds,
GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.GuildMessages, // Add if needed for prefix commands or message content GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent, // Add if needed for message content GatewayIntentBits.MessageContent,
], ],
}) as BotClient; // Assert the type here }) as BotClient;
// Define Shoukaku nodes // Define Shoukaku nodes
const Nodes: NodeOption[] = [ const Nodes: NodeOption[] = [
{ {
name: process.env.LAVALINK_NAME || "lavalink-node-1", // Use an env var or default name name: process.env.LAVALINK_NAME || "lavalink-node-1",
url: `${process.env.LAVALINK_HOST || "localhost"}:${process.env.LAVALINK_PORT || 2333}`, // Use || 2333 for default port number url: `${process.env.LAVALINK_HOST || "localhost"}:${process.env.LAVALINK_PORT || 2333}`,
auth: process.env.LAVALINK_PASSWORD || "youshallnotpass", // Password from your Lavalink server config auth: process.env.LAVALINK_PASSWORD || "youshallnotpass",
secure: process.env.LAVALINK_SECURE === "true", // Set to true if using HTTPS/WSS secure: process.env.LAVALINK_SECURE === "true",
}, },
]; ];
// Shoukaku _options // Shoukaku _options
const shoukakuOptions: ShoukakuOptions = { const shoukakuOptions: ShoukakuOptions = {
moveOnDisconnect: false, // Whether to move players to another node when a node disconnects moveOnDisconnect: false,
resume: true, // Whether to resume players session after Lavalink restarts resume: true,
reconnectTries: 3, // Number of attempts to reconnect to Lavalink reconnectTries: 3,
reconnectInterval: 5000, // Interval between reconnect attempts in milliseconds reconnectInterval: 5000,
// Add other _options as needed
}; };
// Initialize Shoukaku // Initialize Shoukaku
@ -84,7 +83,7 @@ _client.shoukaku = new Shoukaku(new Connectors.DiscordJS(_client), Nodes, shouka
// Show the actual Lavalink connection details (without exposing the actual password) // Show the actual Lavalink connection details (without exposing the actual password)
logger.info( logger.info(
`Lavalink connection configured to: ${process.env.LAVALINK_HOST}:${process.env.LAVALINK_PORT} (Password: ${process.env.LAVALINK_PASSWORD ? "[SET]" : "[NOT SET]"})`, `Lavalink connection configured to: ${process.env.LAVALINK_HOST || "localhost"}:${process.env.LAVALINK_PORT || 2333} (Password: ${process.env.LAVALINK_PASSWORD ? "[SET]" : "[NOT SET]"})`,
); );
// Collections for commands // Collections for commands
@ -92,16 +91,17 @@ _client.commands = new Collection<string, Command>();
// --- Command Loading --- // --- Command Loading ---
const commandsPath = path.join(__dirname, "commands"); const commandsPath = path.join(__dirname, "commands");
// Read .ts files now // Read .js files instead of .ts after compilation
const commandFiles = fs.readdirSync(commandsPath).filter((file: string) => file.endsWith(".ts")); const commandFiles = fs.readdirSync(commandsPath).filter((file: string) => file.endsWith(".js"));
const loadCommands = async () => { const loadCommands = async () => {
for (const file of commandFiles) { for (const file of commandFiles) {
const filePath = path.join(commandsPath, file); const filePath = path.join(commandsPath, file);
try { try {
// Use dynamic import for ES Modules/CommonJS interop // Use dynamic import with file:// protocol for ES Modules
const commandModule = await import(filePath); const fileUrl = new URL(`file://${filePath}`).href;
const command: Command = commandModule.default || commandModule; // Handle default exports const commandModule = await import(fileUrl);
const command: Command = commandModule.default || commandModule;
if (command && typeof command === "object" && "data" in command && "execute" in command) { if (command && typeof command === "object" && "data" in command && "execute" in command) {
_client.commands.set(command.data.name, command); _client.commands.set(command.data.name, command);
@ -112,7 +112,6 @@ const loadCommands = async () => {
); );
} }
} catch (error: unknown) { } catch (error: unknown) {
// Type the error as unknown
const errorMessage = error instanceof Error ? error.message : String(error); const errorMessage = error instanceof Error ? error.message : String(error);
logger.error(`Error loading command at ${filePath}: ${errorMessage}`, error); logger.error(`Error loading command at ${filePath}: ${errorMessage}`, error);
} }
@ -121,22 +120,24 @@ const loadCommands = async () => {
// --- Event Handling --- // --- Event Handling ---
const eventsPath = path.join(__dirname, "events"); const eventsPath = path.join(__dirname, "events");
// Read .ts files now // Read .js files instead of .ts after compilation
const eventFiles = fs.readdirSync(eventsPath).filter((file: string) => file.endsWith(".ts")); const eventFiles = fs.readdirSync(eventsPath).filter((file: string) => file.endsWith(".js"));
const loadEvents = async () => { const loadEvents = async () => {
for (const file of eventFiles) { for (const file of eventFiles) {
const filePath = path.join(eventsPath, file); const filePath = path.join(eventsPath, file);
try { try {
const eventModule = await import(filePath); // Use dynamic import with file:// protocol for ES Modules
const event: BotEvent = eventModule.default || eventModule; // Handle default exports const fileUrl = new URL(`file://${filePath}`).href;
const eventModule = await import(fileUrl);
const event: BotEvent = eventModule.default || eventModule;
if (event && typeof event === "object" && "name" in event && "execute" in event) { if (event && typeof event === "object" && "name" in event && "execute" in event) {
if (event.once) { if (event.once) {
_client.once(event.name, (..._args: any[]) => event.execute(..._args, _client)); // Pass _client _client.once(event.name, (..._args: any[]) => event.execute(..._args, _client));
logger.info(`Loaded event ${event.name} (once)`); logger.info(`Loaded event ${event.name} (once)`);
} else { } else {
_client.on(event.name, (..._args: any[]) => event.execute(..._args, _client)); // Pass _client _client.on(event.name, (..._args: any[]) => event.execute(..._args, _client));
logger.info(`Loaded event ${event.name}`); logger.info(`Loaded event ${event.name}`);
} }
} else { } else {
@ -161,7 +162,6 @@ _client.shoukaku.on("error", (name: string, error: Error) =>
_client.shoukaku.on("close", (name: string, code: number, reason: string | undefined) => _client.shoukaku.on("close", (name: string, code: number, reason: string | undefined) =>
logger.warn(`Lavalink Node: ${name} closed with code ${code}. Reason: ${reason || "No reason"}`), logger.warn(`Lavalink Node: ${name} closed with code ${code}. Reason: ${reason || "No reason"}`),
); );
// Corrected disconnect event signature based on common usage and error TS148
_client.shoukaku.on("disconnect", (name: string, count: number) => { _client.shoukaku.on("disconnect", (name: string, count: number) => {
logger.warn( logger.warn(
`Lavalink Node: ${name} disconnected. ${count} players were disconnected from this node.`, `Lavalink Node: ${name} disconnected. ${count} players were disconnected from this node.`,
@ -180,7 +180,7 @@ async function main() {
} catch (error: unknown) { } catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : String(error); const errorMessage = error instanceof Error ? error.message : String(error);
logger.error(`Failed to log in: ${errorMessage}`); logger.error(`Failed to log in: ${errorMessage}`);
process.exit(1); // Exit if login fails process.exit(1);
} }
} }
@ -197,6 +197,4 @@ process.on("unhandledRejection", (reason: unknown, promise: Promise<any>) => {
}); });
process.on("uncaughtException", (error: Error, origin: NodeJS.UncaughtExceptionOrigin) => { process.on("uncaughtException", (error: Error, origin: NodeJS.UncaughtExceptionOrigin) => {
logger.error(`Uncaught exception: ${error.message}`, { error, origin }); logger.error(`Uncaught exception: ${error.message}`, { error, origin });
// Optional: exit process on critical uncaught exceptions
// process.exit(1);
}); });

View File

@ -1,20 +1,19 @@
import { Shoukaku, NodeOption, ShoukakuOptions, Player, Connectors } from "shoukaku"; // Removed player event types, Added Connectors import { Shoukaku, NodeOption, ShoukakuOptions, Player, Connectors } from 'shoukaku';
// import { Connectors } from 'shoukaku-discord.js'; // Use the discord.js connector - Removed this line import logger from '../utils/logger.js';
import logger from "../utils/logger"; import { BotClient } from '../index.js';
import { BotClient } from "../index";
// Removed imports from play.ts for now as player listeners are removed // Removed imports from play.ts for now as player listeners are removed
// Define Node _options (replace with your actual Lavalink details from .env) // Define Node options (replace with your actual Lavalink details from .env)
const nodes: NodeOption[] = [ const nodes: NodeOption[] = [
{ {
name: process.env.LAVALINK_NAME || "Lavalink-Node-1", name: process.env.LAVALINK_NAME || 'Lavalink-Node-1',
url: process.env.LAVALINK_URL || "lavalink:2333", // Use service name for Docker Compose if applicable url: process.env.LAVALINK_URL || 'lavalink:2333', // Use service name for Docker Compose if applicable
auth: process.env.LAVALINK_AUTH || "youshallnotpass", auth: process.env.LAVALINK_AUTH || 'youshallnotpass',
secure: process.env.LAVALINK_SECURE === "true" || false, secure: process.env.LAVALINK_SECURE === 'true' || false,
}, },
]; ];
// Define Shoukaku _options // Define Shoukaku options
const shoukakuOptions: ShoukakuOptions = { const shoukakuOptions: ShoukakuOptions = {
moveOnDisconnect: false, moveOnDisconnect: false,
resume: false, // Resume doesn't work reliably across restarts/disconnects without session persistence resume: false, // Resume doesn't work reliably across restarts/disconnects without session persistence
@ -25,36 +24,36 @@ const shoukakuOptions: ShoukakuOptions = {
}; };
// Function to initialize Shoukaku and attach listeners // Function to initialize Shoukaku and attach listeners
export function initializeShoukaku(_client: BotClient): Shoukaku { export function initializeShoukaku(client: BotClient): Shoukaku {
if (!_client) { if (!client) {
throw new Error("initializeShoukaku requires a _client instance."); throw new Error("initializeShoukaku requires a client instance.");
} }
const shoukaku = new Shoukaku(new Connectors.DiscordJS(_client), nodes, shoukakuOptions); const shoukaku = new Shoukaku(new Connectors.DiscordJS(client), nodes, shoukakuOptions);
// --- Shoukaku Node Event Listeners --- // --- Shoukaku Node Event Listeners ---
shoukaku.on("ready", (name, resumed) => shoukaku.on('ready', (name, resumed) =>
logger.info(`Lavalink Node '${name}' ready. Resumed: ${resumed}`), logger.info(`Lavalink Node '${name}' ready. Resumed: ${resumed}`)
); );
shoukaku.on("error", (name, error) => shoukaku.on('error', (name, error) =>
logger.error(`Lavalink Node '${name}' error: ${error.message}`, error), logger.error(`Lavalink Node '${name}' error: ${error.message}`, error)
); );
shoukaku.on("close", (name, code, reason) => shoukaku.on('close', (name, code, reason) =>
logger.warn(`Lavalink Node '${name}' closed. Code: ${code}. Reason: ${reason || "No reason"}`), logger.warn(`Lavalink Node '${name}' closed. Code: ${code}. Reason: ${reason || 'No reason'}`)
); );
// Fix: Correct disconnect listener signature // Fix: Correct disconnect listener signature
shoukaku.on("disconnect", (name, count) => { shoukaku.on('disconnect', (name, count) => {
// count = count of players disconnected from the node // count = count of players disconnected from the node
logger.warn(`Lavalink Node '${name}' disconnected. ${count} players disconnected.`); logger.warn(`Lavalink Node '${name}' disconnected. ${count} players disconnected.`);
// If players were not moved, you might want to attempt to reconnect them or clean them up. // If players were not moved, you might want to attempt to reconnect them or clean them up.
}); });
shoukaku.on("debug", (name, info) => { shoukaku.on('debug', (name, info) => {
// Only log debug messages if not in production or if explicitly enabled // Only log debug messages if not in production or if explicitly enabled
if (process.env.NODE_ENV !== "production" || process.env.LAVALINK_DEBUG === "true") { if (process.env.NODE_ENV !== 'production' || process.env.LAVALINK_DEBUG === 'true') {
logger.debug(`Lavalink Node '${name}' debug: ${info}`); logger.debug(`Lavalink Node '${name}' debug: ${info}`);
} }
}); });

View File

@ -1,7 +1,9 @@
{ {
"extends": "./tsconfig.json", "extends": "./tsconfig.json",
"compilerOptions": { "compilerOptions": {
"rootDir": "." "rootDir": ".",
"module": "NodeNext",
"moduleResolution": "NodeNext"
}, },
"include": ["deploy-commands.ts"] "include": ["deploy-commands.ts"]
} }

View File

@ -1,8 +1,8 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "ES2020", "target": "ES2020",
"module": "ESNext", "module": "NodeNext",
"moduleResolution": "Node", "moduleResolution": "NodeNext",
"lib": ["ES2020"], "lib": ["ES2020"],
"outDir": "dist", "outDir": "dist",
"rootDir": "src", "rootDir": "src",
@ -13,7 +13,8 @@
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"declaration": true, "declaration": true,
"sourceMap": true "sourceMap": true,
"allowSyntheticDefaultImports": true
}, },
"include": [ "include": [
"src/**/*" "src/**/*"