Change some typescript compilation options and fix eslint

This commit is contained in:
Caramel 2023-06-15 13:09:23 +02:00
parent 3b6244461e
commit b8db72bac4
No known key found for this signature in database
175 changed files with 627 additions and 540 deletions

View File

@ -1,3 +1,22 @@
module.exports = { module.exports = {
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
env: {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.cjs', 'dist', '*.exclude.*'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
},
root: true, root: true,
}; };

View File

@ -1,27 +1,9 @@
module.exports = { module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: { parserOptions: {
project: './tsconfig.json', project: './tsconfig.json',
tsconfigRootDir: __dirname, tsconfigRootDir: __dirname,
sourceType: 'module', sourceType: 'module',
}, },
plugins: ['@typescript-eslint/eslint-plugin', 'require-extensions'], extends: ['../.eslintrc.cjs'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
'plugin:require-extensions/recommended',
],
root: false, root: false,
env: {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.cjs'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
}; };

View File

@ -19,7 +19,6 @@
"migrate": "PICSUR_PRODUCTION=\"true\" yarn typeorm migration:generate -d ./src/datasource.ts", "migrate": "PICSUR_PRODUCTION=\"true\" yarn typeorm migration:generate -d ./src/datasource.ts",
"format": "prettier --write \"src/**/*.ts\"", "format": "prettier --write \"src/**/*.ts\"",
"clean": "rimraf dist", "clean": "rimraf dist",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"purge": "rm -rf dist && rm -rf node_modules" "purge": "rm -rf dist && rm -rf node_modules"
}, },
"dependencies": { "dependencies": {
@ -40,10 +39,9 @@
"bcrypt": "^5.1.0", "bcrypt": "^5.1.0",
"bmp-img": "^1.2.1", "bmp-img": "^1.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"eslint-plugin-require-extensions": "^0.1.3",
"file-type": "^18.5.0", "file-type": "^18.5.0",
"is-docker": "^3.0.0", "is-docker": "^3.0.0",
"ms": "^2.1.3", "ms": "3.0.0-canary.1",
"node-fetch": "^3.3.1", "node-fetch": "^3.3.1",
"p-timeout": "^6.1.1", "p-timeout": "^6.1.1",
"passport": "^0.6.0", "passport": "^0.6.0",
@ -77,11 +75,6 @@
"@types/passport-strategy": "^0.2.35", "@types/passport-strategy": "^0.2.35",
"@types/sharp": "^0.32.0", "@types/sharp": "^0.32.0",
"@types/supertest": "^2.0.12", "@types/supertest": "^2.0.12",
"@typescript-eslint/eslint-plugin": "^5.59.9",
"@typescript-eslint/parser": "^5.59.9",
"eslint": "^8.42.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^4.2.1",
"prettier": "^2.8.8", "prettier": "^2.8.8",
"source-map-support": "^0.5.21", "source-map-support": "^0.5.21",
"ts-loader": "^9.4.3", "ts-loader": "^9.4.3",

View File

@ -30,7 +30,7 @@ const imageCorsConfig = cors({
const imageCorsOverride = ( const imageCorsOverride = (
req: IncomingMessage, req: IncomingMessage,
res: ServerResponse, res: ServerResponse,
next: Function, next: () => void,
) => { ) => {
res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin'); res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');

View File

@ -1,6 +1,11 @@
import { Injectable, Logger } from '@nestjs/common'; import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { AsyncFailable, Fail, FT, HasFailed } from 'picsur-shared/dist/types'; import {
AsyncFailable,
Fail,
FT,
HasFailed,
} from 'picsur-shared/dist/types/failable';
import { FindResult } from 'picsur-shared/dist/types/find-result'; import { FindResult } from 'picsur-shared/dist/types/find-result';
import { generateRandomString } from 'picsur-shared/dist/util/random'; import { generateRandomString } from 'picsur-shared/dist/util/random';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';

View File

@ -1,6 +1,6 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { AsyncFailable, Fail, FT } from 'picsur-shared/dist/types'; import { AsyncFailable, Fail, FT } from 'picsur-shared/dist/types/failable';
import { FindResult } from 'picsur-shared/dist/types/find-result'; import { FindResult } from 'picsur-shared/dist/types/find-result';
import { generateRandomString } from 'picsur-shared/dist/util/random'; import { generateRandomString } from 'picsur-shared/dist/util/random';
import { In, LessThan, Repository } from 'typeorm'; import { In, LessThan, Repository } from 'typeorm';

View File

@ -1,7 +1,12 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { ImageEntryVariant } from 'picsur-shared/dist/dto/image-entry-variant.enum'; import { ImageEntryVariant } from 'picsur-shared/dist/dto/image-entry-variant.enum';
import { AsyncFailable, Fail, FT, HasFailed } from 'picsur-shared/dist/types'; import {
AsyncFailable,
Fail,
FT,
HasFailed,
} from 'picsur-shared/dist/types/failable';
import { LessThan, Repository } from 'typeorm'; import { LessThan, Repository } from 'typeorm';
import { EImageDerivativeBackend } from '../../database/entities/images/image-derivative.entity'; import { EImageDerivativeBackend } from '../../database/entities/images/image-derivative.entity';
import { EImageFileBackend } from '../../database/entities/images/image-file.entity'; import { EImageFileBackend } from '../../database/entities/images/image-file.entity';

View File

@ -10,7 +10,7 @@ import {
Failable, Failable,
FT, FT,
HasFailed, HasFailed,
} from 'picsur-shared/dist/types'; } from 'picsur-shared/dist/types/failable';
type Enum = Record<string, string>; type Enum = Record<string, string>;
type EnumValue<E> = E[keyof E]; type EnumValue<E> = E[keyof E];

View File

@ -11,7 +11,12 @@ import {
SysPreferenceValidators, SysPreferenceValidators,
SysPreferenceValueTypes, SysPreferenceValueTypes,
} from 'picsur-shared/dist/dto/sys-preferences.enum'; } from 'picsur-shared/dist/dto/sys-preferences.enum';
import { AsyncFailable, Fail, FT, HasFailed } from 'picsur-shared/dist/types'; import {
AsyncFailable,
Fail,
FT,
HasFailed,
} from 'picsur-shared/dist/types/failable';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { import {
ESysPreferenceBackend, ESysPreferenceBackend,
@ -37,7 +42,7 @@ export class SysPreferenceDbService {
value: PrefValueType, value: PrefValueType,
): AsyncFailable<DecodedSysPref> { ): AsyncFailable<DecodedSysPref> {
// Validate // Validate
let sysPreference = await this.encodeSysPref(key, value); const sysPreference = await this.encodeSysPref(key, value);
if (HasFailed(sysPreference)) return sysPreference; if (HasFailed(sysPreference)) return sysPreference;
// Set // Set
@ -60,7 +65,7 @@ export class SysPreferenceDbService {
public async getPreference(key: string): AsyncFailable<DecodedSysPref> { public async getPreference(key: string): AsyncFailable<DecodedSysPref> {
// Validate // Validate
let validatedKey = this.prefCommon.validatePrefKey(key, SysPreference); const validatedKey = this.prefCommon.validatePrefKey(key, SysPreference);
if (HasFailed(validatedKey)) return validatedKey; if (HasFailed(validatedKey)) return validatedKey;
// See the comment in 'mutex-fallback.ts' for why we are using a mutex here // See the comment in 'mutex-fallback.ts' for why we are using a mutex here
@ -112,7 +117,7 @@ export class SysPreferenceDbService {
key: string, key: string,
type: PrefValueTypeStrings, type: PrefValueTypeStrings,
): AsyncFailable<PrefValueType> { ): AsyncFailable<PrefValueType> {
let pref = await this.getPreference(key); const pref = await this.getPreference(key);
if (HasFailed(pref)) return pref; if (HasFailed(pref)) return pref;
if (pref.type !== type) if (pref.type !== type)
return Fail(FT.UsrValidation, 'Invalid preference type'); return Fail(FT.UsrValidation, 'Invalid preference type');
@ -122,7 +127,7 @@ export class SysPreferenceDbService {
public async getAllPreferences(): AsyncFailable<DecodedSysPref[]> { public async getAllPreferences(): AsyncFailable<DecodedSysPref[]> {
// TODO: We are fetching each value invidually, we should fetch all at once // TODO: We are fetching each value invidually, we should fetch all at once
let internalSysPrefs = await Promise.all( const internalSysPrefs = await Promise.all(
SysPreferenceList.map((key) => this.getPreference(key)), SysPreferenceList.map((key) => this.getPreference(key)),
); );
if (internalSysPrefs.some((pref) => HasFailed(pref))) { if (internalSysPrefs.some((pref) => HasFailed(pref))) {
@ -158,7 +163,7 @@ export class SysPreferenceDbService {
return Fail(FT.UsrValidation, undefined, valueValidated.error); return Fail(FT.UsrValidation, undefined, valueValidated.error);
} }
let verifySysPreference = new ESysPreferenceBackend(); const verifySysPreference = new ESysPreferenceBackend();
verifySysPreference.key = validated.key; verifySysPreference.key = validated.key;
verifySysPreference.value = validated.value; verifySysPreference.value = validated.value;

View File

@ -11,7 +11,12 @@ import {
UsrPreferenceValidators, UsrPreferenceValidators,
UsrPreferenceValueTypes, UsrPreferenceValueTypes,
} from 'picsur-shared/dist/dto/usr-preferences.enum'; } from 'picsur-shared/dist/dto/usr-preferences.enum';
import { AsyncFailable, Fail, FT, HasFailed } from 'picsur-shared/dist/types'; import {
AsyncFailable,
Fail,
FT,
HasFailed,
} from 'picsur-shared/dist/types/failable';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { import {
EUsrPreferenceBackend, EUsrPreferenceBackend,
@ -38,7 +43,7 @@ export class UsrPreferenceDbService {
value: PrefValueType, value: PrefValueType,
): AsyncFailable<DecodedUsrPref> { ): AsyncFailable<DecodedUsrPref> {
// Validate // Validate
let usrPreference = await this.encodeUsrPref(userid, key, value); const usrPreference = await this.encodeUsrPref(userid, key, value);
if (HasFailed(usrPreference)) return usrPreference; if (HasFailed(usrPreference)) return usrPreference;
// Set // Set
@ -66,7 +71,7 @@ export class UsrPreferenceDbService {
key: string, key: string,
): AsyncFailable<DecodedUsrPref> { ): AsyncFailable<DecodedUsrPref> {
// Validate // Validate
let validatedKey = this.prefCommon.validatePrefKey(key, UsrPreference); const validatedKey = this.prefCommon.validatePrefKey(key, UsrPreference);
if (HasFailed(validatedKey)) return validatedKey; if (HasFailed(validatedKey)) return validatedKey;
// See the comment in 'mutex-fallback.ts' for why we are using a mutex here // See the comment in 'mutex-fallback.ts' for why we are using a mutex here
@ -145,7 +150,7 @@ export class UsrPreferenceDbService {
key: string, key: string,
type: PrefValueTypeStrings, type: PrefValueTypeStrings,
): AsyncFailable<PrefValueType> { ): AsyncFailable<PrefValueType> {
let pref = await this.getPreference(userid, key); const pref = await this.getPreference(userid, key);
if (HasFailed(pref)) return pref; if (HasFailed(pref)) return pref;
if (pref.type !== type) if (pref.type !== type)
return Fail(FT.UsrValidation, 'Invalid preference type'); return Fail(FT.UsrValidation, 'Invalid preference type');
@ -157,7 +162,7 @@ export class UsrPreferenceDbService {
userid: string, userid: string,
): AsyncFailable<DecodedUsrPref[]> { ): AsyncFailable<DecodedUsrPref[]> {
// TODO: We are fetching each value invidually, we should fetch all at once // TODO: We are fetching each value invidually, we should fetch all at once
let internalSysPrefs = await Promise.all( const internalSysPrefs = await Promise.all(
UsrPreferenceList.map((key) => this.getPreference(userid, key)), UsrPreferenceList.map((key) => this.getPreference(userid, key)),
); );
if (internalSysPrefs.some((pref) => HasFailed(pref))) { if (internalSysPrefs.some((pref) => HasFailed(pref))) {
@ -199,7 +204,7 @@ export class UsrPreferenceDbService {
return Fail(FT.UsrValidation, undefined, valueValidated.error); return Fail(FT.UsrValidation, undefined, valueValidated.error);
} }
let verifySysPreference = new EUsrPreferenceBackend(); const verifySysPreference = new EUsrPreferenceBackend();
verifySysPreference.key = validated.key; verifySysPreference.key = validated.key;
verifySysPreference.value = validated.value; verifySysPreference.value = validated.value;
verifySysPreference.user_id = userid; verifySysPreference.user_id = userid;

View File

@ -1,6 +1,6 @@
import { Logger, Module, OnModuleInit } from '@nestjs/common'; import { Logger, Module, OnModuleInit } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { HasFailed } from 'picsur-shared/dist/types'; import { HasFailed } from 'picsur-shared/dist/types/failable';
import { EarlyConfigModule } from '../../config/early/early-config.module'; import { EarlyConfigModule } from '../../config/early/early-config.module';
import { HostConfigService } from '../../config/early/host.config.service'; import { HostConfigService } from '../../config/early/host.config.service';
import { ERoleBackend } from '../../database/entities/users/role.entity'; import { ERoleBackend } from '../../database/entities/users/role.entity';

View File

@ -7,7 +7,7 @@ import {
FT, FT,
HasFailed, HasFailed,
HasSuccess, HasSuccess,
} from 'picsur-shared/dist/types'; } from 'picsur-shared/dist/types/failable';
import { makeUnique } from 'picsur-shared/dist/util/unique'; import { makeUnique } from 'picsur-shared/dist/util/unique';
import { In, Repository } from 'typeorm'; import { In, Repository } from 'typeorm';
import { ERoleBackend } from '../../database/entities/users/role.entity'; import { ERoleBackend } from '../../database/entities/users/role.entity';
@ -33,7 +33,7 @@ export class RoleDbService {
if (await this.exists(name)) if (await this.exists(name))
return Fail(FT.Conflict, 'Role already exists'); return Fail(FT.Conflict, 'Role already exists');
let role = new ERoleBackend(); const role = new ERoleBackend();
role.name = name; role.name = name;
role.permissions = permissions; role.permissions = permissions;
@ -105,7 +105,7 @@ export class RoleDbService {
role: string | ERoleBackend, role: string | ERoleBackend,
permissions: Permissions, permissions: Permissions,
// Extra bypass for internal use // Extra bypass for internal use
allowImmutable: boolean = false, allowImmutable = false,
): AsyncFailable<ERoleBackend> { ): AsyncFailable<ERoleBackend> {
const roleToModify = await this.resolve(role); const roleToModify = await this.resolve(role);
if (HasFailed(roleToModify)) return roleToModify; if (HasFailed(roleToModify)) return roleToModify;
@ -166,7 +166,7 @@ export class RoleDbService {
return HasSuccess(await this.findOne(name)); return HasSuccess(await this.findOne(name));
} }
public async nukeSystemRoles(IAmSure: boolean = false): AsyncFailable<true> { public async nukeSystemRoles(IAmSure = false): AsyncFailable<true> {
if (!IAmSure) if (!IAmSure)
return Fail( return Fail(
FT.SysValidation, FT.SysValidation,

View File

@ -1,6 +1,6 @@
import { Injectable, Logger } from '@nestjs/common'; import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { AsyncFailable, Fail, FT } from 'picsur-shared/dist/types'; import { AsyncFailable, Fail, FT } from 'picsur-shared/dist/types/failable';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { ESystemStateBackend } from '../../database/entities/system/system-state.entity'; import { ESystemStateBackend } from '../../database/entities/system/system-state.entity';

View File

@ -1,6 +1,6 @@
import { Logger, Module, OnModuleInit } from '@nestjs/common'; import { Logger, Module, OnModuleInit } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { HasFailed } from 'picsur-shared/dist/types'; import { HasFailed } from 'picsur-shared/dist/types/failable';
import { generateRandomString } from 'picsur-shared/dist/util/random'; import { generateRandomString } from 'picsur-shared/dist/util/random';
import { AuthConfigService } from '../../config/early/auth.config.service'; import { AuthConfigService } from '../../config/early/auth.config.service';
import { EarlyConfigModule } from '../../config/early/early-config.module'; import { EarlyConfigModule } from '../../config/early/early-config.module';

View File

@ -8,7 +8,7 @@ import {
FT, FT,
HasFailed, HasFailed,
HasSuccess, HasSuccess,
} from 'picsur-shared/dist/types'; } from 'picsur-shared/dist/types/failable';
import { FindResult } from 'picsur-shared/dist/types/find-result'; import { FindResult } from 'picsur-shared/dist/types/find-result';
import { makeUnique } from 'picsur-shared/dist/util/unique'; import { makeUnique } from 'picsur-shared/dist/util/unique';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
@ -53,7 +53,7 @@ export class UserDbService {
const strength = await this.getBCryptStrength(); const strength = await this.getBCryptStrength();
const hashedPassword = await bcrypt.hash(password, strength); const hashedPassword = await bcrypt.hash(password, strength);
let user = new EUserBackend(); const user = new EUserBackend();
user.username = username; user.username = username;
user.hashed_password = hashedPassword; user.hashed_password = hashedPassword;
if (byPassRoleCheck) { if (byPassRoleCheck) {
@ -208,7 +208,7 @@ export class UserDbService {
username: string, username: string,
// Also fetch fields that aren't normally sent to the client // Also fetch fields that aren't normally sent to the client
// (e.g. hashed password) // (e.g. hashed password)
getPrivate: boolean = false, getPrivate = false,
): AsyncFailable<EUserBackend> { ): AsyncFailable<EUserBackend> {
try { try {
const found = await this.usersRepository.findOne({ const found = await this.usersRepository.findOne({

View File

@ -2,8 +2,8 @@ import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config'; import { ConfigService } from '@nestjs/config';
import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from '@nestjs/typeorm'; import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from '@nestjs/typeorm';
import { ParseInt, ParseString } from 'picsur-shared/dist/util/parse-simple'; import { ParseInt, ParseString } from 'picsur-shared/dist/util/parse-simple';
import { EntityList } from '../../database/entities'; import { EntityList } from '../../database/entities/index';
import { MigrationList } from '../../database/migrations'; import { MigrationList } from '../../database/migrations/index';
import { DefaultName, EnvPrefix } from '../config.static'; import { DefaultName, EnvPrefix } from '../config.static';
import { HostConfigService } from './host.config.service'; import { HostConfigService } from './host.config.service';
@ -48,10 +48,10 @@ export class TypeOrmConfigService implements TypeOrmOptionsFactory {
return varOptions; return varOptions;
} }
public createTypeOrmOptions(connectionName?: string) { public createTypeOrmOptions() {
const varOptions = this.getTypeOrmServerOptions(); const varOptions = this.getTypeOrmServerOptions();
return { return {
type: 'postgres' as 'postgres', type: 'postgres' as const,
synchronize: !this.hostService.isProduction(), synchronize: !this.hostService.isProduction(),
migrationsRun: true, migrationsRun: true,

View File

@ -1,6 +1,6 @@
import { Injectable, Logger } from '@nestjs/common'; import { Injectable, Logger } from '@nestjs/common';
import { SysPreference } from 'picsur-shared/dist/dto/sys-preferences.enum'; import { SysPreference } from 'picsur-shared/dist/dto/sys-preferences.enum';
import { HasFailed } from 'picsur-shared/dist/types'; import { HasFailed } from 'picsur-shared/dist/types/failable';
import { SysPreferenceDbService } from '../../collections/preference-db/sys-preference-db.service'; import { SysPreferenceDbService } from '../../collections/preference-db/sys-preference-db.service';
@Injectable() @Injectable()

View File

@ -1,7 +1,7 @@
import { FactoryProvider, Injectable, Logger } from '@nestjs/common'; import { FactoryProvider, Injectable, Logger } from '@nestjs/common';
import { JwtModuleOptions, JwtOptionsFactory } from '@nestjs/jwt'; import { JwtModuleOptions, JwtOptionsFactory } from '@nestjs/jwt';
import ms from 'ms'; import ms from 'ms';
import { ThrowIfFailed } from 'picsur-shared/dist/types'; import { ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { SysPreferenceDbService } from '../../collections/preference-db/sys-preference-db.service'; import { SysPreferenceDbService } from '../../collections/preference-db/sys-preference-db.service';
@Injectable() @Injectable()

View File

@ -1,6 +1,11 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { SysPreference } from 'picsur-shared/dist/dto/sys-preferences.enum'; import { SysPreference } from 'picsur-shared/dist/dto/sys-preferences.enum';
import { AsyncFailable, Fail, FT, HasFailed } from 'picsur-shared/dist/types'; import {
AsyncFailable,
Fail,
FT,
HasFailed,
} from 'picsur-shared/dist/types/failable';
import { URLRegex, UUIDRegex } from 'picsur-shared/dist/util/common-regex'; import { URLRegex, UUIDRegex } from 'picsur-shared/dist/util/common-regex';
import { SysPreferenceDbService } from '../../collections/preference-db/sys-preference-db.service'; import { SysPreferenceDbService } from '../../collections/preference-db/sys-preference-db.service';
import { ReportInterval, ReportUrl } from '../config.static'; import { ReportInterval, ReportUrl } from '../config.static';

View File

@ -1,6 +1,6 @@
import { IsEntityID } from 'picsur-shared/dist/validators/entity-id.validator'; import { IsEntityID } from 'picsur-shared/dist/validators/entity-id.validator';
import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'; import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm';
import z from 'zod'; import * as z from 'zod';
export const ESysPreferenceSchema = z.object({ export const ESysPreferenceSchema = z.object({
id: IsEntityID().optional(), id: IsEntityID().optional(),

View File

@ -8,7 +8,7 @@ import {
PrimaryGeneratedColumn, PrimaryGeneratedColumn,
Unique, Unique,
} from 'typeorm'; } from 'typeorm';
import z from 'zod'; import * as z from 'zod';
import { EUserBackend } from '../users/user.entity'; import { EUserBackend } from '../users/user.entity';
export const EUsrPreferenceSchema = z.object({ export const EUsrPreferenceSchema = z.object({

View File

@ -1,3 +1,4 @@
import { MigrationInterface } from 'typeorm';
import { V030A1661692206479 } from './1661692206479-V_0_3_0_a'; import { V030A1661692206479 } from './1661692206479-V_0_3_0_a';
import { V032A1662029904716 } from './1662029904716-V_0_3_2_a'; import { V032A1662029904716 } from './1662029904716-V_0_3_2_a';
import { V040A1662314197741 } from './1662314197741-V_0_4_0_a'; import { V040A1662314197741 } from './1662314197741-V_0_4_0_a';
@ -5,8 +6,9 @@ import { V040B1662485374471 } from './1662485374471-V_0_4_0_b';
import { V040C1662535484200 } from './1662535484200-V_0_4_0_c'; import { V040C1662535484200 } from './1662535484200-V_0_4_0_c';
import { V040D1662728275448 } from './1662728275448-V_0_4_0_d'; import { V040D1662728275448 } from './1662728275448-V_0_4_0_d';
import { V050A1672154027079 } from './1672154027079-V_0_5_0_a'; import { V050A1672154027079 } from './1672154027079-V_0_5_0_a';
import { Newable } from 'picsur-shared/dist/types/newable.js';
export const MigrationList: Function[] = [ export const MigrationList: Newable<MigrationInterface>[] = [
V030A1661692206479, V030A1661692206479,
V032A1662029904716, V032A1662029904716,
V040A1662314197741, V040A1662314197741,

View File

@ -1,12 +1,12 @@
import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common'; import { Injectable, PipeTransform } from '@nestjs/common';
import { Ext2FileType } from 'picsur-shared/dist/dto/mimes.dto'; import { Ext2FileType } from 'picsur-shared/dist/dto/mimes.dto';
import { Fail, FT, HasFailed } from 'picsur-shared/dist/types'; import { FT, Fail, HasFailed } from 'picsur-shared/dist/types/failable';
import { UUIDRegex } from 'picsur-shared/dist/util/common-regex'; import { UUIDRegex } from 'picsur-shared/dist/util/common-regex';
import { ImageFullId } from '../../models/constants/image-full-id.const'; import { ImageFullId } from '../../models/constants/image-full-id.const';
@Injectable() @Injectable()
export class ImageFullIdPipe implements PipeTransform<string, ImageFullId> { export class ImageFullIdPipe implements PipeTransform<string, ImageFullId> {
transform(value: string, metadata: ArgumentMetadata): ImageFullId { transform(value: string): ImageFullId {
const split = value.split('.'); const split = value.split('.');
if (split.length === 2) { if (split.length === 2) {
const [id, ext] = split; const [id, ext] = split;

View File

@ -1,10 +1,10 @@
import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common'; import { Injectable, PipeTransform } from '@nestjs/common';
import { Fail, FT } from 'picsur-shared/dist/types'; import { FT, Fail } from 'picsur-shared/dist/types/failable';
import { UUIDRegex } from 'picsur-shared/dist/util/common-regex'; import { UUIDRegex } from 'picsur-shared/dist/util/common-regex';
@Injectable() @Injectable()
export class ImageIdPipe implements PipeTransform<string, string> { export class ImageIdPipe implements PipeTransform<string, string> {
transform(value: string, metadata: ArgumentMetadata): string { transform(value: string): string {
if (UUIDRegex.test(value)) return value; if (UUIDRegex.test(value)) return value;
throw Fail(FT.UsrValidation, 'Invalid image id'); throw Fail(FT.UsrValidation, 'Invalid image id');
} }

View File

@ -1,7 +1,7 @@
import { Multipart, MultipartFile } from '@fastify/multipart'; import { Multipart, MultipartFile } from '@fastify/multipart';
import { Injectable, Logger, PipeTransform, Scope } from '@nestjs/common'; import { Injectable, Logger, PipeTransform, Scope } from '@nestjs/common';
import { FastifyRequest } from 'fastify'; import { FastifyRequest } from 'fastify';
import { Fail, FT } from 'picsur-shared/dist/types'; import { Fail, FT } from 'picsur-shared/dist/types/failable';
import { MultipartConfigService } from '../../config/early/multipart.config.service'; import { MultipartConfigService } from '../../config/early/multipart.config.service';
@Injectable({ scope: Scope.REQUEST }) @Injectable({ scope: Scope.REQUEST })
@ -12,7 +12,7 @@ export class PostFilePipe implements PipeTransform {
private readonly multipartConfigService: MultipartConfigService, private readonly multipartConfigService: MultipartConfigService,
) {} ) {}
async transform({ request, data }: { data: any; request: FastifyRequest }) { async transform({ request }: { request: FastifyRequest }) {
if (!request.isMultipart()) throw Fail(FT.UsrValidation, 'Invalid file'); if (!request.isMultipart()) throw Fail(FT.UsrValidation, 'Invalid file');
// Only one file is allowed // Only one file is allowed

View File

@ -1,13 +1,7 @@
import { MultipartFile } from '@fastify/multipart'; import { MultipartFile } from '@fastify/multipart';
import { import { Injectable, Logger, PipeTransform, Scope } from '@nestjs/common';
ArgumentMetadata,
Injectable,
Logger,
PipeTransform,
Scope,
} from '@nestjs/common';
import { FastifyRequest } from 'fastify'; import { FastifyRequest } from 'fastify';
import { Fail, FT } from 'picsur-shared/dist/types'; import { FT, Fail } from 'picsur-shared/dist/types/failable';
import { MultipartConfigService } from '../../config/early/multipart.config.service'; import { MultipartConfigService } from '../../config/early/multipart.config.service';
export type FileIterator = AsyncIterableIterator<MultipartFile>; export type FileIterator = AsyncIterableIterator<MultipartFile>;
@ -20,10 +14,7 @@ export class MultiPartPipe implements PipeTransform {
private readonly multipartConfigService: MultipartConfigService, private readonly multipartConfigService: MultipartConfigService,
) {} ) {}
async transform<T extends Object>( async transform({ request, data }: { data: any; request: FastifyRequest }) {
{ request, data }: { data: any; request: FastifyRequest },
metadata: ArgumentMetadata,
) {
const filesLimit = typeof data === 'number' ? data : undefined; const filesLimit = typeof data === 'number' ? data : undefined;
if (!request.isMultipart()) throw Fail(FT.UsrValidation, 'Invalid files'); if (!request.isMultipart()) throw Fail(FT.UsrValidation, 'Invalid files');

View File

@ -4,7 +4,7 @@ import {
SetMetadata, SetMetadata,
UseGuards, UseGuards,
} from '@nestjs/common'; } from '@nestjs/common';
import { Fail, FT } from 'picsur-shared/dist/types'; import { Fail, FT } from 'picsur-shared/dist/types/failable';
import { CombineFCDecorators } from 'picsur-shared/dist/util/decorator'; import { CombineFCDecorators } from 'picsur-shared/dist/util/decorator';
import { LocalAuthGuard } from '../managers/auth/guards/local-auth.guard'; import { LocalAuthGuard } from '../managers/auth/guards/local-auth.guard';
import { Permission, Permissions } from '../models/constants/permissions.const'; import { Permission, Permissions } from '../models/constants/permissions.const';

View File

@ -1,5 +1,5 @@
import { createParamDecorator, ExecutionContext } from '@nestjs/common'; import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { Fail, FT } from 'picsur-shared/dist/types'; import { Fail, FT } from 'picsur-shared/dist/types/failable';
import AuthFastifyRequest from '../models/interfaces/authrequest.dto'; import AuthFastifyRequest from '../models/interfaces/authrequest.dto';
export const ReqUser = createParamDecorator( export const ReqUser = createParamDecorator(

View File

@ -6,12 +6,12 @@ import { Newable } from 'picsur-shared/dist/types/newable';
type ReturnsMethodDecorator<ReturnType> = < type ReturnsMethodDecorator<ReturnType> = <
T extends (...args: any) => ReturnType | Promise<ReturnType>, T extends (...args: any) => ReturnType | Promise<ReturnType>,
>( >(
target: Object, target: object,
propertyKey: string | symbol, propertyKey: string | symbol,
descriptor: TypedPropertyDescriptor<T>, descriptor: TypedPropertyDescriptor<T>,
) => TypedPropertyDescriptor<T> | void; ) => TypedPropertyDescriptor<T> | void;
export function Returns<N extends Object>( export function Returns<N extends object>(
newable: Newable<N>, newable: Newable<N>,
): ReturnsMethodDecorator<N> { ): ReturnsMethodDecorator<N> {
return SetMetadata('returns', newable); return SetMetadata('returns', newable);

View File

@ -9,7 +9,7 @@ import {
import { Reflector } from '@nestjs/core'; import { Reflector } from '@nestjs/core';
import { FastifyReply } from 'fastify'; import { FastifyReply } from 'fastify';
import { ApiAnySuccessResponse } from 'picsur-shared/dist/dto/api/api.dto'; import { ApiAnySuccessResponse } from 'picsur-shared/dist/dto/api/api.dto';
import { Fail, FT } from 'picsur-shared/dist/types'; import { Fail, FT } from 'picsur-shared/dist/types/failable';
import { ZodDtoStatic } from 'picsur-shared/dist/util/create-zod-dto'; import { ZodDtoStatic } from 'picsur-shared/dist/util/create-zod-dto';
import { map, Observable } from 'rxjs'; import { map, Observable } from 'rxjs';
@ -20,7 +20,7 @@ export interface ZodValidationInterceptorOptions {
} }
@Injectable() @Injectable()
export class SuccessInterceptor<T> implements NestInterceptor { export class SuccessInterceptor implements NestInterceptor {
private readonly logger = new Logger(); private readonly logger = new Logger();
// TODO: make work // TODO: make work
@ -82,7 +82,7 @@ export class SuccessInterceptor<T> implements NestInterceptor {
); );
} }
let schema = schemaStatic.zodSchema; const schema = schemaStatic.zodSchema;
const parseResult = schema.safeParse(data); const parseResult = schema.safeParse(data);
if (!parseResult.success) { if (!parseResult.success) {
@ -105,7 +105,7 @@ export class SuccessInterceptor<T> implements NestInterceptor {
const response = context.switchToHttp().getResponse<FastifyReply>(); const response = context.switchToHttp().getResponse<FastifyReply>();
const newResponse: ApiAnySuccessResponse = { const newResponse: ApiAnySuccessResponse = {
success: true as true, // really typescript success: true as const, // really typescript
statusCode: response.statusCode, statusCode: response.statusCode,
timestamp: new Date().toISOString(), timestamp: new Date().toISOString(),
timeMs: Math.round(response.getResponseTime()), timeMs: Math.round(response.getResponseTime()),

View File

@ -1,10 +1,10 @@
import { ExecutionContext, Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { ThrottlerGuard } from '@nestjs/throttler'; import { ThrottlerGuard } from '@nestjs/throttler';
import { Fail, FT } from 'picsur-shared/dist/types'; import { FT, Fail } from 'picsur-shared/dist/types/failable';
@Injectable() @Injectable()
export class PicsurThrottlerGuard extends ThrottlerGuard { export class PicsurThrottlerGuard extends ThrottlerGuard {
protected override throwThrottlingException(context: ExecutionContext): void { protected override throwThrottlingException(): void {
throw Fail(FT.RateLimit); throw Fail(FT.RateLimit);
} }
} }

View File

@ -9,7 +9,7 @@ import {
Optional, Optional,
PipeTransform, PipeTransform,
} from '@nestjs/common'; } from '@nestjs/common';
import { Fail, FT } from 'picsur-shared/dist/types'; import { Fail, FT } from 'picsur-shared/dist/types/failable';
import { ZodDtoStatic } from 'picsur-shared/dist/util/create-zod-dto'; import { ZodDtoStatic } from 'picsur-shared/dist/util/create-zod-dto';
export interface ZodValidationPipeOptions { export interface ZodValidationPipeOptions {
@ -30,7 +30,7 @@ export class ZodValidationPipe implements PipeTransform {
public transform(value: unknown, metadata: ArgumentMetadata): unknown { public transform(value: unknown, metadata: ArgumentMetadata): unknown {
if (!this.validateCustom && metadata.type === 'custom') return value; if (!this.validateCustom && metadata.type === 'custom') return value;
let zodSchema = (metadata?.metatype as ZodDtoStatic)?.zodSchema; const zodSchema = (metadata?.metatype as ZodDtoStatic)?.zodSchema;
if (zodSchema) { if (zodSchema) {
const parseResult = zodSchema.safeParse(value); const parseResult = zodSchema.safeParse(value);

View File

@ -2,7 +2,7 @@ import { Injectable, Logger } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt'; import { JwtService } from '@nestjs/jwt';
import { JwtData, JwtDataSchema } from 'picsur-shared/dist/dto/jwt.dto'; import { JwtData, JwtDataSchema } from 'picsur-shared/dist/dto/jwt.dto';
import { EUser } from 'picsur-shared/dist/entities/user.entity'; import { EUser } from 'picsur-shared/dist/entities/user.entity';
import { AsyncFailable, Fail, FT } from 'picsur-shared/dist/types'; import { AsyncFailable, Fail, FT } from 'picsur-shared/dist/types/failable';
@Injectable() @Injectable()
export class AuthManagerService { export class AuthManagerService {

View File

@ -2,7 +2,7 @@ import { Injectable, Logger } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport'; import { PassportStrategy } from '@nestjs/passport';
import { HeaderAPIKeyStrategy } from 'passport-headerapikey'; import { HeaderAPIKeyStrategy } from 'passport-headerapikey';
import { EUser, EUserSchema } from 'picsur-shared/dist/entities/user.entity'; import { EUser, EUserSchema } from 'picsur-shared/dist/entities/user.entity';
import { HasFailed } from 'picsur-shared/dist/types'; import { HasFailed } from 'picsur-shared/dist/types/failable';
import { IsApiKey } from 'picsur-shared/dist/validators/api-key.validator'; import { IsApiKey } from 'picsur-shared/dist/validators/api-key.validator';
import { ApiKeyDbService } from '../../../collections/apikey-db/apikey-db.service'; import { ApiKeyDbService } from '../../../collections/apikey-db/apikey-db.service';
import { EUserBackend2EUser } from '../../../models/transformers/user.transformer'; import { EUserBackend2EUser } from '../../../models/transformers/user.transformer';
@ -23,7 +23,7 @@ export class ApiKeyStrategy extends PassportStrategy(
false, false,
( (
apikey: string, apikey: string,
verified: (err: Error | null, user?: Object, info?: Object) => void, verified: (err: Error | null, user?: object, info?: object) => void,
) => { ) => {
this.validate(apikey) this.validate(apikey)
.then((user) => { .then((user) => {

View File

@ -8,11 +8,12 @@ import { ReqType } from './reqtype';
class GuestPassportStrategy extends Strategy { class GuestPassportStrategy extends Strategy {
// Will be overridden by the nest implementation // Will be overridden by the nest implementation
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async validate(req: ReqType): Promise<any> { async validate(req: ReqType): Promise<any> {
return undefined; return undefined;
} }
override async authenticate(req: ReqType, options?: any) { override async authenticate(req: ReqType) {
const user = await this.validate(req); const user = await this.validate(req);
this.success(user); this.success(user);
} }
@ -28,7 +29,7 @@ export class GuestStrategy extends PassportStrategy(
} }
// Return the guest user created by the guestservice // Return the guest user created by the guestservice
override async validate(payload: any): Promise<EUser> { override async validate(): Promise<EUser> {
return EUserBackend2EUser(await this.guestService.getGuestUser()); return EUserBackend2EUser(await this.guestService.getGuestUser());
} }
} }

View File

@ -3,7 +3,7 @@ import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy as JwtPassportStrategy } from 'passport-jwt'; import { ExtractJwt, Strategy as JwtPassportStrategy } from 'passport-jwt';
import { JwtDataSchema } from 'picsur-shared/dist/dto/jwt.dto'; import { JwtDataSchema } from 'picsur-shared/dist/dto/jwt.dto';
import { EUser } from 'picsur-shared/dist/entities/user.entity'; import { EUser } from 'picsur-shared/dist/entities/user.entity';
import { ThrowIfFailed } from 'picsur-shared/dist/types'; import { ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { UserDbService } from '../../../collections/user-db/user-db.service'; import { UserDbService } from '../../../collections/user-db/user-db.service';
import { EUserBackend2EUser } from '../../../models/transformers/user.transformer'; import { EUserBackend2EUser } from '../../../models/transformers/user.transformer';

View File

@ -2,7 +2,10 @@ import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport'; import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-local'; import { Strategy } from 'passport-local';
import { EUser } from 'picsur-shared/dist/entities/user.entity'; import { EUser } from 'picsur-shared/dist/entities/user.entity';
import { AsyncFailable, ThrowIfFailed } from 'picsur-shared/dist/types'; import {
AsyncFailable,
ThrowIfFailed,
} from 'picsur-shared/dist/types/failable';
import { UserDbService } from '../../../collections/user-db/user-db.service'; import { UserDbService } from '../../../collections/user-db/user-db.service';
import { EUserBackend2EUser } from '../../../models/transformers/user.transformer'; import { EUserBackend2EUser } from '../../../models/transformers/user.transformer';

View File

@ -9,7 +9,7 @@ import {
FT, FT,
HasFailed, HasFailed,
ThrowIfFailed, ThrowIfFailed,
} from 'picsur-shared/dist/types'; } from 'picsur-shared/dist/types/failable';
import { makeUnique } from 'picsur-shared/dist/util/unique'; import { makeUnique } from 'picsur-shared/dist/util/unique';
import { UserDbService } from '../../../collections/user-db/user-db.service'; import { UserDbService } from '../../../collections/user-db/user-db.service';
import { Permissions } from '../../../models/constants/permissions.const'; import { Permissions } from '../../../models/constants/permissions.const';

View File

@ -1,5 +1,5 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { HasFailed } from 'picsur-shared/dist/types'; import { HasFailed } from 'picsur-shared/dist/types/failable';
import { UserDbService } from '../../collections/user-db/user-db.service'; import { UserDbService } from '../../collections/user-db/user-db.service';
import { EUserBackend } from '../../database/entities/users/user.entity'; import { EUserBackend } from '../../database/entities/users/user.entity';

View File

@ -6,7 +6,12 @@ import {
SupportedFileTypeCategory, SupportedFileTypeCategory,
} from 'picsur-shared/dist/dto/mimes.dto'; } from 'picsur-shared/dist/dto/mimes.dto';
import { SysPreference } from 'picsur-shared/dist/dto/sys-preferences.enum'; import { SysPreference } from 'picsur-shared/dist/dto/sys-preferences.enum';
import { AsyncFailable, Fail, FT, HasFailed } from 'picsur-shared/dist/types'; import {
AsyncFailable,
Fail,
FT,
HasFailed,
} from 'picsur-shared/dist/types/failable';
import { SharpOptions } from 'sharp'; import { SharpOptions } from 'sharp';
import { SysPreferenceDbService } from '../../collections/preference-db/sys-preference-db.service'; import { SysPreferenceDbService } from '../../collections/preference-db/sys-preference-db.service';
import { SharpWrapper } from '../../workers/sharp.wrapper'; import { SharpWrapper } from '../../workers/sharp.wrapper';

View File

@ -2,7 +2,7 @@ import { Logger, Module, OnModuleInit } from '@nestjs/common';
import { Interval } from '@nestjs/schedule'; import { Interval } from '@nestjs/schedule';
import ms from 'ms'; import ms from 'ms';
import { SysPreference } from 'picsur-shared/dist/dto/sys-preferences.enum'; import { SysPreference } from 'picsur-shared/dist/dto/sys-preferences.enum';
import { HasFailed } from 'picsur-shared/dist/types'; import { HasFailed } from 'picsur-shared/dist/types/failable';
import { ImageDBModule } from '../../collections/image-db/image-db.module'; import { ImageDBModule } from '../../collections/image-db/image-db.module';
import { ImageDBService } from '../../collections/image-db/image-db.service'; import { ImageDBService } from '../../collections/image-db/image-db.service';
import { ImageFileDBService } from '../../collections/image-db/image-file-db.service'; import { ImageFileDBService } from '../../collections/image-db/image-file-db.service';

View File

@ -5,7 +5,12 @@ import {
SupportedFileTypeCategory, SupportedFileTypeCategory,
} from 'picsur-shared/dist/dto/mimes.dto'; } from 'picsur-shared/dist/dto/mimes.dto';
import { AsyncFailable, Fail, FT, HasFailed } from 'picsur-shared/dist/types'; import {
AsyncFailable,
Fail,
FT,
HasFailed,
} from 'picsur-shared/dist/types/failable';
import { ParseFileType } from 'picsur-shared/dist/util/parse-mime'; import { ParseFileType } from 'picsur-shared/dist/util/parse-mime';
import { ImageConverterService } from './image-converter.service'; import { ImageConverterService } from './image-converter.service';
import { ImageResult } from './imageresult'; import { ImageResult } from './imageresult';

View File

@ -1,5 +1,5 @@
import { Injectable, Logger } from '@nestjs/common'; import { Injectable, Logger } from '@nestjs/common';
import Crypto from 'crypto'; import { createHash } from 'crypto';
import { fileTypeFromBuffer, FileTypeResult } from 'file-type'; import { fileTypeFromBuffer, FileTypeResult } from 'file-type';
import { ImageRequestParams } from 'picsur-shared/dist/dto/api/image.dto'; import { ImageRequestParams } from 'picsur-shared/dist/dto/api/image.dto';
import { ImageEntryVariant } from 'picsur-shared/dist/dto/image-entry-variant.enum'; import { ImageEntryVariant } from 'picsur-shared/dist/dto/image-entry-variant.enum';
@ -11,7 +11,12 @@ import {
} from 'picsur-shared/dist/dto/mimes.dto'; } from 'picsur-shared/dist/dto/mimes.dto';
import { SysPreference } from 'picsur-shared/dist/dto/sys-preferences.enum'; import { SysPreference } from 'picsur-shared/dist/dto/sys-preferences.enum';
import { UsrPreference } from 'picsur-shared/dist/dto/usr-preferences.enum'; import { UsrPreference } from 'picsur-shared/dist/dto/usr-preferences.enum';
import { AsyncFailable, Fail, FT, HasFailed } from 'picsur-shared/dist/types'; import {
AsyncFailable,
Fail,
FT,
HasFailed,
} from 'picsur-shared/dist/types/failable';
import { FindResult } from 'picsur-shared/dist/types/find-result'; import { FindResult } from 'picsur-shared/dist/types/find-result';
import { ParseFileType } from 'picsur-shared/dist/util/parse-mime'; import { ParseFileType } from 'picsur-shared/dist/util/parse-mime';
import { IsQOI } from 'qoi-img'; import { IsQOI } from 'qoi-img';
@ -229,7 +234,7 @@ export class ImageManagerService {
} }
return { return {
[ImageEntryVariant.MASTER]: result[ImageEntryVariant.MASTER]!, [ImageEntryVariant.MASTER]: result[ImageEntryVariant.MASTER],
[ImageEntryVariant.ORIGINAL]: result[ImageEntryVariant.ORIGINAL], [ImageEntryVariant.ORIGINAL]: result[ImageEntryVariant.ORIGINAL],
}; };
} }
@ -268,7 +273,7 @@ export class ImageManagerService {
private getConvertHash(options: object) { private getConvertHash(options: object) {
// Return a sha256 hash of the stringified options // Return a sha256 hash of the stringified options
const stringified = JSON.stringify(options); const stringified = JSON.stringify(options);
const hash = Crypto.createHash('sha256'); const hash = createHash('sha256');
hash.update(stringified); hash.update(stringified);
const digest = hash.digest('hex'); const digest = hash.digest('hex');
return digest; return digest;

View File

@ -1,3 +1,5 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-empty-function */
// @ts-nocheck // @ts-nocheck
/* /*
@ -310,8 +312,8 @@ export class WebPInfo extends StreamParserWritable {
['VP8', 'VP8L', 'ANMF'].map((t) => [t, true] as [ChunkType, true]), ['VP8', 'VP8L', 'ANMF'].map((t) => [t, true] as [ChunkType, true]),
); );
private offset: number = 0; private offset = 0;
private maxSeekableOffset: number = -1; // same as file size - 1 private maxSeekableOffset = -1; // same as file size - 1
private pending?: { private pending?: {
size: number; size: number;

View File

@ -1,8 +1,8 @@
import { Injectable, Logger } from '@nestjs/common'; import { Injectable, Logger } from '@nestjs/common';
import isDocker from 'is-docker'; import isDocker from 'is-docker';
import fetch from 'node-fetch'; import fetch from 'node-fetch';
import os from 'os'; import * as os from 'os';
import { FallbackIfFailed, HasFailed } from 'picsur-shared/dist/types'; import { FallbackIfFailed, HasFailed } from 'picsur-shared/dist/types/failable';
import { UUIDRegex } from 'picsur-shared/dist/util/common-regex'; import { UUIDRegex } from 'picsur-shared/dist/util/common-regex';
import { ImageDBService } from '../../collections/image-db/image-db.service'; import { ImageDBService } from '../../collections/image-db/image-db.service';
import { SystemStateDbService } from '../../collections/system-state-db/system-state-db.service'; import { SystemStateDbService } from '../../collections/system-state-db/system-state-db.service';

View File

@ -24,7 +24,7 @@ export const UndeletableRolesList: string[] = UndeletableRolesTuple;
export const SystemRolesList = UndeletableRolesList; export const SystemRolesList = UndeletableRolesList;
// Defaults // Defaults
type SystemRole = typeof UndeletableRolesTuple[number]; type SystemRole = (typeof UndeletableRolesTuple)[number];
const SystemRoleDefaultsTyped: { const SystemRoleDefaultsTyped: {
[key in SystemRole]: Permissions; [key in SystemRole]: Permissions;
} = { } = {

View File

@ -12,7 +12,7 @@ import {
ApiKeyUpdateResponse, ApiKeyUpdateResponse,
} from 'picsur-shared/dist/dto/api/apikeys.dto'; } from 'picsur-shared/dist/dto/api/apikeys.dto';
import { Permission } from 'picsur-shared/dist/dto/permissions.enum'; import { Permission } from 'picsur-shared/dist/dto/permissions.enum';
import { ThrowIfFailed } from 'picsur-shared/dist/types'; import { ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { ApiKeyDbService } from '../../../collections/apikey-db/apikey-db.service'; import { ApiKeyDbService } from '../../../collections/apikey-db/apikey-db.service';
import { import {
HasPermission, HasPermission,

View File

@ -3,8 +3,6 @@ import { NoPermissions } from '../../../decorators/permissions.decorator';
@Controller('api/experiment') @Controller('api/experiment')
@NoPermissions() @NoPermissions()
export class ExperimentController { export class ExperimentController {
constructor() {}
// @Get() // @Get()
// @Returns(UserInfoResponse) // @Returns(UserInfoResponse)
// async testRoute( // async testRoute(

View File

@ -11,7 +11,7 @@ import {
SupportedImageFileTypes, SupportedImageFileTypes,
} from 'picsur-shared/dist/dto/mimes.dto'; } from 'picsur-shared/dist/dto/mimes.dto';
import { TrackingState } from 'picsur-shared/dist/dto/tracking-state.enum'; import { TrackingState } from 'picsur-shared/dist/dto/tracking-state.enum';
import { FallbackIfFailed } from 'picsur-shared/dist/types'; import { FallbackIfFailed } from 'picsur-shared/dist/types/failable';
import { HostConfigService } from '../../../config/early/host.config.service'; import { HostConfigService } from '../../../config/early/host.config.service';
import { InfoConfigService } from '../../../config/late/info.config.service'; import { InfoConfigService } from '../../../config/late/info.config.service';
import { UsageConfigService } from '../../../config/late/usage.config.service'; import { UsageConfigService } from '../../../config/late/usage.config.service';

View File

@ -6,7 +6,7 @@ import {
UpdatePreferenceRequest, UpdatePreferenceRequest,
UpdatePreferenceResponse, UpdatePreferenceResponse,
} from 'picsur-shared/dist/dto/api/pref.dto'; } from 'picsur-shared/dist/dto/api/pref.dto';
import { ThrowIfFailed } from 'picsur-shared/dist/types'; import { ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { SysPreferenceDbService } from '../../../collections/preference-db/sys-preference-db.service'; import { SysPreferenceDbService } from '../../../collections/preference-db/sys-preference-db.service';
import { RequiredPermissions } from '../../../decorators/permissions.decorator'; import { RequiredPermissions } from '../../../decorators/permissions.decorator';
import { Returns } from '../../../decorators/returns.decorator'; import { Returns } from '../../../decorators/returns.decorator';

View File

@ -6,7 +6,7 @@ import {
UpdatePreferenceRequest, UpdatePreferenceRequest,
UpdatePreferenceResponse, UpdatePreferenceResponse,
} from 'picsur-shared/dist/dto/api/pref.dto'; } from 'picsur-shared/dist/dto/api/pref.dto';
import { ThrowIfFailed } from 'picsur-shared/dist/types'; import { ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { UsrPreferenceDbService } from '../../../collections/preference-db/usr-preference-db.service'; import { UsrPreferenceDbService } from '../../../collections/preference-db/usr-preference-db.service';
import { RequiredPermissions } from '../../../decorators/permissions.decorator'; import { RequiredPermissions } from '../../../decorators/permissions.decorator';
import { ReqUserID } from '../../../decorators/request-user.decorator'; import { ReqUserID } from '../../../decorators/request-user.decorator';

View File

@ -12,7 +12,7 @@ import {
RoleUpdateResponse, RoleUpdateResponse,
SpecialRolesResponse, SpecialRolesResponse,
} from 'picsur-shared/dist/dto/api/roles.dto'; } from 'picsur-shared/dist/dto/api/roles.dto';
import { Fail, FT, ThrowIfFailed } from 'picsur-shared/dist/types'; import { Fail, FT, ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { RoleDbService } from '../../../collections/role-db/role-db.service'; import { RoleDbService } from '../../../collections/role-db/role-db.service';
import { UserDbService } from '../../../collections/user-db/user-db.service'; import { UserDbService } from '../../../collections/user-db/user-db.service';
import { RequiredPermissions } from '../../../decorators/permissions.decorator'; import { RequiredPermissions } from '../../../decorators/permissions.decorator';

View File

@ -1,7 +1,7 @@
import { Controller, Logger, Post, Req, Res } from '@nestjs/common'; import { Controller, Logger, Post, Req, Res } from '@nestjs/common';
import { Throttle } from '@nestjs/throttler'; import { Throttle } from '@nestjs/throttler';
import type { FastifyReply, FastifyRequest } from 'fastify'; import type { FastifyReply, FastifyRequest } from 'fastify';
import { Fail, FT, ThrowIfFailed } from 'picsur-shared/dist/types'; import { Fail, FT, ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { UsageConfigService } from '../../../config/late/usage.config.service'; import { UsageConfigService } from '../../../config/late/usage.config.service';
import { NoPermissions } from '../../../decorators/permissions.decorator'; import { NoPermissions } from '../../../decorators/permissions.decorator';
import { ReturnsAnything } from '../../../decorators/returns.decorator'; import { ReturnsAnything } from '../../../decorators/returns.decorator';

View File

@ -13,7 +13,7 @@ import {
UserUpdateRequest, UserUpdateRequest,
UserUpdateResponse, UserUpdateResponse,
} from 'picsur-shared/dist/dto/api/user-manage.dto'; } from 'picsur-shared/dist/dto/api/user-manage.dto';
import { ThrowIfFailed } from 'picsur-shared/dist/types'; import { ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { UserDbService } from '../../../collections/user-db/user-db.service'; import { UserDbService } from '../../../collections/user-db/user-db.service';
import { RequiredPermissions } from '../../../decorators/permissions.decorator'; import { RequiredPermissions } from '../../../decorators/permissions.decorator';
import { Returns } from '../../../decorators/returns.decorator'; import { Returns } from '../../../decorators/returns.decorator';

View File

@ -10,7 +10,7 @@ import {
UserRegisterResponse, UserRegisterResponse,
} from 'picsur-shared/dist/dto/api/user.dto'; } from 'picsur-shared/dist/dto/api/user.dto';
import type { EUser } from 'picsur-shared/dist/entities/user.entity'; import type { EUser } from 'picsur-shared/dist/entities/user.entity';
import { ThrowIfFailed } from 'picsur-shared/dist/types'; import { ThrowIfFailed } from 'picsur-shared/dist/types/failable';
import { UserDbService } from '../../../collections/user-db/user-db.service'; import { UserDbService } from '../../../collections/user-db/user-db.service';
import { import {
NoPermissions, NoPermissions,

View File

@ -21,7 +21,12 @@ import {
ImageUploadResponse, ImageUploadResponse,
} from 'picsur-shared/dist/dto/api/image-manage.dto'; } from 'picsur-shared/dist/dto/api/image-manage.dto';
import { Permission } from 'picsur-shared/dist/dto/permissions.enum'; import { Permission } from 'picsur-shared/dist/dto/permissions.enum';
import { Fail, FT, HasFailed, ThrowIfFailed } from 'picsur-shared/dist/types'; import {
Fail,
FT,
HasFailed,
ThrowIfFailed,
} from 'picsur-shared/dist/types/failable';
import { PostFiles } from '../../decorators/multipart/multipart.decorator'; import { PostFiles } from '../../decorators/multipart/multipart.decorator';
import type { FileIterator } from '../../decorators/multipart/postfiles.pipe'; import type { FileIterator } from '../../decorators/multipart/postfiles.pipe';
import { import {

View File

@ -7,7 +7,11 @@ import {
} from 'picsur-shared/dist/dto/api/image.dto'; } from 'picsur-shared/dist/dto/api/image.dto';
import { ImageEntryVariant } from 'picsur-shared/dist/dto/image-entry-variant.enum'; import { ImageEntryVariant } from 'picsur-shared/dist/dto/image-entry-variant.enum';
import { FileType2Mime } from 'picsur-shared/dist/dto/mimes.dto'; import { FileType2Mime } from 'picsur-shared/dist/dto/mimes.dto';
import { FT, IsFailure, ThrowIfFailed } from 'picsur-shared/dist/types'; import {
FT,
IsFailure,
ThrowIfFailed,
} from 'picsur-shared/dist/types/failable';
import { UserDbService } from '../../collections/user-db/user-db.service'; import { UserDbService } from '../../collections/user-db/user-db.service';
import { ImageFullIdParam } from '../../decorators/image-id/image-full-id.decorator'; import { ImageFullIdParam } from '../../decorators/image-id/image-full-id.decorator';
import { ImageIdParam } from '../../decorators/image-id/image-id.decorator'; import { ImageIdParam } from '../../decorators/image-id/image-id.decorator';

View File

@ -1,6 +1,6 @@
import { readFile } from 'fs/promises'; import { readFile } from 'fs/promises';
import { resolve } from 'path'; import { resolve } from 'path';
import { AsyncFailable, Fail, FT } from 'picsur-shared/dist/types'; import { AsyncFailable, Fail, FT } from 'picsur-shared/dist/types/failable';
import { PackageRoot } from '../config/config.static'; import { PackageRoot } from '../config/config.static';
export const BrandingPath = resolve(PackageRoot, '../branding'); export const BrandingPath = resolve(PackageRoot, '../branding');

View File

@ -1,4 +1,4 @@
import { AsyncFailable, Fail, FT } from 'picsur-shared/dist/types'; import { AsyncFailable, Fail, FT } from 'picsur-shared/dist/types/failable';
export async function GetNextAsync<T>( export async function GetNextAsync<T>(
iterator: AsyncIterableIterator<T>, iterator: AsyncIterableIterator<T>,

View File

@ -1,7 +1,7 @@
import { Logger } from '@nestjs/common'; import { Logger } from '@nestjs/common';
import { ChildProcess, fork } from 'child_process'; import { ChildProcess, fork } from 'child_process';
import pTimeout from 'p-timeout'; import pTimeout from 'p-timeout';
import path from 'path'; import { dirname, join as pathJoin } from 'path';
import { FileType } from 'picsur-shared/dist/dto/mimes.dto'; import { FileType } from 'picsur-shared/dist/dto/mimes.dto';
import { import {
AsyncFailable, AsyncFailable,
@ -9,7 +9,7 @@ import {
Failable, Failable,
FT, FT,
HasFailed, HasFailed,
} from 'picsur-shared/dist/types'; } from 'picsur-shared/dist/types/failable';
import { Sharp, SharpOptions } from 'sharp'; import { Sharp, SharpOptions } from 'sharp';
import { import {
SharpWorkerFinishOptions, SharpWorkerFinishOptions,
@ -22,13 +22,13 @@ import {
import { SharpResult } from './sharp/universal-sharp'; import { SharpResult } from './sharp/universal-sharp';
const moduleURL = new URL(import.meta.url); const moduleURL = new URL(import.meta.url);
const __dirname = path.dirname(moduleURL.pathname); const __dirname = dirname(moduleURL.pathname);
export class SharpWrapper { export class SharpWrapper {
private readonly workerID: number = Math.floor(Math.random() * 100000); private readonly workerID: number = Math.floor(Math.random() * 100000);
private readonly logger: Logger = new Logger('SharpWrapper' + this.workerID); private readonly logger: Logger = new Logger('SharpWrapper' + this.workerID);
private static readonly WORKER_PATH = path.join( private static readonly WORKER_PATH = pathJoin(
__dirname, __dirname,
'./sharp', './sharp',
'sharp.worker.js', 'sharp.worker.js',

View File

@ -1,5 +1,5 @@
import { FileType } from 'picsur-shared/dist/dto/mimes.dto'; import { FileType } from 'picsur-shared/dist/dto/mimes.dto';
import posix from 'posix.js'; import { setrlimit } from 'posix.js';
import { Sharp } from 'sharp'; import { Sharp } from 'sharp';
import { import {
SharpWorkerFinishOptions, SharpWorkerFinishOptions,
@ -11,7 +11,7 @@ import {
import { UniversalSharpIn, UniversalSharpOut } from './universal-sharp'; import { UniversalSharpIn, UniversalSharpOut } from './universal-sharp';
export class SharpWorker { export class SharpWorker {
private startTime: number = 0; private startTime = 0;
private sharpi: Sharp | null = null; private sharpi: Sharp | null = null;
constructor() { constructor() {
@ -29,7 +29,7 @@ export class SharpWorker {
return this.purge('MEMORY_LIMIT_MB environment variable is not set'); return this.purge('MEMORY_LIMIT_MB environment variable is not set');
} }
posix.setrlimit('data', { setrlimit('data', {
soft: 1000 * 1000 * memoryLimit, soft: 1000 * 1000 * memoryLimit,
hard: 1000 * 1000 * memoryLimit, hard: 1000 * 1000 * memoryLimit,
}); });

View File

@ -11,8 +11,5 @@
"declaration": true, "declaration": true,
"sourceMap": true, "sourceMap": true,
"emitDecoratorMetadata": true "emitDecoratorMetadata": true
},
"ts-node": {
"experimentalSpecifierResolution": "node"
} }
} }

9
frontend/.eslintrc.cjs Normal file
View File

@ -0,0 +1,9 @@
module.exports = {
parserOptions: {
project: './tsconfig.base.json',
tsconfigRootDir: __dirname,
sourceType: 'module',
},
ignorePatterns: ['src/environments', 'custom-webpack.config.js'],
root: false,
};

View File

@ -14,11 +14,7 @@ export default {
use: { use: {
loader: 'babel-loader', loader: 'babel-loader',
options: { options: {
presets: [ presets: [['@babel/preset-env']],
[
'@babel/preset-env',
],
],
}, },
}, },
}, },

View File

@ -9,7 +9,7 @@
"scripts": { "scripts": {
"ng": "ng", "ng": "ng",
"start": "ng serve --host 0.0.0.0", "start": "ng serve --host 0.0.0.0",
"build": "ng build", "build": "ng build --verbose",
"watch": "ng build --watch --configuration development", "watch": "ng build --watch --configuration development",
"purge": "rm -rf dist && rm -rf node_modules && rm -rf .angular" "purge": "rm -rf dist && rm -rf node_modules && rm -rf .angular"
}, },
@ -47,7 +47,6 @@
"browserslist": "^4.21.7", "browserslist": "^4.21.7",
"caniuse-lite": "^1.0.30001495", "caniuse-lite": "^1.0.30001495",
"fuse.js": "^6.6.2", "fuse.js": "^6.6.2",
"jwt-decode": "^3.1.2",
"material-icons": "^1.13.8", "material-icons": "^1.13.8",
"moment": "^2.29.4", "moment": "^2.29.4",
"ng-mat-select-infinite-scroll": "^4.0.0", "ng-mat-select-infinite-scroll": "^4.0.0",
@ -62,5 +61,8 @@
"webpack-bundle-analyzer": "^4.9.0", "webpack-bundle-analyzer": "^4.9.0",
"zod": "^3.21.4", "zod": "^3.21.4",
"zone.js": "^0.13.0" "zone.js": "^0.13.0"
},
"dependencies": {
"@leteu/jwt-decoder": "^1.0.4"
} }
} }

View File

@ -25,14 +25,14 @@ export class AppComponent implements OnInit {
@ViewChild(MatSidenav) sidebar: MatSidenav; @ViewChild(MatSidenav) sidebar: MatSidenav;
loading: boolean = false; loading = false;
private loadingTimeout: number | null = null; private loadingTimeout: number | null = null;
wrapContentWithContainer: boolean = true; wrapContentWithContainer = true;
sidebarPortal: Portal<any> | undefined = undefined; sidebarPortal: Portal<any> | undefined = undefined;
isDesktop: boolean = false; isDesktop = false;
hasSidebar: boolean = false; hasSidebar = false;
public constructor( public constructor(
private readonly router: Router, private readonly router: Router,
@ -64,7 +64,7 @@ export class AppComponent implements OnInit {
if (event instanceof NavigationEnd) { if (event instanceof NavigationEnd) {
this.loadingEnd(); this.loadingEnd();
} }
if (event instanceof NavigationEnd) this.onNavigationEnd(event); if (event instanceof NavigationEnd) this.onNavigationEnd();
if (event instanceof NavigationError) this.onNavigationError(event); if (event instanceof NavigationError) this.onNavigationError(event);
}); });
} }
@ -84,7 +84,7 @@ export class AppComponent implements OnInit {
this.router.navigate(['/error/404'], { replaceUrl: true }); this.router.navigate(['/error/404'], { replaceUrl: true });
} }
private async onNavigationEnd(event: NavigationEnd) { private async onNavigationEnd() {
const data = this.routeData; const data = this.routeData;
this.wrapContentWithContainer = !data.noContainer; this.wrapContentWithContainer = !data.noContainer;

View File

@ -3,10 +3,10 @@ import {
MatFormFieldAppearance, MatFormFieldAppearance,
SubscriptSizing, SubscriptSizing,
} from '@angular/material/form-field'; } from '@angular/material/form-field';
import { FT, Fail } from 'picsur-shared/dist/types'; import { FT, Fail } from 'picsur-shared/dist/types/failable';
import { Logger } from 'src/app/services/logger/logger.service'; import { Logger } from '../../services/logger/logger.service';
import { ClipboardService } from 'src/app/util/clipboard.service'; import { ClipboardService } from '../../util/clipboard.service';
import { ErrorService } from 'src/app/util/error-manager/error.service'; import { ErrorService } from '../../util/error-manager/error.service';
@Component({ @Component({
selector: 'copy-field', selector: 'copy-field',
@ -17,11 +17,11 @@ export class CopyFieldComponent {
private readonly logger = new Logger(CopyFieldComponent.name); private readonly logger = new Logger(CopyFieldComponent.name);
// Two parameters: name, value // Two parameters: name, value
@Input() label: string = 'Loading...'; @Input() label = 'Loading...';
@Input() value: string = 'Loading...'; @Input() value = 'Loading...';
@Input() showHideButton: boolean = false; @Input() showHideButton = false;
@Input() hidden: boolean = false; @Input() hidden = false;
@Input() color: 'primary' | 'accent' | 'warn' = 'primary'; @Input() color: 'primary' | 'accent' | 'warn' = 'primary';
@Input() appearance: MatFormFieldAppearance = 'outline'; @Input() appearance: MatFormFieldAppearance = 'outline';

View File

@ -3,8 +3,9 @@ import { NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { ErrorManagerModule } from 'src/app/util/error-manager/error-manager.module';
import { CopyFieldComponent } from './copy-field.component'; import { CopyFieldComponent } from './copy-field.component';
import { ErrorManagerModule } from '../../util/error-manager/error-manager.module';
@NgModule({ @NgModule({
declarations: [CopyFieldComponent], declarations: [CopyFieldComponent],
imports: [ imports: [

View File

@ -5,11 +5,10 @@ import { Component, Input } from '@angular/core';
templateUrl: './fab.component.html', templateUrl: './fab.component.html',
}) })
export class FabComponent { export class FabComponent {
@Input('aria-label') ariaLabel: string = 'Floating Action Button'; @Input('aria-label') ariaLabel = 'Floating Action Button';
@Input() icon: string = 'add'; @Input() icon = 'add';
@Input() color: string = 'primary'; @Input() color = 'primary';
@Input('tooltip') tooltip: string; @Input('tooltip') tooltip: string;
// eslint-disable-next-line @typescript-eslint/no-empty-function
@Input() onClick: () => void = () => {}; @Input() onClick: () => void = () => {};
constructor() {}
} }

View File

@ -22,7 +22,7 @@
[matTooltip]="tooltip" [matTooltip]="tooltip"
matTooltipPosition="left" matTooltipPosition="left"
[matTooltipDisabled]="!openManager.isOpen" [matTooltipDisabled]="!openManager.isOpen"
(click)="click($event)" (click)="click()"
aria-label="" aria-label=""
> >
<mat-icon <mat-icon

View File

@ -9,19 +9,19 @@ import { SpeedDialAnimation } from './speed-dial.animation';
animations: [SpeedDialAnimation], animations: [SpeedDialAnimation],
}) })
export class SpeedDialComponent { export class SpeedDialComponent {
@Input('aria-label') ariaLabel: string = 'Floating Action Button'; @Input('aria-label') ariaLabel = 'Floating Action Button';
@Input('icon') icon: string = 'add'; @Input('icon') icon = 'add';
@Input('icon-hover') iconHover: string = 'close'; @Input('icon-hover') iconHover = 'close';
@Input('color') color: string = 'primary'; @Input('color') color = 'primary';
@Input('open-on-hover') openOnHover: boolean = false; @Input('open-on-hover') openOnHover = false;
@Input('tooltip') tooltip: string; @Input('tooltip') tooltip: string;
@Output('main-click') clickEmitter = new Subject<void>(); @Output('main-click') clickEmitter = new Subject<void>();
public openManager = new OpenManager(); public openManager = new OpenManager();
private touchUntil: number = 0; private touchUntil = 0;
@HostListener('document:touchstart', ['$event']) @HostListener('document:touchstart', ['$event'])
@HostListener('document:touchend', ['$event']) @HostListener('document:touchend', ['$event'])
@ -35,13 +35,13 @@ export class SpeedDialComponent {
@HostListener('document:click', ['$event']) @HostListener('document:click', ['$event'])
@HostListener('document:keydown.escape', ['$event']) @HostListener('document:keydown.escape', ['$event'])
anyClick(e: Event) { anyClick() {
if (!this.openManager.isOpen || this.openManager.isAnimating) return; if (!this.openManager.isOpen || this.openManager.isAnimating) return;
this.openManager.close(); this.openManager.close();
} }
click(e: MouseEvent) { click() {
if (!this.openManager.isOpen) { if (!this.openManager.isOpen) {
this.openManager.open(); this.openManager.open();
} else { } else {

View File

@ -5,7 +5,7 @@ import {
OnInit, OnInit,
} from '@angular/core'; } from '@angular/core';
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator'; import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
import { InfoService } from 'src/app/services/api/info.service'; import { InfoService } from '../../services/api/info.service';
@Component({ @Component({
selector: 'app-footer', selector: 'app-footer',
@ -19,8 +19,8 @@ export class FooterComponent implements OnInit {
private readonly changeDetector: ChangeDetectorRef, private readonly changeDetector: ChangeDetectorRef,
) {} ) {}
isDemo: boolean = false; isDemo = false;
version: string = 'Unkown Version'; version = 'Unkown Version';
ngOnInit(): void { ngOnInit(): void {
this.subscribeInfo(); this.subscribeInfo();

View File

@ -11,11 +11,11 @@ import { Router } from '@angular/router';
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator'; import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
import { Permission } from 'picsur-shared/dist/dto/permissions.enum'; import { Permission } from 'picsur-shared/dist/dto/permissions.enum';
import { EUser } from 'picsur-shared/dist/entities/user.entity'; import { EUser } from 'picsur-shared/dist/entities/user.entity';
import { HasFailed } from 'picsur-shared/dist/types'; import { HasFailed } from 'picsur-shared/dist/types/failable';
import { PermissionService } from 'src/app/services/api/permission.service'; import { UserService } from '../../services/api/user.service';
import { UserService } from 'src/app/services/api/user.service'; import { PermissionService } from '../../services/api/permission.service';
import { Logger } from 'src/app/services/logger/logger.service'; import { Logger } from '../../services/logger/logger.service';
import { ErrorService } from 'src/app/util/error-manager/error.service'; import { ErrorService } from '../../util/error-manager/error.service';
@Component({ @Component({
selector: 'app-header', selector: 'app-header',
@ -38,17 +38,17 @@ export class HeaderComponent implements OnInit {
this._enableHamburger = value; this._enableHamburger = value;
this.changeDetector.markForCheck(); this.changeDetector.markForCheck();
} }
public _enableHamburger: boolean = true; public _enableHamburger = true;
@Output('onHamburgerClick') onHamburgerClick = new EventEmitter<void>(); @Output('onHamburgerClick') onHamburgerClick = new EventEmitter<void>();
@Input('loading') public loading: boolean = false; @Input('loading') public loading = false;
private currentUser: EUser | null = null; private currentUser: EUser | null = null;
public canLogIn: boolean = false; public canLogIn = false;
public canAccessSettings: boolean = false; public canAccessSettings = false;
public canUpload: boolean = false; public canUpload = false;
public canRegister: boolean = false; public canRegister = false;
public get user() { public get user() {
return this.currentUser; return this.currentUser;

View File

@ -7,8 +7,8 @@ import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatToolbarModule } from '@angular/material/toolbar'; import { MatToolbarModule } from '@angular/material/toolbar';
import { MatTooltipModule } from '@angular/material/tooltip'; import { MatTooltipModule } from '@angular/material/tooltip';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { ErrorManagerModule } from 'src/app/util/error-manager/error-manager.module';
import { HeaderComponent } from './header.component'; import { HeaderComponent } from './header.component';
import { ErrorManagerModule } from '../../util/error-manager/error-manager.module';
@NgModule({ @NgModule({
imports: [ imports: [

View File

@ -1,12 +1,11 @@
import { Directive, ElementRef, Inject } from '@angular/core'; import { Directive, ElementRef, Inject } from '@angular/core';
import { import {
boxExtractor,
ResizeObserverDirective,
ResizeObserverService,
RESIZE_OPTION_BOX, RESIZE_OPTION_BOX,
ResizeObserverService,
boxExtractor,
} from '@ng-web-apis/resize-observer'; } from '@ng-web-apis/resize-observer';
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator'; import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
import { map, Observable } from 'rxjs'; import { Observable, map } from 'rxjs';
@Directive({ @Directive({
selector: '[masonry-item]', selector: '[masonry-item]',

View File

@ -12,9 +12,9 @@ import {
} from '@angular/core'; } from '@angular/core';
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator'; import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
import { combineLatest, Subscription } from 'rxjs'; import { combineLatest, Subscription } from 'rxjs';
import { RemoveChildren } from 'src/app/util/remove-children';
import { Throttle } from 'src/app/util/throttle';
import { MasonryItemDirective } from './masonry-item.directive'; import { MasonryItemDirective } from './masonry-item.directive';
import { RemoveChildren } from '../../util/remove-children';
import { Throttle } from '../../util/throttle';
@Component({ @Component({
selector: 'masonry', selector: 'masonry',
@ -30,7 +30,7 @@ export class MasonryComponent implements AfterViewInit, OnDestroy {
this.changeDetector.markForCheck(); this.changeDetector.markForCheck();
} }
public _column_count = 1; public _column_count = 1;
@Input('update-speed') update_speed: number = 200; @Input('update-speed') update_speed = 200;
@ContentChildren(MasonryItemDirective) @ContentChildren(MasonryItemDirective)
private content: QueryList<MasonryItemDirective>; private content: QueryList<MasonryItemDirective>;
@ -59,7 +59,7 @@ export class MasonryComponent implements AfterViewInit, OnDestroy {
this.sizesSubscription = combineLatest(sizes) this.sizesSubscription = combineLatest(sizes)
.pipe(Throttle(this.update_speed)) .pipe(Throttle(this.update_speed))
.subscribe((output) => { .subscribe(() => {
this.resortItems(items); this.resortItems(items);
}); });
@ -76,7 +76,7 @@ export class MasonryComponent implements AfterViewInit, OnDestroy {
RemoveChildren(columnsArray[i]); RemoveChildren(columnsArray[i]);
} }
const columnSizes = columnsArray.map((c) => 0); const columnSizes = columnsArray.map(() => 0);
for (let i = 0; i < itemsArray.length; i++) { for (let i = 0; i < itemsArray.length; i++) {
const item = itemsArray[i]; const item = itemsArray[i];
@ -84,7 +84,7 @@ export class MasonryComponent implements AfterViewInit, OnDestroy {
let smallestColumn = 0; let smallestColumn = 0;
let smallestColumnSize = columnSizes[0]; let smallestColumnSize = columnSizes[0];
for (let j = columnSizes.length - 1; j >= 0; j--) { for (let j = columnSizes.length - 1; j >= 0; j--) {
let better_j = (j + i) % columnSizes.length; const better_j = (j + i) % columnSizes.length;
if (columnSizes[better_j] <= smallestColumnSize) { if (columnSizes[better_j] <= smallestColumnSize) {
smallestColumn = better_j; smallestColumn = better_j;

View File

@ -1,5 +1,5 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Required } from 'src/app/models/decorators/required.decorator'; import { Required } from '../../models/decorators/required.decorator';
@Component({ @Component({
selector: 'paginator', selector: 'paginator',
@ -13,18 +13,18 @@ export class PaginatorComponent implements OnInit {
this.calculateRanges(); this.calculateRanges();
} }
page: number = 1; page = 1;
@Input('page') set pageInput(value: number) { @Input('page') set pageInput(value: number) {
this.page = value; this.page = value;
this.calculateRanges(); this.calculateRanges();
} }
@Output('page') pageChange = new EventEmitter<number>(); @Output('page') pageChange = new EventEmitter<number>();
@Input('show-first-last') showFirstLast: boolean = true; @Input('show-first-last') showFirstLast = true;
@Input('shown-pages') shownPages: number = 7; @Input('shown-pages') shownPages = 7;
@Input('shown-first-pages') shownFirstPages: number = 1; @Input('shown-first-pages') shownFirstPages = 1;
@Input('shown-last-pages') shownLastPages: number = 1; @Input('shown-last-pages') shownLastPages = 1;
firstPagesRange: [number, number] | null = null; firstPagesRange: [number, number] | null = null;
lastPagesRange: [number, number] | null = null; lastPagesRange: [number, number] | null = null;

View File

@ -2,8 +2,8 @@ import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { PipesModule } from 'src/app/pipes/pipes.module';
import { PaginatorComponent } from './paginator.component'; import { PaginatorComponent } from './paginator.component';
import { PipesModule } from '../../pipes/pipes.module';
@NgModule({ @NgModule({
declarations: [PaginatorComponent], declarations: [PaginatorComponent],

View File

@ -14,7 +14,7 @@
<mat-icon *ngIf="state === 'error'">broken_image</mat-icon> <mat-icon *ngIf="state === 'error'">broken_image</mat-icon>
<mat-spinner <mat-spinner
(nguiInview)="onInview($event)" (nguiInview)="onInview()"
(nguiOutview)="onOutview($event)" (nguiOutview)="onOutview()"
*ngIf="state === 'init' || state === 'loading'" *ngIf="state === 'init' || state === 'loading'"
></mat-spinner> ></mat-spinner>

View File

@ -5,16 +5,15 @@ import {
ElementRef, ElementRef,
Input, Input,
OnChanges, OnChanges,
SimpleChanges,
ViewChild, ViewChild,
} from '@angular/core'; } from '@angular/core';
import { FileType, ImageFileType } from 'picsur-shared/dist/dto/mimes.dto'; import { FileType, ImageFileType } from 'picsur-shared/dist/dto/mimes.dto';
import { AsyncFailable, HasFailed } from 'picsur-shared/dist/types'; import { AsyncFailable, HasFailed } from 'picsur-shared/dist/types/failable';
import { URLRegex } from 'picsur-shared/dist/util/common-regex'; import { URLRegex } from 'picsur-shared/dist/util/common-regex';
import { ParseMime2FileType } from 'picsur-shared/dist/util/parse-mime'; import { ParseMime2FileType } from 'picsur-shared/dist/util/parse-mime';
import { ApiService } from 'src/app/services/api/api.service'; import { ApiService } from '../../services/api/api.service';
import { Logger } from 'src/app/services/logger/logger.service'; import { Logger } from '../../services/logger/logger.service';
import { QoiWorkerService } from 'src/app/workers/qoi-worker.service'; import { QoiWorkerService } from '../../workers/qoi-worker.service';
enum PicsurImgState { enum PicsurImgState {
Init = 'init', Init = 'init',
@ -48,12 +47,12 @@ export class PicsurImgComponent implements OnChanges {
private readonly changeDetector: ChangeDetectorRef, private readonly changeDetector: ChangeDetectorRef,
) {} ) {}
ngOnChanges(changes: SimpleChanges): void { ngOnChanges(): void {
if (this.isInView) this.reload(); if (this.isInView) this.reload();
} }
private reload() { private reload() {
let url = this.imageURL ?? ''; const url = this.imageURL ?? '';
if (!URLRegex.test(url)) { if (!URLRegex.test(url)) {
this.state = PicsurImgState.Loading; this.state = PicsurImgState.Loading;
this.changeDetector.markForCheck(); this.changeDetector.markForCheck();
@ -68,7 +67,7 @@ export class PicsurImgComponent implements OnChanges {
this.changeDetector.markForCheck(); this.changeDetector.markForCheck();
} }
}) })
.catch((e) => this.logger.error); .catch(this.logger.error);
} }
private async update(url: string): AsyncFailable<void> { private async update(url: string): AsyncFailable<void> {
@ -111,7 +110,7 @@ export class PicsurImgComponent implements OnChanges {
return ParseMime2FileType(mime); return ParseMime2FileType(mime);
} }
onInview(e: any) { onInview() {
this.isInView = true; this.isInView = true;
if (this.state === PicsurImgState.Init) { if (this.state === PicsurImgState.Init) {
@ -120,7 +119,7 @@ export class PicsurImgComponent implements OnChanges {
} }
} }
onOutview(e: any) { onOutview() {
this.isInView = false; this.isInView = false;
} }
} }

View File

@ -5,13 +5,13 @@ import {
DecodedPref, DecodedPref,
PrefValueType, PrefValueType,
} from 'picsur-shared/dist/dto/preferences.dto'; } from 'picsur-shared/dist/dto/preferences.dto';
import { AsyncFailable, HasFailed } from 'picsur-shared/dist/types'; import { AsyncFailable, HasFailed } from 'picsur-shared/dist/types/failable';
import { filter } from 'rxjs'; import { filter } from 'rxjs';
import { Required } from 'src/app/models/decorators/required.decorator';
import { Logger } from 'src/app/services/logger/logger.service';
import { ErrorService } from 'src/app/util/error-manager/error.service';
import { Throttle } from 'src/app/util/throttle';
import { ZodTypeAny } from 'zod'; import { ZodTypeAny } from 'zod';
import { Required } from '../../models/decorators/required.decorator';
import { Logger } from '../../services/logger/logger.service';
import { ErrorService } from '../../util/error-manager/error.service';
import { Throttle } from '../../util/throttle';
@Component({ @Component({
selector: 'pref-option', selector: 'pref-option',
@ -40,8 +40,8 @@ export class PrefOptionComponent implements OnInit {
pref: PrefValueType, pref: PrefValueType,
) => AsyncFailable<any>; ) => AsyncFailable<any>;
@Input() @Required name: string = ''; @Input() @Required name = '';
@Input() helpText: string = ''; @Input() helpText = '';
@Input() validator?: ZodTypeAny = undefined; @Input() validator?: ZodTypeAny = undefined;
constructor(private readonly errorService: ErrorService) {} constructor(private readonly errorService: ErrorService) {}
@ -96,7 +96,7 @@ export class PrefOptionComponent implements OnInit {
subscribeUpdate() { subscribeUpdate() {
return this.formControl.valueChanges return this.formControl.valueChanges
.pipe( .pipe(
filter((value) => this.formControl.errors === null), filter(() => this.formControl.errors === null),
Throttle(300), Throttle(300),
) )
.subscribe(this.updatePreference.bind(this)); .subscribe(this.updatePreference.bind(this));

View File

@ -7,8 +7,8 @@ import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select'; import { MatSelectModule } from '@angular/material/select';
import { MatTooltipModule } from '@angular/material/tooltip'; import { MatTooltipModule } from '@angular/material/tooltip';
import { ErrorManagerModule } from 'src/app/util/error-manager/error-manager.module';
import { PrefOptionComponent } from './pref-option.component'; import { PrefOptionComponent } from './pref-option.component';
import { ErrorManagerModule } from '../../util/error-manager/error-manager.module';
@NgModule({ @NgModule({
imports: [ imports: [

View File

@ -6,7 +6,7 @@ import { MatChipInputEvent } from '@angular/material/chips';
import Fuse from 'fuse.js'; import Fuse from 'fuse.js';
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator'; import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
import { BehaviorSubject } from 'rxjs'; import { BehaviorSubject } from 'rxjs';
import { Required } from 'src/app/models/decorators/required.decorator'; import { Required } from '../../models/decorators/required.decorator';
@Component({ @Component({
selector: 'values-picker', selector: 'values-picker',
@ -18,7 +18,7 @@ export class ValuesPickerComponent implements OnInit, OnChanges {
readonly separatorKeysCodes: number[] = [ENTER, COMMA]; readonly separatorKeysCodes: number[] = [ENTER, COMMA];
// Ui niceties // Ui niceties
@Input('name') @Required name: string = ''; @Input('name') @Required name = '';
public get nameCap(): string { public get nameCap(): string {
return this.name.charAt(0).toUpperCase() + this.name.slice(1); return this.name.charAt(0).toUpperCase() + this.name.slice(1);
} }
@ -107,14 +107,14 @@ export class ValuesPickerComponent implements OnInit, OnChanges {
@AutoUnsubscribe() @AutoUnsubscribe()
private subscribeInputValue() { private subscribeInputValue() {
return this.inputControl.valueChanges.subscribe((value) => { return this.inputControl.valueChanges.subscribe(() => {
this.updateSelectable(); this.updateSelectable();
}); });
} }
@AutoUnsubscribe() @AutoUnsubscribe()
private subscribeMyValue() { private subscribeMyValue() {
return this.myControl.valueChanges.subscribe((value) => { return this.myControl.valueChanges.subscribe(() => {
this.updateSelectable(); this.updateSelectable();
}); });
} }

View File

@ -4,7 +4,6 @@ import {
CanActivate, CanActivate,
CanActivateChild, CanActivateChild,
Router, Router,
RouterStateSnapshot,
} from '@angular/router'; } from '@angular/router';
import { isPermissionsArray } from 'picsur-shared/dist/validators/permissions.validator'; import { isPermissionsArray } from 'picsur-shared/dist/validators/permissions.validator';
import { PRouteData } from '../models/dto/picsur-routes.dto'; import { PRouteData } from '../models/dto/picsur-routes.dto';
@ -24,18 +23,15 @@ export class PermissionGuard implements CanActivate, CanActivateChild {
private readonly router: Router, private readonly router: Router,
) {} ) {}
async canActivateChild( async canActivateChild(childRoute: ActivatedRouteSnapshot) {
childRoute: ActivatedRouteSnapshot, return await this.can(childRoute);
state: RouterStateSnapshot,
) {
return await this.can(childRoute, state);
} }
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { async canActivate(route: ActivatedRouteSnapshot) {
return await this.can(route, state); return await this.can(route);
} }
private async can(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { private async can(route: ActivatedRouteSnapshot) {
const requiredPermissions: string[] = this.nestedPermissions(route); const requiredPermissions: string[] = this.nestedPermissions(route);
const allPermissionsArray = await this.staticInfo.getAllPermissions(); const allPermissionsArray = await this.staticInfo.getAllPermissions();

View File

@ -1,9 +1,9 @@
import { TrackingState } from 'picsur-shared/dist/dto/tracking-state.enum'; import { TrackingState } from 'picsur-shared/dist/dto/tracking-state.enum';
export class ServerInfo { export class ServerInfo {
production: boolean = false; production = false;
demo: boolean = false; demo = false;
version: string = '0.0.0'; version = '0.0.0';
host_override?: string; host_override?: string;
tracking: { tracking: {
state: TrackingState; state: TrackingState;

View File

@ -1,5 +1,5 @@
import { FormControl } from '@angular/forms'; import { FormControl } from '@angular/forms';
import { Fail, Failable, FT } from 'picsur-shared/dist/types'; import { Fail, Failable, FT } from 'picsur-shared/dist/types/failable';
import { UserPassModel } from '../forms-dto/userpass.dto'; import { UserPassModel } from '../forms-dto/userpass.dto';
import { import {
CreatePasswordError, CreatePasswordError,

View File

@ -1,5 +1,5 @@
import { FormControl } from '@angular/forms'; import { FormControl } from '@angular/forms';
import { Fail, Failable, FT } from 'picsur-shared/dist/types'; import { Fail, Failable, FT } from 'picsur-shared/dist/types/failable';
import { UserPassModel } from '../forms-dto/userpass.dto'; import { UserPassModel } from '../forms-dto/userpass.dto';
import { Compare } from '../validators/compare.validator'; import { Compare } from '../validators/compare.validator';
import { import {

View File

@ -11,7 +11,7 @@ import {
} from '../validators/user.validator'; } from '../validators/user.validator';
export class UpdateUserControl { export class UpdateUserControl {
private id: string = ''; private id = '';
public username = new FormControl('', UsernameValidators); public username = new FormControl('', UsernameValidators);
public password = new FormControl('', PasswordValidators); public password = new FormControl('', PasswordValidators);
public roles = new FormControl<string[]>([]); public roles = new FormControl<string[]>([]);

View File

@ -4,9 +4,9 @@ import { Pipe, PipeTransform } from '@angular/core';
name: 'truncate', name: 'truncate',
}) })
export class TruncatePipe implements PipeTransform { export class TruncatePipe implements PipeTransform {
transform(text: string, length: number = 32, suffix: string = '...'): string { transform(text: string, length = 32, suffix = '...'): string {
if (text.length > length) { if (text.length > length) {
let truncated: string = text.substring(0, length).trim() + suffix; const truncated: string = text.substring(0, length).trim() + suffix;
return truncated; return truncated;
} }

View File

@ -1,10 +1,10 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { PRoutes } from 'src/app/models/dto/picsur-routes.dto';
import { E401Component } from './401.component'; import { E401Component } from './401.component';
import { E404Component } from './404.component'; import { E404Component } from './404.component';
import { ImageDeleteFailureComponent } from './delete-failure.component'; import { ImageDeleteFailureComponent } from './delete-failure.component';
import { ImageDeleteSuccessComponent } from './delete-success.component'; import { ImageDeleteSuccessComponent } from './delete-success.component';
import { PRoutes } from '../../models/dto/picsur-routes.dto';
const routes: PRoutes = [ const routes: PRoutes = [
{ {

View File

@ -6,19 +6,19 @@ import { EImage } from 'picsur-shared/dist/entities/image.entity';
import { HasFailed } from 'picsur-shared/dist/types/failable'; import { HasFailed } from 'picsur-shared/dist/types/failable';
import { import {
BehaviorSubject, BehaviorSubject,
Observable,
filter, filter,
map, map,
merge, merge,
Observable,
switchMap, switchMap,
timer, timer,
} from 'rxjs'; } from 'rxjs';
import { ImageService } from 'src/app/services/api/image.service'; import { ImageService } from '../../services/api/image.service';
import { UserService } from 'src/app/services/api/user.service'; import { UserService } from '../../services/api/user.service';
import { Logger } from 'src/app/services/logger/logger.service'; import { Logger } from '../../services/logger/logger.service';
import { BootstrapService, BSScreenSize } from 'src/app/util/bootstrap.service'; import { BSScreenSize, BootstrapService } from '../../util/bootstrap.service';
import { DialogService } from 'src/app/util/dialog-manager/dialog.service'; import { DialogService } from '../../util/dialog-manager/dialog.service';
import { ErrorService } from 'src/app/util/error-manager/error.service'; import { ErrorService } from '../../util/error-manager/error.service';
@Component({ @Component({
templateUrl: './images.component.html', templateUrl: './images.component.html',
@ -39,8 +39,8 @@ export class ImagesComponent implements OnInit {
); );
} }
page: number = 1; page = 1;
pages: number = 1; pages = 1;
constructor( constructor(
private readonly route: ActivatedRoute, private readonly route: ActivatedRoute,
@ -110,7 +110,7 @@ export class ImagesComponent implements OnInit {
merge( merge(
...images ...images
.filter((i) => i.expires_at !== null) .filter((i) => i.expires_at !== null)
.map((i) => timer(i.expires_at!).pipe(map(() => i))), .map((i) => timer(i.expires_at ?? new Date(0)).pipe(map(() => i))),
), ),
), ),
) as Observable<EImage>; ) as Observable<EImage>;

View File

@ -4,12 +4,12 @@ import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MomentModule } from 'ngx-moment'; import { MomentModule } from 'ngx-moment';
import { MasonryModule } from 'src/app/components/masonry/masonry.module'; import { MasonryModule } from '../../components/masonry/masonry.module';
import { PaginatorModule } from 'src/app/components/paginator/paginator.module'; import { PaginatorModule } from '../../components/paginator/paginator.module';
import { PicsurImgModule } from 'src/app/components/picsur-img/picsur-img.module'; import { PicsurImgModule } from '../../components/picsur-img/picsur-img.module';
import { PipesModule } from 'src/app/pipes/pipes.module'; import { PipesModule } from '../../pipes/pipes.module';
import { DialogManagerModule } from 'src/app/util/dialog-manager/dialog-manager.module'; import { DialogManagerModule } from '../../util/dialog-manager/dialog-manager.module';
import { ErrorManagerModule } from 'src/app/util/error-manager/error-manager.module'; import { ErrorManagerModule } from '../../util/error-manager/error-manager.module';
import { ImagesComponent } from './images.component'; import { ImagesComponent } from './images.component';
import { ImagesRoutingModule } from './images.routing.module'; import { ImagesRoutingModule } from './images.routing.module';

View File

@ -1,9 +1,9 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { Permission } from 'picsur-shared/dist/dto/permissions.enum'; import { Permission } from 'picsur-shared/dist/dto/permissions.enum';
import { PermissionGuard } from 'src/app/guards/permission.guard';
import { PRoutes } from 'src/app/models/dto/picsur-routes.dto';
import { ImagesComponent } from './images.component'; import { ImagesComponent } from './images.component';
import { PermissionGuard } from '../../guards/permission.guard';
import { PRoutes } from '../../models/dto/picsur-routes.dto';
const routes: PRoutes = [ const routes: PRoutes = [
{ {

View File

@ -1,11 +1,11 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { Fail, FT, HasFailed } from 'picsur-shared/dist/types'; import { Fail, FT, HasFailed } from 'picsur-shared/dist/types/failable';
import { ProcessingViewMeta } from 'src/app/models/dto/processing-view-meta.dto'; import { ProcessingViewMeta } from '../../models/dto/processing-view-meta.dto';
import { ApiService } from 'src/app/services/api/api.service'; import { ApiService } from '../../services/api/api.service';
import { ImageService } from 'src/app/services/api/image.service'; import { ImageService } from '../../services/api/image.service';
import { Logger } from 'src/app/services/logger/logger.service'; import { Logger } from '../../services/logger/logger.service';
import { ErrorService } from 'src/app/util/error-manager/error.service'; import { ErrorService } from '../../util/error-manager/error.service';
@Component({ @Component({
templateUrl: './processing.component.html', templateUrl: './processing.component.html',

View File

@ -1,9 +1,9 @@
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { ErrorManagerModule } from 'src/app/util/error-manager/error-manager.module';
import { ProcessingComponent } from './processing.component'; import { ProcessingComponent } from './processing.component';
import { ProcessingRoutingModule } from './processing.routing.module'; import { ProcessingRoutingModule } from './processing.routing.module';
import { ErrorManagerModule } from '../../util/error-manager/error-manager.module';
@NgModule({ @NgModule({
declarations: [ProcessingComponent], declarations: [ProcessingComponent],

View File

@ -1,7 +1,7 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { PRoutes } from 'src/app/models/dto/picsur-routes.dto';
import { ProcessingComponent } from './processing.component'; import { ProcessingComponent } from './processing.component';
import { PRoutes } from '../../models/dto/picsur-routes.dto';
const routes: PRoutes = [ const routes: PRoutes = [
{ {

View File

@ -1,5 +1,5 @@
<mat-form-field class="editfield" appearance="outline" color="primary"> <mat-form-field class="editfield" appearance="outline" color="primary">
<mat-label>Name</mat-label> <mat-label>Name</mat-label>
<input matInput [formControl]="field" (change)="update($event)" /> <input matInput [formControl]="field" (change)="update()" />
<mat-error *ngIf="field.invalid">{{ getErrorMessage() }}</mat-error> <mat-error *ngIf="field.invalid">{{ getErrorMessage() }}</mat-error>
</mat-form-field> </mat-form-field>

View File

@ -1,6 +1,6 @@
import { Component, EventEmitter, Input, Output } from '@angular/core'; import { Component, EventEmitter, Input, Output } from '@angular/core';
import { FormControl, Validators } from '@angular/forms'; import { FormControl, Validators } from '@angular/forms';
import { Logger } from 'src/app/services/logger/logger.service'; import { Logger } from '../../../../services/logger/logger.service';
@Component({ @Component({
selector: 'app-settings-apikey-editor', selector: 'app-settings-apikey-editor',
@ -22,7 +22,7 @@ export class SettingsApiKeyEditorComponent {
Validators.maxLength(255), Validators.maxLength(255),
]); ]);
async update(event: Event) { async update() {
if (this.field.invalid) { if (this.field.invalid) {
return; return;
} }

View File

@ -2,16 +2,16 @@ import { Component, OnInit, ViewChild } from '@angular/core';
import { MatPaginator, PageEvent } from '@angular/material/paginator'; import { MatPaginator, PageEvent } from '@angular/material/paginator';
import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator'; import { AutoUnsubscribe } from 'ngx-auto-unsubscribe-decorator';
import { EApiKey } from 'picsur-shared/dist/entities/apikey.entity'; import { EApiKey } from 'picsur-shared/dist/entities/apikey.entity';
import { FT, Fail, HasFailed } from 'picsur-shared/dist/types'; import { FT, Fail, HasFailed } from 'picsur-shared/dist/types/failable';
import { BehaviorSubject, Subject } from 'rxjs'; import { BehaviorSubject, Subject } from 'rxjs';
import { ApiKeysService } from 'src/app/services/api/apikeys.service'; import { ApiKeysService } from '../../../services/api/apikeys.service';
import { UserService } from 'src/app/services/api/user.service'; import { UserService } from '../../../services/api/user.service';
import { Logger } from 'src/app/services/logger/logger.service'; import { Logger } from '../../../services/logger/logger.service';
import { BootstrapService } from 'src/app/util/bootstrap.service'; import { BootstrapService } from '../../../util/bootstrap.service';
import { ClipboardService } from 'src/app/util/clipboard.service'; import { ClipboardService } from '../../../util/clipboard.service';
import { DialogService } from 'src/app/util/dialog-manager/dialog.service'; import { DialogService } from '../../../util/dialog-manager/dialog.service';
import { ErrorService } from 'src/app/util/error-manager/error.service'; import { ErrorService } from '../../../util/error-manager/error.service';
import { Throttle } from 'src/app/util/throttle'; import { Throttle } from '../../../util/throttle';
@Component({ @Component({
templateUrl: './settings-apikeys.component.html', templateUrl: './settings-apikeys.component.html',
@ -31,7 +31,7 @@ export class SettingsApiKeysComponent implements OnInit {
public dataSubject = new BehaviorSubject<EApiKey[]>([]); public dataSubject = new BehaviorSubject<EApiKey[]>([]);
public updateSubject = new Subject<PageEvent>(); public updateSubject = new Subject<PageEvent>();
public totalApiKeys: number = 0; public totalApiKeys = 0;
@ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatPaginator) paginator: MatPaginator;
@ -136,7 +136,7 @@ export class SettingsApiKeysComponent implements OnInit {
return this.updateSubject return this.updateSubject
.pipe(Throttle(500)) .pipe(Throttle(500))
.subscribe(async (pageEvent: PageEvent) => { .subscribe(async (pageEvent: PageEvent) => {
let success = await this.fetchApiKeys( const success = await this.fetchApiKeys(
pageEvent.pageSize, pageEvent.pageSize,
pageEvent.pageIndex, pageEvent.pageIndex,
); );

Some files were not shown because too many files have changed in this diff Show More