update packages and fix build

This commit is contained in:
Caramel
2023-11-28 18:55:41 +01:00
parent 1e9dad9ac2
commit d7241fa7b4
30 changed files with 4555 additions and 4264 deletions

View File

@@ -21,65 +21,65 @@
"purge": "rm -rf dist && rm -rf node_modules"
},
"dependencies": {
"@fastify/helmet": "^10.1.1",
"@fastify/multipart": "^7.6.1",
"@fastify/reply-from": "^9.3.0",
"@fastify/static": "^6.10.2",
"@nestjs/common": "^10.0.0",
"@nestjs/config": "^2.3.4",
"@nestjs/core": "^10.0.0",
"@nestjs/jwt": "^10.1.0",
"@nestjs/passport": "^9.0.3",
"@nestjs/platform-fastify": "^10.0.0",
"@nestjs/schedule": "^3.0.0",
"@fastify/helmet": "^11.1.1",
"@fastify/multipart": "^8.0.0",
"@fastify/reply-from": "^9.4.0",
"@fastify/static": "^6.12.0",
"@nestjs/common": "^10.2.10",
"@nestjs/config": "^3.1.1",
"@nestjs/core": "^10.2.10",
"@nestjs/jwt": "^10.2.0",
"@nestjs/passport": "^10.0.2",
"@nestjs/platform-fastify": "^10.2.10",
"@nestjs/schedule": "^4.0.0",
"@nestjs/serve-static": "^4.0.0",
"@nestjs/throttler": "^4.0.0",
"@nestjs/typeorm": "^9.0.1",
"bcrypt": "^5.1.0",
"@nestjs/throttler": "^5.0.1",
"@nestjs/typeorm": "^10.0.1",
"bcrypt": "^5.1.1",
"bmp-img": "^1.2.1",
"cors": "^2.8.5",
"extensionless": "^1.4.5",
"file-type": "^18.5.0",
"extensionless": "^1.7.3",
"file-type": "^18.7.0",
"is-docker": "^3.0.0",
"ms": "2.1.3",
"node-fetch": "^3.3.1",
"node-fetch": "^3.3.2",
"p-timeout": "^6.1.2",
"passport": "^0.6.0",
"passport": "^0.7.0",
"passport-headerapikey": "^1.2.2",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"passport-strategy": "^1.0.0",
"pg": "^8.11.0",
"pg": "^8.11.3",
"picsur-shared": "*",
"posix.js": "^0.1.1",
"qoi-img": "^2.1.1",
"reflect-metadata": "^0.1.13",
"rimraf": "^5.0.1",
"rimraf": "^5.0.5",
"rxjs": "^7.8.1",
"sharp": "^0.32.1",
"sharp": "^0.32.6",
"stream-parser": "^0.3.1",
"thunks": "^4.9.6",
"typeorm": "0.3.16",
"zod": "^3.21.4"
"typeorm": "0.3.17",
"zod": "^3.22.4"
},
"devDependencies": {
"@nestjs/cli": "^10.0.1",
"@nestjs/schematics": "^10.0.1",
"@nestjs/testing": "^10.0.0",
"@types/bcrypt": "^5.0.0",
"@types/cors": "^2.8.13",
"@types/multer": "^1.4.7",
"@types/node": "^20.3.1",
"@types/passport-jwt": "^3.0.8",
"@types/passport-local": "^1.0.35",
"@types/passport-strategy": "^0.2.35",
"@nestjs/cli": "^10.2.1",
"@nestjs/schematics": "^10.0.3",
"@nestjs/testing": "^10.2.10",
"@types/bcrypt": "^5.0.2",
"@types/cors": "^2.8.17",
"@types/multer": "^1.4.11",
"@types/node": "^20.10.0",
"@types/passport-jwt": "^3.0.13",
"@types/passport-local": "^1.0.38",
"@types/passport-strategy": "^0.2.38",
"@types/sharp": "^0.32.0",
"@types/supertest": "^2.0.12",
"prettier": "^2.8.8",
"@types/supertest": "^2.0.16",
"prettier": "^3.1.0",
"source-map-support": "^0.5.21",
"ts-loader": "^9.4.3",
"ts-loader": "^9.5.1",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.1.3"
"typescript": "^5.3.2"
}
}

View File

@@ -32,7 +32,7 @@ export class JwtConfigService implements JwtOptionsFactory {
await this.prefService.getStringPreference('jwt_expires_in'),
);
let milliseconds = ms(expiresIn as any);
let milliseconds = ms(expiresIn as string);
if (isNaN(milliseconds)) {
milliseconds = 1000 * 60 * 60 * 24; // 1 day
}

View File

@@ -0,0 +1,12 @@
import { Throttle } from '@nestjs/throttler';
export const EasyThrottle = (
limit: number,
ttl?: number,
): MethodDecorator & ClassDecorator =>
Throttle({
default: {
limit,
ttl: ttl ?? 60,
},
});

View File

@@ -8,8 +8,12 @@ import { ZodValidationPipe } from './validate/zod-validator.pipe';
@Module({
imports: [
ThrottlerModule.forRoot({
ttl: 60,
limit: 60,
throttlers: [
{
limit: 60,
ttl: 60,
},
],
}),
],
providers: [

View File

@@ -4,7 +4,7 @@ import { FT, Fail } from 'picsur-shared/dist/types/failable';
@Injectable()
export class PicsurThrottlerGuard extends ThrottlerGuard {
protected override throwThrottlingException(): void {
protected override throwThrottlingException(): Promise<void> {
throw Fail(FT.RateLimit);
}
}

View File

@@ -62,7 +62,7 @@ export class ImageConverterService {
if (HasFailed(memLimit) || HasFailed(timeLimit)) {
return Fail(FT.Internal, 'Failed to get conversion limits');
}
let timeLimitMS = ms(timeLimit as any);
let timeLimitMS = ms(timeLimit as string);
if (isNaN(timeLimitMS) || timeLimitMS === 0) timeLimitMS = 15 * 1000; // 15 seconds
const sharpWrapper = new SharpWrapper(timeLimitMS, memLimit);

View File

@@ -49,7 +49,7 @@ export class ImageManagerModule implements OnModuleInit {
return;
}
let after_ms = ms(remove_derivatives_after as any);
let after_ms = ms(remove_derivatives_after as string);
if (isNaN(after_ms) || after_ms === 0) {
this.logger.log('remove_derivatives_after is 0, skipping cron');
return;
@@ -59,6 +59,7 @@ export class ImageManagerModule implements OnModuleInit {
const result = await this.imageFileDB.cleanupDerivatives(after_ms / 1000);
if (HasFailed(result)) {
result.print(this.logger);
return;
}
if (result > 0) this.logger.log(`Cleaned up ${result} derivatives`);

View File

@@ -242,9 +242,8 @@ export class ImageManagerService {
// Util stuff ==================================================================
private async getFileTypeFromBuffer(image: Buffer): AsyncFailable<FileType> {
const filetypeResult: FileTypeResult | undefined = await fileTypeFromBuffer(
image,
);
const filetypeResult: FileTypeResult | undefined =
await fileTypeFromBuffer(image);
let mime: string | undefined;
if (filetypeResult === undefined) {

View File

@@ -1,5 +1,4 @@
import { Body, Controller, Post } from '@nestjs/common';
import { Throttle } from '@nestjs/throttler';
import {
ApiKeyCreateResponse,
ApiKeyDeleteRequest,
@@ -14,6 +13,7 @@ import {
import { Permission } from 'picsur-shared/dist/dto/permissions.enum';
import { ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { ApiKeyDbService } from '../../../collections/apikey-db/apikey-db.service';
import { EasyThrottle } from '../../../decorators/easy-throttle.decorator';
import {
HasPermission,
RequiredPermissions,
@@ -54,7 +54,7 @@ export class ApiKeysController {
@Post('create')
@Returns(ApiKeyCreateResponse)
@Throttle(10)
@EasyThrottle(10)
async createApiKey(
@ReqUserID() userID: string,
): Promise<ApiKeyCreateResponse> {

View File

@@ -1,5 +1,4 @@
import { Body, Controller, Get, Logger, Param, Post } from '@nestjs/common';
import { Throttle } from '@nestjs/throttler';
import {
GetPreferenceResponse,
MultiplePreferencesResponse,
@@ -8,6 +7,7 @@ import {
} from 'picsur-shared/dist/dto/api/pref.dto';
import { ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { SysPreferenceDbService } from '../../../collections/preference-db/sys-preference-db.service';
import { EasyThrottle } from '../../../decorators/easy-throttle.decorator';
import { RequiredPermissions } from '../../../decorators/permissions.decorator';
import { Returns } from '../../../decorators/returns.decorator';
import { Permission } from '../../../models/constants/permissions.const';
@@ -21,7 +21,7 @@ export class SysPrefController {
@Get()
@Returns(MultiplePreferencesResponse)
@Throttle(20)
@EasyThrottle(20)
async getAllSysPrefs(): Promise<MultiplePreferencesResponse> {
const prefs = ThrowIfFailed(await this.prefService.getAllPreferences());
@@ -41,7 +41,7 @@ export class SysPrefController {
@Post(':key')
@Returns(UpdatePreferenceResponse)
@Throttle(30)
@EasyThrottle(30)
async setSysPref(
@Param('key') key: string,
@Body() body: UpdatePreferenceRequest,

View File

@@ -1,5 +1,4 @@
import { Body, Controller, Get, Logger, Param, Post } from '@nestjs/common';
import { Throttle } from '@nestjs/throttler';
import {
GetPreferenceResponse,
MultiplePreferencesResponse,
@@ -8,6 +7,7 @@ import {
} from 'picsur-shared/dist/dto/api/pref.dto';
import { ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { UsrPreferenceDbService } from '../../../collections/preference-db/usr-preference-db.service';
import { EasyThrottle } from '../../../decorators/easy-throttle.decorator';
import { RequiredPermissions } from '../../../decorators/permissions.decorator';
import { ReqUserID } from '../../../decorators/request-user.decorator';
import { Returns } from '../../../decorators/returns.decorator';
@@ -22,7 +22,7 @@ export class UsrPrefController {
@Get()
@Returns(MultiplePreferencesResponse)
@Throttle(20)
@EasyThrottle(20)
async getAllUsrPrefs(
@ReqUserID() userid: string,
): Promise<MultiplePreferencesResponse> {
@@ -51,7 +51,7 @@ export class UsrPrefController {
@Post(':key')
@Returns(UpdatePreferenceResponse)
@Throttle(30)
@EasyThrottle(30)
async setUsrPref(
@Param('key') key: string,
@ReqUserID() userid: string,

View File

@@ -1,5 +1,4 @@
import { Body, Controller, Get, Logger, Post } from '@nestjs/common';
import { Throttle } from '@nestjs/throttler';
import {
RoleCreateRequest,
RoleCreateResponse,
@@ -12,9 +11,10 @@ import {
RoleUpdateResponse,
SpecialRolesResponse,
} from 'picsur-shared/dist/dto/api/roles.dto';
import { Fail, FT, ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { FT, Fail, ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { RoleDbService } from '../../../collections/role-db/role-db.service';
import { UserDbService } from '../../../collections/user-db/user-db.service';
import { EasyThrottle } from '../../../decorators/easy-throttle.decorator';
import { RequiredPermissions } from '../../../decorators/permissions.decorator';
import { Returns } from '../../../decorators/returns.decorator';
import { Permission } from '../../../models/constants/permissions.const';
@@ -57,7 +57,7 @@ export class RolesController {
@Post('update')
@Returns(RoleUpdateResponse)
@Throttle(20)
@EasyThrottle(20)
async updateRole(
@Body() body: RoleUpdateRequest,
): Promise<RoleUpdateResponse> {
@@ -75,7 +75,7 @@ export class RolesController {
@Post('create')
@Returns(RoleCreateResponse)
@Throttle(10)
@EasyThrottle(10)
async createRole(
@Body() role: RoleCreateRequest,
): Promise<RoleCreateResponse> {

View File

@@ -1,8 +1,8 @@
import { Controller, Logger, Post, Req, Res } from '@nestjs/common';
import { Throttle } from '@nestjs/throttler';
import type { FastifyReply, FastifyRequest } from 'fastify';
import { Fail, FT, ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { FT, Fail, ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { UsageConfigService } from '../../../config/late/usage.config.service';
import { EasyThrottle } from '../../../decorators/easy-throttle.decorator';
import { NoPermissions } from '../../../decorators/permissions.decorator';
import { ReturnsAnything } from '../../../decorators/returns.decorator';
@@ -15,7 +15,7 @@ export class UsageController {
@Post(['report', 'report/*'])
@ReturnsAnything()
@Throttle(120)
@EasyThrottle(120)
async deleteRole(
@Req() req: FastifyRequest,
@Res({

View File

@@ -1,5 +1,4 @@
import { Body, Controller, Get, Logger, Post } from '@nestjs/common';
import { Throttle } from '@nestjs/throttler';
import {
GetSpecialUsersResponse,
UserCreateRequest,
@@ -15,6 +14,7 @@ import {
} from 'picsur-shared/dist/dto/api/user-manage.dto';
import { ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { UserDbService } from '../../../collections/user-db/user-db.service';
import { EasyThrottle } from '../../../decorators/easy-throttle.decorator';
import { RequiredPermissions } from '../../../decorators/permissions.decorator';
import { Returns } from '../../../decorators/returns.decorator';
import { Permission } from '../../../models/constants/permissions.const';
@@ -47,7 +47,7 @@ export class UserAdminController {
@Post('create')
@Returns(UserCreateResponse)
@Throttle(10)
@EasyThrottle(10)
async register(
@Body() create: UserCreateRequest,
): Promise<UserCreateResponse> {
@@ -80,7 +80,7 @@ export class UserAdminController {
@Post('update')
@Returns(UserUpdateResponse)
@Throttle(20)
@EasyThrottle(20)
async setPermissions(
@Body() body: UserUpdateRequest,
): Promise<UserUpdateResponse> {

View File

@@ -1,5 +1,4 @@
import { Body, Controller, Get, Logger, Post } from '@nestjs/common';
import { Throttle } from '@nestjs/throttler';
import {
UserCheckNameRequest,
UserCheckNameResponse,
@@ -12,6 +11,7 @@ import {
import type { EUser } from 'picsur-shared/dist/entities/user.entity';
import { ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { UserDbService } from '../../../collections/user-db/user-db.service';
import { EasyThrottle } from '../../../decorators/easy-throttle.decorator';
import {
NoPermissions,
RequiredPermissions,
@@ -35,7 +35,7 @@ export class UserController {
@Post('login')
@Returns(UserLoginResponse)
@UseLocalAuth(Permission.UserLogin)
@Throttle(30, 300)
@EasyThrottle(30, 300)
async login(@ReqUser() user: EUser): Promise<UserLoginResponse> {
const jwt_token = ThrowIfFailed(await this.authService.createToken(user));
@@ -45,7 +45,7 @@ export class UserController {
@Post('register')
@Returns(UserRegisterResponse)
@RequiredPermissions(Permission.UserRegister)
@Throttle(5, 300)
@EasyThrottle(5, 300)
async register(
@Body() register: UserRegisterRequest,
): Promise<UserRegisterResponse> {
@@ -59,7 +59,7 @@ export class UserController {
@Post('checkname')
@Returns(UserCheckNameResponse)
@RequiredPermissions(Permission.UserRegister)
@Throttle(20)
@EasyThrottle(20)
async checkName(
@Body() checkName: UserCheckNameRequest,
): Promise<UserCheckNameResponse> {
@@ -71,7 +71,7 @@ export class UserController {
@Get('me')
@Returns(UserMeResponse)
@RequiredPermissions(Permission.UserKeepLogin)
@Throttle(10)
@EasyThrottle(10)
async me(@ReqUserID() userid: string): Promise<UserMeResponse> {
const backenduser = ThrowIfFailed(await this.usersService.findOne(userid));
@@ -86,7 +86,7 @@ export class UserController {
@Get('me/permissions')
@Returns(UserMePermissionsResponse)
@NoPermissions()
@Throttle(20)
@EasyThrottle(20)
async refresh(
@ReqUserID() userid: string,
): Promise<UserMePermissionsResponse> {

View File

@@ -7,7 +7,6 @@ import {
Post,
Res,
} from '@nestjs/common';
import { Throttle } from '@nestjs/throttler';
import type { FastifyReply } from 'fastify';
import {
ImageDeleteRequest,
@@ -22,11 +21,12 @@ import {
} from 'picsur-shared/dist/dto/api/image-manage.dto';
import { Permission } from 'picsur-shared/dist/dto/permissions.enum';
import {
Fail,
FT,
Fail,
HasFailed,
ThrowIfFailed,
} from 'picsur-shared/dist/types/failable';
import { EasyThrottle } from '../../decorators/easy-throttle.decorator';
import { PostFiles } from '../../decorators/multipart/multipart.decorator';
import type { FileIterator } from '../../decorators/multipart/postfiles.pipe';
import {
@@ -37,6 +37,7 @@ import { ReqUserID } from '../../decorators/request-user.decorator';
import { Returns } from '../../decorators/returns.decorator';
import { ImageManagerService } from '../../managers/image/image.service';
import { GetNextAsync } from '../../util/iterator';
@Controller('api/image')
@RequiredPermissions(Permission.ImageUpload)
export class ImageManageController {
@@ -46,7 +47,7 @@ export class ImageManageController {
@Post('upload')
@Returns(ImageUploadResponse)
@Throttle(20)
@EasyThrottle(20)
async uploadImage(
@PostFiles(1) multipart: FileIterator,
@ReqUserID() userid: string,

View File

@@ -21,9 +21,6 @@ export const HelmetOptions: FastifyHelmetOptions = {
// Destroy reference to global object on new page
crossOriginOpenerPolicy: true,
crossOriginResourcePolicy: true,
// Dont fully understand the purpose of this
// But pretty sure we dont need it
expectCt: false,
// Do not send referrer header
referrerPolicy: true,
// Ensure browser doesnt connect with HTTP

View File

@@ -124,7 +124,7 @@ async function bmpSharpOut(sharpImage: Sharp): Promise<SharpResult> {
const encoded = BMPencode(raw.data, {
width: raw.info.width,
height: raw.info.height,
channels: raw.info.channels,
channels: raw.info.channels as 3 | 4,
});
return {
@@ -141,7 +141,7 @@ async function qoiSharpOut(sharpImage: Sharp): Promise<SharpResult> {
const encoded = QOIencode(raw.data, {
width: raw.info.width,
height: raw.info.height,
channels: raw.info.channels,
channels: raw.info.channels as 3 | 4,
});
return {

View File

@@ -43,7 +43,8 @@
"ngx-auto-unsubscribe-decorator",
"moment",
"platform",
"form-data"
"form-data",
"ms"
],
"optimization": true,
"webWorkerTsConfig": "tsconfig.worker.json",

View File

@@ -14,40 +14,40 @@
"purge": "rm -rf dist && rm -rf node_modules && rm -rf .angular"
},
"devDependencies": {
"@angular-builders/custom-webpack": "^16.0.0",
"@angular-devkit/build-angular": "^16.1.0",
"@angular/animations": "^16.1.1",
"@angular/cdk": "^16.1.1",
"@angular/cli": "^16.1.0",
"@angular/common": "^16.1.1",
"@angular/compiler": "^16.1.1",
"@angular/compiler-cli": "^16.1.1",
"@angular/core": "^16.1.1",
"@angular/forms": "^16.1.1",
"@angular/material": "^16.1.1",
"@angular/platform-browser": "^16.1.1",
"@angular/platform-browser-dynamic": "^16.1.1",
"@angular/router": "^16.1.1",
"@babel/cli": "^7.22.5",
"@babel/core": "^7.22.5",
"@babel/preset-env": "^7.22.5",
"@fontsource/roboto": "^5.0.3",
"@ng-web-apis/common": "^2.1.0",
"@ng-web-apis/resize-observer": "^2.0.0",
"@angular-builders/custom-webpack": "^17.0.0",
"@angular-devkit/build-angular": "^17.0.3",
"@angular/animations": "^17.0.4",
"@angular/cdk": "^17.0.1",
"@angular/cli": "^17.0.3",
"@angular/common": "^17.0.4",
"@angular/compiler": "^17.0.4",
"@angular/compiler-cli": "^17.0.4",
"@angular/core": "^17.0.4",
"@angular/forms": "^17.0.4",
"@angular/material": "^17.0.1",
"@angular/platform-browser": "^17.0.4",
"@angular/platform-browser-dynamic": "^17.0.4",
"@angular/router": "^17.0.4",
"@babel/cli": "^7.23.4",
"@babel/core": "^7.23.3",
"@babel/preset-env": "^7.23.3",
"@fontsource/roboto": "^5.0.8",
"@ng-web-apis/common": "^3.0.6",
"@ng-web-apis/resize-observer": "^3.0.6",
"@ngui/common": "^1.0.0",
"@popperjs/core": "^2.11.8",
"@types/ackee-tracker": "^5.0.2",
"@types/node": "^20.3.1",
"@types/resize-observer-browser": "^0.1.7",
"@types/validator": "^13.7.17",
"@types/ackee-tracker": "^5.0.4",
"@types/node": "^20.10.0",
"@types/resize-observer-browser": "^0.1.11",
"@types/validator": "^13.11.7",
"ackee-tracker": "^5.1.0",
"axios": "^1.4.0",
"babel-loader": "^9.1.2",
"bootstrap": "^5.3.0",
"browserslist": "^4.21.8",
"caniuse-lite": "^1.0.30001503",
"fuse.js": "^6.6.2",
"material-icons": "^1.13.8",
"axios": "^1.6.2",
"babel-loader": "^9.1.3",
"bootstrap": "^5.3.2",
"browserslist": "^4.22.1",
"caniuse-lite": "^1.0.30001565",
"fuse.js": "^7.0.0",
"material-icons": "^1.13.12",
"moment": "^2.29.4",
"ng-mat-select-infinite-scroll": "^4.0.0",
"ngx-auto-unsubscribe-decorator": "^1.1.0",
@@ -56,11 +56,11 @@
"picsur-shared": "*",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1",
"tslib": "^2.5.3",
"typescript": "^5.1.3",
"webpack-bundle-analyzer": "^4.9.0",
"zod": "^3.21.4",
"zone.js": "^0.13.1"
"tslib": "^2.6.2",
"typescript": "^5.3.2",
"webpack-bundle-analyzer": "^4.10.1",
"zod": "^3.22.4",
"zone.js": "^0.14.2"
},
"dependencies": {
"@leteu/jwt-decoder": "^1.0.4"

View File

@@ -52,8 +52,10 @@ mat-toolbar {
/* Make sure the toolbar will stay on top of the content as it scrolls past. */
z-index: 2;
box-shadow: 0px 2px 5px -3px rgba(0, 0, 0, 0.2),
0px 5px 8px 0px rgba(0, 0, 0, 0.14), 0px 1px 14px 0px rgba(0, 0, 0, 0.12);
box-shadow:
0px 2px 5px -3px rgba(0, 0, 0, 0.2),
0px 5px 8px 0px rgba(0, 0, 0, 0.14),
0px 1px 14px 0px rgba(0, 0, 0, 0.12);
}
.loading-bar {

View File

@@ -80,12 +80,12 @@ export class PrefOptionComponent implements OnInit {
this.pref.type === 'string'
? `Updated ${this.name}`
: this.pref.type === 'number'
? `Updated ${this.name}`
: this.pref.type === 'boolean'
? value
? `Enabled ${this.name}`
: `Disabled ${this.name}`
: '';
? `Updated ${this.name}`
: this.pref.type === 'boolean'
? value
? `Enabled ${this.name}`
: `Disabled ${this.name}`
: '';
this.errorService.success(message);
} else {
this.errorService.showFailure(result, this.logger);

View File

@@ -29,18 +29,18 @@ export class InfoService {
return this.infoSubject.value;
}
private infoSubject: BehaviorSubject<ServerInfo>;
constructor(
@Inject(LOCATION) private readonly location: Location,
private readonly api: ApiService,
private readonly infoStorage: InfoStorageService,
) {
this.updateInfo().catch((e) => this.logger.warn(e));
this.infoSubject = new BehaviorSubject<ServerInfo>(
this.infoStorage?.get() ?? new ServerInfo(),
);
}
private infoSubject = new BehaviorSubject<ServerInfo>(
this.infoStorage?.get() ?? new ServerInfo(),
);
public async getLoadedSnapshot(): Promise<ServerInfo> {
if (this.isLoaded()) {
return this.snapshot;

View File

@@ -60,16 +60,16 @@ export class BootstrapService {
const size = xxxl
? BSScreenSize.xxxl
: xxl
? BSScreenSize.xxl
: xl
? BSScreenSize.xl
: lg
? BSScreenSize.lg
: md
? BSScreenSize.md
: sm
? BSScreenSize.sm
: BSScreenSize.xs;
? BSScreenSize.xxl
: xl
? BSScreenSize.xl
: lg
? BSScreenSize.lg
: md
? BSScreenSize.md
: sm
? BSScreenSize.sm
: BSScreenSize.xs;
this.screenSizeSubject.next(size);
});

View File

@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />

View File

@@ -23,22 +23,22 @@
"terser": ">=5.14.2",
"typeorm": ">=0.3.9",
"jsonwebtoken": ">=9.0.0",
"typescript": "~4.9.5",
"typescript": "~5.2.0",
"webpack": ">=5.76.0",
"fastify-static": "npm:@fastify/static@*",
"fastify-formbody": "npm:@fastify/formbody@*",
"minimist": "npm:minimist-lite@*"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.59.11",
"@typescript-eslint/parser": "^5.59.11",
"eslint": "^8.42.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^4.2.1",
"@typescript-eslint/eslint-plugin": "^6.13.1",
"@typescript-eslint/parser": "^6.13.1",
"eslint": "^8.54.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-require-extensions": "^0.1.3",
"ms": "3.0.0-canary.1",
"prettier": "^2.8.8",
"prettier-plugin-sh": "^0.12.8"
"ms": "2.1.3",
"prettier": "^3.1.0",
"prettier-plugin-sh": "^0.13.1"
},
"packageManager": "yarn@3.2.2"
}

View File

@@ -14,12 +14,13 @@
},
"dependencies": {
"ms": "2.1.3",
"zod": "^3.21.4"
"zod": "^3.22.4"
},
"devDependencies": {
"@types/node": "^20.3.1",
"@types/ms": "^0.7.34",
"@types/node": "^20.10.0",
"tsc-watch": "^6.0.4",
"typescript": "^5.1.3"
"typescript": "^5.3.2"
},
"scripts": {
"clean": "rm -rf ./dist",

View File

@@ -2,24 +2,24 @@ import { z } from 'zod';
import { EImageSchema } from '../../entities/image.entity';
import { EUserSchema } from '../../entities/user.entity';
import { createZodDto } from '../../util/create-zod-dto';
import { ParseBool, ParseInt } from '../../util/parse-simple';
import { ParseBoolZ, ParseIntZ } from '../../util/parse-simple';
import { ImageEntryVariant } from '../image-entry-variant.enum';
export const ImageRequestParamsSchema = z
.object({
height: z.preprocess(ParseInt, z.number().int().min(1).max(32767)),
width: z.preprocess(ParseInt, z.number().int().min(1).max(32767)),
height: z.preprocess(ParseIntZ, z.number().int().min(1).max(32767)),
width: z.preprocess(ParseIntZ, z.number().int().min(1).max(32767)),
rotate: z.preprocess(
ParseInt,
ParseIntZ,
z.number().int().multipleOf(90).min(0).max(360),
),
flipx: z.preprocess(ParseBool, z.boolean()),
flipy: z.preprocess(ParseBool, z.boolean()),
greyscale: z.preprocess(ParseBool, z.boolean()),
noalpha: z.preprocess(ParseBool, z.boolean()),
negative: z.preprocess(ParseBool, z.boolean()),
shrinkonly: z.preprocess(ParseBool, z.boolean()),
quality: z.preprocess(ParseInt, z.number().int().min(1).max(100)),
flipx: z.preprocess(ParseBoolZ, z.boolean()),
flipy: z.preprocess(ParseBoolZ, z.boolean()),
greyscale: z.preprocess(ParseBoolZ, z.boolean()),
noalpha: z.preprocess(ParseBoolZ, z.boolean()),
negative: z.preprocess(ParseBoolZ, z.boolean()),
shrinkonly: z.preprocess(ParseBoolZ, z.boolean()),
quality: z.preprocess(ParseIntZ, z.number().int().min(1).max(100)),
})
.partial();

View File

@@ -10,6 +10,10 @@ export const ParseBool = <T extends boolean | null = null>(
return fallback === undefined ? (null as T) : fallback;
};
export const ParseBoolZ = (value: unknown): boolean | null => {
return ParseBool(value, null);
};
export const ParseInt = <T extends number | null = null>(
value: unknown,
fallback?: T,
@@ -23,8 +27,12 @@ export const ParseInt = <T extends number | null = null>(
return fallback === undefined
? (null as T)
: fallback === null
? fallback
: Math.round(fallback);
? fallback
: Math.round(fallback);
};
export const ParseIntZ = (value: unknown): number | null => {
return ParseInt(value, null);
};
export const ParseString = <T extends string | null = null>(
@@ -36,3 +44,7 @@ export const ParseString = <T extends string | null = null>(
if (typeof value === 'number') return value.toString();
return fallback === undefined ? (null as T) : fallback;
};
export const ParseStringZ = (value: unknown): string | null => {
return ParseString(value, null);
};

8463
yarn.lock

File diff suppressed because it is too large Load Diff