the initial stuff

This commit is contained in:
Hexugory 2023-03-28 23:13:13 -05:00
parent e0116c565c
commit e3b28826f4
24 changed files with 3602 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/node_modules
/out
*.sqlite
config.json

2775
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

22
package.json Normal file
View File

@ -0,0 +1,22 @@
{
"name": "2023Collectabot",
"version": "1.0.0",
"description": "stupid",
"main": "out/mud.js",
"scripts": {
"build": "tsc",
"start": "node ./out/mud.js"
},
"author": "Collectabot Team",
"license": "MIT",
"devDependencies": {
"@types/node": "^18.15.11",
"@types/validator": "^13.7.14",
"typescript": "^5.0.2"
},
"dependencies": {
"discord.js": "^14.8.0",
"sequelize": "^6.30.0",
"sqlite3": "^5.1.6"
}
}

13
src/clientstrings.json Normal file
View File

@ -0,0 +1,13 @@
{
"command": {
"guildOnly": "that command doesn't work in DMs!",
"ownerOnly": "you can't use that command if you don't own this bot...",
"noPermission": "you aren't allowed to use that command!",
"noArguments": "i can't do anything without the command arguments!",
"missingArguments": "you're missing arguments!",
"invalidArgument": "`{1}` is invalid!",
"usagePrefix": "the proper usage would be: ",
"onCooldown": "you need to wait {1} more seconds before reusing the `{2}` command!"
},
"error": "there was an error, shout at hexugory and hope he hears you!"
}

249
src/commandclient.ts Normal file
View File

@ -0,0 +1,249 @@
import { Client, ClientOptions, Collection, GuildChannel, GuildMember, Message } from "discord.js";
import config from "./config.json";
import strings from "./clientstrings.json";
import { Sequelize } from "sequelize";
import { CommandList } from "./commands/commandlist";
import { Command } from "./commands/command";
import { BlacklistUsers } from "./models/blacklistusers";
import { CommandBlacklist } from "./models/commandblacklist";
import { SlashCommand } from "./slash/slash";
import { SlashCommandList } from "./slash/commandlist";
export class CommandClient extends Client {
constructor (options: ClientOptions, db: Sequelize) {
super(options);
process.on('exit', this.destroy);
process.on('SIGINT', this.destroy);
this.db = db;
for (const command of CommandList) {
this.commands.set(command.name, command);
}
for (const command of SlashCommandList) {
this.slashCommands.set(command.name, command);
}
this.on('messageCreate', async (msg: Message) => {
if (!msg.content.startsWith(config.prefix) || msg.author.bot) return;
if (msg.author.id != config.owner && (await BlacklistUsers.findOne({ where: { user_id: msg.author.id } }))) return;
this.parseCommand(msg);
});
this.on('ready', () => {
console.log(`Logged in as ${this.user!.tag}`);
});
this.on('interactionCreate', async (int) => {
if (int.isCommand()) {
if (!int.channel) return;
const command = this.slashCommands.get(int.commandName);
if (!command) throw new Error('Slash command does not exist');
if (!int.guild && command.guildOnly) {
int.reply({ content: strings.command.guildOnly, ephemeral: true });
return;
}
if (command.permission && int.user.id != config.owner) {
if (!(int.channel instanceof GuildChannel)) {
int.reply({ content: strings.command.guildOnly, ephemeral: true });
return;
}
for (const permission of command.permission) {
if (!(int.member as GuildMember).permissionsIn(int.channel).has(permission)){
int.reply({ content: strings.command.noPermission, ephemeral: true });
return;
}
}
}
command.execute(int).catch(error => {
int.reply({ content: strings.error, ephemeral: true })
.catch(error => console.error(error));
return console.error(error);
});
return console.info(`${int.user.tag} (${int.user.id}) used ${command.name} in ${'name' in int.channel ? int.channel.name : 'DM CHANNEL'} (${int.channel.id})`);
}
else if (int.isAutocomplete()) {
if (!int.channel) return;
const command = this.slashCommands.get(int.commandName);
if (!command) throw new Error('Slash command does not exist');
command.autocomplete?.(int).catch(error => {
return console.error(error);
});
}
});
this.login(config.token);
}
/**
* Gives an array of single or multi-word arguments
* @param msg
* @returns
*/
static formatArgs (msg: string): string[] {
const args = msg.match(/("[^"]+")|(\S+)/g);
if (args === null) return [];
for (let [i, arg] of args.entries()) {
args[i] = arg.replace(/(^"|"$)/g, '');
}
return args;
}
async parseCommand (msg: Message): Promise<Command | undefined> {
const args = CommandClient.formatArgs(msg.content.slice(config.prefix.length));
if (args.length < 1) return;
const commandName = args.shift()!.toLowerCase();
const command: Command | undefined = this.commands.get(commandName)
|| this.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName));
if (!command) {
this.nonCommandParse();
return;
};
if (command.ownerOnly && msg.author.id != config.owner) {
msg.reply(strings.command.ownerOnly);
return;
}
if (msg.channel instanceof GuildChannel) {
if (!msg.member) throw new Error('Command sending member does not exist');
if (msg.author.id != config.owner) {
if (command.permission) {
for (const permission of command.permission) {
if (!msg.member.permissionsIn(msg.channel).has(permission)) {
msg.reply(strings.command.noPermission);
return;
}
}
}
const member = (await CommandBlacklist.findOrCreate({ where: { user_id: msg.author.id, guild_id: msg.guild!.id } }))[0];
if (JSON.parse(member.blacklist)[command.name]) {
return;
}
}
}
if(command.guildOnly && !(msg.channel instanceof GuildChannel)) {
msg.reply(strings.command.guildOnly);
return;
}
if (command.args.length > 0 && !command.args[0].optional && args.length === 0) {
let reply = strings.command.noArguments;
if (command.usage) {
reply += `\n${strings.command.usagePrefix} \`${config.prefix}${command.name} ${command.usage}\``;
}
msg.channel.send(reply);
return;
}
if (args.length < command.args.filter(arg => {return !arg.optional}).length) {
let reply = strings.command.missingArguments;
if (command.usage) {
reply += `\n${strings.command.usagePrefix} \`${config.prefix}${command.name} ${command.usage}\``;
}
msg.channel.send(reply);
return;
}
if (command.cooldown && msg.author.id != config.owner) {
if (!this.cooldowns.has(command.name)) {
this.cooldowns.set(command.name, new Collection());
}
const now = Date.now();
const timestamps = this.cooldowns.get(command.name);
if (!timestamps) throw new Error('Command lacks cooldown collection');
if (timestamps.has(msg.author.id)) {
const expirationTime = (timestamps.get(msg.author.id) as number) + command.cooldown;
const timeLeft = (expirationTime - now) / 1000;
msg.reply(strings.command.onCooldown.replace('{1}', timeLeft.toFixed(1)).replace('{2}', command.name));
return;
}
timestamps.set(msg.author.id, now);
setTimeout(() => timestamps.delete(msg.author.id), command.cooldown);
}
try {
return this.runCommand(msg, command, args);
}
catch (error) {
console.error(error);
msg.reply(strings.error);
}
}
nonCommandParse () {
return;
}
runCommand (msg: Message, command: Command, args: string[]): Command | undefined {
if (command.args.length > 0 && !command.args[command.args.length-1].infinite) {
args[command.args.length-1] = args.slice(command.args.length-1, args.length).join(' ');
}
const parsedArgs: any[] = [];
for(var i = 0; i < command.args.length; i++) {
try {
if (!command.args[i].infinite) {
if (!command.args[i].type.validate(args[i], msg)) throw new Error('Argument is invalid');
parsedArgs[i] = command.args[i].type.parse(args[i], msg);
}
else {
const infinite = [];
for (var j = i; j < args.length; j++) {
if (!command.args[i].type.validate(args[j], msg)) throw new Error('Argument is invalid');
infinite.push(command.args[i].type.parse(args[j], msg));
}
parsedArgs[i] = infinite;
}
if (command.args[i].validator && !command.args[i].validator?.(args[i], msg)) throw new Error('Argument is invalid');
}
catch {
msg.reply(strings.command.invalidArgument.replace('{1}', args[i]));
return;
}
}
const keyedArgs: { [key: string]: any } = {};
for (var i = 0; i < command.args.length; i++) {
keyedArgs[command.args[i].key] = parsedArgs[i];
}
console.info(`${msg.author.tag} (${msg.author.id}) used ${command.name} in ${'name' in msg.channel ? msg.channel.name : 'DM CHANNEL'} (${msg.channel.id})`);
command.execute(msg, keyedArgs);
return command;
}
readonly commands = new Collection<string, Command>();
readonly slashCommands = new Collection<string, SlashCommand>();
readonly cooldowns = new Collection<string, Collection<string, number>>();
db: Sequelize
}

54
src/commands/blacklist.ts Normal file
View File

@ -0,0 +1,54 @@
import { GuildMember, Message, PermissionFlagsBits } from "discord.js"
import { CommandClient } from "../commandclient"
import { CommandBlacklist } from "../models/commandblacklist"
import { MemberArgument } from "../types/member"
import { StringArgument } from "../types/string"
import { Command } from "./command"
interface BlacklistCommandArguments {
member: GuildMember
command: string
}
export class BlacklistCommand implements Command {
name = 'blacklist'
aliases = []
description = 'Blacklist a member from a command'
usage = 'blacklist <command> <member>'
permission = [PermissionFlagsBits.ManageMessages]
guildOnly = true
ownerOnly = false
args = [
{
key: 'member',
type: MemberArgument,
infinite: false,
optional: false
},
{
key: 'command',
type: StringArgument,
infinite: false,
optional: false
}
]
async execute(msg: Message, arglist: {}) {
const args = arglist as BlacklistCommandArguments;
const { commands } = msg.client as CommandClient;
if (!commands.get(args.command)) {
return msg.reply(`there's no \`${args.command}\` command`);
}
const member = (await CommandBlacklist.findOrCreate({ where: { user_id: args.member.id, guild_id: msg.guild!.id } }))[0];
const blacklist = JSON.parse(member.blacklist);
blacklist[args.command] = !blacklist[args.command];
member.set({
blacklist: JSON.stringify(blacklist)
});
await member.save();
return msg.reply(`${blacklist[args.command] ? '' : 'un'}blacklisted **${args.member.user.tag}** from \`${args.command}\``);
}
};

21
src/commands/command.ts Normal file
View File

@ -0,0 +1,21 @@
import { Message, PermissionResolvable } from "discord.js"
import { Argument } from "../types/arg"
export interface Command {
name: string
aliases: string[]
description: string
cooldown?: number
usage: string
permission: PermissionResolvable[]
guildOnly: boolean
ownerOnly: boolean
args: {
key: string
type: Argument
validator?(arg: string | any[], msg: Message): boolean
infinite: boolean
optional: boolean
}[]
execute(msg: Message, arglist: {}): Promise<any>
}

View File

@ -0,0 +1,13 @@
import { BlacklistCommand } from "./blacklist";
import { DeploySlashCommand } from "./deployslash";
import { GlobalBlacklistCommand } from "./gblacklist";
import { KillCommand } from "./kill";
import { RandomCaseCommand } from "./randomcase";
export const CommandList = [
new GlobalBlacklistCommand(),
new BlacklistCommand(),
new RandomCaseCommand(),
new KillCommand(),
new DeploySlashCommand()
];

View File

@ -0,0 +1,38 @@
import { Message } from "discord.js"
import { CommandClient } from "../commandclient"
import { Command } from "./command"
export class DeploySlashCommand implements Command{
name = 'deployslash'
aliases = []
description = 'Deploys slash commands'
usage = ''
permission = []
guildOnly = false
ownerOnly = true
args = []
async execute(msg: Message) {
const client = msg.client as CommandClient;
client.slashCommands.forEach(async (command) => {
console.log(command);
if (command.guildID) {
const data = {
name: command.name,
description: command.description,
options: command.args
}
console.log(await client.application!.commands.create(data, command.guildID));
}
else {
const data = {
name: command.name,
description: command.description,
options: command.args
}
console.log(await client.application!.commands.create(data));
}
});
}
};

View File

@ -0,0 +1,46 @@
import { Message, User } from "discord.js"
import { Command } from "./command"
import { UserArgument } from "../types/user"
import { BlacklistUsers } from "../models/blacklistusers"
interface GlobalBlacklistArguments {
users: User[]
}
export class GlobalBlacklistCommand implements Command {
name = 'gblacklist'
aliases = []
description = 'banish to the shadow realm'
usage = 'no'
permission = []
guildOnly = false
ownerOnly = true
args = [
{
key: 'users',
type: UserArgument,
infinite: true,
optional: false
}
]
async execute(msg: Message, arglist: {}) {
const args = arglist as GlobalBlacklistArguments;
let replystr = '';
for (const user of args.users){
const row = (await BlacklistUsers.findOne({ where: { user_id: user.id } }));
if (row) {
row.destroy()
replystr += `${user.tag}: removed\n`
}
else {
await BlacklistUsers.create({ user_id: user.id });
replystr += `${user.tag}: added\n`
}
}
msg.reply(replystr);
}
};

19
src/commands/kill.ts Normal file
View File

@ -0,0 +1,19 @@
import { Message, PermissionResolvable } from "discord.js";
import { Command } from "./command";
export class KillCommand implements Command {
name = 'kill'
aliases = []
description = 'no'
usage = 'no'
permission = []
guildOnly = false
ownerOnly = true
args = []
async execute(msg: Message) {
console.info('dying');
msg.client.destroy();
process.exit(0);
}
};

View File

@ -0,0 +1,35 @@
import { Message } from "discord.js"
import { Command } from "./command"
import { StringArgument } from "../types/string"
interface RandomCaseArguments {
string: string
}
export class RandomCaseCommand implements Command {
name = 'randomcase'
aliases = []
description = 'dOEs thIs'
usage = 'some words'
permission = []
guildOnly = false
ownerOnly = false
args = [
{
key: 'string',
type: StringArgument,
infinite: false,
optional: false
}
]
async execute(msg: Message, arglist: {}) {
const args = (arglist as RandomCaseArguments);
var strSplit = args.string.toLowerCase().split('');
for(let [i, char] of strSplit.entries()){
if (Math.random() > 0.5) strSplit[i] = char.toUpperCase();
}
msg.channel.send(strSplit.join(''));
return;
}
};

37
src/database.ts Normal file
View File

@ -0,0 +1,37 @@
import { DataTypes, Sequelize } from "sequelize";
import { BlacklistUsers } from "./models/blacklistusers";
import { CommandBlacklist } from "./models/commandblacklist";
export const db = new Sequelize({
dialect: 'sqlite',
storage: './database.sqlite',
logging: false
});
BlacklistUsers.init({
user_id: {
type: DataTypes.TEXT,
primaryKey: true
}
},
{
tableName: 'BlacklistUsers',
sequelize: db
});
CommandBlacklist.init({
user_id: DataTypes.TEXT,
guild_id: DataTypes.TEXT,
blacklist: {
type: DataTypes.TEXT,
defaultValue: '{}'
}
},
{
tableName: 'CommandBlacklist',
sequelize: db
});
(async () => {
await db.sync();
})();

View File

@ -0,0 +1,5 @@
import { InferAttributes, InferCreationAttributes, Model } from "sequelize";
export class BlacklistUsers extends Model<InferAttributes<BlacklistUsers>, InferCreationAttributes<BlacklistUsers>> {
declare readonly user_id: string
}

View File

@ -0,0 +1,7 @@
import { CreationOptional, InferAttributes, InferCreationAttributes, Model } from "sequelize";
export class CommandBlacklist extends Model<InferAttributes<CommandBlacklist>, InferCreationAttributes<CommandBlacklist>> {
declare user_id: string
declare guild_id: string
declare blacklist: CreationOptional<string>
}

0
src/mud.ts Normal file
View File

4
src/slash/commandlist.ts Normal file
View File

@ -0,0 +1,4 @@
export const SlashCommandList = [
//new Command()
];

24
src/slash/slash.ts Normal file
View File

@ -0,0 +1,24 @@
import { ApplicationCommandOptionData, AutocompleteInteraction, CommandInteraction, PermissionResolvable, CommandInteractionOption, CacheType } from "discord.js"
export interface SlashCommand {
name: string
description: string
cooldown?: number
permission: PermissionResolvable[]
guildID?: string
ownerOnly: boolean
guildOnly: boolean
args: ApplicationCommandOptionData[]
autocomplete?(int: AutocompleteInteraction): Promise<void>
execute(int: CommandInteraction): Promise<any>
}
export function createArgumentsObject(data: readonly CommandInteractionOption<CacheType>[]) {
var a: {
[key: string]: any
} = {};
for (const arg of data) {
a[arg.name] = arg.value;
}
return a;
}

7
src/types/arg.ts Normal file
View File

@ -0,0 +1,7 @@
import { Message } from "discord.js"
export interface Argument {
name: string
validate (arg: string, msg: Message): boolean
parse (arg: string, msg: Message): any
}

48
src/types/duration.ts Normal file
View File

@ -0,0 +1,48 @@
import { Argument } from "./arg";
export interface Duration {
period: "minute" | "hour" | "day" | "week" | "month" | "year"
amount: number
}
class HumanTimeArgumentClass implements Argument {
name = 'humantime'
validate (arg: string) {
return arg.match(/\d+ ?((minute|hour|day|week|month|year)|(m|h|d|w|y))/ig) !== null;
}
parse (arg: string): Duration[] {
const timeMatches = arg.match(/\d+ ?((minute|hour|day|week|month|year)|(m|h|d|w|y))/ig);
const durations: Duration[] = [];
for (const time of timeMatches!) {
const duration = time.match(/(\d+) ?((minute|hour|day|week|month|year)|(m|h|d|w|y))/i);
switch (duration![2]) {
case 'm':
duration![2] = "minute";
break;
case 'h':
duration![2] = "hour";
break;
case 'd':
duration![2] = "day";
break;
case 'w':
duration![2] = "week";
break;
case 'y':
duration![2] = "year";
break;
}
const period = duration![2] as "minute" | "hour" | "day" | "week" | "month" | "year"
durations.push({
period: period,
amount: parseInt(duration![1], 10)
});
}
return durations;
}
};
export const HumanTimeArgument = new HumanTimeArgumentClass();

32
src/types/member.ts Normal file
View File

@ -0,0 +1,32 @@
import { Message } from "discord.js";
import { Argument } from "./arg";
class MemberArgumentClass implements Argument {
name = 'user'
validate (arg: string, msg: Message) {
var idMatch = arg.match(/<@!?(\d+)>/);
if (!idMatch) {
return msg.guild!.members.cache.filter(member => {return member.user.username.toLowerCase().startsWith(arg.toLowerCase())}).size === 1;
}
var id = idMatch[1];
if (!msg.client.users.resolve(id)) return false;
return true;
}
parse (arg: string, msg: Message) {
var idMatch = arg.match(/<@!?(\d+)>/);
if (!idMatch) {
return msg.guild!.members.cache.find(member => {return member.user.username.toLowerCase().startsWith(arg.toLowerCase())});
}
var id = idMatch[1];
return msg.guild!.members.resolve(id);
}
}
export const MemberArgument = new MemberArgumentClass();

15
src/types/string.ts Normal file
View File

@ -0,0 +1,15 @@
import { Argument } from "./arg";
class StringArgumentClass implements Argument {
name = 'string'
validate (arg: string): arg is string {
return typeof arg === 'string';
}
parse (arg: string): string {
return arg;
}
};
export const StringArgument = new StringArgumentClass();

32
src/types/user.ts Normal file
View File

@ -0,0 +1,32 @@
import { Message } from "discord.js";
import { Argument } from "./arg";
class UserArgumentClass implements Argument {
name = 'user'
validate (arg: any, msg: Message) {
var id = arg.match(/<@!?(\d+)>/);
if (id) id = id[1];
if (!id) {
return msg.client.users.cache.filter(user => {return user.username.toLowerCase().startsWith(arg.toLowerCase())}).size === 1;
}
if (!msg.client.users.resolve(id)) return false;
return true;
}
parse (arg: any, msg: Message) {
var id = arg.match(/<@!?(\d+)>/);
if (id) id = id[1];
if (!id) {
return msg.client.users.cache.find(user => {return user.username.toLowerCase().startsWith(arg.toLowerCase())});
}
return msg.client.users.resolve(id);
}
}
export const UserArgument = new UserArgumentClass();

102
tsconfig.json Normal file
View File

@ -0,0 +1,102 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Projects */
// "incremental": true, /* Enable incremental compilation */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
"rootDir": "./src", /* Specify the root folder within your source files. */
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
"resolveJsonModule": true, /* Enable importing .json files */
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
"sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
"outDir": "./out", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}