+> {
+ // tslint:disable-next-line callable-types (This is extended from and can't extend from a type alias in ts<2.2)
+ (
+ req: Request,
+ res: Response,
+ next: NextFunction,
+ ): void;
+}
+
+export type ErrorRequestHandler<
+ P = ParamsDictionary,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ LocalsObj extends Record = Record
+> = (
+ err: any,
+ req: Request,
+ res: Response,
+ next: NextFunction,
+) => void;
+
+export type PathParams = string | RegExp | Array;
+
+export type RequestHandlerParams<
+ P = ParamsDictionary,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ LocalsObj extends Record = Record
+> =
+ | RequestHandler
+ | ErrorRequestHandler
+ | Array | ErrorRequestHandler>;
+
+type RemoveTail = S extends `${infer P}${Tail}` ? P : S;
+type GetRouteParameter = RemoveTail<
+ RemoveTail, `-${string}`>,
+ `.${string}`
+>;
+
+// prettier-ignore
+export type RouteParameters = string extends Route
+ ? ParamsDictionary
+ : Route extends `${string}(${string}`
+ ? ParamsDictionary //TODO: handling for regex parameters
+ : Route extends `${string}:${infer Rest}`
+ ? (
+ GetRouteParameter extends never
+ ? ParamsDictionary
+ : GetRouteParameter extends `${infer ParamName}?`
+ ? { [P in ParamName]?: string }
+ : { [P in GetRouteParameter]: string }
+ ) &
+ (Rest extends `${GetRouteParameter}${infer Next}`
+ ? RouteParameters : unknown)
+ : {};
+
+export interface IRouterMatcher<
+ T,
+ Method extends 'all' | 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options' | 'head' = any
+> {
+ <
+ Route extends string,
+ P = RouteParameters,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ LocalsObj extends Record = Record
+ >(
+ // (it's used as the default type parameter for P)
+ // eslint-disable-next-line no-unnecessary-generics
+ path: Route,
+ // (This generic is meant to be passed explicitly.)
+ // eslint-disable-next-line no-unnecessary-generics
+ ...handlers: Array>
+ ): T;
+ <
+ Path extends string,
+ P = RouteParameters,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ LocalsObj extends Record = Record
+ >(
+ // (it's used as the default type parameter for P)
+ // eslint-disable-next-line no-unnecessary-generics
+ path: Path,
+ // (This generic is meant to be passed explicitly.)
+ // eslint-disable-next-line no-unnecessary-generics
+ ...handlers: Array>
+ ): T;
+ <
+ P = ParamsDictionary,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ LocalsObj extends Record = Record
+ >(
+ path: PathParams,
+ // (This generic is meant to be passed explicitly.)
+ // eslint-disable-next-line no-unnecessary-generics
+ ...handlers: Array>
+ ): T;
+ <
+ P = ParamsDictionary,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ LocalsObj extends Record = Record
+ >(
+ path: PathParams,
+ // (This generic is meant to be passed explicitly.)
+ // eslint-disable-next-line no-unnecessary-generics
+ ...handlers: Array>
+ ): T;
+ (path: PathParams, subApplication: Application): T;
+}
+
+export interface IRouterHandler {
+ (...handlers: Array>>): T;
+ (...handlers: Array>>): T;
+ <
+ P = RouteParameters,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ LocalsObj extends Record = Record
+ >(
+ // (This generic is meant to be passed explicitly.)
+ // eslint-disable-next-line no-unnecessary-generics
+ ...handlers: Array>
+ ): T;
+ <
+ P = RouteParameters,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ LocalsObj extends Record = Record
+ >(
+ // (This generic is meant to be passed explicitly.)
+ // eslint-disable-next-line no-unnecessary-generics
+ ...handlers: Array>
+ ): T;
+ <
+ P = ParamsDictionary,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ LocalsObj extends Record = Record
+ >(
+ // (This generic is meant to be passed explicitly.)
+ // eslint-disable-next-line no-unnecessary-generics
+ ...handlers: Array>
+ ): T;
+ <
+ P = ParamsDictionary,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ LocalsObj extends Record = Record
+ >(
+ // (This generic is meant to be passed explicitly.)
+ // eslint-disable-next-line no-unnecessary-generics
+ ...handlers: Array>
+ ): T;
+}
+
+export interface IRouter extends RequestHandler {
+ /**
+ * Map the given param placeholder `name`(s) to the given callback(s).
+ *
+ * Parameter mapping is used to provide pre-conditions to routes
+ * which use normalized placeholders. For example a _:user_id_ parameter
+ * could automatically load a user's information from the database without
+ * any additional code,
+ *
+ * The callback uses the samesignature as middleware, the only differencing
+ * being that the value of the placeholder is passed, in this case the _id_
+ * of the user. Once the `next()` function is invoked, just like middleware
+ * it will continue on to execute the route, or subsequent parameter functions.
+ *
+ * app.param('user_id', function(req, res, next, id){
+ * User.find(id, function(err, user){
+ * if (err) {
+ * next(err);
+ * } else if (user) {
+ * req.user = user;
+ * next();
+ * } else {
+ * next(new Error('failed to load user'));
+ * }
+ * });
+ * });
+ */
+ param(name: string, handler: RequestParamHandler): this;
+
+ /**
+ * Alternatively, you can pass only a callback, in which case you have the opportunity to alter the app.param()
+ *
+ * @deprecated since version 4.11
+ */
+ param(callback: (name: string, matcher: RegExp) => RequestParamHandler): this;
+
+ /**
+ * Special-cased "all" method, applying the given route `path`,
+ * middleware, and callback to _every_ HTTP method.
+ */
+ all: IRouterMatcher;
+ get: IRouterMatcher;
+ post: IRouterMatcher;
+ put: IRouterMatcher;
+ delete: IRouterMatcher;
+ patch: IRouterMatcher;
+ options: IRouterMatcher;
+ head: IRouterMatcher;
+
+ checkout: IRouterMatcher;
+ connect: IRouterMatcher;
+ copy: IRouterMatcher;
+ lock: IRouterMatcher;
+ merge: IRouterMatcher;
+ mkactivity: IRouterMatcher;
+ mkcol: IRouterMatcher;
+ move: IRouterMatcher;
+ 'm-search': IRouterMatcher;
+ notify: IRouterMatcher;
+ propfind: IRouterMatcher;
+ proppatch: IRouterMatcher;
+ purge: IRouterMatcher;
+ report: IRouterMatcher;
+ search: IRouterMatcher;
+ subscribe: IRouterMatcher;
+ trace: IRouterMatcher;
+ unlock: IRouterMatcher;
+ unsubscribe: IRouterMatcher;
+
+ use: IRouterHandler & IRouterMatcher;
+
+ route(prefix: T): IRoute;
+ route(prefix: PathParams): IRoute;
+ /**
+ * Stack of configured routes
+ */
+ stack: any[];
+}
+
+export interface IRoute {
+ path: string;
+ stack: any;
+ all: IRouterHandler;
+ get: IRouterHandler;
+ post: IRouterHandler;
+ put: IRouterHandler;
+ delete: IRouterHandler;
+ patch: IRouterHandler;
+ options: IRouterHandler;
+ head: IRouterHandler;
+
+ checkout: IRouterHandler;
+ copy: IRouterHandler;
+ lock: IRouterHandler;
+ merge: IRouterHandler;
+ mkactivity: IRouterHandler;
+ mkcol: IRouterHandler;
+ move: IRouterHandler;
+ 'm-search': IRouterHandler;
+ notify: IRouterHandler;
+ purge: IRouterHandler;
+ report: IRouterHandler;
+ search: IRouterHandler;
+ subscribe: IRouterHandler;
+ trace: IRouterHandler;
+ unlock: IRouterHandler;
+ unsubscribe: IRouterHandler;
+}
+
+export interface Router extends IRouter {}
+
+export interface CookieOptions {
+ maxAge?: number | undefined;
+ signed?: boolean | undefined;
+ expires?: Date | undefined;
+ httpOnly?: boolean | undefined;
+ path?: string | undefined;
+ domain?: string | undefined;
+ secure?: boolean | undefined;
+ encode?: ((val: string) => string) | undefined;
+ sameSite?: boolean | 'lax' | 'strict' | 'none' | undefined;
+}
+
+export interface ByteRange {
+ start: number;
+ end: number;
+}
+
+export interface RequestRanges extends RangeParserRanges {}
+
+export type Errback = (err: Error) => void;
+
+/**
+ * @param P For most requests, this should be `ParamsDictionary`, but if you're
+ * using this in a route handler for a route that uses a `RegExp` or a wildcard
+ * `string` path (e.g. `'/user/*'`), then `req.params` will be an array, in
+ * which case you should use `ParamsArray` instead.
+ *
+ * @see https://expressjs.com/en/api.html#req.params
+ *
+ * @example
+ * app.get('/user/:id', (req, res) => res.send(req.params.id)); // implicitly `ParamsDictionary`
+ * app.get(/user\/(.*)/, (req, res) => res.send(req.params[0]));
+ * app.get('/user/*', (req, res) => res.send(req.params[0]));
+ */
+export interface Request<
+ P = ParamsDictionary,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = ParsedQs,
+ LocalsObj extends Record = Record
+> extends http.IncomingMessage,
+ Express.Request {
+ /**
+ * Return request header.
+ *
+ * The `Referrer` header field is special-cased,
+ * both `Referrer` and `Referer` are interchangeable.
+ *
+ * Examples:
+ *
+ * req.get('Content-Type');
+ * // => "text/plain"
+ *
+ * req.get('content-type');
+ * // => "text/plain"
+ *
+ * req.get('Something');
+ * // => undefined
+ *
+ * Aliased as `req.header()`.
+ */
+ get(name: 'set-cookie'): string[] | undefined;
+ get(name: string): string | undefined;
+
+ header(name: 'set-cookie'): string[] | undefined;
+ header(name: string): string | undefined;
+
+ /**
+ * Check if the given `type(s)` is acceptable, returning
+ * the best match when true, otherwise `undefined`, in which
+ * case you should respond with 406 "Not Acceptable".
+ *
+ * The `type` value may be a single mime type string
+ * such as "application/json", the extension name
+ * such as "json", a comma-delimted list such as "json, html, text/plain",
+ * or an array `["json", "html", "text/plain"]`. When a list
+ * or array is given the _best_ match, if any is returned.
+ *
+ * Examples:
+ *
+ * // Accept: text/html
+ * req.accepts('html');
+ * // => "html"
+ *
+ * // Accept: text/*, application/json
+ * req.accepts('html');
+ * // => "html"
+ * req.accepts('text/html');
+ * // => "text/html"
+ * req.accepts('json, text');
+ * // => "json"
+ * req.accepts('application/json');
+ * // => "application/json"
+ *
+ * // Accept: text/*, application/json
+ * req.accepts('image/png');
+ * req.accepts('png');
+ * // => undefined
+ *
+ * // Accept: text/*;q=.5, application/json
+ * req.accepts(['html', 'json']);
+ * req.accepts('html, json');
+ * // => "json"
+ */
+ accepts(): string[];
+ accepts(type: string): string | false;
+ accepts(type: string[]): string | false;
+ accepts(...type: string[]): string | false;
+
+ /**
+ * Returns the first accepted charset of the specified character sets,
+ * based on the request's Accept-Charset HTTP header field.
+ * If none of the specified charsets is accepted, returns false.
+ *
+ * For more information, or if you have issues or concerns, see accepts.
+ */
+ acceptsCharsets(): string[];
+ acceptsCharsets(charset: string): string | false;
+ acceptsCharsets(charset: string[]): string | false;
+ acceptsCharsets(...charset: string[]): string | false;
+
+ /**
+ * Returns the first accepted encoding of the specified encodings,
+ * based on the request's Accept-Encoding HTTP header field.
+ * If none of the specified encodings is accepted, returns false.
+ *
+ * For more information, or if you have issues or concerns, see accepts.
+ */
+ acceptsEncodings(): string[];
+ acceptsEncodings(encoding: string): string | false;
+ acceptsEncodings(encoding: string[]): string | false;
+ acceptsEncodings(...encoding: string[]): string | false;
+
+ /**
+ * Returns the first accepted language of the specified languages,
+ * based on the request's Accept-Language HTTP header field.
+ * If none of the specified languages is accepted, returns false.
+ *
+ * For more information, or if you have issues or concerns, see accepts.
+ */
+ acceptsLanguages(): string[];
+ acceptsLanguages(lang: string): string | false;
+ acceptsLanguages(lang: string[]): string | false;
+ acceptsLanguages(...lang: string[]): string | false;
+
+ /**
+ * Parse Range header field, capping to the given `size`.
+ *
+ * Unspecified ranges such as "0-" require knowledge of your resource length. In
+ * the case of a byte range this is of course the total number of bytes.
+ * If the Range header field is not given `undefined` is returned.
+ * If the Range header field is given, return value is a result of range-parser.
+ * See more ./types/range-parser/index.d.ts
+ *
+ * NOTE: remember that ranges are inclusive, so for example "Range: users=0-3"
+ * should respond with 4 users when available, not 3.
+ *
+ */
+ range(size: number, options?: RangeParserOptions): RangeParserRanges | RangeParserResult | undefined;
+
+ /**
+ * Return an array of Accepted media types
+ * ordered from highest quality to lowest.
+ */
+ accepted: MediaType[];
+
+ /**
+ * @deprecated since 4.11 Use either req.params, req.body or req.query, as applicable.
+ *
+ * Return the value of param `name` when present or `defaultValue`.
+ *
+ * - Checks route placeholders, ex: _/user/:id_
+ * - Checks body params, ex: id=12, {"id":12}
+ * - Checks query string params, ex: ?id=12
+ *
+ * To utilize request bodies, `req.body`
+ * should be an object. This can be done by using
+ * the `connect.bodyParser()` middleware.
+ */
+ param(name: string, defaultValue?: any): string;
+
+ /**
+ * Check if the incoming request contains the "Content-Type"
+ * header field, and it contains the give mime `type`.
+ *
+ * Examples:
+ *
+ * // With Content-Type: text/html; charset=utf-8
+ * req.is('html');
+ * req.is('text/html');
+ * req.is('text/*');
+ * // => true
+ *
+ * // When Content-Type is application/json
+ * req.is('json');
+ * req.is('application/json');
+ * req.is('application/*');
+ * // => true
+ *
+ * req.is('html');
+ * // => false
+ */
+ is(type: string | string[]): string | false | null;
+
+ /**
+ * Return the protocol string "http" or "https"
+ * when requested with TLS. When the "trust proxy"
+ * setting is enabled the "X-Forwarded-Proto" header
+ * field will be trusted. If you're running behind
+ * a reverse proxy that supplies https for you this
+ * may be enabled.
+ */
+ protocol: string;
+
+ /**
+ * Short-hand for:
+ *
+ * req.protocol == 'https'
+ */
+ secure: boolean;
+
+ /**
+ * Return the remote address, or when
+ * "trust proxy" is `true` return
+ * the upstream addr.
+ */
+ ip: string;
+
+ /**
+ * When "trust proxy" is `true`, parse
+ * the "X-Forwarded-For" ip address list.
+ *
+ * For example if the value were "client, proxy1, proxy2"
+ * you would receive the array `["client", "proxy1", "proxy2"]`
+ * where "proxy2" is the furthest down-stream.
+ */
+ ips: string[];
+
+ /**
+ * Return subdomains as an array.
+ *
+ * Subdomains are the dot-separated parts of the host before the main domain of
+ * the app. By default, the domain of the app is assumed to be the last two
+ * parts of the host. This can be changed by setting "subdomain offset".
+ *
+ * For example, if the domain is "tobi.ferrets.example.com":
+ * If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`.
+ * If "subdomain offset" is 3, req.subdomains is `["tobi"]`.
+ */
+ subdomains: string[];
+
+ /**
+ * Short-hand for `url.parse(req.url).pathname`.
+ */
+ path: string;
+
+ /**
+ * Parse the "Host" header field hostname.
+ */
+ hostname: string;
+
+ /**
+ * @deprecated Use hostname instead.
+ */
+ host: string;
+
+ /**
+ * Check if the request is fresh, aka
+ * Last-Modified and/or the ETag
+ * still match.
+ */
+ fresh: boolean;
+
+ /**
+ * Check if the request is stale, aka
+ * "Last-Modified" and / or the "ETag" for the
+ * resource has changed.
+ */
+ stale: boolean;
+
+ /**
+ * Check if the request was an _XMLHttpRequest_.
+ */
+ xhr: boolean;
+
+ //body: { username: string; password: string; remember: boolean; title: string; };
+ body: ReqBody;
+
+ //cookies: { string; remember: boolean; };
+ cookies: any;
+
+ method: string;
+
+ params: P;
+
+ query: ReqQuery;
+
+ route: any;
+
+ signedCookies: any;
+
+ originalUrl: string;
+
+ url: string;
+
+ baseUrl: string;
+
+ app: Application;
+
+ /**
+ * After middleware.init executed, Request will contain res and next properties
+ * See: express/lib/middleware/init.js
+ */
+ res?: Response | undefined;
+ next?: NextFunction | undefined;
+}
+
+export interface MediaType {
+ value: string;
+ quality: number;
+ type: string;
+ subtype: string;
+}
+
+export type Send> = (body?: ResBody) => T;
+
+export interface Response<
+ ResBody = any,
+ LocalsObj extends Record = Record,
+ StatusCode extends number = number
+> extends http.ServerResponse,
+ Express.Response {
+ /**
+ * Set status `code`.
+ */
+ status(code: StatusCode): this;
+
+ /**
+ * Set the response HTTP status code to `statusCode` and send its string representation as the response body.
+ * @link http://expressjs.com/4x/api.html#res.sendStatus
+ *
+ * Examples:
+ *
+ * res.sendStatus(200); // equivalent to res.status(200).send('OK')
+ * res.sendStatus(403); // equivalent to res.status(403).send('Forbidden')
+ * res.sendStatus(404); // equivalent to res.status(404).send('Not Found')
+ * res.sendStatus(500); // equivalent to res.status(500).send('Internal Server Error')
+ */
+ sendStatus(code: StatusCode): this;
+
+ /**
+ * Set Link header field with the given `links`.
+ *
+ * Examples:
+ *
+ * res.links({
+ * next: 'http://api.example.com/users?page=2',
+ * last: 'http://api.example.com/users?page=5'
+ * });
+ */
+ links(links: any): this;
+
+ /**
+ * Send a response.
+ *
+ * Examples:
+ *
+ * res.send(new Buffer('wahoo'));
+ * res.send({ some: 'json' });
+ * res.send('some html
');
+ * res.status(404).send('Sorry, cant find that');
+ */
+ send: Send;
+
+ /**
+ * Send JSON response.
+ *
+ * Examples:
+ *
+ * res.json(null);
+ * res.json({ user: 'tj' });
+ * res.status(500).json('oh noes!');
+ * res.status(404).json('I dont have that');
+ */
+ json: Send;
+
+ /**
+ * Send JSON response with JSONP callback support.
+ *
+ * Examples:
+ *
+ * res.jsonp(null);
+ * res.jsonp({ user: 'tj' });
+ * res.status(500).jsonp('oh noes!');
+ * res.status(404).jsonp('I dont have that');
+ */
+ jsonp: Send;
+
+ /**
+ * Transfer the file at the given `path`.
+ *
+ * Automatically sets the _Content-Type_ response header field.
+ * The callback `fn(err)` is invoked when the transfer is complete
+ * or when an error occurs. Be sure to check `res.headersSent`
+ * if you wish to attempt responding, as the header and some data
+ * may have already been transferred.
+ *
+ * Options:
+ *
+ * - `maxAge` defaulting to 0 (can be string converted by `ms`)
+ * - `root` root directory for relative filenames
+ * - `headers` object of headers to serve with file
+ * - `dotfiles` serve dotfiles, defaulting to false; can be `"allow"` to send them
+ *
+ * Other options are passed along to `send`.
+ *
+ * Examples:
+ *
+ * The following example illustrates how `res.sendFile()` may
+ * be used as an alternative for the `static()` middleware for
+ * dynamic situations. The code backing `res.sendFile()` is actually
+ * the same code, so HTTP cache support etc is identical.
+ *
+ * app.get('/user/:uid/photos/:file', function(req, res){
+ * var uid = req.params.uid
+ * , file = req.params.file;
+ *
+ * req.user.mayViewFilesFrom(uid, function(yes){
+ * if (yes) {
+ * res.sendFile('/uploads/' + uid + '/' + file);
+ * } else {
+ * res.send(403, 'Sorry! you cant see that.');
+ * }
+ * });
+ * });
+ *
+ * @api public
+ */
+ sendFile(path: string, fn?: Errback): void;
+ sendFile(path: string, options: any, fn?: Errback): void;
+
+ /**
+ * @deprecated Use sendFile instead.
+ */
+ sendfile(path: string): void;
+ /**
+ * @deprecated Use sendFile instead.
+ */
+ sendfile(path: string, options: any): void;
+ /**
+ * @deprecated Use sendFile instead.
+ */
+ sendfile(path: string, fn: Errback): void;
+ /**
+ * @deprecated Use sendFile instead.
+ */
+ sendfile(path: string, options: any, fn: Errback): void;
+
+ /**
+ * Transfer the file at the given `path` as an attachment.
+ *
+ * Optionally providing an alternate attachment `filename`,
+ * and optional callback `fn(err)`. The callback is invoked
+ * when the data transfer is complete, or when an error has
+ * ocurred. Be sure to check `res.headersSent` if you plan to respond.
+ *
+ * The optional options argument passes through to the underlying
+ * res.sendFile() call, and takes the exact same parameters.
+ *
+ * This method uses `res.sendfile()`.
+ */
+ download(path: string, fn?: Errback): void;
+ download(path: string, filename: string, fn?: Errback): void;
+ download(path: string, filename: string, options: any, fn?: Errback): void;
+
+ /**
+ * Set _Content-Type_ response header with `type` through `mime.lookup()`
+ * when it does not contain "/", or set the Content-Type to `type` otherwise.
+ *
+ * Examples:
+ *
+ * res.type('.html');
+ * res.type('html');
+ * res.type('json');
+ * res.type('application/json');
+ * res.type('png');
+ */
+ contentType(type: string): this;
+
+ /**
+ * Set _Content-Type_ response header with `type` through `mime.lookup()`
+ * when it does not contain "/", or set the Content-Type to `type` otherwise.
+ *
+ * Examples:
+ *
+ * res.type('.html');
+ * res.type('html');
+ * res.type('json');
+ * res.type('application/json');
+ * res.type('png');
+ */
+ type(type: string): this;
+
+ /**
+ * Respond to the Acceptable formats using an `obj`
+ * of mime-type callbacks.
+ *
+ * This method uses `req.accepted`, an array of
+ * acceptable types ordered by their quality values.
+ * When "Accept" is not present the _first_ callback
+ * is invoked, otherwise the first match is used. When
+ * no match is performed the server responds with
+ * 406 "Not Acceptable".
+ *
+ * Content-Type is set for you, however if you choose
+ * you may alter this within the callback using `res.type()`
+ * or `res.set('Content-Type', ...)`.
+ *
+ * res.format({
+ * 'text/plain': function(){
+ * res.send('hey');
+ * },
+ *
+ * 'text/html': function(){
+ * res.send('hey
');
+ * },
+ *
+ * 'appliation/json': function(){
+ * res.send({ message: 'hey' });
+ * }
+ * });
+ *
+ * In addition to canonicalized MIME types you may
+ * also use extnames mapped to these types:
+ *
+ * res.format({
+ * text: function(){
+ * res.send('hey');
+ * },
+ *
+ * html: function(){
+ * res.send('hey
');
+ * },
+ *
+ * json: function(){
+ * res.send({ message: 'hey' });
+ * }
+ * });
+ *
+ * By default Express passes an `Error`
+ * with a `.status` of 406 to `next(err)`
+ * if a match is not made. If you provide
+ * a `.default` callback it will be invoked
+ * instead.
+ */
+ format(obj: any): this;
+
+ /**
+ * Set _Content-Disposition_ header to _attachment_ with optional `filename`.
+ */
+ attachment(filename?: string): this;
+
+ /**
+ * Set header `field` to `val`, or pass
+ * an object of header fields.
+ *
+ * Examples:
+ *
+ * res.set('Foo', ['bar', 'baz']);
+ * res.set('Accept', 'application/json');
+ * res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' });
+ *
+ * Aliased as `res.header()`.
+ */
+ set(field: any): this;
+ set(field: string, value?: string | string[]): this;
+
+ header(field: any): this;
+ header(field: string, value?: string | string[]): this;
+
+ // Property indicating if HTTP headers has been sent for the response.
+ headersSent: boolean;
+
+ /** Get value for header `field`. */
+ get(field: string): string|undefined;
+
+ /** Clear cookie `name`. */
+ clearCookie(name: string, options?: CookieOptions): this;
+
+ /**
+ * Set cookie `name` to `val`, with the given `options`.
+ *
+ * Options:
+ *
+ * - `maxAge` max-age in milliseconds, converted to `expires`
+ * - `signed` sign the cookie
+ * - `path` defaults to "/"
+ *
+ * Examples:
+ *
+ * // "Remember Me" for 15 minutes
+ * res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
+ *
+ * // save as above
+ * res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })
+ */
+ cookie(name: string, val: string, options: CookieOptions): this;
+ cookie(name: string, val: any, options: CookieOptions): this;
+ cookie(name: string, val: any): this;
+
+ /**
+ * Set the location header to `url`.
+ *
+ * The given `url` can also be the name of a mapped url, for
+ * example by default express supports "back" which redirects
+ * to the _Referrer_ or _Referer_ headers or "/".
+ *
+ * Examples:
+ *
+ * res.location('/foo/bar').;
+ * res.location('http://example.com');
+ * res.location('../login'); // /blog/post/1 -> /blog/login
+ *
+ * Mounting:
+ *
+ * When an application is mounted and `res.location()`
+ * is given a path that does _not_ lead with "/" it becomes
+ * relative to the mount-point. For example if the application
+ * is mounted at "/blog", the following would become "/blog/login".
+ *
+ * res.location('login');
+ *
+ * While the leading slash would result in a location of "/login":
+ *
+ * res.location('/login');
+ */
+ location(url: string): this;
+
+ /**
+ * Redirect to the given `url` with optional response `status`
+ * defaulting to 302.
+ *
+ * The resulting `url` is determined by `res.location()`, so
+ * it will play nicely with mounted apps, relative paths,
+ * `"back"` etc.
+ *
+ * Examples:
+ *
+ * res.redirect('back');
+ * res.redirect('/foo/bar');
+ * res.redirect('http://example.com');
+ * res.redirect(301, 'http://example.com');
+ * res.redirect('http://example.com', 301);
+ * res.redirect('../login'); // /blog/post/1 -> /blog/login
+ */
+ redirect(url: string): void;
+ redirect(status: number, url: string): void;
+ /** @deprecated use res.redirect(status, url) instead */
+ redirect(url: string, status: number): void;
+
+ /**
+ * Render `view` with the given `options` and optional callback `fn`.
+ * When a callback function is given a response will _not_ be made
+ * automatically, otherwise a response of _200_ and _text/html_ is given.
+ *
+ * Options:
+ *
+ * - `cache` boolean hinting to the engine it should cache
+ * - `filename` filename of the view being rendered
+ */
+ render(view: string, options?: object, callback?: (err: Error, html: string) => void): void;
+ render(view: string, callback?: (err: Error, html: string) => void): void;
+
+ locals: LocalsObj & Locals;
+
+ charset: string;
+
+ /**
+ * Adds the field to the Vary response header, if it is not there already.
+ * Examples:
+ *
+ * res.vary('User-Agent').render('docs');
+ *
+ */
+ vary(field: string): this;
+
+ app: Application;
+
+ /**
+ * Appends the specified value to the HTTP response header field.
+ * If the header is not already set, it creates the header with the specified value.
+ * The value parameter can be a string or an array.
+ *
+ * Note: calling res.set() after res.append() will reset the previously-set header value.
+ *
+ * @since 4.11.0
+ */
+ append(field: string, value?: string[] | string): this;
+
+ /**
+ * After middleware.init executed, Response will contain req property
+ * See: express/lib/middleware/init.js
+ */
+ req: Request;
+}
+
+export interface Handler extends RequestHandler {}
+
+export type RequestParamHandler = (req: Request, res: Response, next: NextFunction, value: any, name: string) => any;
+
+export type ApplicationRequestHandler = IRouterHandler &
+ IRouterMatcher &
+ ((...handlers: RequestHandlerParams[]) => T);
+
+export interface Application<
+ LocalsObj extends Record = Record
+> extends EventEmitter, IRouter, Express.Application {
+ /**
+ * Express instance itself is a request handler, which could be invoked without
+ * third argument.
+ */
+ (req: Request | http.IncomingMessage, res: Response | http.ServerResponse): any;
+
+ /**
+ * Initialize the server.
+ *
+ * - setup default configuration
+ * - setup default middleware
+ * - setup route reflection methods
+ */
+ init(): void;
+
+ /**
+ * Initialize application configuration.
+ */
+ defaultConfiguration(): void;
+
+ /**
+ * Register the given template engine callback `fn`
+ * as `ext`.
+ *
+ * By default will `require()` the engine based on the
+ * file extension. For example if you try to render
+ * a "foo.jade" file Express will invoke the following internally:
+ *
+ * app.engine('jade', require('jade').__express);
+ *
+ * For engines that do not provide `.__express` out of the box,
+ * or if you wish to "map" a different extension to the template engine
+ * you may use this method. For example mapping the EJS template engine to
+ * ".html" files:
+ *
+ * app.engine('html', require('ejs').renderFile);
+ *
+ * In this case EJS provides a `.renderFile()` method with
+ * the same signature that Express expects: `(path, options, callback)`,
+ * though note that it aliases this method as `ejs.__express` internally
+ * so if you're using ".ejs" extensions you dont need to do anything.
+ *
+ * Some template engines do not follow this convention, the
+ * [Consolidate.js](https://github.com/visionmedia/consolidate.js)
+ * library was created to map all of node's popular template
+ * engines to follow this convention, thus allowing them to
+ * work seamlessly within Express.
+ */
+ engine(
+ ext: string,
+ fn: (path: string, options: object, callback: (e: any, rendered?: string) => void) => void,
+ ): this;
+
+ /**
+ * Assign `setting` to `val`, or return `setting`'s value.
+ *
+ * app.set('foo', 'bar');
+ * app.get('foo');
+ * // => "bar"
+ * app.set('foo', ['bar', 'baz']);
+ * app.get('foo');
+ * // => ["bar", "baz"]
+ *
+ * Mounted servers inherit their parent server's settings.
+ */
+ set(setting: string, val: any): this;
+ get: ((name: string) => any) & IRouterMatcher;
+
+ param(name: string | string[], handler: RequestParamHandler): this;
+
+ /**
+ * Alternatively, you can pass only a callback, in which case you have the opportunity to alter the app.param()
+ *
+ * @deprecated since version 4.11
+ */
+ param(callback: (name: string, matcher: RegExp) => RequestParamHandler): this;
+
+ /**
+ * Return the app's absolute pathname
+ * based on the parent(s) that have
+ * mounted it.
+ *
+ * For example if the application was
+ * mounted as "/admin", which itself
+ * was mounted as "/blog" then the
+ * return value would be "/blog/admin".
+ */
+ path(): string;
+
+ /**
+ * Check if `setting` is enabled (truthy).
+ *
+ * app.enabled('foo')
+ * // => false
+ *
+ * app.enable('foo')
+ * app.enabled('foo')
+ * // => true
+ */
+ enabled(setting: string): boolean;
+
+ /**
+ * Check if `setting` is disabled.
+ *
+ * app.disabled('foo')
+ * // => true
+ *
+ * app.enable('foo')
+ * app.disabled('foo')
+ * // => false
+ */
+ disabled(setting: string): boolean;
+
+ /** Enable `setting`. */
+ enable(setting: string): this;
+
+ /** Disable `setting`. */
+ disable(setting: string): this;
+
+ /**
+ * Render the given view `name` name with `options`
+ * and a callback accepting an error and the
+ * rendered template string.
+ *
+ * Example:
+ *
+ * app.render('email', { name: 'Tobi' }, function(err, html){
+ * // ...
+ * })
+ */
+ render(name: string, options?: object, callback?: (err: Error, html: string) => void): void;
+ render(name: string, callback: (err: Error, html: string) => void): void;
+
+ /**
+ * Listen for connections.
+ *
+ * A node `http.Server` is returned, with this
+ * application (which is a `Function`) as its
+ * callback. If you wish to create both an HTTP
+ * and HTTPS server you may do so with the "http"
+ * and "https" modules as shown here:
+ *
+ * var http = require('http')
+ * , https = require('https')
+ * , express = require('express')
+ * , app = express();
+ *
+ * http.createServer(app).listen(80);
+ * https.createServer({ ... }, app).listen(443);
+ */
+ listen(port: number, hostname: string, backlog: number, callback?: () => void): http.Server;
+ listen(port: number, hostname: string, callback?: () => void): http.Server;
+ listen(port: number, callback?: () => void): http.Server;
+ listen(callback?: () => void): http.Server;
+ listen(path: string, callback?: () => void): http.Server;
+ listen(handle: any, listeningListener?: () => void): http.Server;
+
+ router: string;
+
+ settings: any;
+
+ resource: any;
+
+ map: any;
+
+ locals: LocalsObj & Locals;
+
+ /**
+ * The app.routes object houses all of the routes defined mapped by the
+ * associated HTTP verb. This object may be used for introspection
+ * capabilities, for example Express uses this internally not only for
+ * routing but to provide default OPTIONS behaviour unless app.options()
+ * is used. Your application or framework may also remove routes by
+ * simply by removing them from this object.
+ */
+ routes: any;
+
+ /**
+ * Used to get all registered routes in Express Application
+ */
+ _router: any;
+
+ use: ApplicationRequestHandler;
+
+ /**
+ * The mount event is fired on a sub-app, when it is mounted on a parent app.
+ * The parent app is passed to the callback function.
+ *
+ * NOTE:
+ * Sub-apps will:
+ * - Not inherit the value of settings that have a default value. You must set the value in the sub-app.
+ * - Inherit the value of settings with no default value.
+ */
+ on: (event: string, callback: (parent: Application) => void) => this;
+
+ /**
+ * The app.mountpath property contains one or more path patterns on which a sub-app was mounted.
+ */
+ mountpath: string | string[];
+}
+
+export interface Express extends Application {
+ request: Request;
+ response: Response;
+}
diff --git a/backend/node_modules/@types/express-serve-static-core/package.json b/backend/node_modules/@types/express-serve-static-core/package.json
new file mode 100644
index 0000000..63900d6
--- /dev/null
+++ b/backend/node_modules/@types/express-serve-static-core/package.json
@@ -0,0 +1,54 @@
+{
+ "name": "@types/express-serve-static-core",
+ "version": "4.17.33",
+ "description": "TypeScript definitions for Express",
+ "homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/express-serve-static-core",
+ "license": "MIT",
+ "contributors": [
+ {
+ "name": "Boris Yankov",
+ "url": "https://github.com/borisyankov",
+ "githubUsername": "borisyankov"
+ },
+ {
+ "name": "Satana Charuwichitratana",
+ "url": "https://github.com/micksatana",
+ "githubUsername": "micksatana"
+ },
+ {
+ "name": "Sami Jaber",
+ "url": "https://github.com/samijaber",
+ "githubUsername": "samijaber"
+ },
+ {
+ "name": "Jose Luis Leon",
+ "url": "https://github.com/JoseLion",
+ "githubUsername": "JoseLion"
+ },
+ {
+ "name": "David Stephens",
+ "url": "https://github.com/dwrss",
+ "githubUsername": "dwrss"
+ },
+ {
+ "name": "Shin Ando",
+ "url": "https://github.com/andoshin11",
+ "githubUsername": "andoshin11"
+ }
+ ],
+ "main": "",
+ "types": "index.d.ts",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
+ "directory": "types/express-serve-static-core"
+ },
+ "scripts": {},
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*"
+ },
+ "typesPublisherContentHash": "0a827d8ef2f7f9ef4c3093ee5f8b4a148b276b25d09a337a636065cf58d32616",
+ "typeScriptVersion": "4.2"
+}
\ No newline at end of file
diff --git a/backend/node_modules/@types/express/LICENSE b/backend/node_modules/@types/express/LICENSE
new file mode 100644
index 0000000..9e841e7
--- /dev/null
+++ b/backend/node_modules/@types/express/LICENSE
@@ -0,0 +1,21 @@
+ MIT License
+
+ Copyright (c) Microsoft Corporation.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE
diff --git a/backend/node_modules/@types/express/README.md b/backend/node_modules/@types/express/README.md
new file mode 100644
index 0000000..302c833
--- /dev/null
+++ b/backend/node_modules/@types/express/README.md
@@ -0,0 +1,16 @@
+# Installation
+> `npm install --save @types/express`
+
+# Summary
+This package contains type definitions for Express (http://expressjs.com).
+
+# Details
+Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/express.
+
+### Additional Details
+ * Last updated: Fri, 03 Feb 2023 21:32:47 GMT
+ * Dependencies: [@types/body-parser](https://npmjs.com/package/@types/body-parser), [@types/express-serve-static-core](https://npmjs.com/package/@types/express-serve-static-core), [@types/qs](https://npmjs.com/package/@types/qs), [@types/serve-static](https://npmjs.com/package/@types/serve-static)
+ * Global values: none
+
+# Credits
+These definitions were written by [Boris Yankov](https://github.com/borisyankov), [China Medical University Hospital](https://github.com/CMUH), [Puneet Arora](https://github.com/puneetar), and [Dylan Frankland](https://github.com/dfrankland).
diff --git a/backend/node_modules/@types/express/index.d.ts b/backend/node_modules/@types/express/index.d.ts
new file mode 100644
index 0000000..53dc74d
--- /dev/null
+++ b/backend/node_modules/@types/express/index.d.ts
@@ -0,0 +1,136 @@
+// Type definitions for Express 4.17
+// Project: http://expressjs.com
+// Definitions by: Boris Yankov
+// China Medical University Hospital
+// Puneet Arora
+// Dylan Frankland
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+
+/* =================== USAGE ===================
+
+ import express = require("express");
+ var app = express();
+
+ =============================================== */
+
+///
+///
+
+import * as bodyParser from 'body-parser';
+import * as serveStatic from 'serve-static';
+import * as core from 'express-serve-static-core';
+import * as qs from 'qs';
+
+/**
+ * Creates an Express application. The express() function is a top-level function exported by the express module.
+ */
+declare function e(): core.Express;
+
+declare namespace e {
+ /**
+ * This is a built-in middleware function in Express. It parses incoming requests with JSON payloads and is based on body-parser.
+ * @since 4.16.0
+ */
+ var json: typeof bodyParser.json;
+
+ /**
+ * This is a built-in middleware function in Express. It parses incoming requests with Buffer payloads and is based on body-parser.
+ * @since 4.17.0
+ */
+ var raw: typeof bodyParser.raw;
+
+ /**
+ * This is a built-in middleware function in Express. It parses incoming requests with text payloads and is based on body-parser.
+ * @since 4.17.0
+ */
+ var text: typeof bodyParser.text;
+
+ /**
+ * These are the exposed prototypes.
+ */
+ var application: Application;
+ var request: Request;
+ var response: Response;
+
+ /**
+ * This is a built-in middleware function in Express. It serves static files and is based on serve-static.
+ */
+ var static: serveStatic.RequestHandlerConstructor;
+
+ /**
+ * This is a built-in middleware function in Express. It parses incoming requests with urlencoded payloads and is based on body-parser.
+ * @since 4.16.0
+ */
+ var urlencoded: typeof bodyParser.urlencoded;
+
+ /**
+ * This is a built-in middleware function in Express. It parses incoming request query parameters.
+ */
+ export function query(options: qs.IParseOptions | typeof qs.parse): Handler;
+
+ export function Router(options?: RouterOptions): core.Router;
+
+ interface RouterOptions {
+ /**
+ * Enable case sensitivity.
+ */
+ caseSensitive?: boolean | undefined;
+
+ /**
+ * Preserve the req.params values from the parent router.
+ * If the parent and the child have conflicting param names, the child’s value take precedence.
+ *
+ * @default false
+ * @since 4.5.0
+ */
+ mergeParams?: boolean | undefined;
+
+ /**
+ * Enable strict routing.
+ */
+ strict?: boolean | undefined;
+ }
+
+ interface Application extends core.Application {}
+ interface CookieOptions extends core.CookieOptions {}
+ interface Errback extends core.Errback {}
+ interface ErrorRequestHandler<
+ P = core.ParamsDictionary,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = core.Query,
+ Locals extends Record = Record
+ > extends core.ErrorRequestHandler {}
+ interface Express extends core.Express {}
+ interface Handler extends core.Handler {}
+ interface IRoute extends core.IRoute {}
+ interface IRouter extends core.IRouter {}
+ interface IRouterHandler extends core.IRouterHandler {}
+ interface IRouterMatcher extends core.IRouterMatcher {}
+ interface MediaType extends core.MediaType {}
+ interface NextFunction extends core.NextFunction {}
+ interface Locals extends core.Locals {}
+ interface Request<
+ P = core.ParamsDictionary,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = core.Query,
+ Locals extends Record = Record
+ > extends core.Request {}
+ interface RequestHandler<
+ P = core.ParamsDictionary,
+ ResBody = any,
+ ReqBody = any,
+ ReqQuery = core.Query,
+ Locals extends Record = Record
+ > extends core.RequestHandler {}
+ interface RequestParamHandler extends core.RequestParamHandler {}
+ interface Response<
+ ResBody = any,
+ Locals extends Record = Record
+ > extends core.Response {}
+ interface Router extends core.Router {}
+ interface Send extends core.Send {}
+}
+
+export = e;
diff --git a/backend/node_modules/@types/express/package.json b/backend/node_modules/@types/express/package.json
new file mode 100644
index 0000000..10071c3
--- /dev/null
+++ b/backend/node_modules/@types/express/package.json
@@ -0,0 +1,45 @@
+{
+ "name": "@types/express",
+ "version": "4.17.17",
+ "description": "TypeScript definitions for Express",
+ "homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/express",
+ "license": "MIT",
+ "contributors": [
+ {
+ "name": "Boris Yankov",
+ "url": "https://github.com/borisyankov",
+ "githubUsername": "borisyankov"
+ },
+ {
+ "name": "China Medical University Hospital",
+ "url": "https://github.com/CMUH",
+ "githubUsername": "CMUH"
+ },
+ {
+ "name": "Puneet Arora",
+ "url": "https://github.com/puneetar",
+ "githubUsername": "puneetar"
+ },
+ {
+ "name": "Dylan Frankland",
+ "url": "https://github.com/dfrankland",
+ "githubUsername": "dfrankland"
+ }
+ ],
+ "main": "",
+ "types": "index.d.ts",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
+ "directory": "types/express"
+ },
+ "scripts": {},
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^4.17.33",
+ "@types/qs": "*",
+ "@types/serve-static": "*"
+ },
+ "typesPublisherContentHash": "a4c3d98898199c22408b7c0662e85011cacce7899cd22a66275337ec40edac14",
+ "typeScriptVersion": "4.2"
+}
\ No newline at end of file
diff --git a/backend/node_modules/@types/mime/LICENSE b/backend/node_modules/@types/mime/LICENSE
new file mode 100644
index 0000000..9e841e7
--- /dev/null
+++ b/backend/node_modules/@types/mime/LICENSE
@@ -0,0 +1,21 @@
+ MIT License
+
+ Copyright (c) Microsoft Corporation.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE
diff --git a/backend/node_modules/@types/mime/Mime.d.ts b/backend/node_modules/@types/mime/Mime.d.ts
new file mode 100644
index 0000000..2639c09
--- /dev/null
+++ b/backend/node_modules/@types/mime/Mime.d.ts
@@ -0,0 +1,11 @@
+import type { TypeMap } from './index';
+
+declare class Mime {
+ constructor(typeMap: TypeMap, ...mimes: TypeMap[]);
+
+ getType(path: string): string | null;
+ getExtension(mime: string): string | null;
+ define(typeMap: TypeMap, force?: boolean): void;
+}
+
+export = Mime;
diff --git a/backend/node_modules/@types/mime/README.md b/backend/node_modules/@types/mime/README.md
new file mode 100644
index 0000000..78557f2
--- /dev/null
+++ b/backend/node_modules/@types/mime/README.md
@@ -0,0 +1,16 @@
+# Installation
+> `npm install --save @types/mime`
+
+# Summary
+This package contains type definitions for mime (https://github.com/broofa/node-mime).
+
+# Details
+Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/mime.
+
+### Additional Details
+ * Last updated: Thu, 04 Aug 2022 21:02:19 GMT
+ * Dependencies: none
+ * Global values: `mime`, `mimelite`
+
+# Credits
+These definitions were written by [Jeff Goddard](https://github.com/jedigo), and [Daniel Hritzkiv](https://github.com/dhritzkiv).
diff --git a/backend/node_modules/@types/mime/index.d.ts b/backend/node_modules/@types/mime/index.d.ts
new file mode 100644
index 0000000..ce0df4a
--- /dev/null
+++ b/backend/node_modules/@types/mime/index.d.ts
@@ -0,0 +1,21 @@
+// Type definitions for mime 3.0
+// Project: https://github.com/broofa/node-mime
+// Definitions by: Jeff Goddard
+// Daniel Hritzkiv
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+
+// Originally imported from: https://github.com/soywiz/typescript-node-definitions/mime.d.ts
+
+import Mime = require('./Mime');
+
+export as namespace mime;
+
+declare namespace mime {
+ interface TypeMap {
+ [key: string]: string[];
+ }
+}
+
+declare const mime: Mime;
+
+export = mime;
diff --git a/backend/node_modules/@types/mime/lite.d.ts b/backend/node_modules/@types/mime/lite.d.ts
new file mode 100644
index 0000000..a5684fa
--- /dev/null
+++ b/backend/node_modules/@types/mime/lite.d.ts
@@ -0,0 +1,7 @@
+import Mime = require('./Mime');
+
+declare const mimelite: Mime;
+
+export as namespace mimelite;
+
+export = mimelite;
diff --git a/backend/node_modules/@types/mime/package.json b/backend/node_modules/@types/mime/package.json
new file mode 100644
index 0000000..59e3306
--- /dev/null
+++ b/backend/node_modules/@types/mime/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "@types/mime",
+ "version": "3.0.1",
+ "description": "TypeScript definitions for mime",
+ "homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/mime",
+ "license": "MIT",
+ "contributors": [
+ {
+ "name": "Jeff Goddard",
+ "url": "https://github.com/jedigo",
+ "githubUsername": "jedigo"
+ },
+ {
+ "name": "Daniel Hritzkiv",
+ "url": "https://github.com/dhritzkiv",
+ "githubUsername": "dhritzkiv"
+ }
+ ],
+ "main": "",
+ "types": "index.d.ts",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
+ "directory": "types/mime"
+ },
+ "scripts": {},
+ "dependencies": {},
+ "typesPublisherContentHash": "594e1e4777af908b69119d71c37be0a70e63c840095dcdb0881343b51b7286f3",
+ "typeScriptVersion": "4.0"
+}
\ No newline at end of file
diff --git a/backend/node_modules/@types/qs/LICENSE b/backend/node_modules/@types/qs/LICENSE
new file mode 100644
index 0000000..9e841e7
--- /dev/null
+++ b/backend/node_modules/@types/qs/LICENSE
@@ -0,0 +1,21 @@
+ MIT License
+
+ Copyright (c) Microsoft Corporation.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE
diff --git a/backend/node_modules/@types/qs/README.md b/backend/node_modules/@types/qs/README.md
new file mode 100644
index 0000000..9044010
--- /dev/null
+++ b/backend/node_modules/@types/qs/README.md
@@ -0,0 +1,16 @@
+# Installation
+> `npm install --save @types/qs`
+
+# Summary
+This package contains type definitions for qs (https://github.com/ljharb/qs).
+
+# Details
+Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/qs.
+
+### Additional Details
+ * Last updated: Wed, 07 Jul 2021 17:02:42 GMT
+ * Dependencies: none
+ * Global values: `qs`
+
+# Credits
+These definitions were written by [Roman Korneev](https://github.com/RWander), [Leon Yu](https://github.com/leonyu), [Belinda Teh](https://github.com/tehbelinda), [Melvin Lee](https://github.com/zyml), [Arturs Vonda](https://github.com/artursvonda), [Carlos Bonetti](https://github.com/CarlosBonetti), [Dan Smith](https://github.com/dpsmith3), [Hunter Perrin](https://github.com/hperrin), and [Jordan Harband](https://github.com/ljharb).
diff --git a/backend/node_modules/@types/qs/index.d.ts b/backend/node_modules/@types/qs/index.d.ts
new file mode 100644
index 0000000..35810c5
--- /dev/null
+++ b/backend/node_modules/@types/qs/index.d.ts
@@ -0,0 +1,62 @@
+// Type definitions for qs 6.9
+// Project: https://github.com/ljharb/qs
+// Definitions by: Roman Korneev
+// Leon Yu
+// Belinda Teh
+// Melvin Lee
+// Arturs Vonda
+// Carlos Bonetti
+// Dan Smith
+// Hunter Perrin
+// Jordan Harband
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+export = QueryString;
+export as namespace qs;
+
+declare namespace QueryString {
+ type defaultEncoder = (str: any, defaultEncoder?: any, charset?: string) => string;
+ type defaultDecoder = (str: string, decoder?: any, charset?: string) => string;
+
+ interface IStringifyOptions {
+ delimiter?: string | undefined;
+ strictNullHandling?: boolean | undefined;
+ skipNulls?: boolean | undefined;
+ encode?: boolean | undefined;
+ encoder?: ((str: any, defaultEncoder: defaultEncoder, charset: string, type: 'key' | 'value') => string) | undefined;
+ filter?: Array | ((prefix: string, value: any) => any) | undefined;
+ arrayFormat?: 'indices' | 'brackets' | 'repeat' | 'comma' | undefined;
+ indices?: boolean | undefined;
+ sort?: ((a: any, b: any) => number) | undefined;
+ serializeDate?: ((d: Date) => string) | undefined;
+ format?: 'RFC1738' | 'RFC3986' | undefined;
+ encodeValuesOnly?: boolean | undefined;
+ addQueryPrefix?: boolean | undefined;
+ allowDots?: boolean | undefined;
+ charset?: 'utf-8' | 'iso-8859-1' | undefined;
+ charsetSentinel?: boolean | undefined;
+ }
+
+ interface IParseOptions {
+ comma?: boolean | undefined;
+ delimiter?: string | RegExp | undefined;
+ depth?: number | false | undefined;
+ decoder?: ((str: string, defaultDecoder: defaultDecoder, charset: string, type: 'key' | 'value') => any) | undefined;
+ arrayLimit?: number | undefined;
+ parseArrays?: boolean | undefined;
+ allowDots?: boolean | undefined;
+ plainObjects?: boolean | undefined;
+ allowPrototypes?: boolean | undefined;
+ parameterLimit?: number | undefined;
+ strictNullHandling?: boolean | undefined;
+ ignoreQueryPrefix?: boolean | undefined;
+ charset?: 'utf-8' | 'iso-8859-1' | undefined;
+ charsetSentinel?: boolean | undefined;
+ interpretNumericEntities?: boolean | undefined;
+ }
+
+ interface ParsedQs { [key: string]: undefined | string | string[] | ParsedQs | ParsedQs[] }
+
+ function stringify(obj: any, options?: IStringifyOptions): string;
+ function parse(str: string, options?: IParseOptions & { decoder?: never | undefined }): ParsedQs;
+ function parse(str: string | Record, options?: IParseOptions): { [key: string]: unknown };
+}
diff --git a/backend/node_modules/@types/qs/package.json b/backend/node_modules/@types/qs/package.json
new file mode 100644
index 0000000..7edba8b
--- /dev/null
+++ b/backend/node_modules/@types/qs/package.json
@@ -0,0 +1,65 @@
+{
+ "name": "@types/qs",
+ "version": "6.9.7",
+ "description": "TypeScript definitions for qs",
+ "homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/qs",
+ "license": "MIT",
+ "contributors": [
+ {
+ "name": "Roman Korneev",
+ "url": "https://github.com/RWander",
+ "githubUsername": "RWander"
+ },
+ {
+ "name": "Leon Yu",
+ "url": "https://github.com/leonyu",
+ "githubUsername": "leonyu"
+ },
+ {
+ "name": "Belinda Teh",
+ "url": "https://github.com/tehbelinda",
+ "githubUsername": "tehbelinda"
+ },
+ {
+ "name": "Melvin Lee",
+ "url": "https://github.com/zyml",
+ "githubUsername": "zyml"
+ },
+ {
+ "name": "Arturs Vonda",
+ "url": "https://github.com/artursvonda",
+ "githubUsername": "artursvonda"
+ },
+ {
+ "name": "Carlos Bonetti",
+ "url": "https://github.com/CarlosBonetti",
+ "githubUsername": "CarlosBonetti"
+ },
+ {
+ "name": "Dan Smith",
+ "url": "https://github.com/dpsmith3",
+ "githubUsername": "dpsmith3"
+ },
+ {
+ "name": "Hunter Perrin",
+ "url": "https://github.com/hperrin",
+ "githubUsername": "hperrin"
+ },
+ {
+ "name": "Jordan Harband",
+ "url": "https://github.com/ljharb",
+ "githubUsername": "ljharb"
+ }
+ ],
+ "main": "",
+ "types": "index.d.ts",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
+ "directory": "types/qs"
+ },
+ "scripts": {},
+ "dependencies": {},
+ "typesPublisherContentHash": "b33fed3eed022f94c7db53593571f370eaa77aa17b3e302dc1bd77304f03e56c",
+ "typeScriptVersion": "3.6"
+}
\ No newline at end of file
diff --git a/backend/node_modules/@types/range-parser/LICENSE b/backend/node_modules/@types/range-parser/LICENSE
new file mode 100644
index 0000000..9e841e7
--- /dev/null
+++ b/backend/node_modules/@types/range-parser/LICENSE
@@ -0,0 +1,21 @@
+ MIT License
+
+ Copyright (c) Microsoft Corporation.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE
diff --git a/backend/node_modules/@types/range-parser/README.md b/backend/node_modules/@types/range-parser/README.md
new file mode 100644
index 0000000..16c80f9
--- /dev/null
+++ b/backend/node_modules/@types/range-parser/README.md
@@ -0,0 +1,55 @@
+# Installation
+> `npm install --save @types/range-parser`
+
+# Summary
+This package contains type definitions for range-parser (https://github.com/jshttp/range-parser).
+
+# Details
+Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/range-parser.
+## [index.d.ts](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/range-parser/index.d.ts)
+````ts
+// Type definitions for range-parser 1.2
+// Project: https://github.com/jshttp/range-parser
+// Definitions by: Tomek Łaziuk
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+
+/**
+ * When ranges are returned, the array has a "type" property which is the type of
+ * range that is required (most commonly, "bytes"). Each array element is an object
+ * with a "start" and "end" property for the portion of the range.
+ *
+ * @returns `-1` when unsatisfiable and `-2` when syntactically invalid, ranges otherwise.
+ */
+declare function RangeParser(size: number, str: string, options?: RangeParser.Options): RangeParser.Result | RangeParser.Ranges;
+
+declare namespace RangeParser {
+ interface Ranges extends Array {
+ type: string;
+ }
+ interface Range {
+ start: number;
+ end: number;
+ }
+ interface Options {
+ /**
+ * The "combine" option can be set to `true` and overlapping & adjacent ranges
+ * will be combined into a single range.
+ */
+ combine?: boolean | undefined;
+ }
+ type ResultUnsatisfiable = -1;
+ type ResultInvalid = -2;
+ type Result = ResultUnsatisfiable | ResultInvalid;
+}
+
+export = RangeParser;
+
+````
+
+### Additional Details
+ * Last updated: Wed, 07 Jul 2021 17:02:53 GMT
+ * Dependencies: none
+ * Global values: none
+
+# Credits
+These definitions were written by [Tomek Łaziuk](https://github.com/tlaziuk).
diff --git a/backend/node_modules/@types/range-parser/index.d.ts b/backend/node_modules/@types/range-parser/index.d.ts
new file mode 100644
index 0000000..e973bf3
--- /dev/null
+++ b/backend/node_modules/@types/range-parser/index.d.ts
@@ -0,0 +1,35 @@
+// Type definitions for range-parser 1.2
+// Project: https://github.com/jshttp/range-parser
+// Definitions by: Tomek Łaziuk
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+
+/**
+ * When ranges are returned, the array has a "type" property which is the type of
+ * range that is required (most commonly, "bytes"). Each array element is an object
+ * with a "start" and "end" property for the portion of the range.
+ *
+ * @returns `-1` when unsatisfiable and `-2` when syntactically invalid, ranges otherwise.
+ */
+declare function RangeParser(size: number, str: string, options?: RangeParser.Options): RangeParser.Result | RangeParser.Ranges;
+
+declare namespace RangeParser {
+ interface Ranges extends Array {
+ type: string;
+ }
+ interface Range {
+ start: number;
+ end: number;
+ }
+ interface Options {
+ /**
+ * The "combine" option can be set to `true` and overlapping & adjacent ranges
+ * will be combined into a single range.
+ */
+ combine?: boolean | undefined;
+ }
+ type ResultUnsatisfiable = -1;
+ type ResultInvalid = -2;
+ type Result = ResultUnsatisfiable | ResultInvalid;
+}
+
+export = RangeParser;
diff --git a/backend/node_modules/@types/range-parser/package.json b/backend/node_modules/@types/range-parser/package.json
new file mode 100644
index 0000000..8d7cedb
--- /dev/null
+++ b/backend/node_modules/@types/range-parser/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "@types/range-parser",
+ "version": "1.2.4",
+ "description": "TypeScript definitions for range-parser",
+ "homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/range-parser",
+ "license": "MIT",
+ "contributors": [
+ {
+ "name": "Tomek Łaziuk",
+ "url": "https://github.com/tlaziuk",
+ "githubUsername": "tlaziuk"
+ }
+ ],
+ "main": "",
+ "types": "index.d.ts",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
+ "directory": "types/range-parser"
+ },
+ "scripts": {},
+ "dependencies": {},
+ "typesPublisherContentHash": "60a027a88ae9d7c5ae30935c98266f5033af3c38944121c975bf5e136b9053f3",
+ "typeScriptVersion": "3.6"
+}
\ No newline at end of file
diff --git a/backend/node_modules/@types/serve-static/LICENSE b/backend/node_modules/@types/serve-static/LICENSE
new file mode 100644
index 0000000..9e841e7
--- /dev/null
+++ b/backend/node_modules/@types/serve-static/LICENSE
@@ -0,0 +1,21 @@
+ MIT License
+
+ Copyright (c) Microsoft Corporation.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE
diff --git a/backend/node_modules/@types/serve-static/README.md b/backend/node_modules/@types/serve-static/README.md
new file mode 100644
index 0000000..ccb1d37
--- /dev/null
+++ b/backend/node_modules/@types/serve-static/README.md
@@ -0,0 +1,16 @@
+# Installation
+> `npm install --save @types/serve-static`
+
+# Summary
+This package contains type definitions for serve-static (https://github.com/expressjs/serve-static).
+
+# Details
+Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/serve-static.
+
+### Additional Details
+ * Last updated: Thu, 23 Feb 2023 19:02:39 GMT
+ * Dependencies: [@types/mime](https://npmjs.com/package/@types/mime), [@types/node](https://npmjs.com/package/@types/node)
+ * Global values: none
+
+# Credits
+These definitions were written by [Uros Smolnik](https://github.com/urossmolnik), [Linus Unnebäck](https://github.com/LinusU), and [Devansh Jethmalani](https://github.com/devanshj).
diff --git a/backend/node_modules/@types/serve-static/index.d.ts b/backend/node_modules/@types/serve-static/index.d.ts
new file mode 100644
index 0000000..0939bf3
--- /dev/null
+++ b/backend/node_modules/@types/serve-static/index.d.ts
@@ -0,0 +1,113 @@
+// Type definitions for serve-static 1.15
+// Project: https://github.com/expressjs/serve-static
+// Definitions by: Uros Smolnik
+// Linus Unnebäck
+// Devansh Jethmalani
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+
+///
+import * as m from "mime";
+import * as http from "http";
+
+/**
+ * Create a new middleware function to serve files from within a given root directory.
+ * The file to serve will be determined by combining req.url with the provided root directory.
+ * When a file is not found, instead of sending a 404 response, this module will instead call next() to move on to the next middleware, allowing for stacking and fall-backs.
+ */
+declare function serveStatic(
+ root: string,
+ options?: serveStatic.ServeStaticOptions
+): serveStatic.RequestHandler;
+
+declare namespace serveStatic {
+ var mime: typeof m;
+ interface ServeStaticOptions {
+ /**
+ * Enable or disable accepting ranged requests, defaults to true.
+ * Disabling this will not send Accept-Ranges and ignore the contents of the Range request header.
+ */
+ acceptRanges?: boolean | undefined;
+
+ /**
+ * Enable or disable setting Cache-Control response header, defaults to true.
+ * Disabling this will ignore the immutable and maxAge options.
+ */
+ cacheControl?: boolean | undefined;
+
+ /**
+ * Set how "dotfiles" are treated when encountered. A dotfile is a file or directory that begins with a dot (".").
+ * Note this check is done on the path itself without checking if the path actually exists on the disk.
+ * If root is specified, only the dotfiles above the root are checked (i.e. the root itself can be within a dotfile when when set to "deny").
+ * The default value is 'ignore'.
+ * 'allow' No special treatment for dotfiles
+ * 'deny' Send a 403 for any request for a dotfile
+ * 'ignore' Pretend like the dotfile does not exist and call next()
+ */
+ dotfiles?: string | undefined;
+
+ /**
+ * Enable or disable etag generation, defaults to true.
+ */
+ etag?: boolean | undefined;
+
+ /**
+ * Set file extension fallbacks. When set, if a file is not found, the given extensions will be added to the file name and search for.
+ * The first that exists will be served. Example: ['html', 'htm'].
+ * The default value is false.
+ */
+ extensions?: string[] | false | undefined;
+
+ /**
+ * Let client errors fall-through as unhandled requests, otherwise forward a client error.
+ * The default value is true.
+ */
+ fallthrough?: boolean | undefined;
+
+ /**
+ * Enable or disable the immutable directive in the Cache-Control response header.
+ * If enabled, the maxAge option should also be specified to enable caching. The immutable directive will prevent supported clients from making conditional requests during the life of the maxAge option to check if the file has changed.
+ */
+ immutable?: boolean | undefined;
+
+ /**
+ * By default this module will send "index.html" files in response to a request on a directory.
+ * To disable this set false or to supply a new index pass a string or an array in preferred order.
+ */
+ index?: boolean | string | string[] | undefined;
+
+ /**
+ * Enable or disable Last-Modified header, defaults to true. Uses the file system's last modified value.
+ */
+ lastModified?: boolean | undefined;
+
+ /**
+ * Provide a max-age in milliseconds for http caching, defaults to 0. This can also be a string accepted by the ms module.
+ */
+ maxAge?: number | string | undefined;
+
+ /**
+ * Redirect to trailing "/" when the pathname is a dir. Defaults to true.
+ */
+ redirect?: boolean | undefined;
+
+ /**
+ * Function to set custom headers on response. Alterations to the headers need to occur synchronously.
+ * The function is called as fn(res, path, stat), where the arguments are:
+ * res the response object
+ * path the file path that is being sent
+ * stat the stat object of the file that is being sent
+ */
+ setHeaders?: ((res: R, path: string, stat: any) => any) | undefined;
+ }
+
+ interface RequestHandler {
+ (request: http.IncomingMessage, response: R, next: () => void): any;
+ }
+
+ interface RequestHandlerConstructor {
+ (root: string, options?: ServeStaticOptions): RequestHandler;
+ mime: typeof m;
+ }
+}
+
+export = serveStatic;
diff --git a/backend/node_modules/@types/serve-static/package.json b/backend/node_modules/@types/serve-static/package.json
new file mode 100644
index 0000000..e8f3a21
--- /dev/null
+++ b/backend/node_modules/@types/serve-static/package.json
@@ -0,0 +1,38 @@
+{
+ "name": "@types/serve-static",
+ "version": "1.15.1",
+ "description": "TypeScript definitions for serve-static",
+ "homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/serve-static",
+ "license": "MIT",
+ "contributors": [
+ {
+ "name": "Uros Smolnik",
+ "url": "https://github.com/urossmolnik",
+ "githubUsername": "urossmolnik"
+ },
+ {
+ "name": "Linus Unnebäck",
+ "url": "https://github.com/LinusU",
+ "githubUsername": "LinusU"
+ },
+ {
+ "name": "Devansh Jethmalani",
+ "url": "https://github.com/devanshj",
+ "githubUsername": "devanshj"
+ }
+ ],
+ "main": "",
+ "types": "index.d.ts",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
+ "directory": "types/serve-static"
+ },
+ "scripts": {},
+ "dependencies": {
+ "@types/mime": "*",
+ "@types/node": "*"
+ },
+ "typesPublisherContentHash": "a5245bfbae31bb734209d348df3855b5fae08859f07b3de412d264f25a0b0232",
+ "typeScriptVersion": "4.2"
+}
\ No newline at end of file
diff --git a/backend/node_modules/@types/ws/LICENSE b/backend/node_modules/@types/ws/LICENSE
new file mode 100644
index 0000000..9e841e7
--- /dev/null
+++ b/backend/node_modules/@types/ws/LICENSE
@@ -0,0 +1,21 @@
+ MIT License
+
+ Copyright (c) Microsoft Corporation.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE
diff --git a/backend/node_modules/@types/ws/README.md b/backend/node_modules/@types/ws/README.md
new file mode 100644
index 0000000..c73841d
--- /dev/null
+++ b/backend/node_modules/@types/ws/README.md
@@ -0,0 +1,16 @@
+# Installation
+> `npm install --save @types/ws`
+
+# Summary
+This package contains type definitions for ws (https://github.com/websockets/ws).
+
+# Details
+Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/ws.
+
+### Additional Details
+ * Last updated: Mon, 19 Jul 2021 23:01:29 GMT
+ * Dependencies: [@types/node](https://npmjs.com/package/@types/node)
+ * Global values: none
+
+# Credits
+These definitions were written by [Paul Loyd](https://github.com/loyd), [Margus Lamp](https://github.com/mlamp), [Philippe D'Alva](https://github.com/TitaneBoy), [reduckted](https://github.com/reduckted), [teidesu](https://github.com/teidesu), [Bartosz Wojtkowiak](https://github.com/wojtkowiak), and [Kyle Hensel](https://github.com/k-yle).
diff --git a/backend/node_modules/@types/ws/index.d.ts b/backend/node_modules/@types/ws/index.d.ts
new file mode 100644
index 0000000..d2adbcf
--- /dev/null
+++ b/backend/node_modules/@types/ws/index.d.ts
@@ -0,0 +1,353 @@
+// Type definitions for ws 7.4
+// Project: https://github.com/websockets/ws
+// Definitions by: Paul Loyd
+// Margus Lamp
+// Philippe D'Alva
+// reduckted
+// teidesu
+// Bartosz Wojtkowiak
+// Kyle Hensel
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+
+///
+
+import { EventEmitter } from "events";
+import {
+ Agent,
+ ClientRequest,
+ ClientRequestArgs,
+ IncomingMessage,
+ OutgoingHttpHeaders,
+ Server as HTTPServer,
+} from "http";
+import { Server as HTTPSServer } from "https";
+import { Socket } from "net";
+import { Duplex, DuplexOptions } from "stream";
+import { SecureContextOptions } from "tls";
+import { URL } from "url";
+import { ZlibOptions } from "zlib";
+
+// WebSocket socket.
+declare class WebSocket extends EventEmitter {
+ /** The connection is not yet open. */
+ static readonly CONNECTING: 0;
+ /** The connection is open and ready to communicate. */
+ static readonly OPEN: 1;
+ /** The connection is in the process of closing. */
+ static readonly CLOSING: 2;
+ /** The connection is closed. */
+ static readonly CLOSED: 3;
+
+ binaryType: "nodebuffer" | "arraybuffer" | "fragments";
+ readonly bufferedAmount: number;
+ readonly extensions: string;
+ readonly protocol: string;
+ /** The current state of the connection */
+ readonly readyState:
+ | typeof WebSocket.CONNECTING
+ | typeof WebSocket.OPEN
+ | typeof WebSocket.CLOSING
+ | typeof WebSocket.CLOSED;
+ readonly url: string;
+
+ /** The connection is not yet open. */
+ readonly CONNECTING: 0;
+ /** The connection is open and ready to communicate. */
+ readonly OPEN: 1;
+ /** The connection is in the process of closing. */
+ readonly CLOSING: 2;
+ /** The connection is closed. */
+ readonly CLOSED: 3;
+
+ onopen: (event: WebSocket.OpenEvent) => void;
+ onerror: (event: WebSocket.ErrorEvent) => void;
+ onclose: (event: WebSocket.CloseEvent) => void;
+ onmessage: (event: WebSocket.MessageEvent) => void;
+
+ constructor(address: string | URL, options?: WebSocket.ClientOptions | ClientRequestArgs);
+ constructor(
+ address: string | URL,
+ protocols?: string | string[],
+ options?: WebSocket.ClientOptions | ClientRequestArgs,
+ );
+
+ close(code?: number, data?: string): void;
+ ping(data?: any, mask?: boolean, cb?: (err: Error) => void): void;
+ pong(data?: any, mask?: boolean, cb?: (err: Error) => void): void;
+ send(data: any, cb?: (err?: Error) => void): void;
+ send(
+ data: any,
+ options: { mask?: boolean | undefined; binary?: boolean | undefined; compress?: boolean | undefined; fin?: boolean | undefined },
+ cb?: (err?: Error) => void,
+ ): void;
+ terminate(): void;
+
+ // HTML5 WebSocket events
+ addEventListener(
+ method: "message",
+ cb: (event: { data: any; type: string; target: WebSocket }) => void,
+ options?: WebSocket.EventListenerOptions,
+ ): void;
+ addEventListener(
+ method: "close",
+ cb: (event: { wasClean: boolean; code: number; reason: string; target: WebSocket }) => void,
+ options?: WebSocket.EventListenerOptions,
+ ): void;
+ addEventListener(
+ method: "error",
+ cb: (event: { error: any; message: any; type: string; target: WebSocket }) => void,
+ options?: WebSocket.EventListenerOptions,
+ ): void;
+ addEventListener(
+ method: "open",
+ cb: (event: { target: WebSocket }) => void,
+ options?: WebSocket.EventListenerOptions,
+ ): void;
+ addEventListener(method: string, listener: () => void, options?: WebSocket.EventListenerOptions): void;
+
+ removeEventListener(method: "message", cb?: (event: { data: any; type: string; target: WebSocket }) => void): void;
+ removeEventListener(
+ method: "close",
+ cb?: (event: { wasClean: boolean; code: number; reason: string; target: WebSocket }) => void,
+ ): void;
+ removeEventListener(
+ method: "error",
+ cb?: (event: { error: any; message: any; type: string; target: WebSocket }) => void,
+ ): void;
+ removeEventListener(method: "open", cb?: (event: { target: WebSocket }) => void): void;
+ removeEventListener(method: string, listener?: () => void): void;
+
+ // Events
+ on(event: "close", listener: (this: WebSocket, code: number, reason: string) => void): this;
+ on(event: "error", listener: (this: WebSocket, err: Error) => void): this;
+ on(event: "upgrade", listener: (this: WebSocket, request: IncomingMessage) => void): this;
+ on(event: "message", listener: (this: WebSocket, data: WebSocket.Data) => void): this;
+ on(event: "open", listener: (this: WebSocket) => void): this;
+ on(event: "ping" | "pong", listener: (this: WebSocket, data: Buffer) => void): this;
+ on(
+ event: "unexpected-response",
+ listener: (this: WebSocket, request: ClientRequest, response: IncomingMessage) => void,
+ ): this;
+ on(event: string | symbol, listener: (this: WebSocket, ...args: any[]) => void): this;
+
+ once(event: "close", listener: (this: WebSocket, code: number, reason: string) => void): this;
+ once(event: "error", listener: (this: WebSocket, err: Error) => void): this;
+ once(event: "upgrade", listener: (this: WebSocket, request: IncomingMessage) => void): this;
+ once(event: "message", listener: (this: WebSocket, data: WebSocket.Data) => void): this;
+ once(event: "open", listener: (this: WebSocket) => void): this;
+ once(event: "ping" | "pong", listener: (this: WebSocket, data: Buffer) => void): this;
+ once(
+ event: "unexpected-response",
+ listener: (this: WebSocket, request: ClientRequest, response: IncomingMessage) => void,
+ ): this;
+ once(event: string | symbol, listener: (this: WebSocket, ...args: any[]) => void): this;
+
+ off(event: "close", listener: (this: WebSocket, code: number, reason: string) => void): this;
+ off(event: "error", listener: (this: WebSocket, err: Error) => void): this;
+ off(event: "upgrade", listener: (this: WebSocket, request: IncomingMessage) => void): this;
+ off(event: "message", listener: (this: WebSocket, data: WebSocket.Data) => void): this;
+ off(event: "open", listener: (this: WebSocket) => void): this;
+ off(event: "ping" | "pong", listener: (this: WebSocket, data: Buffer) => void): this;
+ off(
+ event: "unexpected-response",
+ listener: (this: WebSocket, request: ClientRequest, response: IncomingMessage) => void,
+ ): this;
+ off(event: string | symbol, listener: (this: WebSocket, ...args: any[]) => void): this;
+
+ addListener(event: "close", listener: (code: number, message: string) => void): this;
+ addListener(event: "error", listener: (err: Error) => void): this;
+ addListener(event: "upgrade", listener: (request: IncomingMessage) => void): this;
+ addListener(event: "message", listener: (data: WebSocket.Data) => void): this;
+ addListener(event: "open", listener: () => void): this;
+ addListener(event: "ping" | "pong", listener: (data: Buffer) => void): this;
+ addListener(
+ event: "unexpected-response",
+ listener: (request: ClientRequest, response: IncomingMessage) => void,
+ ): this;
+ addListener(event: string | symbol, listener: (...args: any[]) => void): this;
+
+ removeListener(event: "close", listener: (code: number, message: string) => void): this;
+ removeListener(event: "error", listener: (err: Error) => void): this;
+ removeListener(event: "upgrade", listener: (request: IncomingMessage) => void): this;
+ removeListener(event: "message", listener: (data: WebSocket.Data) => void): this;
+ removeListener(event: "open", listener: () => void): this;
+ removeListener(event: "ping" | "pong", listener: (data: Buffer) => void): this;
+ removeListener(
+ event: "unexpected-response",
+ listener: (request: ClientRequest, response: IncomingMessage) => void,
+ ): this;
+ removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
+}
+
+declare namespace WebSocket {
+ /**
+ * Data represents the message payload received over the WebSocket.
+ */
+ type Data = string | Buffer | ArrayBuffer | Buffer[];
+
+ /**
+ * CertMeta represents the accepted types for certificate & key data.
+ */
+ type CertMeta = string | string[] | Buffer | Buffer[];
+
+ /**
+ * VerifyClientCallbackSync is a synchronous callback used to inspect the
+ * incoming message. The return value (boolean) of the function determines
+ * whether or not to accept the handshake.
+ */
+ type VerifyClientCallbackSync = (info: { origin: string; secure: boolean; req: IncomingMessage }) => boolean;
+
+ /**
+ * VerifyClientCallbackAsync is an asynchronous callback used to inspect the
+ * incoming message. The return value (boolean) of the function determines
+ * whether or not to accept the handshake.
+ */
+ type VerifyClientCallbackAsync = (
+ info: { origin: string; secure: boolean; req: IncomingMessage },
+ callback: (res: boolean, code?: number, message?: string, headers?: OutgoingHttpHeaders) => void,
+ ) => void;
+
+ interface ClientOptions extends SecureContextOptions {
+ protocol?: string | undefined;
+ followRedirects?: boolean | undefined;
+ handshakeTimeout?: number | undefined;
+ maxRedirects?: number | undefined;
+ perMessageDeflate?: boolean | PerMessageDeflateOptions | undefined;
+ localAddress?: string | undefined;
+ protocolVersion?: number | undefined;
+ headers?: { [key: string]: string } | undefined;
+ origin?: string | undefined;
+ agent?: Agent | undefined;
+ host?: string | undefined;
+ family?: number | undefined;
+ checkServerIdentity?(servername: string, cert: CertMeta): boolean;
+ rejectUnauthorized?: boolean | undefined;
+ maxPayload?: number | undefined;
+ }
+
+ interface PerMessageDeflateOptions {
+ serverNoContextTakeover?: boolean | undefined;
+ clientNoContextTakeover?: boolean | undefined;
+ serverMaxWindowBits?: number | undefined;
+ clientMaxWindowBits?: number | undefined;
+ zlibDeflateOptions?: {
+ flush?: number | undefined;
+ finishFlush?: number | undefined;
+ chunkSize?: number | undefined;
+ windowBits?: number | undefined;
+ level?: number | undefined;
+ memLevel?: number | undefined;
+ strategy?: number | undefined;
+ dictionary?: Buffer | Buffer[] | DataView | undefined;
+ info?: boolean | undefined;
+ } | undefined;
+ zlibInflateOptions?: ZlibOptions | undefined;
+ threshold?: number | undefined;
+ concurrencyLimit?: number | undefined;
+ }
+
+ interface OpenEvent {
+ type: string;
+ target: WebSocket;
+ }
+
+ interface ErrorEvent {
+ error: any;
+ message: string;
+ type: string;
+ target: WebSocket;
+ }
+
+ interface CloseEvent {
+ wasClean: boolean;
+ code: number;
+ reason: string;
+ type: string;
+ target: WebSocket;
+ }
+
+ interface MessageEvent {
+ data: Data;
+ type: string;
+ target: WebSocket;
+ }
+
+ interface EventListenerOptions {
+ once?: boolean | undefined;
+ }
+
+ interface ServerOptions {
+ host?: string | undefined;
+ port?: number | undefined;
+ backlog?: number | undefined;
+ server?: HTTPServer | HTTPSServer | undefined;
+ verifyClient?: VerifyClientCallbackAsync | VerifyClientCallbackSync | undefined;
+ handleProtocols?: any;
+ path?: string | undefined;
+ noServer?: boolean | undefined;
+ clientTracking?: boolean | undefined;
+ perMessageDeflate?: boolean | PerMessageDeflateOptions | undefined;
+ maxPayload?: number | undefined;
+ }
+
+ interface AddressInfo {
+ address: string;
+ family: string;
+ port: number;
+ }
+
+ // WebSocket Server
+ class Server extends EventEmitter {
+ options: ServerOptions;
+ path: string;
+ clients: Set;
+
+ constructor(options?: ServerOptions, callback?: () => void);
+
+ address(): AddressInfo | string;
+ close(cb?: (err?: Error) => void): void;
+ handleUpgrade(
+ request: IncomingMessage,
+ socket: Socket,
+ upgradeHead: Buffer,
+ callback: (client: WebSocket, request: IncomingMessage) => void,
+ ): void;
+ shouldHandle(request: IncomingMessage): boolean | Promise;
+
+ // Events
+ on(event: "connection", cb: (this: Server, socket: WebSocket, request: IncomingMessage) => void): this;
+ on(event: "error", cb: (this: Server, error: Error) => void): this;
+ on(event: "headers", cb: (this: Server, headers: string[], request: IncomingMessage) => void): this;
+ on(event: "close" | "listening", cb: (this: Server) => void): this;
+ on(event: string | symbol, listener: (this: Server, ...args: any[]) => void): this;
+
+ once(event: "connection", cb: (this: Server, socket: WebSocket, request: IncomingMessage) => void): this;
+ once(event: "error", cb: (this: Server, error: Error) => void): this;
+ once(event: "headers", cb: (this: Server, headers: string[], request: IncomingMessage) => void): this;
+ once(event: "close" | "listening", cb: (this: Server) => void): this;
+ once(event: string | symbol, listener: (...args: any[]) => void): this;
+
+ off(event: "connection", cb: (this: Server, socket: WebSocket, request: IncomingMessage) => void): this;
+ off(event: "error", cb: (this: Server, error: Error) => void): this;
+ off(event: "headers", cb: (this: Server, headers: string[], request: IncomingMessage) => void): this;
+ off(event: "close" | "listening", cb: (this: Server) => void): this;
+ off(event: string | symbol, listener: (this: Server, ...args: any[]) => void): this;
+
+ addListener(event: "connection", cb: (client: WebSocket, request: IncomingMessage) => void): this;
+ addListener(event: "error", cb: (err: Error) => void): this;
+ addListener(event: "headers", cb: (headers: string[], request: IncomingMessage) => void): this;
+ addListener(event: "close" | "listening", cb: () => void): this;
+ addListener(event: string | symbol, listener: (...args: any[]) => void): this;
+
+ removeListener(event: "connection", cb: (client: WebSocket) => void): this;
+ removeListener(event: "error", cb: (err: Error) => void): this;
+ removeListener(event: "headers", cb: (headers: string[], request: IncomingMessage) => void): this;
+ removeListener(event: "close" | "listening", cb: () => void): this;
+ removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
+ }
+
+ // WebSocket stream
+ function createWebSocketStream(websocket: WebSocket, options?: DuplexOptions): Duplex;
+}
+
+export = WebSocket;
diff --git a/backend/node_modules/@types/ws/package.json b/backend/node_modules/@types/ws/package.json
new file mode 100644
index 0000000..b3ea358
--- /dev/null
+++ b/backend/node_modules/@types/ws/package.json
@@ -0,0 +1,57 @@
+{
+ "name": "@types/ws",
+ "version": "7.4.7",
+ "description": "TypeScript definitions for ws",
+ "homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/ws",
+ "license": "MIT",
+ "contributors": [
+ {
+ "name": "Paul Loyd",
+ "url": "https://github.com/loyd",
+ "githubUsername": "loyd"
+ },
+ {
+ "name": "Margus Lamp",
+ "url": "https://github.com/mlamp",
+ "githubUsername": "mlamp"
+ },
+ {
+ "name": "Philippe D'Alva",
+ "url": "https://github.com/TitaneBoy",
+ "githubUsername": "TitaneBoy"
+ },
+ {
+ "name": "reduckted",
+ "url": "https://github.com/reduckted",
+ "githubUsername": "reduckted"
+ },
+ {
+ "name": "teidesu",
+ "url": "https://github.com/teidesu",
+ "githubUsername": "teidesu"
+ },
+ {
+ "name": "Bartosz Wojtkowiak",
+ "url": "https://github.com/wojtkowiak",
+ "githubUsername": "wojtkowiak"
+ },
+ {
+ "name": "Kyle Hensel",
+ "url": "https://github.com/k-yle",
+ "githubUsername": "k-yle"
+ }
+ ],
+ "main": "",
+ "types": "index.d.ts",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
+ "directory": "types/ws"
+ },
+ "scripts": {},
+ "dependencies": {
+ "@types/node": "*"
+ },
+ "typesPublisherContentHash": "bfa5f3d19c5c1f1c415aec2e218c5c83c4c88b441bb05b2c022b6cfee2c36dfd",
+ "typeScriptVersion": "3.6"
+}
\ No newline at end of file
diff --git a/backend/node_modules/ansi-regex/index.d.ts b/backend/node_modules/ansi-regex/index.d.ts
new file mode 100644
index 0000000..2dbf6af
--- /dev/null
+++ b/backend/node_modules/ansi-regex/index.d.ts
@@ -0,0 +1,37 @@
+declare namespace ansiRegex {
+ interface Options {
+ /**
+ Match only the first ANSI escape.
+
+ @default false
+ */
+ onlyFirst: boolean;
+ }
+}
+
+/**
+Regular expression for matching ANSI escape codes.
+
+@example
+```
+import ansiRegex = require('ansi-regex');
+
+ansiRegex().test('\u001B[4mcake\u001B[0m');
+//=> true
+
+ansiRegex().test('cake');
+//=> false
+
+'\u001B[4mcake\u001B[0m'.match(ansiRegex());
+//=> ['\u001B[4m', '\u001B[0m']
+
+'\u001B[4mcake\u001B[0m'.match(ansiRegex({onlyFirst: true}));
+//=> ['\u001B[4m']
+
+'\u001B]8;;https://github.com\u0007click\u001B]8;;\u0007'.match(ansiRegex());
+//=> ['\u001B]8;;https://github.com\u0007', '\u001B]8;;\u0007']
+```
+*/
+declare function ansiRegex(options?: ansiRegex.Options): RegExp;
+
+export = ansiRegex;
diff --git a/backend/node_modules/ansi-regex/index.js b/backend/node_modules/ansi-regex/index.js
new file mode 100644
index 0000000..616ff83
--- /dev/null
+++ b/backend/node_modules/ansi-regex/index.js
@@ -0,0 +1,10 @@
+'use strict';
+
+module.exports = ({onlyFirst = false} = {}) => {
+ const pattern = [
+ '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
+ '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'
+ ].join('|');
+
+ return new RegExp(pattern, onlyFirst ? undefined : 'g');
+};
diff --git a/backend/node_modules/ansi-regex/license b/backend/node_modules/ansi-regex/license
new file mode 100644
index 0000000..e7af2f7
--- /dev/null
+++ b/backend/node_modules/ansi-regex/license
@@ -0,0 +1,9 @@
+MIT License
+
+Copyright (c) Sindre Sorhus (sindresorhus.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/backend/node_modules/ansi-regex/package.json b/backend/node_modules/ansi-regex/package.json
new file mode 100644
index 0000000..017f531
--- /dev/null
+++ b/backend/node_modules/ansi-regex/package.json
@@ -0,0 +1,55 @@
+{
+ "name": "ansi-regex",
+ "version": "5.0.1",
+ "description": "Regular expression for matching ANSI escape codes",
+ "license": "MIT",
+ "repository": "chalk/ansi-regex",
+ "author": {
+ "name": "Sindre Sorhus",
+ "email": "sindresorhus@gmail.com",
+ "url": "sindresorhus.com"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "scripts": {
+ "test": "xo && ava && tsd",
+ "view-supported": "node fixtures/view-codes.js"
+ },
+ "files": [
+ "index.js",
+ "index.d.ts"
+ ],
+ "keywords": [
+ "ansi",
+ "styles",
+ "color",
+ "colour",
+ "colors",
+ "terminal",
+ "console",
+ "cli",
+ "string",
+ "tty",
+ "escape",
+ "formatting",
+ "rgb",
+ "256",
+ "shell",
+ "xterm",
+ "command-line",
+ "text",
+ "regex",
+ "regexp",
+ "re",
+ "match",
+ "test",
+ "find",
+ "pattern"
+ ],
+ "devDependencies": {
+ "ava": "^2.4.0",
+ "tsd": "^0.9.0",
+ "xo": "^0.25.3"
+ }
+}
diff --git a/backend/node_modules/ansi-regex/readme.md b/backend/node_modules/ansi-regex/readme.md
new file mode 100644
index 0000000..4d848bc
--- /dev/null
+++ b/backend/node_modules/ansi-regex/readme.md
@@ -0,0 +1,78 @@
+# ansi-regex
+
+> Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)
+
+
+## Install
+
+```
+$ npm install ansi-regex
+```
+
+
+## Usage
+
+```js
+const ansiRegex = require('ansi-regex');
+
+ansiRegex().test('\u001B[4mcake\u001B[0m');
+//=> true
+
+ansiRegex().test('cake');
+//=> false
+
+'\u001B[4mcake\u001B[0m'.match(ansiRegex());
+//=> ['\u001B[4m', '\u001B[0m']
+
+'\u001B[4mcake\u001B[0m'.match(ansiRegex({onlyFirst: true}));
+//=> ['\u001B[4m']
+
+'\u001B]8;;https://github.com\u0007click\u001B]8;;\u0007'.match(ansiRegex());
+//=> ['\u001B]8;;https://github.com\u0007', '\u001B]8;;\u0007']
+```
+
+
+## API
+
+### ansiRegex(options?)
+
+Returns a regex for matching ANSI escape codes.
+
+#### options
+
+Type: `object`
+
+##### onlyFirst
+
+Type: `boolean`
+Default: `false` *(Matches any ANSI escape codes in a string)*
+
+Match only the first ANSI escape.
+
+
+## FAQ
+
+### Why do you test for codes not in the ECMA 48 standard?
+
+Some of the codes we run as a test are codes that we acquired finding various lists of non-standard or manufacturer specific codes. We test for both standard and non-standard codes, as most of them follow the same or similar format and can be safely matched in strings without the risk of removing actual string content. There are a few non-standard control codes that do not follow the traditional format (i.e. they end in numbers) thus forcing us to exclude them from the test because we cannot reliably match them.
+
+On the historical side, those ECMA standards were established in the early 90's whereas the VT100, for example, was designed in the mid/late 70's. At that point in time, control codes were still pretty ungoverned and engineers used them for a multitude of things, namely to activate hardware ports that may have been proprietary. Somewhere else you see a similar 'anarchy' of codes is in the x86 architecture for processors; there are a ton of "interrupts" that can mean different things on certain brands of processors, most of which have been phased out.
+
+
+## Maintainers
+
+- [Sindre Sorhus](https://github.com/sindresorhus)
+- [Josh Junon](https://github.com/qix-)
+
+
+---
+
+
diff --git a/backend/node_modules/ansi-styles/index.d.ts b/backend/node_modules/ansi-styles/index.d.ts
new file mode 100644
index 0000000..44a907e
--- /dev/null
+++ b/backend/node_modules/ansi-styles/index.d.ts
@@ -0,0 +1,345 @@
+declare type CSSColor =
+ | 'aliceblue'
+ | 'antiquewhite'
+ | 'aqua'
+ | 'aquamarine'
+ | 'azure'
+ | 'beige'
+ | 'bisque'
+ | 'black'
+ | 'blanchedalmond'
+ | 'blue'
+ | 'blueviolet'
+ | 'brown'
+ | 'burlywood'
+ | 'cadetblue'
+ | 'chartreuse'
+ | 'chocolate'
+ | 'coral'
+ | 'cornflowerblue'
+ | 'cornsilk'
+ | 'crimson'
+ | 'cyan'
+ | 'darkblue'
+ | 'darkcyan'
+ | 'darkgoldenrod'
+ | 'darkgray'
+ | 'darkgreen'
+ | 'darkgrey'
+ | 'darkkhaki'
+ | 'darkmagenta'
+ | 'darkolivegreen'
+ | 'darkorange'
+ | 'darkorchid'
+ | 'darkred'
+ | 'darksalmon'
+ | 'darkseagreen'
+ | 'darkslateblue'
+ | 'darkslategray'
+ | 'darkslategrey'
+ | 'darkturquoise'
+ | 'darkviolet'
+ | 'deeppink'
+ | 'deepskyblue'
+ | 'dimgray'
+ | 'dimgrey'
+ | 'dodgerblue'
+ | 'firebrick'
+ | 'floralwhite'
+ | 'forestgreen'
+ | 'fuchsia'
+ | 'gainsboro'
+ | 'ghostwhite'
+ | 'gold'
+ | 'goldenrod'
+ | 'gray'
+ | 'green'
+ | 'greenyellow'
+ | 'grey'
+ | 'honeydew'
+ | 'hotpink'
+ | 'indianred'
+ | 'indigo'
+ | 'ivory'
+ | 'khaki'
+ | 'lavender'
+ | 'lavenderblush'
+ | 'lawngreen'
+ | 'lemonchiffon'
+ | 'lightblue'
+ | 'lightcoral'
+ | 'lightcyan'
+ | 'lightgoldenrodyellow'
+ | 'lightgray'
+ | 'lightgreen'
+ | 'lightgrey'
+ | 'lightpink'
+ | 'lightsalmon'
+ | 'lightseagreen'
+ | 'lightskyblue'
+ | 'lightslategray'
+ | 'lightslategrey'
+ | 'lightsteelblue'
+ | 'lightyellow'
+ | 'lime'
+ | 'limegreen'
+ | 'linen'
+ | 'magenta'
+ | 'maroon'
+ | 'mediumaquamarine'
+ | 'mediumblue'
+ | 'mediumorchid'
+ | 'mediumpurple'
+ | 'mediumseagreen'
+ | 'mediumslateblue'
+ | 'mediumspringgreen'
+ | 'mediumturquoise'
+ | 'mediumvioletred'
+ | 'midnightblue'
+ | 'mintcream'
+ | 'mistyrose'
+ | 'moccasin'
+ | 'navajowhite'
+ | 'navy'
+ | 'oldlace'
+ | 'olive'
+ | 'olivedrab'
+ | 'orange'
+ | 'orangered'
+ | 'orchid'
+ | 'palegoldenrod'
+ | 'palegreen'
+ | 'paleturquoise'
+ | 'palevioletred'
+ | 'papayawhip'
+ | 'peachpuff'
+ | 'peru'
+ | 'pink'
+ | 'plum'
+ | 'powderblue'
+ | 'purple'
+ | 'rebeccapurple'
+ | 'red'
+ | 'rosybrown'
+ | 'royalblue'
+ | 'saddlebrown'
+ | 'salmon'
+ | 'sandybrown'
+ | 'seagreen'
+ | 'seashell'
+ | 'sienna'
+ | 'silver'
+ | 'skyblue'
+ | 'slateblue'
+ | 'slategray'
+ | 'slategrey'
+ | 'snow'
+ | 'springgreen'
+ | 'steelblue'
+ | 'tan'
+ | 'teal'
+ | 'thistle'
+ | 'tomato'
+ | 'turquoise'
+ | 'violet'
+ | 'wheat'
+ | 'white'
+ | 'whitesmoke'
+ | 'yellow'
+ | 'yellowgreen';
+
+declare namespace ansiStyles {
+ interface ColorConvert {
+ /**
+ The RGB color space.
+
+ @param red - (`0`-`255`)
+ @param green - (`0`-`255`)
+ @param blue - (`0`-`255`)
+ */
+ rgb(red: number, green: number, blue: number): string;
+
+ /**
+ The RGB HEX color space.
+
+ @param hex - A hexadecimal string containing RGB data.
+ */
+ hex(hex: string): string;
+
+ /**
+ @param keyword - A CSS color name.
+ */
+ keyword(keyword: CSSColor): string;
+
+ /**
+ The HSL color space.
+
+ @param hue - (`0`-`360`)
+ @param saturation - (`0`-`100`)
+ @param lightness - (`0`-`100`)
+ */
+ hsl(hue: number, saturation: number, lightness: number): string;
+
+ /**
+ The HSV color space.
+
+ @param hue - (`0`-`360`)
+ @param saturation - (`0`-`100`)
+ @param value - (`0`-`100`)
+ */
+ hsv(hue: number, saturation: number, value: number): string;
+
+ /**
+ The HSV color space.
+
+ @param hue - (`0`-`360`)
+ @param whiteness - (`0`-`100`)
+ @param blackness - (`0`-`100`)
+ */
+ hwb(hue: number, whiteness: number, blackness: number): string;
+
+ /**
+ Use a [4-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4-bit) to set text color.
+ */
+ ansi(ansi: number): string;
+
+ /**
+ Use an [8-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) to set text color.
+ */
+ ansi256(ansi: number): string;
+ }
+
+ interface CSPair {
+ /**
+ The ANSI terminal control sequence for starting this style.
+ */
+ readonly open: string;
+
+ /**
+ The ANSI terminal control sequence for ending this style.
+ */
+ readonly close: string;
+ }
+
+ interface ColorBase {
+ readonly ansi: ColorConvert;
+ readonly ansi256: ColorConvert;
+ readonly ansi16m: ColorConvert;
+
+ /**
+ The ANSI terminal control sequence for ending this color.
+ */
+ readonly close: string;
+ }
+
+ interface Modifier {
+ /**
+ Resets the current color chain.
+ */
+ readonly reset: CSPair;
+
+ /**
+ Make text bold.
+ */
+ readonly bold: CSPair;
+
+ /**
+ Emitting only a small amount of light.
+ */
+ readonly dim: CSPair;
+
+ /**
+ Make text italic. (Not widely supported)
+ */
+ readonly italic: CSPair;
+
+ /**
+ Make text underline. (Not widely supported)
+ */
+ readonly underline: CSPair;
+
+ /**
+ Inverse background and foreground colors.
+ */
+ readonly inverse: CSPair;
+
+ /**
+ Prints the text, but makes it invisible.
+ */
+ readonly hidden: CSPair;
+
+ /**
+ Puts a horizontal line through the center of the text. (Not widely supported)
+ */
+ readonly strikethrough: CSPair;
+ }
+
+ interface ForegroundColor {
+ readonly black: CSPair;
+ readonly red: CSPair;
+ readonly green: CSPair;
+ readonly yellow: CSPair;
+ readonly blue: CSPair;
+ readonly cyan: CSPair;
+ readonly magenta: CSPair;
+ readonly white: CSPair;
+
+ /**
+ Alias for `blackBright`.
+ */
+ readonly gray: CSPair;
+
+ /**
+ Alias for `blackBright`.
+ */
+ readonly grey: CSPair;
+
+ readonly blackBright: CSPair;
+ readonly redBright: CSPair;
+ readonly greenBright: CSPair;
+ readonly yellowBright: CSPair;
+ readonly blueBright: CSPair;
+ readonly cyanBright: CSPair;
+ readonly magentaBright: CSPair;
+ readonly whiteBright: CSPair;
+ }
+
+ interface BackgroundColor {
+ readonly bgBlack: CSPair;
+ readonly bgRed: CSPair;
+ readonly bgGreen: CSPair;
+ readonly bgYellow: CSPair;
+ readonly bgBlue: CSPair;
+ readonly bgCyan: CSPair;
+ readonly bgMagenta: CSPair;
+ readonly bgWhite: CSPair;
+
+ /**
+ Alias for `bgBlackBright`.
+ */
+ readonly bgGray: CSPair;
+
+ /**
+ Alias for `bgBlackBright`.
+ */
+ readonly bgGrey: CSPair;
+
+ readonly bgBlackBright: CSPair;
+ readonly bgRedBright: CSPair;
+ readonly bgGreenBright: CSPair;
+ readonly bgYellowBright: CSPair;
+ readonly bgBlueBright: CSPair;
+ readonly bgCyanBright: CSPair;
+ readonly bgMagentaBright: CSPair;
+ readonly bgWhiteBright: CSPair;
+ }
+}
+
+declare const ansiStyles: {
+ readonly modifier: ansiStyles.Modifier;
+ readonly color: ansiStyles.ForegroundColor & ansiStyles.ColorBase;
+ readonly bgColor: ansiStyles.BackgroundColor & ansiStyles.ColorBase;
+ readonly codes: ReadonlyMap;
+} & ansiStyles.BackgroundColor & ansiStyles.ForegroundColor & ansiStyles.Modifier;
+
+export = ansiStyles;
diff --git a/backend/node_modules/ansi-styles/index.js b/backend/node_modules/ansi-styles/index.js
new file mode 100644
index 0000000..5d82581
--- /dev/null
+++ b/backend/node_modules/ansi-styles/index.js
@@ -0,0 +1,163 @@
+'use strict';
+
+const wrapAnsi16 = (fn, offset) => (...args) => {
+ const code = fn(...args);
+ return `\u001B[${code + offset}m`;
+};
+
+const wrapAnsi256 = (fn, offset) => (...args) => {
+ const code = fn(...args);
+ return `\u001B[${38 + offset};5;${code}m`;
+};
+
+const wrapAnsi16m = (fn, offset) => (...args) => {
+ const rgb = fn(...args);
+ return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`;
+};
+
+const ansi2ansi = n => n;
+const rgb2rgb = (r, g, b) => [r, g, b];
+
+const setLazyProperty = (object, property, get) => {
+ Object.defineProperty(object, property, {
+ get: () => {
+ const value = get();
+
+ Object.defineProperty(object, property, {
+ value,
+ enumerable: true,
+ configurable: true
+ });
+
+ return value;
+ },
+ enumerable: true,
+ configurable: true
+ });
+};
+
+/** @type {typeof import('color-convert')} */
+let colorConvert;
+const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => {
+ if (colorConvert === undefined) {
+ colorConvert = require('color-convert');
+ }
+
+ const offset = isBackground ? 10 : 0;
+ const styles = {};
+
+ for (const [sourceSpace, suite] of Object.entries(colorConvert)) {
+ const name = sourceSpace === 'ansi16' ? 'ansi' : sourceSpace;
+ if (sourceSpace === targetSpace) {
+ styles[name] = wrap(identity, offset);
+ } else if (typeof suite === 'object') {
+ styles[name] = wrap(suite[targetSpace], offset);
+ }
+ }
+
+ return styles;
+};
+
+function assembleStyles() {
+ const codes = new Map();
+ const styles = {
+ modifier: {
+ reset: [0, 0],
+ // 21 isn't widely supported and 22 does the same thing
+ bold: [1, 22],
+ dim: [2, 22],
+ italic: [3, 23],
+ underline: [4, 24],
+ inverse: [7, 27],
+ hidden: [8, 28],
+ strikethrough: [9, 29]
+ },
+ color: {
+ black: [30, 39],
+ red: [31, 39],
+ green: [32, 39],
+ yellow: [33, 39],
+ blue: [34, 39],
+ magenta: [35, 39],
+ cyan: [36, 39],
+ white: [37, 39],
+
+ // Bright color
+ blackBright: [90, 39],
+ redBright: [91, 39],
+ greenBright: [92, 39],
+ yellowBright: [93, 39],
+ blueBright: [94, 39],
+ magentaBright: [95, 39],
+ cyanBright: [96, 39],
+ whiteBright: [97, 39]
+ },
+ bgColor: {
+ bgBlack: [40, 49],
+ bgRed: [41, 49],
+ bgGreen: [42, 49],
+ bgYellow: [43, 49],
+ bgBlue: [44, 49],
+ bgMagenta: [45, 49],
+ bgCyan: [46, 49],
+ bgWhite: [47, 49],
+
+ // Bright color
+ bgBlackBright: [100, 49],
+ bgRedBright: [101, 49],
+ bgGreenBright: [102, 49],
+ bgYellowBright: [103, 49],
+ bgBlueBright: [104, 49],
+ bgMagentaBright: [105, 49],
+ bgCyanBright: [106, 49],
+ bgWhiteBright: [107, 49]
+ }
+ };
+
+ // Alias bright black as gray (and grey)
+ styles.color.gray = styles.color.blackBright;
+ styles.bgColor.bgGray = styles.bgColor.bgBlackBright;
+ styles.color.grey = styles.color.blackBright;
+ styles.bgColor.bgGrey = styles.bgColor.bgBlackBright;
+
+ for (const [groupName, group] of Object.entries(styles)) {
+ for (const [styleName, style] of Object.entries(group)) {
+ styles[styleName] = {
+ open: `\u001B[${style[0]}m`,
+ close: `\u001B[${style[1]}m`
+ };
+
+ group[styleName] = styles[styleName];
+
+ codes.set(style[0], style[1]);
+ }
+
+ Object.defineProperty(styles, groupName, {
+ value: group,
+ enumerable: false
+ });
+ }
+
+ Object.defineProperty(styles, 'codes', {
+ value: codes,
+ enumerable: false
+ });
+
+ styles.color.close = '\u001B[39m';
+ styles.bgColor.close = '\u001B[49m';
+
+ setLazyProperty(styles.color, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, false));
+ setLazyProperty(styles.color, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, false));
+ setLazyProperty(styles.color, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, false));
+ setLazyProperty(styles.bgColor, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, true));
+ setLazyProperty(styles.bgColor, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, true));
+ setLazyProperty(styles.bgColor, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, true));
+
+ return styles;
+}
+
+// Make the export immutable
+Object.defineProperty(module, 'exports', {
+ enumerable: true,
+ get: assembleStyles
+});
diff --git a/backend/node_modules/ansi-styles/license b/backend/node_modules/ansi-styles/license
new file mode 100644
index 0000000..e7af2f7
--- /dev/null
+++ b/backend/node_modules/ansi-styles/license
@@ -0,0 +1,9 @@
+MIT License
+
+Copyright (c) Sindre Sorhus (sindresorhus.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/backend/node_modules/ansi-styles/package.json b/backend/node_modules/ansi-styles/package.json
new file mode 100644
index 0000000..7539328
--- /dev/null
+++ b/backend/node_modules/ansi-styles/package.json
@@ -0,0 +1,56 @@
+{
+ "name": "ansi-styles",
+ "version": "4.3.0",
+ "description": "ANSI escape codes for styling strings in the terminal",
+ "license": "MIT",
+ "repository": "chalk/ansi-styles",
+ "funding": "https://github.com/chalk/ansi-styles?sponsor=1",
+ "author": {
+ "name": "Sindre Sorhus",
+ "email": "sindresorhus@gmail.com",
+ "url": "sindresorhus.com"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "scripts": {
+ "test": "xo && ava && tsd",
+ "screenshot": "svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"
+ },
+ "files": [
+ "index.js",
+ "index.d.ts"
+ ],
+ "keywords": [
+ "ansi",
+ "styles",
+ "color",
+ "colour",
+ "colors",
+ "terminal",
+ "console",
+ "cli",
+ "string",
+ "tty",
+ "escape",
+ "formatting",
+ "rgb",
+ "256",
+ "shell",
+ "xterm",
+ "log",
+ "logging",
+ "command-line",
+ "text"
+ ],
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "devDependencies": {
+ "@types/color-convert": "^1.9.0",
+ "ava": "^2.3.0",
+ "svg-term-cli": "^2.1.1",
+ "tsd": "^0.11.0",
+ "xo": "^0.25.3"
+ }
+}
diff --git a/backend/node_modules/ansi-styles/readme.md b/backend/node_modules/ansi-styles/readme.md
new file mode 100644
index 0000000..24883de
--- /dev/null
+++ b/backend/node_modules/ansi-styles/readme.md
@@ -0,0 +1,152 @@
+# ansi-styles [](https://travis-ci.org/chalk/ansi-styles)
+
+> [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) for styling strings in the terminal
+
+You probably want the higher-level [chalk](https://github.com/chalk/chalk) module for styling your strings.
+
+
+
+## Install
+
+```
+$ npm install ansi-styles
+```
+
+## Usage
+
+```js
+const style = require('ansi-styles');
+
+console.log(`${style.green.open}Hello world!${style.green.close}`);
+
+
+// Color conversion between 16/256/truecolor
+// NOTE: If conversion goes to 16 colors or 256 colors, the original color
+// may be degraded to fit that color palette. This means terminals
+// that do not support 16 million colors will best-match the
+// original color.
+console.log(style.bgColor.ansi.hsl(120, 80, 72) + 'Hello world!' + style.bgColor.close);
+console.log(style.color.ansi256.rgb(199, 20, 250) + 'Hello world!' + style.color.close);
+console.log(style.color.ansi16m.hex('#abcdef') + 'Hello world!' + style.color.close);
+```
+
+## API
+
+Each style has an `open` and `close` property.
+
+## Styles
+
+### Modifiers
+
+- `reset`
+- `bold`
+- `dim`
+- `italic` *(Not widely supported)*
+- `underline`
+- `inverse`
+- `hidden`
+- `strikethrough` *(Not widely supported)*
+
+### Colors
+
+- `black`
+- `red`
+- `green`
+- `yellow`
+- `blue`
+- `magenta`
+- `cyan`
+- `white`
+- `blackBright` (alias: `gray`, `grey`)
+- `redBright`
+- `greenBright`
+- `yellowBright`
+- `blueBright`
+- `magentaBright`
+- `cyanBright`
+- `whiteBright`
+
+### Background colors
+
+- `bgBlack`
+- `bgRed`
+- `bgGreen`
+- `bgYellow`
+- `bgBlue`
+- `bgMagenta`
+- `bgCyan`
+- `bgWhite`
+- `bgBlackBright` (alias: `bgGray`, `bgGrey`)
+- `bgRedBright`
+- `bgGreenBright`
+- `bgYellowBright`
+- `bgBlueBright`
+- `bgMagentaBright`
+- `bgCyanBright`
+- `bgWhiteBright`
+
+## Advanced usage
+
+By default, you get a map of styles, but the styles are also available as groups. They are non-enumerable so they don't show up unless you access them explicitly. This makes it easier to expose only a subset in a higher-level module.
+
+- `style.modifier`
+- `style.color`
+- `style.bgColor`
+
+###### Example
+
+```js
+console.log(style.color.green.open);
+```
+
+Raw escape codes (i.e. without the CSI escape prefix `\u001B[` and render mode postfix `m`) are available under `style.codes`, which returns a `Map` with the open codes as keys and close codes as values.
+
+###### Example
+
+```js
+console.log(style.codes.get(36));
+//=> 39
+```
+
+## [256 / 16 million (TrueColor) support](https://gist.github.com/XVilka/8346728)
+
+`ansi-styles` uses the [`color-convert`](https://github.com/Qix-/color-convert) package to allow for converting between various colors and ANSI escapes, with support for 256 and 16 million colors.
+
+The following color spaces from `color-convert` are supported:
+
+- `rgb`
+- `hex`
+- `keyword`
+- `hsl`
+- `hsv`
+- `hwb`
+- `ansi`
+- `ansi256`
+
+To use these, call the associated conversion function with the intended output, for example:
+
+```js
+style.color.ansi.rgb(100, 200, 15); // RGB to 16 color ansi foreground code
+style.bgColor.ansi.rgb(100, 200, 15); // RGB to 16 color ansi background code
+
+style.color.ansi256.hsl(120, 100, 60); // HSL to 256 color ansi foreground code
+style.bgColor.ansi256.hsl(120, 100, 60); // HSL to 256 color ansi foreground code
+
+style.color.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color foreground code
+style.bgColor.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color background code
+```
+
+## Related
+
+- [ansi-escapes](https://github.com/sindresorhus/ansi-escapes) - ANSI escape codes for manipulating the terminal
+
+## Maintainers
+
+- [Sindre Sorhus](https://github.com/sindresorhus)
+- [Josh Junon](https://github.com/qix-)
+
+## For enterprise
+
+Available as part of the Tidelift Subscription.
+
+The maintainers of `ansi-styles` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-ansi-styles?utm_source=npm-ansi-styles&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
diff --git a/backend/node_modules/base64-js/LICENSE b/backend/node_modules/base64-js/LICENSE
new file mode 100644
index 0000000..6d52b8a
--- /dev/null
+++ b/backend/node_modules/base64-js/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Jameson Little
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/backend/node_modules/base64-js/README.md b/backend/node_modules/base64-js/README.md
new file mode 100644
index 0000000..b42a48f
--- /dev/null
+++ b/backend/node_modules/base64-js/README.md
@@ -0,0 +1,34 @@
+base64-js
+=========
+
+`base64-js` does basic base64 encoding/decoding in pure JS.
+
+[](http://travis-ci.org/beatgammit/base64-js)
+
+Many browsers already have base64 encoding/decoding functionality, but it is for text data, not all-purpose binary data.
+
+Sometimes encoding/decoding binary data in the browser is useful, and that is what this module does.
+
+## install
+
+With [npm](https://npmjs.org) do:
+
+`npm install base64-js` and `var base64js = require('base64-js')`
+
+For use in web browsers do:
+
+``
+
+[Get supported base64-js with the Tidelift Subscription](https://tidelift.com/subscription/pkg/npm-base64-js?utm_source=npm-base64-js&utm_medium=referral&utm_campaign=readme)
+
+## methods
+
+`base64js` has three exposed functions, `byteLength`, `toByteArray` and `fromByteArray`, which both take a single argument.
+
+* `byteLength` - Takes a base64 string and returns length of byte array
+* `toByteArray` - Takes a base64 string and returns a byte array
+* `fromByteArray` - Takes a byte array and returns a base64 string
+
+## license
+
+MIT
diff --git a/backend/node_modules/base64-js/base64js.min.js b/backend/node_modules/base64-js/base64js.min.js
new file mode 100644
index 0000000..908ac83
--- /dev/null
+++ b/backend/node_modules/base64-js/base64js.min.js
@@ -0,0 +1 @@
+(function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"==typeof window?"undefined"==typeof global?"undefined"==typeof self?this:self:global:window,b.base64js=a()}})(function(){return function(){function b(d,e,g){function a(j,i){if(!e[j]){if(!d[j]){var f="function"==typeof require&&require;if(!i&&f)return f(j,!0);if(h)return h(j,!0);var c=new Error("Cannot find module '"+j+"'");throw c.code="MODULE_NOT_FOUND",c}var k=e[j]={exports:{}};d[j][0].call(k.exports,function(b){var c=d[j][1][b];return a(c||b)},k,k.exports,b,d,e,g)}return e[j].exports}for(var h="function"==typeof require&&require,c=0;c>16,j[k++]=255&b>>8,j[k++]=255&b;return 2===h&&(b=l[a.charCodeAt(c)]<<2|l[a.charCodeAt(c+1)]>>4,j[k++]=255&b),1===h&&(b=l[a.charCodeAt(c)]<<10|l[a.charCodeAt(c+1)]<<4|l[a.charCodeAt(c+2)]>>2,j[k++]=255&b>>8,j[k++]=255&b),j}function g(a){return k[63&a>>18]+k[63&a>>12]+k[63&a>>6]+k[63&a]}function h(a,b,c){for(var d,e=[],f=b;fj?j:g+f));return 1===d?(b=a[c-1],e.push(k[b>>2]+k[63&b<<4]+"==")):2===d&&(b=(a[c-2]<<8)+a[c-1],e.push(k[b>>10]+k[63&b>>4]+k[63&b<<2]+"=")),e.join("")}c.byteLength=function(a){var b=d(a),c=b[0],e=b[1];return 3*(c+e)/4-e},c.toByteArray=f,c.fromByteArray=j;for(var k=[],l=[],m="undefined"==typeof Uint8Array?Array:Uint8Array,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",o=0,p=n.length;o 0) {
+ throw new Error('Invalid string. Length must be a multiple of 4')
+ }
+
+ // Trim off extra bytes after placeholder bytes are found
+ // See: https://github.com/beatgammit/base64-js/issues/42
+ var validLen = b64.indexOf('=')
+ if (validLen === -1) validLen = len
+
+ var placeHoldersLen = validLen === len
+ ? 0
+ : 4 - (validLen % 4)
+
+ return [validLen, placeHoldersLen]
+}
+
+// base64 is 4/3 + up to two characters of the original data
+function byteLength (b64) {
+ var lens = getLens(b64)
+ var validLen = lens[0]
+ var placeHoldersLen = lens[1]
+ return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
+}
+
+function _byteLength (b64, validLen, placeHoldersLen) {
+ return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
+}
+
+function toByteArray (b64) {
+ var tmp
+ var lens = getLens(b64)
+ var validLen = lens[0]
+ var placeHoldersLen = lens[1]
+
+ var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))
+
+ var curByte = 0
+
+ // if there are placeholders, only get up to the last complete 4 chars
+ var len = placeHoldersLen > 0
+ ? validLen - 4
+ : validLen
+
+ var i
+ for (i = 0; i < len; i += 4) {
+ tmp =
+ (revLookup[b64.charCodeAt(i)] << 18) |
+ (revLookup[b64.charCodeAt(i + 1)] << 12) |
+ (revLookup[b64.charCodeAt(i + 2)] << 6) |
+ revLookup[b64.charCodeAt(i + 3)]
+ arr[curByte++] = (tmp >> 16) & 0xFF
+ arr[curByte++] = (tmp >> 8) & 0xFF
+ arr[curByte++] = tmp & 0xFF
+ }
+
+ if (placeHoldersLen === 2) {
+ tmp =
+ (revLookup[b64.charCodeAt(i)] << 2) |
+ (revLookup[b64.charCodeAt(i + 1)] >> 4)
+ arr[curByte++] = tmp & 0xFF
+ }
+
+ if (placeHoldersLen === 1) {
+ tmp =
+ (revLookup[b64.charCodeAt(i)] << 10) |
+ (revLookup[b64.charCodeAt(i + 1)] << 4) |
+ (revLookup[b64.charCodeAt(i + 2)] >> 2)
+ arr[curByte++] = (tmp >> 8) & 0xFF
+ arr[curByte++] = tmp & 0xFF
+ }
+
+ return arr
+}
+
+function tripletToBase64 (num) {
+ return lookup[num >> 18 & 0x3F] +
+ lookup[num >> 12 & 0x3F] +
+ lookup[num >> 6 & 0x3F] +
+ lookup[num & 0x3F]
+}
+
+function encodeChunk (uint8, start, end) {
+ var tmp
+ var output = []
+ for (var i = start; i < end; i += 3) {
+ tmp =
+ ((uint8[i] << 16) & 0xFF0000) +
+ ((uint8[i + 1] << 8) & 0xFF00) +
+ (uint8[i + 2] & 0xFF)
+ output.push(tripletToBase64(tmp))
+ }
+ return output.join('')
+}
+
+function fromByteArray (uint8) {
+ var tmp
+ var len = uint8.length
+ var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
+ var parts = []
+ var maxChunkLength = 16383 // must be multiple of 3
+
+ // go through the array every three bytes, we'll deal with trailing stuff later
+ for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
+ parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
+ }
+
+ // pad the end with zeros, but make sure to not forget the extra bytes
+ if (extraBytes === 1) {
+ tmp = uint8[len - 1]
+ parts.push(
+ lookup[tmp >> 2] +
+ lookup[(tmp << 4) & 0x3F] +
+ '=='
+ )
+ } else if (extraBytes === 2) {
+ tmp = (uint8[len - 2] << 8) + uint8[len - 1]
+ parts.push(
+ lookup[tmp >> 10] +
+ lookup[(tmp >> 4) & 0x3F] +
+ lookup[(tmp << 2) & 0x3F] +
+ '='
+ )
+ }
+
+ return parts.join('')
+}
diff --git a/backend/node_modules/base64-js/package.json b/backend/node_modules/base64-js/package.json
new file mode 100644
index 0000000..c3972e3
--- /dev/null
+++ b/backend/node_modules/base64-js/package.json
@@ -0,0 +1,47 @@
+{
+ "name": "base64-js",
+ "description": "Base64 encoding/decoding in pure JS",
+ "version": "1.5.1",
+ "author": "T. Jameson Little ",
+ "typings": "index.d.ts",
+ "bugs": {
+ "url": "https://github.com/beatgammit/base64-js/issues"
+ },
+ "devDependencies": {
+ "babel-minify": "^0.5.1",
+ "benchmark": "^2.1.4",
+ "browserify": "^16.3.0",
+ "standard": "*",
+ "tape": "4.x"
+ },
+ "homepage": "https://github.com/beatgammit/base64-js",
+ "keywords": [
+ "base64"
+ ],
+ "license": "MIT",
+ "main": "index.js",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/beatgammit/base64-js.git"
+ },
+ "scripts": {
+ "build": "browserify -s base64js -r ./ | minify > base64js.min.js",
+ "lint": "standard",
+ "test": "npm run lint && npm run unit",
+ "unit": "tape test/*.js"
+ },
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+}
diff --git a/backend/node_modules/buffer/AUTHORS.md b/backend/node_modules/buffer/AUTHORS.md
new file mode 100644
index 0000000..468aa19
--- /dev/null
+++ b/backend/node_modules/buffer/AUTHORS.md
@@ -0,0 +1,73 @@
+# Authors
+
+#### Ordered by first contribution.
+
+- Romain Beauxis (toots@rastageeks.org)
+- Tobias Koppers (tobias.koppers@googlemail.com)
+- Janus (ysangkok@gmail.com)
+- Rainer Dreyer (rdrey1@gmail.com)
+- Tõnis Tiigi (tonistiigi@gmail.com)
+- James Halliday (mail@substack.net)
+- Michael Williamson (mike@zwobble.org)
+- elliottcable (github@elliottcable.name)
+- rafael (rvalle@livelens.net)
+- Andrew Kelley (superjoe30@gmail.com)
+- Andreas Madsen (amwebdk@gmail.com)
+- Mike Brevoort (mike.brevoort@pearson.com)
+- Brian White (mscdex@mscdex.net)
+- Feross Aboukhadijeh (feross@feross.org)
+- Ruben Verborgh (ruben@verborgh.org)
+- eliang (eliang.cs@gmail.com)
+- Jesse Tane (jesse.tane@gmail.com)
+- Alfonso Boza (alfonso@cloud.com)
+- Mathias Buus (mathiasbuus@gmail.com)
+- Devon Govett (devongovett@gmail.com)
+- Daniel Cousens (github@dcousens.com)
+- Joseph Dykstra (josephdykstra@gmail.com)
+- Parsha Pourkhomami (parshap+git@gmail.com)
+- Damjan Košir (damjan.kosir@gmail.com)
+- daverayment (dave.rayment@gmail.com)
+- kawanet (u-suke@kawa.net)
+- Linus Unnebäck (linus@folkdatorn.se)
+- Nolan Lawson (nolan.lawson@gmail.com)
+- Calvin Metcalf (calvin.metcalf@gmail.com)
+- Koki Takahashi (hakatasiloving@gmail.com)
+- Guy Bedford (guybedford@gmail.com)
+- Jan Schär (jscissr@gmail.com)
+- RaulTsc (tomescu.raul@gmail.com)
+- Matthieu Monsch (monsch@alum.mit.edu)
+- Dan Ehrenberg (littledan@chromium.org)
+- Kirill Fomichev (fanatid@ya.ru)
+- Yusuke Kawasaki (u-suke@kawa.net)
+- DC (dcposch@dcpos.ch)
+- John-David Dalton (john.david.dalton@gmail.com)
+- adventure-yunfei (adventure030@gmail.com)
+- Emil Bay (github@tixz.dk)
+- Sam Sudar (sudar.sam@gmail.com)
+- Volker Mische (volker.mische@gmail.com)
+- David Walton (support@geekstocks.com)
+- Сковорода Никита Андреевич (chalkerx@gmail.com)
+- greenkeeper[bot] (greenkeeper[bot]@users.noreply.github.com)
+- ukstv (sergey.ukustov@machinomy.com)
+- Renée Kooi (renee@kooi.me)
+- ranbochen (ranbochen@qq.com)
+- Vladimir Borovik (bobahbdb@gmail.com)
+- greenkeeper[bot] (23040076+greenkeeper[bot]@users.noreply.github.com)
+- kumavis (aaron@kumavis.me)
+- Sergey Ukustov (sergey.ukustov@machinomy.com)
+- Fei Liu (liu.feiwood@gmail.com)
+- Blaine Bublitz (blaine.bublitz@gmail.com)
+- clement (clement@seald.io)
+- Koushik Dutta (koushd@gmail.com)
+- Jordan Harband (ljharb@gmail.com)
+- Niklas Mischkulnig (mischnic@users.noreply.github.com)
+- Nikolai Vavilov (vvnicholas@gmail.com)
+- Fedor Nezhivoi (gyzerok@users.noreply.github.com)
+- shuse2 (shus.toda@gmail.com)
+- Peter Newman (peternewman@users.noreply.github.com)
+- mathmakgakpak (44949126+mathmakgakpak@users.noreply.github.com)
+- jkkang (jkkang@smartauth.kr)
+- Deklan Webster (deklanw@gmail.com)
+- Martin Heidegger (martin.heidegger@gmail.com)
+
+#### Generated by bin/update-authors.sh.
diff --git a/backend/node_modules/buffer/LICENSE b/backend/node_modules/buffer/LICENSE
new file mode 100644
index 0000000..d6bf75d
--- /dev/null
+++ b/backend/node_modules/buffer/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Feross Aboukhadijeh, and other contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/backend/node_modules/buffer/README.md b/backend/node_modules/buffer/README.md
new file mode 100644
index 0000000..451e235
--- /dev/null
+++ b/backend/node_modules/buffer/README.md
@@ -0,0 +1,410 @@
+# buffer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url]
+
+[travis-image]: https://img.shields.io/travis/feross/buffer/master.svg
+[travis-url]: https://travis-ci.org/feross/buffer
+[npm-image]: https://img.shields.io/npm/v/buffer.svg
+[npm-url]: https://npmjs.org/package/buffer
+[downloads-image]: https://img.shields.io/npm/dm/buffer.svg
+[downloads-url]: https://npmjs.org/package/buffer
+[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg
+[standard-url]: https://standardjs.com
+
+#### The buffer module from [node.js](https://nodejs.org/), for the browser.
+
+[![saucelabs][saucelabs-image]][saucelabs-url]
+
+[saucelabs-image]: https://saucelabs.com/browser-matrix/buffer.svg
+[saucelabs-url]: https://saucelabs.com/u/buffer
+
+With [browserify](http://browserify.org), simply `require('buffer')` or use the `Buffer` global and you will get this module.
+
+The goal is to provide an API that is 100% identical to
+[node's Buffer API](https://nodejs.org/api/buffer.html). Read the
+[official docs](https://nodejs.org/api/buffer.html) for the full list of properties,
+instance methods, and class methods that are supported.
+
+## features
+
+- Manipulate binary data like a boss, in all browsers!
+- Super fast. Backed by Typed Arrays (`Uint8Array`/`ArrayBuffer`, not `Object`)
+- Extremely small bundle size (**6.75KB minified + gzipped**, 51.9KB with comments)
+- Excellent browser support (Chrome, Firefox, Edge, Safari 11+, iOS 11+, Android, etc.)
+- Preserves Node API exactly, with one minor difference (see below)
+- Square-bracket `buf[4]` notation works!
+- Does not modify any browser prototypes or put anything on `window`
+- Comprehensive test suite (including all buffer tests from node.js core)
+
+## install
+
+To use this module directly (without browserify), install it:
+
+```bash
+npm install buffer
+```
+
+This module was previously called **native-buffer-browserify**, but please use **buffer**
+from now on.
+
+If you do not use a bundler, you can use the [standalone script](https://bundle.run/buffer).
+
+## usage
+
+The module's API is identical to node's `Buffer` API. Read the
+[official docs](https://nodejs.org/api/buffer.html) for the full list of properties,
+instance methods, and class methods that are supported.
+
+As mentioned above, `require('buffer')` or use the `Buffer` global with
+[browserify](http://browserify.org) and this module will automatically be included
+in your bundle. Almost any npm module will work in the browser, even if it assumes that
+the node `Buffer` API will be available.
+
+To depend on this module explicitly (without browserify), require it like this:
+
+```js
+var Buffer = require('buffer/').Buffer // note: the trailing slash is important!
+```
+
+To require this module explicitly, use `require('buffer/')` which tells the node.js module
+lookup algorithm (also used by browserify) to use the **npm module** named `buffer`
+instead of the **node.js core** module named `buffer`!
+
+
+## how does it work?
+
+The Buffer constructor returns instances of `Uint8Array` that have their prototype
+changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of `Uint8Array`,
+so the returned instances will have all the node `Buffer` methods and the
+`Uint8Array` methods. Square bracket notation works as expected -- it returns a
+single octet.
+
+The `Uint8Array` prototype remains unmodified.
+
+
+## tracking the latest node api
+
+This module tracks the Buffer API in the latest (unstable) version of node.js. The Buffer
+API is considered **stable** in the
+[node stability index](https://nodejs.org/docs/latest/api/documentation.html#documentation_stability_index),
+so it is unlikely that there will ever be breaking changes.
+Nonetheless, when/if the Buffer API changes in node, this module's API will change
+accordingly.
+
+## related packages
+
+- [`buffer-reverse`](https://www.npmjs.com/package/buffer-reverse) - Reverse a buffer
+- [`buffer-xor`](https://www.npmjs.com/package/buffer-xor) - Bitwise xor a buffer
+- [`is-buffer`](https://www.npmjs.com/package/is-buffer) - Determine if an object is a Buffer without including the whole `Buffer` package
+
+## conversion packages
+
+### convert typed array to buffer
+
+Use [`typedarray-to-buffer`](https://www.npmjs.com/package/typedarray-to-buffer) to convert any kind of typed array to a `Buffer`. Does not perform a copy, so it's super fast.
+
+### convert buffer to typed array
+
+`Buffer` is a subclass of `Uint8Array` (which is a typed array). So there is no need to explicitly convert to typed array. Just use the buffer as a `Uint8Array`.
+
+### convert blob to buffer
+
+Use [`blob-to-buffer`](https://www.npmjs.com/package/blob-to-buffer) to convert a `Blob` to a `Buffer`.
+
+### convert buffer to blob
+
+To convert a `Buffer` to a `Blob`, use the `Blob` constructor:
+
+```js
+var blob = new Blob([ buffer ])
+```
+
+Optionally, specify a mimetype:
+
+```js
+var blob = new Blob([ buffer ], { type: 'text/html' })
+```
+
+### convert arraybuffer to buffer
+
+To convert an `ArrayBuffer` to a `Buffer`, use the `Buffer.from` function. Does not perform a copy, so it's super fast.
+
+```js
+var buffer = Buffer.from(arrayBuffer)
+```
+
+### convert buffer to arraybuffer
+
+To convert a `Buffer` to an `ArrayBuffer`, use the `.buffer` property (which is present on all `Uint8Array` objects):
+
+```js
+var arrayBuffer = buffer.buffer.slice(
+ buffer.byteOffset, buffer.byteOffset + buffer.byteLength
+)
+```
+
+Alternatively, use the [`to-arraybuffer`](https://www.npmjs.com/package/to-arraybuffer) module.
+
+## performance
+
+See perf tests in `/perf`.
+
+`BrowserBuffer` is the browser `buffer` module (this repo). `Uint8Array` is included as a
+sanity check (since `BrowserBuffer` uses `Uint8Array` under the hood, `Uint8Array` will
+always be at least a bit faster). Finally, `NodeBuffer` is the node.js buffer module,
+which is included to compare against.
+
+NOTE: Performance has improved since these benchmarks were taken. PR welcome to update the README.
+
+### Chrome 38
+
+| Method | Operations | Accuracy | Sampled | Fastest |
+|:-------|:-----------|:---------|:--------|:-------:|
+| BrowserBuffer#bracket-notation | 11,457,464 ops/sec | ±0.86% | 66 | ✓ |
+| Uint8Array#bracket-notation | 10,824,332 ops/sec | ±0.74% | 65 | |
+| | | | |
+| BrowserBuffer#concat | 450,532 ops/sec | ±0.76% | 68 | |
+| Uint8Array#concat | 1,368,911 ops/sec | ±1.50% | 62 | ✓ |
+| | | | |
+| BrowserBuffer#copy(16000) | 903,001 ops/sec | ±0.96% | 67 | |
+| Uint8Array#copy(16000) | 1,422,441 ops/sec | ±1.04% | 66 | ✓ |
+| | | | |
+| BrowserBuffer#copy(16) | 11,431,358 ops/sec | ±0.46% | 69 | |
+| Uint8Array#copy(16) | 13,944,163 ops/sec | ±1.12% | 68 | ✓ |
+| | | | |
+| BrowserBuffer#new(16000) | 106,329 ops/sec | ±6.70% | 44 | |
+| Uint8Array#new(16000) | 131,001 ops/sec | ±2.85% | 31 | ✓ |
+| | | | |
+| BrowserBuffer#new(16) | 1,554,491 ops/sec | ±1.60% | 65 | |
+| Uint8Array#new(16) | 6,623,930 ops/sec | ±1.66% | 65 | ✓ |
+| | | | |
+| BrowserBuffer#readDoubleBE | 112,830 ops/sec | ±0.51% | 69 | ✓ |
+| DataView#getFloat64 | 93,500 ops/sec | ±0.57% | 68 | |
+| | | | |
+| BrowserBuffer#readFloatBE | 146,678 ops/sec | ±0.95% | 68 | ✓ |
+| DataView#getFloat32 | 99,311 ops/sec | ±0.41% | 67 | |
+| | | | |
+| BrowserBuffer#readUInt32LE | 843,214 ops/sec | ±0.70% | 69 | ✓ |
+| DataView#getUint32 | 103,024 ops/sec | ±0.64% | 67 | |
+| | | | |
+| BrowserBuffer#slice | 1,013,941 ops/sec | ±0.75% | 67 | |
+| Uint8Array#subarray | 1,903,928 ops/sec | ±0.53% | 67 | ✓ |
+| | | | |
+| BrowserBuffer#writeFloatBE | 61,387 ops/sec | ±0.90% | 67 | |
+| DataView#setFloat32 | 141,249 ops/sec | ±0.40% | 66 | ✓ |
+
+
+### Firefox 33
+
+| Method | Operations | Accuracy | Sampled | Fastest |
+|:-------|:-----------|:---------|:--------|:-------:|
+| BrowserBuffer#bracket-notation | 20,800,421 ops/sec | ±1.84% | 60 | |
+| Uint8Array#bracket-notation | 20,826,235 ops/sec | ±2.02% | 61 | ✓ |
+| | | | |
+| BrowserBuffer#concat | 153,076 ops/sec | ±2.32% | 61 | |
+| Uint8Array#concat | 1,255,674 ops/sec | ±8.65% | 52 | ✓ |
+| | | | |
+| BrowserBuffer#copy(16000) | 1,105,312 ops/sec | ±1.16% | 63 | |
+| Uint8Array#copy(16000) | 1,615,911 ops/sec | ±0.55% | 66 | ✓ |
+| | | | |
+| BrowserBuffer#copy(16) | 16,357,599 ops/sec | ±0.73% | 68 | |
+| Uint8Array#copy(16) | 31,436,281 ops/sec | ±1.05% | 68 | ✓ |
+| | | | |
+| BrowserBuffer#new(16000) | 52,995 ops/sec | ±6.01% | 35 | |
+| Uint8Array#new(16000) | 87,686 ops/sec | ±5.68% | 45 | ✓ |
+| | | | |
+| BrowserBuffer#new(16) | 252,031 ops/sec | ±1.61% | 66 | |
+| Uint8Array#new(16) | 8,477,026 ops/sec | ±0.49% | 68 | ✓ |
+| | | | |
+| BrowserBuffer#readDoubleBE | 99,871 ops/sec | ±0.41% | 69 | |
+| DataView#getFloat64 | 285,663 ops/sec | ±0.70% | 68 | ✓ |
+| | | | |
+| BrowserBuffer#readFloatBE | 115,540 ops/sec | ±0.42% | 69 | |
+| DataView#getFloat32 | 288,722 ops/sec | ±0.82% | 68 | ✓ |
+| | | | |
+| BrowserBuffer#readUInt32LE | 633,926 ops/sec | ±1.08% | 67 | ✓ |
+| DataView#getUint32 | 294,808 ops/sec | ±0.79% | 64 | |
+| | | | |
+| BrowserBuffer#slice | 349,425 ops/sec | ±0.46% | 69 | |
+| Uint8Array#subarray | 5,965,819 ops/sec | ±0.60% | 65 | ✓ |
+| | | | |
+| BrowserBuffer#writeFloatBE | 59,980 ops/sec | ±0.41% | 67 | |
+| DataView#setFloat32 | 317,634 ops/sec | ±0.63% | 68 | ✓ |
+
+### Safari 8
+
+| Method | Operations | Accuracy | Sampled | Fastest |
+|:-------|:-----------|:---------|:--------|:-------:|
+| BrowserBuffer#bracket-notation | 10,279,729 ops/sec | ±2.25% | 56 | ✓ |
+| Uint8Array#bracket-notation | 10,030,767 ops/sec | ±2.23% | 59 | |
+| | | | |
+| BrowserBuffer#concat | 144,138 ops/sec | ±1.38% | 65 | |
+| Uint8Array#concat | 4,950,764 ops/sec | ±1.70% | 63 | ✓ |
+| | | | |
+| BrowserBuffer#copy(16000) | 1,058,548 ops/sec | ±1.51% | 64 | |
+| Uint8Array#copy(16000) | 1,409,666 ops/sec | ±1.17% | 65 | ✓ |
+| | | | |
+| BrowserBuffer#copy(16) | 6,282,529 ops/sec | ±1.88% | 58 | |
+| Uint8Array#copy(16) | 11,907,128 ops/sec | ±2.87% | 58 | ✓ |
+| | | | |
+| BrowserBuffer#new(16000) | 101,663 ops/sec | ±3.89% | 57 | |
+| Uint8Array#new(16000) | 22,050,818 ops/sec | ±6.51% | 46 | ✓ |
+| | | | |
+| BrowserBuffer#new(16) | 176,072 ops/sec | ±2.13% | 64 | |
+| Uint8Array#new(16) | 24,385,731 ops/sec | ±5.01% | 51 | ✓ |
+| | | | |
+| BrowserBuffer#readDoubleBE | 41,341 ops/sec | ±1.06% | 67 | |
+| DataView#getFloat64 | 322,280 ops/sec | ±0.84% | 68 | ✓ |
+| | | | |
+| BrowserBuffer#readFloatBE | 46,141 ops/sec | ±1.06% | 65 | |
+| DataView#getFloat32 | 337,025 ops/sec | ±0.43% | 69 | ✓ |
+| | | | |
+| BrowserBuffer#readUInt32LE | 151,551 ops/sec | ±1.02% | 66 | |
+| DataView#getUint32 | 308,278 ops/sec | ±0.94% | 67 | ✓ |
+| | | | |
+| BrowserBuffer#slice | 197,365 ops/sec | ±0.95% | 66 | |
+| Uint8Array#subarray | 9,558,024 ops/sec | ±3.08% | 58 | ✓ |
+| | | | |
+| BrowserBuffer#writeFloatBE | 17,518 ops/sec | ±1.03% | 63 | |
+| DataView#setFloat32 | 319,751 ops/sec | ±0.48% | 68 | ✓ |
+
+
+### Node 0.11.14
+
+| Method | Operations | Accuracy | Sampled | Fastest |
+|:-------|:-----------|:---------|:--------|:-------:|
+| BrowserBuffer#bracket-notation | 10,489,828 ops/sec | ±3.25% | 90 | |
+| Uint8Array#bracket-notation | 10,534,884 ops/sec | ±0.81% | 92 | ✓ |
+| NodeBuffer#bracket-notation | 10,389,910 ops/sec | ±0.97% | 87 | |
+| | | | |
+| BrowserBuffer#concat | 487,830 ops/sec | ±2.58% | 88 | |
+| Uint8Array#concat | 1,814,327 ops/sec | ±1.28% | 88 | ✓ |
+| NodeBuffer#concat | 1,636,523 ops/sec | ±1.88% | 73 | |
+| | | | |
+| BrowserBuffer#copy(16000) | 1,073,665 ops/sec | ±0.77% | 90 | |
+| Uint8Array#copy(16000) | 1,348,517 ops/sec | ±0.84% | 89 | ✓ |
+| NodeBuffer#copy(16000) | 1,289,533 ops/sec | ±0.82% | 93 | |
+| | | | |
+| BrowserBuffer#copy(16) | 12,782,706 ops/sec | ±0.74% | 85 | |
+| Uint8Array#copy(16) | 14,180,427 ops/sec | ±0.93% | 92 | ✓ |
+| NodeBuffer#copy(16) | 11,083,134 ops/sec | ±1.06% | 89 | |
+| | | | |
+| BrowserBuffer#new(16000) | 141,678 ops/sec | ±3.30% | 67 | |
+| Uint8Array#new(16000) | 161,491 ops/sec | ±2.96% | 60 | |
+| NodeBuffer#new(16000) | 292,699 ops/sec | ±3.20% | 55 | ✓ |
+| | | | |
+| BrowserBuffer#new(16) | 1,655,466 ops/sec | ±2.41% | 82 | |
+| Uint8Array#new(16) | 14,399,926 ops/sec | ±0.91% | 94 | ✓ |
+| NodeBuffer#new(16) | 3,894,696 ops/sec | ±0.88% | 92 | |
+| | | | |
+| BrowserBuffer#readDoubleBE | 109,582 ops/sec | ±0.75% | 93 | ✓ |
+| DataView#getFloat64 | 91,235 ops/sec | ±0.81% | 90 | |
+| NodeBuffer#readDoubleBE | 88,593 ops/sec | ±0.96% | 81 | |
+| | | | |
+| BrowserBuffer#readFloatBE | 139,854 ops/sec | ±1.03% | 85 | ✓ |
+| DataView#getFloat32 | 98,744 ops/sec | ±0.80% | 89 | |
+| NodeBuffer#readFloatBE | 92,769 ops/sec | ±0.94% | 93 | |
+| | | | |
+| BrowserBuffer#readUInt32LE | 710,861 ops/sec | ±0.82% | 92 | |
+| DataView#getUint32 | 117,893 ops/sec | ±0.84% | 91 | |
+| NodeBuffer#readUInt32LE | 851,412 ops/sec | ±0.72% | 93 | ✓ |
+| | | | |
+| BrowserBuffer#slice | 1,673,877 ops/sec | ±0.73% | 94 | |
+| Uint8Array#subarray | 6,919,243 ops/sec | ±0.67% | 90 | ✓ |
+| NodeBuffer#slice | 4,617,604 ops/sec | ±0.79% | 93 | |
+| | | | |
+| BrowserBuffer#writeFloatBE | 66,011 ops/sec | ±0.75% | 93 | |
+| DataView#setFloat32 | 127,760 ops/sec | ±0.72% | 93 | ✓ |
+| NodeBuffer#writeFloatBE | 103,352 ops/sec | ±0.83% | 93 | |
+
+### iojs 1.8.1
+
+| Method | Operations | Accuracy | Sampled | Fastest |
+|:-------|:-----------|:---------|:--------|:-------:|
+| BrowserBuffer#bracket-notation | 10,990,488 ops/sec | ±1.11% | 91 | |
+| Uint8Array#bracket-notation | 11,268,757 ops/sec | ±0.65% | 97 | |
+| NodeBuffer#bracket-notation | 11,353,260 ops/sec | ±0.83% | 94 | ✓ |
+| | | | |
+| BrowserBuffer#concat | 378,954 ops/sec | ±0.74% | 94 | |
+| Uint8Array#concat | 1,358,288 ops/sec | ±0.97% | 87 | |
+| NodeBuffer#concat | 1,934,050 ops/sec | ±1.11% | 78 | ✓ |
+| | | | |
+| BrowserBuffer#copy(16000) | 894,538 ops/sec | ±0.56% | 84 | |
+| Uint8Array#copy(16000) | 1,442,656 ops/sec | ±0.71% | 96 | |
+| NodeBuffer#copy(16000) | 1,457,898 ops/sec | ±0.53% | 92 | ✓ |
+| | | | |
+| BrowserBuffer#copy(16) | 12,870,457 ops/sec | ±0.67% | 95 | |
+| Uint8Array#copy(16) | 16,643,989 ops/sec | ±0.61% | 93 | ✓ |
+| NodeBuffer#copy(16) | 14,885,848 ops/sec | ±0.74% | 94 | |
+| | | | |
+| BrowserBuffer#new(16000) | 109,264 ops/sec | ±4.21% | 63 | |
+| Uint8Array#new(16000) | 138,916 ops/sec | ±1.87% | 61 | |
+| NodeBuffer#new(16000) | 281,449 ops/sec | ±3.58% | 51 | ✓ |
+| | | | |
+| BrowserBuffer#new(16) | 1,362,935 ops/sec | ±0.56% | 99 | |
+| Uint8Array#new(16) | 6,193,090 ops/sec | ±0.64% | 95 | ✓ |
+| NodeBuffer#new(16) | 4,745,425 ops/sec | ±1.56% | 90 | |
+| | | | |
+| BrowserBuffer#readDoubleBE | 118,127 ops/sec | ±0.59% | 93 | ✓ |
+| DataView#getFloat64 | 107,332 ops/sec | ±0.65% | 91 | |
+| NodeBuffer#readDoubleBE | 116,274 ops/sec | ±0.94% | 95 | |
+| | | | |
+| BrowserBuffer#readFloatBE | 150,326 ops/sec | ±0.58% | 95 | ✓ |
+| DataView#getFloat32 | 110,541 ops/sec | ±0.57% | 98 | |
+| NodeBuffer#readFloatBE | 121,599 ops/sec | ±0.60% | 87 | |
+| | | | |
+| BrowserBuffer#readUInt32LE | 814,147 ops/sec | ±0.62% | 93 | |
+| DataView#getUint32 | 137,592 ops/sec | ±0.64% | 90 | |
+| NodeBuffer#readUInt32LE | 931,650 ops/sec | ±0.71% | 96 | ✓ |
+| | | | |
+| BrowserBuffer#slice | 878,590 ops/sec | ±0.68% | 93 | |
+| Uint8Array#subarray | 2,843,308 ops/sec | ±1.02% | 90 | |
+| NodeBuffer#slice | 4,998,316 ops/sec | ±0.68% | 90 | ✓ |
+| | | | |
+| BrowserBuffer#writeFloatBE | 65,927 ops/sec | ±0.74% | 93 | |
+| DataView#setFloat32 | 139,823 ops/sec | ±0.97% | 89 | ✓ |
+| NodeBuffer#writeFloatBE | 135,763 ops/sec | ±0.65% | 96 | |
+| | | | |
+
+## Testing the project
+
+First, install the project:
+
+ npm install
+
+Then, to run tests in Node.js, run:
+
+ npm run test-node
+
+To test locally in a browser, you can run:
+
+ npm run test-browser-es5-local # For ES5 browsers that don't support ES6
+ npm run test-browser-es6-local # For ES6 compliant browsers
+
+This will print out a URL that you can then open in a browser to run the tests, using [airtap](https://www.npmjs.com/package/airtap).
+
+To run automated browser tests using Saucelabs, ensure that your `SAUCE_USERNAME` and `SAUCE_ACCESS_KEY` environment variables are set, then run:
+
+ npm test
+
+This is what's run in Travis, to check against various browsers. The list of browsers is kept in the `bin/airtap-es5.yml` and `bin/airtap-es6.yml` files.
+
+## JavaScript Standard Style
+
+This module uses [JavaScript Standard Style](https://github.com/feross/standard).
+
+[](https://github.com/feross/standard)
+
+To test that the code conforms to the style, `npm install` and run:
+
+ ./node_modules/.bin/standard
+
+## credit
+
+This was originally forked from [buffer-browserify](https://github.com/toots/buffer-browserify).
+
+## Security Policies and Procedures
+
+The `buffer` team and community take all security bugs in `buffer` seriously. Please see our [security policies and procedures](https://github.com/feross/security) document to learn how to report issues.
+
+## license
+
+MIT. Copyright (C) [Feross Aboukhadijeh](http://feross.org), and other contributors. Originally forked from an MIT-licensed module by Romain Beauxis.
diff --git a/backend/node_modules/buffer/index.d.ts b/backend/node_modules/buffer/index.d.ts
new file mode 100644
index 0000000..07096a2
--- /dev/null
+++ b/backend/node_modules/buffer/index.d.ts
@@ -0,0 +1,194 @@
+export class Buffer extends Uint8Array {
+ length: number
+ write(string: string, offset?: number, length?: number, encoding?: string): number;
+ toString(encoding?: string, start?: number, end?: number): string;
+ toJSON(): { type: 'Buffer', data: any[] };
+ equals(otherBuffer: Buffer): boolean;
+ compare(otherBuffer: Uint8Array, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number;
+ copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;
+ slice(start?: number, end?: number): Buffer;
+ writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
+ writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
+ writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
+ writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
+ readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number;
+ readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number;
+ readIntLE(offset: number, byteLength: number, noAssert?: boolean): number;
+ readIntBE(offset: number, byteLength: number, noAssert?: boolean): number;
+ readUInt8(offset: number, noAssert?: boolean): number;
+ readUInt16LE(offset: number, noAssert?: boolean): number;
+ readUInt16BE(offset: number, noAssert?: boolean): number;
+ readUInt32LE(offset: number, noAssert?: boolean): number;
+ readUInt32BE(offset: number, noAssert?: boolean): number;
+ readBigUInt64LE(offset: number): BigInt;
+ readBigUInt64BE(offset: number): BigInt;
+ readInt8(offset: number, noAssert?: boolean): number;
+ readInt16LE(offset: number, noAssert?: boolean): number;
+ readInt16BE(offset: number, noAssert?: boolean): number;
+ readInt32LE(offset: number, noAssert?: boolean): number;
+ readInt32BE(offset: number, noAssert?: boolean): number;
+ readBigInt64LE(offset: number): BigInt;
+ readBigInt64BE(offset: number): BigInt;
+ readFloatLE(offset: number, noAssert?: boolean): number;
+ readFloatBE(offset: number, noAssert?: boolean): number;
+ readDoubleLE(offset: number, noAssert?: boolean): number;
+ readDoubleBE(offset: number, noAssert?: boolean): number;
+ reverse(): this;
+ swap16(): Buffer;
+ swap32(): Buffer;
+ swap64(): Buffer;
+ writeUInt8(value: number, offset: number, noAssert?: boolean): number;
+ writeUInt16LE(value: number, offset: number, noAssert?: boolean): number;
+ writeUInt16BE(value: number, offset: number, noAssert?: boolean): number;
+ writeUInt32LE(value: number, offset: number, noAssert?: boolean): number;
+ writeUInt32BE(value: number, offset: number, noAssert?: boolean): number;
+ writeBigUInt64LE(value: number, offset: number): BigInt;
+ writeBigUInt64BE(value: number, offset: number): BigInt;
+ writeInt8(value: number, offset: number, noAssert?: boolean): number;
+ writeInt16LE(value: number, offset: number, noAssert?: boolean): number;
+ writeInt16BE(value: number, offset: number, noAssert?: boolean): number;
+ writeInt32LE(value: number, offset: number, noAssert?: boolean): number;
+ writeInt32BE(value: number, offset: number, noAssert?: boolean): number;
+ writeBigInt64LE(value: number, offset: number): BigInt;
+ writeBigInt64BE(value: number, offset: number): BigInt;
+ writeFloatLE(value: number, offset: number, noAssert?: boolean): number;
+ writeFloatBE(value: number, offset: number, noAssert?: boolean): number;
+ writeDoubleLE(value: number, offset: number, noAssert?: boolean): number;
+ writeDoubleBE(value: number, offset: number, noAssert?: boolean): number;
+ fill(value: any, offset?: number, end?: number): this;
+ indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;
+ lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;
+ includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean;
+
+ /**
+ * Allocates a new buffer containing the given {str}.
+ *
+ * @param str String to store in buffer.
+ * @param encoding encoding to use, optional. Default is 'utf8'
+ */
+ constructor (str: string, encoding?: string);
+ /**
+ * Allocates a new buffer of {size} octets.
+ *
+ * @param size count of octets to allocate.
+ */
+ constructor (size: number);
+ /**
+ * Allocates a new buffer containing the given {array} of octets.
+ *
+ * @param array The octets to store.
+ */
+ constructor (array: Uint8Array);
+ /**
+ * Produces a Buffer backed by the same allocated memory as
+ * the given {ArrayBuffer}.
+ *
+ *
+ * @param arrayBuffer The ArrayBuffer with which to share memory.
+ */
+ constructor (arrayBuffer: ArrayBuffer);
+ /**
+ * Allocates a new buffer containing the given {array} of octets.
+ *
+ * @param array The octets to store.
+ */
+ constructor (array: any[]);
+ /**
+ * Copies the passed {buffer} data onto a new {Buffer} instance.
+ *
+ * @param buffer The buffer to copy.
+ */
+ constructor (buffer: Buffer);
+ prototype: Buffer;
+ /**
+ * Allocates a new Buffer using an {array} of octets.
+ *
+ * @param array
+ */
+ static from(array: any[]): Buffer;
+ /**
+ * When passed a reference to the .buffer property of a TypedArray instance,
+ * the newly created Buffer will share the same allocated memory as the TypedArray.
+ * The optional {byteOffset} and {length} arguments specify a memory range
+ * within the {arrayBuffer} that will be shared by the Buffer.
+ *
+ * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer()
+ * @param byteOffset
+ * @param length
+ */
+ static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer;
+ /**
+ * Copies the passed {buffer} data onto a new Buffer instance.
+ *
+ * @param buffer
+ */
+ static from(buffer: Buffer | Uint8Array): Buffer;
+ /**
+ * Creates a new Buffer containing the given JavaScript string {str}.
+ * If provided, the {encoding} parameter identifies the character encoding.
+ * If not provided, {encoding} defaults to 'utf8'.
+ *
+ * @param str
+ */
+ static from(str: string, encoding?: string): Buffer;
+ /**
+ * Returns true if {obj} is a Buffer
+ *
+ * @param obj object to test.
+ */
+ static isBuffer(obj: any): obj is Buffer;
+ /**
+ * Returns true if {encoding} is a valid encoding argument.
+ * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex'
+ *
+ * @param encoding string to test.
+ */
+ static isEncoding(encoding: string): boolean;
+ /**
+ * Gives the actual byte length of a string. encoding defaults to 'utf8'.
+ * This is not the same as String.prototype.length since that returns the number of characters in a string.
+ *
+ * @param string string to test.
+ * @param encoding encoding used to evaluate (defaults to 'utf8')
+ */
+ static byteLength(string: string, encoding?: string): number;
+ /**
+ * Returns a buffer which is the result of concatenating all the buffers in the list together.
+ *
+ * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer.
+ * If the list has exactly one item, then the first item of the list is returned.
+ * If the list has more than one item, then a new Buffer is created.
+ *
+ * @param list An array of Buffer objects to concatenate
+ * @param totalLength Total length of the buffers when concatenated.
+ * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly.
+ */
+ static concat(list: Uint8Array[], totalLength?: number): Buffer;
+ /**
+ * The same as buf1.compare(buf2).
+ */
+ static compare(buf1: Uint8Array, buf2: Uint8Array): number;
+ /**
+ * Allocates a new buffer of {size} octets.
+ *
+ * @param size count of octets to allocate.
+ * @param fill if specified, buffer will be initialized by calling buf.fill(fill).
+ * If parameter is omitted, buffer will be filled with zeros.
+ * @param encoding encoding used for call to buf.fill while initializing
+ */
+ static alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer;
+ /**
+ * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents
+ * of the newly created Buffer are unknown and may contain sensitive data.
+ *
+ * @param size count of octets to allocate
+ */
+ static allocUnsafe(size: number): Buffer;
+ /**
+ * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents
+ * of the newly created Buffer are unknown and may contain sensitive data.
+ *
+ * @param size count of octets to allocate
+ */
+ static allocUnsafeSlow(size: number): Buffer;
+}
diff --git a/backend/node_modules/buffer/index.js b/backend/node_modules/buffer/index.js
new file mode 100644
index 0000000..7a0e9c2
--- /dev/null
+++ b/backend/node_modules/buffer/index.js
@@ -0,0 +1,2106 @@
+/*!
+ * The buffer module from node.js, for the browser.
+ *
+ * @author Feross Aboukhadijeh
+ * @license MIT
+ */
+/* eslint-disable no-proto */
+
+'use strict'
+
+const base64 = require('base64-js')
+const ieee754 = require('ieee754')
+const customInspectSymbol =
+ (typeof Symbol === 'function' && typeof Symbol['for'] === 'function') // eslint-disable-line dot-notation
+ ? Symbol['for']('nodejs.util.inspect.custom') // eslint-disable-line dot-notation
+ : null
+
+exports.Buffer = Buffer
+exports.SlowBuffer = SlowBuffer
+exports.INSPECT_MAX_BYTES = 50
+
+const K_MAX_LENGTH = 0x7fffffff
+exports.kMaxLength = K_MAX_LENGTH
+
+/**
+ * If `Buffer.TYPED_ARRAY_SUPPORT`:
+ * === true Use Uint8Array implementation (fastest)
+ * === false Print warning and recommend using `buffer` v4.x which has an Object
+ * implementation (most compatible, even IE6)
+ *
+ * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
+ * Opera 11.6+, iOS 4.2+.
+ *
+ * We report that the browser does not support typed arrays if the are not subclassable
+ * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array`
+ * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support
+ * for __proto__ and has a buggy typed array implementation.
+ */
+Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport()
+
+if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' &&
+ typeof console.error === 'function') {
+ console.error(
+ 'This browser lacks typed array (Uint8Array) support which is required by ' +
+ '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.'
+ )
+}
+
+function typedArraySupport () {
+ // Can typed array instances can be augmented?
+ try {
+ const arr = new Uint8Array(1)
+ const proto = { foo: function () { return 42 } }
+ Object.setPrototypeOf(proto, Uint8Array.prototype)
+ Object.setPrototypeOf(arr, proto)
+ return arr.foo() === 42
+ } catch (e) {
+ return false
+ }
+}
+
+Object.defineProperty(Buffer.prototype, 'parent', {
+ enumerable: true,
+ get: function () {
+ if (!Buffer.isBuffer(this)) return undefined
+ return this.buffer
+ }
+})
+
+Object.defineProperty(Buffer.prototype, 'offset', {
+ enumerable: true,
+ get: function () {
+ if (!Buffer.isBuffer(this)) return undefined
+ return this.byteOffset
+ }
+})
+
+function createBuffer (length) {
+ if (length > K_MAX_LENGTH) {
+ throw new RangeError('The value "' + length + '" is invalid for option "size"')
+ }
+ // Return an augmented `Uint8Array` instance
+ const buf = new Uint8Array(length)
+ Object.setPrototypeOf(buf, Buffer.prototype)
+ return buf
+}
+
+/**
+ * The Buffer constructor returns instances of `Uint8Array` that have their
+ * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
+ * `Uint8Array`, so the returned instances will have all the node `Buffer` methods
+ * and the `Uint8Array` methods. Square bracket notation works as expected -- it
+ * returns a single octet.
+ *
+ * The `Uint8Array` prototype remains unmodified.
+ */
+
+function Buffer (arg, encodingOrOffset, length) {
+ // Common case.
+ if (typeof arg === 'number') {
+ if (typeof encodingOrOffset === 'string') {
+ throw new TypeError(
+ 'The "string" argument must be of type string. Received type number'
+ )
+ }
+ return allocUnsafe(arg)
+ }
+ return from(arg, encodingOrOffset, length)
+}
+
+Buffer.poolSize = 8192 // not used by this implementation
+
+function from (value, encodingOrOffset, length) {
+ if (typeof value === 'string') {
+ return fromString(value, encodingOrOffset)
+ }
+
+ if (ArrayBuffer.isView(value)) {
+ return fromArrayView(value)
+ }
+
+ if (value == null) {
+ throw new TypeError(
+ 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' +
+ 'or Array-like Object. Received type ' + (typeof value)
+ )
+ }
+
+ if (isInstance(value, ArrayBuffer) ||
+ (value && isInstance(value.buffer, ArrayBuffer))) {
+ return fromArrayBuffer(value, encodingOrOffset, length)
+ }
+
+ if (typeof SharedArrayBuffer !== 'undefined' &&
+ (isInstance(value, SharedArrayBuffer) ||
+ (value && isInstance(value.buffer, SharedArrayBuffer)))) {
+ return fromArrayBuffer(value, encodingOrOffset, length)
+ }
+
+ if (typeof value === 'number') {
+ throw new TypeError(
+ 'The "value" argument must not be of type number. Received type number'
+ )
+ }
+
+ const valueOf = value.valueOf && value.valueOf()
+ if (valueOf != null && valueOf !== value) {
+ return Buffer.from(valueOf, encodingOrOffset, length)
+ }
+
+ const b = fromObject(value)
+ if (b) return b
+
+ if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null &&
+ typeof value[Symbol.toPrimitive] === 'function') {
+ return Buffer.from(value[Symbol.toPrimitive]('string'), encodingOrOffset, length)
+ }
+
+ throw new TypeError(
+ 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' +
+ 'or Array-like Object. Received type ' + (typeof value)
+ )
+}
+
+/**
+ * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
+ * if value is a number.
+ * Buffer.from(str[, encoding])
+ * Buffer.from(array)
+ * Buffer.from(buffer)
+ * Buffer.from(arrayBuffer[, byteOffset[, length]])
+ **/
+Buffer.from = function (value, encodingOrOffset, length) {
+ return from(value, encodingOrOffset, length)
+}
+
+// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug:
+// https://github.com/feross/buffer/pull/148
+Object.setPrototypeOf(Buffer.prototype, Uint8Array.prototype)
+Object.setPrototypeOf(Buffer, Uint8Array)
+
+function assertSize (size) {
+ if (typeof size !== 'number') {
+ throw new TypeError('"size" argument must be of type number')
+ } else if (size < 0) {
+ throw new RangeError('The value "' + size + '" is invalid for option "size"')
+ }
+}
+
+function alloc (size, fill, encoding) {
+ assertSize(size)
+ if (size <= 0) {
+ return createBuffer(size)
+ }
+ if (fill !== undefined) {
+ // Only pay attention to encoding if it's a string. This
+ // prevents accidentally sending in a number that would
+ // be interpreted as a start offset.
+ return typeof encoding === 'string'
+ ? createBuffer(size).fill(fill, encoding)
+ : createBuffer(size).fill(fill)
+ }
+ return createBuffer(size)
+}
+
+/**
+ * Creates a new filled Buffer instance.
+ * alloc(size[, fill[, encoding]])
+ **/
+Buffer.alloc = function (size, fill, encoding) {
+ return alloc(size, fill, encoding)
+}
+
+function allocUnsafe (size) {
+ assertSize(size)
+ return createBuffer(size < 0 ? 0 : checked(size) | 0)
+}
+
+/**
+ * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
+ * */
+Buffer.allocUnsafe = function (size) {
+ return allocUnsafe(size)
+}
+/**
+ * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
+ */
+Buffer.allocUnsafeSlow = function (size) {
+ return allocUnsafe(size)
+}
+
+function fromString (string, encoding) {
+ if (typeof encoding !== 'string' || encoding === '') {
+ encoding = 'utf8'
+ }
+
+ if (!Buffer.isEncoding(encoding)) {
+ throw new TypeError('Unknown encoding: ' + encoding)
+ }
+
+ const length = byteLength(string, encoding) | 0
+ let buf = createBuffer(length)
+
+ const actual = buf.write(string, encoding)
+
+ if (actual !== length) {
+ // Writing a hex string, for example, that contains invalid characters will
+ // cause everything after the first invalid character to be ignored. (e.g.
+ // 'abxxcd' will be treated as 'ab')
+ buf = buf.slice(0, actual)
+ }
+
+ return buf
+}
+
+function fromArrayLike (array) {
+ const length = array.length < 0 ? 0 : checked(array.length) | 0
+ const buf = createBuffer(length)
+ for (let i = 0; i < length; i += 1) {
+ buf[i] = array[i] & 255
+ }
+ return buf
+}
+
+function fromArrayView (arrayView) {
+ if (isInstance(arrayView, Uint8Array)) {
+ const copy = new Uint8Array(arrayView)
+ return fromArrayBuffer(copy.buffer, copy.byteOffset, copy.byteLength)
+ }
+ return fromArrayLike(arrayView)
+}
+
+function fromArrayBuffer (array, byteOffset, length) {
+ if (byteOffset < 0 || array.byteLength < byteOffset) {
+ throw new RangeError('"offset" is outside of buffer bounds')
+ }
+
+ if (array.byteLength < byteOffset + (length || 0)) {
+ throw new RangeError('"length" is outside of buffer bounds')
+ }
+
+ let buf
+ if (byteOffset === undefined && length === undefined) {
+ buf = new Uint8Array(array)
+ } else if (length === undefined) {
+ buf = new Uint8Array(array, byteOffset)
+ } else {
+ buf = new Uint8Array(array, byteOffset, length)
+ }
+
+ // Return an augmented `Uint8Array` instance
+ Object.setPrototypeOf(buf, Buffer.prototype)
+
+ return buf
+}
+
+function fromObject (obj) {
+ if (Buffer.isBuffer(obj)) {
+ const len = checked(obj.length) | 0
+ const buf = createBuffer(len)
+
+ if (buf.length === 0) {
+ return buf
+ }
+
+ obj.copy(buf, 0, 0, len)
+ return buf
+ }
+
+ if (obj.length !== undefined) {
+ if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) {
+ return createBuffer(0)
+ }
+ return fromArrayLike(obj)
+ }
+
+ if (obj.type === 'Buffer' && Array.isArray(obj.data)) {
+ return fromArrayLike(obj.data)
+ }
+}
+
+function checked (length) {
+ // Note: cannot use `length < K_MAX_LENGTH` here because that fails when
+ // length is NaN (which is otherwise coerced to zero.)
+ if (length >= K_MAX_LENGTH) {
+ throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
+ 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes')
+ }
+ return length | 0
+}
+
+function SlowBuffer (length) {
+ if (+length != length) { // eslint-disable-line eqeqeq
+ length = 0
+ }
+ return Buffer.alloc(+length)
+}
+
+Buffer.isBuffer = function isBuffer (b) {
+ return b != null && b._isBuffer === true &&
+ b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false
+}
+
+Buffer.compare = function compare (a, b) {
+ if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength)
+ if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength)
+ if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
+ throw new TypeError(
+ 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array'
+ )
+ }
+
+ if (a === b) return 0
+
+ let x = a.length
+ let y = b.length
+
+ for (let i = 0, len = Math.min(x, y); i < len; ++i) {
+ if (a[i] !== b[i]) {
+ x = a[i]
+ y = b[i]
+ break
+ }
+ }
+
+ if (x < y) return -1
+ if (y < x) return 1
+ return 0
+}
+
+Buffer.isEncoding = function isEncoding (encoding) {
+ switch (String(encoding).toLowerCase()) {
+ case 'hex':
+ case 'utf8':
+ case 'utf-8':
+ case 'ascii':
+ case 'latin1':
+ case 'binary':
+ case 'base64':
+ case 'ucs2':
+ case 'ucs-2':
+ case 'utf16le':
+ case 'utf-16le':
+ return true
+ default:
+ return false
+ }
+}
+
+Buffer.concat = function concat (list, length) {
+ if (!Array.isArray(list)) {
+ throw new TypeError('"list" argument must be an Array of Buffers')
+ }
+
+ if (list.length === 0) {
+ return Buffer.alloc(0)
+ }
+
+ let i
+ if (length === undefined) {
+ length = 0
+ for (i = 0; i < list.length; ++i) {
+ length += list[i].length
+ }
+ }
+
+ const buffer = Buffer.allocUnsafe(length)
+ let pos = 0
+ for (i = 0; i < list.length; ++i) {
+ let buf = list[i]
+ if (isInstance(buf, Uint8Array)) {
+ if (pos + buf.length > buffer.length) {
+ if (!Buffer.isBuffer(buf)) buf = Buffer.from(buf)
+ buf.copy(buffer, pos)
+ } else {
+ Uint8Array.prototype.set.call(
+ buffer,
+ buf,
+ pos
+ )
+ }
+ } else if (!Buffer.isBuffer(buf)) {
+ throw new TypeError('"list" argument must be an Array of Buffers')
+ } else {
+ buf.copy(buffer, pos)
+ }
+ pos += buf.length
+ }
+ return buffer
+}
+
+function byteLength (string, encoding) {
+ if (Buffer.isBuffer(string)) {
+ return string.length
+ }
+ if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) {
+ return string.byteLength
+ }
+ if (typeof string !== 'string') {
+ throw new TypeError(
+ 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' +
+ 'Received type ' + typeof string
+ )
+ }
+
+ const len = string.length
+ const mustMatch = (arguments.length > 2 && arguments[2] === true)
+ if (!mustMatch && len === 0) return 0
+
+ // Use a for loop to avoid recursion
+ let loweredCase = false
+ for (;;) {
+ switch (encoding) {
+ case 'ascii':
+ case 'latin1':
+ case 'binary':
+ return len
+ case 'utf8':
+ case 'utf-8':
+ return utf8ToBytes(string).length
+ case 'ucs2':
+ case 'ucs-2':
+ case 'utf16le':
+ case 'utf-16le':
+ return len * 2
+ case 'hex':
+ return len >>> 1
+ case 'base64':
+ return base64ToBytes(string).length
+ default:
+ if (loweredCase) {
+ return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8
+ }
+ encoding = ('' + encoding).toLowerCase()
+ loweredCase = true
+ }
+ }
+}
+Buffer.byteLength = byteLength
+
+function slowToString (encoding, start, end) {
+ let loweredCase = false
+
+ // No need to verify that "this.length <= MAX_UINT32" since it's a read-only
+ // property of a typed array.
+
+ // This behaves neither like String nor Uint8Array in that we set start/end
+ // to their upper/lower bounds if the value passed is out of range.
+ // undefined is handled specially as per ECMA-262 6th Edition,
+ // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
+ if (start === undefined || start < 0) {
+ start = 0
+ }
+ // Return early if start > this.length. Done here to prevent potential uint32
+ // coercion fail below.
+ if (start > this.length) {
+ return ''
+ }
+
+ if (end === undefined || end > this.length) {
+ end = this.length
+ }
+
+ if (end <= 0) {
+ return ''
+ }
+
+ // Force coercion to uint32. This will also coerce falsey/NaN values to 0.
+ end >>>= 0
+ start >>>= 0
+
+ if (end <= start) {
+ return ''
+ }
+
+ if (!encoding) encoding = 'utf8'
+
+ while (true) {
+ switch (encoding) {
+ case 'hex':
+ return hexSlice(this, start, end)
+
+ case 'utf8':
+ case 'utf-8':
+ return utf8Slice(this, start, end)
+
+ case 'ascii':
+ return asciiSlice(this, start, end)
+
+ case 'latin1':
+ case 'binary':
+ return latin1Slice(this, start, end)
+
+ case 'base64':
+ return base64Slice(this, start, end)
+
+ case 'ucs2':
+ case 'ucs-2':
+ case 'utf16le':
+ case 'utf-16le':
+ return utf16leSlice(this, start, end)
+
+ default:
+ if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
+ encoding = (encoding + '').toLowerCase()
+ loweredCase = true
+ }
+ }
+}
+
+// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package)
+// to detect a Buffer instance. It's not possible to use `instanceof Buffer`
+// reliably in a browserify context because there could be multiple different
+// copies of the 'buffer' package in use. This method works even for Buffer
+// instances that were created from another copy of the `buffer` package.
+// See: https://github.com/feross/buffer/issues/154
+Buffer.prototype._isBuffer = true
+
+function swap (b, n, m) {
+ const i = b[n]
+ b[n] = b[m]
+ b[m] = i
+}
+
+Buffer.prototype.swap16 = function swap16 () {
+ const len = this.length
+ if (len % 2 !== 0) {
+ throw new RangeError('Buffer size must be a multiple of 16-bits')
+ }
+ for (let i = 0; i < len; i += 2) {
+ swap(this, i, i + 1)
+ }
+ return this
+}
+
+Buffer.prototype.swap32 = function swap32 () {
+ const len = this.length
+ if (len % 4 !== 0) {
+ throw new RangeError('Buffer size must be a multiple of 32-bits')
+ }
+ for (let i = 0; i < len; i += 4) {
+ swap(this, i, i + 3)
+ swap(this, i + 1, i + 2)
+ }
+ return this
+}
+
+Buffer.prototype.swap64 = function swap64 () {
+ const len = this.length
+ if (len % 8 !== 0) {
+ throw new RangeError('Buffer size must be a multiple of 64-bits')
+ }
+ for (let i = 0; i < len; i += 8) {
+ swap(this, i, i + 7)
+ swap(this, i + 1, i + 6)
+ swap(this, i + 2, i + 5)
+ swap(this, i + 3, i + 4)
+ }
+ return this
+}
+
+Buffer.prototype.toString = function toString () {
+ const length = this.length
+ if (length === 0) return ''
+ if (arguments.length === 0) return utf8Slice(this, 0, length)
+ return slowToString.apply(this, arguments)
+}
+
+Buffer.prototype.toLocaleString = Buffer.prototype.toString
+
+Buffer.prototype.equals = function equals (b) {
+ if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
+ if (this === b) return true
+ return Buffer.compare(this, b) === 0
+}
+
+Buffer.prototype.inspect = function inspect () {
+ let str = ''
+ const max = exports.INSPECT_MAX_BYTES
+ str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim()
+ if (this.length > max) str += ' ... '
+ return ''
+}
+if (customInspectSymbol) {
+ Buffer.prototype[customInspectSymbol] = Buffer.prototype.inspect
+}
+
+Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {
+ if (isInstance(target, Uint8Array)) {
+ target = Buffer.from(target, target.offset, target.byteLength)
+ }
+ if (!Buffer.isBuffer(target)) {
+ throw new TypeError(
+ 'The "target" argument must be one of type Buffer or Uint8Array. ' +
+ 'Received type ' + (typeof target)
+ )
+ }
+
+ if (start === undefined) {
+ start = 0
+ }
+ if (end === undefined) {
+ end = target ? target.length : 0
+ }
+ if (thisStart === undefined) {
+ thisStart = 0
+ }
+ if (thisEnd === undefined) {
+ thisEnd = this.length
+ }
+
+ if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {
+ throw new RangeError('out of range index')
+ }
+
+ if (thisStart >= thisEnd && start >= end) {
+ return 0
+ }
+ if (thisStart >= thisEnd) {
+ return -1
+ }
+ if (start >= end) {
+ return 1
+ }
+
+ start >>>= 0
+ end >>>= 0
+ thisStart >>>= 0
+ thisEnd >>>= 0
+
+ if (this === target) return 0
+
+ let x = thisEnd - thisStart
+ let y = end - start
+ const len = Math.min(x, y)
+
+ const thisCopy = this.slice(thisStart, thisEnd)
+ const targetCopy = target.slice(start, end)
+
+ for (let i = 0; i < len; ++i) {
+ if (thisCopy[i] !== targetCopy[i]) {
+ x = thisCopy[i]
+ y = targetCopy[i]
+ break
+ }
+ }
+
+ if (x < y) return -1
+ if (y < x) return 1
+ return 0
+}
+
+// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
+// OR the last index of `val` in `buffer` at offset <= `byteOffset`.
+//
+// Arguments:
+// - buffer - a Buffer to search
+// - val - a string, Buffer, or number
+// - byteOffset - an index into `buffer`; will be clamped to an int32
+// - encoding - an optional encoding, relevant is val is a string
+// - dir - true for indexOf, false for lastIndexOf
+function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {
+ // Empty buffer means no match
+ if (buffer.length === 0) return -1
+
+ // Normalize byteOffset
+ if (typeof byteOffset === 'string') {
+ encoding = byteOffset
+ byteOffset = 0
+ } else if (byteOffset > 0x7fffffff) {
+ byteOffset = 0x7fffffff
+ } else if (byteOffset < -0x80000000) {
+ byteOffset = -0x80000000
+ }
+ byteOffset = +byteOffset // Coerce to Number.
+ if (numberIsNaN(byteOffset)) {
+ // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
+ byteOffset = dir ? 0 : (buffer.length - 1)
+ }
+
+ // Normalize byteOffset: negative offsets start from the end of the buffer
+ if (byteOffset < 0) byteOffset = buffer.length + byteOffset
+ if (byteOffset >= buffer.length) {
+ if (dir) return -1
+ else byteOffset = buffer.length - 1
+ } else if (byteOffset < 0) {
+ if (dir) byteOffset = 0
+ else return -1
+ }
+
+ // Normalize val
+ if (typeof val === 'string') {
+ val = Buffer.from(val, encoding)
+ }
+
+ // Finally, search either indexOf (if dir is true) or lastIndexOf
+ if (Buffer.isBuffer(val)) {
+ // Special case: looking for empty string/buffer always fails
+ if (val.length === 0) {
+ return -1
+ }
+ return arrayIndexOf(buffer, val, byteOffset, encoding, dir)
+ } else if (typeof val === 'number') {
+ val = val & 0xFF // Search for a byte value [0-255]
+ if (typeof Uint8Array.prototype.indexOf === 'function') {
+ if (dir) {
+ return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)
+ } else {
+ return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)
+ }
+ }
+ return arrayIndexOf(buffer, [val], byteOffset, encoding, dir)
+ }
+
+ throw new TypeError('val must be string, number or Buffer')
+}
+
+function arrayIndexOf (arr, val, byteOffset, encoding, dir) {
+ let indexSize = 1
+ let arrLength = arr.length
+ let valLength = val.length
+
+ if (encoding !== undefined) {
+ encoding = String(encoding).toLowerCase()
+ if (encoding === 'ucs2' || encoding === 'ucs-2' ||
+ encoding === 'utf16le' || encoding === 'utf-16le') {
+ if (arr.length < 2 || val.length < 2) {
+ return -1
+ }
+ indexSize = 2
+ arrLength /= 2
+ valLength /= 2
+ byteOffset /= 2
+ }
+ }
+
+ function read (buf, i) {
+ if (indexSize === 1) {
+ return buf[i]
+ } else {
+ return buf.readUInt16BE(i * indexSize)
+ }
+ }
+
+ let i
+ if (dir) {
+ let foundIndex = -1
+ for (i = byteOffset; i < arrLength; i++) {
+ if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
+ if (foundIndex === -1) foundIndex = i
+ if (i - foundIndex + 1 === valLength) return foundIndex * indexSize
+ } else {
+ if (foundIndex !== -1) i -= i - foundIndex
+ foundIndex = -1
+ }
+ }
+ } else {
+ if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength
+ for (i = byteOffset; i >= 0; i--) {
+ let found = true
+ for (let j = 0; j < valLength; j++) {
+ if (read(arr, i + j) !== read(val, j)) {
+ found = false
+ break
+ }
+ }
+ if (found) return i
+ }
+ }
+
+ return -1
+}
+
+Buffer.prototype.includes = function includes (val, byteOffset, encoding) {
+ return this.indexOf(val, byteOffset, encoding) !== -1
+}
+
+Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {
+ return bidirectionalIndexOf(this, val, byteOffset, encoding, true)
+}
+
+Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {
+ return bidirectionalIndexOf(this, val, byteOffset, encoding, false)
+}
+
+function hexWrite (buf, string, offset, length) {
+ offset = Number(offset) || 0
+ const remaining = buf.length - offset
+ if (!length) {
+ length = remaining
+ } else {
+ length = Number(length)
+ if (length > remaining) {
+ length = remaining
+ }
+ }
+
+ const strLen = string.length
+
+ if (length > strLen / 2) {
+ length = strLen / 2
+ }
+ let i
+ for (i = 0; i < length; ++i) {
+ const parsed = parseInt(string.substr(i * 2, 2), 16)
+ if (numberIsNaN(parsed)) return i
+ buf[offset + i] = parsed
+ }
+ return i
+}
+
+function utf8Write (buf, string, offset, length) {
+ return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
+}
+
+function asciiWrite (buf, string, offset, length) {
+ return blitBuffer(asciiToBytes(string), buf, offset, length)
+}
+
+function base64Write (buf, string, offset, length) {
+ return blitBuffer(base64ToBytes(string), buf, offset, length)
+}
+
+function ucs2Write (buf, string, offset, length) {
+ return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
+}
+
+Buffer.prototype.write = function write (string, offset, length, encoding) {
+ // Buffer#write(string)
+ if (offset === undefined) {
+ encoding = 'utf8'
+ length = this.length
+ offset = 0
+ // Buffer#write(string, encoding)
+ } else if (length === undefined && typeof offset === 'string') {
+ encoding = offset
+ length = this.length
+ offset = 0
+ // Buffer#write(string, offset[, length][, encoding])
+ } else if (isFinite(offset)) {
+ offset = offset >>> 0
+ if (isFinite(length)) {
+ length = length >>> 0
+ if (encoding === undefined) encoding = 'utf8'
+ } else {
+ encoding = length
+ length = undefined
+ }
+ } else {
+ throw new Error(
+ 'Buffer.write(string, encoding, offset[, length]) is no longer supported'
+ )
+ }
+
+ const remaining = this.length - offset
+ if (length === undefined || length > remaining) length = remaining
+
+ if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
+ throw new RangeError('Attempt to write outside buffer bounds')
+ }
+
+ if (!encoding) encoding = 'utf8'
+
+ let loweredCase = false
+ for (;;) {
+ switch (encoding) {
+ case 'hex':
+ return hexWrite(this, string, offset, length)
+
+ case 'utf8':
+ case 'utf-8':
+ return utf8Write(this, string, offset, length)
+
+ case 'ascii':
+ case 'latin1':
+ case 'binary':
+ return asciiWrite(this, string, offset, length)
+
+ case 'base64':
+ // Warning: maxLength not taken into account in base64Write
+ return base64Write(this, string, offset, length)
+
+ case 'ucs2':
+ case 'ucs-2':
+ case 'utf16le':
+ case 'utf-16le':
+ return ucs2Write(this, string, offset, length)
+
+ default:
+ if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
+ encoding = ('' + encoding).toLowerCase()
+ loweredCase = true
+ }
+ }
+}
+
+Buffer.prototype.toJSON = function toJSON () {
+ return {
+ type: 'Buffer',
+ data: Array.prototype.slice.call(this._arr || this, 0)
+ }
+}
+
+function base64Slice (buf, start, end) {
+ if (start === 0 && end === buf.length) {
+ return base64.fromByteArray(buf)
+ } else {
+ return base64.fromByteArray(buf.slice(start, end))
+ }
+}
+
+function utf8Slice (buf, start, end) {
+ end = Math.min(buf.length, end)
+ const res = []
+
+ let i = start
+ while (i < end) {
+ const firstByte = buf[i]
+ let codePoint = null
+ let bytesPerSequence = (firstByte > 0xEF)
+ ? 4
+ : (firstByte > 0xDF)
+ ? 3
+ : (firstByte > 0xBF)
+ ? 2
+ : 1
+
+ if (i + bytesPerSequence <= end) {
+ let secondByte, thirdByte, fourthByte, tempCodePoint
+
+ switch (bytesPerSequence) {
+ case 1:
+ if (firstByte < 0x80) {
+ codePoint = firstByte
+ }
+ break
+ case 2:
+ secondByte = buf[i + 1]
+ if ((secondByte & 0xC0) === 0x80) {
+ tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
+ if (tempCodePoint > 0x7F) {
+ codePoint = tempCodePoint
+ }
+ }
+ break
+ case 3:
+ secondByte = buf[i + 1]
+ thirdByte = buf[i + 2]
+ if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
+ tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
+ if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
+ codePoint = tempCodePoint
+ }
+ }
+ break
+ case 4:
+ secondByte = buf[i + 1]
+ thirdByte = buf[i + 2]
+ fourthByte = buf[i + 3]
+ if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
+ tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
+ if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
+ codePoint = tempCodePoint
+ }
+ }
+ }
+ }
+
+ if (codePoint === null) {
+ // we did not generate a valid codePoint so insert a
+ // replacement char (U+FFFD) and advance only 1 byte
+ codePoint = 0xFFFD
+ bytesPerSequence = 1
+ } else if (codePoint > 0xFFFF) {
+ // encode to utf16 (surrogate pair dance)
+ codePoint -= 0x10000
+ res.push(codePoint >>> 10 & 0x3FF | 0xD800)
+ codePoint = 0xDC00 | codePoint & 0x3FF
+ }
+
+ res.push(codePoint)
+ i += bytesPerSequence
+ }
+
+ return decodeCodePointsArray(res)
+}
+
+// Based on http://stackoverflow.com/a/22747272/680742, the browser with
+// the lowest limit is Chrome, with 0x10000 args.
+// We go 1 magnitude less, for safety
+const MAX_ARGUMENTS_LENGTH = 0x1000
+
+function decodeCodePointsArray (codePoints) {
+ const len = codePoints.length
+ if (len <= MAX_ARGUMENTS_LENGTH) {
+ return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
+ }
+
+ // Decode in chunks to avoid "call stack size exceeded".
+ let res = ''
+ let i = 0
+ while (i < len) {
+ res += String.fromCharCode.apply(
+ String,
+ codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
+ )
+ }
+ return res
+}
+
+function asciiSlice (buf, start, end) {
+ let ret = ''
+ end = Math.min(buf.length, end)
+
+ for (let i = start; i < end; ++i) {
+ ret += String.fromCharCode(buf[i] & 0x7F)
+ }
+ return ret
+}
+
+function latin1Slice (buf, start, end) {
+ let ret = ''
+ end = Math.min(buf.length, end)
+
+ for (let i = start; i < end; ++i) {
+ ret += String.fromCharCode(buf[i])
+ }
+ return ret
+}
+
+function hexSlice (buf, start, end) {
+ const len = buf.length
+
+ if (!start || start < 0) start = 0
+ if (!end || end < 0 || end > len) end = len
+
+ let out = ''
+ for (let i = start; i < end; ++i) {
+ out += hexSliceLookupTable[buf[i]]
+ }
+ return out
+}
+
+function utf16leSlice (buf, start, end) {
+ const bytes = buf.slice(start, end)
+ let res = ''
+ // If bytes.length is odd, the last 8 bits must be ignored (same as node.js)
+ for (let i = 0; i < bytes.length - 1; i += 2) {
+ res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256))
+ }
+ return res
+}
+
+Buffer.prototype.slice = function slice (start, end) {
+ const len = this.length
+ start = ~~start
+ end = end === undefined ? len : ~~end
+
+ if (start < 0) {
+ start += len
+ if (start < 0) start = 0
+ } else if (start > len) {
+ start = len
+ }
+
+ if (end < 0) {
+ end += len
+ if (end < 0) end = 0
+ } else if (end > len) {
+ end = len
+ }
+
+ if (end < start) end = start
+
+ const newBuf = this.subarray(start, end)
+ // Return an augmented `Uint8Array` instance
+ Object.setPrototypeOf(newBuf, Buffer.prototype)
+
+ return newBuf
+}
+
+/*
+ * Need to make sure that buffer isn't trying to write out of bounds.
+ */
+function checkOffset (offset, ext, length) {
+ if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
+ if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
+}
+
+Buffer.prototype.readUintLE =
+Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+ let val = this[offset]
+ let mul = 1
+ let i = 0
+ while (++i < byteLength && (mul *= 0x100)) {
+ val += this[offset + i] * mul
+ }
+
+ return val
+}
+
+Buffer.prototype.readUintBE =
+Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) {
+ checkOffset(offset, byteLength, this.length)
+ }
+
+ let val = this[offset + --byteLength]
+ let mul = 1
+ while (byteLength > 0 && (mul *= 0x100)) {
+ val += this[offset + --byteLength] * mul
+ }
+
+ return val
+}
+
+Buffer.prototype.readUint8 =
+Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 1, this.length)
+ return this[offset]
+}
+
+Buffer.prototype.readUint16LE =
+Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 2, this.length)
+ return this[offset] | (this[offset + 1] << 8)
+}
+
+Buffer.prototype.readUint16BE =
+Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 2, this.length)
+ return (this[offset] << 8) | this[offset + 1]
+}
+
+Buffer.prototype.readUint32LE =
+Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+
+ return ((this[offset]) |
+ (this[offset + 1] << 8) |
+ (this[offset + 2] << 16)) +
+ (this[offset + 3] * 0x1000000)
+}
+
+Buffer.prototype.readUint32BE =
+Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+
+ return (this[offset] * 0x1000000) +
+ ((this[offset + 1] << 16) |
+ (this[offset + 2] << 8) |
+ this[offset + 3])
+}
+
+Buffer.prototype.readBigUInt64LE = defineBigIntMethod(function readBigUInt64LE (offset) {
+ offset = offset >>> 0
+ validateNumber(offset, 'offset')
+ const first = this[offset]
+ const last = this[offset + 7]
+ if (first === undefined || last === undefined) {
+ boundsError(offset, this.length - 8)
+ }
+
+ const lo = first +
+ this[++offset] * 2 ** 8 +
+ this[++offset] * 2 ** 16 +
+ this[++offset] * 2 ** 24
+
+ const hi = this[++offset] +
+ this[++offset] * 2 ** 8 +
+ this[++offset] * 2 ** 16 +
+ last * 2 ** 24
+
+ return BigInt(lo) + (BigInt(hi) << BigInt(32))
+})
+
+Buffer.prototype.readBigUInt64BE = defineBigIntMethod(function readBigUInt64BE (offset) {
+ offset = offset >>> 0
+ validateNumber(offset, 'offset')
+ const first = this[offset]
+ const last = this[offset + 7]
+ if (first === undefined || last === undefined) {
+ boundsError(offset, this.length - 8)
+ }
+
+ const hi = first * 2 ** 24 +
+ this[++offset] * 2 ** 16 +
+ this[++offset] * 2 ** 8 +
+ this[++offset]
+
+ const lo = this[++offset] * 2 ** 24 +
+ this[++offset] * 2 ** 16 +
+ this[++offset] * 2 ** 8 +
+ last
+
+ return (BigInt(hi) << BigInt(32)) + BigInt(lo)
+})
+
+Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+ let val = this[offset]
+ let mul = 1
+ let i = 0
+ while (++i < byteLength && (mul *= 0x100)) {
+ val += this[offset + i] * mul
+ }
+ mul *= 0x80
+
+ if (val >= mul) val -= Math.pow(2, 8 * byteLength)
+
+ return val
+}
+
+Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) checkOffset(offset, byteLength, this.length)
+
+ let i = byteLength
+ let mul = 1
+ let val = this[offset + --i]
+ while (i > 0 && (mul *= 0x100)) {
+ val += this[offset + --i] * mul
+ }
+ mul *= 0x80
+
+ if (val >= mul) val -= Math.pow(2, 8 * byteLength)
+
+ return val
+}
+
+Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 1, this.length)
+ if (!(this[offset] & 0x80)) return (this[offset])
+ return ((0xff - this[offset] + 1) * -1)
+}
+
+Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 2, this.length)
+ const val = this[offset] | (this[offset + 1] << 8)
+ return (val & 0x8000) ? val | 0xFFFF0000 : val
+}
+
+Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 2, this.length)
+ const val = this[offset + 1] | (this[offset] << 8)
+ return (val & 0x8000) ? val | 0xFFFF0000 : val
+}
+
+Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+
+ return (this[offset]) |
+ (this[offset + 1] << 8) |
+ (this[offset + 2] << 16) |
+ (this[offset + 3] << 24)
+}
+
+Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+
+ return (this[offset] << 24) |
+ (this[offset + 1] << 16) |
+ (this[offset + 2] << 8) |
+ (this[offset + 3])
+}
+
+Buffer.prototype.readBigInt64LE = defineBigIntMethod(function readBigInt64LE (offset) {
+ offset = offset >>> 0
+ validateNumber(offset, 'offset')
+ const first = this[offset]
+ const last = this[offset + 7]
+ if (first === undefined || last === undefined) {
+ boundsError(offset, this.length - 8)
+ }
+
+ const val = this[offset + 4] +
+ this[offset + 5] * 2 ** 8 +
+ this[offset + 6] * 2 ** 16 +
+ (last << 24) // Overflow
+
+ return (BigInt(val) << BigInt(32)) +
+ BigInt(first +
+ this[++offset] * 2 ** 8 +
+ this[++offset] * 2 ** 16 +
+ this[++offset] * 2 ** 24)
+})
+
+Buffer.prototype.readBigInt64BE = defineBigIntMethod(function readBigInt64BE (offset) {
+ offset = offset >>> 0
+ validateNumber(offset, 'offset')
+ const first = this[offset]
+ const last = this[offset + 7]
+ if (first === undefined || last === undefined) {
+ boundsError(offset, this.length - 8)
+ }
+
+ const val = (first << 24) + // Overflow
+ this[++offset] * 2 ** 16 +
+ this[++offset] * 2 ** 8 +
+ this[++offset]
+
+ return (BigInt(val) << BigInt(32)) +
+ BigInt(this[++offset] * 2 ** 24 +
+ this[++offset] * 2 ** 16 +
+ this[++offset] * 2 ** 8 +
+ last)
+})
+
+Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+ return ieee754.read(this, offset, true, 23, 4)
+}
+
+Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 4, this.length)
+ return ieee754.read(this, offset, false, 23, 4)
+}
+
+Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 8, this.length)
+ return ieee754.read(this, offset, true, 52, 8)
+}
+
+Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
+ offset = offset >>> 0
+ if (!noAssert) checkOffset(offset, 8, this.length)
+ return ieee754.read(this, offset, false, 52, 8)
+}
+
+function checkInt (buf, value, offset, ext, max, min) {
+ if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance')
+ if (value > max || value < min) throw new RangeError('"value" argument is out of bounds')
+ if (offset + ext > buf.length) throw new RangeError('Index out of range')
+}
+
+Buffer.prototype.writeUintLE =
+Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) {
+ const maxBytes = Math.pow(2, 8 * byteLength) - 1
+ checkInt(this, value, offset, byteLength, maxBytes, 0)
+ }
+
+ let mul = 1
+ let i = 0
+ this[offset] = value & 0xFF
+ while (++i < byteLength && (mul *= 0x100)) {
+ this[offset + i] = (value / mul) & 0xFF
+ }
+
+ return offset + byteLength
+}
+
+Buffer.prototype.writeUintBE =
+Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ byteLength = byteLength >>> 0
+ if (!noAssert) {
+ const maxBytes = Math.pow(2, 8 * byteLength) - 1
+ checkInt(this, value, offset, byteLength, maxBytes, 0)
+ }
+
+ let i = byteLength - 1
+ let mul = 1
+ this[offset + i] = value & 0xFF
+ while (--i >= 0 && (mul *= 0x100)) {
+ this[offset + i] = (value / mul) & 0xFF
+ }
+
+ return offset + byteLength
+}
+
+Buffer.prototype.writeUint8 =
+Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
+ this[offset] = (value & 0xff)
+ return offset + 1
+}
+
+Buffer.prototype.writeUint16LE =
+Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
+ this[offset] = (value & 0xff)
+ this[offset + 1] = (value >>> 8)
+ return offset + 2
+}
+
+Buffer.prototype.writeUint16BE =
+Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
+ this[offset] = (value >>> 8)
+ this[offset + 1] = (value & 0xff)
+ return offset + 2
+}
+
+Buffer.prototype.writeUint32LE =
+Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
+ this[offset + 3] = (value >>> 24)
+ this[offset + 2] = (value >>> 16)
+ this[offset + 1] = (value >>> 8)
+ this[offset] = (value & 0xff)
+ return offset + 4
+}
+
+Buffer.prototype.writeUint32BE =
+Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
+ this[offset] = (value >>> 24)
+ this[offset + 1] = (value >>> 16)
+ this[offset + 2] = (value >>> 8)
+ this[offset + 3] = (value & 0xff)
+ return offset + 4
+}
+
+function wrtBigUInt64LE (buf, value, offset, min, max) {
+ checkIntBI(value, min, max, buf, offset, 7)
+
+ let lo = Number(value & BigInt(0xffffffff))
+ buf[offset++] = lo
+ lo = lo >> 8
+ buf[offset++] = lo
+ lo = lo >> 8
+ buf[offset++] = lo
+ lo = lo >> 8
+ buf[offset++] = lo
+ let hi = Number(value >> BigInt(32) & BigInt(0xffffffff))
+ buf[offset++] = hi
+ hi = hi >> 8
+ buf[offset++] = hi
+ hi = hi >> 8
+ buf[offset++] = hi
+ hi = hi >> 8
+ buf[offset++] = hi
+ return offset
+}
+
+function wrtBigUInt64BE (buf, value, offset, min, max) {
+ checkIntBI(value, min, max, buf, offset, 7)
+
+ let lo = Number(value & BigInt(0xffffffff))
+ buf[offset + 7] = lo
+ lo = lo >> 8
+ buf[offset + 6] = lo
+ lo = lo >> 8
+ buf[offset + 5] = lo
+ lo = lo >> 8
+ buf[offset + 4] = lo
+ let hi = Number(value >> BigInt(32) & BigInt(0xffffffff))
+ buf[offset + 3] = hi
+ hi = hi >> 8
+ buf[offset + 2] = hi
+ hi = hi >> 8
+ buf[offset + 1] = hi
+ hi = hi >> 8
+ buf[offset] = hi
+ return offset + 8
+}
+
+Buffer.prototype.writeBigUInt64LE = defineBigIntMethod(function writeBigUInt64LE (value, offset = 0) {
+ return wrtBigUInt64LE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff'))
+})
+
+Buffer.prototype.writeBigUInt64BE = defineBigIntMethod(function writeBigUInt64BE (value, offset = 0) {
+ return wrtBigUInt64BE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff'))
+})
+
+Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) {
+ const limit = Math.pow(2, (8 * byteLength) - 1)
+
+ checkInt(this, value, offset, byteLength, limit - 1, -limit)
+ }
+
+ let i = 0
+ let mul = 1
+ let sub = 0
+ this[offset] = value & 0xFF
+ while (++i < byteLength && (mul *= 0x100)) {
+ if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
+ sub = 1
+ }
+ this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
+ }
+
+ return offset + byteLength
+}
+
+Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) {
+ const limit = Math.pow(2, (8 * byteLength) - 1)
+
+ checkInt(this, value, offset, byteLength, limit - 1, -limit)
+ }
+
+ let i = byteLength - 1
+ let mul = 1
+ let sub = 0
+ this[offset + i] = value & 0xFF
+ while (--i >= 0 && (mul *= 0x100)) {
+ if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
+ sub = 1
+ }
+ this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
+ }
+
+ return offset + byteLength
+}
+
+Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
+ if (value < 0) value = 0xff + value + 1
+ this[offset] = (value & 0xff)
+ return offset + 1
+}
+
+Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
+ this[offset] = (value & 0xff)
+ this[offset + 1] = (value >>> 8)
+ return offset + 2
+}
+
+Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
+ this[offset] = (value >>> 8)
+ this[offset + 1] = (value & 0xff)
+ return offset + 2
+}
+
+Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
+ this[offset] = (value & 0xff)
+ this[offset + 1] = (value >>> 8)
+ this[offset + 2] = (value >>> 16)
+ this[offset + 3] = (value >>> 24)
+ return offset + 4
+}
+
+Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
+ if (value < 0) value = 0xffffffff + value + 1
+ this[offset] = (value >>> 24)
+ this[offset + 1] = (value >>> 16)
+ this[offset + 2] = (value >>> 8)
+ this[offset + 3] = (value & 0xff)
+ return offset + 4
+}
+
+Buffer.prototype.writeBigInt64LE = defineBigIntMethod(function writeBigInt64LE (value, offset = 0) {
+ return wrtBigUInt64LE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff'))
+})
+
+Buffer.prototype.writeBigInt64BE = defineBigIntMethod(function writeBigInt64BE (value, offset = 0) {
+ return wrtBigUInt64BE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff'))
+})
+
+function checkIEEE754 (buf, value, offset, ext, max, min) {
+ if (offset + ext > buf.length) throw new RangeError('Index out of range')
+ if (offset < 0) throw new RangeError('Index out of range')
+}
+
+function writeFloat (buf, value, offset, littleEndian, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) {
+ checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
+ }
+ ieee754.write(buf, value, offset, littleEndian, 23, 4)
+ return offset + 4
+}
+
+Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
+ return writeFloat(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
+ return writeFloat(this, value, offset, false, noAssert)
+}
+
+function writeDouble (buf, value, offset, littleEndian, noAssert) {
+ value = +value
+ offset = offset >>> 0
+ if (!noAssert) {
+ checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
+ }
+ ieee754.write(buf, value, offset, littleEndian, 52, 8)
+ return offset + 8
+}
+
+Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
+ return writeDouble(this, value, offset, true, noAssert)
+}
+
+Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
+ return writeDouble(this, value, offset, false, noAssert)
+}
+
+// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
+Buffer.prototype.copy = function copy (target, targetStart, start, end) {
+ if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer')
+ if (!start) start = 0
+ if (!end && end !== 0) end = this.length
+ if (targetStart >= target.length) targetStart = target.length
+ if (!targetStart) targetStart = 0
+ if (end > 0 && end < start) end = start
+
+ // Copy 0 bytes; we're done
+ if (end === start) return 0
+ if (target.length === 0 || this.length === 0) return 0
+
+ // Fatal error conditions
+ if (targetStart < 0) {
+ throw new RangeError('targetStart out of bounds')
+ }
+ if (start < 0 || start >= this.length) throw new RangeError('Index out of range')
+ if (end < 0) throw new RangeError('sourceEnd out of bounds')
+
+ // Are we oob?
+ if (end > this.length) end = this.length
+ if (target.length - targetStart < end - start) {
+ end = target.length - targetStart + start
+ }
+
+ const len = end - start
+
+ if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') {
+ // Use built-in when available, missing from IE11
+ this.copyWithin(targetStart, start, end)
+ } else {
+ Uint8Array.prototype.set.call(
+ target,
+ this.subarray(start, end),
+ targetStart
+ )
+ }
+
+ return len
+}
+
+// Usage:
+// buffer.fill(number[, offset[, end]])
+// buffer.fill(buffer[, offset[, end]])
+// buffer.fill(string[, offset[, end]][, encoding])
+Buffer.prototype.fill = function fill (val, start, end, encoding) {
+ // Handle string cases:
+ if (typeof val === 'string') {
+ if (typeof start === 'string') {
+ encoding = start
+ start = 0
+ end = this.length
+ } else if (typeof end === 'string') {
+ encoding = end
+ end = this.length
+ }
+ if (encoding !== undefined && typeof encoding !== 'string') {
+ throw new TypeError('encoding must be a string')
+ }
+ if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
+ throw new TypeError('Unknown encoding: ' + encoding)
+ }
+ if (val.length === 1) {
+ const code = val.charCodeAt(0)
+ if ((encoding === 'utf8' && code < 128) ||
+ encoding === 'latin1') {
+ // Fast path: If `val` fits into a single byte, use that numeric value.
+ val = code
+ }
+ }
+ } else if (typeof val === 'number') {
+ val = val & 255
+ } else if (typeof val === 'boolean') {
+ val = Number(val)
+ }
+
+ // Invalid ranges are not set to a default, so can range check early.
+ if (start < 0 || this.length < start || this.length < end) {
+ throw new RangeError('Out of range index')
+ }
+
+ if (end <= start) {
+ return this
+ }
+
+ start = start >>> 0
+ end = end === undefined ? this.length : end >>> 0
+
+ if (!val) val = 0
+
+ let i
+ if (typeof val === 'number') {
+ for (i = start; i < end; ++i) {
+ this[i] = val
+ }
+ } else {
+ const bytes = Buffer.isBuffer(val)
+ ? val
+ : Buffer.from(val, encoding)
+ const len = bytes.length
+ if (len === 0) {
+ throw new TypeError('The value "' + val +
+ '" is invalid for argument "value"')
+ }
+ for (i = 0; i < end - start; ++i) {
+ this[i + start] = bytes[i % len]
+ }
+ }
+
+ return this
+}
+
+// CUSTOM ERRORS
+// =============
+
+// Simplified versions from Node, changed for Buffer-only usage
+const errors = {}
+function E (sym, getMessage, Base) {
+ errors[sym] = class NodeError extends Base {
+ constructor () {
+ super()
+
+ Object.defineProperty(this, 'message', {
+ value: getMessage.apply(this, arguments),
+ writable: true,
+ configurable: true
+ })
+
+ // Add the error code to the name to include it in the stack trace.
+ this.name = `${this.name} [${sym}]`
+ // Access the stack to generate the error message including the error code
+ // from the name.
+ this.stack // eslint-disable-line no-unused-expressions
+ // Reset the name to the actual name.
+ delete this.name
+ }
+
+ get code () {
+ return sym
+ }
+
+ set code (value) {
+ Object.defineProperty(this, 'code', {
+ configurable: true,
+ enumerable: true,
+ value,
+ writable: true
+ })
+ }
+
+ toString () {
+ return `${this.name} [${sym}]: ${this.message}`
+ }
+ }
+}
+
+E('ERR_BUFFER_OUT_OF_BOUNDS',
+ function (name) {
+ if (name) {
+ return `${name} is outside of buffer bounds`
+ }
+
+ return 'Attempt to access memory outside buffer bounds'
+ }, RangeError)
+E('ERR_INVALID_ARG_TYPE',
+ function (name, actual) {
+ return `The "${name}" argument must be of type number. Received type ${typeof actual}`
+ }, TypeError)
+E('ERR_OUT_OF_RANGE',
+ function (str, range, input) {
+ let msg = `The value of "${str}" is out of range.`
+ let received = input
+ if (Number.isInteger(input) && Math.abs(input) > 2 ** 32) {
+ received = addNumericalSeparator(String(input))
+ } else if (typeof input === 'bigint') {
+ received = String(input)
+ if (input > BigInt(2) ** BigInt(32) || input < -(BigInt(2) ** BigInt(32))) {
+ received = addNumericalSeparator(received)
+ }
+ received += 'n'
+ }
+ msg += ` It must be ${range}. Received ${received}`
+ return msg
+ }, RangeError)
+
+function addNumericalSeparator (val) {
+ let res = ''
+ let i = val.length
+ const start = val[0] === '-' ? 1 : 0
+ for (; i >= start + 4; i -= 3) {
+ res = `_${val.slice(i - 3, i)}${res}`
+ }
+ return `${val.slice(0, i)}${res}`
+}
+
+// CHECK FUNCTIONS
+// ===============
+
+function checkBounds (buf, offset, byteLength) {
+ validateNumber(offset, 'offset')
+ if (buf[offset] === undefined || buf[offset + byteLength] === undefined) {
+ boundsError(offset, buf.length - (byteLength + 1))
+ }
+}
+
+function checkIntBI (value, min, max, buf, offset, byteLength) {
+ if (value > max || value < min) {
+ const n = typeof min === 'bigint' ? 'n' : ''
+ let range
+ if (byteLength > 3) {
+ if (min === 0 || min === BigInt(0)) {
+ range = `>= 0${n} and < 2${n} ** ${(byteLength + 1) * 8}${n}`
+ } else {
+ range = `>= -(2${n} ** ${(byteLength + 1) * 8 - 1}${n}) and < 2 ** ` +
+ `${(byteLength + 1) * 8 - 1}${n}`
+ }
+ } else {
+ range = `>= ${min}${n} and <= ${max}${n}`
+ }
+ throw new errors.ERR_OUT_OF_RANGE('value', range, value)
+ }
+ checkBounds(buf, offset, byteLength)
+}
+
+function validateNumber (value, name) {
+ if (typeof value !== 'number') {
+ throw new errors.ERR_INVALID_ARG_TYPE(name, 'number', value)
+ }
+}
+
+function boundsError (value, length, type) {
+ if (Math.floor(value) !== value) {
+ validateNumber(value, type)
+ throw new errors.ERR_OUT_OF_RANGE(type || 'offset', 'an integer', value)
+ }
+
+ if (length < 0) {
+ throw new errors.ERR_BUFFER_OUT_OF_BOUNDS()
+ }
+
+ throw new errors.ERR_OUT_OF_RANGE(type || 'offset',
+ `>= ${type ? 1 : 0} and <= ${length}`,
+ value)
+}
+
+// HELPER FUNCTIONS
+// ================
+
+const INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g
+
+function base64clean (str) {
+ // Node takes equal signs as end of the Base64 encoding
+ str = str.split('=')[0]
+ // Node strips out invalid characters like \n and \t from the string, base64-js does not
+ str = str.trim().replace(INVALID_BASE64_RE, '')
+ // Node converts strings with length < 2 to ''
+ if (str.length < 2) return ''
+ // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
+ while (str.length % 4 !== 0) {
+ str = str + '='
+ }
+ return str
+}
+
+function utf8ToBytes (string, units) {
+ units = units || Infinity
+ let codePoint
+ const length = string.length
+ let leadSurrogate = null
+ const bytes = []
+
+ for (let i = 0; i < length; ++i) {
+ codePoint = string.charCodeAt(i)
+
+ // is surrogate component
+ if (codePoint > 0xD7FF && codePoint < 0xE000) {
+ // last char was a lead
+ if (!leadSurrogate) {
+ // no lead yet
+ if (codePoint > 0xDBFF) {
+ // unexpected trail
+ if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+ continue
+ } else if (i + 1 === length) {
+ // unpaired lead
+ if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+ continue
+ }
+
+ // valid lead
+ leadSurrogate = codePoint
+
+ continue
+ }
+
+ // 2 leads in a row
+ if (codePoint < 0xDC00) {
+ if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+ leadSurrogate = codePoint
+ continue
+ }
+
+ // valid surrogate pair
+ codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
+ } else if (leadSurrogate) {
+ // valid bmp char, but last char was a lead
+ if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+ }
+
+ leadSurrogate = null
+
+ // encode utf8
+ if (codePoint < 0x80) {
+ if ((units -= 1) < 0) break
+ bytes.push(codePoint)
+ } else if (codePoint < 0x800) {
+ if ((units -= 2) < 0) break
+ bytes.push(
+ codePoint >> 0x6 | 0xC0,
+ codePoint & 0x3F | 0x80
+ )
+ } else if (codePoint < 0x10000) {
+ if ((units -= 3) < 0) break
+ bytes.push(
+ codePoint >> 0xC | 0xE0,
+ codePoint >> 0x6 & 0x3F | 0x80,
+ codePoint & 0x3F | 0x80
+ )
+ } else if (codePoint < 0x110000) {
+ if ((units -= 4) < 0) break
+ bytes.push(
+ codePoint >> 0x12 | 0xF0,
+ codePoint >> 0xC & 0x3F | 0x80,
+ codePoint >> 0x6 & 0x3F | 0x80,
+ codePoint & 0x3F | 0x80
+ )
+ } else {
+ throw new Error('Invalid code point')
+ }
+ }
+
+ return bytes
+}
+
+function asciiToBytes (str) {
+ const byteArray = []
+ for (let i = 0; i < str.length; ++i) {
+ // Node's code seems to be doing this and not & 0x7F..
+ byteArray.push(str.charCodeAt(i) & 0xFF)
+ }
+ return byteArray
+}
+
+function utf16leToBytes (str, units) {
+ let c, hi, lo
+ const byteArray = []
+ for (let i = 0; i < str.length; ++i) {
+ if ((units -= 2) < 0) break
+
+ c = str.charCodeAt(i)
+ hi = c >> 8
+ lo = c % 256
+ byteArray.push(lo)
+ byteArray.push(hi)
+ }
+
+ return byteArray
+}
+
+function base64ToBytes (str) {
+ return base64.toByteArray(base64clean(str))
+}
+
+function blitBuffer (src, dst, offset, length) {
+ let i
+ for (i = 0; i < length; ++i) {
+ if ((i + offset >= dst.length) || (i >= src.length)) break
+ dst[i + offset] = src[i]
+ }
+ return i
+}
+
+// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass
+// the `instanceof` check but they should be treated as of that type.
+// See: https://github.com/feross/buffer/issues/166
+function isInstance (obj, type) {
+ return obj instanceof type ||
+ (obj != null && obj.constructor != null && obj.constructor.name != null &&
+ obj.constructor.name === type.name)
+}
+function numberIsNaN (obj) {
+ // For IE11 support
+ return obj !== obj // eslint-disable-line no-self-compare
+}
+
+// Create lookup table for `toString('hex')`
+// See: https://github.com/feross/buffer/issues/219
+const hexSliceLookupTable = (function () {
+ const alphabet = '0123456789abcdef'
+ const table = new Array(256)
+ for (let i = 0; i < 16; ++i) {
+ const i16 = i * 16
+ for (let j = 0; j < 16; ++j) {
+ table[i16 + j] = alphabet[i] + alphabet[j]
+ }
+ }
+ return table
+})()
+
+// Return not function with Error if BigInt not supported
+function defineBigIntMethod (fn) {
+ return typeof BigInt === 'undefined' ? BufferBigIntNotDefined : fn
+}
+
+function BufferBigIntNotDefined () {
+ throw new Error('BigInt not supported')
+}
diff --git a/backend/node_modules/buffer/package.json b/backend/node_modules/buffer/package.json
new file mode 100644
index 0000000..ca1ad9a
--- /dev/null
+++ b/backend/node_modules/buffer/package.json
@@ -0,0 +1,93 @@
+{
+ "name": "buffer",
+ "description": "Node.js Buffer API, for the browser",
+ "version": "6.0.3",
+ "author": {
+ "name": "Feross Aboukhadijeh",
+ "email": "feross@feross.org",
+ "url": "https://feross.org"
+ },
+ "bugs": {
+ "url": "https://github.com/feross/buffer/issues"
+ },
+ "contributors": [
+ "Romain Beauxis ",
+ "James Halliday "
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.2.1"
+ },
+ "devDependencies": {
+ "airtap": "^3.0.0",
+ "benchmark": "^2.1.4",
+ "browserify": "^17.0.0",
+ "concat-stream": "^2.0.0",
+ "hyperquest": "^2.1.3",
+ "is-buffer": "^2.0.5",
+ "is-nan": "^1.3.0",
+ "split": "^1.0.1",
+ "standard": "*",
+ "tape": "^5.0.1",
+ "through2": "^4.0.2",
+ "uglify-js": "^3.11.5"
+ },
+ "homepage": "https://github.com/feross/buffer",
+ "jspm": {
+ "map": {
+ "./index.js": {
+ "node": "@node/buffer"
+ }
+ }
+ },
+ "keywords": [
+ "arraybuffer",
+ "browser",
+ "browserify",
+ "buffer",
+ "compatible",
+ "dataview",
+ "uint8array"
+ ],
+ "license": "MIT",
+ "main": "index.js",
+ "types": "index.d.ts",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/feross/buffer.git"
+ },
+ "scripts": {
+ "perf": "browserify --debug perf/bracket-notation.js > perf/bundle.js && open perf/index.html",
+ "perf-node": "node perf/bracket-notation.js && node perf/concat.js && node perf/copy-big.js && node perf/copy.js && node perf/new-big.js && node perf/new.js && node perf/readDoubleBE.js && node perf/readFloatBE.js && node perf/readUInt32LE.js && node perf/slice.js && node perf/writeFloatBE.js",
+ "size": "browserify -r ./ | uglifyjs -c -m | gzip | wc -c",
+ "test": "standard && node ./bin/test.js",
+ "test-browser-old": "airtap -- test/*.js",
+ "test-browser-old-local": "airtap --local -- test/*.js",
+ "test-browser-new": "airtap -- test/*.js test/node/*.js",
+ "test-browser-new-local": "airtap --local -- test/*.js test/node/*.js",
+ "test-node": "tape test/*.js test/node/*.js",
+ "update-authors": "./bin/update-authors.sh"
+ },
+ "standard": {
+ "ignore": [
+ "test/node/**/*.js",
+ "test/common.js",
+ "test/_polyfill.js",
+ "perf/**/*.js"
+ ]
+ },
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+}
diff --git a/backend/node_modules/camelcase/index.d.ts b/backend/node_modules/camelcase/index.d.ts
new file mode 100644
index 0000000..58f2069
--- /dev/null
+++ b/backend/node_modules/camelcase/index.d.ts
@@ -0,0 +1,63 @@
+declare namespace camelcase {
+ interface Options {
+ /**
+ Uppercase the first character: `foo-bar` → `FooBar`.
+
+ @default false
+ */
+ readonly pascalCase?: boolean;
+ }
+}
+
+declare const camelcase: {
+ /**
+ Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`.
+
+ @param input - String to convert to camel case.
+
+ @example
+ ```
+ import camelCase = require('camelcase');
+
+ camelCase('foo-bar');
+ //=> 'fooBar'
+
+ camelCase('foo_bar');
+ //=> 'fooBar'
+
+ camelCase('Foo-Bar');
+ //=> 'fooBar'
+
+ camelCase('Foo-Bar', {pascalCase: true});
+ //=> 'FooBar'
+
+ camelCase('--foo.bar', {pascalCase: false});
+ //=> 'fooBar'
+
+ camelCase('foo bar');
+ //=> 'fooBar'
+
+ console.log(process.argv[3]);
+ //=> '--foo-bar'
+ camelCase(process.argv[3]);
+ //=> 'fooBar'
+
+ camelCase(['foo', 'bar']);
+ //=> 'fooBar'
+
+ camelCase(['__foo__', '--bar'], {pascalCase: true});
+ //=> 'FooBar'
+ ```
+ */
+ (input: string | ReadonlyArray, options?: camelcase.Options): string;
+
+ // TODO: Remove this for the next major release, refactor the whole definition to:
+ // declare function camelcase(
+ // input: string | ReadonlyArray,
+ // options?: camelcase.Options
+ // ): string;
+ // export = camelcase;
+ default: typeof camelcase;
+};
+
+export = camelcase;
diff --git a/backend/node_modules/camelcase/index.js b/backend/node_modules/camelcase/index.js
new file mode 100644
index 0000000..579f99b
--- /dev/null
+++ b/backend/node_modules/camelcase/index.js
@@ -0,0 +1,76 @@
+'use strict';
+
+const preserveCamelCase = string => {
+ let isLastCharLower = false;
+ let isLastCharUpper = false;
+ let isLastLastCharUpper = false;
+
+ for (let i = 0; i < string.length; i++) {
+ const character = string[i];
+
+ if (isLastCharLower && /[a-zA-Z]/.test(character) && character.toUpperCase() === character) {
+ string = string.slice(0, i) + '-' + string.slice(i);
+ isLastCharLower = false;
+ isLastLastCharUpper = isLastCharUpper;
+ isLastCharUpper = true;
+ i++;
+ } else if (isLastCharUpper && isLastLastCharUpper && /[a-zA-Z]/.test(character) && character.toLowerCase() === character) {
+ string = string.slice(0, i - 1) + '-' + string.slice(i - 1);
+ isLastLastCharUpper = isLastCharUpper;
+ isLastCharUpper = false;
+ isLastCharLower = true;
+ } else {
+ isLastCharLower = character.toLowerCase() === character && character.toUpperCase() !== character;
+ isLastLastCharUpper = isLastCharUpper;
+ isLastCharUpper = character.toUpperCase() === character && character.toLowerCase() !== character;
+ }
+ }
+
+ return string;
+};
+
+const camelCase = (input, options) => {
+ if (!(typeof input === 'string' || Array.isArray(input))) {
+ throw new TypeError('Expected the input to be `string | string[]`');
+ }
+
+ options = Object.assign({
+ pascalCase: false
+ }, options);
+
+ const postProcess = x => options.pascalCase ? x.charAt(0).toUpperCase() + x.slice(1) : x;
+
+ if (Array.isArray(input)) {
+ input = input.map(x => x.trim())
+ .filter(x => x.length)
+ .join('-');
+ } else {
+ input = input.trim();
+ }
+
+ if (input.length === 0) {
+ return '';
+ }
+
+ if (input.length === 1) {
+ return options.pascalCase ? input.toUpperCase() : input.toLowerCase();
+ }
+
+ const hasUpperCase = input !== input.toLowerCase();
+
+ if (hasUpperCase) {
+ input = preserveCamelCase(input);
+ }
+
+ input = input
+ .replace(/^[_.\- ]+/, '')
+ .toLowerCase()
+ .replace(/[_.\- ]+(\w|$)/g, (_, p1) => p1.toUpperCase())
+ .replace(/\d+(\w|$)/g, m => m.toUpperCase());
+
+ return postProcess(input);
+};
+
+module.exports = camelCase;
+// TODO: Remove this for the next major release
+module.exports.default = camelCase;
diff --git a/backend/node_modules/camelcase/license b/backend/node_modules/camelcase/license
new file mode 100644
index 0000000..e7af2f7
--- /dev/null
+++ b/backend/node_modules/camelcase/license
@@ -0,0 +1,9 @@
+MIT License
+
+Copyright (c) Sindre Sorhus (sindresorhus.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/backend/node_modules/camelcase/package.json b/backend/node_modules/camelcase/package.json
new file mode 100644
index 0000000..fbdbaaa
--- /dev/null
+++ b/backend/node_modules/camelcase/package.json
@@ -0,0 +1,43 @@
+{
+ "name": "camelcase",
+ "version": "5.3.1",
+ "description": "Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`",
+ "license": "MIT",
+ "repository": "sindresorhus/camelcase",
+ "author": {
+ "name": "Sindre Sorhus",
+ "email": "sindresorhus@gmail.com",
+ "url": "sindresorhus.com"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "scripts": {
+ "test": "xo && ava && tsd"
+ },
+ "files": [
+ "index.js",
+ "index.d.ts"
+ ],
+ "keywords": [
+ "camelcase",
+ "camel-case",
+ "camel",
+ "case",
+ "dash",
+ "hyphen",
+ "dot",
+ "underscore",
+ "separator",
+ "string",
+ "text",
+ "convert",
+ "pascalcase",
+ "pascal-case"
+ ],
+ "devDependencies": {
+ "ava": "^1.4.1",
+ "tsd": "^0.7.1",
+ "xo": "^0.24.0"
+ }
+}
diff --git a/backend/node_modules/camelcase/readme.md b/backend/node_modules/camelcase/readme.md
new file mode 100644
index 0000000..fde2726
--- /dev/null
+++ b/backend/node_modules/camelcase/readme.md
@@ -0,0 +1,99 @@
+# camelcase [](https://travis-ci.org/sindresorhus/camelcase)
+
+> Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`
+
+---
+
+
+
+---
+
+## Install
+
+```
+$ npm install camelcase
+```
+
+
+## Usage
+
+```js
+const camelCase = require('camelcase');
+
+camelCase('foo-bar');
+//=> 'fooBar'
+
+camelCase('foo_bar');
+//=> 'fooBar'
+
+camelCase('Foo-Bar');
+//=> 'fooBar'
+
+camelCase('Foo-Bar', {pascalCase: true});
+//=> 'FooBar'
+
+camelCase('--foo.bar', {pascalCase: false});
+//=> 'fooBar'
+
+camelCase('foo bar');
+//=> 'fooBar'
+
+console.log(process.argv[3]);
+//=> '--foo-bar'
+camelCase(process.argv[3]);
+//=> 'fooBar'
+
+camelCase(['foo', 'bar']);
+//=> 'fooBar'
+
+camelCase(['__foo__', '--bar'], {pascalCase: true});
+//=> 'FooBar'
+```
+
+
+## API
+
+### camelCase(input, [options])
+
+#### input
+
+Type: `string` `string[]`
+
+String to convert to camel case.
+
+#### options
+
+Type: `Object`
+
+##### pascalCase
+
+Type: `boolean`
+Default: `false`
+
+Uppercase the first character: `foo-bar` → `FooBar`
+
+
+## Security
+
+To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
+
+
+## Related
+
+- [decamelize](https://github.com/sindresorhus/decamelize) - The inverse of this module
+- [uppercamelcase](https://github.com/SamVerschueren/uppercamelcase) - Like this module, but to PascalCase instead of camelCase
+- [titleize](https://github.com/sindresorhus/titleize) - Capitalize every word in string
+- [humanize-string](https://github.com/sindresorhus/humanize-string) - Convert a camelized/dasherized/underscored string into a humanized one
+
+
+## License
+
+MIT © [Sindre Sorhus](https://sindresorhus.com)
diff --git a/backend/node_modules/cliui/CHANGELOG.md b/backend/node_modules/cliui/CHANGELOG.md
new file mode 100644
index 0000000..6a77f8f
--- /dev/null
+++ b/backend/node_modules/cliui/CHANGELOG.md
@@ -0,0 +1,76 @@
+# Change Log
+
+All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
+
+## [6.0.0](https://www.github.com/yargs/cliui/compare/v5.0.0...v6.0.0) (2019-11-10)
+
+
+### ⚠ BREAKING CHANGES
+
+* update deps, drop Node 6
+
+### Code Refactoring
+
+* update deps, drop Node 6 ([62056df](https://www.github.com/yargs/cliui/commit/62056df))
+
+## [5.0.0](https://github.com/yargs/cliui/compare/v4.1.0...v5.0.0) (2019-04-10)
+
+
+### Bug Fixes
+
+* Update wrap-ansi to fix compatibility with latest versions of chalk. ([#60](https://github.com/yargs/cliui/issues/60)) ([7bf79ae](https://github.com/yargs/cliui/commit/7bf79ae))
+
+
+### BREAKING CHANGES
+
+* Drop support for node < 6.
+
+
+
+
+## [4.1.0](https://github.com/yargs/cliui/compare/v4.0.0...v4.1.0) (2018-04-23)
+
+
+### Features
+
+* add resetOutput method ([#57](https://github.com/yargs/cliui/issues/57)) ([7246902](https://github.com/yargs/cliui/commit/7246902))
+
+
+
+
+## [4.0.0](https://github.com/yargs/cliui/compare/v3.2.0...v4.0.0) (2017-12-18)
+
+
+### Bug Fixes
+
+* downgrades strip-ansi to version 3.0.1 ([#54](https://github.com/yargs/cliui/issues/54)) ([5764c46](https://github.com/yargs/cliui/commit/5764c46))
+* set env variable FORCE_COLOR. ([#56](https://github.com/yargs/cliui/issues/56)) ([7350e36](https://github.com/yargs/cliui/commit/7350e36))
+
+
+### Chores
+
+* drop support for node < 4 ([#53](https://github.com/yargs/cliui/issues/53)) ([b105376](https://github.com/yargs/cliui/commit/b105376))
+
+
+### Features
+
+* add fallback for window width ([#45](https://github.com/yargs/cliui/issues/45)) ([d064922](https://github.com/yargs/cliui/commit/d064922))
+
+
+### BREAKING CHANGES
+
+* officially drop support for Node < 4
+
+
+
+
+## [3.2.0](https://github.com/yargs/cliui/compare/v3.1.2...v3.2.0) (2016-04-11)
+
+
+### Bug Fixes
+
+* reduces tarball size ([acc6c33](https://github.com/yargs/cliui/commit/acc6c33))
+
+### Features
+
+* adds standard-version for release management ([ff84e32](https://github.com/yargs/cliui/commit/ff84e32))
diff --git a/backend/node_modules/cliui/LICENSE.txt b/backend/node_modules/cliui/LICENSE.txt
new file mode 100644
index 0000000..c7e2747
--- /dev/null
+++ b/backend/node_modules/cliui/LICENSE.txt
@@ -0,0 +1,14 @@
+Copyright (c) 2015, Contributors
+
+Permission to use, copy, modify, and/or distribute this software
+for any purpose with or without fee is hereby granted, provided
+that the above copyright notice and this permission notice
+appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
+LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/backend/node_modules/cliui/README.md b/backend/node_modules/cliui/README.md
new file mode 100644
index 0000000..deacfa0
--- /dev/null
+++ b/backend/node_modules/cliui/README.md
@@ -0,0 +1,115 @@
+# cliui
+
+[](https://travis-ci.org/yargs/cliui)
+[](https://coveralls.io/r/yargs/cliui?branch=)
+[](https://www.npmjs.com/package/cliui)
+[](https://github.com/conventional-changelog/standard-version)
+
+easily create complex multi-column command-line-interfaces.
+
+## Example
+
+```js
+var ui = require('cliui')()
+
+ui.div('Usage: $0 [command] [options]')
+
+ui.div({
+ text: 'Options:',
+ padding: [2, 0, 2, 0]
+})
+
+ui.div(
+ {
+ text: "-f, --file",
+ width: 20,
+ padding: [0, 4, 0, 4]
+ },
+ {
+ text: "the file to load." +
+ chalk.green("(if this description is long it wraps).")
+ ,
+ width: 20
+ },
+ {
+ text: chalk.red("[required]"),
+ align: 'right'
+ }
+)
+
+console.log(ui.toString())
+```
+
+
+
+## Layout DSL
+
+cliui exposes a simple layout DSL:
+
+If you create a single `ui.div`, passing a string rather than an
+object:
+
+* `\n`: characters will be interpreted as new rows.
+* `\t`: characters will be interpreted as new columns.
+* `\s`: characters will be interpreted as padding.
+
+**as an example...**
+
+```js
+var ui = require('./')({
+ width: 60
+})
+
+ui.div(
+ 'Usage: node ./bin/foo.js\n' +
+ ' \t provide a regex\n' +
+ ' \t provide a glob\t [required]'
+)
+
+console.log(ui.toString())
+```
+
+**will output:**
+
+```shell
+Usage: node ./bin/foo.js
+ provide a regex
+ provide a glob [required]
+```
+
+## Methods
+
+```js
+cliui = require('cliui')
+```
+
+### cliui({width: integer})
+
+Specify the maximum width of the UI being generated.
+If no width is provided, cliui will try to get the current window's width and use it, and if that doesn't work, width will be set to `80`.
+
+### cliui({wrap: boolean})
+
+Enable or disable the wrapping of text in a column.
+
+### cliui.div(column, column, column)
+
+Create a row with any number of columns, a column
+can either be a string, or an object with the following
+options:
+
+* **text:** some text to place in the column.
+* **width:** the width of a column.
+* **align:** alignment, `right` or `center`.
+* **padding:** `[top, right, bottom, left]`.
+* **border:** should a border be placed around the div?
+
+### cliui.span(column, column, column)
+
+Similar to `div`, except the next row will be appended without
+a new line being created.
+
+### cliui.resetOutput()
+
+Resets the UI elements of the current cliui instance, maintaining the values
+set for `width` and `wrap`.
diff --git a/backend/node_modules/cliui/index.js b/backend/node_modules/cliui/index.js
new file mode 100644
index 0000000..e917b00
--- /dev/null
+++ b/backend/node_modules/cliui/index.js
@@ -0,0 +1,354 @@
+'use strict'
+
+const stringWidth = require('string-width')
+const stripAnsi = require('strip-ansi')
+const wrap = require('wrap-ansi')
+
+const align = {
+ right: alignRight,
+ center: alignCenter
+}
+const top = 0
+const right = 1
+const bottom = 2
+const left = 3
+
+class UI {
+ constructor (opts) {
+ this.width = opts.width
+ this.wrap = opts.wrap
+ this.rows = []
+ }
+
+ span (...args) {
+ const cols = this.div(...args)
+ cols.span = true
+ }
+
+ resetOutput () {
+ this.rows = []
+ }
+
+ div (...args) {
+ if (args.length === 0) {
+ this.div('')
+ }
+
+ if (this.wrap && this._shouldApplyLayoutDSL(...args)) {
+ return this._applyLayoutDSL(args[0])
+ }
+
+ const cols = args.map(arg => {
+ if (typeof arg === 'string') {
+ return this._colFromString(arg)
+ }
+
+ return arg
+ })
+
+ this.rows.push(cols)
+ return cols
+ }
+
+ _shouldApplyLayoutDSL (...args) {
+ return args.length === 1 && typeof args[0] === 'string' &&
+ /[\t\n]/.test(args[0])
+ }
+
+ _applyLayoutDSL (str) {
+ const rows = str.split('\n').map(row => row.split('\t'))
+ let leftColumnWidth = 0
+
+ // simple heuristic for layout, make sure the
+ // second column lines up along the left-hand.
+ // don't allow the first column to take up more
+ // than 50% of the screen.
+ rows.forEach(columns => {
+ if (columns.length > 1 && stringWidth(columns[0]) > leftColumnWidth) {
+ leftColumnWidth = Math.min(
+ Math.floor(this.width * 0.5),
+ stringWidth(columns[0])
+ )
+ }
+ })
+
+ // generate a table:
+ // replacing ' ' with padding calculations.
+ // using the algorithmically generated width.
+ rows.forEach(columns => {
+ this.div(...columns.map((r, i) => {
+ return {
+ text: r.trim(),
+ padding: this._measurePadding(r),
+ width: (i === 0 && columns.length > 1) ? leftColumnWidth : undefined
+ }
+ }))
+ })
+
+ return this.rows[this.rows.length - 1]
+ }
+
+ _colFromString (text) {
+ return {
+ text,
+ padding: this._measurePadding(text)
+ }
+ }
+
+ _measurePadding (str) {
+ // measure padding without ansi escape codes
+ const noAnsi = stripAnsi(str)
+ return [0, noAnsi.match(/\s*$/)[0].length, 0, noAnsi.match(/^\s*/)[0].length]
+ }
+
+ toString () {
+ const lines = []
+
+ this.rows.forEach(row => {
+ this.rowToString(row, lines)
+ })
+
+ // don't display any lines with the
+ // hidden flag set.
+ return lines
+ .filter(line => !line.hidden)
+ .map(line => line.text)
+ .join('\n')
+ }
+
+ rowToString (row, lines) {
+ this._rasterize(row).forEach((rrow, r) => {
+ let str = ''
+ rrow.forEach((col, c) => {
+ const { width } = row[c] // the width with padding.
+ const wrapWidth = this._negatePadding(row[c]) // the width without padding.
+
+ let ts = col // temporary string used during alignment/padding.
+
+ if (wrapWidth > stringWidth(col)) {
+ ts += ' '.repeat(wrapWidth - stringWidth(col))
+ }
+
+ // align the string within its column.
+ if (row[c].align && row[c].align !== 'left' && this.wrap) {
+ ts = align[row[c].align](ts, wrapWidth)
+ if (stringWidth(ts) < wrapWidth) {
+ ts += ' '.repeat(width - stringWidth(ts) - 1)
+ }
+ }
+
+ // apply border and padding to string.
+ const padding = row[c].padding || [0, 0, 0, 0]
+ if (padding[left]) {
+ str += ' '.repeat(padding[left])
+ }
+
+ str += addBorder(row[c], ts, '| ')
+ str += ts
+ str += addBorder(row[c], ts, ' |')
+ if (padding[right]) {
+ str += ' '.repeat(padding[right])
+ }
+
+ // if prior row is span, try to render the
+ // current row on the prior line.
+ if (r === 0 && lines.length > 0) {
+ str = this._renderInline(str, lines[lines.length - 1])
+ }
+ })
+
+ // remove trailing whitespace.
+ lines.push({
+ text: str.replace(/ +$/, ''),
+ span: row.span
+ })
+ })
+
+ return lines
+ }
+
+ // if the full 'source' can render in
+ // the target line, do so.
+ _renderInline (source, previousLine) {
+ const leadingWhitespace = source.match(/^ */)[0].length
+ const target = previousLine.text
+ const targetTextWidth = stringWidth(target.trimRight())
+
+ if (!previousLine.span) {
+ return source
+ }
+
+ // if we're not applying wrapping logic,
+ // just always append to the span.
+ if (!this.wrap) {
+ previousLine.hidden = true
+ return target + source
+ }
+
+ if (leadingWhitespace < targetTextWidth) {
+ return source
+ }
+
+ previousLine.hidden = true
+
+ return target.trimRight() + ' '.repeat(leadingWhitespace - targetTextWidth) + source.trimLeft()
+ }
+
+ _rasterize (row) {
+ const rrows = []
+ const widths = this._columnWidths(row)
+ let wrapped
+
+ // word wrap all columns, and create
+ // a data-structure that is easy to rasterize.
+ row.forEach((col, c) => {
+ // leave room for left and right padding.
+ col.width = widths[c]
+ if (this.wrap) {
+ wrapped = wrap(col.text, this._negatePadding(col), { hard: true }).split('\n')
+ } else {
+ wrapped = col.text.split('\n')
+ }
+
+ if (col.border) {
+ wrapped.unshift('.' + '-'.repeat(this._negatePadding(col) + 2) + '.')
+ wrapped.push("'" + '-'.repeat(this._negatePadding(col) + 2) + "'")
+ }
+
+ // add top and bottom padding.
+ if (col.padding) {
+ wrapped.unshift(...new Array(col.padding[top] || 0).fill(''))
+ wrapped.push(...new Array(col.padding[bottom] || 0).fill(''))
+ }
+
+ wrapped.forEach((str, r) => {
+ if (!rrows[r]) {
+ rrows.push([])
+ }
+
+ const rrow = rrows[r]
+
+ for (let i = 0; i < c; i++) {
+ if (rrow[i] === undefined) {
+ rrow.push('')
+ }
+ }
+
+ rrow.push(str)
+ })
+ })
+
+ return rrows
+ }
+
+ _negatePadding (col) {
+ let wrapWidth = col.width
+ if (col.padding) {
+ wrapWidth -= (col.padding[left] || 0) + (col.padding[right] || 0)
+ }
+
+ if (col.border) {
+ wrapWidth -= 4
+ }
+
+ return wrapWidth
+ }
+
+ _columnWidths (row) {
+ if (!this.wrap) {
+ return row.map(col => {
+ return col.width || stringWidth(col.text)
+ })
+ }
+
+ let unset = row.length
+ let remainingWidth = this.width
+
+ // column widths can be set in config.
+ const widths = row.map(col => {
+ if (col.width) {
+ unset--
+ remainingWidth -= col.width
+ return col.width
+ }
+
+ return undefined
+ })
+
+ // any unset widths should be calculated.
+ const unsetWidth = unset ? Math.floor(remainingWidth / unset) : 0
+
+ return widths.map((w, i) => {
+ if (w === undefined) {
+ return Math.max(unsetWidth, _minWidth(row[i]))
+ }
+
+ return w
+ })
+ }
+}
+
+function addBorder (col, ts, style) {
+ if (col.border) {
+ if (/[.']-+[.']/.test(ts)) {
+ return ''
+ }
+
+ if (ts.trim().length !== 0) {
+ return style
+ }
+
+ return ' '
+ }
+
+ return ''
+}
+
+// calculates the minimum width of
+// a column, based on padding preferences.
+function _minWidth (col) {
+ const padding = col.padding || []
+ const minWidth = 1 + (padding[left] || 0) + (padding[right] || 0)
+ if (col.border) {
+ return minWidth + 4
+ }
+
+ return minWidth
+}
+
+function getWindowWidth () {
+ /* istanbul ignore next: depends on terminal */
+ if (typeof process === 'object' && process.stdout && process.stdout.columns) {
+ return process.stdout.columns
+ }
+}
+
+function alignRight (str, width) {
+ str = str.trim()
+ const strWidth = stringWidth(str)
+
+ if (strWidth < width) {
+ return ' '.repeat(width - strWidth) + str
+ }
+
+ return str
+}
+
+function alignCenter (str, width) {
+ str = str.trim()
+ const strWidth = stringWidth(str)
+
+ /* istanbul ignore next */
+ if (strWidth >= width) {
+ return str
+ }
+
+ return ' '.repeat((width - strWidth) >> 1) + str
+}
+
+module.exports = function (opts = {}) {
+ return new UI({
+ width: opts.width || getWindowWidth() || /* istanbul ignore next */ 80,
+ wrap: opts.wrap !== false
+ })
+}
diff --git a/backend/node_modules/cliui/package.json b/backend/node_modules/cliui/package.json
new file mode 100644
index 0000000..f92fd10
--- /dev/null
+++ b/backend/node_modules/cliui/package.json
@@ -0,0 +1,65 @@
+{
+ "name": "cliui",
+ "version": "6.0.0",
+ "description": "easily create complex multi-column command-line-interfaces",
+ "main": "index.js",
+ "scripts": {
+ "pretest": "standard",
+ "test": "nyc mocha",
+ "coverage": "nyc --reporter=text-lcov mocha | coveralls"
+ },
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/yargs/cliui.git"
+ },
+ "config": {
+ "blanket": {
+ "pattern": [
+ "index.js"
+ ],
+ "data-cover-never": [
+ "node_modules",
+ "test"
+ ],
+ "output-reporter": "spec"
+ }
+ },
+ "standard": {
+ "ignore": [
+ "**/example/**"
+ ],
+ "globals": [
+ "it"
+ ]
+ },
+ "keywords": [
+ "cli",
+ "command-line",
+ "layout",
+ "design",
+ "console",
+ "wrap",
+ "table"
+ ],
+ "author": "Ben Coe ",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ },
+ "devDependencies": {
+ "chai": "^4.2.0",
+ "chalk": "^3.0.0",
+ "coveralls": "^3.0.3",
+ "mocha": "^6.2.2",
+ "nyc": "^14.1.1",
+ "standard": "^12.0.1"
+ },
+ "files": [
+ "index.js"
+ ],
+ "engine": {
+ "node": ">=8"
+ }
+}
diff --git a/backend/node_modules/color-convert/CHANGELOG.md b/backend/node_modules/color-convert/CHANGELOG.md
new file mode 100644
index 0000000..0a7bce4
--- /dev/null
+++ b/backend/node_modules/color-convert/CHANGELOG.md
@@ -0,0 +1,54 @@
+# 1.0.0 - 2016-01-07
+
+- Removed: unused speed test
+- Added: Automatic routing between previously unsupported conversions
+([#27](https://github.com/Qix-/color-convert/pull/27))
+- Removed: `xxx2xxx()` and `xxx2xxxRaw()` functions
+([#27](https://github.com/Qix-/color-convert/pull/27))
+- Removed: `convert()` class
+([#27](https://github.com/Qix-/color-convert/pull/27))
+- Changed: all functions to lookup dictionary
+([#27](https://github.com/Qix-/color-convert/pull/27))
+- Changed: `ansi` to `ansi256`
+([#27](https://github.com/Qix-/color-convert/pull/27))
+- Fixed: argument grouping for functions requiring only one argument
+([#27](https://github.com/Qix-/color-convert/pull/27))
+
+# 0.6.0 - 2015-07-23
+
+- Added: methods to handle
+[ANSI](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) 16/256 colors:
+ - rgb2ansi16
+ - rgb2ansi
+ - hsl2ansi16
+ - hsl2ansi
+ - hsv2ansi16
+ - hsv2ansi
+ - hwb2ansi16
+ - hwb2ansi
+ - cmyk2ansi16
+ - cmyk2ansi
+ - keyword2ansi16
+ - keyword2ansi
+ - ansi162rgb
+ - ansi162hsl
+ - ansi162hsv
+ - ansi162hwb
+ - ansi162cmyk
+ - ansi162keyword
+ - ansi2rgb
+ - ansi2hsl
+ - ansi2hsv
+ - ansi2hwb
+ - ansi2cmyk
+ - ansi2keyword
+([#18](https://github.com/harthur/color-convert/pull/18))
+
+# 0.5.3 - 2015-06-02
+
+- Fixed: hsl2hsv does not return `NaN` anymore when using `[0,0,0]`
+([#15](https://github.com/harthur/color-convert/issues/15))
+
+---
+
+Check out commit logs for older releases
diff --git a/backend/node_modules/color-convert/LICENSE b/backend/node_modules/color-convert/LICENSE
new file mode 100644
index 0000000..5b4c386
--- /dev/null
+++ b/backend/node_modules/color-convert/LICENSE
@@ -0,0 +1,21 @@
+Copyright (c) 2011-2016 Heather Arthur
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/backend/node_modules/color-convert/README.md b/backend/node_modules/color-convert/README.md
new file mode 100644
index 0000000..d4b08fc
--- /dev/null
+++ b/backend/node_modules/color-convert/README.md
@@ -0,0 +1,68 @@
+# color-convert
+
+[](https://travis-ci.org/Qix-/color-convert)
+
+Color-convert is a color conversion library for JavaScript and node.
+It converts all ways between `rgb`, `hsl`, `hsv`, `hwb`, `cmyk`, `ansi`, `ansi16`, `hex` strings, and CSS `keyword`s (will round to closest):
+
+```js
+var convert = require('color-convert');
+
+convert.rgb.hsl(140, 200, 100); // [96, 48, 59]
+convert.keyword.rgb('blue'); // [0, 0, 255]
+
+var rgbChannels = convert.rgb.channels; // 3
+var cmykChannels = convert.cmyk.channels; // 4
+var ansiChannels = convert.ansi16.channels; // 1
+```
+
+# Install
+
+```console
+$ npm install color-convert
+```
+
+# API
+
+Simply get the property of the _from_ and _to_ conversion that you're looking for.
+
+All functions have a rounded and unrounded variant. By default, return values are rounded. To get the unrounded (raw) results, simply tack on `.raw` to the function.
+
+All 'from' functions have a hidden property called `.channels` that indicates the number of channels the function expects (not including alpha).
+
+```js
+var convert = require('color-convert');
+
+// Hex to LAB
+convert.hex.lab('DEADBF'); // [ 76, 21, -2 ]
+convert.hex.lab.raw('DEADBF'); // [ 75.56213190997677, 20.653827952644754, -2.290532499330533 ]
+
+// RGB to CMYK
+convert.rgb.cmyk(167, 255, 4); // [ 35, 0, 98, 0 ]
+convert.rgb.cmyk.raw(167, 255, 4); // [ 34.509803921568626, 0, 98.43137254901961, 0 ]
+```
+
+### Arrays
+All functions that accept multiple arguments also support passing an array.
+
+Note that this does **not** apply to functions that convert from a color that only requires one value (e.g. `keyword`, `ansi256`, `hex`, etc.)
+
+```js
+var convert = require('color-convert');
+
+convert.rgb.hex(123, 45, 67); // '7B2D43'
+convert.rgb.hex([123, 45, 67]); // '7B2D43'
+```
+
+## Routing
+
+Conversions that don't have an _explicitly_ defined conversion (in [conversions.js](conversions.js)), but can be converted by means of sub-conversions (e.g. XYZ -> **RGB** -> CMYK), are automatically routed together. This allows just about any color model supported by `color-convert` to be converted to any other model, so long as a sub-conversion path exists. This is also true for conversions requiring more than one step in between (e.g. LCH -> **LAB** -> **XYZ** -> **RGB** -> Hex).
+
+Keep in mind that extensive conversions _may_ result in a loss of precision, and exist only to be complete. For a list of "direct" (single-step) conversions, see [conversions.js](conversions.js).
+
+# Contribute
+
+If there is a new model you would like to support, or want to add a direct conversion between two existing models, please send us a pull request.
+
+# License
+Copyright © 2011-2016, Heather Arthur and Josh Junon. Licensed under the [MIT License](LICENSE).
diff --git a/backend/node_modules/color-convert/conversions.js b/backend/node_modules/color-convert/conversions.js
new file mode 100644
index 0000000..2657f26
--- /dev/null
+++ b/backend/node_modules/color-convert/conversions.js
@@ -0,0 +1,839 @@
+/* MIT license */
+/* eslint-disable no-mixed-operators */
+const cssKeywords = require('color-name');
+
+// NOTE: conversions should only return primitive values (i.e. arrays, or
+// values that give correct `typeof` results).
+// do not use box values types (i.e. Number(), String(), etc.)
+
+const reverseKeywords = {};
+for (const key of Object.keys(cssKeywords)) {
+ reverseKeywords[cssKeywords[key]] = key;
+}
+
+const convert = {
+ rgb: {channels: 3, labels: 'rgb'},
+ hsl: {channels: 3, labels: 'hsl'},
+ hsv: {channels: 3, labels: 'hsv'},
+ hwb: {channels: 3, labels: 'hwb'},
+ cmyk: {channels: 4, labels: 'cmyk'},
+ xyz: {channels: 3, labels: 'xyz'},
+ lab: {channels: 3, labels: 'lab'},
+ lch: {channels: 3, labels: 'lch'},
+ hex: {channels: 1, labels: ['hex']},
+ keyword: {channels: 1, labels: ['keyword']},
+ ansi16: {channels: 1, labels: ['ansi16']},
+ ansi256: {channels: 1, labels: ['ansi256']},
+ hcg: {channels: 3, labels: ['h', 'c', 'g']},
+ apple: {channels: 3, labels: ['r16', 'g16', 'b16']},
+ gray: {channels: 1, labels: ['gray']}
+};
+
+module.exports = convert;
+
+// Hide .channels and .labels properties
+for (const model of Object.keys(convert)) {
+ if (!('channels' in convert[model])) {
+ throw new Error('missing channels property: ' + model);
+ }
+
+ if (!('labels' in convert[model])) {
+ throw new Error('missing channel labels property: ' + model);
+ }
+
+ if (convert[model].labels.length !== convert[model].channels) {
+ throw new Error('channel and label counts mismatch: ' + model);
+ }
+
+ const {channels, labels} = convert[model];
+ delete convert[model].channels;
+ delete convert[model].labels;
+ Object.defineProperty(convert[model], 'channels', {value: channels});
+ Object.defineProperty(convert[model], 'labels', {value: labels});
+}
+
+convert.rgb.hsl = function (rgb) {
+ const r = rgb[0] / 255;
+ const g = rgb[1] / 255;
+ const b = rgb[2] / 255;
+ const min = Math.min(r, g, b);
+ const max = Math.max(r, g, b);
+ const delta = max - min;
+ let h;
+ let s;
+
+ if (max === min) {
+ h = 0;
+ } else if (r === max) {
+ h = (g - b) / delta;
+ } else if (g === max) {
+ h = 2 + (b - r) / delta;
+ } else if (b === max) {
+ h = 4 + (r - g) / delta;
+ }
+
+ h = Math.min(h * 60, 360);
+
+ if (h < 0) {
+ h += 360;
+ }
+
+ const l = (min + max) / 2;
+
+ if (max === min) {
+ s = 0;
+ } else if (l <= 0.5) {
+ s = delta / (max + min);
+ } else {
+ s = delta / (2 - max - min);
+ }
+
+ return [h, s * 100, l * 100];
+};
+
+convert.rgb.hsv = function (rgb) {
+ let rdif;
+ let gdif;
+ let bdif;
+ let h;
+ let s;
+
+ const r = rgb[0] / 255;
+ const g = rgb[1] / 255;
+ const b = rgb[2] / 255;
+ const v = Math.max(r, g, b);
+ const diff = v - Math.min(r, g, b);
+ const diffc = function (c) {
+ return (v - c) / 6 / diff + 1 / 2;
+ };
+
+ if (diff === 0) {
+ h = 0;
+ s = 0;
+ } else {
+ s = diff / v;
+ rdif = diffc(r);
+ gdif = diffc(g);
+ bdif = diffc(b);
+
+ if (r === v) {
+ h = bdif - gdif;
+ } else if (g === v) {
+ h = (1 / 3) + rdif - bdif;
+ } else if (b === v) {
+ h = (2 / 3) + gdif - rdif;
+ }
+
+ if (h < 0) {
+ h += 1;
+ } else if (h > 1) {
+ h -= 1;
+ }
+ }
+
+ return [
+ h * 360,
+ s * 100,
+ v * 100
+ ];
+};
+
+convert.rgb.hwb = function (rgb) {
+ const r = rgb[0];
+ const g = rgb[1];
+ let b = rgb[2];
+ const h = convert.rgb.hsl(rgb)[0];
+ const w = 1 / 255 * Math.min(r, Math.min(g, b));
+
+ b = 1 - 1 / 255 * Math.max(r, Math.max(g, b));
+
+ return [h, w * 100, b * 100];
+};
+
+convert.rgb.cmyk = function (rgb) {
+ const r = rgb[0] / 255;
+ const g = rgb[1] / 255;
+ const b = rgb[2] / 255;
+
+ const k = Math.min(1 - r, 1 - g, 1 - b);
+ const c = (1 - r - k) / (1 - k) || 0;
+ const m = (1 - g - k) / (1 - k) || 0;
+ const y = (1 - b - k) / (1 - k) || 0;
+
+ return [c * 100, m * 100, y * 100, k * 100];
+};
+
+function comparativeDistance(x, y) {
+ /*
+ See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance
+ */
+ return (
+ ((x[0] - y[0]) ** 2) +
+ ((x[1] - y[1]) ** 2) +
+ ((x[2] - y[2]) ** 2)
+ );
+}
+
+convert.rgb.keyword = function (rgb) {
+ const reversed = reverseKeywords[rgb];
+ if (reversed) {
+ return reversed;
+ }
+
+ let currentClosestDistance = Infinity;
+ let currentClosestKeyword;
+
+ for (const keyword of Object.keys(cssKeywords)) {
+ const value = cssKeywords[keyword];
+
+ // Compute comparative distance
+ const distance = comparativeDistance(rgb, value);
+
+ // Check if its less, if so set as closest
+ if (distance < currentClosestDistance) {
+ currentClosestDistance = distance;
+ currentClosestKeyword = keyword;
+ }
+ }
+
+ return currentClosestKeyword;
+};
+
+convert.keyword.rgb = function (keyword) {
+ return cssKeywords[keyword];
+};
+
+convert.rgb.xyz = function (rgb) {
+ let r = rgb[0] / 255;
+ let g = rgb[1] / 255;
+ let b = rgb[2] / 255;
+
+ // Assume sRGB
+ r = r > 0.04045 ? (((r + 0.055) / 1.055) ** 2.4) : (r / 12.92);
+ g = g > 0.04045 ? (((g + 0.055) / 1.055) ** 2.4) : (g / 12.92);
+ b = b > 0.04045 ? (((b + 0.055) / 1.055) ** 2.4) : (b / 12.92);
+
+ const x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);
+ const y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);
+ const z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);
+
+ return [x * 100, y * 100, z * 100];
+};
+
+convert.rgb.lab = function (rgb) {
+ const xyz = convert.rgb.xyz(rgb);
+ let x = xyz[0];
+ let y = xyz[1];
+ let z = xyz[2];
+
+ x /= 95.047;
+ y /= 100;
+ z /= 108.883;
+
+ x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116);
+ y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116);
+ z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116);
+
+ const l = (116 * y) - 16;
+ const a = 500 * (x - y);
+ const b = 200 * (y - z);
+
+ return [l, a, b];
+};
+
+convert.hsl.rgb = function (hsl) {
+ const h = hsl[0] / 360;
+ const s = hsl[1] / 100;
+ const l = hsl[2] / 100;
+ let t2;
+ let t3;
+ let val;
+
+ if (s === 0) {
+ val = l * 255;
+ return [val, val, val];
+ }
+
+ if (l < 0.5) {
+ t2 = l * (1 + s);
+ } else {
+ t2 = l + s - l * s;
+ }
+
+ const t1 = 2 * l - t2;
+
+ const rgb = [0, 0, 0];
+ for (let i = 0; i < 3; i++) {
+ t3 = h + 1 / 3 * -(i - 1);
+ if (t3 < 0) {
+ t3++;
+ }
+
+ if (t3 > 1) {
+ t3--;
+ }
+
+ if (6 * t3 < 1) {
+ val = t1 + (t2 - t1) * 6 * t3;
+ } else if (2 * t3 < 1) {
+ val = t2;
+ } else if (3 * t3 < 2) {
+ val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
+ } else {
+ val = t1;
+ }
+
+ rgb[i] = val * 255;
+ }
+
+ return rgb;
+};
+
+convert.hsl.hsv = function (hsl) {
+ const h = hsl[0];
+ let s = hsl[1] / 100;
+ let l = hsl[2] / 100;
+ let smin = s;
+ const lmin = Math.max(l, 0.01);
+
+ l *= 2;
+ s *= (l <= 1) ? l : 2 - l;
+ smin *= lmin <= 1 ? lmin : 2 - lmin;
+ const v = (l + s) / 2;
+ const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s);
+
+ return [h, sv * 100, v * 100];
+};
+
+convert.hsv.rgb = function (hsv) {
+ const h = hsv[0] / 60;
+ const s = hsv[1] / 100;
+ let v = hsv[2] / 100;
+ const hi = Math.floor(h) % 6;
+
+ const f = h - Math.floor(h);
+ const p = 255 * v * (1 - s);
+ const q = 255 * v * (1 - (s * f));
+ const t = 255 * v * (1 - (s * (1 - f)));
+ v *= 255;
+
+ switch (hi) {
+ case 0:
+ return [v, t, p];
+ case 1:
+ return [q, v, p];
+ case 2:
+ return [p, v, t];
+ case 3:
+ return [p, q, v];
+ case 4:
+ return [t, p, v];
+ case 5:
+ return [v, p, q];
+ }
+};
+
+convert.hsv.hsl = function (hsv) {
+ const h = hsv[0];
+ const s = hsv[1] / 100;
+ const v = hsv[2] / 100;
+ const vmin = Math.max(v, 0.01);
+ let sl;
+ let l;
+
+ l = (2 - s) * v;
+ const lmin = (2 - s) * vmin;
+ sl = s * vmin;
+ sl /= (lmin <= 1) ? lmin : 2 - lmin;
+ sl = sl || 0;
+ l /= 2;
+
+ return [h, sl * 100, l * 100];
+};
+
+// http://dev.w3.org/csswg/css-color/#hwb-to-rgb
+convert.hwb.rgb = function (hwb) {
+ const h = hwb[0] / 360;
+ let wh = hwb[1] / 100;
+ let bl = hwb[2] / 100;
+ const ratio = wh + bl;
+ let f;
+
+ // Wh + bl cant be > 1
+ if (ratio > 1) {
+ wh /= ratio;
+ bl /= ratio;
+ }
+
+ const i = Math.floor(6 * h);
+ const v = 1 - bl;
+ f = 6 * h - i;
+
+ if ((i & 0x01) !== 0) {
+ f = 1 - f;
+ }
+
+ const n = wh + f * (v - wh); // Linear interpolation
+
+ let r;
+ let g;
+ let b;
+ /* eslint-disable max-statements-per-line,no-multi-spaces */
+ switch (i) {
+ default:
+ case 6:
+ case 0: r = v; g = n; b = wh; break;
+ case 1: r = n; g = v; b = wh; break;
+ case 2: r = wh; g = v; b = n; break;
+ case 3: r = wh; g = n; b = v; break;
+ case 4: r = n; g = wh; b = v; break;
+ case 5: r = v; g = wh; b = n; break;
+ }
+ /* eslint-enable max-statements-per-line,no-multi-spaces */
+
+ return [r * 255, g * 255, b * 255];
+};
+
+convert.cmyk.rgb = function (cmyk) {
+ const c = cmyk[0] / 100;
+ const m = cmyk[1] / 100;
+ const y = cmyk[2] / 100;
+ const k = cmyk[3] / 100;
+
+ const r = 1 - Math.min(1, c * (1 - k) + k);
+ const g = 1 - Math.min(1, m * (1 - k) + k);
+ const b = 1 - Math.min(1, y * (1 - k) + k);
+
+ return [r * 255, g * 255, b * 255];
+};
+
+convert.xyz.rgb = function (xyz) {
+ const x = xyz[0] / 100;
+ const y = xyz[1] / 100;
+ const z = xyz[2] / 100;
+ let r;
+ let g;
+ let b;
+
+ r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986);
+ g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415);
+ b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570);
+
+ // Assume sRGB
+ r = r > 0.0031308
+ ? ((1.055 * (r ** (1.0 / 2.4))) - 0.055)
+ : r * 12.92;
+
+ g = g > 0.0031308
+ ? ((1.055 * (g ** (1.0 / 2.4))) - 0.055)
+ : g * 12.92;
+
+ b = b > 0.0031308
+ ? ((1.055 * (b ** (1.0 / 2.4))) - 0.055)
+ : b * 12.92;
+
+ r = Math.min(Math.max(0, r), 1);
+ g = Math.min(Math.max(0, g), 1);
+ b = Math.min(Math.max(0, b), 1);
+
+ return [r * 255, g * 255, b * 255];
+};
+
+convert.xyz.lab = function (xyz) {
+ let x = xyz[0];
+ let y = xyz[1];
+ let z = xyz[2];
+
+ x /= 95.047;
+ y /= 100;
+ z /= 108.883;
+
+ x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116);
+ y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116);
+ z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116);
+
+ const l = (116 * y) - 16;
+ const a = 500 * (x - y);
+ const b = 200 * (y - z);
+
+ return [l, a, b];
+};
+
+convert.lab.xyz = function (lab) {
+ const l = lab[0];
+ const a = lab[1];
+ const b = lab[2];
+ let x;
+ let y;
+ let z;
+
+ y = (l + 16) / 116;
+ x = a / 500 + y;
+ z = y - b / 200;
+
+ const y2 = y ** 3;
+ const x2 = x ** 3;
+ const z2 = z ** 3;
+ y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787;
+ x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787;
+ z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787;
+
+ x *= 95.047;
+ y *= 100;
+ z *= 108.883;
+
+ return [x, y, z];
+};
+
+convert.lab.lch = function (lab) {
+ const l = lab[0];
+ const a = lab[1];
+ const b = lab[2];
+ let h;
+
+ const hr = Math.atan2(b, a);
+ h = hr * 360 / 2 / Math.PI;
+
+ if (h < 0) {
+ h += 360;
+ }
+
+ const c = Math.sqrt(a * a + b * b);
+
+ return [l, c, h];
+};
+
+convert.lch.lab = function (lch) {
+ const l = lch[0];
+ const c = lch[1];
+ const h = lch[2];
+
+ const hr = h / 360 * 2 * Math.PI;
+ const a = c * Math.cos(hr);
+ const b = c * Math.sin(hr);
+
+ return [l, a, b];
+};
+
+convert.rgb.ansi16 = function (args, saturation = null) {
+ const [r, g, b] = args;
+ let value = saturation === null ? convert.rgb.hsv(args)[2] : saturation; // Hsv -> ansi16 optimization
+
+ value = Math.round(value / 50);
+
+ if (value === 0) {
+ return 30;
+ }
+
+ let ansi = 30
+ + ((Math.round(b / 255) << 2)
+ | (Math.round(g / 255) << 1)
+ | Math.round(r / 255));
+
+ if (value === 2) {
+ ansi += 60;
+ }
+
+ return ansi;
+};
+
+convert.hsv.ansi16 = function (args) {
+ // Optimization here; we already know the value and don't need to get
+ // it converted for us.
+ return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]);
+};
+
+convert.rgb.ansi256 = function (args) {
+ const r = args[0];
+ const g = args[1];
+ const b = args[2];
+
+ // We use the extended greyscale palette here, with the exception of
+ // black and white. normal palette only has 4 greyscale shades.
+ if (r === g && g === b) {
+ if (r < 8) {
+ return 16;
+ }
+
+ if (r > 248) {
+ return 231;
+ }
+
+ return Math.round(((r - 8) / 247) * 24) + 232;
+ }
+
+ const ansi = 16
+ + (36 * Math.round(r / 255 * 5))
+ + (6 * Math.round(g / 255 * 5))
+ + Math.round(b / 255 * 5);
+
+ return ansi;
+};
+
+convert.ansi16.rgb = function (args) {
+ let color = args % 10;
+
+ // Handle greyscale
+ if (color === 0 || color === 7) {
+ if (args > 50) {
+ color += 3.5;
+ }
+
+ color = color / 10.5 * 255;
+
+ return [color, color, color];
+ }
+
+ const mult = (~~(args > 50) + 1) * 0.5;
+ const r = ((color & 1) * mult) * 255;
+ const g = (((color >> 1) & 1) * mult) * 255;
+ const b = (((color >> 2) & 1) * mult) * 255;
+
+ return [r, g, b];
+};
+
+convert.ansi256.rgb = function (args) {
+ // Handle greyscale
+ if (args >= 232) {
+ const c = (args - 232) * 10 + 8;
+ return [c, c, c];
+ }
+
+ args -= 16;
+
+ let rem;
+ const r = Math.floor(args / 36) / 5 * 255;
+ const g = Math.floor((rem = args % 36) / 6) / 5 * 255;
+ const b = (rem % 6) / 5 * 255;
+
+ return [r, g, b];
+};
+
+convert.rgb.hex = function (args) {
+ const integer = ((Math.round(args[0]) & 0xFF) << 16)
+ + ((Math.round(args[1]) & 0xFF) << 8)
+ + (Math.round(args[2]) & 0xFF);
+
+ const string = integer.toString(16).toUpperCase();
+ return '000000'.substring(string.length) + string;
+};
+
+convert.hex.rgb = function (args) {
+ const match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);
+ if (!match) {
+ return [0, 0, 0];
+ }
+
+ let colorString = match[0];
+
+ if (match[0].length === 3) {
+ colorString = colorString.split('').map(char => {
+ return char + char;
+ }).join('');
+ }
+
+ const integer = parseInt(colorString, 16);
+ const r = (integer >> 16) & 0xFF;
+ const g = (integer >> 8) & 0xFF;
+ const b = integer & 0xFF;
+
+ return [r, g, b];
+};
+
+convert.rgb.hcg = function (rgb) {
+ const r = rgb[0] / 255;
+ const g = rgb[1] / 255;
+ const b = rgb[2] / 255;
+ const max = Math.max(Math.max(r, g), b);
+ const min = Math.min(Math.min(r, g), b);
+ const chroma = (max - min);
+ let grayscale;
+ let hue;
+
+ if (chroma < 1) {
+ grayscale = min / (1 - chroma);
+ } else {
+ grayscale = 0;
+ }
+
+ if (chroma <= 0) {
+ hue = 0;
+ } else
+ if (max === r) {
+ hue = ((g - b) / chroma) % 6;
+ } else
+ if (max === g) {
+ hue = 2 + (b - r) / chroma;
+ } else {
+ hue = 4 + (r - g) / chroma;
+ }
+
+ hue /= 6;
+ hue %= 1;
+
+ return [hue * 360, chroma * 100, grayscale * 100];
+};
+
+convert.hsl.hcg = function (hsl) {
+ const s = hsl[1] / 100;
+ const l = hsl[2] / 100;
+
+ const c = l < 0.5 ? (2.0 * s * l) : (2.0 * s * (1.0 - l));
+
+ let f = 0;
+ if (c < 1.0) {
+ f = (l - 0.5 * c) / (1.0 - c);
+ }
+
+ return [hsl[0], c * 100, f * 100];
+};
+
+convert.hsv.hcg = function (hsv) {
+ const s = hsv[1] / 100;
+ const v = hsv[2] / 100;
+
+ const c = s * v;
+ let f = 0;
+
+ if (c < 1.0) {
+ f = (v - c) / (1 - c);
+ }
+
+ return [hsv[0], c * 100, f * 100];
+};
+
+convert.hcg.rgb = function (hcg) {
+ const h = hcg[0] / 360;
+ const c = hcg[1] / 100;
+ const g = hcg[2] / 100;
+
+ if (c === 0.0) {
+ return [g * 255, g * 255, g * 255];
+ }
+
+ const pure = [0, 0, 0];
+ const hi = (h % 1) * 6;
+ const v = hi % 1;
+ const w = 1 - v;
+ let mg = 0;
+
+ /* eslint-disable max-statements-per-line */
+ switch (Math.floor(hi)) {
+ case 0:
+ pure[0] = 1; pure[1] = v; pure[2] = 0; break;
+ case 1:
+ pure[0] = w; pure[1] = 1; pure[2] = 0; break;
+ case 2:
+ pure[0] = 0; pure[1] = 1; pure[2] = v; break;
+ case 3:
+ pure[0] = 0; pure[1] = w; pure[2] = 1; break;
+ case 4:
+ pure[0] = v; pure[1] = 0; pure[2] = 1; break;
+ default:
+ pure[0] = 1; pure[1] = 0; pure[2] = w;
+ }
+ /* eslint-enable max-statements-per-line */
+
+ mg = (1.0 - c) * g;
+
+ return [
+ (c * pure[0] + mg) * 255,
+ (c * pure[1] + mg) * 255,
+ (c * pure[2] + mg) * 255
+ ];
+};
+
+convert.hcg.hsv = function (hcg) {
+ const c = hcg[1] / 100;
+ const g = hcg[2] / 100;
+
+ const v = c + g * (1.0 - c);
+ let f = 0;
+
+ if (v > 0.0) {
+ f = c / v;
+ }
+
+ return [hcg[0], f * 100, v * 100];
+};
+
+convert.hcg.hsl = function (hcg) {
+ const c = hcg[1] / 100;
+ const g = hcg[2] / 100;
+
+ const l = g * (1.0 - c) + 0.5 * c;
+ let s = 0;
+
+ if (l > 0.0 && l < 0.5) {
+ s = c / (2 * l);
+ } else
+ if (l >= 0.5 && l < 1.0) {
+ s = c / (2 * (1 - l));
+ }
+
+ return [hcg[0], s * 100, l * 100];
+};
+
+convert.hcg.hwb = function (hcg) {
+ const c = hcg[1] / 100;
+ const g = hcg[2] / 100;
+ const v = c + g * (1.0 - c);
+ return [hcg[0], (v - c) * 100, (1 - v) * 100];
+};
+
+convert.hwb.hcg = function (hwb) {
+ const w = hwb[1] / 100;
+ const b = hwb[2] / 100;
+ const v = 1 - b;
+ const c = v - w;
+ let g = 0;
+
+ if (c < 1) {
+ g = (v - c) / (1 - c);
+ }
+
+ return [hwb[0], c * 100, g * 100];
+};
+
+convert.apple.rgb = function (apple) {
+ return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255];
+};
+
+convert.rgb.apple = function (rgb) {
+ return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535];
+};
+
+convert.gray.rgb = function (args) {
+ return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255];
+};
+
+convert.gray.hsl = function (args) {
+ return [0, 0, args[0]];
+};
+
+convert.gray.hsv = convert.gray.hsl;
+
+convert.gray.hwb = function (gray) {
+ return [0, 100, gray[0]];
+};
+
+convert.gray.cmyk = function (gray) {
+ return [0, 0, 0, gray[0]];
+};
+
+convert.gray.lab = function (gray) {
+ return [gray[0], 0, 0];
+};
+
+convert.gray.hex = function (gray) {
+ const val = Math.round(gray[0] / 100 * 255) & 0xFF;
+ const integer = (val << 16) + (val << 8) + val;
+
+ const string = integer.toString(16).toUpperCase();
+ return '000000'.substring(string.length) + string;
+};
+
+convert.rgb.gray = function (rgb) {
+ const val = (rgb[0] + rgb[1] + rgb[2]) / 3;
+ return [val / 255 * 100];
+};
diff --git a/backend/node_modules/color-convert/index.js b/backend/node_modules/color-convert/index.js
new file mode 100644
index 0000000..b648e57
--- /dev/null
+++ b/backend/node_modules/color-convert/index.js
@@ -0,0 +1,81 @@
+const conversions = require('./conversions');
+const route = require('./route');
+
+const convert = {};
+
+const models = Object.keys(conversions);
+
+function wrapRaw(fn) {
+ const wrappedFn = function (...args) {
+ const arg0 = args[0];
+ if (arg0 === undefined || arg0 === null) {
+ return arg0;
+ }
+
+ if (arg0.length > 1) {
+ args = arg0;
+ }
+
+ return fn(args);
+ };
+
+ // Preserve .conversion property if there is one
+ if ('conversion' in fn) {
+ wrappedFn.conversion = fn.conversion;
+ }
+
+ return wrappedFn;
+}
+
+function wrapRounded(fn) {
+ const wrappedFn = function (...args) {
+ const arg0 = args[0];
+
+ if (arg0 === undefined || arg0 === null) {
+ return arg0;
+ }
+
+ if (arg0.length > 1) {
+ args = arg0;
+ }
+
+ const result = fn(args);
+
+ // We're assuming the result is an array here.
+ // see notice in conversions.js; don't use box types
+ // in conversion functions.
+ if (typeof result === 'object') {
+ for (let len = result.length, i = 0; i < len; i++) {
+ result[i] = Math.round(result[i]);
+ }
+ }
+
+ return result;
+ };
+
+ // Preserve .conversion property if there is one
+ if ('conversion' in fn) {
+ wrappedFn.conversion = fn.conversion;
+ }
+
+ return wrappedFn;
+}
+
+models.forEach(fromModel => {
+ convert[fromModel] = {};
+
+ Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels});
+ Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels});
+
+ const routes = route(fromModel);
+ const routeModels = Object.keys(routes);
+
+ routeModels.forEach(toModel => {
+ const fn = routes[toModel];
+
+ convert[fromModel][toModel] = wrapRounded(fn);
+ convert[fromModel][toModel].raw = wrapRaw(fn);
+ });
+});
+
+module.exports = convert;
diff --git a/backend/node_modules/color-convert/package.json b/backend/node_modules/color-convert/package.json
new file mode 100644
index 0000000..6e48000
--- /dev/null
+++ b/backend/node_modules/color-convert/package.json
@@ -0,0 +1,48 @@
+{
+ "name": "color-convert",
+ "description": "Plain color conversion functions",
+ "version": "2.0.1",
+ "author": "Heather Arthur ",
+ "license": "MIT",
+ "repository": "Qix-/color-convert",
+ "scripts": {
+ "pretest": "xo",
+ "test": "node test/basic.js"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ },
+ "keywords": [
+ "color",
+ "colour",
+ "convert",
+ "converter",
+ "conversion",
+ "rgb",
+ "hsl",
+ "hsv",
+ "hwb",
+ "cmyk",
+ "ansi",
+ "ansi16"
+ ],
+ "files": [
+ "index.js",
+ "conversions.js",
+ "route.js"
+ ],
+ "xo": {
+ "rules": {
+ "default-case": 0,
+ "no-inline-comments": 0,
+ "operator-linebreak": 0
+ }
+ },
+ "devDependencies": {
+ "chalk": "^2.4.2",
+ "xo": "^0.24.0"
+ },
+ "dependencies": {
+ "color-name": "~1.1.4"
+ }
+}
diff --git a/backend/node_modules/color-convert/route.js b/backend/node_modules/color-convert/route.js
new file mode 100644
index 0000000..1a08521
--- /dev/null
+++ b/backend/node_modules/color-convert/route.js
@@ -0,0 +1,97 @@
+const conversions = require('./conversions');
+
+/*
+ This function routes a model to all other models.
+
+ all functions that are routed have a property `.conversion` attached
+ to the returned synthetic function. This property is an array
+ of strings, each with the steps in between the 'from' and 'to'
+ color models (inclusive).
+
+ conversions that are not possible simply are not included.
+*/
+
+function buildGraph() {
+ const graph = {};
+ // https://jsperf.com/object-keys-vs-for-in-with-closure/3
+ const models = Object.keys(conversions);
+
+ for (let len = models.length, i = 0; i < len; i++) {
+ graph[models[i]] = {
+ // http://jsperf.com/1-vs-infinity
+ // micro-opt, but this is simple.
+ distance: -1,
+ parent: null
+ };
+ }
+
+ return graph;
+}
+
+// https://en.wikipedia.org/wiki/Breadth-first_search
+function deriveBFS(fromModel) {
+ const graph = buildGraph();
+ const queue = [fromModel]; // Unshift -> queue -> pop
+
+ graph[fromModel].distance = 0;
+
+ while (queue.length) {
+ const current = queue.pop();
+ const adjacents = Object.keys(conversions[current]);
+
+ for (let len = adjacents.length, i = 0; i < len; i++) {
+ const adjacent = adjacents[i];
+ const node = graph[adjacent];
+
+ if (node.distance === -1) {
+ node.distance = graph[current].distance + 1;
+ node.parent = current;
+ queue.unshift(adjacent);
+ }
+ }
+ }
+
+ return graph;
+}
+
+function link(from, to) {
+ return function (args) {
+ return to(from(args));
+ };
+}
+
+function wrapConversion(toModel, graph) {
+ const path = [graph[toModel].parent, toModel];
+ let fn = conversions[graph[toModel].parent][toModel];
+
+ let cur = graph[toModel].parent;
+ while (graph[cur].parent) {
+ path.unshift(graph[cur].parent);
+ fn = link(conversions[graph[cur].parent][cur], fn);
+ cur = graph[cur].parent;
+ }
+
+ fn.conversion = path;
+ return fn;
+}
+
+module.exports = function (fromModel) {
+ const graph = deriveBFS(fromModel);
+ const conversion = {};
+
+ const models = Object.keys(graph);
+ for (let len = models.length, i = 0; i < len; i++) {
+ const toModel = models[i];
+ const node = graph[toModel];
+
+ if (node.parent === null) {
+ // No possible conversion, or this node is the source model.
+ continue;
+ }
+
+ conversion[toModel] = wrapConversion(toModel, graph);
+ }
+
+ return conversion;
+};
+
diff --git a/backend/node_modules/color-name/LICENSE b/backend/node_modules/color-name/LICENSE
new file mode 100644
index 0000000..4d9802a
--- /dev/null
+++ b/backend/node_modules/color-name/LICENSE
@@ -0,0 +1,8 @@
+The MIT License (MIT)
+Copyright (c) 2015 Dmitry Ivanov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/backend/node_modules/color-name/README.md b/backend/node_modules/color-name/README.md
new file mode 100644
index 0000000..3611a6b
--- /dev/null
+++ b/backend/node_modules/color-name/README.md
@@ -0,0 +1,11 @@
+A JSON with color names and its values. Based on http://dev.w3.org/csswg/css-color/#named-colors.
+
+[](https://nodei.co/npm/color-name/)
+
+
+```js
+var colors = require('color-name');
+colors.red //[255,0,0]
+```
+
+
diff --git a/backend/node_modules/color-name/index.js b/backend/node_modules/color-name/index.js
new file mode 100644
index 0000000..e42aa68
--- /dev/null
+++ b/backend/node_modules/color-name/index.js
@@ -0,0 +1,152 @@
+'use strict'
+
+module.exports = {
+ "aliceblue": [240, 248, 255],
+ "antiquewhite": [250, 235, 215],
+ "aqua": [0, 255, 255],
+ "aquamarine": [127, 255, 212],
+ "azure": [240, 255, 255],
+ "beige": [245, 245, 220],
+ "bisque": [255, 228, 196],
+ "black": [0, 0, 0],
+ "blanchedalmond": [255, 235, 205],
+ "blue": [0, 0, 255],
+ "blueviolet": [138, 43, 226],
+ "brown": [165, 42, 42],
+ "burlywood": [222, 184, 135],
+ "cadetblue": [95, 158, 160],
+ "chartreuse": [127, 255, 0],
+ "chocolate": [210, 105, 30],
+ "coral": [255, 127, 80],
+ "cornflowerblue": [100, 149, 237],
+ "cornsilk": [255, 248, 220],
+ "crimson": [220, 20, 60],
+ "cyan": [0, 255, 255],
+ "darkblue": [0, 0, 139],
+ "darkcyan": [0, 139, 139],
+ "darkgoldenrod": [184, 134, 11],
+ "darkgray": [169, 169, 169],
+ "darkgreen": [0, 100, 0],
+ "darkgrey": [169, 169, 169],
+ "darkkhaki": [189, 183, 107],
+ "darkmagenta": [139, 0, 139],
+ "darkolivegreen": [85, 107, 47],
+ "darkorange": [255, 140, 0],
+ "darkorchid": [153, 50, 204],
+ "darkred": [139, 0, 0],
+ "darksalmon": [233, 150, 122],
+ "darkseagreen": [143, 188, 143],
+ "darkslateblue": [72, 61, 139],
+ "darkslategray": [47, 79, 79],
+ "darkslategrey": [47, 79, 79],
+ "darkturquoise": [0, 206, 209],
+ "darkviolet": [148, 0, 211],
+ "deeppink": [255, 20, 147],
+ "deepskyblue": [0, 191, 255],
+ "dimgray": [105, 105, 105],
+ "dimgrey": [105, 105, 105],
+ "dodgerblue": [30, 144, 255],
+ "firebrick": [178, 34, 34],
+ "floralwhite": [255, 250, 240],
+ "forestgreen": [34, 139, 34],
+ "fuchsia": [255, 0, 255],
+ "gainsboro": [220, 220, 220],
+ "ghostwhite": [248, 248, 255],
+ "gold": [255, 215, 0],
+ "goldenrod": [218, 165, 32],
+ "gray": [128, 128, 128],
+ "green": [0, 128, 0],
+ "greenyellow": [173, 255, 47],
+ "grey": [128, 128, 128],
+ "honeydew": [240, 255, 240],
+ "hotpink": [255, 105, 180],
+ "indianred": [205, 92, 92],
+ "indigo": [75, 0, 130],
+ "ivory": [255, 255, 240],
+ "khaki": [240, 230, 140],
+ "lavender": [230, 230, 250],
+ "lavenderblush": [255, 240, 245],
+ "lawngreen": [124, 252, 0],
+ "lemonchiffon": [255, 250, 205],
+ "lightblue": [173, 216, 230],
+ "lightcoral": [240, 128, 128],
+ "lightcyan": [224, 255, 255],
+ "lightgoldenrodyellow": [250, 250, 210],
+ "lightgray": [211, 211, 211],
+ "lightgreen": [144, 238, 144],
+ "lightgrey": [211, 211, 211],
+ "lightpink": [255, 182, 193],
+ "lightsalmon": [255, 160, 122],
+ "lightseagreen": [32, 178, 170],
+ "lightskyblue": [135, 206, 250],
+ "lightslategray": [119, 136, 153],
+ "lightslategrey": [119, 136, 153],
+ "lightsteelblue": [176, 196, 222],
+ "lightyellow": [255, 255, 224],
+ "lime": [0, 255, 0],
+ "limegreen": [50, 205, 50],
+ "linen": [250, 240, 230],
+ "magenta": [255, 0, 255],
+ "maroon": [128, 0, 0],
+ "mediumaquamarine": [102, 205, 170],
+ "mediumblue": [0, 0, 205],
+ "mediumorchid": [186, 85, 211],
+ "mediumpurple": [147, 112, 219],
+ "mediumseagreen": [60, 179, 113],
+ "mediumslateblue": [123, 104, 238],
+ "mediumspringgreen": [0, 250, 154],
+ "mediumturquoise": [72, 209, 204],
+ "mediumvioletred": [199, 21, 133],
+ "midnightblue": [25, 25, 112],
+ "mintcream": [245, 255, 250],
+ "mistyrose": [255, 228, 225],
+ "moccasin": [255, 228, 181],
+ "navajowhite": [255, 222, 173],
+ "navy": [0, 0, 128],
+ "oldlace": [253, 245, 230],
+ "olive": [128, 128, 0],
+ "olivedrab": [107, 142, 35],
+ "orange": [255, 165, 0],
+ "orangered": [255, 69, 0],
+ "orchid": [218, 112, 214],
+ "palegoldenrod": [238, 232, 170],
+ "palegreen": [152, 251, 152],
+ "paleturquoise": [175, 238, 238],
+ "palevioletred": [219, 112, 147],
+ "papayawhip": [255, 239, 213],
+ "peachpuff": [255, 218, 185],
+ "peru": [205, 133, 63],
+ "pink": [255, 192, 203],
+ "plum": [221, 160, 221],
+ "powderblue": [176, 224, 230],
+ "purple": [128, 0, 128],
+ "rebeccapurple": [102, 51, 153],
+ "red": [255, 0, 0],
+ "rosybrown": [188, 143, 143],
+ "royalblue": [65, 105, 225],
+ "saddlebrown": [139, 69, 19],
+ "salmon": [250, 128, 114],
+ "sandybrown": [244, 164, 96],
+ "seagreen": [46, 139, 87],
+ "seashell": [255, 245, 238],
+ "sienna": [160, 82, 45],
+ "silver": [192, 192, 192],
+ "skyblue": [135, 206, 235],
+ "slateblue": [106, 90, 205],
+ "slategray": [112, 128, 144],
+ "slategrey": [112, 128, 144],
+ "snow": [255, 250, 250],
+ "springgreen": [0, 255, 127],
+ "steelblue": [70, 130, 180],
+ "tan": [210, 180, 140],
+ "teal": [0, 128, 128],
+ "thistle": [216, 191, 216],
+ "tomato": [255, 99, 71],
+ "turquoise": [64, 224, 208],
+ "violet": [238, 130, 238],
+ "wheat": [245, 222, 179],
+ "white": [255, 255, 255],
+ "whitesmoke": [245, 245, 245],
+ "yellow": [255, 255, 0],
+ "yellowgreen": [154, 205, 50]
+};
diff --git a/backend/node_modules/color-name/package.json b/backend/node_modules/color-name/package.json
new file mode 100644
index 0000000..7acc902
--- /dev/null
+++ b/backend/node_modules/color-name/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "color-name",
+ "version": "1.1.4",
+ "description": "A list of color names and its values",
+ "main": "index.js",
+ "files": [
+ "index.js"
+ ],
+ "scripts": {
+ "test": "node test.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git@github.com:colorjs/color-name.git"
+ },
+ "keywords": [
+ "color-name",
+ "color",
+ "color-keyword",
+ "keyword"
+ ],
+ "author": "DY ",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/colorjs/color-name/issues"
+ },
+ "homepage": "https://github.com/colorjs/color-name"
+}
diff --git a/backend/node_modules/decamelize/index.js b/backend/node_modules/decamelize/index.js
new file mode 100644
index 0000000..8d5bab7
--- /dev/null
+++ b/backend/node_modules/decamelize/index.js
@@ -0,0 +1,13 @@
+'use strict';
+module.exports = function (str, sep) {
+ if (typeof str !== 'string') {
+ throw new TypeError('Expected a string');
+ }
+
+ sep = typeof sep === 'undefined' ? '_' : sep;
+
+ return str
+ .replace(/([a-z\d])([A-Z])/g, '$1' + sep + '$2')
+ .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + sep + '$2')
+ .toLowerCase();
+};
diff --git a/backend/node_modules/decamelize/license b/backend/node_modules/decamelize/license
new file mode 100644
index 0000000..654d0bf
--- /dev/null
+++ b/backend/node_modules/decamelize/license
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Sindre Sorhus (sindresorhus.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/backend/node_modules/decamelize/package.json b/backend/node_modules/decamelize/package.json
new file mode 100644
index 0000000..ca35790
--- /dev/null
+++ b/backend/node_modules/decamelize/package.json
@@ -0,0 +1,38 @@
+{
+ "name": "decamelize",
+ "version": "1.2.0",
+ "description": "Convert a camelized string into a lowercased one with a custom separator: unicornRainbow → unicorn_rainbow",
+ "license": "MIT",
+ "repository": "sindresorhus/decamelize",
+ "author": {
+ "name": "Sindre Sorhus",
+ "email": "sindresorhus@gmail.com",
+ "url": "sindresorhus.com"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "scripts": {
+ "test": "xo && ava"
+ },
+ "files": [
+ "index.js"
+ ],
+ "keywords": [
+ "decamelize",
+ "decamelcase",
+ "camelcase",
+ "lowercase",
+ "case",
+ "dash",
+ "hyphen",
+ "string",
+ "str",
+ "text",
+ "convert"
+ ],
+ "devDependencies": {
+ "ava": "*",
+ "xo": "*"
+ }
+}
diff --git a/backend/node_modules/decamelize/readme.md b/backend/node_modules/decamelize/readme.md
new file mode 100644
index 0000000..624c7ee
--- /dev/null
+++ b/backend/node_modules/decamelize/readme.md
@@ -0,0 +1,48 @@
+# decamelize [](https://travis-ci.org/sindresorhus/decamelize)
+
+> Convert a camelized string into a lowercased one with a custom separator
+> Example: `unicornRainbow` → `unicorn_rainbow`
+
+
+## Install
+
+```
+$ npm install --save decamelize
+```
+
+
+## Usage
+
+```js
+const decamelize = require('decamelize');
+
+decamelize('unicornRainbow');
+//=> 'unicorn_rainbow'
+
+decamelize('unicornRainbow', '-');
+//=> 'unicorn-rainbow'
+```
+
+
+## API
+
+### decamelize(input, [separator])
+
+#### input
+
+Type: `string`
+
+#### separator
+
+Type: `string`
+Default: `_`
+
+
+## Related
+
+See [`camelcase`](https://github.com/sindresorhus/camelcase) for the inverse.
+
+
+## License
+
+MIT © [Sindre Sorhus](https://sindresorhus.com)
diff --git a/backend/node_modules/emoji-regex/LICENSE-MIT.txt b/backend/node_modules/emoji-regex/LICENSE-MIT.txt
new file mode 100644
index 0000000..a41e0a7
--- /dev/null
+++ b/backend/node_modules/emoji-regex/LICENSE-MIT.txt
@@ -0,0 +1,20 @@
+Copyright Mathias Bynens
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/backend/node_modules/emoji-regex/README.md b/backend/node_modules/emoji-regex/README.md
new file mode 100644
index 0000000..f10e173
--- /dev/null
+++ b/backend/node_modules/emoji-regex/README.md
@@ -0,0 +1,73 @@
+# emoji-regex [](https://travis-ci.org/mathiasbynens/emoji-regex)
+
+_emoji-regex_ offers a regular expression to match all emoji symbols (including textual representations of emoji) as per the Unicode Standard.
+
+This repository contains a script that generates this regular expression based on [the data from Unicode v12](https://github.com/mathiasbynens/unicode-12.0.0). Because of this, the regular expression can easily be updated whenever new emoji are added to the Unicode standard.
+
+## Installation
+
+Via [npm](https://www.npmjs.com/):
+
+```bash
+npm install emoji-regex
+```
+
+In [Node.js](https://nodejs.org/):
+
+```js
+const emojiRegex = require('emoji-regex');
+// Note: because the regular expression has the global flag set, this module
+// exports a function that returns the regex rather than exporting the regular
+// expression itself, to make it impossible to (accidentally) mutate the
+// original regular expression.
+
+const text = `
+\u{231A}: ⌚ default emoji presentation character (Emoji_Presentation)
+\u{2194}\u{FE0F}: ↔️ default text presentation character rendered as emoji
+\u{1F469}: 👩 emoji modifier base (Emoji_Modifier_Base)
+\u{1F469}\u{1F3FF}: 👩🏿 emoji modifier base followed by a modifier
+`;
+
+const regex = emojiRegex();
+let match;
+while (match = regex.exec(text)) {
+ const emoji = match[0];
+ console.log(`Matched sequence ${ emoji } — code points: ${ [...emoji].length }`);
+}
+```
+
+Console output:
+
+```
+Matched sequence ⌚ — code points: 1
+Matched sequence ⌚ — code points: 1
+Matched sequence ↔️ — code points: 2
+Matched sequence ↔️ — code points: 2
+Matched sequence 👩 — code points: 1
+Matched sequence 👩 — code points: 1
+Matched sequence 👩🏿 — code points: 2
+Matched sequence 👩🏿 — code points: 2
+```
+
+To match emoji in their textual representation as well (i.e. emoji that are not `Emoji_Presentation` symbols and that aren’t forced to render as emoji by a variation selector), `require` the other regex:
+
+```js
+const emojiRegex = require('emoji-regex/text.js');
+```
+
+Additionally, in environments which support ES2015 Unicode escapes, you may `require` ES2015-style versions of the regexes:
+
+```js
+const emojiRegex = require('emoji-regex/es2015/index.js');
+const emojiRegexText = require('emoji-regex/es2015/text.js');
+```
+
+## Author
+
+| [](https://twitter.com/mathias "Follow @mathias on Twitter") |
+|---|
+| [Mathias Bynens](https://mathiasbynens.be/) |
+
+## License
+
+_emoji-regex_ is available under the [MIT](https://mths.be/mit) license.
diff --git a/backend/node_modules/emoji-regex/es2015/index.js b/backend/node_modules/emoji-regex/es2015/index.js
new file mode 100644
index 0000000..b4cf3dc
--- /dev/null
+++ b/backend/node_modules/emoji-regex/es2015/index.js
@@ -0,0 +1,6 @@
+"use strict";
+
+module.exports = () => {
+ // https://mths.be/emoji
+ return /\u{1F3F4}\u{E0067}\u{E0062}(?:\u{E0065}\u{E006E}\u{E0067}|\u{E0073}\u{E0063}\u{E0074}|\u{E0077}\u{E006C}\u{E0073})\u{E007F}|\u{1F468}(?:\u{1F3FC}\u200D(?:\u{1F91D}\u200D\u{1F468}\u{1F3FB}|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FF}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}-\u{1F3FE}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FE}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}-\u{1F3FD}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FD}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}\u{1F3FC}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u200D(?:\u2764\uFE0F\u200D(?:\u{1F48B}\u200D)?\u{1F468}|[\u{1F468}\u{1F469}]\u200D(?:\u{1F466}\u200D\u{1F466}|\u{1F467}\u200D[\u{1F466}\u{1F467}])|\u{1F466}\u200D\u{1F466}|\u{1F467}\u200D[\u{1F466}\u{1F467}]|[\u{1F468}\u{1F469}]\u200D[\u{1F466}\u{1F467}]|[\u2695\u2696\u2708]\uFE0F|[\u{1F466}\u{1F467}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|(?:\u{1F3FB}\u200D[\u2695\u2696\u2708]|\u{1F3FF}\u200D[\u2695\u2696\u2708]|\u{1F3FE}\u200D[\u2695\u2696\u2708]|\u{1F3FD}\u200D[\u2695\u2696\u2708]|\u{1F3FC}\u200D[\u2695\u2696\u2708])\uFE0F|\u{1F3FB}\u200D[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}]|[\u{1F3FB}-\u{1F3FF}])|(?:\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}|\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F469})\u{1F3FB}|\u{1F9D1}(?:\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}[\u{1F3FB}-\u{1F3FF}]|\u200D\u{1F91D}\u200D\u{1F9D1})|(?:\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}|\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D[\u{1F468}\u{1F469}])[\u{1F3FB}-\u{1F3FE}]|(?:\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}|\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469})[\u{1F3FB}\u{1F3FC}]|\u{1F469}(?:\u{1F3FE}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}-\u{1F3FD}\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FC}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}\u{1F3FD}-\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FB}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FC}-\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FD}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}\u{1F3FC}\u{1F3FE}\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u200D(?:\u2764\uFE0F\u200D(?:\u{1F48B}\u200D[\u{1F468}\u{1F469}]|[\u{1F468}\u{1F469}])|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FF}\u200D[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F469}\u200D\u{1F469}\u200D(?:\u{1F466}\u200D\u{1F466}|\u{1F467}\u200D[\u{1F466}\u{1F467}])|(?:\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}|\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469})[\u{1F3FB}-\u{1F3FD}]|\u{1F469}\u200D\u{1F466}\u200D\u{1F466}|\u{1F469}\u200D\u{1F469}\u200D[\u{1F466}\u{1F467}]|(?:\u{1F441}\uFE0F\u200D\u{1F5E8}|\u{1F469}(?:\u{1F3FF}\u200D[\u2695\u2696\u2708]|\u{1F3FE}\u200D[\u2695\u2696\u2708]|\u{1F3FC}\u200D[\u2695\u2696\u2708]|\u{1F3FB}\u200D[\u2695\u2696\u2708]|\u{1F3FD}\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|(?:[\u26F9\u{1F3CB}\u{1F3CC}\u{1F575}]\uFE0F|[\u{1F46F}\u{1F93C}\u{1F9DE}\u{1F9DF}])\u200D[\u2640\u2642]|[\u26F9\u{1F3CB}\u{1F3CC}\u{1F575}][\u{1F3FB}-\u{1F3FF}]\u200D[\u2640\u2642]|[\u{1F3C3}\u{1F3C4}\u{1F3CA}\u{1F46E}\u{1F471}\u{1F473}\u{1F477}\u{1F481}\u{1F482}\u{1F486}\u{1F487}\u{1F645}-\u{1F647}\u{1F64B}\u{1F64D}\u{1F64E}\u{1F6A3}\u{1F6B4}-\u{1F6B6}\u{1F926}\u{1F937}-\u{1F939}\u{1F93D}\u{1F93E}\u{1F9B8}\u{1F9B9}\u{1F9CD}-\u{1F9CF}\u{1F9D6}-\u{1F9DD}](?:[\u{1F3FB}-\u{1F3FF}]\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\u{1F3F4}\u200D\u2620)\uFE0F|\u{1F469}\u200D\u{1F467}\u200D[\u{1F466}\u{1F467}]|\u{1F3F3}\uFE0F\u200D\u{1F308}|\u{1F415}\u200D\u{1F9BA}|\u{1F469}\u200D\u{1F466}|\u{1F469}\u200D\u{1F467}|\u{1F1FD}\u{1F1F0}|\u{1F1F4}\u{1F1F2}|\u{1F1F6}\u{1F1E6}|[#\*0-9]\uFE0F\u20E3|\u{1F1E7}[\u{1F1E6}\u{1F1E7}\u{1F1E9}-\u{1F1EF}\u{1F1F1}-\u{1F1F4}\u{1F1F6}-\u{1F1F9}\u{1F1FB}\u{1F1FC}\u{1F1FE}\u{1F1FF}]|\u{1F1F9}[\u{1F1E6}\u{1F1E8}\u{1F1E9}\u{1F1EB}-\u{1F1ED}\u{1F1EF}-\u{1F1F4}\u{1F1F7}\u{1F1F9}\u{1F1FB}\u{1F1FC}\u{1F1FF}]|\u{1F1EA}[\u{1F1E6}\u{1F1E8}\u{1F1EA}\u{1F1EC}\u{1F1ED}\u{1F1F7}-\u{1F1FA}]|\u{1F9D1}[\u{1F3FB}-\u{1F3FF}]|\u{1F1F7}[\u{1F1EA}\u{1F1F4}\u{1F1F8}\u{1F1FA}\u{1F1FC}]|\u{1F469}[\u{1F3FB}-\u{1F3FF}]|\u{1F1F2}[\u{1F1E6}\u{1F1E8}-\u{1F1ED}\u{1F1F0}-\u{1F1FF}]|\u{1F1E6}[\u{1F1E8}-\u{1F1EC}\u{1F1EE}\u{1F1F1}\u{1F1F2}\u{1F1F4}\u{1F1F6}-\u{1F1FA}\u{1F1FC}\u{1F1FD}\u{1F1FF}]|\u{1F1F0}[\u{1F1EA}\u{1F1EC}-\u{1F1EE}\u{1F1F2}\u{1F1F3}\u{1F1F5}\u{1F1F7}\u{1F1FC}\u{1F1FE}\u{1F1FF}]|\u{1F1ED}[\u{1F1F0}\u{1F1F2}\u{1F1F3}\u{1F1F7}\u{1F1F9}\u{1F1FA}]|\u{1F1E9}[\u{1F1EA}\u{1F1EC}\u{1F1EF}\u{1F1F0}\u{1F1F2}\u{1F1F4}\u{1F1FF}]|\u{1F1FE}[\u{1F1EA}\u{1F1F9}]|\u{1F1EC}[\u{1F1E6}\u{1F1E7}\u{1F1E9}-\u{1F1EE}\u{1F1F1}-\u{1F1F3}\u{1F1F5}-\u{1F1FA}\u{1F1FC}\u{1F1FE}]|\u{1F1F8}[\u{1F1E6}-\u{1F1EA}\u{1F1EC}-\u{1F1F4}\u{1F1F7}-\u{1F1F9}\u{1F1FB}\u{1F1FD}-\u{1F1FF}]|\u{1F1EB}[\u{1F1EE}-\u{1F1F0}\u{1F1F2}\u{1F1F4}\u{1F1F7}]|\u{1F1F5}[\u{1F1E6}\u{1F1EA}-\u{1F1ED}\u{1F1F0}-\u{1F1F3}\u{1F1F7}-\u{1F1F9}\u{1F1FC}\u{1F1FE}]|\u{1F1FB}[\u{1F1E6}\u{1F1E8}\u{1F1EA}\u{1F1EC}\u{1F1EE}\u{1F1F3}\u{1F1FA}]|\u{1F1F3}[\u{1F1E6}\u{1F1E8}\u{1F1EA}-\u{1F1EC}\u{1F1EE}\u{1F1F1}\u{1F1F4}\u{1F1F5}\u{1F1F7}\u{1F1FA}\u{1F1FF}]|\u{1F1E8}[\u{1F1E6}\u{1F1E8}\u{1F1E9}\u{1F1EB}-\u{1F1EE}\u{1F1F0}-\u{1F1F5}\u{1F1F7}\u{1F1FA}-\u{1F1FF}]|\u{1F1F1}[\u{1F1E6}-\u{1F1E8}\u{1F1EE}\u{1F1F0}\u{1F1F7}-\u{1F1FB}\u{1F1FE}]|\u{1F1FF}[\u{1F1E6}\u{1F1F2}\u{1F1FC}]|\u{1F1FC}[\u{1F1EB}\u{1F1F8}]|\u{1F1FA}[\u{1F1E6}\u{1F1EC}\u{1F1F2}\u{1F1F3}\u{1F1F8}\u{1F1FE}\u{1F1FF}]|\u{1F1EE}[\u{1F1E8}-\u{1F1EA}\u{1F1F1}-\u{1F1F4}\u{1F1F6}-\u{1F1F9}]|\u{1F1EF}[\u{1F1EA}\u{1F1F2}\u{1F1F4}\u{1F1F5}]|[\u{1F3C3}\u{1F3C4}\u{1F3CA}\u{1F46E}\u{1F471}\u{1F473}\u{1F477}\u{1F481}\u{1F482}\u{1F486}\u{1F487}\u{1F645}-\u{1F647}\u{1F64B}\u{1F64D}\u{1F64E}\u{1F6A3}\u{1F6B4}-\u{1F6B6}\u{1F926}\u{1F937}-\u{1F939}\u{1F93D}\u{1F93E}\u{1F9B8}\u{1F9B9}\u{1F9CD}-\u{1F9CF}\u{1F9D6}-\u{1F9DD}][\u{1F3FB}-\u{1F3FF}]|[\u26F9\u{1F3CB}\u{1F3CC}\u{1F575}][\u{1F3FB}-\u{1F3FF}]|[\u261D\u270A-\u270D\u{1F385}\u{1F3C2}\u{1F3C7}\u{1F442}\u{1F443}\u{1F446}-\u{1F450}\u{1F466}\u{1F467}\u{1F46B}-\u{1F46D}\u{1F470}\u{1F472}\u{1F474}-\u{1F476}\u{1F478}\u{1F47C}\u{1F483}\u{1F485}\u{1F4AA}\u{1F574}\u{1F57A}\u{1F590}\u{1F595}\u{1F596}\u{1F64C}\u{1F64F}\u{1F6C0}\u{1F6CC}\u{1F90F}\u{1F918}-\u{1F91C}\u{1F91E}\u{1F91F}\u{1F930}-\u{1F936}\u{1F9B5}\u{1F9B6}\u{1F9BB}\u{1F9D2}-\u{1F9D5}][\u{1F3FB}-\u{1F3FF}]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55\u{1F004}\u{1F0CF}\u{1F18E}\u{1F191}-\u{1F19A}\u{1F1E6}-\u{1F1FF}\u{1F201}\u{1F21A}\u{1F22F}\u{1F232}-\u{1F236}\u{1F238}-\u{1F23A}\u{1F250}\u{1F251}\u{1F300}-\u{1F320}\u{1F32D}-\u{1F335}\u{1F337}-\u{1F37C}\u{1F37E}-\u{1F393}\u{1F3A0}-\u{1F3CA}\u{1F3CF}-\u{1F3D3}\u{1F3E0}-\u{1F3F0}\u{1F3F4}\u{1F3F8}-\u{1F43E}\u{1F440}\u{1F442}-\u{1F4FC}\u{1F4FF}-\u{1F53D}\u{1F54B}-\u{1F54E}\u{1F550}-\u{1F567}\u{1F57A}\u{1F595}\u{1F596}\u{1F5A4}\u{1F5FB}-\u{1F64F}\u{1F680}-\u{1F6C5}\u{1F6CC}\u{1F6D0}-\u{1F6D2}\u{1F6D5}\u{1F6EB}\u{1F6EC}\u{1F6F4}-\u{1F6FA}\u{1F7E0}-\u{1F7EB}\u{1F90D}-\u{1F93A}\u{1F93C}-\u{1F945}\u{1F947}-\u{1F971}\u{1F973}-\u{1F976}\u{1F97A}-\u{1F9A2}\u{1F9A5}-\u{1F9AA}\u{1F9AE}-\u{1F9CA}\u{1F9CD}-\u{1F9FF}\u{1FA70}-\u{1FA73}\u{1FA78}-\u{1FA7A}\u{1FA80}-\u{1FA82}\u{1FA90}-\u{1FA95}]|[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299\u{1F004}\u{1F0CF}\u{1F170}\u{1F171}\u{1F17E}\u{1F17F}\u{1F18E}\u{1F191}-\u{1F19A}\u{1F1E6}-\u{1F1FF}\u{1F201}\u{1F202}\u{1F21A}\u{1F22F}\u{1F232}-\u{1F23A}\u{1F250}\u{1F251}\u{1F300}-\u{1F321}\u{1F324}-\u{1F393}\u{1F396}\u{1F397}\u{1F399}-\u{1F39B}\u{1F39E}-\u{1F3F0}\u{1F3F3}-\u{1F3F5}\u{1F3F7}-\u{1F4FD}\u{1F4FF}-\u{1F53D}\u{1F549}-\u{1F54E}\u{1F550}-\u{1F567}\u{1F56F}\u{1F570}\u{1F573}-\u{1F57A}\u{1F587}\u{1F58A}-\u{1F58D}\u{1F590}\u{1F595}\u{1F596}\u{1F5A4}\u{1F5A5}\u{1F5A8}\u{1F5B1}\u{1F5B2}\u{1F5BC}\u{1F5C2}-\u{1F5C4}\u{1F5D1}-\u{1F5D3}\u{1F5DC}-\u{1F5DE}\u{1F5E1}\u{1F5E3}\u{1F5E8}\u{1F5EF}\u{1F5F3}\u{1F5FA}-\u{1F64F}\u{1F680}-\u{1F6C5}\u{1F6CB}-\u{1F6D2}\u{1F6D5}\u{1F6E0}-\u{1F6E5}\u{1F6E9}\u{1F6EB}\u{1F6EC}\u{1F6F0}\u{1F6F3}-\u{1F6FA}\u{1F7E0}-\u{1F7EB}\u{1F90D}-\u{1F93A}\u{1F93C}-\u{1F945}\u{1F947}-\u{1F971}\u{1F973}-\u{1F976}\u{1F97A}-\u{1F9A2}\u{1F9A5}-\u{1F9AA}\u{1F9AE}-\u{1F9CA}\u{1F9CD}-\u{1F9FF}\u{1FA70}-\u{1FA73}\u{1FA78}-\u{1FA7A}\u{1FA80}-\u{1FA82}\u{1FA90}-\u{1FA95}]\uFE0F|[\u261D\u26F9\u270A-\u270D\u{1F385}\u{1F3C2}-\u{1F3C4}\u{1F3C7}\u{1F3CA}-\u{1F3CC}\u{1F442}\u{1F443}\u{1F446}-\u{1F450}\u{1F466}-\u{1F478}\u{1F47C}\u{1F481}-\u{1F483}\u{1F485}-\u{1F487}\u{1F48F}\u{1F491}\u{1F4AA}\u{1F574}\u{1F575}\u{1F57A}\u{1F590}\u{1F595}\u{1F596}\u{1F645}-\u{1F647}\u{1F64B}-\u{1F64F}\u{1F6A3}\u{1F6B4}-\u{1F6B6}\u{1F6C0}\u{1F6CC}\u{1F90F}\u{1F918}-\u{1F91F}\u{1F926}\u{1F930}-\u{1F939}\u{1F93C}-\u{1F93E}\u{1F9B5}\u{1F9B6}\u{1F9B8}\u{1F9B9}\u{1F9BB}\u{1F9CD}-\u{1F9CF}\u{1F9D1}-\u{1F9DD}]/gu;
+};
diff --git a/backend/node_modules/emoji-regex/es2015/text.js b/backend/node_modules/emoji-regex/es2015/text.js
new file mode 100644
index 0000000..780309d
--- /dev/null
+++ b/backend/node_modules/emoji-regex/es2015/text.js
@@ -0,0 +1,6 @@
+"use strict";
+
+module.exports = () => {
+ // https://mths.be/emoji
+ return /\u{1F3F4}\u{E0067}\u{E0062}(?:\u{E0065}\u{E006E}\u{E0067}|\u{E0073}\u{E0063}\u{E0074}|\u{E0077}\u{E006C}\u{E0073})\u{E007F}|\u{1F468}(?:\u{1F3FC}\u200D(?:\u{1F91D}\u200D\u{1F468}\u{1F3FB}|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FF}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}-\u{1F3FE}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FE}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}-\u{1F3FD}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FD}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}\u{1F3FC}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u200D(?:\u2764\uFE0F\u200D(?:\u{1F48B}\u200D)?\u{1F468}|[\u{1F468}\u{1F469}]\u200D(?:\u{1F466}\u200D\u{1F466}|\u{1F467}\u200D[\u{1F466}\u{1F467}])|\u{1F466}\u200D\u{1F466}|\u{1F467}\u200D[\u{1F466}\u{1F467}]|[\u{1F468}\u{1F469}]\u200D[\u{1F466}\u{1F467}]|[\u2695\u2696\u2708]\uFE0F|[\u{1F466}\u{1F467}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|(?:\u{1F3FB}\u200D[\u2695\u2696\u2708]|\u{1F3FF}\u200D[\u2695\u2696\u2708]|\u{1F3FE}\u200D[\u2695\u2696\u2708]|\u{1F3FD}\u200D[\u2695\u2696\u2708]|\u{1F3FC}\u200D[\u2695\u2696\u2708])\uFE0F|\u{1F3FB}\u200D[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}]|[\u{1F3FB}-\u{1F3FF}])|(?:\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}|\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F469})\u{1F3FB}|\u{1F9D1}(?:\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}[\u{1F3FB}-\u{1F3FF}]|\u200D\u{1F91D}\u200D\u{1F9D1})|(?:\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}|\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D[\u{1F468}\u{1F469}])[\u{1F3FB}-\u{1F3FE}]|(?:\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}|\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469})[\u{1F3FB}\u{1F3FC}]|\u{1F469}(?:\u{1F3FE}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}-\u{1F3FD}\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FC}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}\u{1F3FD}-\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FB}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FC}-\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FD}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}\u{1F3FC}\u{1F3FE}\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u200D(?:\u2764\uFE0F\u200D(?:\u{1F48B}\u200D[\u{1F468}\u{1F469}]|[\u{1F468}\u{1F469}])|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FF}\u200D[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F469}\u200D\u{1F469}\u200D(?:\u{1F466}\u200D\u{1F466}|\u{1F467}\u200D[\u{1F466}\u{1F467}])|(?:\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}|\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469})[\u{1F3FB}-\u{1F3FD}]|\u{1F469}\u200D\u{1F466}\u200D\u{1F466}|\u{1F469}\u200D\u{1F469}\u200D[\u{1F466}\u{1F467}]|(?:\u{1F441}\uFE0F\u200D\u{1F5E8}|\u{1F469}(?:\u{1F3FF}\u200D[\u2695\u2696\u2708]|\u{1F3FE}\u200D[\u2695\u2696\u2708]|\u{1F3FC}\u200D[\u2695\u2696\u2708]|\u{1F3FB}\u200D[\u2695\u2696\u2708]|\u{1F3FD}\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|(?:[\u26F9\u{1F3CB}\u{1F3CC}\u{1F575}]\uFE0F|[\u{1F46F}\u{1F93C}\u{1F9DE}\u{1F9DF}])\u200D[\u2640\u2642]|[\u26F9\u{1F3CB}\u{1F3CC}\u{1F575}][\u{1F3FB}-\u{1F3FF}]\u200D[\u2640\u2642]|[\u{1F3C3}\u{1F3C4}\u{1F3CA}\u{1F46E}\u{1F471}\u{1F473}\u{1F477}\u{1F481}\u{1F482}\u{1F486}\u{1F487}\u{1F645}-\u{1F647}\u{1F64B}\u{1F64D}\u{1F64E}\u{1F6A3}\u{1F6B4}-\u{1F6B6}\u{1F926}\u{1F937}-\u{1F939}\u{1F93D}\u{1F93E}\u{1F9B8}\u{1F9B9}\u{1F9CD}-\u{1F9CF}\u{1F9D6}-\u{1F9DD}](?:[\u{1F3FB}-\u{1F3FF}]\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\u{1F3F4}\u200D\u2620)\uFE0F|\u{1F469}\u200D\u{1F467}\u200D[\u{1F466}\u{1F467}]|\u{1F3F3}\uFE0F\u200D\u{1F308}|\u{1F415}\u200D\u{1F9BA}|\u{1F469}\u200D\u{1F466}|\u{1F469}\u200D\u{1F467}|\u{1F1FD}\u{1F1F0}|\u{1F1F4}\u{1F1F2}|\u{1F1F6}\u{1F1E6}|[#\*0-9]\uFE0F\u20E3|\u{1F1E7}[\u{1F1E6}\u{1F1E7}\u{1F1E9}-\u{1F1EF}\u{1F1F1}-\u{1F1F4}\u{1F1F6}-\u{1F1F9}\u{1F1FB}\u{1F1FC}\u{1F1FE}\u{1F1FF}]|\u{1F1F9}[\u{1F1E6}\u{1F1E8}\u{1F1E9}\u{1F1EB}-\u{1F1ED}\u{1F1EF}-\u{1F1F4}\u{1F1F7}\u{1F1F9}\u{1F1FB}\u{1F1FC}\u{1F1FF}]|\u{1F1EA}[\u{1F1E6}\u{1F1E8}\u{1F1EA}\u{1F1EC}\u{1F1ED}\u{1F1F7}-\u{1F1FA}]|\u{1F9D1}[\u{1F3FB}-\u{1F3FF}]|\u{1F1F7}[\u{1F1EA}\u{1F1F4}\u{1F1F8}\u{1F1FA}\u{1F1FC}]|\u{1F469}[\u{1F3FB}-\u{1F3FF}]|\u{1F1F2}[\u{1F1E6}\u{1F1E8}-\u{1F1ED}\u{1F1F0}-\u{1F1FF}]|\u{1F1E6}[\u{1F1E8}-\u{1F1EC}\u{1F1EE}\u{1F1F1}\u{1F1F2}\u{1F1F4}\u{1F1F6}-\u{1F1FA}\u{1F1FC}\u{1F1FD}\u{1F1FF}]|\u{1F1F0}[\u{1F1EA}\u{1F1EC}-\u{1F1EE}\u{1F1F2}\u{1F1F3}\u{1F1F5}\u{1F1F7}\u{1F1FC}\u{1F1FE}\u{1F1FF}]|\u{1F1ED}[\u{1F1F0}\u{1F1F2}\u{1F1F3}\u{1F1F7}\u{1F1F9}\u{1F1FA}]|\u{1F1E9}[\u{1F1EA}\u{1F1EC}\u{1F1EF}\u{1F1F0}\u{1F1F2}\u{1F1F4}\u{1F1FF}]|\u{1F1FE}[\u{1F1EA}\u{1F1F9}]|\u{1F1EC}[\u{1F1E6}\u{1F1E7}\u{1F1E9}-\u{1F1EE}\u{1F1F1}-\u{1F1F3}\u{1F1F5}-\u{1F1FA}\u{1F1FC}\u{1F1FE}]|\u{1F1F8}[\u{1F1E6}-\u{1F1EA}\u{1F1EC}-\u{1F1F4}\u{1F1F7}-\u{1F1F9}\u{1F1FB}\u{1F1FD}-\u{1F1FF}]|\u{1F1EB}[\u{1F1EE}-\u{1F1F0}\u{1F1F2}\u{1F1F4}\u{1F1F7}]|\u{1F1F5}[\u{1F1E6}\u{1F1EA}-\u{1F1ED}\u{1F1F0}-\u{1F1F3}\u{1F1F7}-\u{1F1F9}\u{1F1FC}\u{1F1FE}]|\u{1F1FB}[\u{1F1E6}\u{1F1E8}\u{1F1EA}\u{1F1EC}\u{1F1EE}\u{1F1F3}\u{1F1FA}]|\u{1F1F3}[\u{1F1E6}\u{1F1E8}\u{1F1EA}-\u{1F1EC}\u{1F1EE}\u{1F1F1}\u{1F1F4}\u{1F1F5}\u{1F1F7}\u{1F1FA}\u{1F1FF}]|\u{1F1E8}[\u{1F1E6}\u{1F1E8}\u{1F1E9}\u{1F1EB}-\u{1F1EE}\u{1F1F0}-\u{1F1F5}\u{1F1F7}\u{1F1FA}-\u{1F1FF}]|\u{1F1F1}[\u{1F1E6}-\u{1F1E8}\u{1F1EE}\u{1F1F0}\u{1F1F7}-\u{1F1FB}\u{1F1FE}]|\u{1F1FF}[\u{1F1E6}\u{1F1F2}\u{1F1FC}]|\u{1F1FC}[\u{1F1EB}\u{1F1F8}]|\u{1F1FA}[\u{1F1E6}\u{1F1EC}\u{1F1F2}\u{1F1F3}\u{1F1F8}\u{1F1FE}\u{1F1FF}]|\u{1F1EE}[\u{1F1E8}-\u{1F1EA}\u{1F1F1}-\u{1F1F4}\u{1F1F6}-\u{1F1F9}]|\u{1F1EF}[\u{1F1EA}\u{1F1F2}\u{1F1F4}\u{1F1F5}]|[\u{1F3C3}\u{1F3C4}\u{1F3CA}\u{1F46E}\u{1F471}\u{1F473}\u{1F477}\u{1F481}\u{1F482}\u{1F486}\u{1F487}\u{1F645}-\u{1F647}\u{1F64B}\u{1F64D}\u{1F64E}\u{1F6A3}\u{1F6B4}-\u{1F6B6}\u{1F926}\u{1F937}-\u{1F939}\u{1F93D}\u{1F93E}\u{1F9B8}\u{1F9B9}\u{1F9CD}-\u{1F9CF}\u{1F9D6}-\u{1F9DD}][\u{1F3FB}-\u{1F3FF}]|[\u26F9\u{1F3CB}\u{1F3CC}\u{1F575}][\u{1F3FB}-\u{1F3FF}]|[\u261D\u270A-\u270D\u{1F385}\u{1F3C2}\u{1F3C7}\u{1F442}\u{1F443}\u{1F446}-\u{1F450}\u{1F466}\u{1F467}\u{1F46B}-\u{1F46D}\u{1F470}\u{1F472}\u{1F474}-\u{1F476}\u{1F478}\u{1F47C}\u{1F483}\u{1F485}\u{1F4AA}\u{1F574}\u{1F57A}\u{1F590}\u{1F595}\u{1F596}\u{1F64C}\u{1F64F}\u{1F6C0}\u{1F6CC}\u{1F90F}\u{1F918}-\u{1F91C}\u{1F91E}\u{1F91F}\u{1F930}-\u{1F936}\u{1F9B5}\u{1F9B6}\u{1F9BB}\u{1F9D2}-\u{1F9D5}][\u{1F3FB}-\u{1F3FF}]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55\u{1F004}\u{1F0CF}\u{1F18E}\u{1F191}-\u{1F19A}\u{1F1E6}-\u{1F1FF}\u{1F201}\u{1F21A}\u{1F22F}\u{1F232}-\u{1F236}\u{1F238}-\u{1F23A}\u{1F250}\u{1F251}\u{1F300}-\u{1F320}\u{1F32D}-\u{1F335}\u{1F337}-\u{1F37C}\u{1F37E}-\u{1F393}\u{1F3A0}-\u{1F3CA}\u{1F3CF}-\u{1F3D3}\u{1F3E0}-\u{1F3F0}\u{1F3F4}\u{1F3F8}-\u{1F43E}\u{1F440}\u{1F442}-\u{1F4FC}\u{1F4FF}-\u{1F53D}\u{1F54B}-\u{1F54E}\u{1F550}-\u{1F567}\u{1F57A}\u{1F595}\u{1F596}\u{1F5A4}\u{1F5FB}-\u{1F64F}\u{1F680}-\u{1F6C5}\u{1F6CC}\u{1F6D0}-\u{1F6D2}\u{1F6D5}\u{1F6EB}\u{1F6EC}\u{1F6F4}-\u{1F6FA}\u{1F7E0}-\u{1F7EB}\u{1F90D}-\u{1F93A}\u{1F93C}-\u{1F945}\u{1F947}-\u{1F971}\u{1F973}-\u{1F976}\u{1F97A}-\u{1F9A2}\u{1F9A5}-\u{1F9AA}\u{1F9AE}-\u{1F9CA}\u{1F9CD}-\u{1F9FF}\u{1FA70}-\u{1FA73}\u{1FA78}-\u{1FA7A}\u{1FA80}-\u{1FA82}\u{1FA90}-\u{1FA95}]|[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299\u{1F004}\u{1F0CF}\u{1F170}\u{1F171}\u{1F17E}\u{1F17F}\u{1F18E}\u{1F191}-\u{1F19A}\u{1F1E6}-\u{1F1FF}\u{1F201}\u{1F202}\u{1F21A}\u{1F22F}\u{1F232}-\u{1F23A}\u{1F250}\u{1F251}\u{1F300}-\u{1F321}\u{1F324}-\u{1F393}\u{1F396}\u{1F397}\u{1F399}-\u{1F39B}\u{1F39E}-\u{1F3F0}\u{1F3F3}-\u{1F3F5}\u{1F3F7}-\u{1F4FD}\u{1F4FF}-\u{1F53D}\u{1F549}-\u{1F54E}\u{1F550}-\u{1F567}\u{1F56F}\u{1F570}\u{1F573}-\u{1F57A}\u{1F587}\u{1F58A}-\u{1F58D}\u{1F590}\u{1F595}\u{1F596}\u{1F5A4}\u{1F5A5}\u{1F5A8}\u{1F5B1}\u{1F5B2}\u{1F5BC}\u{1F5C2}-\u{1F5C4}\u{1F5D1}-\u{1F5D3}\u{1F5DC}-\u{1F5DE}\u{1F5E1}\u{1F5E3}\u{1F5E8}\u{1F5EF}\u{1F5F3}\u{1F5FA}-\u{1F64F}\u{1F680}-\u{1F6C5}\u{1F6CB}-\u{1F6D2}\u{1F6D5}\u{1F6E0}-\u{1F6E5}\u{1F6E9}\u{1F6EB}\u{1F6EC}\u{1F6F0}\u{1F6F3}-\u{1F6FA}\u{1F7E0}-\u{1F7EB}\u{1F90D}-\u{1F93A}\u{1F93C}-\u{1F945}\u{1F947}-\u{1F971}\u{1F973}-\u{1F976}\u{1F97A}-\u{1F9A2}\u{1F9A5}-\u{1F9AA}\u{1F9AE}-\u{1F9CA}\u{1F9CD}-\u{1F9FF}\u{1FA70}-\u{1FA73}\u{1FA78}-\u{1FA7A}\u{1FA80}-\u{1FA82}\u{1FA90}-\u{1FA95}]\uFE0F?|[\u261D\u26F9\u270A-\u270D\u{1F385}\u{1F3C2}-\u{1F3C4}\u{1F3C7}\u{1F3CA}-\u{1F3CC}\u{1F442}\u{1F443}\u{1F446}-\u{1F450}\u{1F466}-\u{1F478}\u{1F47C}\u{1F481}-\u{1F483}\u{1F485}-\u{1F487}\u{1F48F}\u{1F491}\u{1F4AA}\u{1F574}\u{1F575}\u{1F57A}\u{1F590}\u{1F595}\u{1F596}\u{1F645}-\u{1F647}\u{1F64B}-\u{1F64F}\u{1F6A3}\u{1F6B4}-\u{1F6B6}\u{1F6C0}\u{1F6CC}\u{1F90F}\u{1F918}-\u{1F91F}\u{1F926}\u{1F930}-\u{1F939}\u{1F93C}-\u{1F93E}\u{1F9B5}\u{1F9B6}\u{1F9B8}\u{1F9B9}\u{1F9BB}\u{1F9CD}-\u{1F9CF}\u{1F9D1}-\u{1F9DD}]/gu;
+};
diff --git a/backend/node_modules/emoji-regex/index.d.ts b/backend/node_modules/emoji-regex/index.d.ts
new file mode 100644
index 0000000..1955b47
--- /dev/null
+++ b/backend/node_modules/emoji-regex/index.d.ts
@@ -0,0 +1,23 @@
+declare module 'emoji-regex' {
+ function emojiRegex(): RegExp;
+
+ export default emojiRegex;
+}
+
+declare module 'emoji-regex/text' {
+ function emojiRegex(): RegExp;
+
+ export default emojiRegex;
+}
+
+declare module 'emoji-regex/es2015' {
+ function emojiRegex(): RegExp;
+
+ export default emojiRegex;
+}
+
+declare module 'emoji-regex/es2015/text' {
+ function emojiRegex(): RegExp;
+
+ export default emojiRegex;
+}
diff --git a/backend/node_modules/emoji-regex/index.js b/backend/node_modules/emoji-regex/index.js
new file mode 100644
index 0000000..d993a3a
--- /dev/null
+++ b/backend/node_modules/emoji-regex/index.js
@@ -0,0 +1,6 @@
+"use strict";
+
+module.exports = function () {
+ // https://mths.be/emoji
+ return /\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F|\uD83D\uDC68(?:\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68\uD83C\uDFFB|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|[\u2695\u2696\u2708]\uFE0F|\uD83D[\uDC66\uDC67]|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708])\uFE0F|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C[\uDFFB-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)\uD83C\uDFFB|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB\uDFFC])|\uD83D\uDC69(?:\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB-\uDFFD])|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|(?:(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)\uFE0F|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\uD83C\uDFF4\u200D\u2620)\uFE0F|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF4\uD83C\uDDF2|\uD83C\uDDF6\uD83C\uDDE6|[#\*0-9]\uFE0F\u20E3|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83D\uDC69(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270A-\u270D]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC70\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDCAA\uDD74\uDD7A\uDD90\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD36\uDDB5\uDDB6\uDDBB\uDDD2-\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5\uDEEB\uDEEC\uDEF4-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g;
+};
diff --git a/backend/node_modules/emoji-regex/package.json b/backend/node_modules/emoji-regex/package.json
new file mode 100644
index 0000000..6d32352
--- /dev/null
+++ b/backend/node_modules/emoji-regex/package.json
@@ -0,0 +1,50 @@
+{
+ "name": "emoji-regex",
+ "version": "8.0.0",
+ "description": "A regular expression to match all Emoji-only symbols as per the Unicode Standard.",
+ "homepage": "https://mths.be/emoji-regex",
+ "main": "index.js",
+ "types": "index.d.ts",
+ "keywords": [
+ "unicode",
+ "regex",
+ "regexp",
+ "regular expressions",
+ "code points",
+ "symbols",
+ "characters",
+ "emoji"
+ ],
+ "license": "MIT",
+ "author": {
+ "name": "Mathias Bynens",
+ "url": "https://mathiasbynens.be/"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/mathiasbynens/emoji-regex.git"
+ },
+ "bugs": "https://github.com/mathiasbynens/emoji-regex/issues",
+ "files": [
+ "LICENSE-MIT.txt",
+ "index.js",
+ "index.d.ts",
+ "text.js",
+ "es2015/index.js",
+ "es2015/text.js"
+ ],
+ "scripts": {
+ "build": "rm -rf -- es2015; babel src -d .; NODE_ENV=es2015 babel src -d ./es2015; node script/inject-sequences.js",
+ "test": "mocha",
+ "test:watch": "npm run test -- --watch"
+ },
+ "devDependencies": {
+ "@babel/cli": "^7.2.3",
+ "@babel/core": "^7.3.4",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.2.0",
+ "@babel/preset-env": "^7.3.4",
+ "mocha": "^6.0.2",
+ "regexgen": "^1.3.0",
+ "unicode-12.0.0": "^0.7.9"
+ }
+}
diff --git a/backend/node_modules/emoji-regex/text.js b/backend/node_modules/emoji-regex/text.js
new file mode 100644
index 0000000..0a55ce2
--- /dev/null
+++ b/backend/node_modules/emoji-regex/text.js
@@ -0,0 +1,6 @@
+"use strict";
+
+module.exports = function () {
+ // https://mths.be/emoji
+ return /\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F|\uD83D\uDC68(?:\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68\uD83C\uDFFB|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|[\u2695\u2696\u2708]\uFE0F|\uD83D[\uDC66\uDC67]|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708])\uFE0F|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C[\uDFFB-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)\uD83C\uDFFB|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB\uDFFC])|\uD83D\uDC69(?:\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB-\uDFFD])|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|(?:(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)\uFE0F|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\uD83C\uDFF4\u200D\u2620)\uFE0F|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF4\uD83C\uDDF2|\uD83C\uDDF6\uD83C\uDDE6|[#\*0-9]\uFE0F\u20E3|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83D\uDC69(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270A-\u270D]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC70\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDCAA\uDD74\uDD7A\uDD90\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD36\uDDB5\uDDB6\uDDBB\uDDD2-\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5\uDEEB\uDEEC\uDEF4-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])\uFE0F?|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g;
+};
diff --git a/backend/node_modules/err-code/README.md b/backend/node_modules/err-code/README.md
new file mode 100644
index 0000000..5afdab0
--- /dev/null
+++ b/backend/node_modules/err-code/README.md
@@ -0,0 +1,70 @@
+# err-code
+
+[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency status][david-dm-image]][david-dm-url] [![Dev Dependency status][david-dm-dev-image]][david-dm-dev-url] [![Greenkeeper badge][greenkeeper-image]][greenkeeper-url]
+
+[npm-url]:https://npmjs.org/package/err-code
+[downloads-image]:http://img.shields.io/npm/dm/err-code.svg
+[npm-image]:http://img.shields.io/npm/v/err-code.svg
+[travis-url]:https://travis-ci.org/IndigoUnited/js-err-code
+[travis-image]:http://img.shields.io/travis/IndigoUnited/js-err-code/master.svg
+[david-dm-url]:https://david-dm.org/IndigoUnited/js-err-code
+[david-dm-image]:https://img.shields.io/david/IndigoUnited/js-err-code.svg
+[david-dm-dev-url]:https://david-dm.org/IndigoUnited/js-err-code?type=dev
+[david-dm-dev-image]:https://img.shields.io/david/dev/IndigoUnited/js-err-code.svg
+[greenkeeper-image]:https://badges.greenkeeper.io/IndigoUnited/js-err-code.svg
+[greenkeeper-url]:https://greenkeeper.io/
+
+Create new error instances with a code and additional properties.
+
+
+## Installation
+
+```console
+$ npm install err-code
+// or
+$ bower install err-code
+```
+
+The browser file is named index.umd.js which supports CommonJS, AMD and globals (errCode).
+
+
+## Why
+
+I find myself doing this repeatedly:
+
+```js
+var err = new Error('My message');
+err.code = 'SOMECODE';
+err.detail = 'Additional information about the error';
+throw err;
+```
+
+
+## Usage
+
+Simple usage.
+
+```js
+var errcode = require('err-code');
+
+// fill error with message + code
+throw errcode(new Error('My message'), 'ESOMECODE');
+// fill error with message + code + props
+throw errcode(new Error('My message'), 'ESOMECODE', { detail: 'Additional information about the error' });
+// fill error with message + props
+throw errcode(new Error('My message'), { detail: 'Additional information about the error' });
+```
+
+## Pre-existing fields
+
+If the passed `Error` already has a `.code` field, or fields specified in the third argument to `errcode` they will be overwritten, unless the fields are read only or otherwise throw during assignment in which case a new object will be created that shares a prototype chain with the original `Error`. The `.stack` and `.message` properties will be carried over from the original error and `.code` or any passed properties will be set on it.
+
+
+## Tests
+
+`$ npm test`
+
+
+## License
+
+Released under the [MIT License](http://www.opensource.org/licenses/mit-license.php).
diff --git a/backend/node_modules/err-code/dist/index.d.ts b/backend/node_modules/err-code/dist/index.d.ts
new file mode 100644
index 0000000..64e39c6
--- /dev/null
+++ b/backend/node_modules/err-code/dist/index.d.ts
@@ -0,0 +1,16 @@
+export = createError;
+/**
+ *
+ * @param {any} err - An Error
+ * @param {string|Extensions} code - A string code or props to set on the error
+ * @param {Extensions} [props] - Props to set on the error
+ * @returns {Error & Extensions}
+ */
+declare function createError(err: any, code: string | Extensions, props?: Extensions | undefined): Error & Extensions;
+declare namespace createError {
+ export { Extensions, Err };
+}
+type Extensions = {
+ [key: string]: any;
+};
+type Err = Error;
diff --git a/backend/node_modules/err-code/index.js b/backend/node_modules/err-code/index.js
new file mode 100644
index 0000000..8ce7573
--- /dev/null
+++ b/backend/node_modules/err-code/index.js
@@ -0,0 +1,69 @@
+'use strict';
+
+/**
+ * @typedef {{ [key: string]: any }} Extensions
+ * @typedef {Error} Err
+ * @property {string} message
+ */
+
+/**
+ *
+ * @param {Error} obj
+ * @param {Extensions} props
+ * @returns {Error & Extensions}
+ */
+function assign(obj, props) {
+ for (const key in props) {
+ Object.defineProperty(obj, key, {
+ value: props[key],
+ enumerable: true,
+ configurable: true,
+ });
+ }
+
+ return obj;
+}
+
+/**
+ *
+ * @param {any} err - An Error
+ * @param {string|Extensions} code - A string code or props to set on the error
+ * @param {Extensions} [props] - Props to set on the error
+ * @returns {Error & Extensions}
+ */
+function createError(err, code, props) {
+ if (!err || typeof err === 'string') {
+ throw new TypeError('Please pass an Error to err-code');
+ }
+
+ if (!props) {
+ props = {};
+ }
+
+ if (typeof code === 'object') {
+ props = code;
+ code = '';
+ }
+
+ if (code) {
+ props.code = code;
+ }
+
+ try {
+ return assign(err, props);
+ } catch (_) {
+ props.message = err.message;
+ props.stack = err.stack;
+
+ const ErrClass = function () {};
+
+ ErrClass.prototype = Object.create(Object.getPrototypeOf(err));
+
+ // @ts-ignore
+ const output = assign(new ErrClass(), props);
+
+ return output;
+ }
+}
+
+module.exports = createError;
diff --git a/backend/node_modules/err-code/index.umd.js b/backend/node_modules/err-code/index.umd.js
new file mode 100644
index 0000000..f718339
--- /dev/null
+++ b/backend/node_modules/err-code/index.umd.js
@@ -0,0 +1,73 @@
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.errCode = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i index.umd.js"
+ },
+ "bugs": {
+ "url": "https://github.com/IndigoUnited/js-err-code/issues/"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/IndigoUnited/js-err-code.git"
+ },
+ "keywords": [
+ "error",
+ "err",
+ "code",
+ "properties",
+ "property"
+ ],
+ "author": "IndigoUnited (http://indigounited.com)",
+ "license": "MIT",
+ "devDependencies": {
+ "@satazor/eslint-config": "^3.0.0",
+ "@types/expect.js": "0.3.29",
+ "@types/mocha": "8.2.0",
+ "browserify": "^17.0.0",
+ "eslint": "^7.19.0",
+ "expect.js": "^0.3.1",
+ "mocha": "^8.2.1",
+ "typescript": "^4.1.3"
+ },
+ "files": [
+ "index.js",
+ "index.umd.js",
+ "dist/index.d.ts"
+ ]
+}
diff --git a/backend/node_modules/eventemitter3/LICENSE b/backend/node_modules/eventemitter3/LICENSE
new file mode 100644
index 0000000..abcbd54
--- /dev/null
+++ b/backend/node_modules/eventemitter3/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Arnout Kazemier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/backend/node_modules/eventemitter3/README.md b/backend/node_modules/eventemitter3/README.md
new file mode 100644
index 0000000..aba7e18
--- /dev/null
+++ b/backend/node_modules/eventemitter3/README.md
@@ -0,0 +1,94 @@
+# EventEmitter3
+
+[](https://www.npmjs.com/package/eventemitter3)[](https://travis-ci.org/primus/eventemitter3)[](https://david-dm.org/primus/eventemitter3)[](https://coveralls.io/r/primus/eventemitter3?branch=master)[](https://webchat.freenode.net/?channels=primus)
+
+[](https://saucelabs.com/u/eventemitter3)
+
+EventEmitter3 is a high performance EventEmitter. It has been micro-optimized
+for various of code paths making this, one of, if not the fastest EventEmitter
+available for Node.js and browsers. The module is API compatible with the
+EventEmitter that ships by default with Node.js but there are some slight
+differences:
+
+- Domain support has been removed.
+- We do not `throw` an error when you emit an `error` event and nobody is
+ listening.
+- The `newListener` and `removeListener` events have been removed as they
+ are useful only in some uncommon use-cases.
+- The `setMaxListeners`, `getMaxListeners`, `prependListener` and
+ `prependOnceListener` methods are not available.
+- Support for custom context for events so there is no need to use `fn.bind`.
+- The `removeListener` method removes all matching listeners, not only the
+ first.
+
+It's a drop in replacement for existing EventEmitters, but just faster. Free
+performance, who wouldn't want that? The EventEmitter is written in EcmaScript 3
+so it will work in the oldest browsers and node versions that you need to
+support.
+
+## Installation
+
+```bash
+$ npm install --save eventemitter3
+```
+
+## CDN
+
+Recommended CDN:
+
+```text
+https://unpkg.com/eventemitter3@latest/umd/eventemitter3.min.js
+```
+
+## Usage
+
+After installation the only thing you need to do is require the module:
+
+```js
+var EventEmitter = require('eventemitter3');
+```
+
+And you're ready to create your own EventEmitter instances. For the API
+documentation, please follow the official Node.js documentation:
+
+http://nodejs.org/api/events.html
+
+### Contextual emits
+
+We've upgraded the API of the `EventEmitter.on`, `EventEmitter.once` and
+`EventEmitter.removeListener` to accept an extra argument which is the `context`
+or `this` value that should be set for the emitted events. This means you no
+longer have the overhead of an event that required `fn.bind` in order to get a
+custom `this` value.
+
+```js
+var EE = new EventEmitter()
+ , context = { foo: 'bar' };
+
+function emitted() {
+ console.log(this === context); // true
+}
+
+EE.once('event-name', emitted, context);
+EE.on('another-event', emitted, context);
+EE.removeListener('another-event', emitted, context);
+```
+
+### Tests and benchmarks
+
+This module is well tested. You can run:
+
+- `npm test` to run the tests under Node.js.
+- `npm run test-browser` to run the tests in real browsers via Sauce Labs.
+
+We also have a set of benchmarks to compare EventEmitter3 with some available
+alternatives. To run the benchmarks run `npm run benchmark`.
+
+Tests and benchmarks are not included in the npm package. If you want to play
+with them you have to clone the GitHub repository.
+Note that you will have to run an additional `npm i` in the benchmarks folder
+before `npm run benchmark`.
+
+## License
+
+[MIT](LICENSE)
diff --git a/backend/node_modules/eventemitter3/index.d.ts b/backend/node_modules/eventemitter3/index.d.ts
new file mode 100644
index 0000000..118f68b
--- /dev/null
+++ b/backend/node_modules/eventemitter3/index.d.ts
@@ -0,0 +1,134 @@
+/**
+ * Minimal `EventEmitter` interface that is molded against the Node.js
+ * `EventEmitter` interface.
+ */
+declare class EventEmitter<
+ EventTypes extends EventEmitter.ValidEventTypes = string | symbol,
+ Context extends any = any
+> {
+ static prefixed: string | boolean;
+
+ /**
+ * Return an array listing the events for which the emitter has registered
+ * listeners.
+ */
+ eventNames(): Array>;
+
+ /**
+ * Return the listeners registered for a given event.
+ */
+ listeners>(
+ event: T
+ ): Array>;
+
+ /**
+ * Return the number of listeners listening to a given event.
+ */
+ listenerCount(event: EventEmitter.EventNames): number;
+
+ /**
+ * Calls each of the listeners registered for a given event.
+ */
+ emit>(
+ event: T,
+ ...args: EventEmitter.EventArgs
+ ): boolean;
+
+ /**
+ * Add a listener for a given event.
+ */
+ on>(
+ event: T,
+ fn: EventEmitter.EventListener,
+ context?: Context
+ ): this;
+ addListener>(
+ event: T,
+ fn: EventEmitter.EventListener,
+ context?: Context
+ ): this;
+
+ /**
+ * Add a one-time listener for a given event.
+ */
+ once>(
+ event: T,
+ fn: EventEmitter.EventListener,
+ context?: Context
+ ): this;
+
+ /**
+ * Remove the listeners of a given event.
+ */
+ removeListener>(
+ event: T,
+ fn?: EventEmitter.EventListener,
+ context?: Context,
+ once?: boolean
+ ): this;
+ off>(
+ event: T,
+ fn?: EventEmitter.EventListener,
+ context?: Context,
+ once?: boolean
+ ): this;
+
+ /**
+ * Remove all listeners, or those of the specified event.
+ */
+ removeAllListeners(event?: EventEmitter.EventNames): this;
+}
+
+declare namespace EventEmitter {
+ export interface ListenerFn {
+ (...args: Args): void;
+ }
+
+ export interface EventEmitterStatic {
+ new <
+ EventTypes extends ValidEventTypes = string | symbol,
+ Context = any
+ >(): EventEmitter;
+ }
+
+ /**
+ * `object` should be in either of the following forms:
+ * ```
+ * interface EventTypes {
+ * 'event-with-parameters': any[]
+ * 'event-with-example-handler': (...args: any[]) => void
+ * }
+ * ```
+ */
+ export type ValidEventTypes = string | symbol | object;
+
+ export type EventNames = T extends string | symbol
+ ? T
+ : keyof T;
+
+ export type ArgumentMap = {
+ [K in keyof T]: T[K] extends (...args: any[]) => void
+ ? Parameters
+ : T[K] extends any[]
+ ? T[K]
+ : any[];
+ };
+
+ export type EventListener<
+ T extends ValidEventTypes,
+ K extends EventNames
+ > = T extends string | symbol
+ ? (...args: any[]) => void
+ : (
+ ...args: ArgumentMap>[Extract]
+ ) => void;
+
+ export type EventArgs<
+ T extends ValidEventTypes,
+ K extends EventNames
+ > = Parameters