Standardize code formatting for consistency
Update all NestJS imports to use double quotes instead of single quotes across multiple files. Adjusted indentation in various files to ensure uniform code style. These changes improve code readability and maintainability.
This commit is contained in:
parent
2aa132e511
commit
fd8ad47cf7
@ -1,8 +1,8 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { AdminController } from './admin.controller';
|
||||
import { AdminService } from './admin.service';
|
||||
import { Test, TestingModule } from "@nestjs/testing";
|
||||
import { AdminController } from "./admin.controller";
|
||||
import { AdminService } from "./admin.service";
|
||||
|
||||
describe('AdminController', () => {
|
||||
describe("AdminController", () => {
|
||||
let controller: AdminController;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -14,7 +14,7 @@ describe('AdminController', () => {
|
||||
controller = module.get<AdminController>(AdminController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
it("should be defined", () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Controller } from '@nestjs/common';
|
||||
import { AdminService } from './admin.service';
|
||||
import { Controller } from "@nestjs/common";
|
||||
import { AdminService } from "./admin.service";
|
||||
|
||||
@Controller('admin')
|
||||
@Controller("admin")
|
||||
export class AdminController {
|
||||
constructor(private readonly adminService: AdminService) {}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AdminService } from './admin.service';
|
||||
import { AdminController } from './admin.controller';
|
||||
import { Module } from "@nestjs/common";
|
||||
import { AdminController } from "./admin.controller";
|
||||
import { AdminService } from "./admin.service";
|
||||
|
||||
@Module({
|
||||
controllers: [AdminController],
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { AdminService } from './admin.service';
|
||||
import { Test, TestingModule } from "@nestjs/testing";
|
||||
import { AdminService } from "./admin.service";
|
||||
|
||||
describe('AdminService', () => {
|
||||
describe("AdminService", () => {
|
||||
let service: AdminService;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -12,7 +12,7 @@ describe('AdminService', () => {
|
||||
service = module.get<AdminService>(AdminService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
it("should be defined", () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable } from "@nestjs/common";
|
||||
|
||||
@Injectable()
|
||||
export class AdminService {}
|
||||
|
@ -1,17 +1,17 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { Module } from "@nestjs/common";
|
||||
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
import { DbModule } from './db/db.module';
|
||||
import { ThrottlerModule } from '@nestjs/throttler';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { AuthModule } from './auth/auth.module';
|
||||
import { CredentialsModule } from './credentials/credentials.module';
|
||||
import { FilesModule } from './files/files.module';
|
||||
import { AdminModule } from './admin/admin.module';
|
||||
import { GroupsModule } from './groups/groups.module';
|
||||
import { MachinesModule } from './machines/machines.module';
|
||||
import { AuthorsModule } from 'apps/backend/src/app/authors/authors.module';
|
||||
import { ConfigModule } from "@nestjs/config";
|
||||
import { ThrottlerModule } from "@nestjs/throttler";
|
||||
import { AuthorsModule } from "apps/backend/src/app/authors/authors.module";
|
||||
import { AdminModule } from "./admin/admin.module";
|
||||
import { AppController } from "./app.controller";
|
||||
import { AppService } from "./app.service";
|
||||
import { AuthModule } from "./auth/auth.module";
|
||||
import { CredentialsModule } from "./credentials/credentials.module";
|
||||
import { DbModule } from "./db/db.module";
|
||||
import { FilesModule } from "./files/files.module";
|
||||
import { GroupsModule } from "./groups/groups.module";
|
||||
import { MachinesModule } from "./machines/machines.module";
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
@ -4,14 +4,15 @@ import {
|
||||
Delete,
|
||||
Get,
|
||||
HttpCode,
|
||||
HttpStatus, Patch,
|
||||
HttpStatus,
|
||||
Patch,
|
||||
Post,
|
||||
UnauthorizedException,
|
||||
UseGuards
|
||||
UseGuards,
|
||||
} from "@nestjs/common";
|
||||
import { SignInDto, SignUpDto } from "apps/backend/src/app/auth/auth.dto";
|
||||
import { AuthService } from "apps/backend/src/app/auth/auth.service";
|
||||
import { UserGuard } from "./auth.guard";
|
||||
import { AuthService } from 'apps/backend/src/app/auth/auth.service';
|
||||
import { SignInDto, SignUpDto } from 'apps/backend/src/app/auth/auth.dto';
|
||||
|
||||
@Controller("auth")
|
||||
export class AuthController {
|
||||
@ -39,8 +40,8 @@ export class AuthController {
|
||||
@UseGuards(UserGuard)
|
||||
async getMe(@Body() body: object) {
|
||||
// @ts-ignore
|
||||
const targetId = body.sourceUserId
|
||||
const userData = await this.authService.fetchUserById(targetId)
|
||||
const targetId = body.sourceUserId;
|
||||
const userData = await this.authService.fetchUserById(targetId);
|
||||
if (!userData) {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
@ -52,9 +53,9 @@ export class AuthController {
|
||||
@UseGuards(UserGuard)
|
||||
async deleteMe(@Body() body: object) {
|
||||
// @ts-ignore
|
||||
const targetId = body.sourceUserId
|
||||
const targetId = body.sourceUserId;
|
||||
try {
|
||||
await this.authService.deleteUser(targetId)
|
||||
await this.authService.deleteUser(targetId);
|
||||
} catch (err) {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
|
@ -1,23 +1,26 @@
|
||||
import { Injectable, CanActivate, ExecutionContext, UnauthorizedException, Inject } from "@nestjs/common";
|
||||
import type { Request } from "express";
|
||||
import { eq } from "drizzle-orm";
|
||||
import {
|
||||
CanActivate,
|
||||
ExecutionContext,
|
||||
Inject,
|
||||
Injectable,
|
||||
UnauthorizedException,
|
||||
} from "@nestjs/common";
|
||||
import { Reflector } from "@nestjs/core";
|
||||
import { DbService } from 'apps/backend/src/app/db/db.service';
|
||||
import { UsersTable } from 'apps/backend/src/app/db/schema';
|
||||
import { CredentialsService } from 'apps/backend/src/app/credentials/credentials.service';
|
||||
import { CredentialsService } from "apps/backend/src/app/credentials/credentials.service";
|
||||
import { DbService } from "apps/backend/src/app/db/db.service";
|
||||
import { UsersTable } from "apps/backend/src/app/db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import type { Request } from "express";
|
||||
|
||||
@Injectable()
|
||||
export class UserGuard implements CanActivate {
|
||||
|
||||
constructor(
|
||||
@Inject(CredentialsService) private readonly credentialService: CredentialsService,
|
||||
@Inject(CredentialsService)
|
||||
private readonly credentialService: CredentialsService,
|
||||
@Inject(DbService) private readonly databaseService: DbService,
|
||||
) {
|
||||
}
|
||||
) {}
|
||||
|
||||
async canActivate(
|
||||
context: ExecutionContext
|
||||
): Promise<boolean> {
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
const request: Request = context.switchToHttp().getRequest();
|
||||
const authHeader = request.headers.authorization;
|
||||
|
||||
@ -27,7 +30,8 @@ export class UserGuard implements CanActivate {
|
||||
const token = authHeader.split(" ")[1];
|
||||
const vToken = await this.credentialService.verifyAuthToken(token);
|
||||
|
||||
const user = await this.databaseService.use()
|
||||
const user = await this.databaseService
|
||||
.use()
|
||||
.select()
|
||||
.from(UsersTable)
|
||||
.where(eq(UsersTable.uuid, vToken.payload.sub));
|
||||
@ -49,25 +53,23 @@ export class UserGuard implements CanActivate {
|
||||
|
||||
@Injectable()
|
||||
export class AdminGuard implements CanActivate {
|
||||
|
||||
constructor(
|
||||
@Inject(CredentialsService) private readonly credentialService: CredentialsService,
|
||||
@Inject(CredentialsService)
|
||||
private readonly credentialService: CredentialsService,
|
||||
@Inject(DbService) private readonly databaseService: DbService,
|
||||
) {}
|
||||
async canActivate(
|
||||
context: ExecutionContext
|
||||
): Promise<boolean> {
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
const request: Request = context.switchToHttp().getRequest();
|
||||
|
||||
const authHeader = request.headers.authorization;
|
||||
if (!authHeader) {
|
||||
throw new UnauthorizedException("No authorization header found.");
|
||||
|
||||
}
|
||||
const token = authHeader.split(" ")[1];
|
||||
const vToken = await this.credentialService.verifyAuthToken(token);
|
||||
|
||||
const user = await this.databaseService.use()
|
||||
const user = await this.databaseService
|
||||
.use()
|
||||
.select()
|
||||
.from(UsersTable)
|
||||
.where(eq(UsersTable.uuid, vToken.payload.sub));
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { AdminGuard, UserGuard } from "apps/backend/src/app/auth/auth.guard";
|
||||
import { CredentialsModule } from "apps/backend/src/app/credentials/credentials.module";
|
||||
import { CredentialsService } from "apps/backend/src/app/credentials/credentials.service";
|
||||
import { DbModule } from "apps/backend/src/app/db/db.module";
|
||||
import { AuthController } from "./auth.controller";
|
||||
import { AuthService } from "./auth.service";
|
||||
import { DbModule } from 'apps/backend/src/app/db/db.module';
|
||||
import { CredentialsModule } from 'apps/backend/src/app/credentials/credentials.module';
|
||||
import { CredentialsService } from 'apps/backend/src/app/credentials/credentials.service';
|
||||
import { AdminGuard, UserGuard } from 'apps/backend/src/app/auth/auth.guard';
|
||||
|
||||
@Module({
|
||||
imports: [DbModule, CredentialsModule],
|
||||
|
@ -3,11 +3,11 @@ import {
|
||||
OnModuleInit,
|
||||
UnauthorizedException,
|
||||
} from "@nestjs/common";
|
||||
import { SignInDto, SignUpDto } from "apps/backend/src/app/auth/auth.dto";
|
||||
import { CredentialsService } from "apps/backend/src/app/credentials/credentials.service";
|
||||
import { DbService } from "apps/backend/src/app/db/db.service";
|
||||
import { UsersTable } from "apps/backend/src/app/db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { DbService } from 'apps/backend/src/app/db/db.service';
|
||||
import { CredentialsService } from 'apps/backend/src/app/credentials/credentials.service';
|
||||
import { UsersTable } from 'apps/backend/src/app/db/schema';
|
||||
import { SignInDto, SignUpDto } from 'apps/backend/src/app/auth/auth.dto';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService implements OnModuleInit {
|
||||
@ -156,4 +156,3 @@ export class AuthService implements OnModuleInit {
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { AuthorsController } from 'apps/backend/src/app/authors/authors.controller';
|
||||
import { AuthorsService } from 'apps/backend/src/app/authors/authors.service';
|
||||
import { Test, TestingModule } from "@nestjs/testing";
|
||||
import { AuthorsController } from "apps/backend/src/app/authors/authors.controller";
|
||||
import { AuthorsService } from "apps/backend/src/app/authors/authors.service";
|
||||
|
||||
describe('AuthorsController', () => {
|
||||
describe("AuthorsController", () => {
|
||||
let controller: AuthorsController;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -14,7 +14,7 @@ describe('AuthorsController', () => {
|
||||
controller = module.get<AuthorsController>(AuthorsController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
it("should be defined", () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,16 @@
|
||||
import { Controller, DefaultValuePipe, Delete, Get, Param, ParseIntPipe, Post, Query } from '@nestjs/common';
|
||||
import { AuthorsService } from 'apps/backend/src/app/authors/authors.service';
|
||||
import {
|
||||
Controller,
|
||||
DefaultValuePipe,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Post,
|
||||
Query,
|
||||
} from "@nestjs/common";
|
||||
import { AuthorsService } from "apps/backend/src/app/authors/authors.service";
|
||||
|
||||
@Controller('authors')
|
||||
@Controller("authors")
|
||||
export class AuthorsController {
|
||||
constructor(private readonly authorService: AuthorsService) {}
|
||||
|
||||
@ -9,23 +18,18 @@ export class AuthorsController {
|
||||
async findMany(
|
||||
@Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number,
|
||||
@Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number,
|
||||
@Query("search", new DefaultValuePipe("")) search: string
|
||||
@Query("search", new DefaultValuePipe("")) search: string,
|
||||
) {
|
||||
const query = {limit, offset, search}
|
||||
|
||||
const query = { limit, offset, search };
|
||||
}
|
||||
|
||||
//POST a new group
|
||||
@Post("new")
|
||||
async newAuthor() {
|
||||
|
||||
}
|
||||
async newAuthor() {}
|
||||
|
||||
//DELETE a group
|
||||
@Delete(":authorId")
|
||||
async deleteAuthor(@Param('authorId') authorId: string) {
|
||||
|
||||
}
|
||||
async deleteAuthor(@Param("authorId") authorId: string) {}
|
||||
|
||||
//GET files associated to authors with limit and offset
|
||||
@Get(":authorId")
|
||||
@ -33,9 +37,8 @@ export class AuthorsController {
|
||||
@Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number,
|
||||
@Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number,
|
||||
@Query("search", new DefaultValuePipe("")) search: string,
|
||||
@Param('authorId') authorId: string
|
||||
@Param("authorId") authorId: string,
|
||||
) {
|
||||
const query = {limit, offset, search}
|
||||
|
||||
const query = { limit, offset, search };
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AuthorsService } from 'apps/backend/src/app/authors/authors.service';
|
||||
import { AuthorsController } from 'apps/backend/src/app/authors/authors.controller';
|
||||
import { Module } from "@nestjs/common";
|
||||
import { AuthorsController } from "apps/backend/src/app/authors/authors.controller";
|
||||
import { AuthorsService } from "apps/backend/src/app/authors/authors.service";
|
||||
|
||||
@Module({
|
||||
controllers: [AuthorsController],
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { AuthorsService } from 'apps/backend/src/app/authors/authors.service';
|
||||
import { Test, TestingModule } from "@nestjs/testing";
|
||||
import { AuthorsService } from "apps/backend/src/app/authors/authors.service";
|
||||
|
||||
describe('AuthorsService', () => {
|
||||
describe("AuthorsService", () => {
|
||||
let service: AuthorsService;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -12,7 +12,7 @@ describe('AuthorsService', () => {
|
||||
service = module.get<AuthorsService>(AuthorsService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
it("should be defined", () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable } from "@nestjs/common";
|
||||
|
||||
@Injectable()
|
||||
export class AuthorsService {}
|
||||
|
@ -36,7 +36,7 @@ export class CredentialsService {
|
||||
console.log(result);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
console.log(error);
|
||||
throw new BadRequestException("Invalid token");
|
||||
}
|
||||
}
|
||||
|
@ -61,9 +61,11 @@ export const FilesTable = pgTable("files", {
|
||||
})
|
||||
.notNull(),
|
||||
|
||||
checksum: p.varchar("checksum", {
|
||||
length: 64
|
||||
}).notNull(),
|
||||
checksum: p
|
||||
.varchar("checksum", {
|
||||
length: 64,
|
||||
})
|
||||
.notNull(),
|
||||
|
||||
uploader: p
|
||||
.varchar("uploader", {
|
||||
@ -71,9 +73,7 @@ export const FilesTable = pgTable("files", {
|
||||
})
|
||||
.notNull(),
|
||||
|
||||
groupId: p
|
||||
.uuid("group_id")
|
||||
.references(()=> FilesGroupTable.uuid),
|
||||
groupId: p.uuid("group_id").references(() => FilesGroupTable.uuid),
|
||||
|
||||
fileSize: p.integer("file_size").notNull(),
|
||||
|
||||
@ -109,7 +109,7 @@ export const FilesGroupTable = pgTable("f_groups", {
|
||||
})
|
||||
.unique()
|
||||
.notNull(),
|
||||
})
|
||||
});
|
||||
|
||||
//TODO Files types
|
||||
export const FilesTypesTable = pgTable("f_types", {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { FilesController } from './files.controller';
|
||||
import { FilesService } from './files.service';
|
||||
import { Test, TestingModule } from "@nestjs/testing";
|
||||
import { FilesController } from "./files.controller";
|
||||
import { FilesService } from "./files.service";
|
||||
|
||||
describe('FilesController', () => {
|
||||
describe("FilesController", () => {
|
||||
let controller: FilesController;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -14,7 +14,7 @@ describe('FilesController', () => {
|
||||
controller = module.get<FilesController>(FilesController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
it("should be defined", () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Controller } from '@nestjs/common';
|
||||
import { FilesService } from './files.service';
|
||||
import { Controller } from "@nestjs/common";
|
||||
import { FilesService } from "./files.service";
|
||||
|
||||
@Controller('files')
|
||||
@Controller("files")
|
||||
export class FilesController {
|
||||
constructor(private readonly filesService: FilesService) {}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { FilesService } from './files.service';
|
||||
import { FilesController } from './files.controller';
|
||||
import { Module } from "@nestjs/common";
|
||||
import { FilesController } from "./files.controller";
|
||||
import { FilesService } from "./files.service";
|
||||
|
||||
@Module({
|
||||
controllers: [FilesController],
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { FilesService } from './files.service';
|
||||
import { Test, TestingModule } from "@nestjs/testing";
|
||||
import { FilesService } from "./files.service";
|
||||
|
||||
describe('FilesService', () => {
|
||||
describe("FilesService", () => {
|
||||
let service: FilesService;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -12,7 +12,7 @@ describe('FilesService', () => {
|
||||
service = module.get<FilesService>(FilesService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
it("should be defined", () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable } from "@nestjs/common";
|
||||
|
||||
@Injectable()
|
||||
export class FilesService {}
|
||||
|
0
apps/backend/src/app/global.dto.ts
Normal file
0
apps/backend/src/app/global.dto.ts
Normal file
@ -1,8 +1,8 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { GroupsController } from './groups.controller';
|
||||
import { GroupsService } from './groups.service';
|
||||
import { Test, TestingModule } from "@nestjs/testing";
|
||||
import { GroupsController } from "./groups.controller";
|
||||
import { GroupsService } from "./groups.service";
|
||||
|
||||
describe('GroupsController', () => {
|
||||
describe("GroupsController", () => {
|
||||
let controller: GroupsController;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -14,7 +14,7 @@ describe('GroupsController', () => {
|
||||
controller = module.get<GroupsController>(GroupsController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
it("should be defined", () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
@ -1,8 +1,17 @@
|
||||
import { Controller, DefaultValuePipe, Delete, Get, Param, ParseIntPipe, Post, Query } from '@nestjs/common';
|
||||
import { GroupsService } from './groups.service';
|
||||
import { ISearchQuery } from 'apps/backend/src/app/groups/groups.types';
|
||||
import {
|
||||
Controller,
|
||||
DefaultValuePipe,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Post,
|
||||
Query,
|
||||
} from "@nestjs/common";
|
||||
import { ISearchQuery } from "apps/backend/src/app/groups/groups.types";
|
||||
import { GroupsService } from "./groups.service";
|
||||
|
||||
@Controller('groups')
|
||||
@Controller("groups")
|
||||
export class GroupsController {
|
||||
constructor(private readonly groupsService: GroupsService) {}
|
||||
|
||||
@ -11,23 +20,18 @@ export class GroupsController {
|
||||
async findMany(
|
||||
@Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number,
|
||||
@Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number,
|
||||
@Query("search", new DefaultValuePipe("")) search: string
|
||||
@Query("search", new DefaultValuePipe("")) search: string,
|
||||
) {
|
||||
const query = {limit, offset, search}
|
||||
|
||||
const query = { limit, offset, search };
|
||||
}
|
||||
|
||||
//POST a new group
|
||||
@Post("new")
|
||||
async newGroup() {
|
||||
|
||||
}
|
||||
async newGroup() {}
|
||||
|
||||
//DELETE a group
|
||||
@Delete(":groupId")
|
||||
async deleteGroup(@Param('groupId') groupId: string) {
|
||||
|
||||
}
|
||||
async deleteGroup(@Param("groupId") groupId: string) {}
|
||||
|
||||
//GET files associated to group with limit and offset
|
||||
@Get(":groupId")
|
||||
@ -35,9 +39,8 @@ export class GroupsController {
|
||||
@Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number,
|
||||
@Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number,
|
||||
@Query("search", new DefaultValuePipe("")) search: string,
|
||||
@Param('groupId') groupId: string
|
||||
@Param("groupId") groupId: string,
|
||||
) {
|
||||
const query = {limit, offset, search}
|
||||
|
||||
const query = { limit, offset, search };
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { GroupsService } from './groups.service';
|
||||
import { GroupsController } from './groups.controller';
|
||||
import { Module } from "@nestjs/common";
|
||||
import { GroupsController } from "./groups.controller";
|
||||
import { GroupsService } from "./groups.service";
|
||||
|
||||
@Module({
|
||||
controllers: [GroupsController],
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { GroupsService } from './groups.service';
|
||||
import { Test, TestingModule } from "@nestjs/testing";
|
||||
import { GroupsService } from "./groups.service";
|
||||
|
||||
describe('GroupsService', () => {
|
||||
describe("GroupsService", () => {
|
||||
let service: GroupsService;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -12,7 +12,7 @@ describe('GroupsService', () => {
|
||||
service = module.get<GroupsService>(GroupsService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
it("should be defined", () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable } from "@nestjs/common";
|
||||
|
||||
@Injectable()
|
||||
export class GroupsService {}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { MachinesController } from 'apps/backend/src/app/machines/machines.controller';
|
||||
import { MachinesService } from 'apps/backend/src/app/machines/machines.service';
|
||||
import { Test, TestingModule } from "@nestjs/testing";
|
||||
import { MachinesController } from "apps/backend/src/app/machines/machines.controller";
|
||||
import { MachinesService } from "apps/backend/src/app/machines/machines.service";
|
||||
|
||||
describe('MachineController', () => {
|
||||
describe("MachineController", () => {
|
||||
let controller: MachinesController;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -14,7 +14,7 @@ describe('MachineController', () => {
|
||||
controller = module.get<MachinesController>(MachinesController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
it("should be defined", () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,16 @@
|
||||
import { Controller, DefaultValuePipe, Delete, Get, Param, ParseIntPipe, Post, Query } from '@nestjs/common';
|
||||
import { MachinesService } from 'apps/backend/src/app/machines/machines.service';
|
||||
import {
|
||||
Controller,
|
||||
DefaultValuePipe,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Post,
|
||||
Query,
|
||||
} from "@nestjs/common";
|
||||
import { MachinesService } from "apps/backend/src/app/machines/machines.service";
|
||||
|
||||
@Controller('machines')
|
||||
@Controller("machines")
|
||||
export class MachinesController {
|
||||
constructor(private readonly machineService: MachinesService) {}
|
||||
|
||||
@ -9,30 +18,24 @@ export class MachinesController {
|
||||
async findMany(
|
||||
@Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number,
|
||||
@Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number,
|
||||
@Query("search", new DefaultValuePipe("")) search: string
|
||||
@Query("search", new DefaultValuePipe("")) search: string,
|
||||
) {
|
||||
const query = {limit, offset, search}
|
||||
|
||||
const query = { limit, offset, search };
|
||||
}
|
||||
|
||||
@Post("new")
|
||||
async newMachine() {
|
||||
|
||||
}
|
||||
async newMachine() {}
|
||||
|
||||
@Delete(":machineId")
|
||||
async deleteGroup(@Param('machineId') machineId: string) {
|
||||
|
||||
}
|
||||
async deleteGroup(@Param("machineId") machineId: string) {}
|
||||
|
||||
@Get(":groupId")
|
||||
async getForGroup(
|
||||
@Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number,
|
||||
@Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number,
|
||||
@Query("search", new DefaultValuePipe("")) search: string,
|
||||
@Param('machineId') machineId: string
|
||||
@Param("machineId") machineId: string,
|
||||
) {
|
||||
const query = {limit, offset, search}
|
||||
|
||||
const query = { limit, offset, search };
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { MachinesService } from 'apps/backend/src/app/machines/machines.service';
|
||||
import { MachinesController } from 'apps/backend/src/app/machines/machines.controller';
|
||||
import { Module } from "@nestjs/common";
|
||||
import { MachinesController } from "apps/backend/src/app/machines/machines.controller";
|
||||
import { MachinesService } from "apps/backend/src/app/machines/machines.service";
|
||||
|
||||
@Module({
|
||||
controllers: [MachinesController],
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { MachinesService } from 'apps/backend/src/app/machines/machines.service';
|
||||
import { Test, TestingModule } from "@nestjs/testing";
|
||||
import { MachinesService } from "apps/backend/src/app/machines/machines.service";
|
||||
|
||||
describe('MachinesService', () => {
|
||||
describe("MachinesService", () => {
|
||||
let service: MachinesService;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -12,7 +12,7 @@ describe('MachinesService', () => {
|
||||
service = module.get<MachinesService>(MachinesService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
it("should be defined", () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable } from "@nestjs/common";
|
||||
|
||||
@Injectable()
|
||||
export class MachinesService {}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { DbModule } from "apps/backend/src/app/db/db.module";
|
||||
import { StorageService } from "apps/backend/src/app/storage/storage.service";
|
||||
import { DbModule } from 'apps/backend/src/app/db/db.module';
|
||||
|
||||
@Module({
|
||||
imports: [DbModule],
|
||||
|
@ -8,11 +8,14 @@ import {
|
||||
InternalServerErrorException,
|
||||
NotFoundException,
|
||||
} from "@nestjs/common";
|
||||
import { DbService } from "apps/backend/src/app/db/db.service";
|
||||
import {
|
||||
FilesTypeForMachine,
|
||||
FilesTypesTable,
|
||||
} from "apps/backend/src/app/db/schema";
|
||||
import { IFileInformation } from "apps/backend/src/app/storage/storage.types";
|
||||
import { eq } from "drizzle-orm";
|
||||
import FileType from "file-type";
|
||||
import { DbService } from 'apps/backend/src/app/db/db.service';
|
||||
import { IFileInformation } from 'apps/backend/src/app/storage/storage.types';
|
||||
import { FilesTypeForMachine, FilesTypesTable } from 'apps/backend/src/app/db/schema';
|
||||
import { eq } from 'drizzle-orm';
|
||||
|
||||
@Injectable()
|
||||
export class StorageService {
|
||||
@ -20,7 +23,6 @@ export class StorageService {
|
||||
private maxFileSize = 256; // MiB unit
|
||||
constructor(private readonly dbService: DbService) {}
|
||||
|
||||
|
||||
/**
|
||||
* Save a file to the specified directory.
|
||||
*
|
||||
@ -44,8 +46,10 @@ export class StorageService {
|
||||
* @param {Buffer} file - The file to check.
|
||||
* @return {Promise<boolean>} - A Promise that resolves to true if the conditions are met, false otherwise.
|
||||
*/
|
||||
private async checkConditions(machineIds: Array<string>,file: Buffer): Promise<boolean> {
|
||||
|
||||
private async checkConditions(
|
||||
machineIds: Array<string>,
|
||||
file: Buffer,
|
||||
): Promise<boolean> {
|
||||
/**
|
||||
* Checks if the current MIME type is allowed based on the given set of allowed MIME types.
|
||||
* @param {Set<string>} allowedMime - The set of allowed MIME types.
|
||||
@ -60,53 +64,55 @@ export class StorageService {
|
||||
const fileType = await FileType.fileTypeFromBuffer(file);
|
||||
|
||||
// Array of MIMEs with possible duplicate field
|
||||
const _mimes: Array<string> = []
|
||||
const _mimes: Array<string> = [];
|
||||
|
||||
// Fetching MIMEs for the associated machines
|
||||
for (const machineId of machineIds) {
|
||||
console.debug(`Fetching mimeTypes for machine : ${machineId}`)
|
||||
console.debug(`Fetching mimeTypes for machine : ${machineId}`);
|
||||
// Get MIMEs associated to a machine
|
||||
const allowedMimeId = this.dbService.use()
|
||||
const allowedMimeId = this.dbService
|
||||
.use()
|
||||
.select()
|
||||
.from(FilesTypeForMachine)
|
||||
.where(eq(FilesTypeForMachine.machineId, machineId)).as("allowedMimeId");
|
||||
const _allowedMime = await this.dbService.use()
|
||||
.where(eq(FilesTypeForMachine.machineId, machineId))
|
||||
.as("allowedMimeId");
|
||||
const _allowedMime = await this.dbService
|
||||
.use()
|
||||
.select({
|
||||
slug: FilesTypesTable.mime,
|
||||
name: FilesTypesTable.typeName
|
||||
name: FilesTypesTable.typeName,
|
||||
})
|
||||
.from(FilesTypesTable)
|
||||
.leftJoin(allowedMimeId, eq(FilesTypesTable.id, allowedMimeId.fileTypeId))
|
||||
console.debug(`Total : ${_allowedMime.length}`)
|
||||
.leftJoin(
|
||||
allowedMimeId,
|
||||
eq(FilesTypesTable.id, allowedMimeId.fileTypeId),
|
||||
);
|
||||
console.debug(`Total : ${_allowedMime.length}`);
|
||||
// Append each MIME of a machine
|
||||
for (const allowedMimeElement of _allowedMime) {
|
||||
_mimes.push(allowedMimeElement.slug)
|
||||
_mimes.push(allowedMimeElement.slug);
|
||||
}
|
||||
}
|
||||
//Store the MIMEs without duplicate
|
||||
const mimeSet = new Set(_mimes)
|
||||
console.debug(`Indexed ${mimeSet.size} unique mimeTypes`)
|
||||
const mimeSet = new Set(_mimes);
|
||||
console.debug(`Indexed ${mimeSet.size} unique mimeTypes`);
|
||||
|
||||
//check file size is less than 2mb
|
||||
const fileSize = file.byteLength;
|
||||
if (fileSize > this.maxFileSize * (1024 * 1024)) {
|
||||
throw new BadRequestException(
|
||||
"File size to high.",
|
||||
{
|
||||
throw new BadRequestException("File size to high.", {
|
||||
cause: "File size",
|
||||
description: `File size exceeds the limit. Maximum file size allowed is ${this.maxFileSize}MiB.`
|
||||
}
|
||||
);
|
||||
description: `File size exceeds the limit. Maximum file size allowed is ${this.maxFileSize}MiB.`,
|
||||
});
|
||||
}
|
||||
|
||||
if (!checkMime(mimeSet, fileType.mime)) throw new BadRequestException(
|
||||
{
|
||||
if (!checkMime(mimeSet, fileType.mime))
|
||||
throw new BadRequestException({
|
||||
cause: "MIME type",
|
||||
description: `Invalid MIME type. Allowed MIME types are: ${[...mimeSet].join(", ")}.`
|
||||
}
|
||||
)
|
||||
description: `Invalid MIME type. Allowed MIME types are: ${[...mimeSet].join(", ")}.`,
|
||||
});
|
||||
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,12 +139,16 @@ export class StorageService {
|
||||
public async getChecksum(file: Buffer): Promise<string> {
|
||||
return new Promise((resolve) => {
|
||||
try {
|
||||
const checksum = crypto.createHash("sha256").update(file).digest("hex").toLowerCase();
|
||||
resolve(checksum)
|
||||
const checksum = crypto
|
||||
.createHash("sha256")
|
||||
.update(file)
|
||||
.digest("hex")
|
||||
.toLowerCase();
|
||||
resolve(checksum);
|
||||
} catch (err) {
|
||||
throw new InternalServerErrorException(err)
|
||||
throw new InternalServerErrorException(err);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -149,9 +159,13 @@ export class StorageService {
|
||||
* @param {boolean} [isDocumentation] - Optional flag to indicate if the file is a documentation file.
|
||||
* @returns {Promise<IFileInformation>} - A Promise that resolves to the generated file information.
|
||||
*/
|
||||
public async generateInformation(file: Buffer, fileDisplayName: string, isDocumentation?: boolean): Promise<IFileInformation> {
|
||||
public async generateInformation(
|
||||
file: Buffer,
|
||||
fileDisplayName: string,
|
||||
isDocumentation?: boolean,
|
||||
): Promise<IFileInformation> {
|
||||
const fileType = await FileType.fileTypeFromBuffer(file);
|
||||
const checksum = await this.getChecksum(file)
|
||||
const checksum = await this.getChecksum(file);
|
||||
const fileName = `${isDocumentation ? "doc" : "file"}-${checksum}.${fileType.ext.toLowerCase()}`;
|
||||
return {
|
||||
fileName: fileName,
|
||||
@ -159,24 +173,39 @@ export class StorageService {
|
||||
fileSize: file.byteLength,
|
||||
fileChecksum: checksum,
|
||||
fileType: fileType,
|
||||
isDocumentation: isDocumentation || false
|
||||
}
|
||||
isDocumentation: isDocumentation || false,
|
||||
};
|
||||
}
|
||||
|
||||
public async new(fileDisplayName: string, file: Buffer, isDocumentation?: boolean) {
|
||||
public async new(
|
||||
fileDisplayName: string,
|
||||
file: Buffer,
|
||||
isDocumentation?: boolean,
|
||||
) {
|
||||
try {
|
||||
const info = await this.generateInformation(file, fileDisplayName, isDocumentation);
|
||||
console.log(`Trying to append a new file : "${info.fileDisplayName}"...\n > Checksum SHA-256 : ${info.fileChecksum}\n > Size : ${info.fileSize / (1024*1024)}Mio\n > File format : ${info.fileType.mime}\n`)
|
||||
const condition = await this.checkConditions([/* TODO import autorized file format */], file)
|
||||
const info = await this.generateInformation(
|
||||
file,
|
||||
fileDisplayName,
|
||||
isDocumentation,
|
||||
);
|
||||
console.log(
|
||||
`Trying to append a new file : "${info.fileDisplayName}"...\n > Checksum SHA-256 : ${info.fileChecksum}\n > Size : ${info.fileSize / (1024 * 1024)}Mio\n > File format : ${info.fileType.mime}\n`,
|
||||
);
|
||||
const condition = await this.checkConditions(
|
||||
[
|
||||
/* TODO import autorized file format */
|
||||
],
|
||||
file,
|
||||
);
|
||||
if (!condition) {
|
||||
console.warn(`File "${info.fileDisplayName}" did not pass the files requirement.\n${info.fileChecksum}`)
|
||||
console.warn(
|
||||
`File "${info.fileDisplayName}" did not pass the files requirement.\n${info.fileChecksum}`,
|
||||
);
|
||||
}
|
||||
|
||||
//TODO Append in DB and save to storage
|
||||
|
||||
|
||||
} catch (err) {
|
||||
throw new BadRequestException(err)
|
||||
throw new BadRequestException(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import FileType from 'file-type';
|
||||
|
||||
import FileType from "file-type";
|
||||
|
||||
export interface IFileInformation {
|
||||
fileDisplayName: string;
|
||||
@ -13,5 +12,5 @@ export interface IFileInformation {
|
||||
export interface IFileWithInformation<AdditionalData> {
|
||||
buffer: Buffer;
|
||||
info: IFileInformation;
|
||||
additionalData?: AdditionalData
|
||||
additionalData?: AdditionalData;
|
||||
}
|
@ -1,78 +1,75 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
// Inspired by react-hot-toast library
|
||||
import * as React from "react"
|
||||
import * as React from "react";
|
||||
|
||||
import type {
|
||||
ToastActionElement,
|
||||
ToastProps,
|
||||
} from "./toast"
|
||||
import type { ToastActionElement, ToastProps } from "./toast";
|
||||
|
||||
const TOAST_LIMIT = 1
|
||||
const TOAST_REMOVE_DELAY = 1000000
|
||||
const TOAST_LIMIT = 1;
|
||||
const TOAST_REMOVE_DELAY = 1000000;
|
||||
|
||||
type ToasterToast = ToastProps & {
|
||||
id: string
|
||||
title?: React.ReactNode
|
||||
description?: React.ReactNode
|
||||
action?: ToastActionElement
|
||||
}
|
||||
id: string;
|
||||
title?: React.ReactNode;
|
||||
description?: React.ReactNode;
|
||||
action?: ToastActionElement;
|
||||
};
|
||||
|
||||
const actionTypes = {
|
||||
ADD_TOAST: "ADD_TOAST",
|
||||
UPDATE_TOAST: "UPDATE_TOAST",
|
||||
DISMISS_TOAST: "DISMISS_TOAST",
|
||||
REMOVE_TOAST: "REMOVE_TOAST",
|
||||
} as const
|
||||
} as const;
|
||||
|
||||
let count = 0
|
||||
let count = 0;
|
||||
|
||||
function genId() {
|
||||
count = (count + 1) % Number.MAX_SAFE_INTEGER
|
||||
return count.toString()
|
||||
count = (count + 1) % Number.MAX_SAFE_INTEGER;
|
||||
return count.toString();
|
||||
}
|
||||
|
||||
type ActionType = typeof actionTypes
|
||||
type ActionType = typeof actionTypes;
|
||||
|
||||
type Action =
|
||||
| {
|
||||
type: ActionType["ADD_TOAST"]
|
||||
toast: ToasterToast
|
||||
type: ActionType["ADD_TOAST"];
|
||||
toast: ToasterToast;
|
||||
}
|
||||
| {
|
||||
type: ActionType["UPDATE_TOAST"]
|
||||
toast: Partial<ToasterToast>
|
||||
type: ActionType["UPDATE_TOAST"];
|
||||
toast: Partial<ToasterToast>;
|
||||
}
|
||||
| {
|
||||
type: ActionType["DISMISS_TOAST"]
|
||||
toastId?: ToasterToast["id"]
|
||||
type: ActionType["DISMISS_TOAST"];
|
||||
toastId?: ToasterToast["id"];
|
||||
}
|
||||
| {
|
||||
type: ActionType["REMOVE_TOAST"]
|
||||
toastId?: ToasterToast["id"]
|
||||
}
|
||||
type: ActionType["REMOVE_TOAST"];
|
||||
toastId?: ToasterToast["id"];
|
||||
};
|
||||
|
||||
interface State {
|
||||
toasts: ToasterToast[]
|
||||
toasts: ToasterToast[];
|
||||
}
|
||||
|
||||
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()
|
||||
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();
|
||||
|
||||
const addToRemoveQueue = (toastId: string) => {
|
||||
if (toastTimeouts.has(toastId)) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
toastTimeouts.delete(toastId)
|
||||
toastTimeouts.delete(toastId);
|
||||
dispatch({
|
||||
type: "REMOVE_TOAST",
|
||||
toastId: toastId,
|
||||
})
|
||||
}, TOAST_REMOVE_DELAY)
|
||||
});
|
||||
}, TOAST_REMOVE_DELAY);
|
||||
|
||||
toastTimeouts.set(toastId, timeout)
|
||||
}
|
||||
toastTimeouts.set(toastId, timeout);
|
||||
};
|
||||
|
||||
export const reducer = (state: State, action: Action): State => {
|
||||
switch (action.type) {
|
||||
@ -80,26 +77,26 @@ export const reducer = (state: State, action: Action): State => {
|
||||
return {
|
||||
...state,
|
||||
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
|
||||
}
|
||||
};
|
||||
|
||||
case "UPDATE_TOAST":
|
||||
return {
|
||||
...state,
|
||||
toasts: state.toasts.map((t) =>
|
||||
t.id === action.toast.id ? { ...t, ...action.toast } : t
|
||||
t.id === action.toast.id ? { ...t, ...action.toast } : t,
|
||||
),
|
||||
}
|
||||
};
|
||||
|
||||
case "DISMISS_TOAST": {
|
||||
const { toastId } = action
|
||||
const { toastId } = action;
|
||||
|
||||
// ! Side effects ! - This could be extracted into a dismissToast() action,
|
||||
// but I'll keep it here for simplicity
|
||||
if (toastId) {
|
||||
addToRemoveQueue(toastId)
|
||||
addToRemoveQueue(toastId);
|
||||
} else {
|
||||
for (const toast1 of state.toasts) {
|
||||
addToRemoveQueue(toast1.id)
|
||||
addToRemoveQueue(toast1.id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,46 +108,46 @@ export const reducer = (state: State, action: Action): State => {
|
||||
...t,
|
||||
open: false,
|
||||
}
|
||||
: t
|
||||
: t,
|
||||
),
|
||||
}
|
||||
};
|
||||
}
|
||||
case "REMOVE_TOAST":
|
||||
if (action.toastId === undefined) {
|
||||
return {
|
||||
...state,
|
||||
toasts: [],
|
||||
}
|
||||
};
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
toasts: state.toasts.filter((t) => t.id !== action.toastId),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const listeners: Array<(state: State) => void> = []
|
||||
const listeners: Array<(state: State) => void> = [];
|
||||
|
||||
let memoryState: State = { toasts: [] }
|
||||
let memoryState: State = { toasts: [] };
|
||||
|
||||
function dispatch(action: Action) {
|
||||
memoryState = reducer(memoryState, action)
|
||||
memoryState = reducer(memoryState, action);
|
||||
for (const listener of listeners) {
|
||||
listener(memoryState)
|
||||
listener(memoryState);
|
||||
}
|
||||
}
|
||||
|
||||
type Toast = Omit<ToasterToast, "id">
|
||||
type Toast = Omit<ToasterToast, "id">;
|
||||
|
||||
function toast({ ...props }: Toast) {
|
||||
const id = genId()
|
||||
const id = genId();
|
||||
|
||||
const update = (props: ToasterToast) =>
|
||||
dispatch({
|
||||
type: "UPDATE_TOAST",
|
||||
toast: { ...props, id },
|
||||
})
|
||||
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id })
|
||||
});
|
||||
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
|
||||
|
||||
dispatch({
|
||||
type: "ADD_TOAST",
|
||||
@ -159,37 +156,37 @@ function toast({ ...props }: Toast) {
|
||||
id,
|
||||
open: true,
|
||||
onOpenChange: (open) => {
|
||||
if (!open) dismiss()
|
||||
if (!open) dismiss();
|
||||
},
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
return {
|
||||
id: id,
|
||||
dismiss,
|
||||
update,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function useToast() {
|
||||
const [state, setState] = React.useState<State>(memoryState)
|
||||
const [state, setState] = React.useState<State>(memoryState);
|
||||
|
||||
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
|
||||
React.useEffect(() => {
|
||||
listeners.push(setState)
|
||||
listeners.push(setState);
|
||||
return () => {
|
||||
const index = listeners.indexOf(setState)
|
||||
const index = listeners.indexOf(setState);
|
||||
if (index > -1) {
|
||||
listeners.splice(index, 1)
|
||||
listeners.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}, [state])
|
||||
};
|
||||
}, [state]);
|
||||
|
||||
return {
|
||||
...state,
|
||||
toast,
|
||||
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export { useToast, toast }
|
||||
export { useToast, toast };
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { type ClassValue, clsx } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
import { type ClassValue, clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user