mirror of
https://github.com/spacebarchat/server.git
synced 2024-11-22 10:22:39 +01:00
✨ Util
This commit is contained in:
parent
4f9eb951ce
commit
76000f8fa1
17
.vscode/launch.json
vendored
17
.vscode/launch.json
vendored
@ -8,8 +8,17 @@
|
||||
"sourceMaps": true,
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"program": "${workspaceFolder}/dist/test/db_test.js",
|
||||
"name": "Launch Server",
|
||||
"program": "${workspaceFolder}/dist/index.js",
|
||||
"preLaunchTask": "tsc: build - tsconfig.json",
|
||||
"outFiles": ["${workspaceFolder}/dist/**/*.js"]
|
||||
},
|
||||
{
|
||||
"sourceMaps": true,
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Test",
|
||||
"program": "${workspaceFolder}/dist/test/mongo_test.js",
|
||||
"preLaunchTask": "tsc: build - tsconfig.json",
|
||||
"outFiles": ["${workspaceFolder}/dist/**/*.js"]
|
||||
},
|
||||
@ -18,7 +27,9 @@
|
||||
"program": "${file}",
|
||||
"request": "launch",
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"type": "node"
|
||||
"runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"],
|
||||
"type": "node",
|
||||
"resolveSourceMapLocations": ["${workspaceFolder}/**", "!**/node_modules/**"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
2636
package-lock.json
generated
2636
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
@ -22,16 +22,24 @@
|
||||
"@types/node-fetch": "^2.5.7",
|
||||
"express": "^4.17.1",
|
||||
"express-cache-middleware": "^1.0.1",
|
||||
"express-validator": "^6.9.2",
|
||||
"faker": "^5.1.0",
|
||||
"lambert-db": "^1.0.3",
|
||||
"lambert-server": "^1.0.3",
|
||||
"missing-native-js-functions": "^1.0.8",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"jwa": "^2.0.0",
|
||||
"jws": "^4.0.0",
|
||||
"lambert-db": "^1.1.0",
|
||||
"lambert-server": "^1.0.8",
|
||||
"missing-native-js-functions": "^1.1.6",
|
||||
"node-fetch": "^2.6.1",
|
||||
"rethinkdb-ts": "^2.4.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/faker": "^5.1.5",
|
||||
"@types/node": "^14.14.10",
|
||||
"@types/jsonwebtoken": "^8.5.0",
|
||||
"@types/jws": "^3.2.3",
|
||||
"@types/node": "^14.14.22",
|
||||
"lambert-server": "file:../../Trenite/Lambert-server",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.1.2"
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
import fs from "fs/promises";
|
||||
import { Server, ServerOptions } from "lambert-server";
|
||||
import { Authentication, GlobalRateLimit } from "./middlewares/";
|
||||
import Config from "./util/Config";
|
||||
import db from "./util/Database";
|
||||
|
||||
export interface DiscordServerOptions extends ServerOptions {}
|
||||
|
||||
@ -19,6 +22,13 @@ export class DiscordServer extends Server {
|
||||
}
|
||||
|
||||
async start() {
|
||||
await db.init();
|
||||
console.log("[DB] connected");
|
||||
await Promise.all([Config.init()]);
|
||||
|
||||
this.app.use(GlobalRateLimit);
|
||||
this.app.use(Authentication);
|
||||
|
||||
// recursively loads files in routes/
|
||||
this.routes = await this.registerRoutes(__dirname + "/routes/");
|
||||
// const indexHTML = await (await fetch("https://discord.com/app")).buffer();
|
||||
|
38
src/Util.ts
38
src/Util.ts
@ -1,38 +0,0 @@
|
||||
import fs from "fs/promises";
|
||||
import "missing-native-js-functions";
|
||||
|
||||
export interface traverseDirectoryOptions {
|
||||
dirname: string;
|
||||
filter?: RegExp;
|
||||
excludeDirs?: RegExp;
|
||||
recursive?: boolean;
|
||||
}
|
||||
|
||||
const DEFAULT_EXCLUDE_DIR = /^\./;
|
||||
const DEFAULT_FILTER = /^([^\.].*)\.js$/;
|
||||
|
||||
export async function traverseDirectory<T>(
|
||||
options: traverseDirectoryOptions,
|
||||
action: (path: string) => T
|
||||
): Promise<T[]> {
|
||||
if (!options.filter) options.filter = DEFAULT_FILTER;
|
||||
if (!options.excludeDirs) options.excludeDirs = DEFAULT_EXCLUDE_DIR;
|
||||
|
||||
const routes = await fs.readdir(options.dirname);
|
||||
const promises = <Promise<T | T[] | undefined>[]>routes.map(async (file) => {
|
||||
const path = options.dirname + file;
|
||||
const stat = await fs.lstat(path);
|
||||
if (path.match(<RegExp>options.excludeDirs)) return;
|
||||
|
||||
if (stat.isFile() && path.match(<RegExp>options.filter)) {
|
||||
return action(path);
|
||||
} else if (options.recursive && stat.isDirectory()) {
|
||||
return traverseDirectory({ ...options, dirname: path + "/" }, action);
|
||||
}
|
||||
});
|
||||
const result = await Promise.all(promises);
|
||||
|
||||
const t = <(T | undefined)[]>result.flat();
|
||||
|
||||
return <T[]>t.filter((x) => x != undefined);
|
||||
}
|
38
src/Utils.ts
38
src/Utils.ts
@ -1,38 +0,0 @@
|
||||
import fs from "fs/promises";
|
||||
import "missing-native-js-functions";
|
||||
|
||||
export interface traverseDirectoryOptions {
|
||||
dirname: string;
|
||||
filter?: RegExp;
|
||||
excludeDirs?: RegExp;
|
||||
recursive?: boolean;
|
||||
}
|
||||
|
||||
const DEFAULT_EXCLUDE_DIR = /^\./;
|
||||
const DEFAULT_FILTER = /^([^\.].*)\.js$/;
|
||||
|
||||
export async function traverseDirectory<T>(
|
||||
options: traverseDirectoryOptions,
|
||||
action: (path: string) => T
|
||||
): Promise<T[]> {
|
||||
if (!options.filter) options.filter = DEFAULT_FILTER;
|
||||
if (!options.excludeDirs) options.excludeDirs = DEFAULT_EXCLUDE_DIR;
|
||||
|
||||
const routes = await fs.readdir(options.dirname);
|
||||
const promises = <Promise<T | T[] | undefined>[]>routes.map(async (file) => {
|
||||
const path = options.dirname + file;
|
||||
const stat = await fs.lstat(path);
|
||||
if (path.match(<RegExp>options.excludeDirs)) return;
|
||||
|
||||
if (stat.isFile() && path.match(<RegExp>options.filter)) {
|
||||
return action(path);
|
||||
} else if (options.recursive && stat.isDirectory()) {
|
||||
return traverseDirectory({ ...options, dirname: path + "/" }, action);
|
||||
}
|
||||
});
|
||||
const result = await Promise.all(promises);
|
||||
|
||||
const t = <(T | undefined)[]>result.flat();
|
||||
|
||||
return <T[]>t.filter((x) => x != undefined);
|
||||
}
|
@ -1,3 +1,7 @@
|
||||
process.on("uncaughtException", console.error);
|
||||
process.on("unhandledRejection", console.error);
|
||||
setTimeout(() => {}, 100000000);
|
||||
|
||||
import { DiscordServer } from "./Server";
|
||||
|
||||
const server = new DiscordServer({ port: 3000 });
|
||||
|
4
src/middlewares/index.ts
Normal file
4
src/middlewares/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import { Authentication } from "./Authentication";
|
||||
import { GlobalRateLimit } from "./GlobalRateLimit";
|
||||
|
||||
export { Authentication, GlobalRateLimit };
|
@ -1,59 +0,0 @@
|
||||
import { Snowflake } from "./Snowflake";
|
||||
|
||||
export interface Guild {
|
||||
afkChannel?: Snowflake;
|
||||
afkTimeout: number;
|
||||
onlineCount: number;
|
||||
available: boolean;
|
||||
banner: string | null;
|
||||
channels: GuildChannelManager;
|
||||
readonly createdTimestamp: number;
|
||||
defaultMessageNotifications: DefaultMessageNotifications | number;
|
||||
deleted: boolean;
|
||||
description: string | null;
|
||||
discoverySplash: string | null;
|
||||
embedChannel: GuildChannel | null;
|
||||
embedChannelID: Snowflake | null;
|
||||
embedEnabled: boolean;
|
||||
emojis: GuildEmojiManager;
|
||||
explicitContentFilter: ExplicitContentFilterLevel;
|
||||
features: GuildFeatures[];
|
||||
icon: string | null;
|
||||
id: Snowflake;
|
||||
joinedTimestamp: number;
|
||||
large: boolean;
|
||||
maximumMembers: number | null;
|
||||
maximumPresences: number | null;
|
||||
memberCount: number;
|
||||
members: GuildMemberManager;
|
||||
mfaLevel: number;
|
||||
name: string;
|
||||
readonly nameAcronym: string;
|
||||
readonly owner: Snowflake | null;
|
||||
ownerID: Snowflake;
|
||||
readonly partnered: boolean;
|
||||
preferredLocale: string;
|
||||
premiumSubscriptionCount: number | null;
|
||||
premiumTier: PremiumTier;
|
||||
presences: PresenceManager;
|
||||
readonly publicUpdatesChannel: TextChannel | null;
|
||||
publicUpdatesChannelID: Snowflake | null;
|
||||
region: string;
|
||||
roles: RoleManager;
|
||||
readonly rulesChannel: TextChannel | null;
|
||||
rulesChannelID: Snowflake | null;
|
||||
readonly shard: WebSocketShard;
|
||||
shardID: number;
|
||||
splash: string | null;
|
||||
readonly systemChannel: TextChannel | null;
|
||||
systemChannelFlags: Readonly<SystemChannelFlags>;
|
||||
systemChannelID: Snowflake | null;
|
||||
vanityURLCode: string | null;
|
||||
vanityURLUses: number | null;
|
||||
verificationLevel: VerificationLevel;
|
||||
readonly verified: boolean;
|
||||
readonly voiceStates: VoiceStateManager;
|
||||
readonly widgetChannel: TextChannel | null;
|
||||
widgetChannelID: Snowflake | null;
|
||||
widgetEnabled: boolean | null;
|
||||
}
|
@ -1 +0,0 @@
|
||||
export type Snowflake = string;
|
@ -0,0 +1,9 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { check } from "../../../../util/instanceOf";
|
||||
const router: Router = Router();
|
||||
|
||||
router.post("/", check({ test: String, $user: String }), (req: Request, res: Response) => {
|
||||
res.send("OK");
|
||||
});
|
||||
|
||||
export default router;
|
@ -0,0 +1,4 @@
|
||||
import { Router } from "express";
|
||||
const router: Router = Router();
|
||||
|
||||
export default router;
|
@ -0,0 +1,4 @@
|
||||
import { Router } from "express";
|
||||
const router: Router = Router();
|
||||
|
||||
export default router;
|
@ -0,0 +1,4 @@
|
||||
import { Router } from "express";
|
||||
const router: Router = Router();
|
||||
|
||||
export default router;
|
@ -0,0 +1,4 @@
|
||||
import { Router } from "express";
|
||||
const router: Router = Router();
|
||||
|
||||
export default router;
|
@ -0,0 +1,4 @@
|
||||
import { Router } from "express";
|
||||
const router: Router = Router();
|
||||
|
||||
export default router;
|
@ -0,0 +1,4 @@
|
||||
import { Router } from "express";
|
||||
const router: Router = Router();
|
||||
|
||||
export default router;
|
@ -0,0 +1,4 @@
|
||||
import { Router } from "express";
|
||||
const router: Router = Router();
|
||||
|
||||
export default router;
|
@ -0,0 +1,4 @@
|
||||
import { Router } from "express";
|
||||
const router: Router = Router();
|
||||
|
||||
export default router;
|
@ -0,0 +1,4 @@
|
||||
import { Router } from "express";
|
||||
const router: Router = Router();
|
||||
|
||||
export default router;
|
@ -0,0 +1,4 @@
|
||||
import { Router } from "express";
|
||||
const router: Router = Router();
|
||||
|
||||
export default router;
|
@ -0,0 +1,4 @@
|
||||
import { Router } from "express";
|
||||
const router: Router = Router();
|
||||
|
||||
export default router;
|
@ -0,0 +1,4 @@
|
||||
import { Router } from "express";
|
||||
const router: Router = Router();
|
||||
|
||||
export default router;
|
@ -3,10 +3,10 @@
|
||||
* (../../client/index.html)
|
||||
*/
|
||||
import { Router } from "express";
|
||||
import fetch from "node-fetch";
|
||||
import fetch, { Response } from "node-fetch";
|
||||
|
||||
const router = Router();
|
||||
const cache = new Map();
|
||||
const router: Router = Router();
|
||||
const cache = new Map<string, Response>();
|
||||
const assetEndpoint = "https://discord.com/assets/";
|
||||
|
||||
export async function getCache(key: string): Promise<Response> {
|
||||
|
@ -1,9 +0,0 @@
|
||||
import { r } from "rethinkdb-ts";
|
||||
|
||||
async function main() {
|
||||
const connection = await r.connect({ port: 28015, host: "192.168.178.122" });
|
||||
|
||||
r.db("test");
|
||||
}
|
||||
|
||||
main();
|
37
src/test/jwt.ts
Normal file
37
src/test/jwt.ts
Normal file
@ -0,0 +1,37 @@
|
||||
const jwa = require("jwa");
|
||||
|
||||
var STR64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".split("");
|
||||
|
||||
function base64url(string: string, encoding: string) {
|
||||
// @ts-ignore
|
||||
return Buffer.from(string, encoding).toString("base64").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
||||
}
|
||||
|
||||
function to64String(input: number, current = ""): string {
|
||||
if (input < 0 && current.length == 0) {
|
||||
input = input * -1;
|
||||
}
|
||||
var modify = input % 64;
|
||||
var remain = Math.floor(input / 64);
|
||||
var result = STR64[modify] + current;
|
||||
return remain <= 0 ? result : to64String(remain, result);
|
||||
}
|
||||
|
||||
function to64Parse(input: string) {
|
||||
var result = 0;
|
||||
var toProc = input.split("");
|
||||
var e;
|
||||
for (e in toProc) {
|
||||
result = result * 64 + STR64.indexOf(toProc[e]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const start = `${base64url("311129357362135041")}.${to64String(Date.now())}`;
|
||||
const signature = jwa("HS256").sign(start, `test`);
|
||||
const token = `${start}.${signature}`;
|
||||
console.log(token);
|
||||
|
||||
// MzExMTI5MzU3MzYyMTM1MDQx.XdQb_rA.907VgF60kocnOTl32MSUWGSSzbAytQ0jbt36KjLaxuY
|
||||
// MzExMTI5MzU3MzYyMTM1MDQx.XdQbaPy.4vGx4L7IuFJGsRe6IL3BeybLIvbx4Vauvx12pwNsy2U
|
8
src/test/jwt2.ts
Normal file
8
src/test/jwt2.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
// console.log(jwt.sign("test", "test"));
|
||||
|
||||
jwt.verify(`${"2WmFS_EAdYFCBOFM9pVPo9g4bpuI2I9U_JGTCfrx7Tk".repeat(1000000)}`, "test", (err, decoded) => {
|
||||
if (err) console.error(err);
|
||||
console.log(decoded);
|
||||
});
|
14
src/test/mongo_test.ts
Normal file
14
src/test/mongo_test.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import mongoose from "mongoose";
|
||||
|
||||
async function main() {
|
||||
const mongoConnection = await mongoose.createConnection(
|
||||
"mongodb://localhost:27017/lambert?readPreference=secondaryPreferred",
|
||||
{
|
||||
useNewUrlParser: true,
|
||||
useUnifiedTopology: false,
|
||||
}
|
||||
);
|
||||
console.log("connected");
|
||||
}
|
||||
|
||||
main();
|
34
src/test/rethink_test.ts
Normal file
34
src/test/rethink_test.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { r } from "rethinkdb-ts";
|
||||
|
||||
async function main() {
|
||||
const connection = await r.connect({ port: 28015 });
|
||||
|
||||
const db = r.db("test");
|
||||
const cursor = await db
|
||||
.table("guilds")
|
||||
.get(0)
|
||||
.changes({ squash: true })
|
||||
.map(function (row) {
|
||||
return row("old_val")
|
||||
.keys()
|
||||
.setUnion(row("new_val").keys())
|
||||
.concatMap(function (key) {
|
||||
return r.branch(
|
||||
row("old_val")(key).ne(row("new_val")(key)).default(true),
|
||||
[[key, row("new_val")(key).default(null)]],
|
||||
[]
|
||||
);
|
||||
})
|
||||
.coerceTo("object");
|
||||
})
|
||||
.run(connection);
|
||||
|
||||
console.log("each");
|
||||
cursor.each(function (err, row) {
|
||||
if (err) throw err;
|
||||
console.log(row);
|
||||
});
|
||||
console.log("eachend");
|
||||
}
|
||||
|
||||
main();
|
146
src/util/BitField.ts
Normal file
146
src/util/BitField.ts
Normal file
@ -0,0 +1,146 @@
|
||||
"use strict";
|
||||
|
||||
// https://github.com/discordjs/discord.js/blob/master/src/util/BitField.js
|
||||
// Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah
|
||||
|
||||
export type BitFieldResolvable = number | BitField | string | BitFieldResolvable[];
|
||||
|
||||
/**
|
||||
* Data structure that makes it easy to interact with a bitfield.
|
||||
*/
|
||||
export class BitField {
|
||||
public bitfield: number;
|
||||
|
||||
/**
|
||||
* Numeric bitfield flags.
|
||||
* <info>Defined in extension classes</info>
|
||||
*/
|
||||
public static FLAGS: Record<string, number>;
|
||||
/**
|
||||
*/
|
||||
constructor(bits: BitFieldResolvable = 0) {
|
||||
/**
|
||||
* Bitfield of the packed bits
|
||||
* @type {number}
|
||||
*/
|
||||
this.bitfield = BitField.resolve(bits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the bitfield has a bit, or any of multiple bits.
|
||||
*/
|
||||
any(bit: BitFieldResolvable): boolean {
|
||||
return (this.bitfield & BitField.resolve(bit)) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this bitfield equals another
|
||||
*/
|
||||
equals(bit: BitFieldResolvable): boolean {
|
||||
return this.bitfield === BitField.resolve(bit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the bitfield has a bit, or multiple bits.
|
||||
*/
|
||||
has(bit: BitFieldResolvable): boolean {
|
||||
if (Array.isArray(bit)) return bit.every((p) => this.has(p));
|
||||
bit = BitField.resolve(bit);
|
||||
return (this.bitfield & bit) === bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all given bits that are missing from the bitfield.
|
||||
*/
|
||||
missing(bits: BitFieldResolvable) {
|
||||
if (!Array.isArray(bits)) bits = new BitField(bits).toArray();
|
||||
return bits.filter((p) => !this.has(p));
|
||||
}
|
||||
|
||||
/**
|
||||
* Freezes these bits, making them immutable.
|
||||
*/
|
||||
freeze(): Readonly<BitField> {
|
||||
return Object.freeze(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds bits to these ones.
|
||||
* @param {...BitFieldResolvable} [bits] Bits to add
|
||||
* @returns {BitField} These bits or new BitField if the instance is frozen.
|
||||
*/
|
||||
add(...bits: BitFieldResolvable[]): BitField {
|
||||
let total = 0;
|
||||
for (const bit of bits) {
|
||||
total |= BitField.resolve(bit);
|
||||
}
|
||||
if (Object.isFrozen(this)) return new BitField(this.bitfield | total);
|
||||
this.bitfield |= total;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes bits from these.
|
||||
* @param {...BitFieldResolvable} [bits] Bits to remove
|
||||
*/
|
||||
remove(...bits: BitFieldResolvable[]) {
|
||||
let total = 0;
|
||||
for (const bit of bits) {
|
||||
total |= BitField.resolve(bit);
|
||||
}
|
||||
if (Object.isFrozen(this)) return new BitField(this.bitfield & ~total);
|
||||
this.bitfield &= ~total;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an object mapping field names to a {@link boolean} indicating whether the
|
||||
* bit is available.
|
||||
* @param {...*} hasParams Additional parameters for the has method, if any
|
||||
*/
|
||||
serialize() {
|
||||
const serialized: Record<string, boolean> = {};
|
||||
for (const [flag, bit] of Object.entries(BitField.FLAGS)) serialized[flag] = this.has(bit);
|
||||
return serialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@link Array} of bitfield names based on the bits available.
|
||||
*/
|
||||
toArray(): string[] {
|
||||
return Object.keys(BitField.FLAGS).filter((bit) => this.has(bit));
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return this.bitfield;
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.bitfield;
|
||||
}
|
||||
|
||||
*[Symbol.iterator]() {
|
||||
yield* this.toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to give a bitfield. This can be:
|
||||
* * A bit number (this can be a number literal or a value taken from {@link BitField.FLAGS})
|
||||
* * An instance of BitField
|
||||
* * An Array of BitFieldResolvable
|
||||
* @typedef {number|BitField|BitFieldResolvable[]} BitFieldResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves bitfields to their numeric form.
|
||||
* @param {BitFieldResolvable} [bit=0] - bit(s) to resolve
|
||||
* @returns {number}
|
||||
*/
|
||||
static resolve(bit: BitFieldResolvable = 0): number {
|
||||
if (typeof bit === "number" && bit >= 0) return bit;
|
||||
if (bit instanceof BitField) return bit.bitfield;
|
||||
if (Array.isArray(bit)) return bit.map((p) => this.resolve(p)).reduce((prev, p) => prev | p, 0);
|
||||
if (typeof bit === "string" && typeof this.FLAGS[bit] !== "undefined") return this.FLAGS[bit];
|
||||
throw new RangeError("BITFIELD_INVALID: " + bit);
|
||||
}
|
||||
}
|
25
src/util/Config.ts
Normal file
25
src/util/Config.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import "missing-native-js-functions";
|
||||
import db from "./Database";
|
||||
import { DefaultOptions } from "./Constants";
|
||||
import { ProviderCache } from "lambert-db";
|
||||
var Config: ProviderCache;
|
||||
|
||||
async function init() {
|
||||
Config = db.data.config.cache();
|
||||
await Config.init();
|
||||
await Config.set(DefaultOptions.merge(Config.cache));
|
||||
}
|
||||
|
||||
function get() {
|
||||
return <DefaultOptions>Config.get();
|
||||
}
|
||||
|
||||
function set(val: any) {
|
||||
return Config.set(val);
|
||||
}
|
||||
|
||||
export default {
|
||||
init,
|
||||
get: get,
|
||||
set: set,
|
||||
};
|
679
src/util/Constants.ts
Normal file
679
src/util/Constants.ts
Normal file
@ -0,0 +1,679 @@
|
||||
import crypto from "crypto";
|
||||
import { VerifyOptions } from "jsonwebtoken";
|
||||
|
||||
export interface DefaultOptions {
|
||||
user: {
|
||||
maxGuilds: number;
|
||||
maxUsername: number;
|
||||
maxFriends: number;
|
||||
};
|
||||
guild: {
|
||||
maxRoles: number;
|
||||
maxMembers: number;
|
||||
maxChannels: number;
|
||||
maxChannelsInCategory: number;
|
||||
hideOfflineMember: number;
|
||||
};
|
||||
message: {
|
||||
characters: number;
|
||||
ttsCharacters: number;
|
||||
maxReactions: number;
|
||||
maxAttachmentSize: number;
|
||||
};
|
||||
channel: {
|
||||
maxPins: number;
|
||||
maxTopic: number;
|
||||
};
|
||||
server: {
|
||||
jwtSecret: string;
|
||||
ipRateLimit: {
|
||||
enabled: boolean;
|
||||
count: number;
|
||||
timespan: number;
|
||||
};
|
||||
forwadedFor: false | string;
|
||||
};
|
||||
}
|
||||
|
||||
export const DefaultOptions: DefaultOptions = {
|
||||
user: {
|
||||
maxGuilds: 100,
|
||||
maxUsername: 32,
|
||||
maxFriends: 1000,
|
||||
},
|
||||
guild: {
|
||||
maxRoles: 250,
|
||||
maxMembers: 250000,
|
||||
maxChannels: 500,
|
||||
maxChannelsInCategory: 50,
|
||||
hideOfflineMember: 1000,
|
||||
},
|
||||
message: {
|
||||
characters: 2000,
|
||||
ttsCharacters: 200,
|
||||
maxReactions: 20,
|
||||
maxAttachmentSize: 8388608,
|
||||
},
|
||||
channel: {
|
||||
maxPins: 50,
|
||||
maxTopic: 1024,
|
||||
},
|
||||
server: {
|
||||
jwtSecret: crypto.randomBytes(256).toString("base64"),
|
||||
ipRateLimit: {
|
||||
enabled: true,
|
||||
count: 1000,
|
||||
timespan: 1000 * 60 * 10,
|
||||
},
|
||||
forwadedFor: false,
|
||||
// forwadedFor: "X-Forwarded-For" // nginx/reverse proxy
|
||||
// forwadedFor: "CF-Connecting-IP" // cloudflare:
|
||||
},
|
||||
};
|
||||
|
||||
export const JWTOptions: VerifyOptions = { algorithms: ["HS256"] };
|
||||
|
||||
export const WSCodes = {
|
||||
1000: "WS_CLOSE_REQUESTED",
|
||||
4004: "TOKEN_INVALID",
|
||||
4010: "SHARDING_INVALID",
|
||||
4011: "SHARDING_REQUIRED",
|
||||
4013: "INVALID_INTENTS",
|
||||
4014: "DISALLOWED_INTENTS",
|
||||
};
|
||||
|
||||
const AllowedImageFormats = ["webp", "png", "jpg", "jpeg", "gif"];
|
||||
|
||||
const AllowedImageSizes = Array.from({ length: 9 }, (e, i) => 2 ** (i + 4));
|
||||
|
||||
function makeImageUrl(root: string, { format = "webp", size = 512 } = {}) {
|
||||
if (format && !AllowedImageFormats.includes(format)) throw new Error("IMAGE_FORMAT: " + format);
|
||||
if (size && !AllowedImageSizes.includes(size)) throw new RangeError("IMAGE_SIZE: " + size);
|
||||
return `${root}.${format}${size ? `?size=${size}` : ""}`;
|
||||
}
|
||||
/**
|
||||
* Options for Image URLs.
|
||||
* @typedef {Object} ImageURLOptions
|
||||
* @property {string} [format] One of `webp`, `png`, `jpg`, `jpeg`, `gif`. If no format is provided,
|
||||
* defaults to `webp`.
|
||||
* @property {boolean} [dynamic] If true, the format will dynamically change to `gif` for
|
||||
* animated avatars; the default is false.
|
||||
* @property {number} [size] One of `16`, `32`, `64`, `128`, `256`, `512`, `1024`, `2048`, `4096`
|
||||
*/
|
||||
|
||||
export const Endpoints = {
|
||||
CDN(root: string) {
|
||||
return {
|
||||
Emoji: (emojiID: string, format = "png") => `${root}/emojis/${emojiID}.${format}`,
|
||||
Asset: (name: string) => `${root}/assets/${name}`,
|
||||
DefaultAvatar: (discriminator: string) => `${root}/embed/avatars/${discriminator}.png`,
|
||||
Avatar: (userID: string, hash: string, format = "webp", size: number, dynamic = false) => {
|
||||
if (dynamic) format = hash.startsWith("a_") ? "gif" : format;
|
||||
return makeImageUrl(`${root}/avatars/${userID}/${hash}`, { format, size });
|
||||
},
|
||||
Banner: (guildID: string, hash: string, format = "webp", size: number) =>
|
||||
makeImageUrl(`${root}/banners/${guildID}/${hash}`, { format, size }),
|
||||
Icon: (guildID: string, hash: string, format = "webp", size: number, dynamic = false) => {
|
||||
if (dynamic) format = hash.startsWith("a_") ? "gif" : format;
|
||||
return makeImageUrl(`${root}/icons/${guildID}/${hash}`, { format, size });
|
||||
},
|
||||
AppIcon: (
|
||||
clientID: string,
|
||||
hash: string,
|
||||
{ format = "webp", size }: { format?: string; size?: number } = {}
|
||||
) => makeImageUrl(`${root}/app-icons/${clientID}/${hash}`, { size, format }),
|
||||
AppAsset: (
|
||||
clientID: string,
|
||||
hash: string,
|
||||
{ format = "webp", size }: { format?: string; size?: number } = {}
|
||||
) => makeImageUrl(`${root}/app-assets/${clientID}/${hash}`, { size, format }),
|
||||
GDMIcon: (channelID: string, hash: string, format = "webp", size: number) =>
|
||||
makeImageUrl(`${root}/channel-icons/${channelID}/${hash}`, { size, format }),
|
||||
Splash: (guildID: string, hash: string, format = "webp", size: number) =>
|
||||
makeImageUrl(`${root}/splashes/${guildID}/${hash}`, { size, format }),
|
||||
DiscoverySplash: (guildID: string, hash: string, format = "webp", size: number) =>
|
||||
makeImageUrl(`${root}/discovery-splashes/${guildID}/${hash}`, { size, format }),
|
||||
TeamIcon: (
|
||||
teamID: string,
|
||||
hash: string,
|
||||
{ format = "webp", size }: { format?: string; size?: number } = {}
|
||||
) => makeImageUrl(`${root}/team-icons/${teamID}/${hash}`, { size, format }),
|
||||
};
|
||||
},
|
||||
invite: (root: string, code: string) => `${root}/${code}`,
|
||||
botGateway: "/gateway/bot",
|
||||
};
|
||||
|
||||
/**
|
||||
* The current status of the client. Here are the available statuses:
|
||||
* * READY: 0
|
||||
* * CONNECTING: 1
|
||||
* * RECONNECTING: 2
|
||||
* * IDLE: 3
|
||||
* * NEARLY: 4
|
||||
* * DISCONNECTED: 5
|
||||
* * WAITING_FOR_GUILDS: 6
|
||||
* * IDENTIFYING: 7
|
||||
* * RESUMING: 8
|
||||
* @typedef {number} Status
|
||||
*/
|
||||
export const Status = {
|
||||
READY: 0,
|
||||
CONNECTING: 1,
|
||||
RECONNECTING: 2,
|
||||
IDLE: 3,
|
||||
NEARLY: 4,
|
||||
DISCONNECTED: 5,
|
||||
WAITING_FOR_GUILDS: 6,
|
||||
IDENTIFYING: 7,
|
||||
RESUMING: 8,
|
||||
};
|
||||
|
||||
/**
|
||||
* The current status of a voice connection. Here are the available statuses:
|
||||
* * CONNECTED: 0
|
||||
* * CONNECTING: 1
|
||||
* * AUTHENTICATING: 2
|
||||
* * RECONNECTING: 3
|
||||
* * DISCONNECTED: 4
|
||||
* @typedef {number} VoiceStatus
|
||||
*/
|
||||
export const VoiceStatus = {
|
||||
CONNECTED: 0,
|
||||
CONNECTING: 1,
|
||||
AUTHENTICATING: 2,
|
||||
RECONNECTING: 3,
|
||||
DISCONNECTED: 4,
|
||||
};
|
||||
|
||||
export const OPCodes = {
|
||||
DISPATCH: 0,
|
||||
HEARTBEAT: 1,
|
||||
IDENTIFY: 2,
|
||||
STATUS_UPDATE: 3,
|
||||
VOICE_STATE_UPDATE: 4,
|
||||
VOICE_GUILD_PING: 5,
|
||||
RESUME: 6,
|
||||
RECONNECT: 7,
|
||||
REQUEST_GUILD_MEMBERS: 8,
|
||||
INVALID_SESSION: 9,
|
||||
HELLO: 10,
|
||||
HEARTBEAT_ACK: 11,
|
||||
};
|
||||
|
||||
export const VoiceOPCodes = {
|
||||
IDENTIFY: 0,
|
||||
SELECT_PROTOCOL: 1,
|
||||
READY: 2,
|
||||
HEARTBEAT: 3,
|
||||
SESSION_DESCRIPTION: 4,
|
||||
SPEAKING: 5,
|
||||
HELLO: 8,
|
||||
CLIENT_CONNECT: 12,
|
||||
CLIENT_DISCONNECT: 13,
|
||||
};
|
||||
|
||||
export const Events = {
|
||||
RATE_LIMIT: "rateLimit",
|
||||
CLIENT_READY: "ready",
|
||||
GUILD_CREATE: "guildCreate",
|
||||
GUILD_DELETE: "guildDelete",
|
||||
GUILD_UPDATE: "guildUpdate",
|
||||
GUILD_UNAVAILABLE: "guildUnavailable",
|
||||
GUILD_AVAILABLE: "guildAvailable",
|
||||
GUILD_MEMBER_ADD: "guildMemberAdd",
|
||||
GUILD_MEMBER_REMOVE: "guildMemberRemove",
|
||||
GUILD_MEMBER_UPDATE: "guildMemberUpdate",
|
||||
GUILD_MEMBER_AVAILABLE: "guildMemberAvailable",
|
||||
GUILD_MEMBER_SPEAKING: "guildMemberSpeaking",
|
||||
GUILD_MEMBERS_CHUNK: "guildMembersChunk",
|
||||
GUILD_INTEGRATIONS_UPDATE: "guildIntegrationsUpdate",
|
||||
GUILD_ROLE_CREATE: "roleCreate",
|
||||
GUILD_ROLE_DELETE: "roleDelete",
|
||||
INVITE_CREATE: "inviteCreate",
|
||||
INVITE_DELETE: "inviteDelete",
|
||||
GUILD_ROLE_UPDATE: "roleUpdate",
|
||||
GUILD_EMOJI_CREATE: "emojiCreate",
|
||||
GUILD_EMOJI_DELETE: "emojiDelete",
|
||||
GUILD_EMOJI_UPDATE: "emojiUpdate",
|
||||
GUILD_BAN_ADD: "guildBanAdd",
|
||||
GUILD_BAN_REMOVE: "guildBanRemove",
|
||||
CHANNEL_CREATE: "channelCreate",
|
||||
CHANNEL_DELETE: "channelDelete",
|
||||
CHANNEL_UPDATE: "channelUpdate",
|
||||
CHANNEL_PINS_UPDATE: "channelPinsUpdate",
|
||||
MESSAGE_CREATE: "message",
|
||||
MESSAGE_DELETE: "messageDelete",
|
||||
MESSAGE_UPDATE: "messageUpdate",
|
||||
MESSAGE_BULK_DELETE: "messageDeleteBulk",
|
||||
MESSAGE_REACTION_ADD: "messageReactionAdd",
|
||||
MESSAGE_REACTION_REMOVE: "messageReactionRemove",
|
||||
MESSAGE_REACTION_REMOVE_ALL: "messageReactionRemoveAll",
|
||||
MESSAGE_REACTION_REMOVE_EMOJI: "messageReactionRemoveEmoji",
|
||||
USER_UPDATE: "userUpdate",
|
||||
PRESENCE_UPDATE: "presenceUpdate",
|
||||
VOICE_SERVER_UPDATE: "voiceServerUpdate",
|
||||
VOICE_STATE_UPDATE: "voiceStateUpdate",
|
||||
VOICE_BROADCAST_SUBSCRIBE: "subscribe",
|
||||
VOICE_BROADCAST_UNSUBSCRIBE: "unsubscribe",
|
||||
TYPING_START: "typingStart",
|
||||
TYPING_STOP: "typingStop",
|
||||
WEBHOOKS_UPDATE: "webhookUpdate",
|
||||
ERROR: "error",
|
||||
WARN: "warn",
|
||||
DEBUG: "debug",
|
||||
SHARD_DISCONNECT: "shardDisconnect",
|
||||
SHARD_ERROR: "shardError",
|
||||
SHARD_RECONNECTING: "shardReconnecting",
|
||||
SHARD_READY: "shardReady",
|
||||
SHARD_RESUME: "shardResume",
|
||||
INVALIDATED: "invalidated",
|
||||
RAW: "raw",
|
||||
};
|
||||
|
||||
export const ShardEvents = {
|
||||
CLOSE: "close",
|
||||
DESTROYED: "destroyed",
|
||||
INVALID_SESSION: "invalidSession",
|
||||
READY: "ready",
|
||||
RESUMED: "resumed",
|
||||
ALL_READY: "allReady",
|
||||
};
|
||||
|
||||
/**
|
||||
* The type of Structure allowed to be a partial:
|
||||
* * USER
|
||||
* * CHANNEL (only affects DMChannels)
|
||||
* * GUILD_MEMBER
|
||||
* * MESSAGE
|
||||
* * REACTION
|
||||
* <warn>Partials require you to put checks in place when handling data, read the Partials topic listed in the
|
||||
* sidebar for more information.</warn>
|
||||
* @typedef {string} PartialType
|
||||
*/
|
||||
export const PartialTypes = keyMirror(["USER", "CHANNEL", "GUILD_MEMBER", "MESSAGE", "REACTION"]);
|
||||
|
||||
/**
|
||||
* The type of a websocket message event, e.g. `MESSAGE_CREATE`. Here are the available events:
|
||||
* * READY
|
||||
* * RESUMED
|
||||
* * GUILD_CREATE
|
||||
* * GUILD_DELETE
|
||||
* * GUILD_UPDATE
|
||||
* * INVITE_CREATE
|
||||
* * INVITE_DELETE
|
||||
* * GUILD_MEMBER_ADD
|
||||
* * GUILD_MEMBER_REMOVE
|
||||
* * GUILD_MEMBER_UPDATE
|
||||
* * GUILD_MEMBERS_CHUNK
|
||||
* * GUILD_INTEGRATIONS_UPDATE
|
||||
* * GUILD_ROLE_CREATE
|
||||
* * GUILD_ROLE_DELETE
|
||||
* * GUILD_ROLE_UPDATE
|
||||
* * GUILD_BAN_ADD
|
||||
* * GUILD_BAN_REMOVE
|
||||
* * GUILD_EMOJIS_UPDATE
|
||||
* * CHANNEL_CREATE
|
||||
* * CHANNEL_DELETE
|
||||
* * CHANNEL_UPDATE
|
||||
* * CHANNEL_PINS_UPDATE
|
||||
* * MESSAGE_CREATE
|
||||
* * MESSAGE_DELETE
|
||||
* * MESSAGE_UPDATE
|
||||
* * MESSAGE_DELETE_BULK
|
||||
* * MESSAGE_REACTION_ADD
|
||||
* * MESSAGE_REACTION_REMOVE
|
||||
* * MESSAGE_REACTION_REMOVE_ALL
|
||||
* * MESSAGE_REACTION_REMOVE_EMOJI
|
||||
* * USER_UPDATE
|
||||
* * PRESENCE_UPDATE
|
||||
* * TYPING_START
|
||||
* * VOICE_STATE_UPDATE
|
||||
* * VOICE_SERVER_UPDATE
|
||||
* * WEBHOOKS_UPDATE
|
||||
* @typedef {string} WSEventType
|
||||
*/
|
||||
export const WSEvents = keyMirror([
|
||||
"READY",
|
||||
"RESUMED",
|
||||
"GUILD_CREATE",
|
||||
"GUILD_DELETE",
|
||||
"GUILD_UPDATE",
|
||||
"INVITE_CREATE",
|
||||
"INVITE_DELETE",
|
||||
"GUILD_MEMBER_ADD",
|
||||
"GUILD_MEMBER_REMOVE",
|
||||
"GUILD_MEMBER_UPDATE",
|
||||
"GUILD_MEMBERS_CHUNK",
|
||||
"GUILD_INTEGRATIONS_UPDATE",
|
||||
"GUILD_ROLE_CREATE",
|
||||
"GUILD_ROLE_DELETE",
|
||||
"GUILD_ROLE_UPDATE",
|
||||
"GUILD_BAN_ADD",
|
||||
"GUILD_BAN_REMOVE",
|
||||
"GUILD_EMOJIS_UPDATE",
|
||||
"CHANNEL_CREATE",
|
||||
"CHANNEL_DELETE",
|
||||
"CHANNEL_UPDATE",
|
||||
"CHANNEL_PINS_UPDATE",
|
||||
"MESSAGE_CREATE",
|
||||
"MESSAGE_DELETE",
|
||||
"MESSAGE_UPDATE",
|
||||
"MESSAGE_DELETE_BULK",
|
||||
"MESSAGE_REACTION_ADD",
|
||||
"MESSAGE_REACTION_REMOVE",
|
||||
"MESSAGE_REACTION_REMOVE_ALL",
|
||||
"MESSAGE_REACTION_REMOVE_EMOJI",
|
||||
"USER_UPDATE",
|
||||
"PRESENCE_UPDATE",
|
||||
"TYPING_START",
|
||||
"VOICE_STATE_UPDATE",
|
||||
"VOICE_SERVER_UPDATE",
|
||||
"WEBHOOKS_UPDATE",
|
||||
]);
|
||||
|
||||
/**
|
||||
* The type of a message, e.g. `DEFAULT`. Here are the available types:
|
||||
* * DEFAULT
|
||||
* * RECIPIENT_ADD
|
||||
* * RECIPIENT_REMOVE
|
||||
* * CALL
|
||||
* * CHANNEL_NAME_CHANGE
|
||||
* * CHANNEL_ICON_CHANGE
|
||||
* * PINS_ADD
|
||||
* * GUILD_MEMBER_JOIN
|
||||
* * USER_PREMIUM_GUILD_SUBSCRIPTION
|
||||
* * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1
|
||||
* * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2
|
||||
* * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3
|
||||
* * CHANNEL_FOLLOW_ADD
|
||||
* * GUILD_DISCOVERY_DISQUALIFIED
|
||||
* * GUILD_DISCOVERY_REQUALIFIED
|
||||
* * REPLY
|
||||
* @typedef {string} MessageType
|
||||
*/
|
||||
export const MessageTypes = [
|
||||
"DEFAULT",
|
||||
"RECIPIENT_ADD",
|
||||
"RECIPIENT_REMOVE",
|
||||
"CALL",
|
||||
"CHANNEL_NAME_CHANGE",
|
||||
"CHANNEL_ICON_CHANGE",
|
||||
"PINS_ADD",
|
||||
"GUILD_MEMBER_JOIN",
|
||||
"USER_PREMIUM_GUILD_SUBSCRIPTION",
|
||||
"USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1",
|
||||
"USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2",
|
||||
"USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3",
|
||||
"CHANNEL_FOLLOW_ADD",
|
||||
null,
|
||||
"GUILD_DISCOVERY_DISQUALIFIED",
|
||||
"GUILD_DISCOVERY_REQUALIFIED",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
"REPLY",
|
||||
];
|
||||
|
||||
/**
|
||||
* The types of messages that are `System`. The available types are `MessageTypes` excluding:
|
||||
* * DEFAULT
|
||||
* * REPLY
|
||||
* @typedef {string} SystemMessageType
|
||||
*/
|
||||
export const SystemMessageTypes = MessageTypes.filter(
|
||||
(type: string | null) => type && type !== "DEFAULT" && type !== "REPLY"
|
||||
);
|
||||
|
||||
/**
|
||||
* <info>Bots cannot set a `CUSTOM_STATUS`, it is only for custom statuses received from users</info>
|
||||
* The type of an activity of a users presence, e.g. `PLAYING`. Here are the available types:
|
||||
* * PLAYING
|
||||
* * STREAMING
|
||||
* * LISTENING
|
||||
* * WATCHING
|
||||
* * CUSTOM_STATUS
|
||||
* * COMPETING
|
||||
* @typedef {string} ActivityType
|
||||
*/
|
||||
export const ActivityTypes = ["PLAYING", "STREAMING", "LISTENING", "WATCHING", "CUSTOM_STATUS", "COMPETING"];
|
||||
|
||||
export const ChannelTypes = {
|
||||
TEXT: 0,
|
||||
DM: 1,
|
||||
VOICE: 2,
|
||||
GROUP: 3,
|
||||
CATEGORY: 4,
|
||||
NEWS: 5,
|
||||
STORE: 6,
|
||||
};
|
||||
|
||||
export const ClientApplicationAssetTypes = {
|
||||
SMALL: 1,
|
||||
BIG: 2,
|
||||
};
|
||||
|
||||
export const Colors = {
|
||||
DEFAULT: 0x000000,
|
||||
WHITE: 0xffffff,
|
||||
AQUA: 0x1abc9c,
|
||||
GREEN: 0x2ecc71,
|
||||
BLUE: 0x3498db,
|
||||
YELLOW: 0xffff00,
|
||||
PURPLE: 0x9b59b6,
|
||||
LUMINOUS_VIVID_PINK: 0xe91e63,
|
||||
GOLD: 0xf1c40f,
|
||||
ORANGE: 0xe67e22,
|
||||
RED: 0xe74c3c,
|
||||
GREY: 0x95a5a6,
|
||||
NAVY: 0x34495e,
|
||||
DARK_AQUA: 0x11806a,
|
||||
DARK_GREEN: 0x1f8b4c,
|
||||
DARK_BLUE: 0x206694,
|
||||
DARK_PURPLE: 0x71368a,
|
||||
DARK_VIVID_PINK: 0xad1457,
|
||||
DARK_GOLD: 0xc27c0e,
|
||||
DARK_ORANGE: 0xa84300,
|
||||
DARK_RED: 0x992d22,
|
||||
DARK_GREY: 0x979c9f,
|
||||
DARKER_GREY: 0x7f8c8d,
|
||||
LIGHT_GREY: 0xbcc0c0,
|
||||
DARK_NAVY: 0x2c3e50,
|
||||
BLURPLE: 0x7289da,
|
||||
GREYPLE: 0x99aab5,
|
||||
DARK_BUT_NOT_BLACK: 0x2c2f33,
|
||||
NOT_QUITE_BLACK: 0x23272a,
|
||||
};
|
||||
|
||||
/**
|
||||
* The value set for the explicit content filter levels for a guild:
|
||||
* * DISABLED
|
||||
* * MEMBERS_WITHOUT_ROLES
|
||||
* * ALL_MEMBERS
|
||||
* @typedef {string} ExplicitContentFilterLevel
|
||||
*/
|
||||
export const ExplicitContentFilterLevels = ["DISABLED", "MEMBERS_WITHOUT_ROLES", "ALL_MEMBERS"];
|
||||
|
||||
/**
|
||||
* The value set for the verification levels for a guild:
|
||||
* * NONE
|
||||
* * LOW
|
||||
* * MEDIUM
|
||||
* * HIGH
|
||||
* * VERY_HIGH
|
||||
* @typedef {string} VerificationLevel
|
||||
*/
|
||||
export const VerificationLevels = ["NONE", "LOW", "MEDIUM", "HIGH", "VERY_HIGH"];
|
||||
|
||||
/**
|
||||
* An error encountered while performing an API request. Here are the potential errors:
|
||||
* * UNKNOWN_ACCOUNT
|
||||
* * UNKNOWN_APPLICATION
|
||||
* * UNKNOWN_CHANNEL
|
||||
* * UNKNOWN_GUILD
|
||||
* * UNKNOWN_INTEGRATION
|
||||
* * UNKNOWN_INVITE
|
||||
* * UNKNOWN_MEMBER
|
||||
* * UNKNOWN_MESSAGE
|
||||
* * UNKNOWN_OVERWRITE
|
||||
* * UNKNOWN_PROVIDER
|
||||
* * UNKNOWN_ROLE
|
||||
* * UNKNOWN_TOKEN
|
||||
* * UNKNOWN_USER
|
||||
* * UNKNOWN_EMOJI
|
||||
* * UNKNOWN_WEBHOOK
|
||||
* * UNKNOWN_BAN
|
||||
* * UNKNOWN_GUILD_TEMPLATE
|
||||
* * BOT_PROHIBITED_ENDPOINT
|
||||
* * BOT_ONLY_ENDPOINT
|
||||
* * CHANNEL_HIT_WRITE_RATELIMIT
|
||||
* * MAXIMUM_GUILDS
|
||||
* * MAXIMUM_FRIENDS
|
||||
* * MAXIMUM_PINS
|
||||
* * MAXIMUM_ROLES
|
||||
* * MAXIMUM_WEBHOOKS
|
||||
* * MAXIMUM_REACTIONS
|
||||
* * MAXIMUM_CHANNELS
|
||||
* * MAXIMUM_ATTACHMENTS
|
||||
* * MAXIMUM_INVITES
|
||||
* * GUILD_ALREADY_HAS_TEMPLATE
|
||||
* * UNAUTHORIZED
|
||||
* * ACCOUNT_VERIFICATION_REQUIRED
|
||||
* * REQUEST_ENTITY_TOO_LARGE
|
||||
* * FEATURE_TEMPORARILY_DISABLED
|
||||
* * USER_BANNED
|
||||
* * ALREADY_CROSSPOSTED
|
||||
* * MISSING_ACCESS
|
||||
* * INVALID_ACCOUNT_TYPE
|
||||
* * CANNOT_EXECUTE_ON_DM
|
||||
* * EMBED_DISABLED
|
||||
* * CANNOT_EDIT_MESSAGE_BY_OTHER
|
||||
* * CANNOT_SEND_EMPTY_MESSAGE
|
||||
* * CANNOT_MESSAGE_USER
|
||||
* * CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL
|
||||
* * CHANNEL_VERIFICATION_LEVEL_TOO_HIGH
|
||||
* * OAUTH2_APPLICATION_BOT_ABSENT
|
||||
* * MAXIMUM_OAUTH2_APPLICATIONS
|
||||
* * INVALID_OAUTH_STATE
|
||||
* * MISSING_PERMISSIONS
|
||||
* * INVALID_AUTHENTICATION_TOKEN
|
||||
* * NOTE_TOO_LONG
|
||||
* * INVALID_BULK_DELETE_QUANTITY
|
||||
* * CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL
|
||||
* * INVALID_OR_TAKEN_INVITE_CODE
|
||||
* * CANNOT_EXECUTE_ON_SYSTEM_MESSAGE
|
||||
* * INVALID_OAUTH_TOKEN
|
||||
* * BULK_DELETE_MESSAGE_TOO_OLD
|
||||
* * INVALID_FORM_BODY
|
||||
* * INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT
|
||||
* * INVALID_API_VERSION
|
||||
* * CANNOT_DELETE_COMMUNITY_REQUIRED_CHANNEL
|
||||
* * REACTION_BLOCKED
|
||||
* * RESOURCE_OVERLOADED
|
||||
* @typedef {string} APIError
|
||||
*/
|
||||
export const APIErrors = {
|
||||
UNKNOWN_ACCOUNT: 10001,
|
||||
UNKNOWN_APPLICATION: 10002,
|
||||
UNKNOWN_CHANNEL: 10003,
|
||||
UNKNOWN_GUILD: 10004,
|
||||
UNKNOWN_INTEGRATION: 10005,
|
||||
UNKNOWN_INVITE: 10006,
|
||||
UNKNOWN_MEMBER: 10007,
|
||||
UNKNOWN_MESSAGE: 10008,
|
||||
UNKNOWN_OVERWRITE: 10009,
|
||||
UNKNOWN_PROVIDER: 10010,
|
||||
UNKNOWN_ROLE: 10011,
|
||||
UNKNOWN_TOKEN: 10012,
|
||||
UNKNOWN_USER: 10013,
|
||||
UNKNOWN_EMOJI: 10014,
|
||||
UNKNOWN_WEBHOOK: 10015,
|
||||
UNKNOWN_BAN: 10026,
|
||||
UNKNOWN_GUILD_TEMPLATE: 10057,
|
||||
BOT_PROHIBITED_ENDPOINT: 20001,
|
||||
BOT_ONLY_ENDPOINT: 20002,
|
||||
CHANNEL_HIT_WRITE_RATELIMIT: 20028,
|
||||
MAXIMUM_GUILDS: 30001,
|
||||
MAXIMUM_FRIENDS: 30002,
|
||||
MAXIMUM_PINS: 30003,
|
||||
MAXIMUM_ROLES: 30005,
|
||||
MAXIMUM_WEBHOOKS: 30007,
|
||||
MAXIMUM_REACTIONS: 30010,
|
||||
MAXIMUM_CHANNELS: 30013,
|
||||
MAXIMUM_ATTACHMENTS: 30015,
|
||||
MAXIMUM_INVITES: 30016,
|
||||
GUILD_ALREADY_HAS_TEMPLATE: 30031,
|
||||
UNAUTHORIZED: 40001,
|
||||
ACCOUNT_VERIFICATION_REQUIRED: 40002,
|
||||
REQUEST_ENTITY_TOO_LARGE: 40005,
|
||||
FEATURE_TEMPORARILY_DISABLED: 40006,
|
||||
USER_BANNED: 40007,
|
||||
ALREADY_CROSSPOSTED: 40033,
|
||||
MISSING_ACCESS: 50001,
|
||||
INVALID_ACCOUNT_TYPE: 50002,
|
||||
CANNOT_EXECUTE_ON_DM: 50003,
|
||||
EMBED_DISABLED: 50004,
|
||||
CANNOT_EDIT_MESSAGE_BY_OTHER: 50005,
|
||||
CANNOT_SEND_EMPTY_MESSAGE: 50006,
|
||||
CANNOT_MESSAGE_USER: 50007,
|
||||
CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL: 50008,
|
||||
CHANNEL_VERIFICATION_LEVEL_TOO_HIGH: 50009,
|
||||
OAUTH2_APPLICATION_BOT_ABSENT: 50010,
|
||||
MAXIMUM_OAUTH2_APPLICATIONS: 50011,
|
||||
INVALID_OAUTH_STATE: 50012,
|
||||
MISSING_PERMISSIONS: 50013,
|
||||
INVALID_AUTHENTICATION_TOKEN: 50014,
|
||||
NOTE_TOO_LONG: 50015,
|
||||
INVALID_BULK_DELETE_QUANTITY: 50016,
|
||||
CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL: 50019,
|
||||
INVALID_OR_TAKEN_INVITE_CODE: 50020,
|
||||
CANNOT_EXECUTE_ON_SYSTEM_MESSAGE: 50021,
|
||||
INVALID_OAUTH_TOKEN: 50025,
|
||||
BULK_DELETE_MESSAGE_TOO_OLD: 50034,
|
||||
INVALID_FORM_BODY: 50035,
|
||||
INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT: 50036,
|
||||
INVALID_API_VERSION: 50041,
|
||||
CANNOT_DELETE_COMMUNITY_REQUIRED_CHANNEL: 50074,
|
||||
REACTION_BLOCKED: 90001,
|
||||
RESOURCE_OVERLOADED: 130000,
|
||||
};
|
||||
|
||||
/**
|
||||
* The value set for a guild's default message notifications, e.g. `ALL`. Here are the available types:
|
||||
* * ALL
|
||||
* * MENTIONS
|
||||
* @typedef {string} DefaultMessageNotifications
|
||||
*/
|
||||
export const DefaultMessageNotifications = ["ALL", "MENTIONS"];
|
||||
|
||||
/**
|
||||
* The value set for a team members's membership state:
|
||||
* * INVITED
|
||||
* * ACCEPTED
|
||||
* @typedef {string} MembershipStates
|
||||
*/
|
||||
export const MembershipStates = [
|
||||
// They start at 1
|
||||
null,
|
||||
"INVITED",
|
||||
"ACCEPTED",
|
||||
];
|
||||
|
||||
/**
|
||||
* The value set for a webhook's type:
|
||||
* * Incoming
|
||||
* * Channel Follower
|
||||
* @typedef {string} WebhookTypes
|
||||
*/
|
||||
export const WebhookTypes = [
|
||||
// They start at 1
|
||||
null,
|
||||
"Incoming",
|
||||
"Channel Follower",
|
||||
];
|
||||
|
||||
function keyMirror(arr: string[]) {
|
||||
let tmp = Object.create(null);
|
||||
for (const value of arr) tmp[value] = value;
|
||||
return tmp;
|
||||
}
|
14
src/util/MessageFlags.ts
Normal file
14
src/util/MessageFlags.ts
Normal file
@ -0,0 +1,14 @@
|
||||
// https://github.com/discordjs/discord.js/blob/master/src/util/MessageFlags.js
|
||||
// Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah
|
||||
|
||||
import { BitField } from "./BitField";
|
||||
|
||||
export class MessageFlags extends BitField {
|
||||
static FLAGS = {
|
||||
CROSSPOSTED: 1 << 0,
|
||||
IS_CROSSPOST: 1 << 1,
|
||||
SUPPRESS_EMBEDS: 1 << 2,
|
||||
SOURCE_MESSAGE_DELETED: 1 << 3,
|
||||
URGENT: 1 << 4,
|
||||
};
|
||||
}
|
56
src/util/Permissions.ts
Normal file
56
src/util/Permissions.ts
Normal file
@ -0,0 +1,56 @@
|
||||
// https://github.com/discordjs/discord.js/blob/master/src/util/Permissions.js
|
||||
// Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah
|
||||
|
||||
import { BitField } from "./BitField";
|
||||
|
||||
export type PermissionResolvable = string | number | Permissions | PermissionResolvable[];
|
||||
|
||||
export class Permissions extends BitField {
|
||||
static FLAGS = {
|
||||
CREATE_INSTANT_INVITE: 1 << 0,
|
||||
KICK_MEMBERS: 1 << 1,
|
||||
BAN_MEMBERS: 1 << 2,
|
||||
ADMINISTRATOR: 1 << 3,
|
||||
MANAGE_CHANNELS: 1 << 4,
|
||||
MANAGE_GUILD: 1 << 5,
|
||||
ADD_REACTIONS: 1 << 6,
|
||||
VIEW_AUDIT_LOG: 1 << 7,
|
||||
PRIORITY_SPEAKER: 1 << 8,
|
||||
STREAM: 1 << 9,
|
||||
VIEW_CHANNEL: 1 << 10,
|
||||
SEND_MESSAGES: 1 << 11,
|
||||
SEND_TTS_MESSAGES: 1 << 12,
|
||||
MANAGE_MESSAGES: 1 << 13,
|
||||
EMBED_LINKS: 1 << 14,
|
||||
ATTACH_FILES: 1 << 15,
|
||||
READ_MESSAGE_HISTORY: 1 << 16,
|
||||
MENTION_EVERYONE: 1 << 17,
|
||||
USE_EXTERNAL_EMOJIS: 1 << 18,
|
||||
VIEW_GUILD_INSIGHTS: 1 << 19,
|
||||
CONNECT: 1 << 20,
|
||||
SPEAK: 1 << 21,
|
||||
MUTE_MEMBERS: 1 << 22,
|
||||
DEAFEN_MEMBERS: 1 << 23,
|
||||
MOVE_MEMBERS: 1 << 24,
|
||||
USE_VAD: 1 << 25,
|
||||
CHANGE_NICKNAME: 1 << 26,
|
||||
MANAGE_NICKNAMES: 1 << 27,
|
||||
MANAGE_ROLES: 1 << 28,
|
||||
MANAGE_WEBHOOKS: 1 << 29,
|
||||
MANAGE_EMOJIS: 1 << 30,
|
||||
};
|
||||
|
||||
any(permission: PermissionResolvable, checkAdmin = true) {
|
||||
return (checkAdmin && super.has(Permissions.FLAGS.ADMINISTRATOR)) || super.any(permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the bitfield has a permission, or multiple permissions.
|
||||
* @param {PermissionResolvable} permission Permission(s) to check for
|
||||
* @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override
|
||||
* @returns {boolean}
|
||||
*/
|
||||
has(permission: PermissionResolvable, checkAdmin = true) {
|
||||
return (checkAdmin && super.has(Permissions.FLAGS.ADMINISTRATOR)) || super.has(permission);
|
||||
}
|
||||
}
|
@ -1,16 +1,20 @@
|
||||
// @ts-nocheck
|
||||
|
||||
// github.com/discordjs/discord.js/blob/master/src/util/Snowflake.js
|
||||
// https://github.com/discordjs/discord.js/blob/master/src/util/Snowflake.js
|
||||
// Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah
|
||||
"use strict";
|
||||
|
||||
// Discord epoch (2015-01-01T00:00:00.000Z)
|
||||
const EPOCH = 1420070400000;
|
||||
let INCREMENT = 0;
|
||||
|
||||
/**
|
||||
* A container for useful snowflake-related methods.
|
||||
*/
|
||||
class SnowflakeUtil {
|
||||
export class Snowflake {
|
||||
static EPOCH = 1420070400000;
|
||||
static INCREMENT = 0;
|
||||
static processId = 0;
|
||||
static workerId = 0;
|
||||
|
||||
constructor() {
|
||||
throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
|
||||
}
|
||||
@ -91,11 +95,14 @@ class SnowflakeUtil {
|
||||
`"timestamp" argument must be a number (received ${isNaN(timestamp) ? "NaN" : typeof timestamp})`
|
||||
);
|
||||
}
|
||||
if (INCREMENT >= 4095) INCREMENT = 0;
|
||||
const BINARY = `${(timestamp - EPOCH).toString(2).padStart(42, "0")}0000100000${(INCREMENT++)
|
||||
if (Snowflake.INCREMENT >= 4095) Snowflake.INCREMENT = 0;
|
||||
let workerBin = Snowflake.workerId.toString(2).padStart(5, "0");
|
||||
let processBin = Snowflake.processId.toString(2).padStart(5, "0");
|
||||
|
||||
const BINARY = `${(timestamp - EPOCH)
|
||||
.toString(2)
|
||||
.padStart(12, "0")}`;
|
||||
return SnowflakeUtil.binaryToID(BINARY);
|
||||
.padStart(42, "0")}${workerBin}${processBin}${(Snowflake.INCREMENT++).toString(2).padStart(12, "0")}`;
|
||||
return Snowflake.binaryToID(BINARY);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,7 +122,7 @@ class SnowflakeUtil {
|
||||
* @returns {DeconstructedSnowflake} Deconstructed snowflake
|
||||
*/
|
||||
static deconstruct(snowflake) {
|
||||
const BINARY = SnowflakeUtil.idToBinary(snowflake).toString(2).padStart(64, "0");
|
||||
const BINARY = Snowflake.idToBinary(snowflake).toString(2).padStart(64, "0");
|
||||
const res = {
|
||||
timestamp: parseInt(BINARY.substring(0, 42), 2) + EPOCH,
|
||||
workerID: parseInt(BINARY.substring(42, 47), 2),
|
||||
@ -141,5 +148,3 @@ class SnowflakeUtil {
|
||||
return EPOCH;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SnowflakeUtil;
|
22
src/util/UserFlags.ts
Normal file
22
src/util/UserFlags.ts
Normal file
@ -0,0 +1,22 @@
|
||||
// https://github.com/discordjs/discord.js/blob/master/src/util/UserFlags.js
|
||||
// Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah
|
||||
|
||||
import { BitField } from "./BitField";
|
||||
|
||||
export class UserFlags extends BitField {
|
||||
static FLAGS = {
|
||||
DISCORD_EMPLOYEE: 1 << 0,
|
||||
PARTNERED_SERVER_OWNER: 1 << 1,
|
||||
HYPESQUAD_EVENTS: 1 << 2,
|
||||
BUGHUNTER_LEVEL_1: 1 << 3,
|
||||
HOUSE_BRAVERY: 1 << 6,
|
||||
HOUSE_BRILLIANCE: 1 << 7,
|
||||
HOUSE_BALANCE: 1 << 8,
|
||||
EARLY_SUPPORTER: 1 << 9,
|
||||
TEAM_USER: 1 << 10,
|
||||
SYSTEM: 1 << 12,
|
||||
BUGHUNTER_LEVEL_2: 1 << 14,
|
||||
VERIFIED_BOT: 1 << 16,
|
||||
EARLY_VERIFIED_BOT_DEVELOPER: 1 << 17,
|
||||
};
|
||||
}
|
121
src/util/instanceOf.ts
Normal file
121
src/util/instanceOf.ts
Normal file
@ -0,0 +1,121 @@
|
||||
// different version of lambert-server instanceOf with discord error format
|
||||
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import { Tuple } from "lambert-server";
|
||||
|
||||
const OPTIONAL_PREFIX = "$";
|
||||
|
||||
export function check(schema: any) {
|
||||
return (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const result = instanceOf(schema, req.body, { path: "body" });
|
||||
if (result === true) return next();
|
||||
throw result;
|
||||
} catch (error) {
|
||||
return res.status(400).json({ code: 50035, message: "Invalid Form Body", success: false, errors: error });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class FieldError extends Error {
|
||||
constructor(public code: string, public message: string) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
export function instanceOf(
|
||||
type: any,
|
||||
value: any,
|
||||
{ path = "", optional = false, errors = {} }: { path?: string; optional?: boolean; errors?: any } = {}
|
||||
): Boolean {
|
||||
try {
|
||||
if (!type) return true; // no type was specified
|
||||
|
||||
if (value == null) {
|
||||
if (optional) return true;
|
||||
throw new FieldError("BASE_TYPE_REQUIRED", `This field is required`);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case String:
|
||||
if (typeof value === "string") return true;
|
||||
throw new FieldError("BASE_TYPE_STRING", `This field must be a string`);
|
||||
case Number:
|
||||
value = Number(value);
|
||||
if (typeof value === "number" && !isNaN(value)) return true;
|
||||
throw new FieldError("BASE_TYPE_NUMBER", `This field must be a number`);
|
||||
case BigInt:
|
||||
try {
|
||||
value = BigInt(value);
|
||||
if (typeof value === "bigint") return true;
|
||||
} catch (error) {}
|
||||
throw new FieldError("BASE_TYPE_BIGINT", `This field must be a bigint`);
|
||||
case Boolean:
|
||||
if (value == "true") value = true;
|
||||
if (value == "false") value = false;
|
||||
if (typeof value === "boolean") return true;
|
||||
throw new FieldError("BASE_TYPE_BOOLEAN", `This field must be a boolean`);
|
||||
}
|
||||
|
||||
if (typeof type === "object") {
|
||||
if (type?.constructor?.name != "Object") {
|
||||
if (type instanceof Tuple) {
|
||||
if ((<Tuple>type).types.some((x) => instanceOf(x, value, { path, optional, errors }))) return true;
|
||||
throw new FieldError("BASE_TYPE_CHOICES", `This field must be one of (${type.types})`);
|
||||
}
|
||||
if (value instanceof type) return true;
|
||||
throw new FieldError("BASE_TYPE_CLASS", `This field must be an instance of ${type}`);
|
||||
}
|
||||
if (typeof value !== "object") throw new FieldError("BASE_TYPE_OBJECT", `This field must be a object`);
|
||||
|
||||
if (Array.isArray(type)) {
|
||||
if (!Array.isArray(value)) throw new FieldError("BASE_TYPE_ARRAY", `This field must be an array`);
|
||||
if (!type.length) return true; // type array didn't specify any type
|
||||
|
||||
return (
|
||||
value.every((val, i) => {
|
||||
errors[i] = {};
|
||||
return (
|
||||
instanceOf(type[0], val, { path: `${path}[${i}]`, optional, errors: errors[i] }) === true
|
||||
);
|
||||
}) || errors
|
||||
);
|
||||
}
|
||||
|
||||
const diff = Object.keys(value).missing(
|
||||
Object.keys(type).map((x) => (x.startsWith(OPTIONAL_PREFIX) ? x.slice(OPTIONAL_PREFIX.length) : x))
|
||||
);
|
||||
|
||||
if (diff.length) throw new FieldError("UNKOWN_FIELD", `Unkown key ${diff}`);
|
||||
|
||||
return (
|
||||
Object.keys(type).every((key) => {
|
||||
let newKey = key;
|
||||
const OPTIONAL = key.startsWith(OPTIONAL_PREFIX);
|
||||
if (OPTIONAL) newKey = newKey.slice(OPTIONAL_PREFIX.length);
|
||||
errors[key] = {};
|
||||
|
||||
return (
|
||||
instanceOf(type[key], value[newKey], {
|
||||
path: `${path}.${newKey}`,
|
||||
optional: OPTIONAL,
|
||||
errors: errors[key],
|
||||
}) === true
|
||||
);
|
||||
}) || errors
|
||||
);
|
||||
} else if (typeof type === "number" || typeof type === "string" || typeof type === "boolean") {
|
||||
if (value === type) return true;
|
||||
throw new FieldError("BASE_TYPE_CONSTANT", `This field must be ${value}`);
|
||||
} else if (typeof type === "bigint") {
|
||||
if (BigInt(value) === type) return true;
|
||||
throw new FieldError("BASE_TYPE_CONSTANT", `This field must be ${value}`);
|
||||
}
|
||||
|
||||
return type == value;
|
||||
} catch (error) {
|
||||
let e = error as FieldError;
|
||||
errors._errors = [{ message: e.message, code: e.code }];
|
||||
return errors;
|
||||
}
|
||||
}
|
@ -4,14 +4,14 @@
|
||||
|
||||
/* Basic Options */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"target": "ES6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
|
||||
"target": "ES2020" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
|
||||
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
|
||||
"lib": ["ES2015", "DOM"] /* Specify library files to be included in the compilation. */,
|
||||
"lib": ["ES2020"] /* Specify library files to be included in the compilation. */,
|
||||
"allowJs": true /* Allow javascript files to be compiled. */,
|
||||
"checkJs": true /* Report errors in .js files. */,
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
"declaration": true /* Generates corresponding '.d.ts' file. */,
|
||||
"declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */,
|
||||
"declarationMap": false /* Generates a sourcemap for each corresponding '.d.ts' file. */,
|
||||
"sourceMap": true /* Generates corresponding '.map' file. */,
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
"outDir": "./dist/" /* Redirect output structure to the directory. */,
|
||||
@ -27,7 +27,7 @@
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true /* Enable all strict type-checking options. */,
|
||||
"noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
|
||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||
"strictNullChecks": true /* Enable strict null checks. */,
|
||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||
"strictPropertyInitialization": false /* Enable strict checking of property initialization in classes. */,
|
||||
|
Loading…
Reference in New Issue
Block a user