mirror of https://github.com/sylv/micro.git
feat: better host restrictions
This commit is contained in:
parent
ca63479776
commit
0ea831bb6b
|
@ -12,7 +12,8 @@
|
|||
"scripts": {
|
||||
"watch": "pnpm tsup src/main.ts src/migrations/* --watch --onSuccess \"node dist/main.js\" --target node16",
|
||||
"build": "rm -rf ./dist && pnpm tsup src/main.ts src/types.ts src/migrations/* --dts --sourcemap --target node16",
|
||||
"start": "node ./dist/main.js"
|
||||
"start": "node ./dist/main.js",
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fastify/cookie": "^6.0.0",
|
||||
|
@ -59,15 +60,18 @@
|
|||
"devDependencies": {
|
||||
"@mikro-orm/cli": "^5.2.0",
|
||||
"@swc/core": "^1.2.175",
|
||||
"@sylo-digital/scripts": "^1.0.0",
|
||||
"@tsconfig/node16": "^1.0.2",
|
||||
"@types/bcrypt": "^5.0.0",
|
||||
"@types/dedent": "^0.7.0",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@types/luxon": "^2.3.2",
|
||||
"@types/mime-types": "^2.1.1",
|
||||
"@types/node": "16",
|
||||
"@types/passport-jwt": "^3.0.6",
|
||||
"@types/passport-local": "^1.0.34",
|
||||
"@types/sharp": "^0.30.2",
|
||||
"jest": "^28.1.0",
|
||||
"nodemon": "^2.0.16",
|
||||
"ts-node": "^10.7.0",
|
||||
"tsup": "^5.12.6",
|
||||
|
@ -79,5 +83,8 @@
|
|||
"./src/mikro-orm.config.ts",
|
||||
"./dist/mikro-orm.config.js"
|
||||
]
|
||||
},
|
||||
"jest": {
|
||||
"preset": "@sylo-digital/scripts/jest/node"
|
||||
}
|
||||
}
|
|
@ -3,13 +3,19 @@ import escapeString from "escape-string-regexp";
|
|||
import { HostService } from "../modules/host/host.service";
|
||||
|
||||
export class MicroHost {
|
||||
constructor(url: string, tags?: string[], redirect?: string) {
|
||||
this.url = url;
|
||||
this.tags = tags;
|
||||
this.redirect = redirect;
|
||||
}
|
||||
|
||||
// https://regex101.com/r/ZR9rpp/1
|
||||
@Matches(/^https?:\/\/[\d.:A-z{}-]+$/)
|
||||
url: string;
|
||||
|
||||
@IsString({ each: true })
|
||||
@IsOptional()
|
||||
tags: string[] = [];
|
||||
tags?: string[];
|
||||
|
||||
@IsUrl({ require_protocol: true })
|
||||
@IsOptional()
|
||||
|
@ -26,9 +32,14 @@ export class MicroHost {
|
|||
private _pattern?: RegExp;
|
||||
get pattern() {
|
||||
if (this._pattern) return this._pattern;
|
||||
const escaped = escapeString(this.normalised);
|
||||
const pattern = escaped.replace("\\{\\{username\\}\\}", "(?<username>[a-z0-9-{}]+?)");
|
||||
this._pattern = new RegExp(`^(https?:\\/\\/)?${pattern}\\/?`);
|
||||
this._pattern = MicroHost.getWildcardPattern(this.url);
|
||||
return this._pattern;
|
||||
}
|
||||
|
||||
static getWildcardPattern(url: string) {
|
||||
const normalised = HostService.normaliseHostUrl(url);
|
||||
const escaped = escapeString(normalised);
|
||||
const pattern = escaped.replace("\\{\\{username\\}\\}", "(?<username>[a-z0-9-{}]+?)");
|
||||
return new RegExp(`^(https?:\\/\\/)?${pattern}\\/?`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -249,6 +249,15 @@
|
|||
"nullable": false,
|
||||
"mappedType": "string"
|
||||
},
|
||||
"hostname": {
|
||||
"name": "hostname",
|
||||
"type": "varchar(255)",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "string"
|
||||
},
|
||||
"content": {
|
||||
"name": "content",
|
||||
"type": "varchar(500000)",
|
||||
|
@ -367,8 +376,8 @@
|
|||
"length": 1024,
|
||||
"mappedType": "string"
|
||||
},
|
||||
"host": {
|
||||
"name": "host",
|
||||
"hostname": {
|
||||
"name": "hostname",
|
||||
"type": "varchar(255)",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
|
@ -445,8 +454,8 @@
|
|||
"nullable": false,
|
||||
"mappedType": "string"
|
||||
},
|
||||
"host": {
|
||||
"name": "host",
|
||||
"hostname": {
|
||||
"name": "hostname",
|
||||
"type": "varchar(255)",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import { Migration } from "@mikro-orm/migrations";
|
||||
|
||||
export class Migration20220620182830 extends Migration {
|
||||
async up(): Promise<void> {
|
||||
this.addSql('alter table "pastes" add column "hostname" varchar(255) null;');
|
||||
this.addSql('alter table "links" rename column "host" to "hostname";');
|
||||
this.addSql('alter table "files" rename column "host" to "hostname";');
|
||||
}
|
||||
|
||||
async down(): Promise<void> {
|
||||
this.addSql('alter table "pastes" drop column "hostname";');
|
||||
this.addSql('alter table "links" rename column "hostname" to "host";');
|
||||
this.addSql('alter table "files" rename column "hostname" to "host";');
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ export class AppController {
|
|||
},
|
||||
hosts: config.hosts
|
||||
.filter((host) => {
|
||||
if (!host.tags[0]) return true;
|
||||
if (!host.tags || !host.tags[0]) return true;
|
||||
return host.tags.every((tag) => tags.includes(tag));
|
||||
})
|
||||
.map((host) => ({
|
||||
|
|
|
@ -45,7 +45,7 @@ export class FileController {
|
|||
|
||||
@Get("file/:fileId")
|
||||
async getFile(@Res() reply: FastifyReply, @Param("fileId") fileId: string, @Request() request: FastifyRequest) {
|
||||
const file = await this.fileService.getFile(fileId, request.host);
|
||||
const file = await this.fileService.getFile(fileId, request);
|
||||
return reply.send(file);
|
||||
}
|
||||
|
||||
|
@ -65,10 +65,16 @@ export class FileController {
|
|||
@Headers("X-Micro-Paste-Shortcut") shortcut: string
|
||||
) {
|
||||
const user = await this.userService.getUser(userId);
|
||||
if (!user) throw new ForbiddenException("Unknown user.");
|
||||
if (!user) throw new ForbiddenException("Unknown user");
|
||||
const upload = (await request.file()) as MultipartFile | undefined;
|
||||
if (!upload) throw new BadRequestException("Missing upload.");
|
||||
|
||||
const possibleHosts = hosts.split(/, ?/g);
|
||||
const hostUrl = randomItem(possibleHosts);
|
||||
const host = await this.hostService.getHostFrom(hostUrl, user.tags);
|
||||
|
||||
if (shortcut === "true" && upload.mimetype === "text/plain") {
|
||||
if (host) this.hostService.checkUserCanUploadTo(host, user);
|
||||
const content = await upload.toBuffer();
|
||||
const paste = this.pasteRepo.create({
|
||||
content: content.toString(),
|
||||
|
@ -76,15 +82,13 @@ export class FileController {
|
|||
encrypted: false,
|
||||
owner: userId,
|
||||
extension: "txt",
|
||||
hostname: host?.normalised,
|
||||
});
|
||||
|
||||
await this.pasteRepo.persistAndFlush(paste);
|
||||
return paste;
|
||||
}
|
||||
|
||||
const possibleHosts = hosts.split(/, ?/g);
|
||||
const hostUrl = randomItem(possibleHosts);
|
||||
const host = await this.hostService.getHostFrom(hostUrl, user.tags);
|
||||
const file = await this.fileService.createFile(upload, request, user, host);
|
||||
return file;
|
||||
}
|
||||
|
|
|
@ -13,18 +13,16 @@ import { checkThumbnailSupport } from "@ryanke/thumbnail-generator";
|
|||
import mimeType from "mime-types";
|
||||
import { config } from "../../config";
|
||||
import { generateDeleteKey } from "../../helpers/generate-delete-key.helper";
|
||||
import { WithHostname } from "../host/host.entity";
|
||||
import { Thumbnail } from "../thumbnail/thumbnail.entity";
|
||||
import { User } from "../user/user.entity";
|
||||
import { FileMetadata } from "./file-metadata.embeddable";
|
||||
|
||||
@Entity({ tableName: "files" })
|
||||
export class File {
|
||||
export class File extends WithHostname {
|
||||
@PrimaryKey()
|
||||
id: string;
|
||||
|
||||
@Property({ nullable: true })
|
||||
host?: string;
|
||||
|
||||
@Property()
|
||||
type: string;
|
||||
|
||||
|
@ -71,7 +69,7 @@ export class File {
|
|||
@Property({ persist: false })
|
||||
get urls() {
|
||||
const owner = this.owner.unwrap();
|
||||
const host = this.host ? config.hosts.find((host) => host.normalised === this.host) : null;
|
||||
const host = this.hostname ? config.hosts.find((host) => host.normalised === this.hostname) : null;
|
||||
const baseUrl = host ? host.url.replace("{{username}}", owner.username) : config.rootHost.url;
|
||||
return {
|
||||
view: baseUrl + this.paths.view,
|
||||
|
@ -102,14 +100,5 @@ export class File {
|
|||
};
|
||||
}
|
||||
|
||||
[OptionalProps]:
|
||||
| "paths"
|
||||
| "urls"
|
||||
| "displayName"
|
||||
| "createdAt"
|
||||
| "thumbnail"
|
||||
| "name"
|
||||
| "deleteKey"
|
||||
| "host"
|
||||
| "extension";
|
||||
[OptionalProps]: "paths" | "urls" | "displayName" | "createdAt" | "thumbnail" | "name" | "deleteKey" | "extension";
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import { generateContentId } from "../../helpers/generate-content-id.helper";
|
|||
import { getStreamType } from "../../helpers/get-stream-type.helper";
|
||||
import { HostService } from "../host/host.service";
|
||||
import { StorageService } from "../storage/storage.service";
|
||||
import { User } from "../user/user.entity";
|
||||
import { File } from "./file.entity";
|
||||
|
||||
@Injectable()
|
||||
|
@ -34,9 +35,9 @@ export class FileService implements OnApplicationBootstrap {
|
|||
private orm: MikroORM
|
||||
) {}
|
||||
|
||||
async getFile(id: string, host: MicroHost) {
|
||||
async getFile(id: string, request: FastifyRequest) {
|
||||
const file = await this.fileRepo.findOneOrFail(id);
|
||||
if (!this.hostService.canHostSendEntity(host, file)) {
|
||||
if (file.hostname && !file.canSendTo(request)) {
|
||||
throw new NotFoundException("Your file is in another castle.");
|
||||
}
|
||||
|
||||
|
@ -62,9 +63,10 @@ export class FileService implements OnApplicationBootstrap {
|
|||
async createFile(
|
||||
multipart: Multipart,
|
||||
request: FastifyRequest,
|
||||
owner: { id: string; tags?: string[] },
|
||||
owner: User,
|
||||
host: MicroHost | undefined
|
||||
): Promise<File> {
|
||||
if (host) this.hostService.checkUserCanUploadTo(host, owner);
|
||||
if (!request.headers["content-length"]) throw new BadRequestException('Missing "Content-Length" header.');
|
||||
if (+request.headers["content-length"] >= config.uploadLimit) {
|
||||
const size = xbytes(+request.headers["content-length"]);
|
||||
|
@ -89,7 +91,7 @@ export class FileService implements OnApplicationBootstrap {
|
|||
type: type,
|
||||
name: multipart.filename,
|
||||
owner: owner.id,
|
||||
host: host?.normalised,
|
||||
hostname: host?.normalised.replace("{{username}}", owner.username),
|
||||
hash: hash,
|
||||
size: size,
|
||||
});
|
||||
|
@ -99,7 +101,7 @@ export class FileService implements OnApplicationBootstrap {
|
|||
}
|
||||
|
||||
async sendFile(fileId: string, request: FastifyRequest, reply: FastifyReply) {
|
||||
const file = await this.getFile(fileId, request.host);
|
||||
const file = await this.getFile(fileId, request);
|
||||
const range = request.headers["content-range"] ? contentRange.parse(request.headers["content-range"]) : null;
|
||||
const stream = this.storageService.createReadStream(file.hash, range);
|
||||
if (range) reply.header("Content-Range", contentRange.format(range));
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
import { BeforeCreate, BeforeUpdate, Entity, EventArgs, Property } from "@mikro-orm/core";
|
||||
import { FastifyRequest } from "fastify";
|
||||
import { config } from "../../config";
|
||||
|
||||
function getHostFromRequest(request: FastifyRequest): string {
|
||||
if (request.headers["x-forwarded-host"]) {
|
||||
if (Array.isArray(request.headers["x-forwarded-host"])) {
|
||||
return request.headers["x-forwarded-host"][0];
|
||||
}
|
||||
|
||||
return request.headers["x-forwarded-host"];
|
||||
}
|
||||
|
||||
if (request.headers["host"]) return request.headers["host"];
|
||||
return request.hostname;
|
||||
}
|
||||
|
||||
@Entity({ abstract: true })
|
||||
export abstract class WithHostname {
|
||||
@Property({ nullable: true })
|
||||
hostname?: string;
|
||||
|
||||
getHost() {
|
||||
if (!this.hostname) return config.rootHost;
|
||||
const match = config.hosts.find((host) => host.pattern.test(this.hostname!));
|
||||
if (match) return match;
|
||||
return config.rootHost;
|
||||
}
|
||||
|
||||
canSendTo(request: FastifyRequest) {
|
||||
const hostname = getHostFromRequest(request);
|
||||
if (!config.restrictFilesToHost) return true;
|
||||
|
||||
// root host can send all files
|
||||
if (hostname === config.rootHost.normalised) return true;
|
||||
if (this.hostname === hostname) return true;
|
||||
if (this.hostname?.includes("{{username}}")) {
|
||||
// old files have {{username}} in the persisted hostname, migrating them
|
||||
// to the new format is too difficult so this does a dirty comparison
|
||||
// that should work for most use cases.
|
||||
const withoutWildcard = this.hostname.replace("{{username}}", "");
|
||||
return hostname.endsWith(withoutWildcard);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@BeforeCreate()
|
||||
@BeforeUpdate()
|
||||
async onBeforePersist(args: EventArgs<WithHostname>) {
|
||||
console.log("Before persist");
|
||||
if (args.entity.hostname?.includes("{{username}}")) {
|
||||
throw new Error("Host placeholders should be replaced before insert");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ import { BadRequestException, ForbiddenException } from "@nestjs/common";
|
|||
import normalizeUrl from "normalize-url";
|
||||
import { MicroHost } from "../../classes/MicroHost";
|
||||
import { config } from "../../config";
|
||||
import { randomItem } from "../../helpers/random-item.helper";
|
||||
import { User } from "../user/user.entity";
|
||||
|
||||
export class HostService {
|
||||
formatHostUrl(url: string, username: string, path?: string | null) {
|
||||
|
@ -18,12 +18,11 @@ export class HostService {
|
|||
* @throws if the host could not be resolved.
|
||||
*/
|
||||
async getHostFrom(url: string | undefined, tags: string[] | null): Promise<MicroHost> {
|
||||
console.log({ url });
|
||||
if (!url) return config.rootHost;
|
||||
const normalised = HostService.normaliseHostUrl(url);
|
||||
for (const host of config.hosts) {
|
||||
if (!host.pattern.test(normalised)) continue;
|
||||
if (tags) {
|
||||
if (tags && host.tags) {
|
||||
const hasTags = host.tags.every((tag) => tags.includes(tag));
|
||||
if (!hasTags) {
|
||||
throw new ForbiddenException("Missing host authorisation.");
|
||||
|
@ -36,18 +35,12 @@ export class HostService {
|
|||
throw new BadRequestException(`Invalid host URL "${url}".`);
|
||||
}
|
||||
|
||||
canHostSendEntity(host: MicroHost, entity: { host?: string }) {
|
||||
// todo: if host.wildcard, we should check to make sure the file owner
|
||||
// matches the given username in the request url. so uploads to
|
||||
// sylver.is-fucking.gay can't be accessed on cyk.is-fucking.gay and vice versa
|
||||
if (!config.restrictFilesToHost) return true;
|
||||
// files without a host can be served on all hosts
|
||||
if (!entity.host) return true;
|
||||
// the host that the file was uploaded to can serve the file
|
||||
if (entity.host === host.normalised) return true;
|
||||
// root host can serve all files.
|
||||
if (host.normalised === config.rootHost.normalised) return true;
|
||||
return false;
|
||||
checkUserCanUploadTo(host: MicroHost, user: User) {
|
||||
if (host.tags && !host.tags.every((tag) => user.tags.includes(tag))) {
|
||||
throw new ForbiddenException("You are not allowed to upload to that host.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static normaliseHostUrl(url: string) {
|
||||
|
|
|
@ -1,21 +1,9 @@
|
|||
import { InjectRepository } from "@mikro-orm/nestjs";
|
||||
import { EntityRepository } from "@mikro-orm/postgresql";
|
||||
import {
|
||||
BadRequestException,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
NotFoundException,
|
||||
Param,
|
||||
Post,
|
||||
Query,
|
||||
Request,
|
||||
Res,
|
||||
} from "@nestjs/common";
|
||||
import { Controller, Get, Param, Request, Res } from "@nestjs/common";
|
||||
import { FastifyReply, FastifyRequest } from "fastify";
|
||||
import { UserId } from "../auth/auth.decorators";
|
||||
import { LinkService } from "./link.service";
|
||||
import { Link } from "./link.entity";
|
||||
import { LinkService } from "./link.service";
|
||||
|
||||
@Controller()
|
||||
export class LinkController {
|
||||
|
@ -23,7 +11,7 @@ export class LinkController {
|
|||
|
||||
@Get("link/:id/go")
|
||||
async followLink(@Param("id") id: string, @Request() request: FastifyRequest, @Res() reply: FastifyReply) {
|
||||
const link = await this.linkService.getLink(id, request.host);
|
||||
const link = await this.linkService.getLink(id, request);
|
||||
link.clicks++;
|
||||
await this.linkRepo.persistAndFlush(link);
|
||||
reply.redirect(301, link.destination);
|
||||
|
@ -31,6 +19,6 @@ export class LinkController {
|
|||
|
||||
@Get("link/:id")
|
||||
async getLink(@Request() request: FastifyRequest, @Param("id") id: string) {
|
||||
return this.linkService.getLink(id, request.host);
|
||||
return this.linkService.getLink(id, request);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
import { Entity, IdentifiedReference, ManyToOne, OptionalProps, PrimaryKey, Property } from "@mikro-orm/core";
|
||||
import { generateContentId } from "../../helpers/generate-content-id.helper";
|
||||
import { WithHostname } from "../host/host.entity";
|
||||
import { User } from "../user/user.entity";
|
||||
|
||||
@Entity({ tableName: "links" })
|
||||
export class Link {
|
||||
export class Link extends WithHostname {
|
||||
@PrimaryKey({ type: String })
|
||||
id = generateContentId();
|
||||
|
||||
@Property({ length: 1024 })
|
||||
destination: string;
|
||||
|
||||
@Property({ nullable: true })
|
||||
host?: string;
|
||||
|
||||
@Property()
|
||||
clicks: number = 0;
|
||||
|
||||
|
@ -25,5 +23,5 @@ export class Link {
|
|||
})
|
||||
owner: IdentifiedReference<User>;
|
||||
|
||||
[OptionalProps]: "host" | "clicks" | "createdAt";
|
||||
[OptionalProps]: "hostname" | "clicks" | "createdAt";
|
||||
}
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
import { InjectRepository } from "@mikro-orm/nestjs";
|
||||
import { EntityRepository } from "@mikro-orm/postgresql";
|
||||
import { Injectable, NotFoundException, UnauthorizedException } from "@nestjs/common";
|
||||
import { MicroHost } from "../../classes/MicroHost";
|
||||
import { HostService } from "../host/host.service";
|
||||
import { FastifyRequest } from "fastify";
|
||||
import { Link } from "./link.entity";
|
||||
|
||||
@Injectable()
|
||||
export class LinkService {
|
||||
constructor(@InjectRepository(Link) private linkRepo: EntityRepository<Link>, private hostService: HostService) {}
|
||||
constructor(@InjectRepository(Link) private linkRepo: EntityRepository<Link>) {}
|
||||
|
||||
async getLink(id: string, host: MicroHost | null) {
|
||||
async getLink(id: string, request: FastifyRequest) {
|
||||
const link = await this.linkRepo.findOneOrFail(id);
|
||||
if (host !== null && !this.hostService.canHostSendEntity(host, link)) {
|
||||
throw new NotFoundException("Your redirect is in another castle.");
|
||||
if (link.hostname && !link.canSendTo(request)) {
|
||||
throw new NotFoundException("Your link is in another castle.");
|
||||
}
|
||||
|
||||
return link;
|
||||
|
|
|
@ -4,6 +4,7 @@ import {
|
|||
BadRequestException,
|
||||
Body,
|
||||
Controller,
|
||||
ForbiddenException,
|
||||
Get,
|
||||
HttpCode,
|
||||
NotFoundException,
|
||||
|
@ -15,7 +16,10 @@ import {
|
|||
import { FastifyRequest } from "fastify";
|
||||
import { config } from "../../config";
|
||||
import { generateContentId, generateParanoidId } from "../../helpers/generate-content-id.helper";
|
||||
import { UserId } from "../auth/auth.decorators";
|
||||
import { OptionalJWTAuthGuard } from "../auth/guards/optional-jwt.guard";
|
||||
import { HostService } from "../host/host.service";
|
||||
import { UserService } from "../user/user.service";
|
||||
import { CreatePasteDto, Paste } from "./paste.entity";
|
||||
import { PasteService } from "./paste.service";
|
||||
|
||||
|
@ -23,19 +27,30 @@ import { PasteService } from "./paste.service";
|
|||
export class PasteController {
|
||||
constructor(
|
||||
@InjectRepository(Paste) private pasteRepo: EntityRepository<Paste>,
|
||||
private pasteService: PasteService
|
||||
private pasteService: PasteService,
|
||||
private userService: UserService,
|
||||
private hostService: HostService
|
||||
) {}
|
||||
|
||||
@Post()
|
||||
@UseGuards(OptionalJWTAuthGuard)
|
||||
async create(@Body() pasteBody: CreatePasteDto, @Req() request: FastifyRequest) {
|
||||
async create(@UserId() userId: string, @Body() pasteBody: CreatePasteDto, @Req() request: FastifyRequest) {
|
||||
const user = await this.userService.getUser(userId);
|
||||
if (!user) throw new ForbiddenException("Unknown user");
|
||||
if (request.host) this.hostService.checkUserCanUploadTo(request.host, user);
|
||||
if (!request.user && !config.publicPastes) {
|
||||
throw new BadRequestException("You must be logged in to create a paste on this instance.");
|
||||
}
|
||||
|
||||
const id = pasteBody.paranoid ? generateParanoidId() : generateContentId();
|
||||
const expiresAt = pasteBody.expiresAt ? new Date(pasteBody.expiresAt) : undefined;
|
||||
if (expiresAt && expiresAt.getTime() < Date.now() + 1000) {
|
||||
throw new BadRequestException("Paste expiry must be in the future or unset");
|
||||
}
|
||||
|
||||
const paste = this.pasteRepo.create({
|
||||
...pasteBody,
|
||||
expiresAt: expiresAt,
|
||||
owner: request.user,
|
||||
id: id,
|
||||
});
|
||||
|
@ -45,8 +60,8 @@ export class PasteController {
|
|||
}
|
||||
|
||||
@Get(":pasteId")
|
||||
async get(@Param("pasteId") pasteId: string) {
|
||||
return this.pasteService.getPaste(pasteId);
|
||||
async get(@Param("pasteId") pasteId: string, @Req() request: FastifyRequest) {
|
||||
return this.pasteService.getPaste(pasteId, request);
|
||||
}
|
||||
|
||||
@Post(":pasteId/burn")
|
||||
|
|
|
@ -2,10 +2,11 @@ import { Entity, IdentifiedReference, ManyToOne, OptionalProps, PrimaryKey, Prop
|
|||
import { IsBoolean, IsNumber, IsOptional, IsString, Length } from "class-validator";
|
||||
import { config } from "../../config";
|
||||
import { generateContentId } from "../../helpers/generate-content-id.helper";
|
||||
import { WithHostname } from "../host/host.entity";
|
||||
import { User } from "../user/user.entity";
|
||||
|
||||
@Entity({ tableName: "pastes" })
|
||||
export class Paste {
|
||||
export class Paste extends WithHostname {
|
||||
@PrimaryKey({ type: String })
|
||||
id = generateContentId();
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import { MikroOrmModule } from "@mikro-orm/nestjs";
|
||||
import { Module } from "@nestjs/common";
|
||||
import { HostModule } from "../host/host.module";
|
||||
import { UserModule } from "../user/user.module";
|
||||
import { PasteController } from "./paste.controller";
|
||||
import { Paste } from "./paste.entity";
|
||||
import { PasteService } from "./paste.service";
|
||||
|
||||
@Module({
|
||||
imports: [MikroOrmModule.forFeature([Paste])],
|
||||
imports: [MikroOrmModule.forFeature([Paste]), HostModule, UserModule],
|
||||
controllers: [PasteController],
|
||||
providers: [PasteService],
|
||||
})
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { EntityRepository } from "@mikro-orm/core";
|
||||
import { InjectRepository } from "@mikro-orm/nestjs";
|
||||
import { Injectable, Logger, NotFoundException } from "@nestjs/common";
|
||||
import { BadRequestException, Injectable, Logger, NotFoundException } from "@nestjs/common";
|
||||
import { Cron, CronExpression } from "@nestjs/schedule";
|
||||
import { FastifyRequest } from "fastify";
|
||||
import { Paste } from "./paste.entity";
|
||||
|
||||
@Injectable()
|
||||
|
@ -9,8 +10,12 @@ export class PasteService {
|
|||
private log = new Logger("PasteService");
|
||||
constructor(@InjectRepository(Paste) private pasteRepo: EntityRepository<Paste>) {}
|
||||
|
||||
async getPaste(pasteId: string) {
|
||||
async getPaste(pasteId: string, request: FastifyRequest) {
|
||||
const paste = await this.pasteRepo.findOneOrFail(pasteId);
|
||||
if (!paste.canSendTo(request)) {
|
||||
throw new BadRequestException("Your paste is in another castle.");
|
||||
}
|
||||
|
||||
if (paste.expiresAt && paste.expiresAt.getTime() < Date.now()) {
|
||||
await this.pasteRepo.removeAndFlush(paste);
|
||||
throw new NotFoundException();
|
||||
|
|
|
@ -76,7 +76,7 @@ export class ThumbnailService {
|
|||
.send(existing.data);
|
||||
}
|
||||
|
||||
const file = await this.fileService.getFile(fileId, request.host);
|
||||
const file = await this.fileService.getFile(fileId, request);
|
||||
const thumbnail = await this.createThumbnail(file);
|
||||
return reply
|
||||
.header("X-Micro-Generated", "true")
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
import { GetServerSidePropsContext } from "next";
|
||||
import { http } from "./http.helper";
|
||||
|
||||
export async function fetcher<T = unknown>(url: string): Promise<T> {
|
||||
const response = await http(url);
|
||||
export async function fetcher<T = unknown>(url: string, context?: GetServerSidePropsContext): Promise<T> {
|
||||
const headers: Record<string, string> = {};
|
||||
if (context) {
|
||||
// for host matching we have to forward the host header
|
||||
if (context.req.headers["user-agent"]) headers["User-Agent"] = context.req.headers["user-agent"];
|
||||
if (context.req.headers["host"]) headers["x-forwarded-host"] = context.req.headers["host"];
|
||||
}
|
||||
|
||||
const response = await http(url, { headers });
|
||||
const text = await response.text();
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
|
|
|
@ -141,7 +141,7 @@ export async function getServerSideProps(
|
|||
// yes, im salty about it.
|
||||
|
||||
try {
|
||||
const fallbackData = await fetcher<GetFileData>(`file/${context.query.fileId}`);
|
||||
const fallbackData = await fetcher<GetFileData>(`file/${context.query.fileId}`, context);
|
||||
return { props: { fallbackData } };
|
||||
} catch (error) {
|
||||
if (error instanceof HTTPError) {
|
||||
|
|
|
@ -2,7 +2,7 @@ import { GetPasteData } from "@ryanke/micro-api";
|
|||
import { GetServerSidePropsContext, GetServerSidePropsResult } from "next";
|
||||
import { useRouter } from "next/router";
|
||||
import { Language } from "prism-react-renderer";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { BookOpen, Clock, Trash } from "react-feather";
|
||||
import useSWR from "swr";
|
||||
import { Container } from "../../components/container";
|
||||
|
@ -154,7 +154,7 @@ export async function getServerSideProps(
|
|||
context: GetServerSidePropsContext
|
||||
): Promise<GetServerSidePropsResult<ViewPasteProps>> {
|
||||
try {
|
||||
const fallbackData = await fetcher<GetPasteData>(`paste/${context.query.pasteId}`);
|
||||
const fallbackData = await fetcher<GetPasteData>(`paste/${context.query.pasteId}`, context);
|
||||
return { props: { fallbackData } };
|
||||
} catch (error) {
|
||||
if (error instanceof HTTPError) {
|
||||
|
|
302
pnpm-lock.yaml
302
pnpm-lock.yaml
|
@ -39,9 +39,11 @@ importers:
|
|||
'@ryanke/thumbnail-generator': workspace:^0.0.1
|
||||
'@ryanke/venera': ^0.0.2
|
||||
'@swc/core': ^1.2.175
|
||||
'@sylo-digital/scripts': ^1.0.0
|
||||
'@tsconfig/node16': ^1.0.2
|
||||
'@types/bcrypt': ^5.0.0
|
||||
'@types/dedent': ^0.7.0
|
||||
'@types/jest': ^27.4.1
|
||||
'@types/luxon': ^2.3.2
|
||||
'@types/mime-types': ^2.1.1
|
||||
'@types/node': '16'
|
||||
|
@ -59,6 +61,7 @@ importers:
|
|||
get-stream: ^6.0.1
|
||||
http-status-codes: ^2.2.0
|
||||
istextorbinary: ^6.0.0
|
||||
jest: ^28.1.0
|
||||
luxon: ^2.3.2
|
||||
mime-types: ^2.1.35
|
||||
ms: ^3.0.0-canary.1
|
||||
|
@ -121,15 +124,18 @@ importers:
|
|||
devDependencies:
|
||||
'@mikro-orm/cli': 5.2.0_bxish3hg3dbguccecfvzdrv6hm
|
||||
'@swc/core': 1.2.175
|
||||
'@sylo-digital/scripts': 1.0.0_jest@28.1.1
|
||||
'@tsconfig/node16': 1.0.2
|
||||
'@types/bcrypt': 5.0.0
|
||||
'@types/dedent': 0.7.0
|
||||
'@types/jest': 27.5.2
|
||||
'@types/luxon': 2.3.2
|
||||
'@types/mime-types': 2.1.1
|
||||
'@types/node': 16.10.1
|
||||
'@types/passport-jwt': 3.0.6
|
||||
'@types/passport-local': 1.0.34
|
||||
'@types/sharp': 0.30.2
|
||||
jest: 28.1.1_ljamerpmo44qvadngd6o6tmh2u
|
||||
nodemon: 2.0.16
|
||||
ts-node: 10.7.0_bvx74sey2cc4ezqwnfhit2yjju
|
||||
tsup: 5.12.6_jzlwqgkjzt5mccsp6kc6j2iwe4
|
||||
|
@ -247,7 +253,6 @@ packages:
|
|||
dependencies:
|
||||
'@jridgewell/gen-mapping': 0.1.1
|
||||
'@jridgewell/trace-mapping': 0.3.13
|
||||
dev: true
|
||||
|
||||
/@babel/code-frame/7.14.5:
|
||||
resolution: {integrity: sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==}
|
||||
|
@ -329,11 +334,10 @@ packages:
|
|||
convert-source-map: 1.8.0
|
||||
debug: 4.3.4
|
||||
gensync: 1.0.0-beta.2
|
||||
json5: 2.2.0
|
||||
json5: 2.2.1
|
||||
semver: 6.3.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@babel/eslint-parser/7.17.0_ei34yuzoyih6t7d227j2sk6bc4:
|
||||
resolution: {integrity: sha512-PUEJ7ZBXbRkbq3qqM/jZ2nIuakUBqCYc7Qf52Lj7dlZ6zERnqisdHioL0l4wwQZnmskMeasqUNzLBFKs3nylXA==}
|
||||
|
@ -364,7 +368,6 @@ packages:
|
|||
'@babel/types': 7.18.4
|
||||
'@jridgewell/gen-mapping': 0.3.1
|
||||
jsesc: 2.5.2
|
||||
dev: true
|
||||
|
||||
/@babel/helper-annotate-as-pure/7.16.7:
|
||||
resolution: {integrity: sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==}
|
||||
|
@ -429,7 +432,6 @@ packages:
|
|||
'@babel/helper-validator-option': 7.16.7
|
||||
browserslist: 4.20.3
|
||||
semver: 6.3.0
|
||||
dev: true
|
||||
|
||||
/@babel/helper-create-class-features-plugin/7.18.0:
|
||||
resolution: {integrity: sha512-Kh8zTGR9de3J63e5nS0rQUdRs/kbtwoeQQ0sriS0lItjC96u8XXZN6lKpuyWd2coKSU13py/y+LTmThLuVX0Pg==}
|
||||
|
@ -549,7 +551,6 @@ packages:
|
|||
/@babel/helper-environment-visitor/7.18.2:
|
||||
resolution: {integrity: sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dev: true
|
||||
|
||||
/@babel/helper-explode-assignable-expression/7.16.7:
|
||||
resolution: {integrity: sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==}
|
||||
|
@ -613,7 +614,6 @@ packages:
|
|||
'@babel/types': 7.18.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@babel/helper-optimise-call-expression/7.16.7:
|
||||
resolution: {integrity: sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==}
|
||||
|
@ -626,11 +626,6 @@ packages:
|
|||
resolution: {integrity: sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==}
|
||||
dev: true
|
||||
|
||||
/@babel/helper-plugin-utils/7.14.5:
|
||||
resolution: {integrity: sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dev: false
|
||||
|
||||
/@babel/helper-plugin-utils/7.16.7:
|
||||
resolution: {integrity: sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
@ -638,7 +633,6 @@ packages:
|
|||
/@babel/helper-plugin-utils/7.17.12:
|
||||
resolution: {integrity: sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dev: true
|
||||
|
||||
/@babel/helper-remap-async-to-generator/7.16.8:
|
||||
resolution: {integrity: sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==}
|
||||
|
@ -675,7 +669,6 @@ packages:
|
|||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/types': 7.18.4
|
||||
dev: true
|
||||
|
||||
/@babel/helper-skip-transparent-expression-wrappers/7.16.0:
|
||||
resolution: {integrity: sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==}
|
||||
|
@ -693,6 +686,7 @@ packages:
|
|||
/@babel/helper-validator-identifier/7.15.7:
|
||||
resolution: {integrity: sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dev: false
|
||||
|
||||
/@babel/helper-validator-identifier/7.16.7:
|
||||
resolution: {integrity: sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==}
|
||||
|
@ -733,7 +727,6 @@ packages:
|
|||
'@babel/types': 7.18.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@babel/highlight/7.14.5:
|
||||
resolution: {integrity: sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==}
|
||||
|
@ -1214,7 +1207,7 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.15.5
|
||||
'@babel/helper-plugin-utils': 7.16.7
|
||||
'@babel/helper-plugin-utils': 7.17.12
|
||||
|
||||
/@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.17.4:
|
||||
resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==}
|
||||
|
@ -1231,7 +1224,7 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.15.5
|
||||
'@babel/helper-plugin-utils': 7.14.5
|
||||
'@babel/helper-plugin-utils': 7.17.12
|
||||
dev: false
|
||||
|
||||
/@babel/plugin-syntax-bigint/7.8.3_@babel+core@7.17.4:
|
||||
|
@ -1257,7 +1250,7 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.15.5
|
||||
'@babel/helper-plugin-utils': 7.16.7
|
||||
'@babel/helper-plugin-utils': 7.17.12
|
||||
|
||||
/@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.17.4:
|
||||
resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==}
|
||||
|
@ -1385,7 +1378,7 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.15.5
|
||||
'@babel/helper-plugin-utils': 7.14.5
|
||||
'@babel/helper-plugin-utils': 7.17.12
|
||||
dev: false
|
||||
|
||||
/@babel/plugin-syntax-import-meta/7.10.4_@babel+core@7.17.4:
|
||||
|
@ -1411,7 +1404,7 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.15.5
|
||||
'@babel/helper-plugin-utils': 7.16.7
|
||||
'@babel/helper-plugin-utils': 7.17.12
|
||||
|
||||
/@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.17.4:
|
||||
resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==}
|
||||
|
@ -1474,7 +1467,7 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.15.5
|
||||
'@babel/helper-plugin-utils': 7.16.7
|
||||
'@babel/helper-plugin-utils': 7.17.12
|
||||
|
||||
/@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.17.4:
|
||||
resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==}
|
||||
|
@ -1499,7 +1492,7 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.15.5
|
||||
'@babel/helper-plugin-utils': 7.16.7
|
||||
'@babel/helper-plugin-utils': 7.17.12
|
||||
|
||||
/@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.17.4:
|
||||
resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==}
|
||||
|
@ -1524,7 +1517,7 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.15.5
|
||||
'@babel/helper-plugin-utils': 7.16.7
|
||||
'@babel/helper-plugin-utils': 7.17.12
|
||||
|
||||
/@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.17.4:
|
||||
resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==}
|
||||
|
@ -1558,7 +1551,7 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.15.5
|
||||
'@babel/helper-plugin-utils': 7.16.7
|
||||
'@babel/helper-plugin-utils': 7.17.12
|
||||
|
||||
/@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.17.4:
|
||||
resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==}
|
||||
|
@ -1583,7 +1576,7 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.15.5
|
||||
'@babel/helper-plugin-utils': 7.16.7
|
||||
'@babel/helper-plugin-utils': 7.17.12
|
||||
|
||||
/@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.17.4:
|
||||
resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==}
|
||||
|
@ -1608,7 +1601,7 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.15.5
|
||||
'@babel/helper-plugin-utils': 7.16.7
|
||||
'@babel/helper-plugin-utils': 7.17.12
|
||||
|
||||
/@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.17.4:
|
||||
resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==}
|
||||
|
@ -1654,7 +1647,7 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.15.5
|
||||
'@babel/helper-plugin-utils': 7.16.7
|
||||
'@babel/helper-plugin-utils': 7.17.12
|
||||
|
||||
/@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.17.4:
|
||||
resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==}
|
||||
|
@ -2937,7 +2930,6 @@ packages:
|
|||
globals: 11.12.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@babel/types/7.15.6:
|
||||
resolution: {integrity: sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==}
|
||||
|
@ -2945,6 +2937,7 @@ packages:
|
|||
dependencies:
|
||||
'@babel/helper-validator-identifier': 7.15.7
|
||||
to-fast-properties: 2.0.0
|
||||
dev: false
|
||||
|
||||
/@babel/types/7.17.10:
|
||||
resolution: {integrity: sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A==}
|
||||
|
@ -3226,6 +3219,49 @@ packages:
|
|||
- ts-node
|
||||
dev: true
|
||||
|
||||
/@jest/core/28.1.1_ts-node@10.7.0:
|
||||
resolution: {integrity: sha512-3pYsBoZZ42tXMdlcFeCc/0j9kOlK7MYuXs2B1QbvDgMoW1K9NJ4G/VYvIbMb26iqlkTfPHo7SC2JgjDOk/mxXw==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
|
||||
peerDependencies:
|
||||
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
|
||||
peerDependenciesMeta:
|
||||
node-notifier:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@jest/console': 28.1.1
|
||||
'@jest/reporters': 28.1.1
|
||||
'@jest/test-result': 28.1.1
|
||||
'@jest/transform': 28.1.1
|
||||
'@jest/types': 28.1.1
|
||||
'@types/node': 16.11.33
|
||||
ansi-escapes: 4.3.2
|
||||
chalk: 4.1.2
|
||||
ci-info: 3.3.1
|
||||
exit: 0.1.2
|
||||
graceful-fs: 4.2.10
|
||||
jest-changed-files: 28.0.2
|
||||
jest-config: 28.1.1_p2brwx6nx5zpemlvbnwk444zqy
|
||||
jest-haste-map: 28.1.1
|
||||
jest-message-util: 28.1.1
|
||||
jest-regex-util: 28.0.2
|
||||
jest-resolve: 28.1.1
|
||||
jest-resolve-dependencies: 28.1.1
|
||||
jest-runner: 28.1.1
|
||||
jest-runtime: 28.1.1
|
||||
jest-snapshot: 28.1.1
|
||||
jest-util: 28.1.1
|
||||
jest-validate: 28.1.1
|
||||
jest-watcher: 28.1.1
|
||||
micromatch: 4.0.5
|
||||
pretty-format: 28.1.1
|
||||
rimraf: 3.0.2
|
||||
slash: 3.0.0
|
||||
strip-ansi: 6.0.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/@jest/create-cache-key-function/27.5.1:
|
||||
resolution: {integrity: sha512-dmH1yW+makpTSURTy8VzdUwFnfQh1G8R+DxO2Ho2FFmBbKFEVm+3jWdvFhE2VqB/LATCTokkP0dotjyQyw5/AQ==}
|
||||
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
|
||||
|
@ -3302,7 +3338,7 @@ packages:
|
|||
chalk: 4.1.2
|
||||
collect-v8-coverage: 1.0.1
|
||||
exit: 0.1.2
|
||||
glob: 7.2.0
|
||||
glob: 7.2.3
|
||||
graceful-fs: 4.2.10
|
||||
istanbul-lib-coverage: 3.2.0
|
||||
istanbul-lib-instrument: 5.2.0
|
||||
|
@ -3361,9 +3397,9 @@ packages:
|
|||
resolution: {integrity: sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==}
|
||||
engines: {node: '>= 10.14.2'}
|
||||
dependencies:
|
||||
'@babel/core': 7.15.5
|
||||
'@babel/core': 7.17.4
|
||||
'@jest/types': 26.6.2
|
||||
babel-plugin-istanbul: 6.0.0
|
||||
babel-plugin-istanbul: 6.1.1
|
||||
chalk: 4.1.2
|
||||
convert-source-map: 1.8.0
|
||||
fast-json-stable-stringify: 2.1.0
|
||||
|
@ -3371,7 +3407,7 @@ packages:
|
|||
jest-haste-map: 26.6.2
|
||||
jest-regex-util: 26.0.0
|
||||
jest-util: 26.6.2
|
||||
micromatch: 4.0.4
|
||||
micromatch: 4.0.5
|
||||
pirates: 4.0.5
|
||||
slash: 3.0.0
|
||||
source-map: 0.6.1
|
||||
|
@ -3394,7 +3430,7 @@ packages:
|
|||
jest-haste-map: 28.1.1
|
||||
jest-regex-util: 28.0.2
|
||||
jest-util: 28.1.1
|
||||
micromatch: 4.0.4
|
||||
micromatch: 4.0.5
|
||||
pirates: 4.0.5
|
||||
slash: 3.0.0
|
||||
write-file-atomic: 4.0.1
|
||||
|
@ -3449,12 +3485,10 @@ packages:
|
|||
'@jridgewell/set-array': 1.1.0
|
||||
'@jridgewell/sourcemap-codec': 1.4.12
|
||||
'@jridgewell/trace-mapping': 0.3.13
|
||||
dev: true
|
||||
|
||||
/@jridgewell/resolve-uri/3.0.7:
|
||||
resolution: {integrity: sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
dev: true
|
||||
|
||||
/@jridgewell/set-array/1.1.0:
|
||||
resolution: {integrity: sha512-SfJxIxNVYLTsKwzB3MoOQ1yxf4w/E6MdkvTgrgAt1bfxjSrLUoHMKrDOykwN14q65waezZIdqDneUIPh4/sKxg==}
|
||||
|
@ -3475,7 +3509,6 @@ packages:
|
|||
dependencies:
|
||||
'@jridgewell/resolve-uri': 3.0.7
|
||||
'@jridgewell/sourcemap-codec': 1.4.12
|
||||
dev: true
|
||||
|
||||
/@mapbox/node-pre-gyp/1.0.5:
|
||||
resolution: {integrity: sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==}
|
||||
|
@ -5833,7 +5866,7 @@ packages:
|
|||
eslint: 8.17.0
|
||||
eslint-config-galex: 3.6.5_eslint@8.17.0+jest@28.1.1
|
||||
eslint-plugin-es: 4.1.0_eslint@8.17.0
|
||||
jest: 28.1.1_@types+node@16.11.33
|
||||
jest: 28.1.1_ljamerpmo44qvadngd6o6tmh2u
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
@ -5921,7 +5954,7 @@ packages:
|
|||
/@types/babel__traverse/7.14.2:
|
||||
resolution: {integrity: sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==}
|
||||
dependencies:
|
||||
'@babel/types': 7.15.6
|
||||
'@babel/types': 7.18.4
|
||||
|
||||
/@types/bcrypt/5.0.0:
|
||||
resolution: {integrity: sha512-agtcFKaruL8TmcvqbndlqHPSJgsolhf/qPWchFlgnW1gECTN/nKbFcoFnvKAQRFfKbh+BO6A3SWdJu9t+xF3Lw==}
|
||||
|
@ -7363,7 +7396,7 @@ packages:
|
|||
babel-plugin-istanbul: 6.0.0
|
||||
babel-preset-jest: 26.6.2_@babel+core@7.15.5
|
||||
chalk: 4.1.2
|
||||
graceful-fs: 4.2.8
|
||||
graceful-fs: 4.2.10
|
||||
slash: 3.0.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
@ -7466,6 +7499,7 @@ packages:
|
|||
test-exclude: 6.0.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/babel-plugin-istanbul/6.1.1:
|
||||
resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==}
|
||||
|
@ -7478,7 +7512,6 @@ packages:
|
|||
test-exclude: 6.0.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/babel-plugin-jest-hoist/26.6.2:
|
||||
resolution: {integrity: sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==}
|
||||
|
@ -9749,14 +9782,14 @@ packages:
|
|||
dependencies:
|
||||
find-root: 1.1.0
|
||||
glob-parent: 6.0.2
|
||||
resolve: 1.22.0
|
||||
resolve: 1.22.1
|
||||
dev: true
|
||||
|
||||
/eslint-import-resolver-node/0.3.6:
|
||||
resolution: {integrity: sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==}
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
resolve: 1.22.0
|
||||
resolve: 1.22.1
|
||||
dev: true
|
||||
|
||||
/eslint-module-utils/2.7.3:
|
||||
|
@ -9796,7 +9829,7 @@ packages:
|
|||
is-glob: 4.0.3
|
||||
minimatch: 3.1.2
|
||||
object.values: 1.1.5
|
||||
resolve: 1.22.0
|
||||
resolve: 1.22.1
|
||||
tsconfig-paths: 3.14.1
|
||||
dev: true
|
||||
|
||||
|
@ -9837,7 +9870,7 @@ packages:
|
|||
'@typescript-eslint/eslint-plugin': 5.12.0_aq3u4h7brb5mlv46e3ysvg7bse
|
||||
'@typescript-eslint/utils': 5.28.0_l7pgrp53lxkdqes4ltx44plfmm
|
||||
eslint: 8.17.0
|
||||
jest: 28.1.1_@types+node@16.11.33
|
||||
jest: 28.1.1_ljamerpmo44qvadngd6o6tmh2u
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
@ -10207,7 +10240,7 @@ packages:
|
|||
is-stream: 1.1.0
|
||||
npm-run-path: 2.0.2
|
||||
p-finally: 1.0.0
|
||||
signal-exit: 3.0.4
|
||||
signal-exit: 3.0.7
|
||||
strip-eof: 1.0.0
|
||||
|
||||
/execa/5.1.1:
|
||||
|
@ -11079,6 +11112,7 @@ packages:
|
|||
minimatch: 3.1.2
|
||||
once: 1.4.0
|
||||
path-is-absolute: 1.0.1
|
||||
dev: true
|
||||
|
||||
/glob/7.2.3:
|
||||
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
|
||||
|
@ -11179,10 +11213,6 @@ packages:
|
|||
/graceful-fs/4.2.10:
|
||||
resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==}
|
||||
|
||||
/graceful-fs/4.2.8:
|
||||
resolution: {integrity: sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==}
|
||||
dev: false
|
||||
|
||||
/handlebars/4.7.7:
|
||||
resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==}
|
||||
engines: {node: '>=0.4.7'}
|
||||
|
@ -12178,12 +12208,13 @@ packages:
|
|||
resolution: {integrity: sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
'@babel/core': 7.15.5
|
||||
'@babel/core': 7.17.4
|
||||
'@istanbuljs/schema': 0.1.3
|
||||
istanbul-lib-coverage: 3.2.0
|
||||
semver: 6.3.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/istanbul-lib-instrument/5.2.0:
|
||||
resolution: {integrity: sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==}
|
||||
|
@ -12196,7 +12227,6 @@ packages:
|
|||
semver: 6.3.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/istanbul-lib-report/3.0.0:
|
||||
resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==}
|
||||
|
@ -12313,6 +12343,34 @@ packages:
|
|||
- ts-node
|
||||
dev: true
|
||||
|
||||
/jest-cli/28.1.1_ljamerpmo44qvadngd6o6tmh2u:
|
||||
resolution: {integrity: sha512-+sUfVbJqb1OjBZ0OdBbI6OWfYM1i7bSfzYy6gze1F1w3OKWq8ZTEKkZ8a7ZQPq6G/G1qMh/uKqpdWhgl11NFQQ==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
|
||||
peerDependenciesMeta:
|
||||
node-notifier:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@jest/core': 28.1.1_ts-node@10.7.0
|
||||
'@jest/test-result': 28.1.1
|
||||
'@jest/types': 28.1.1
|
||||
chalk: 4.1.2
|
||||
exit: 0.1.2
|
||||
graceful-fs: 4.2.10
|
||||
import-local: 3.1.0
|
||||
jest-config: 28.1.1_ljamerpmo44qvadngd6o6tmh2u
|
||||
jest-util: 28.1.1
|
||||
jest-validate: 28.1.1
|
||||
prompts: 2.4.2
|
||||
yargs: 17.5.1
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/jest-config/28.1.1_@types+node@16.11.33:
|
||||
resolution: {integrity: sha512-tASynMhS+jVV85zKvjfbJ8nUyJS/jUSYZ5KQxLUN2ZCvcQc/OmhQl2j6VEL3ezQkNofxn5pQ3SPYWPHb0unTZA==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
|
||||
|
@ -12352,6 +12410,86 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/jest-config/28.1.1_ljamerpmo44qvadngd6o6tmh2u:
|
||||
resolution: {integrity: sha512-tASynMhS+jVV85zKvjfbJ8nUyJS/jUSYZ5KQxLUN2ZCvcQc/OmhQl2j6VEL3ezQkNofxn5pQ3SPYWPHb0unTZA==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
|
||||
peerDependencies:
|
||||
'@types/node': '*'
|
||||
ts-node: '>=9.0.0'
|
||||
peerDependenciesMeta:
|
||||
'@types/node':
|
||||
optional: true
|
||||
ts-node:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/core': 7.17.4
|
||||
'@jest/test-sequencer': 28.1.1
|
||||
'@jest/types': 28.1.1
|
||||
'@types/node': 16.10.1
|
||||
babel-jest: 28.1.1_@babel+core@7.17.4
|
||||
chalk: 4.1.2
|
||||
ci-info: 3.3.1
|
||||
deepmerge: 4.2.2
|
||||
glob: 7.2.3
|
||||
graceful-fs: 4.2.10
|
||||
jest-circus: 28.1.1
|
||||
jest-environment-node: 28.1.1
|
||||
jest-get-type: 28.0.2
|
||||
jest-regex-util: 28.0.2
|
||||
jest-resolve: 28.1.1
|
||||
jest-runner: 28.1.1
|
||||
jest-util: 28.1.1
|
||||
jest-validate: 28.1.1
|
||||
micromatch: 4.0.5
|
||||
parse-json: 5.2.0
|
||||
pretty-format: 28.1.1
|
||||
slash: 3.0.0
|
||||
strip-json-comments: 3.1.1
|
||||
ts-node: 10.7.0_bvx74sey2cc4ezqwnfhit2yjju
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/jest-config/28.1.1_p2brwx6nx5zpemlvbnwk444zqy:
|
||||
resolution: {integrity: sha512-tASynMhS+jVV85zKvjfbJ8nUyJS/jUSYZ5KQxLUN2ZCvcQc/OmhQl2j6VEL3ezQkNofxn5pQ3SPYWPHb0unTZA==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
|
||||
peerDependencies:
|
||||
'@types/node': '*'
|
||||
ts-node: '>=9.0.0'
|
||||
peerDependenciesMeta:
|
||||
'@types/node':
|
||||
optional: true
|
||||
ts-node:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/core': 7.17.4
|
||||
'@jest/test-sequencer': 28.1.1
|
||||
'@jest/types': 28.1.1
|
||||
'@types/node': 16.11.33
|
||||
babel-jest: 28.1.1_@babel+core@7.17.4
|
||||
chalk: 4.1.2
|
||||
ci-info: 3.3.1
|
||||
deepmerge: 4.2.2
|
||||
glob: 7.2.3
|
||||
graceful-fs: 4.2.10
|
||||
jest-circus: 28.1.1
|
||||
jest-environment-node: 28.1.1
|
||||
jest-get-type: 28.0.2
|
||||
jest-regex-util: 28.0.2
|
||||
jest-resolve: 28.1.1
|
||||
jest-runner: 28.1.1
|
||||
jest-util: 28.1.1
|
||||
jest-validate: 28.1.1
|
||||
micromatch: 4.0.5
|
||||
parse-json: 5.2.0
|
||||
pretty-format: 28.1.1
|
||||
slash: 3.0.0
|
||||
strip-json-comments: 3.1.1
|
||||
ts-node: 10.7.0_bvx74sey2cc4ezqwnfhit2yjju
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/jest-diff/27.5.1:
|
||||
resolution: {integrity: sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==}
|
||||
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
|
||||
|
@ -12426,9 +12564,9 @@ packages:
|
|||
jest-serializer: 26.6.2
|
||||
jest-util: 26.6.2
|
||||
jest-worker: 26.6.2
|
||||
micromatch: 4.0.4
|
||||
micromatch: 4.0.5
|
||||
sane: 4.1.0
|
||||
walker: 1.0.7
|
||||
walker: 1.0.8
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
|
||||
|
@ -12445,7 +12583,7 @@ packages:
|
|||
jest-regex-util: 28.0.2
|
||||
jest-util: 28.1.1
|
||||
jest-worker: 28.1.1
|
||||
micromatch: 4.0.4
|
||||
micromatch: 4.0.5
|
||||
walker: 1.0.8
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
|
@ -12488,7 +12626,7 @@ packages:
|
|||
'@types/stack-utils': 2.0.1
|
||||
chalk: 4.1.2
|
||||
graceful-fs: 4.2.10
|
||||
micromatch: 4.0.4
|
||||
micromatch: 4.0.5
|
||||
pretty-format: 28.1.1
|
||||
slash: 3.0.0
|
||||
stack-utils: 2.0.5
|
||||
|
@ -12551,7 +12689,7 @@ packages:
|
|||
jest-pnp-resolver: 1.2.2_jest-resolve@28.1.1
|
||||
jest-util: 28.1.1
|
||||
jest-validate: 28.1.1
|
||||
resolve: 1.22.0
|
||||
resolve: 1.22.1
|
||||
resolve.exports: 1.1.0
|
||||
slash: 3.0.0
|
||||
dev: true
|
||||
|
@ -12600,7 +12738,7 @@ packages:
|
|||
cjs-module-lexer: 1.2.2
|
||||
collect-v8-coverage: 1.0.1
|
||||
execa: 5.1.1
|
||||
glob: 7.2.0
|
||||
glob: 7.2.3
|
||||
graceful-fs: 4.2.10
|
||||
jest-haste-map: 28.1.1
|
||||
jest-message-util: 28.1.1
|
||||
|
@ -12662,7 +12800,7 @@ packages:
|
|||
chalk: 4.1.2
|
||||
graceful-fs: 4.2.10
|
||||
is-ci: 2.0.0
|
||||
micromatch: 4.0.4
|
||||
micromatch: 4.0.5
|
||||
|
||||
/jest-util/28.1.1:
|
||||
resolution: {integrity: sha512-FktOu7ca1DZSyhPAxgxB6hfh2+9zMoJ7aEQA759Z6p45NuO8mWcqujH+UdHlCm/V6JTWwDztM2ITCzU1ijJAfw==}
|
||||
|
@ -12673,7 +12811,7 @@ packages:
|
|||
chalk: 4.1.2
|
||||
ci-info: 3.3.1
|
||||
graceful-fs: 4.2.10
|
||||
picomatch: 2.3.0
|
||||
picomatch: 2.3.1
|
||||
dev: true
|
||||
|
||||
/jest-validate/28.1.1:
|
||||
|
@ -12748,6 +12886,26 @@ packages:
|
|||
- ts-node
|
||||
dev: true
|
||||
|
||||
/jest/28.1.1_ljamerpmo44qvadngd6o6tmh2u:
|
||||
resolution: {integrity: sha512-qw9YHBnjt6TCbIDMPMpJZqf9E12rh6869iZaN08/vpOGgHJSAaLLUn6H8W3IAEuy34Ls3rct064mZLETkxJ2XA==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
|
||||
peerDependenciesMeta:
|
||||
node-notifier:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@jest/core': 28.1.1_ts-node@10.7.0
|
||||
'@jest/types': 28.1.1
|
||||
import-local: 3.1.0
|
||||
jest-cli: 28.1.1_ljamerpmo44qvadngd6o6tmh2u
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/joycon/3.1.1:
|
||||
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
|
||||
engines: {node: '>=10'}
|
||||
|
@ -12856,7 +13014,6 @@ packages:
|
|||
resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==}
|
||||
engines: {node: '>=6'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/jsonfile/6.1.0:
|
||||
resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
|
||||
|
@ -13318,16 +13475,10 @@ packages:
|
|||
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
||||
dev: true
|
||||
|
||||
/makeerror/1.0.11:
|
||||
resolution: {integrity: sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=}
|
||||
dependencies:
|
||||
tmpl: 1.0.5
|
||||
|
||||
/makeerror/1.0.12:
|
||||
resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==}
|
||||
dependencies:
|
||||
tmpl: 1.0.5
|
||||
dev: true
|
||||
|
||||
/map-age-cleaner/0.1.3:
|
||||
resolution: {integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==}
|
||||
|
@ -13880,6 +14031,7 @@ packages:
|
|||
dependencies:
|
||||
braces: 3.0.2
|
||||
picomatch: 2.3.0
|
||||
dev: true
|
||||
|
||||
/micromatch/4.0.5:
|
||||
resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
|
||||
|
@ -14288,7 +14440,7 @@ packages:
|
|||
whatwg-url: 5.0.0
|
||||
|
||||
/node-int64/0.4.0:
|
||||
resolution: {integrity: sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=}
|
||||
resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
|
||||
|
||||
/node-libs-browser/2.2.1:
|
||||
resolution: {integrity: sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==}
|
||||
|
@ -14363,7 +14515,7 @@ packages:
|
|||
resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
|
||||
dependencies:
|
||||
hosted-git-info: 2.8.9
|
||||
resolve: 1.22.0
|
||||
resolve: 1.22.1
|
||||
semver: 5.7.1
|
||||
validate-npm-package-license: 3.0.4
|
||||
dev: true
|
||||
|
@ -16331,7 +16483,7 @@ packages:
|
|||
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
glob: 7.2.0
|
||||
glob: 7.2.3
|
||||
|
||||
/ripemd160/2.0.2:
|
||||
resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==}
|
||||
|
@ -16421,7 +16573,7 @@ packages:
|
|||
fb-watchman: 2.0.1
|
||||
micromatch: 3.1.10
|
||||
minimist: 1.2.6
|
||||
walker: 1.0.7
|
||||
walker: 1.0.8
|
||||
|
||||
/scheduler/0.22.0:
|
||||
resolution: {integrity: sha512-6QAm1BgQI88NPYymgGQLCZgvep4FyePDWFpXVK+zNSUgHwlqpJy8VEh8Et0KxTACS4VWwMousBElAZOH9nkkoQ==}
|
||||
|
@ -17409,7 +17561,7 @@ packages:
|
|||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
'@istanbuljs/schema': 0.1.3
|
||||
glob: 7.2.0
|
||||
glob: 7.2.3
|
||||
minimatch: 3.1.2
|
||||
|
||||
/text-decoding/1.0.0:
|
||||
|
@ -17417,7 +17569,7 @@ packages:
|
|||
dev: false
|
||||
|
||||
/text-table/0.2.0:
|
||||
resolution: {integrity: sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=}
|
||||
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
||||
dev: true
|
||||
|
||||
/textextensions/5.14.0:
|
||||
|
@ -18269,16 +18421,10 @@ packages:
|
|||
resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==}
|
||||
dev: true
|
||||
|
||||
/walker/1.0.7:
|
||||
resolution: {integrity: sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=}
|
||||
dependencies:
|
||||
makeerror: 1.0.11
|
||||
|
||||
/walker/1.0.8:
|
||||
resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==}
|
||||
dependencies:
|
||||
makeerror: 1.0.12
|
||||
dev: true
|
||||
|
||||
/watchpack-chokidar2/2.0.1:
|
||||
resolution: {integrity: sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==}
|
||||
|
|
Loading…
Reference in New Issue