├── .gitignore ├── src ├── utils │ └── types.ts ├── typeorm │ ├── entities │ │ ├── TicketConfigRole.ts │ │ ├── Ticket.ts │ │ └── TicketConfig.ts │ └── index.ts ├── handlers │ ├── chatInputCommand.ts │ ├── rolesCommandHandler.ts │ └── buttonInteraction.ts └── index.ts ├── README.md ├── package.json └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | lib 3 | node_modules -------------------------------------------------------------------------------- /src/utils/types.ts: -------------------------------------------------------------------------------- 1 | export type TicketStatus = 'opened' | 'closed' | 'failed' | 'created'; 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Info 2 | 3 | 1. Clone the repository 4 | 2. Run `npm install` 5 | 3. Create a `.env` file with the variables and assign your own values. 6 | ``` 7 | BOT_TOKEN= 8 | MYSQL_DB_HOST= 9 | MYSQL_DB_PORT= 10 | MYSQL_DB_USERNAME= 11 | MYSQL_DB_PASSWORD= 12 | MYSQL_DB_DATABASE= 13 | ``` 14 | 4. Run `npm run start:dev` 15 | -------------------------------------------------------------------------------- /src/typeorm/entities/TicketConfigRole.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; 2 | import { TicketConfig } from './TicketConfig'; 3 | 4 | @Entity({ name: 'ticket_config_roles' }) 5 | export class TicketConfigRole { 6 | @PrimaryGeneratedColumn() 7 | id: number; 8 | 9 | @Column() 10 | roleId: string; 11 | 12 | @ManyToOne(() => TicketConfig, (config) => config.roles) 13 | ticketConfig: TicketConfig; 14 | } 15 | -------------------------------------------------------------------------------- /src/typeorm/entities/Ticket.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; 2 | import { TicketStatus } from '../../utils/types'; 3 | 4 | @Entity({ name: 'tickets' }) 5 | export class Ticket { 6 | @PrimaryGeneratedColumn() 7 | id: number; 8 | 9 | @Column({ nullable: true }) 10 | channelId: string; 11 | 12 | @Column({ nullable: true }) 13 | messageId: string; 14 | 15 | @Column() 16 | createdBy: string; 17 | 18 | @Column({ default: 'created' }) 19 | status: TicketStatus; 20 | } 21 | -------------------------------------------------------------------------------- /src/typeorm/entities/TicketConfig.ts: -------------------------------------------------------------------------------- 1 | import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm'; 2 | import { TicketConfigRole } from './TicketConfigRole'; 3 | 4 | @Entity({ name: 'ticket_configs' }) 5 | export class TicketConfig { 6 | @PrimaryGeneratedColumn() 7 | id: number; 8 | 9 | @Column({ unique: true }) 10 | guildId: string; 11 | 12 | @Column() 13 | messageId: string; 14 | 15 | @Column() 16 | channelId: string; 17 | 18 | @OneToMany(() => TicketConfigRole, (role) => role.ticketConfig) 19 | roles: TicketConfigRole[]; 20 | } 21 | -------------------------------------------------------------------------------- /src/typeorm/index.ts: -------------------------------------------------------------------------------- 1 | import { DataSource } from 'typeorm'; 2 | import { Ticket } from './entities/Ticket'; 3 | import { TicketConfig } from './entities/TicketConfig'; 4 | import { TicketConfigRole } from './entities/TicketConfigRole'; 5 | 6 | export const AppDataSource = new DataSource({ 7 | type: 'mysql', 8 | host: process.env.MYSQL_DB_HOST, 9 | port: parseInt(process.env.MYSQL_DB_PORT || '3306'), 10 | username: process.env.MYSQL_DB_USERNAME, 11 | password: process.env.MYSQL_DB_PASSWORD, 12 | database: process.env.MYSQL_DB_DATABASE, 13 | synchronize: true, 14 | entities: [TicketConfig, Ticket, TicketConfigRole], 15 | }); 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ticket-bot", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node ./lib/index.js", 9 | "start:dev": "nodemon ./src/index.ts", 10 | "build": "tsc" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "devDependencies": { 16 | "dotenv": "^16.0.1", 17 | "nodemon": "^2.0.19", 18 | "ts-node": "^10.9.1", 19 | "typescript": "^4.7.4" 20 | }, 21 | "dependencies": { 22 | "@discordjs/rest": "^1.0.1", 23 | "discord.js": "^14.1.2", 24 | "mysql2": "^2.3.3", 25 | "reflect-metadata": "^0.1.13", 26 | "typeorm": "^0.3.7" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/handlers/chatInputCommand.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ActionRowBuilder, 3 | ButtonBuilder, 4 | ButtonStyle, 5 | CacheType, 6 | ChatInputCommandInteraction, 7 | Client, 8 | GuildTextBasedChannel, 9 | } from 'discord.js'; 10 | import { AppDataSource } from '../typeorm'; 11 | import { TicketConfig } from '../typeorm/entities/TicketConfig'; 12 | import { handleRolesCommand } from './rolesCommandHandler'; 13 | 14 | const ticketConfigRepository = AppDataSource.getRepository(TicketConfig); 15 | 16 | export async function handleChatInputCommand( 17 | client: Client, 18 | interaction: ChatInputCommandInteraction 19 | ) { 20 | console.log('HandleChatInputCommand'); 21 | console.log(interaction.commandName); 22 | switch (interaction.commandName) { 23 | case 'setup': { 24 | const guildId = interaction.guildId || ''; 25 | const channel = interaction.options.getChannel( 26 | 'channel' 27 | ) as GuildTextBasedChannel; 28 | const ticketConfig = await ticketConfigRepository.findOneBy({ guildId }); 29 | const messageOptions = { 30 | content: 31 | 'Interact with the Buttons to either Create or Manage a ticket', 32 | components: [ 33 | new ActionRowBuilder().setComponents( 34 | new ButtonBuilder() 35 | .setCustomId('createTicket') 36 | .setEmoji('🎫') 37 | .setLabel('Create Ticket') 38 | .setStyle(ButtonStyle.Primary) 39 | ), 40 | ], 41 | }; 42 | try { 43 | if (!ticketConfig) { 44 | const msg = await channel.send(messageOptions); 45 | const newTicketConfig = ticketConfigRepository.create({ 46 | guildId, 47 | messageId: msg.id, 48 | channelId: channel.id, 49 | }); 50 | await ticketConfigRepository.save(newTicketConfig); 51 | console.log('Saved new Configuration to Database'); 52 | await interaction.reply({ 53 | content: `Ticket Bot Initialized!`, 54 | ephemeral: true, 55 | }); 56 | } else { 57 | console.log('Ticket Config exists... Updating Values'); 58 | const msg = await channel.send(messageOptions); 59 | ticketConfig.channelId = channel.id; 60 | ticketConfig.messageId = msg.id; 61 | await ticketConfigRepository.save(ticketConfig); 62 | await interaction.reply({ 63 | content: `New message sent in ${channel}. Updated Database Record.`, 64 | ephemeral: true, 65 | }); 66 | } 67 | } catch (err) { 68 | console.log(err); 69 | await interaction.reply({ 70 | content: `Something went wrong...`, 71 | ephemeral: true, 72 | }); 73 | } 74 | } 75 | case 'roles': { 76 | return handleRolesCommand(client, interaction); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import 'dotenv/config'; 3 | import { 4 | ChannelType, 5 | Client, 6 | GatewayIntentBits, 7 | PermissionsBitField, 8 | REST, 9 | RESTPostAPIApplicationCommandsJSONBody, 10 | Routes, 11 | SlashCommandBuilder, 12 | } from 'discord.js'; 13 | import { handleChatInputCommand } from './handlers/chatInputCommand'; 14 | import { AppDataSource } from './typeorm'; 15 | import { handleButtonInteraction } from './handlers/buttonInteraction'; 16 | 17 | const CLIENT_ID = '999203924571607150'; 18 | const GUILD_ID = '997820362446340096'; 19 | const TOKEN = process.env.BOT_TOKEN!; 20 | 21 | const client = new Client({ intents: [GatewayIntentBits.Guilds] }); 22 | const rest = new REST({ version: '10' }).setToken(TOKEN); 23 | 24 | const commands: RESTPostAPIApplicationCommandsJSONBody[] = [ 25 | new SlashCommandBuilder() 26 | .setName('setup') 27 | .setDescription( 28 | 'Initializes the Ticket Bot & Sends a Message to a Channel for Customers to Create Tickets' 29 | ) 30 | .setDefaultMemberPermissions(PermissionsBitField.Flags.Administrator) 31 | .addChannelOption((option) => 32 | option 33 | .setName('channel') 34 | .setDescription('The channel to send the message to') 35 | .setRequired(true) 36 | .addChannelTypes(ChannelType.GuildText) 37 | ) 38 | .toJSON(), 39 | new SlashCommandBuilder() 40 | .setName('roles') 41 | .setDescription('Manage roles for Ticket Bot') 42 | .setDefaultMemberPermissions('0') 43 | .addSubcommand((subcommand) => 44 | subcommand 45 | .setName('add') 46 | .setDescription('Adds a Guild Role to the Ticket Configuration') 47 | .addRoleOption((option) => 48 | option 49 | .setName('role') 50 | .setDescription('The role to add to the Ticket Config') 51 | .setRequired(true) 52 | ) 53 | ) 54 | .addSubcommand((subcommand) => 55 | subcommand 56 | .setName('remove') 57 | .setDescription('Removes a Guild Role from the Ticket Configuration') 58 | .addRoleOption((option) => 59 | option 60 | .setName('role') 61 | .setDescription('The role to remove from the Ticket Config') 62 | .setRequired(true) 63 | ) 64 | ) 65 | .toJSON(), 66 | ]; 67 | 68 | client.on('ready', () => console.log(`${client.user?.tag} logged in`)); 69 | 70 | client.on('interactionCreate', (interaction) => { 71 | if (interaction.isChatInputCommand()) 72 | client.emit('chatInputCommand', client, interaction); 73 | else if (interaction.isButton()) 74 | client.emit('buttonInteraction', client, interaction); 75 | }); 76 | 77 | client.on('chatInputCommand', handleChatInputCommand); 78 | client.on('buttonInteraction', handleButtonInteraction); 79 | 80 | async function main() { 81 | try { 82 | await rest.put(Routes.applicationGuildCommands(CLIENT_ID, GUILD_ID), { 83 | body: commands, 84 | }); 85 | await AppDataSource.initialize(); 86 | client.login(TOKEN); 87 | } catch (err) { 88 | console.log(err); 89 | } 90 | } 91 | 92 | main(); 93 | -------------------------------------------------------------------------------- /src/handlers/rolesCommandHandler.ts: -------------------------------------------------------------------------------- 1 | import { CacheType, ChatInputCommandInteraction, Client } from 'discord.js'; 2 | import { AppDataSource } from '../typeorm'; 3 | import { TicketConfig } from '../typeorm/entities/TicketConfig'; 4 | import { TicketConfigRole } from '../typeorm/entities/TicketConfigRole'; 5 | 6 | const ticketConfigRepository = AppDataSource.getRepository(TicketConfig); 7 | const ticketConfigRoleRepository = 8 | AppDataSource.getRepository(TicketConfigRole); 9 | 10 | export async function handleRolesCommand( 11 | client: Client, 12 | interaction: ChatInputCommandInteraction 13 | ) { 14 | const subcommand = interaction.options.getSubcommand(); 15 | const guildId = interaction.guildId || ''; 16 | console.log('Handle Roles Command'); 17 | console.log(`Subcommand: ${subcommand}`); 18 | const ticketConfig = await ticketConfigRepository.findOneBy({ guildId }); 19 | if (!ticketConfig) { 20 | await interaction.reply({ 21 | content: 'You do not have a ticket config setup. Use the /setup command.', 22 | ephemeral: true, 23 | }); 24 | return; 25 | } 26 | switch (subcommand) { 27 | case 'add': 28 | await handleRolesAddSubcommand(client, interaction, ticketConfig); 29 | break; 30 | 31 | case 'remove': 32 | await handleRolesRemoveSubcommand(client, interaction, ticketConfig); 33 | break; 34 | } 35 | } 36 | 37 | export async function handleRolesRemoveSubcommand( 38 | client: Client, 39 | interaction: ChatInputCommandInteraction, 40 | ticketConfig: TicketConfig 41 | ) { 42 | try { 43 | const role = interaction.options.getRole('role', true); 44 | const ticketConfigRole = await ticketConfigRoleRepository.findOneBy({ 45 | roleId: role.id, 46 | ticketConfig, 47 | }); 48 | if (!ticketConfigRole) { 49 | await interaction.reply({ 50 | content: 'Role did not exist', 51 | ephemeral: true, 52 | }); 53 | return; 54 | } 55 | await ticketConfigRoleRepository.delete(ticketConfigRole); 56 | await interaction.reply({ 57 | content: 'Deleted role successfully!', 58 | ephemeral: true, 59 | }); 60 | } catch (err) { 61 | console.log(err); 62 | await interaction.reply({ 63 | content: 'Something went wrong', 64 | ephemeral: true, 65 | }); 66 | } 67 | } 68 | 69 | export async function handleRolesAddSubcommand( 70 | client: Client, 71 | interaction: ChatInputCommandInteraction, 72 | ticketConfig: TicketConfig 73 | ) { 74 | const role = interaction.options.getRole('role', true); 75 | try { 76 | const ticketConfigRole = await ticketConfigRoleRepository.findOneBy({ 77 | roleId: role.id, 78 | ticketConfig, 79 | }); 80 | if (ticketConfigRole) { 81 | await interaction.reply({ 82 | content: 'That role already is added', 83 | ephemeral: true, 84 | }); 85 | return; 86 | } 87 | 88 | const newRole = ticketConfigRoleRepository.create({ 89 | roleId: role.id, 90 | ticketConfig, 91 | }); 92 | 93 | const savedRoled = await ticketConfigRoleRepository.save(newRole); 94 | console.log('Saved Role to DB'); 95 | await interaction.reply({ 96 | content: 'Role added successfully!', 97 | ephemeral: true, 98 | }); 99 | } catch (err) { 100 | console.log(err); 101 | await interaction.reply({ 102 | content: 'Something went wrong', 103 | ephemeral: true, 104 | }); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/handlers/buttonInteraction.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ActionRowBuilder, 3 | ButtonBuilder, 4 | ButtonInteraction, 5 | ButtonStyle, 6 | CacheType, 7 | ChannelType, 8 | Client, 9 | GuildTextBasedChannel, 10 | OverwriteResolvable, 11 | } from 'discord.js'; 12 | import { AppDataSource } from '../typeorm'; 13 | import { Ticket } from '../typeorm/entities/Ticket'; 14 | import { TicketConfig } from '../typeorm/entities/TicketConfig'; 15 | 16 | const ticketConfigRepository = AppDataSource.getRepository(TicketConfig); 17 | const ticketRepository = AppDataSource.getRepository(Ticket); 18 | 19 | export async function handleButtonInteraction( 20 | client: Client, 21 | interaction: ButtonInteraction 22 | ) { 23 | console.log('Button Interaction'); 24 | const { guild, guildId, channelId } = interaction; 25 | const ticketConfig = await ticketConfigRepository.findOne({ 26 | where: { 27 | guildId: guildId || '', 28 | }, 29 | relations: ['roles'], 30 | }); 31 | console.log(ticketConfig); 32 | if (!ticketConfig) { 33 | console.log('No ticket config exists'); 34 | return; 35 | } 36 | switch (interaction.customId) { 37 | case 'createTicket': { 38 | try { 39 | if (!guild) { 40 | console.log('Guild is Null'); 41 | return; 42 | } 43 | // Check if user has an existing ticket. 44 | const ticket = await ticketRepository.findOneBy({ 45 | createdBy: interaction.user.id, 46 | status: 'opened', 47 | }); 48 | if (ticket) { 49 | await interaction.reply({ 50 | content: 'You already have an existing ticket!', 51 | ephemeral: true, 52 | }); 53 | return; 54 | } 55 | if (ticketConfig.messageId === interaction.message.id) { 56 | console.log('User clicked on the button on the correct msg'); 57 | const newTicket = ticketRepository.create({ 58 | createdBy: interaction.user.id, 59 | }); 60 | const savedTicket = await ticketRepository.save(newTicket); 61 | 62 | const rolePermissions: OverwriteResolvable[] = ticketConfig.roles.map( 63 | (role) => ({ 64 | allow: ['ViewChannel', 'SendMessages'], 65 | id: role.roleId, 66 | }) 67 | ); 68 | 69 | console.log(rolePermissions); 70 | 71 | const newTicketChannel = await guild.channels.create({ 72 | name: `ticket-${savedTicket.id.toString().padStart(6, '0')}`, 73 | type: ChannelType.GuildText, 74 | parent: '1006461080287051786', 75 | permissionOverwrites: [ 76 | { 77 | allow: ['ViewChannel', 'SendMessages'], 78 | id: interaction.user.id, 79 | }, 80 | { 81 | allow: ['ViewChannel', 'SendMessages'], 82 | id: client.user!.id, 83 | }, 84 | { 85 | deny: ['ViewChannel', 'SendMessages'], 86 | id: guildId!, 87 | }, 88 | ...rolePermissions, 89 | ], 90 | }); 91 | const newTicketMessage = await newTicketChannel.send({ 92 | content: 'Ticket Menu', 93 | components: [ 94 | new ActionRowBuilder().setComponents( 95 | new ButtonBuilder() 96 | .setCustomId('closeTicket') 97 | .setStyle(ButtonStyle.Danger) 98 | .setLabel('Close Ticket') 99 | ), 100 | ], 101 | }); 102 | await ticketRepository.update( 103 | { id: savedTicket.id }, 104 | { 105 | messageId: newTicketMessage.id, 106 | channelId: newTicketChannel.id, 107 | status: 'opened', 108 | } 109 | ); 110 | console.log('Updated Ticket Values'); 111 | } 112 | } catch (err) { 113 | console.log(err); 114 | } 115 | break; 116 | } 117 | case 'closeTicket': { 118 | console.log('Closing Ticket'); 119 | const user = interaction.user; 120 | const channel = interaction.channel as GuildTextBasedChannel; 121 | const ticket = await ticketRepository.findOneBy({ channelId }); 122 | if (!ticket) return console.log('Ticket Not Found'); 123 | 124 | const rolePermissions: OverwriteResolvable[] = ticketConfig.roles.map( 125 | (role) => ({ 126 | allow: ['ViewChannel', 'SendMessages'], 127 | id: role.roleId, 128 | }) 129 | ); 130 | 131 | console.log(rolePermissions); 132 | 133 | if (user.id === ticket.createdBy) { 134 | console.log('User who created ticket is now trying to close it...'); 135 | await ticketRepository.update({ id: ticket.id }, { status: 'closed' }); 136 | await channel.edit({ 137 | permissionOverwrites: [ 138 | { 139 | deny: ['ViewChannel', 'SendMessages'], 140 | id: interaction.user.id, 141 | }, 142 | { 143 | allow: ['ViewChannel', 'SendMessages'], 144 | id: client.user!.id, 145 | }, 146 | { 147 | deny: ['ViewChannel', 'SendMessages'], 148 | id: guildId!, 149 | }, 150 | ...rolePermissions, 151 | ], 152 | }); 153 | await interaction.update({ 154 | components: [ 155 | new ActionRowBuilder().setComponents( 156 | new ButtonBuilder() 157 | .setCustomId('createTranscript') 158 | .setStyle(ButtonStyle.Secondary) 159 | .setLabel('Create Transcript'), 160 | new ButtonBuilder() 161 | .setCustomId('closeTicketChannel') 162 | .setStyle(ButtonStyle.Secondary) 163 | .setLabel('Close Channel') 164 | ), 165 | ], 166 | }); 167 | await interaction.followUp({ content: 'Ticket Closed' }); 168 | } 169 | break; 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | "experimentalDecorators": true /* Enable experimental support for TC39 stage 2 draft decorators. */, 18 | "emitDecoratorMetadata": true /* Emit design-type metadata for decorated declarations in source files. */, 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "commonjs" /* Specify what module code is generated. */, 29 | // "rootDir": "./", /* Specify the root folder within your source files. */ 30 | // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | // "resolveJsonModule": true, /* Enable importing .json files. */ 39 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 40 | 41 | /* JavaScript Support */ 42 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 43 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 44 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 45 | 46 | /* Emit */ 47 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 48 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 49 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 50 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 51 | // "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. */ 52 | "outDir": "./lib" /* Specify an output folder for all emitted files. */, 53 | // "removeComments": true, /* Disable emitting comments. */ 54 | // "noEmit": true, /* Disable emitting files from a compilation. */ 55 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 56 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 57 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 58 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 59 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 60 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 61 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 62 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 63 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 64 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 65 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 66 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 67 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 68 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 69 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 70 | 71 | /* Interop Constraints */ 72 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 73 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 74 | "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, 75 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 76 | "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, 77 | 78 | /* Type Checking */ 79 | "strict": true /* Enable all strict type-checking options. */, 80 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 81 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 82 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 83 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 84 | "strictPropertyInitialization": false /* Check for class properties that are declared but not set in the constructor. */, 85 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 86 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 87 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 88 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 89 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 90 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 91 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 92 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 93 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 94 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 95 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 96 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 97 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 98 | 99 | /* Completeness */ 100 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 101 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 102 | } 103 | } 104 | --------------------------------------------------------------------------------