Move server directory outside of frontend src

This commit is contained in:
jeffvli
2022-10-25 16:52:45 -07:00
parent 863dce88b7
commit 0438f2d5f2
105 changed files with 16946 additions and 6901 deletions
@@ -0,0 +1,22 @@
import { z } from 'zod';
import { idValidation, paginationValidation } from './shared.validation';
export const list = {
body: z.object({}),
params: z.object({ ...idValidation('serverId') }),
query: z.object({
...paginationValidation,
serverFolderIds: z.string().min(1),
}),
};
export const detail = {
body: z.object({}),
params: z.object({ ...idValidation('id') }),
query: z.object({}),
};
export const albumArtistsValidation = {
detail,
list,
};
+53
View File
@@ -0,0 +1,53 @@
import { z } from 'zod';
import { AlbumSort } from '@helpers/albums.helpers';
import {
idValidation,
orderByValidation,
paginationValidation,
serverFolderIdValidation,
serverUrlIdValidation,
} from './shared.validation';
const list = {
body: z.object({}),
params: z.object({ ...idValidation('serverId') }),
query: z.object({
...paginationValidation,
...serverFolderIdValidation,
...orderByValidation,
...serverUrlIdValidation,
sortBy: z.nativeEnum(AlbumSort),
}),
};
const detail = {
body: z.object({}),
params: z.object({
...idValidation('albumId'),
...idValidation('serverId'),
}),
query: z.object({
...serverUrlIdValidation,
}),
};
const detailSongList = {
body: z.object({}),
params: z.object({
...idValidation('albumId'),
...idValidation('serverId'),
}),
query: z.object({
...paginationValidation,
...serverFolderIdValidation,
...orderByValidation,
...serverUrlIdValidation,
sortBy: z.nativeEnum(AlbumSort),
}),
};
export const albumsValidation = {
detail,
detailSongList,
list,
};
+30
View File
@@ -0,0 +1,30 @@
import { z } from 'zod';
import { AlbumSort } from '@helpers/albums.helpers';
import {
idValidation,
orderByValidation,
paginationValidation,
serverFolderIdValidation,
} from './shared.validation';
const list = {
body: z.object({}),
params: z.object({}),
query: z.object({
...paginationValidation,
...serverFolderIdValidation,
...orderByValidation,
sortBy: z.nativeEnum(AlbumSort),
}),
};
const detail = {
body: z.object({}),
params: z.object({ ...idValidation('id') }),
query: z.object({}),
};
export const artistsValidation = {
detail,
list,
};
+33
View File
@@ -0,0 +1,33 @@
import { z } from 'zod';
const login = {
body: z.object({
password: z.string(),
username: z.string(),
}),
params: z.object({}),
query: z.object({}),
};
const register = {
body: z.object({
password: z.string().min(6).max(255),
username: z.string().min(4).max(26),
}),
params: z.object({}),
query: z.object({}),
};
const refresh = {
body: z.object({
refreshToken: z.string(),
}),
params: z.object({}),
query: z.object({}),
};
export const authValidation = {
login,
refresh,
register,
};
+19
View File
@@ -0,0 +1,19 @@
import { albumArtistsValidation } from './album-artists.validation';
import { albumsValidation } from './albums.validation';
import { artistsValidation } from './artists.validation';
import { authValidation } from './auth.validation';
import { serversValidation } from './servers.validation';
import { songsValidation } from './songs.validation';
import { usersValidation } from './users.validation';
export { validateRequest, TypedRequest } from './shared.validation';
export const validation = {
albumArtists: albumArtistsValidation,
albums: albumsValidation,
artists: artistsValidation,
auth: authValidation,
servers: serversValidation,
songs: songsValidation,
users: usersValidation,
};
+154
View File
@@ -0,0 +1,154 @@
import { ServerType } from '@prisma/client';
import { z } from 'zod';
import { idValidation } from './shared.validation';
const detail = {
body: z.object({}),
params: z.object({ ...idValidation('serverId') }),
query: z.object({}),
};
const list = {
body: z.object({}),
params: z.object({}),
query: z.object({}),
};
const deleteServer = {
body: z.object({}),
params: z.object({ ...idValidation('serverId') }),
query: z.object({}),
};
const update = {
body: z.object({
legacy: z.boolean().optional(),
name: z.string().optional(),
password: z.string().optional(),
type: z.nativeEnum(ServerType),
url: z.string().optional(),
username: z.string().optional(),
}),
params: z.object({ ...idValidation('serverId') }),
query: z.object({}),
};
const create = {
body: z.object({
legacy: z.boolean().optional(),
name: z.string(),
password: z.string(),
type: z.enum([
ServerType.JELLYFIN,
ServerType.SUBSONIC,
ServerType.NAVIDROME,
]),
url: z.string(),
username: z.string(),
}),
params: z.object({}),
query: z.object({}),
};
const scan = {
body: z.object({ serverFolderId: z.string().array().optional() }),
params: z.object({ ...idValidation('serverId') }),
query: z.object({}),
};
const refresh = {
body: z.object({}),
params: z.object({ ...idValidation('serverId') }),
query: z.object({}),
};
const createCredential = {
body: z.object({ credential: z.string(), username: z.string() }),
params: z.object({ ...idValidation('serverId') }),
query: z.object({}),
};
const getCredentialDetail = {
body: z.object({}),
params: z.object({ ...idValidation('serverId') }),
query: z.object({}),
};
const deleteCredential = {
body: z.object({}),
params: z.object({
...idValidation('serverId'),
...idValidation('credentialId'),
}),
query: z.object({}),
};
const enableCredential = {
body: z.object({}),
params: z.object({
...idValidation('serverId'),
...idValidation('credentialId'),
}),
query: z.object({}),
};
const disableCredential = {
body: z.object({}),
params: z.object({
...idValidation('serverId'),
...idValidation('credentialId'),
}),
query: z.object({}),
};
const createUrl = {
body: z.object({ url: z.string() }),
params: z.object({ ...idValidation('serverId') }),
query: z.object({}),
};
const deleteUrl = {
body: z.object({}),
params: z.object({
...idValidation('serverId'),
...idValidation('urlId'),
}),
query: z.object({}),
};
const enableUrl = {
body: z.object({}),
params: z.object({
...idValidation('serverId'),
...idValidation('urlId'),
}),
query: z.object({}),
};
const disableUrl = {
body: z.object({}),
params: z.object({
...idValidation('serverId'),
...idValidation('urlId'),
}),
query: z.object({}),
};
export const serversValidation = {
create,
createCredential,
createUrl,
deleteCredential,
deleteServer,
deleteUrl,
detail,
disableCredential,
disableUrl,
enableCredential,
enableUrl,
getCredentialDetail,
list,
refresh,
scan,
update,
};
+130
View File
@@ -0,0 +1,130 @@
import { Request, RequestHandler } from 'express';
import { z, ZodError, ZodSchema } from 'zod';
import { SortOrder } from '@/types/types';
import { ApiError } from '@/utils';
// Modified from zod-express-middleware: https://github.com/Aquila169/zod-express-middleware
export type TypedRequest<
S extends {
body: z.AnyZodObject;
params: z.AnyZodObject;
query: z.AnyZodObject;
}
> = Request<z.infer<S['params']>, any, z.infer<S['body']>, z.infer<S['query']>>;
export enum ValidationType {
BODY = 'Body',
PARAMS = 'Params',
QUERY = 'Query',
}
type RequestValidation<TParams, TQuery, TBody> = {
body?: ZodSchema<TBody>;
params?: ZodSchema<TParams>;
query?: ZodSchema<TQuery>;
};
type ErrorListItem = {
errors: ZodError<any>;
type: ValidationType;
value: string;
};
const getErrorValue = (object: any, error: ZodError<any>) => {
const e = error.errors[0];
if (e.code === z.ZodIssueCode.invalid_type) {
return e.expected;
}
return object[e.path[0]][e.path[1]];
};
export const validateRequest: <TParams = any, TQuery = any, TBody = any>(
schemas: RequestValidation<TParams, TQuery, TBody>
) => RequestHandler<TParams, any, TBody, TQuery> =
({ params, query, body }) =>
(req, _res, next) => {
const errors: Array<ErrorListItem> = [];
if (params) {
const parsed = params.safeParse(req.params);
if (!parsed.success) {
errors.push({
errors: parsed.error,
type: ValidationType.PARAMS,
value: getErrorValue(req.params, parsed.error),
});
}
}
if (query) {
const parsed = query.safeParse(req.query);
if (!parsed.success) {
const value = getErrorValue(req.query, parsed.error);
errors.push({
errors: parsed.error,
type: ValidationType.QUERY,
value,
});
}
}
if (body) {
const parsed = body.safeParse(req.body);
if (!parsed.success) {
errors.push({
errors: parsed.error,
type: ValidationType.BODY,
value: getErrorValue(req.body, parsed.error),
});
}
}
if (errors.length > 0) {
const message = JSON.stringify(
[
// `(${errors[0].type})`,
`(${errors[0].type}: ${errors[0].errors.issues[0].path[0]})`,
errors[0].value && `[${errors[0].value}]`,
errors[0].errors.issues[0].message,
]
.filter((x) => x)
.join(' ')
);
throw ApiError.badRequest(message);
}
return next();
};
// const requiredErrorMessage = (
// type: 'Query' | 'Body' | 'Params',
// key: string
// ) => {
// return `(${type}) [${key}] Required`;
// };
export const paginationValidation = {
skip: z.string().refine((value) => {
const parsed = Number(value);
return !Number.isNaN(parsed) && parsed >= 0;
}),
take: z.string().refine((value) => {
const parsed = Number(value);
return !Number.isNaN(parsed) && parsed >= 0;
}),
};
export const serverUrlIdValidation = {
serverUrlId: z.optional(z.string().uuid()),
};
export const idValidation = (property: string) => {
return { [property]: z.string().uuid() };
};
export const serverFolderIdValidation = {
serverFolderId: z.optional(z.string().uuid().array()),
};
export const orderByValidation = {
orderBy: z.nativeEnum(SortOrder),
};
+22
View File
@@ -0,0 +1,22 @@
import { z } from 'zod';
import {
idValidation,
paginationValidation,
serverFolderIdValidation,
} from './shared.validation';
const list = {
body: z.object({}),
params: z.object({ ...idValidation('serverId') }),
query: z.object({
...paginationValidation,
...serverFolderIdValidation,
albumIds: z.optional(z.string()),
artistIds: z.optional(z.string()),
songIds: z.optional(z.string()),
}),
};
export const songsValidation = {
list,
};
+12
View File
@@ -0,0 +1,12 @@
import { z } from 'zod';
import { idValidation } from './shared.validation';
const detail = {
body: z.object({}),
params: z.object({ ...idValidation('id') }),
query: z.object({}),
};
export const usersValidation = {
detail,
};