feat: swagger
This commit is contained in:
parent
bda96dbd14
commit
8743492bc2
36
README.md
36
README.md
@ -7,38 +7,6 @@
|
||||
2) yarn dev - запуск проекта в режиме разработки
|
||||
```
|
||||
|
||||
## Переменные окружения сервиса:
|
||||
# Ссылки на другую документацию:
|
||||
|
||||
**Для конфигурации сервера**:
|
||||
|
||||
```
|
||||
ENVIRONMENT - application environment
|
||||
HTTP_HOST - service host
|
||||
HTTP_PORT - service port
|
||||
PUBLIC_ACCESS_SECRET_KEY - secret to verify private access secret key
|
||||
```
|
||||
|
||||
**Для конфигурации базы данных**:
|
||||
|
||||
```
|
||||
DB_HOST - mongo host
|
||||
DB_PORT - mongo port
|
||||
DB_USERNAME - mongo username
|
||||
DB_PASSWORD - mongo password
|
||||
DB_NAME - database name
|
||||
```
|
||||
|
||||
**Для подключения к сервису авторизации**
|
||||
|
||||
```
|
||||
AUTH_SERVICE_HOST - auth service host
|
||||
AUTH_SERVICE_PORT - auth service port
|
||||
```
|
||||
|
||||
## Среды окружения
|
||||
|
||||
```
|
||||
development - среда для разработки
|
||||
staging - среда для тестирования продукта
|
||||
production - среда продакшена
|
||||
```
|
||||
- [**Переменные окружения сервиса**](./docs/environment/README.md)
|
||||
|
35
docs/environment/README.md
Normal file
35
docs/environment/README.md
Normal file
@ -0,0 +1,35 @@
|
||||
# Переменные окружения сервиса:
|
||||
|
||||
**Для конфигурации сервера**:
|
||||
|
||||
```
|
||||
ENVIRONMENT - application environment
|
||||
HTTP_HOST - service host
|
||||
HTTP_PORT - service port
|
||||
PUBLIC_ACCESS_SECRET_KEY - secret to verify private access secret key
|
||||
```
|
||||
|
||||
**Для конфигурации базы данных**:
|
||||
|
||||
```
|
||||
DB_HOST - mongo host
|
||||
DB_PORT - mongo port
|
||||
DB_USERNAME - mongo username
|
||||
DB_PASSWORD - mongo password
|
||||
DB_NAME - database name
|
||||
```
|
||||
|
||||
**Для подключения к сервису авторизации**
|
||||
|
||||
```
|
||||
AUTH_SERVICE_HOST - auth service host
|
||||
AUTH_SERVICE_PORT - auth service port
|
||||
```
|
||||
|
||||
## Среды окружения
|
||||
|
||||
```
|
||||
development - среда для разработки
|
||||
staging - среда для тестирования продукта
|
||||
production - среда продакшена
|
||||
```
|
@ -37,6 +37,8 @@
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^17.1.2",
|
||||
"@commitlint/config-conventional": "^17.1.0",
|
||||
"@fastify/swagger": "^8.2.1",
|
||||
"@fastify/swagger-ui": "^1.3.0",
|
||||
"@types/bcryptjs": "^2.4.2",
|
||||
"@types/jest": "^29.2.3",
|
||||
"@types/jsonwebtoken": "^8.5.9",
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { Router } from "@/server/router";
|
||||
|
||||
import { setAccountRoutes } from "@/routes/account.routes";
|
||||
import { setPrivilegeRoutes } from "@/routes/privilege.routes";
|
||||
import { setRoleRoutes } from "@/routes/role.routes";
|
||||
import { setTariffRoutes } from "@/routes/tariff.routes";
|
||||
|
||||
import type { FastifyInstance } from "fastify";
|
||||
|
||||
export const combineRoutes = (server: FastifyInstance): void => {
|
||||
server.register(setRoleRoutes, { prefix: "/role" });
|
||||
server.register(setAccountRoutes, { prefix: "/account" });
|
||||
server.register(setPrivilegeRoutes, { prefix: "/privilege" });
|
||||
server.register(setTariffRoutes, { prefix: "/tariff" });
|
||||
export const combineRoutes = (router: Router): void => {
|
||||
router.group("/role", setRoleRoutes);
|
||||
router.group("/account", setAccountRoutes);
|
||||
router.group("/privilege", setPrivilegeRoutes);
|
||||
router.group("/tariff", setTariffRoutes);
|
||||
};
|
||||
|
@ -1,20 +1,7 @@
|
||||
import path from "path";
|
||||
import dotenv from "dotenv";
|
||||
|
||||
import { DEFAULT } from "@/constants/default";
|
||||
|
||||
import type { Environment } from "@/types/environment";
|
||||
|
||||
const defineEnvironment = (): Environment => {
|
||||
const environments: Environment[] = ["development", "staging", "production"];
|
||||
const environment = process.env.ENVIRONMENT as Environment | undefined;
|
||||
|
||||
if (environment && environments.includes(environment)) {
|
||||
return environment;
|
||||
}
|
||||
|
||||
return DEFAULT.environment;
|
||||
};
|
||||
import { defineEnvironment } from "./define-environment";
|
||||
|
||||
export const configureENV = () => {
|
||||
const environment = defineEnvironment();
|
||||
|
14
src/configuration/define-environment.ts
Normal file
14
src/configuration/define-environment.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { DEFAULT } from "@/constants/default";
|
||||
|
||||
import type { Environment } from "@/types/environment";
|
||||
|
||||
export const defineEnvironment = (): Environment => {
|
||||
const environments: Environment[] = ["development", "staging", "production"];
|
||||
const environment = process.env.ENVIRONMENT as Environment | undefined;
|
||||
|
||||
if (environment && environments.includes(environment)) {
|
||||
return environment;
|
||||
}
|
||||
|
||||
return DEFAULT.environment;
|
||||
};
|
@ -1,8 +1,11 @@
|
||||
import cors from "@fastify/cors";
|
||||
import cookie from "@fastify/cookie";
|
||||
import jwt from "@fastify/jwt";
|
||||
import swagger from "@fastify/swagger";
|
||||
import swaggerUI from "@fastify/swagger-ui";
|
||||
|
||||
import printRoutes from "@/plugins/print-routes";
|
||||
import { CONFIGURATION } from "@/constants/configuration";
|
||||
|
||||
import type { FastifyInstance } from "fastify";
|
||||
import type { PluginsOptions } from "@/types/configuration/plugins-options";
|
||||
@ -11,6 +14,33 @@ export const registerFastifyPlugins = (fastify: FastifyInstance, options: Plugin
|
||||
fastify.register(cors, options.cors);
|
||||
fastify.register(cookie, options.cookie);
|
||||
fastify.register(jwt, options.jwt);
|
||||
fastify.register(swagger, {
|
||||
openapi: {
|
||||
info: {
|
||||
title: "Hub admin backend",
|
||||
description: "Тестирование сервиса админ панели хаба",
|
||||
version: "0.1.0",
|
||||
},
|
||||
servers: [{ url: `http://${CONFIGURATION.http.host || "localhost"}:${CONFIGURATION.http.port}` }],
|
||||
components: {
|
||||
securitySchemes: {
|
||||
bearer: {
|
||||
type: "http",
|
||||
bearerFormat: "JWT",
|
||||
scheme: "bearer",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
hideUntagged: true,
|
||||
});
|
||||
fastify.register(swaggerUI, {
|
||||
routePrefix: "/swagger",
|
||||
uiConfig: {
|
||||
docExpansion: "full",
|
||||
deepLinking: false,
|
||||
},
|
||||
});
|
||||
fastify.register(printRoutes);
|
||||
|
||||
return fastify;
|
||||
|
@ -5,10 +5,10 @@ import { AccountModel } from "@/models/account.model";
|
||||
import { getUser } from "@/clients/auth";
|
||||
import { validateEmptyFields } from "@/utils/validate-empty-fields";
|
||||
|
||||
import type { FastifyReply } from "fastify";
|
||||
import type { CreateAccountRequest, GetAccountRequest } from "./types";
|
||||
import type { FastifyReply, FastifyRequest } from "fastify";
|
||||
import type { GetAccountRequest } from "./types";
|
||||
|
||||
export const createAccount = async (request: CreateAccountRequest, reply: FastifyReply) => {
|
||||
export const createAccount = async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
if (!Types.ObjectId.isValid(request.user.id)) {
|
||||
reply.status(400);
|
||||
return new Error("invalid user id");
|
||||
|
@ -1,6 +1,7 @@
|
||||
import type { FastifyRequest } from "fastify";
|
||||
|
||||
import type { CreateAccountRoute, GetAccountRoute } from "@/types/routes/account-routes.type";
|
||||
|
||||
export type CreateAccountRequest = FastifyRequest<CreateAccountRoute>;
|
||||
export type GetAccountRequest = FastifyRequest<GetAccountRoute>;
|
||||
export type GetAccountRequest = FastifyRequest<{
|
||||
Params?: {
|
||||
userId?: string;
|
||||
};
|
||||
}>;
|
||||
|
@ -2,7 +2,7 @@ import type { FastifyRequest, FastifyReply, HookHandlerDoneFunction as Done } fr
|
||||
|
||||
export const verifyUser = async (request: FastifyRequest, reply: FastifyReply, done: Done) => {
|
||||
try {
|
||||
const { id } = await request.jwtVerify<{ id?: string }>({ onlyCookie: true });
|
||||
const { id } = await request.jwtVerify<{ id?: string }>();
|
||||
|
||||
if (!id) {
|
||||
reply.status(401);
|
||||
|
@ -15,7 +15,11 @@ export const validatePrivilege = (privilege: RawPrivilege): Error | null => {
|
||||
return null;
|
||||
};
|
||||
|
||||
export const defineGetAllPrivilegiesFormat = (query: string): GetAllPrivilegiesFormat => {
|
||||
export const defineGetAllPrivilegiesFormat = (query?: string): GetAllPrivilegiesFormat => {
|
||||
if (!query) {
|
||||
return "array";
|
||||
}
|
||||
|
||||
const formats: GetAllPrivilegiesFormat[] = ["array", "map"];
|
||||
const findedFormat = formats.find((format) => query === format);
|
||||
|
||||
|
@ -53,7 +53,7 @@ export const registerPrivilege = async (request: RegisterPrivilegeRequest, reply
|
||||
};
|
||||
|
||||
export const getAllPrivilegies = async (request: GetAllPrivilegiesRequest, reply: FastifyReply) => {
|
||||
const format = defineGetAllPrivilegiesFormat(request.query?.format || "");
|
||||
const format = defineGetAllPrivilegiesFormat(request.query?.format);
|
||||
const privilegies = await PrivilegeModel.find({}).lean();
|
||||
|
||||
if (format === "array") {
|
||||
@ -69,6 +69,7 @@ export const getAllPrivilegies = async (request: GetAllPrivilegiesRequest, reply
|
||||
}
|
||||
|
||||
reply.status(500);
|
||||
|
||||
return new Error("format not defined");
|
||||
};
|
||||
|
||||
|
@ -73,33 +73,32 @@ export const removeRole = async (request: RemoveRoleRequest, reply: FastifyReply
|
||||
};
|
||||
|
||||
export const getRole = async (request: GetRoleRequest, reply: FastifyReply) => {
|
||||
const { name, id } = request.body || {};
|
||||
const { query } = request.params || {};
|
||||
|
||||
if (!name && !id && !query) {
|
||||
reply.status(400);
|
||||
return new Error("either name or id must be filled");
|
||||
}
|
||||
|
||||
if (name || id) {
|
||||
return RoleModel.findOne({
|
||||
$or: [
|
||||
{ name, isDeleted: false },
|
||||
{ id, isDeleted: false },
|
||||
],
|
||||
}).lean();
|
||||
}
|
||||
|
||||
if (!query) {
|
||||
reply.status(400);
|
||||
return new Error("query is empty");
|
||||
}
|
||||
|
||||
if (Types.ObjectId.isValid(query)) {
|
||||
return RoleModel.findOne({ _id: new Types.ObjectId(query), isDeleted: false }).lean();
|
||||
const role = await RoleModel.findOne({ _id: new Types.ObjectId(query), isDeleted: false }).lean();
|
||||
|
||||
if (!role) {
|
||||
reply.status(404);
|
||||
return new Error("role not found");
|
||||
}
|
||||
|
||||
return role;
|
||||
}
|
||||
|
||||
return RoleModel.findOne({ name: query, isDeleted: false }).lean();
|
||||
const role = await RoleModel.findOne({ name: query, isDeleted: false }).lean();
|
||||
|
||||
if (!role) {
|
||||
reply.status(404);
|
||||
return new Error("role not found");
|
||||
}
|
||||
|
||||
return role;
|
||||
};
|
||||
|
||||
export const replaceRole = async (request: UpdateRoleRequest, reply: FastifyReply) => {
|
||||
|
@ -9,9 +9,6 @@ export type CreateRoleRequest = FastifyRequest<{ Body: RoleRequest }>;
|
||||
export type RemoveRoleRequest = FastifyRequest<{ Body: { id?: string } }>;
|
||||
|
||||
export type GetRoleRequest = FastifyRequest<{
|
||||
Body?: Pick<RoleRequest, "name"> & {
|
||||
id?: string;
|
||||
};
|
||||
Params: {
|
||||
query?: string;
|
||||
};
|
||||
|
@ -53,12 +53,8 @@ export const createTariff = async (request: CreateTariffRequest, reply: FastifyR
|
||||
}
|
||||
}
|
||||
|
||||
const privilegiesMap = requestBody.privilegies.reduce<Record<string, Privilege[]>>((accamulator, privilege) => {
|
||||
if (!accamulator[privilege.privilegeId]) {
|
||||
accamulator[privilege.privilegeId] = [];
|
||||
}
|
||||
|
||||
accamulator[privilege.privilegeId].push(privilege);
|
||||
const privilegiesMap = requestBody.privilegies.reduce<Record<string, Privilege>>((accamulator, privilege) => {
|
||||
accamulator[privilege.privilegeId] = privilege;
|
||||
|
||||
return accamulator;
|
||||
}, {});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type { FastifyRequest } from "fastify";
|
||||
import type { CreateTariffRoute, ReplaceTariffRoute } from "@/types/routes/tariff-routes.type";
|
||||
import type { TariffMessage } from "@/types/messages/tariff-message.type";
|
||||
|
||||
export type GetTariffRequest = FastifyRequest<{
|
||||
Params?: {
|
||||
@ -7,5 +7,11 @@ export type GetTariffRequest = FastifyRequest<{
|
||||
};
|
||||
}>;
|
||||
|
||||
export type CreateTariffRequest = FastifyRequest<CreateTariffRoute>;
|
||||
export type ReplaceTariffRequest = FastifyRequest<ReplaceTariffRoute>;
|
||||
export type CreateTariffRequest = FastifyRequest<{
|
||||
Body?: TariffMessage;
|
||||
}>;
|
||||
|
||||
export type ReplaceTariffRequest = FastifyRequest<{
|
||||
Body?: TariffMessage;
|
||||
Params?: { id?: string };
|
||||
}>;
|
||||
|
@ -15,7 +15,7 @@ const server = new Server({
|
||||
jwt: {
|
||||
secret: {
|
||||
public: CONFIGURATION.service.publicAccessSecretKey,
|
||||
private: "",
|
||||
private: "secret",
|
||||
},
|
||||
verify: {
|
||||
allowedIss: "pena-auth-service",
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Schema, model, SchemaDefinition } from "mongoose";
|
||||
|
||||
import { EloquentSchema } from "./eloquent-model.schema";
|
||||
import { eloquentSchema } from "./eloquent.schema";
|
||||
|
||||
import type { Account } from "@/types/models/account.type";
|
||||
|
||||
@ -22,7 +22,7 @@ const schema: SchemaDefinition<Account> = {
|
||||
type: String,
|
||||
default: "user",
|
||||
},
|
||||
...EloquentSchema,
|
||||
...eloquentSchema,
|
||||
};
|
||||
|
||||
const schemaSettings = {
|
||||
|
@ -1,32 +0,0 @@
|
||||
import { Schema, SchemaDefinition } from "mongoose";
|
||||
|
||||
import type { EloquentModel } from "@/types/models/eloquent-model.type";
|
||||
|
||||
export const schema: SchemaDefinition<EloquentModel> = {
|
||||
createdAt: {
|
||||
type: Date,
|
||||
required: true,
|
||||
default: Date.now,
|
||||
},
|
||||
updatedAt: {
|
||||
type: Date,
|
||||
required: true,
|
||||
default: Date.now,
|
||||
},
|
||||
deletedAt: {
|
||||
type: Date,
|
||||
required: false,
|
||||
},
|
||||
isDeleted: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false,
|
||||
},
|
||||
};
|
||||
|
||||
const schemaSettings = {
|
||||
versionKey: false,
|
||||
collection: "privilegies",
|
||||
};
|
||||
|
||||
export const EloquentSchema = new Schema<EloquentModel>(schema, schemaSettings);
|
25
src/models/eloquent.schema.ts
Normal file
25
src/models/eloquent.schema.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { SchemaDefinition } from "mongoose";
|
||||
|
||||
import type { Eloquent } from "@/types/models/eloquent.type";
|
||||
|
||||
export const eloquentSchema: SchemaDefinition<Eloquent> = {
|
||||
createdAt: {
|
||||
type: Date,
|
||||
required: true,
|
||||
default: Date.now,
|
||||
},
|
||||
updatedAt: {
|
||||
type: Date,
|
||||
required: true,
|
||||
default: Date.now,
|
||||
},
|
||||
deletedAt: {
|
||||
type: Date,
|
||||
required: false,
|
||||
},
|
||||
isDeleted: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false,
|
||||
},
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
import { Schema, model, SchemaDefinition } from "mongoose";
|
||||
|
||||
import { EloquentSchema } from "./eloquent-model.schema";
|
||||
import { eloquentSchema } from "./eloquent.schema";
|
||||
|
||||
import type { Privilege } from "@/types/models/privilege.type";
|
||||
|
||||
@ -37,7 +37,7 @@ const schema: SchemaDefinition<Privilege> = {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
...EloquentSchema,
|
||||
...eloquentSchema,
|
||||
};
|
||||
|
||||
const schemaSettings = {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Schema, model, SchemaDefinition } from "mongoose";
|
||||
|
||||
import { EloquentSchema } from "./eloquent-model.schema";
|
||||
import { eloquentSchema } from "./eloquent.schema";
|
||||
|
||||
import type { Role } from "@/types/models/role.type";
|
||||
|
||||
@ -14,7 +14,7 @@ const schema: SchemaDefinition<Role> = {
|
||||
of: Boolean,
|
||||
default: {},
|
||||
},
|
||||
...EloquentSchema,
|
||||
...eloquentSchema,
|
||||
};
|
||||
|
||||
const schemaSettings = {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Schema, model, SchemaDefinition } from "mongoose";
|
||||
|
||||
import { EloquentSchema } from "./eloquent-model.schema";
|
||||
import { eloquentSchema } from "./eloquent.schema";
|
||||
import { PrivilegeSchema } from "./privilege.model";
|
||||
|
||||
import type { Tariff } from "@/types/models/tariff.type";
|
||||
@ -23,7 +23,7 @@ const schema: SchemaDefinition<Tariff> = {
|
||||
of: PrivilegeSchema,
|
||||
default: {},
|
||||
},
|
||||
...EloquentSchema,
|
||||
...eloquentSchema,
|
||||
};
|
||||
|
||||
const schemaSettings = {
|
||||
|
@ -8,7 +8,7 @@ type PrintRoutesRouteOptions = {
|
||||
|
||||
const METHODS_ORDER = ["GET", "POST", "PUT", "DELETE", "HEAD", "PATCH", "OPTIONS"];
|
||||
|
||||
const printRoutes = (routes: Array<RouteOptions & PrintRoutesRouteOptions> = []) => {
|
||||
const printRoutes = (routes: Array<RouteOptions & PrintRoutesRouteOptions> = [], isSwagger = false) => {
|
||||
if (routes.length === 0) {
|
||||
return;
|
||||
}
|
||||
@ -21,8 +21,9 @@ const printRoutes = (routes: Array<RouteOptions & PrintRoutesRouteOptions> = [])
|
||||
|
||||
return accamulator + `${methodsValue}\t${route.url}\n`;
|
||||
}, "");
|
||||
const swaggerOutput = isSwagger ? "GET\t/swagger\n" : "";
|
||||
|
||||
console.info(`\n\nAvailable routes:\n${output}`);
|
||||
console.info(`\n\nAvailable routes:\n${output + swaggerOutput}`);
|
||||
};
|
||||
|
||||
export default fastifyPlugin(
|
||||
@ -34,7 +35,7 @@ export default fastifyPlugin(
|
||||
});
|
||||
|
||||
instance.addHook("onReady", (next) => {
|
||||
printRoutes(routes);
|
||||
printRoutes(routes, !!instance.swagger);
|
||||
next();
|
||||
});
|
||||
|
||||
|
@ -1,16 +1,11 @@
|
||||
import { Router } from "@/server/router";
|
||||
|
||||
import { createAccount, getAccount } from "@/handlers/account";
|
||||
import { verifyUser } from "@/handlers/auth/middleware";
|
||||
|
||||
import type { FastifyInstance, FastifyPluginOptions } from "fastify";
|
||||
import type { GetAccountRoute, CreateAccountRoute } from "@/types/routes/account-routes.type";
|
||||
import { createAccountSchema, getAccountSchema } from "@/swagger/account";
|
||||
|
||||
export const setAccountRoutes = <T = FastifyPluginOptions>(
|
||||
server: FastifyInstance,
|
||||
opts: T,
|
||||
done: () => void
|
||||
): void => {
|
||||
server.get<GetAccountRoute>("/:userId", getAccount);
|
||||
server.post<CreateAccountRoute>("/", { preHandler: [verifyUser] }, createAccount);
|
||||
|
||||
done();
|
||||
export const setAccountRoutes = (router: Router): void => {
|
||||
router.get("/:userId", getAccount, { schema: getAccountSchema });
|
||||
router.post("/", createAccount, { preHandler: [verifyUser], schema: createAccountSchema });
|
||||
};
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { Router } from "@/server/router";
|
||||
|
||||
import {
|
||||
registerPrivilege,
|
||||
getAllPrivilegies,
|
||||
@ -6,18 +8,18 @@ import {
|
||||
replacePrivilege,
|
||||
} from "@/handlers/privilege";
|
||||
|
||||
import type { FastifyInstance, FastifyPluginOptions } from "fastify";
|
||||
import {
|
||||
getPrivilegiesSchema,
|
||||
getPrivilegeSchema,
|
||||
getServicePrivilegiesSchema,
|
||||
registerPrivilegeSchema,
|
||||
replacePrivilegeSchema,
|
||||
} from "@/swagger/privilege";
|
||||
|
||||
export const setPrivilegeRoutes = <T = FastifyPluginOptions>(
|
||||
server: FastifyInstance,
|
||||
opts: T,
|
||||
done: () => void
|
||||
): void => {
|
||||
server.get("/all", getAllPrivilegies);
|
||||
server.get("/:id", getPrivilege);
|
||||
server.get("/service/:serviceKey", getServicePrivilegies);
|
||||
server.post("/", registerPrivilege);
|
||||
server.put("/", replacePrivilege);
|
||||
|
||||
done();
|
||||
export const setPrivilegeRoutes = (router: Router): void => {
|
||||
router.get("/", getAllPrivilegies, { schema: getPrivilegiesSchema });
|
||||
router.get("/:id", getPrivilege, { schema: getPrivilegeSchema });
|
||||
router.get("/service/:serviceKey", getServicePrivilegies, { schema: getServicePrivilegiesSchema });
|
||||
router.post("/", registerPrivilege, { schema: registerPrivilegeSchema });
|
||||
router.put("/", replacePrivilege, { schema: replacePrivilegeSchema });
|
||||
};
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { Router } from "@/server/router";
|
||||
|
||||
import {
|
||||
getRole,
|
||||
getAllRoles,
|
||||
@ -9,17 +11,24 @@ import {
|
||||
restoreRole,
|
||||
} from "@/handlers/roles";
|
||||
|
||||
import type { FastifyInstance, FastifyPluginOptions } from "fastify";
|
||||
import {
|
||||
getRolesSchema,
|
||||
getRoleSchema,
|
||||
createRoleSchema,
|
||||
restoreRoleSchema,
|
||||
updateRoleSchema,
|
||||
replaceRoleSchema,
|
||||
removeRoleSchema,
|
||||
deleteRoleSchema,
|
||||
} from "@/swagger/role";
|
||||
|
||||
export const setRoleRoutes = <T = FastifyPluginOptions>(server: FastifyInstance, opts: T, done: () => void): void => {
|
||||
server.get("/all", getAllRoles);
|
||||
server.get("/:query", getRole);
|
||||
server.post("/", createRole);
|
||||
server.post("/restore", restoreRole);
|
||||
server.patch("/:query", updateRole);
|
||||
server.put("/:query", replaceRole);
|
||||
server.delete("/", removeRole);
|
||||
server.delete("/delete", deleteRole);
|
||||
|
||||
done();
|
||||
export const setRoleRoutes = (router: Router): void => {
|
||||
router.get("/", getAllRoles, { schema: getRolesSchema });
|
||||
router.get("/:query", getRole, { schema: getRoleSchema });
|
||||
router.post("/", createRole, { schema: createRoleSchema });
|
||||
router.post("/restore", restoreRole, { schema: restoreRoleSchema });
|
||||
router.patch("/:query", updateRole, { schema: updateRoleSchema });
|
||||
router.put("/:query", replaceRole, { schema: replaceRoleSchema });
|
||||
router.delete("/", removeRole, { schema: removeRoleSchema });
|
||||
router.delete("/delete", deleteRole, { schema: deleteRoleSchema });
|
||||
};
|
||||
|
@ -1,14 +1,13 @@
|
||||
import { Router } from "@/server/router";
|
||||
|
||||
import { createTariff, replaceTariff, getTariff, getTariffs } from "@/handlers/tariff";
|
||||
import { verifyUser } from "@/handlers/auth/middleware";
|
||||
|
||||
import type { FastifyInstance, FastifyPluginOptions } from "fastify";
|
||||
import type { CreateTariffRoute, ReplaceTariffRoute } from "@/types/routes/tariff-routes.type";
|
||||
import { getTariffSchema, getTariffsSchema, createTariffsSchema, replaceTariffsSchema } from "@/swagger/tariff";
|
||||
|
||||
export const setTariffRoutes = <T = FastifyPluginOptions>(server: FastifyInstance, opts: T, done: () => void): void => {
|
||||
server.get("/:id", getTariff);
|
||||
server.get("/", getTariffs);
|
||||
server.post<CreateTariffRoute>("/", { preHandler: [verifyUser] }, createTariff);
|
||||
server.put<ReplaceTariffRoute>("/", { preHandler: [verifyUser] }, replaceTariff);
|
||||
|
||||
done();
|
||||
export const setTariffRoutes = (router: Router): void => {
|
||||
router.get("/:id", getTariff, { schema: getTariffSchema });
|
||||
router.get("/", getTariffs, { schema: getTariffsSchema });
|
||||
router.post("/", createTariff, { preHandler: [verifyUser], schema: createTariffsSchema });
|
||||
router.put("/", replaceTariff, { preHandler: [verifyUser], schema: replaceTariffsSchema });
|
||||
};
|
||||
|
@ -1,6 +1,8 @@
|
||||
import fastify, { FastifyInstance } from "fastify";
|
||||
import { connect as mongoConnect } from "mongoose";
|
||||
|
||||
import { Router } from "./router";
|
||||
|
||||
import { registerFastifyPlugins } from "@/configuration/register-fastify-plugins";
|
||||
import { combineRoutes } from "@/configuration/combine-routes";
|
||||
import { constituteMongoURI } from "@/configuration/constitute-mongo-uri";
|
||||
@ -43,7 +45,7 @@ export class Server {
|
||||
registerFastifyPlugins(this.fastify, pluginsOptions);
|
||||
}
|
||||
|
||||
combineRoutes(this.fastify);
|
||||
combineRoutes(new Router(this.fastify));
|
||||
}
|
||||
|
||||
public start = async () => {
|
||||
@ -51,7 +53,10 @@ export class Server {
|
||||
const databaseConnection = this.databaseOptions ? mongoConnect(constituteMongoURI(this.databaseOptions)) : null;
|
||||
|
||||
await Promise.all([databaseConnection, fasticyConnection])
|
||||
.then(() => console.info(`server started on ${this.serverOptions?.host}:${this.serverOptions?.port}`))
|
||||
.then(() => {
|
||||
this.fastify.swagger();
|
||||
console.info(`server started on ${this.serverOptions?.host}:${this.serverOptions?.port}`);
|
||||
})
|
||||
.catch((reason) => console.error(reason));
|
||||
};
|
||||
|
||||
|
77
src/server/router.ts
Normal file
77
src/server/router.ts
Normal file
@ -0,0 +1,77 @@
|
||||
import type {
|
||||
FastifyInstance,
|
||||
RouteHandlerMethod,
|
||||
RawRequestDefaultExpression,
|
||||
RawReplyDefaultExpression,
|
||||
RouteShorthandOptions,
|
||||
FastifyPluginOptions,
|
||||
RawServerDefault,
|
||||
RouteGenericInterface,
|
||||
} from "fastify";
|
||||
|
||||
type HandlerMethod<T extends RouteGenericInterface> = RouteHandlerMethod<
|
||||
RawServerDefault,
|
||||
RawRequestDefaultExpression<RawServerDefault>,
|
||||
RawReplyDefaultExpression<RawServerDefault>,
|
||||
T
|
||||
>;
|
||||
|
||||
export class Router {
|
||||
private fastifyInstance: FastifyInstance;
|
||||
|
||||
constructor(fastifyInstance: FastifyInstance) {
|
||||
this.fastifyInstance = fastifyInstance;
|
||||
}
|
||||
|
||||
public group = (path: string, combineRoutes: (router: Router) => void) => {
|
||||
this.fastifyInstance.register(
|
||||
(server: FastifyInstance, opts: FastifyPluginOptions, done: () => void) => {
|
||||
const router = new Router(server);
|
||||
|
||||
combineRoutes(router);
|
||||
done();
|
||||
},
|
||||
{ prefix: path }
|
||||
);
|
||||
};
|
||||
|
||||
public get = <T extends RouteGenericInterface>(
|
||||
path: string,
|
||||
handler: HandlerMethod<T>,
|
||||
options: RouteShorthandOptions
|
||||
) => {
|
||||
this.fastifyInstance.get(path, options, handler);
|
||||
};
|
||||
|
||||
public post = <T extends RouteGenericInterface>(
|
||||
path: string,
|
||||
handler: HandlerMethod<T>,
|
||||
options: RouteShorthandOptions
|
||||
) => {
|
||||
this.fastifyInstance.post(path, options, handler);
|
||||
};
|
||||
|
||||
public put = <T extends RouteGenericInterface>(
|
||||
path: string,
|
||||
handler: HandlerMethod<T>,
|
||||
options: RouteShorthandOptions
|
||||
) => {
|
||||
this.fastifyInstance.put(path, options, handler);
|
||||
};
|
||||
|
||||
public patch = <T extends RouteGenericInterface>(
|
||||
path: string,
|
||||
handler: HandlerMethod<T>,
|
||||
options: RouteShorthandOptions
|
||||
) => {
|
||||
this.fastifyInstance.patch(path, options, handler);
|
||||
};
|
||||
|
||||
public delete = <T extends RouteGenericInterface>(
|
||||
path: string,
|
||||
handler: HandlerMethod<T>,
|
||||
options: RouteShorthandOptions
|
||||
) => {
|
||||
this.fastifyInstance.delete(path, options, handler);
|
||||
};
|
||||
}
|
19
src/swagger/account/index.ts
Normal file
19
src/swagger/account/index.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { getAccountParams } from "./inputs";
|
||||
import { getAccountResponse, createAccountResponse } from "./responses";
|
||||
|
||||
import type { SwaggerSchema } from "@/types/swagger.type";
|
||||
|
||||
export const getAccountSchema: SwaggerSchema = {
|
||||
summary: "Получение информации об аккаунте",
|
||||
description: "Получение аккаунта по ID",
|
||||
tags: ["account"],
|
||||
params: getAccountParams,
|
||||
response: getAccountResponse,
|
||||
};
|
||||
|
||||
export const createAccountSchema: SwaggerSchema = {
|
||||
summary: "Создание аккаунта",
|
||||
tags: ["account"],
|
||||
response: createAccountResponse,
|
||||
security: [{ bearer: [] }],
|
||||
};
|
11
src/swagger/account/inputs.ts
Normal file
11
src/swagger/account/inputs.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import type { SwaggerMessage } from "@/types/swagger.type";
|
||||
|
||||
export const getAccountParams: SwaggerMessage = {
|
||||
type: "object",
|
||||
properties: {
|
||||
userId: {
|
||||
type: "string",
|
||||
description: "ID пользователя",
|
||||
},
|
||||
},
|
||||
};
|
46
src/swagger/account/models.ts
Normal file
46
src/swagger/account/models.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import type { SwaggerMessage } from "@/types/swagger.type";
|
||||
|
||||
export const account: SwaggerMessage = {
|
||||
description: "Аккаунт",
|
||||
type: "object",
|
||||
properties: {
|
||||
userId: { type: "string" },
|
||||
nickname: { type: "string" },
|
||||
avatar: { type: "string" },
|
||||
role: { type: "string" },
|
||||
isDeleted: { type: "boolean" },
|
||||
createdAt: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
},
|
||||
updatedAt: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
},
|
||||
deletedAt: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
},
|
||||
},
|
||||
examples: [
|
||||
{
|
||||
userId: "507f1f77bcf86cd799439011",
|
||||
nickname: "Ivanov Ivan Ivanovich",
|
||||
avatar: "/media/avatar/default-avatar.jpg",
|
||||
role: "user",
|
||||
isDeleted: false,
|
||||
createdAt: "2017-07-21T17:32:28Z",
|
||||
updatedAt: "2017-07-21T17:32:28Z",
|
||||
},
|
||||
{
|
||||
userId: "507f1f77bcf86cd799439011",
|
||||
nickname: "Ivanov Ivan Ivanovich",
|
||||
avatar: "/media/avatar/default-avatar.jpg",
|
||||
role: "user",
|
||||
isDeleted: true,
|
||||
createdAt: "2017-07-21T17:32:28Z",
|
||||
updatedAt: "2019-04-14T15:32:15Z",
|
||||
deletedAt: "2021-08-17T13:23:44Z",
|
||||
},
|
||||
],
|
||||
};
|
18
src/swagger/account/responses.ts
Normal file
18
src/swagger/account/responses.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { swaggerError } from "@/utils/swagger-error";
|
||||
|
||||
import { account } from "./models";
|
||||
|
||||
import type { SwaggerMessage } from "@/types/swagger.type";
|
||||
|
||||
export const getAccountResponse: Record<string, SwaggerMessage> = {
|
||||
200: account,
|
||||
400: swaggerError(400, "invalid user id"),
|
||||
};
|
||||
|
||||
export const createAccountResponse: Record<string, SwaggerMessage> = {
|
||||
200: account,
|
||||
400: swaggerError(400, "invalid user id"),
|
||||
401: swaggerError(401, "invalid token"),
|
||||
404: swaggerError(404, "user not found"),
|
||||
409: swaggerError(409, "account already exist"),
|
||||
};
|
46
src/swagger/privilege/index.ts
Normal file
46
src/swagger/privilege/index.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { privilegeBody, getPrivilegeParams, getServicePrivilegiesParams, getPrivilegiesQuery } from "./inputs";
|
||||
import {
|
||||
getPrivilegeReponse,
|
||||
getPrivilegiesReponse,
|
||||
getAllPrivilegiesReponse,
|
||||
registerPrivilegeResponse,
|
||||
replacePrivilegeResponse,
|
||||
} from "./responses";
|
||||
|
||||
import type { SwaggerSchema } from "@/types/swagger.type";
|
||||
|
||||
export const getPrivilegiesSchema: SwaggerSchema = {
|
||||
summary: "Получение всех привелегий",
|
||||
description: "Получение всех привелегий в разном формате",
|
||||
tags: ["privilege"],
|
||||
querystring: getPrivilegiesQuery,
|
||||
response: getAllPrivilegiesReponse,
|
||||
};
|
||||
|
||||
export const getPrivilegeSchema: SwaggerSchema = {
|
||||
summary: "Получение привилегии по ID",
|
||||
tags: ["privilege"],
|
||||
params: getPrivilegeParams,
|
||||
response: getPrivilegeReponse,
|
||||
};
|
||||
|
||||
export const getServicePrivilegiesSchema: SwaggerSchema = {
|
||||
summary: "Получение привилегий сервиса",
|
||||
tags: ["privilege"],
|
||||
params: getServicePrivilegiesParams,
|
||||
response: getPrivilegiesReponse,
|
||||
};
|
||||
|
||||
export const registerPrivilegeSchema: SwaggerSchema = {
|
||||
summary: "Регистрация привелегии сервиса",
|
||||
tags: ["privilege"],
|
||||
body: privilegeBody,
|
||||
response: registerPrivilegeResponse,
|
||||
};
|
||||
|
||||
export const replacePrivilegeSchema: SwaggerSchema = {
|
||||
summary: "Замена привилегии сервиса",
|
||||
tags: ["privilege"],
|
||||
body: privilegeBody,
|
||||
response: replacePrivilegeResponse,
|
||||
};
|
62
src/swagger/privilege/inputs.ts
Normal file
62
src/swagger/privilege/inputs.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import type { SwaggerMessage } from "@/types/swagger.type";
|
||||
|
||||
export const privilegeBody: SwaggerMessage = {
|
||||
type: "object",
|
||||
required: ["name", "privilegeId", "serviceKey", "description", "type", "value", "price"],
|
||||
properties: {
|
||||
name: { type: "string" },
|
||||
privilegeId: { type: "string" },
|
||||
serviceKey: { type: "string" },
|
||||
description: { type: "string" },
|
||||
type: { type: "string" },
|
||||
value: { type: "string" },
|
||||
price: { type: "number" },
|
||||
},
|
||||
examples: [
|
||||
{
|
||||
name: "507f1f77bcf86cd799439011",
|
||||
privilegeId: "507f1f77bcf86cd799439011",
|
||||
serviceKey: "docx-templater-service",
|
||||
description: "Количество попыток использования",
|
||||
type: "count",
|
||||
value: "200",
|
||||
price: 12300,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const getPrivilegeParams: SwaggerMessage = {
|
||||
type: "object",
|
||||
required: ["id"],
|
||||
properties: {
|
||||
id: {
|
||||
type: "string",
|
||||
description: "ID привилегии",
|
||||
},
|
||||
},
|
||||
examples: [{ id: "507f1f77bcf86cd799439011" }],
|
||||
};
|
||||
|
||||
export const getServicePrivilegiesParams: SwaggerMessage = {
|
||||
type: "object",
|
||||
required: ["serviceKey"],
|
||||
properties: {
|
||||
serviceKey: {
|
||||
type: "string",
|
||||
description: "ID привилегии",
|
||||
},
|
||||
},
|
||||
examples: [{ id: "507f1f77bcf86cd799439011" }],
|
||||
};
|
||||
|
||||
export const getPrivilegiesQuery: SwaggerMessage = {
|
||||
type: "object",
|
||||
properties: {
|
||||
format: {
|
||||
type: "string",
|
||||
description:
|
||||
"Есть два формата списка привелегий, в виде массива и в виде объекта ключ-значение, где ключём является ключ сервиса",
|
||||
},
|
||||
},
|
||||
examples: [{ format: "array" }, { format: "map" }],
|
||||
};
|
103
src/swagger/privilege/models.ts
Normal file
103
src/swagger/privilege/models.ts
Normal file
@ -0,0 +1,103 @@
|
||||
import type { SwaggerMessage, SwaggerValueType } from "@/types/swagger.type";
|
||||
|
||||
const privilegeExamples: SwaggerValueType[] = [
|
||||
{
|
||||
name: "use count",
|
||||
privilegeId: "507f1f77bcf86cd799439011",
|
||||
serviceKey: "docx-templater-service",
|
||||
description: "Количество попыток использования",
|
||||
type: "count",
|
||||
value: "200",
|
||||
price: 12300,
|
||||
isDeleted: false,
|
||||
createdAt: "2017-07-21T17:32:28Z",
|
||||
updatedAt: "2017-07-21T17:32:28Z",
|
||||
},
|
||||
{
|
||||
name: "use count",
|
||||
privilegeId: "507f1f77bcf86cd799439011",
|
||||
serviceKey: "docx-templater-service",
|
||||
description: "Количество попыток использования",
|
||||
type: "count",
|
||||
value: "200",
|
||||
price: 12300,
|
||||
isDeleted: false,
|
||||
createdAt: "2017-07-21T17:32:28Z",
|
||||
updatedAt: "2017-07-21T17:32:28Z",
|
||||
},
|
||||
];
|
||||
|
||||
export const privilege: SwaggerMessage = {
|
||||
type: "object",
|
||||
description: "Привилегия",
|
||||
properties: {
|
||||
name: { type: "string" },
|
||||
privilegeId: { type: "string" },
|
||||
serviceKey: { type: "string" },
|
||||
description: { type: "string" },
|
||||
type: { type: "string" },
|
||||
value: { type: "string" },
|
||||
price: { type: "number" },
|
||||
isDeleted: { type: "boolean" },
|
||||
createdAt: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
},
|
||||
updatedAt: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
},
|
||||
deletedAt: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
},
|
||||
},
|
||||
examples: privilegeExamples,
|
||||
};
|
||||
|
||||
export const privilegiesMessage: SwaggerMessage = {
|
||||
type: "object",
|
||||
description: "Привилегии",
|
||||
oneOf: [
|
||||
{
|
||||
type: "array",
|
||||
items: privilege,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
additionalProperties: privilege,
|
||||
},
|
||||
],
|
||||
examples: [
|
||||
privilegeExamples,
|
||||
{
|
||||
"docx-templater-service": [
|
||||
{
|
||||
name: "use count",
|
||||
privilegeId: "507f1f77bcf86cd799439011",
|
||||
serviceKey: "docx-templater-service",
|
||||
description: "Количество попыток использования",
|
||||
type: "count",
|
||||
value: "200",
|
||||
price: 12300,
|
||||
isDeleted: false,
|
||||
createdAt: "2017-07-21T17:32:28Z",
|
||||
updatedAt: "2017-07-21T17:32:28Z",
|
||||
},
|
||||
{
|
||||
name: "use count",
|
||||
privilegeId: "507f1f77bcf86cd799439011",
|
||||
serviceKey: "docx-templater-service",
|
||||
description: "Количество попыток использования",
|
||||
type: "count",
|
||||
value: "200",
|
||||
price: 12300,
|
||||
isDeleted: true,
|
||||
createdAt: "2017-07-21T17:32:28Z",
|
||||
updatedAt: "2019-04-14T15:32:15Z",
|
||||
deletedAt: "2021-08-17T13:23:44Z",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
35
src/swagger/privilege/responses.ts
Normal file
35
src/swagger/privilege/responses.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { swaggerError } from "@/utils/swagger-error";
|
||||
|
||||
import { privilege, privilegiesMessage } from "./models";
|
||||
|
||||
import type { SwaggerMessage } from "@/types/swagger.type";
|
||||
|
||||
export const getAllPrivilegiesReponse: Record<string, SwaggerMessage> = {
|
||||
200: privilegiesMessage,
|
||||
500: swaggerError(500, "format not defined"),
|
||||
};
|
||||
|
||||
export const getPrivilegiesReponse: Record<string, SwaggerMessage> = {
|
||||
200: {
|
||||
type: "array",
|
||||
items: privilege,
|
||||
},
|
||||
};
|
||||
|
||||
export const getPrivilegeReponse: Record<string, SwaggerMessage> = {
|
||||
200: privilege,
|
||||
400: swaggerError(400, "invalid id"),
|
||||
404: swaggerError(404, "privilege not found"),
|
||||
};
|
||||
|
||||
export const registerPrivilegeResponse: Record<string, SwaggerMessage> = {
|
||||
200: privilege,
|
||||
400: swaggerError(400, "price must be a number"),
|
||||
409: swaggerError(409, "privilege already exist"),
|
||||
};
|
||||
|
||||
export const replacePrivilegeResponse: Record<string, SwaggerMessage> = {
|
||||
200: privilege,
|
||||
400: swaggerError(400, "invalid 'type' value"),
|
||||
404: swaggerError(404, "privilege not found"),
|
||||
};
|
71
src/swagger/role/index.ts
Normal file
71
src/swagger/role/index.ts
Normal file
@ -0,0 +1,71 @@
|
||||
import { getRoleParams, roleBody, getRoleByIdBody, updateRoleBody } from "./inputs";
|
||||
import {
|
||||
getRolesReponse,
|
||||
getRoleReponse,
|
||||
createRoleReponse,
|
||||
restoreRoleReponse,
|
||||
updateRoleReponse,
|
||||
removeRoleReponse,
|
||||
} from "./responses";
|
||||
|
||||
import type { SwaggerSchema } from "@/types/swagger.type";
|
||||
|
||||
export const getRolesSchema: SwaggerSchema = {
|
||||
summary: "Получение всех ролей",
|
||||
tags: ["role"],
|
||||
response: getRolesReponse,
|
||||
};
|
||||
|
||||
export const getRoleSchema: SwaggerSchema = {
|
||||
summary: "Получение роли",
|
||||
tags: ["role"],
|
||||
params: getRoleParams,
|
||||
response: getRoleReponse,
|
||||
};
|
||||
|
||||
export const createRoleSchema: SwaggerSchema = {
|
||||
summary: "Создание роли",
|
||||
tags: ["role"],
|
||||
body: roleBody,
|
||||
response: createRoleReponse,
|
||||
};
|
||||
|
||||
export const restoreRoleSchema: SwaggerSchema = {
|
||||
summary: "Восстановление удалённой роли",
|
||||
description: "Восстанавливает удалённую роль, которая ещё существует в БД",
|
||||
tags: ["role"],
|
||||
body: getRoleByIdBody,
|
||||
response: restoreRoleReponse,
|
||||
};
|
||||
|
||||
export const updateRoleSchema: SwaggerSchema = {
|
||||
summary: "Обновление роли",
|
||||
tags: ["role"],
|
||||
params: getRoleParams,
|
||||
body: updateRoleBody,
|
||||
response: updateRoleReponse,
|
||||
};
|
||||
|
||||
export const replaceRoleSchema: SwaggerSchema = {
|
||||
summary: "Замена роли",
|
||||
tags: ["role"],
|
||||
params: getRoleParams,
|
||||
body: roleBody,
|
||||
response: updateRoleReponse,
|
||||
};
|
||||
|
||||
export const removeRoleSchema: SwaggerSchema = {
|
||||
summary: "Удаление роли",
|
||||
description: "Помечает роль удалённой, но не удаляет её окончательно",
|
||||
tags: ["role"],
|
||||
body: getRoleByIdBody,
|
||||
response: removeRoleReponse,
|
||||
};
|
||||
|
||||
export const deleteRoleSchema: SwaggerSchema = {
|
||||
summary: "Получение всех ролей",
|
||||
description: "Удаляет роль окончательно",
|
||||
tags: ["role"],
|
||||
body: getRoleByIdBody,
|
||||
response: getRolesReponse,
|
||||
};
|
58
src/swagger/role/inputs.ts
Normal file
58
src/swagger/role/inputs.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import type { SwaggerMessage } from "@/types/swagger.type";
|
||||
|
||||
export const getRoleParams: SwaggerMessage = {
|
||||
type: "object",
|
||||
required: ["query"],
|
||||
properties: {
|
||||
query: {
|
||||
type: "string",
|
||||
description: "query может принимать как id, так и name роли",
|
||||
},
|
||||
},
|
||||
examples: [{ query: "507f1f77bcf86cd799439011" }, { query: "admin" }],
|
||||
};
|
||||
|
||||
export const roleBody: SwaggerMessage = {
|
||||
type: "object",
|
||||
required: ["name", "permissions"],
|
||||
properties: {
|
||||
name: {
|
||||
type: "string",
|
||||
description: "Название роли",
|
||||
},
|
||||
permissions: {
|
||||
type: "array",
|
||||
description: "Массив разрешений",
|
||||
items: { type: "string" },
|
||||
},
|
||||
},
|
||||
examples: [{ name: "admin", permissions: ["read", "write"] }],
|
||||
};
|
||||
|
||||
export const updateRoleBody: SwaggerMessage = {
|
||||
type: "object",
|
||||
properties: {
|
||||
name: {
|
||||
type: "string",
|
||||
description: "Название роли",
|
||||
},
|
||||
permissions: {
|
||||
type: "array",
|
||||
description: "Массив разрешений",
|
||||
items: { type: "string" },
|
||||
},
|
||||
},
|
||||
examples: [{ name: "admin", permissions: ["read", "write"] }],
|
||||
};
|
||||
|
||||
export const getRoleByIdBody: SwaggerMessage = {
|
||||
type: "object",
|
||||
required: ["id"],
|
||||
properties: {
|
||||
id: {
|
||||
type: "string",
|
||||
description: "ID роли",
|
||||
},
|
||||
},
|
||||
examples: [{ id: "507f1f77bcf86cd799439011" }],
|
||||
};
|
29
src/swagger/role/models.ts
Normal file
29
src/swagger/role/models.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import type { SwaggerMessage } from "@/types/swagger.type";
|
||||
|
||||
export const role: SwaggerMessage = {
|
||||
type: "object",
|
||||
description: "Роль",
|
||||
properties: {
|
||||
name: { type: "string" },
|
||||
permissions: {
|
||||
type: "object",
|
||||
additionalProperties: { type: "boolean" },
|
||||
},
|
||||
},
|
||||
examples: [
|
||||
{
|
||||
name: "user",
|
||||
permissions: {
|
||||
read: true,
|
||||
write: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "admin",
|
||||
permissions: {
|
||||
read: true,
|
||||
write: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
50
src/swagger/role/responses.ts
Normal file
50
src/swagger/role/responses.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import { swaggerError } from "@/utils/swagger-error";
|
||||
|
||||
import { role } from "./models";
|
||||
|
||||
import type { SwaggerMessage } from "@/types/swagger.type";
|
||||
|
||||
export const getRolesReponse: Record<string, SwaggerMessage> = {
|
||||
200: {
|
||||
type: "array",
|
||||
items: role,
|
||||
},
|
||||
};
|
||||
|
||||
export const getRoleReponse: Record<string, SwaggerMessage> = {
|
||||
200: role,
|
||||
400: swaggerError(400, "query is empty"),
|
||||
404: swaggerError(404, "role not found"),
|
||||
};
|
||||
|
||||
export const createRoleReponse: Record<string, SwaggerMessage> = {
|
||||
200: role,
|
||||
400: swaggerError(400, "field <name> is empty"),
|
||||
409: swaggerError(409, "role already exist"),
|
||||
};
|
||||
|
||||
export const restoreRoleReponse: Record<string, SwaggerMessage> = {
|
||||
200: role,
|
||||
400: swaggerError(400, "wrong id"),
|
||||
404: swaggerError(404, "role by id not found"),
|
||||
409: swaggerError(409, "role not removed"),
|
||||
};
|
||||
|
||||
export const updateRoleReponse: Record<string, SwaggerMessage> = {
|
||||
200: role,
|
||||
400: swaggerError(400, "either name or permissions must be filled"),
|
||||
404: swaggerError(404, "role not found"),
|
||||
};
|
||||
|
||||
export const removeRoleReponse: Record<string, SwaggerMessage> = {
|
||||
200: role,
|
||||
400: swaggerError(400, "wrong id"),
|
||||
404: swaggerError(404, "role by id not found"),
|
||||
409: swaggerError(409, "role already deleted"),
|
||||
};
|
||||
|
||||
export const deleteRoleReponse: Record<string, SwaggerMessage> = {
|
||||
200: role,
|
||||
400: swaggerError(400, "wrong id"),
|
||||
404: swaggerError(404, "role not found"),
|
||||
};
|
30
src/swagger/tariff/index.ts
Normal file
30
src/swagger/tariff/index.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { getTariffParams, tariffBody } from "./inputs";
|
||||
import { getTariffReponse, getTariffsReponse, createTariffReponse, replaceTariffReponse } from "./responses";
|
||||
|
||||
import type { SwaggerSchema } from "@/types/swagger.type";
|
||||
|
||||
export const getTariffSchema: SwaggerSchema = {
|
||||
summary: "Получение тарифа",
|
||||
tags: ["tariff"],
|
||||
params: getTariffParams,
|
||||
response: getTariffReponse,
|
||||
};
|
||||
|
||||
export const getTariffsSchema: SwaggerSchema = {
|
||||
summary: "Получение списка тарифов",
|
||||
tags: ["tariff"],
|
||||
response: getTariffsReponse,
|
||||
};
|
||||
|
||||
export const createTariffsSchema: SwaggerSchema = {
|
||||
summary: "Создание тарифа",
|
||||
tags: ["tariff"],
|
||||
body: tariffBody,
|
||||
response: createTariffReponse,
|
||||
};
|
||||
export const replaceTariffsSchema: SwaggerSchema = {
|
||||
summary: "Замена тарифа",
|
||||
tags: ["tariff"],
|
||||
body: tariffBody,
|
||||
response: replaceTariffReponse,
|
||||
};
|
48
src/swagger/tariff/inputs.ts
Normal file
48
src/swagger/tariff/inputs.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { privilege } from "@/swagger/privilege/models";
|
||||
|
||||
import type { SwaggerMessage } from "@/types/swagger.type";
|
||||
|
||||
export const getTariffParams: SwaggerMessage = {
|
||||
type: "object",
|
||||
required: ["id"],
|
||||
properties: {
|
||||
id: {
|
||||
type: "string",
|
||||
description: "ID тарифа",
|
||||
},
|
||||
},
|
||||
examples: [{ id: "507f1f77bcf86cd799439011" }],
|
||||
};
|
||||
|
||||
export const tariffBody: SwaggerMessage = {
|
||||
type: "object",
|
||||
description: "Тариф",
|
||||
required: ["name", "price", "isCustom", "privilegies"],
|
||||
properties: {
|
||||
name: { type: "string" },
|
||||
price: { type: "number" },
|
||||
isCustom: { type: "boolean" },
|
||||
privilegies: {
|
||||
type: "array",
|
||||
items: privilege,
|
||||
},
|
||||
},
|
||||
examples: [
|
||||
{
|
||||
name: "user",
|
||||
price: 14000,
|
||||
isCustom: false,
|
||||
privilegies: [
|
||||
{
|
||||
name: "507f1f77bcf86cd799439011",
|
||||
privilegeId: "507f1f77bcf86cd799439011",
|
||||
serviceKey: "docx-templater-service",
|
||||
description: "Количество попыток использования",
|
||||
type: "count",
|
||||
value: "200",
|
||||
price: 12300,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
94
src/swagger/tariff/models.ts
Normal file
94
src/swagger/tariff/models.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import type { SwaggerMessage } from "@/types/swagger.type";
|
||||
|
||||
const privilege: SwaggerMessage = {
|
||||
type: "object",
|
||||
description: "Привилегия",
|
||||
properties: {
|
||||
name: { type: "string" },
|
||||
privilegeId: { type: "string" },
|
||||
serviceKey: { type: "string" },
|
||||
description: { type: "string" },
|
||||
type: { type: "string" },
|
||||
value: { type: "string" },
|
||||
price: { type: "number" },
|
||||
},
|
||||
examples: [
|
||||
{
|
||||
name: "507f1f77bcf86cd799439011",
|
||||
privilegeId: "507f1f77bcf86cd799439011",
|
||||
serviceKey: "docx-templater-service",
|
||||
description: "Количество попыток использования",
|
||||
type: "count",
|
||||
value: "200",
|
||||
price: 12300,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const tariff: SwaggerMessage = {
|
||||
type: "object",
|
||||
description: "Тариф",
|
||||
properties: {
|
||||
name: { type: "string" },
|
||||
price: { type: "number" },
|
||||
isCustom: { type: "boolean" },
|
||||
privilegies: {
|
||||
type: "object",
|
||||
additionalProperties: privilege,
|
||||
},
|
||||
isDeleted: { type: "boolean" },
|
||||
createdAt: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
},
|
||||
updatedAt: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
},
|
||||
deletedAt: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
},
|
||||
},
|
||||
examples: [
|
||||
{
|
||||
name: "user",
|
||||
price: 14000,
|
||||
isCustom: false,
|
||||
privilegies: {
|
||||
"507f1f77bcf86cd799439011": {
|
||||
name: "507f1f77bcf86cd799439011",
|
||||
privilegeId: "507f1f77bcf86cd799439011",
|
||||
serviceKey: "docx-templater-service",
|
||||
description: "Количество попыток использования",
|
||||
type: "count",
|
||||
value: "200",
|
||||
price: 12300,
|
||||
},
|
||||
},
|
||||
isDeleted: false,
|
||||
createdAt: "2017-07-21T17:32:28Z",
|
||||
updatedAt: "2017-07-21T17:32:28Z",
|
||||
},
|
||||
{
|
||||
name: "user",
|
||||
price: 14000,
|
||||
isCustom: false,
|
||||
privilegies: {
|
||||
"507f1f77bcf86cd799439011": {
|
||||
name: "507f1f77bcf86cd799439011",
|
||||
privilegeId: "507f1f77bcf86cd799439011",
|
||||
serviceKey: "docx-templater-service",
|
||||
description: "Количество попыток использования",
|
||||
type: "count",
|
||||
value: "200",
|
||||
price: 12300,
|
||||
},
|
||||
},
|
||||
isDeleted: true,
|
||||
createdAt: "2017-07-21T17:32:28Z",
|
||||
updatedAt: "2019-04-14T15:32:15Z",
|
||||
deletedAt: "2021-08-17T13:23:44Z",
|
||||
},
|
||||
],
|
||||
};
|
30
src/swagger/tariff/responses.ts
Normal file
30
src/swagger/tariff/responses.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { swaggerError } from "@/utils/swagger-error";
|
||||
|
||||
import { tariff } from "./models";
|
||||
|
||||
import type { SwaggerMessage } from "@/types/swagger.type";
|
||||
|
||||
export const getTariffReponse: Record<string, SwaggerMessage> = {
|
||||
200: tariff,
|
||||
400: swaggerError(400, "invalid id"),
|
||||
404: swaggerError(404, "tariff not found"),
|
||||
};
|
||||
|
||||
export const getTariffsReponse: Record<string, SwaggerMessage> = {
|
||||
200: {
|
||||
type: "array",
|
||||
items: tariff,
|
||||
},
|
||||
};
|
||||
|
||||
export const createTariffReponse: Record<string, SwaggerMessage> = {
|
||||
200: tariff,
|
||||
400: swaggerError(400, "invalid 'price' value"),
|
||||
404: swaggerError(404, "privilege with id <privilegeId> not found"),
|
||||
};
|
||||
|
||||
export const replaceTariffReponse: Record<string, SwaggerMessage> = {
|
||||
200: tariff,
|
||||
400: swaggerError(400, "invalid id"),
|
||||
404: swaggerError(404, "tariff not found"),
|
||||
};
|
@ -1,10 +1,10 @@
|
||||
import type { EloquentModel } from "../models/eloquent-model.type";
|
||||
import type { Eloquent } from "../models/eloquent.type";
|
||||
import type { Privilege } from "../models/privilege.type";
|
||||
import type { Tariff } from "../models/tariff.type";
|
||||
import type { ObjectWithPossibleFields } from "../object-with-possible-fields";
|
||||
|
||||
export type TariffMessage = ObjectWithPossibleFields<
|
||||
Omit<Tariff, keyof EloquentModel | "privilegies"> & {
|
||||
Omit<Tariff, keyof Eloquent | "privilegies"> & {
|
||||
privilegies: Privilege[];
|
||||
}
|
||||
>;
|
||||
|
@ -1,7 +1,8 @@
|
||||
export type Account = {
|
||||
import type { Eloquent } from "./eloquent.type";
|
||||
|
||||
export type Account = Eloquent & {
|
||||
userId: string;
|
||||
nickname: string;
|
||||
avatar: string;
|
||||
role: string;
|
||||
privilegies: Record<string, string>;
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
export type EloquentModel = {
|
||||
export type Eloquent = {
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
deletedAt: Date;
|
@ -1,6 +1,6 @@
|
||||
import type { EloquentModel } from "./eloquent-model.type";
|
||||
import type { Eloquent } from "./eloquent.type";
|
||||
|
||||
export type Privilege = EloquentModel & {
|
||||
export type Privilege = Eloquent & {
|
||||
name: string;
|
||||
privilegeId: string;
|
||||
serviceKey: string;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { EloquentModel } from "./eloquent-model.type";
|
||||
import type { Eloquent } from "./eloquent.type";
|
||||
|
||||
export type Role = EloquentModel & {
|
||||
export type Role = Eloquent & {
|
||||
name: string;
|
||||
permissions: Record<string, boolean>;
|
||||
};
|
||||
|
@ -1,9 +1,9 @@
|
||||
import type { Privilege } from "./privilege.type";
|
||||
import type { EloquentModel } from "./eloquent-model.type";
|
||||
import type { Eloquent } from "./eloquent.type";
|
||||
|
||||
export type Tariff = EloquentModel & {
|
||||
export type Tariff = Eloquent & {
|
||||
name: string;
|
||||
price: number;
|
||||
isCustom: boolean;
|
||||
privilegies: Record<string, Privilege>;
|
||||
privilegies: Record<string, Omit<Privilege, keyof Eloquent>>;
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { EloquentModel } from "./eloquent-model.type";
|
||||
import type { Eloquent } from "./eloquent.type";
|
||||
|
||||
export type User = EloquentModel & {
|
||||
export type User = Eloquent & {
|
||||
_id: string;
|
||||
login: string;
|
||||
email: string;
|
||||
|
@ -1,13 +0,0 @@
|
||||
import type { RequestGenericInterface } from "fastify";
|
||||
|
||||
export type GetAccountRoute = RequestGenericInterface & {
|
||||
Params?: {
|
||||
userId?: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type CreateAccountRoute = RequestGenericInterface & {
|
||||
Params?: {
|
||||
userId?: string;
|
||||
};
|
||||
};
|
@ -1,11 +0,0 @@
|
||||
import type { RequestGenericInterface } from "fastify";
|
||||
import type { TariffMessage } from "../messages/tariff-message.type";
|
||||
|
||||
export type CreateTariffRoute = RequestGenericInterface & {
|
||||
Body?: TariffMessage;
|
||||
};
|
||||
|
||||
export type ReplaceTariffRoute = RequestGenericInterface & {
|
||||
Body?: TariffMessage;
|
||||
Params?: { id?: string };
|
||||
};
|
48
src/types/swagger.type.ts
Normal file
48
src/types/swagger.type.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import type { FastifySchema } from "fastify";
|
||||
|
||||
export type SwaggerValueType =
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| null
|
||||
| SwaggerValueType[]
|
||||
| { [key: string]: SwaggerValueType };
|
||||
|
||||
type SwaggerMediaType = "object" | "string" | "integer" | "boolean" | "array" | "number";
|
||||
type SwaggerMediaFormat =
|
||||
| "binary"
|
||||
| "base64"
|
||||
| "uuid"
|
||||
| "email"
|
||||
| "date"
|
||||
| "date-time"
|
||||
| "password"
|
||||
| "byte"
|
||||
| "uri"
|
||||
| "hostname"
|
||||
| "ipv4"
|
||||
| "ipv6";
|
||||
|
||||
export type SwaggerMessage = {
|
||||
type: SwaggerMediaType;
|
||||
description?: string;
|
||||
format?: SwaggerMediaFormat;
|
||||
pattern?: string;
|
||||
nullable?: boolean;
|
||||
uniqueItems?: boolean;
|
||||
writeOnly?: boolean;
|
||||
readOnly?: boolean;
|
||||
items?: SwaggerMessage;
|
||||
additionalProperties?: SwaggerMessage;
|
||||
properties?: Record<string, SwaggerMessage | Record<string, SwaggerValueType>>;
|
||||
examples?: SwaggerValueType[];
|
||||
required?: string[];
|
||||
oneOf?: SwaggerMessage[];
|
||||
allOf?: SwaggerMessage[];
|
||||
};
|
||||
|
||||
export type SwaggerSchema = FastifySchema & {
|
||||
params?: SwaggerMessage;
|
||||
body?: SwaggerMessage;
|
||||
response?: Record<number, SwaggerMessage>;
|
||||
};
|
19
src/utils/swagger-error.ts
Normal file
19
src/utils/swagger-error.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import type { SwaggerMessage } from "@/types/swagger.type";
|
||||
|
||||
const STATUS_CODE_MAP: Record<number, string> = {
|
||||
400: "Bad Request",
|
||||
401: "Unauthorized",
|
||||
404: "Not Found",
|
||||
409: "Conflict",
|
||||
500: "Internal Server Error",
|
||||
};
|
||||
|
||||
export const swaggerError = (code: number, message: string): SwaggerMessage => ({
|
||||
type: "object",
|
||||
properties: {
|
||||
statusCode: { type: "integer" },
|
||||
error: { type: "string" },
|
||||
message: { type: "string" },
|
||||
},
|
||||
examples: [{ statusCode: code, error: STATUS_CODE_MAP[code], message: message }],
|
||||
});
|
208
yarn.lock
208
yarn.lock
@ -1204,6 +1204,11 @@
|
||||
minimatch "^3.1.2"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@fastify/accept-negotiator@^1.0.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@fastify/accept-negotiator/-/accept-negotiator-1.1.0.tgz#c1c66b3b771c09742a54dd5bc87c582f6b0630ff"
|
||||
integrity sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ==
|
||||
|
||||
"@fastify/ajv-compiler@^3.3.1":
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@fastify/ajv-compiler/-/ajv-compiler-3.4.0.tgz#e001b7e234b5b704654b1d617d69fa63c348f2a7"
|
||||
@ -1257,6 +1262,41 @@
|
||||
fastify-plugin "^4.0.0"
|
||||
steed "^1.1.3"
|
||||
|
||||
"@fastify/static@^6.0.0":
|
||||
version "6.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@fastify/static/-/static-6.6.0.tgz#763244583abf7a4734bff7b1d1aef0ef445393fb"
|
||||
integrity sha512-UiYSN2dUmDZ48M40xdIwY1dPwSSYD7c+wtoIQP8y7wyxCwcUtf1YT5/Q4n1uJsBF1fySvuo9njQZKlHeiKy4HQ==
|
||||
dependencies:
|
||||
"@fastify/accept-negotiator" "^1.0.0"
|
||||
content-disposition "^0.5.3"
|
||||
fastify-plugin "^4.0.0"
|
||||
glob "^8.0.1"
|
||||
p-limit "^3.1.0"
|
||||
readable-stream "^4.0.0"
|
||||
send "^0.18.0"
|
||||
|
||||
"@fastify/swagger-ui@^1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@fastify/swagger-ui/-/swagger-ui-1.3.0.tgz#967afd8bfa87a539b83ae6bc986f3589e9fdb98a"
|
||||
integrity sha512-Q6vvIyTd1gj0h0IoDAAUX3SBBiL1pybXP0FmFbD4yLMcACIZ7xm8oHCf5lMc3rNC69KhbywuSst3iHgp23x8SA==
|
||||
dependencies:
|
||||
"@fastify/static" "^6.0.0"
|
||||
fastify-plugin "^4.0.0"
|
||||
openapi-types "^12.0.2"
|
||||
rfdc "^1.3.0"
|
||||
yaml "^2.1.3"
|
||||
|
||||
"@fastify/swagger@^8.2.1":
|
||||
version "8.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@fastify/swagger/-/swagger-8.2.1.tgz#a5f744868c25c49bde2469f5412ce0405aac150a"
|
||||
integrity sha512-nYP/3ncrI5YmaGiJf6m+CLdFrdlWSsASHBPqP9uN9/oFFwDJwdUtq0ylmvObxzqWNVt9zT50iT/uvIndVEsvbg==
|
||||
dependencies:
|
||||
fastify-plugin "^4.0.0"
|
||||
json-schema-resolver "^2.0.0"
|
||||
openapi-types "^12.0.0"
|
||||
rfdc "^1.3.0"
|
||||
yaml "^2.1.1"
|
||||
|
||||
"@humanwhocodes/config-array@^0.11.6":
|
||||
version "0.11.7"
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.7.tgz#38aec044c6c828f6ed51d5d7ae3d9b9faf6dbb0f"
|
||||
@ -2184,6 +2224,13 @@ brace-expansion@^1.1.7:
|
||||
balanced-match "^1.0.0"
|
||||
concat-map "0.0.1"
|
||||
|
||||
brace-expansion@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
|
||||
integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
|
||||
braces@^3.0.2, braces@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||
@ -2410,6 +2457,13 @@ concat-map@0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
|
||||
|
||||
content-disposition@^0.5.3:
|
||||
version "0.5.4"
|
||||
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
|
||||
integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
|
||||
dependencies:
|
||||
safe-buffer "5.2.1"
|
||||
|
||||
conventional-changelog-angular@^5.0.11:
|
||||
version "5.0.13"
|
||||
resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz#896885d63b914a70d4934b59d2fe7bde1832b28c"
|
||||
@ -2489,6 +2543,13 @@ dargs@^7.0.0:
|
||||
resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc"
|
||||
integrity sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==
|
||||
|
||||
debug@2.6.9, debug@^2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@4, debug@4.x, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
@ -2496,13 +2557,6 @@ debug@4, debug@4.x, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debu
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@^2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@^3.2.7:
|
||||
version "3.2.7"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
|
||||
@ -2561,6 +2615,16 @@ denque@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1"
|
||||
integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==
|
||||
|
||||
depd@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
|
||||
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
|
||||
|
||||
destroy@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
|
||||
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
|
||||
|
||||
detect-newline@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
|
||||
@ -2616,6 +2680,11 @@ ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11:
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
ee-first@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
|
||||
|
||||
electron-to-chromium@^1.4.251:
|
||||
version "1.4.284"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592"
|
||||
@ -2631,6 +2700,11 @@ emoji-regex@^8.0.0:
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
|
||||
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
|
||||
|
||||
encodeurl@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||
integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
|
||||
|
||||
end-of-stream@^1.4.1:
|
||||
version "1.4.4"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
||||
@ -2704,6 +2778,11 @@ escalade@^3.1.1:
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
|
||||
|
||||
escape-html@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
|
||||
integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
|
||||
|
||||
escape-string-regexp@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
@ -2899,6 +2978,11 @@ esutils@^2.0.2:
|
||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
||||
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
||||
|
||||
etag@~1.8.1:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
|
||||
|
||||
event-target-shim@^5.0.0:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
|
||||
@ -3179,6 +3263,11 @@ forwarded@0.2.0:
|
||||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
|
||||
integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
|
||||
|
||||
fresh@0.5.2:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
||||
integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==
|
||||
|
||||
fs-constants@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
|
||||
@ -3307,6 +3396,17 @@ glob@^7.1.3, glob@^7.1.4:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^8.0.1:
|
||||
version "8.0.3"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e"
|
||||
integrity sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^5.0.1"
|
||||
once "^1.3.0"
|
||||
|
||||
global-dirs@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445"
|
||||
@ -3432,6 +3532,17 @@ html-escaper@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
|
||||
integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
|
||||
|
||||
http-errors@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
|
||||
integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
|
||||
dependencies:
|
||||
depd "2.0.0"
|
||||
inherits "2.0.4"
|
||||
setprototypeof "1.2.0"
|
||||
statuses "2.0.1"
|
||||
toidentifier "1.0.1"
|
||||
|
||||
https-proxy-agent@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
|
||||
@ -3499,7 +3610,7 @@ inflight@^1.0.4:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4:
|
||||
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
@ -4131,6 +4242,15 @@ json-parse-even-better-errors@^2.3.0:
|
||||
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
|
||||
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
|
||||
|
||||
json-schema-resolver@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/json-schema-resolver/-/json-schema-resolver-2.0.0.tgz#d17fdf53560e6bc9af084b930fee27f6ce4a03b6"
|
||||
integrity sha512-pJ4XLQP4Q9HTxl6RVDLJ8Cyh1uitSs0CzDBAz1uoJ4sRD/Bk7cFSXL1FUXDW3zJ7YnfliJx6eu8Jn283bpZ4Yg==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
rfdc "^1.1.4"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
json-schema-traverse@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
|
||||
@ -4409,6 +4529,11 @@ mime-types@^2.1.12:
|
||||
dependencies:
|
||||
mime-db "1.52.0"
|
||||
|
||||
mime@1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
|
||||
|
||||
mimic-fn@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||
@ -4431,6 +4556,13 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimatch@^5.0.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.2.tgz#0939d7d6f0898acbd1508abe534d1929368a8fff"
|
||||
integrity sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg==
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimist-options@4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619"
|
||||
@ -4669,6 +4801,13 @@ on-exit-leak-free@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz#5c703c968f7e7f851885f6459bf8a8a57edc9cc4"
|
||||
integrity sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==
|
||||
|
||||
on-finished@2.4.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
|
||||
integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
|
||||
dependencies:
|
||||
ee-first "1.1.1"
|
||||
|
||||
once@^1.3.0, once@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
@ -4692,6 +4831,11 @@ open@^8.4.0:
|
||||
is-docker "^2.1.1"
|
||||
is-wsl "^2.2.0"
|
||||
|
||||
openapi-types@^12.0.0, openapi-types@^12.0.2:
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/openapi-types/-/openapi-types-12.1.0.tgz#bd01acc937b73c9f6db2ac2031bf0231e21ebff0"
|
||||
integrity sha512-XpeCy01X6L5EpP+6Hc3jWN7rMZJ+/k1lwki/kTmWzbVhdPie3jd5O2ZtedEx8Yp58icJ0osVldLMrTB/zslQXA==
|
||||
|
||||
optionator@^0.9.1:
|
||||
version "0.9.1"
|
||||
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
|
||||
@ -4935,6 +5079,11 @@ quick-lru@^4.0.1:
|
||||
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f"
|
||||
integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==
|
||||
|
||||
range-parser@~1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
|
||||
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
|
||||
|
||||
react-is@^18.0.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
|
||||
@ -5070,7 +5219,7 @@ reusify@^1.0.0, reusify@^1.0.4:
|
||||
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
|
||||
|
||||
rfdc@^1.2.0, rfdc@^1.3.0:
|
||||
rfdc@^1.1.4, rfdc@^1.2.0, rfdc@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b"
|
||||
integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==
|
||||
@ -5089,7 +5238,7 @@ run-parallel@^1.1.9:
|
||||
dependencies:
|
||||
queue-microtask "^1.2.2"
|
||||
|
||||
safe-buffer@^5.0.1, safe-buffer@~5.2.0:
|
||||
safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@~5.2.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||
@ -5161,11 +5310,35 @@ semver@~7.0.0:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
|
||||
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
|
||||
|
||||
send@^0.18.0:
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"
|
||||
integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==
|
||||
dependencies:
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
destroy "1.2.0"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
fresh "0.5.2"
|
||||
http-errors "2.0.0"
|
||||
mime "1.6.0"
|
||||
ms "2.1.3"
|
||||
on-finished "2.4.1"
|
||||
range-parser "~1.2.1"
|
||||
statuses "2.0.1"
|
||||
|
||||
set-cookie-parser@^2.4.1:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.5.1.tgz#ddd3e9a566b0e8e0862aca974a6ac0e01349430b"
|
||||
integrity sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==
|
||||
|
||||
setprototypeof@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
|
||||
integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
|
||||
|
||||
shebang-command@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
|
||||
@ -5318,6 +5491,11 @@ stack-utils@^2.0.3:
|
||||
dependencies:
|
||||
escape-string-regexp "^2.0.0"
|
||||
|
||||
statuses@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
|
||||
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
|
||||
|
||||
steed@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/steed/-/steed-1.1.3.tgz#f1525dd5adb12eb21bf74749537668d625b9abc5"
|
||||
@ -5546,6 +5724,11 @@ to-regex-range@^5.0.1:
|
||||
dependencies:
|
||||
is-number "^7.0.0"
|
||||
|
||||
toidentifier@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
|
||||
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
|
||||
|
||||
touch@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b"
|
||||
@ -5847,6 +6030,11 @@ yaml@^1.10.0:
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
||||
|
||||
yaml@^2.1.1, yaml@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.1.3.tgz#9b3a4c8aff9821b696275c79a8bee8399d945207"
|
||||
integrity sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==
|
||||
|
||||
yargs-parser@^20.2.3:
|
||||
version "20.2.9"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
|
||||
|
Loading…
Reference in New Issue
Block a user