Skip to content

Commit

Permalink
refactor(app): reworked everything to use the new systems, endpoints,…
Browse files Browse the repository at this point in the history
… parsing and deleted unused stuff
  • Loading branch information
ADRFranklin committed May 10, 2024
1 parent 9de603d commit 5ef7647
Show file tree
Hide file tree
Showing 486 changed files with 68,421 additions and 13,288 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ data/
db/
logs/
dist/
tmp/
.eslintcache
*.log
.DS_Store
Expand Down
34 changes: 24 additions & 10 deletions .vscode/resources.code-snippets
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
},
"Generates a new resource mapper class": {
"scope": "typescript",
"prefix": "grmc",
"prefix": "grm",
"body": [
"import { Mapper } from \"@/infra/entity/mapper\";",
"import { Service } from \"diod\";",
Expand Down Expand Up @@ -100,9 +100,9 @@
],
"description": "Generates a new mapper class"
},
"Generates a new resource mongoose database repository": {
"Generates a new resource database repository": {
"scope": "typescript",
"prefix": "grmdr",
"prefix": "grdr",
"body": [
"import { Service } from 'diod';",
"",
Expand Down Expand Up @@ -144,7 +144,7 @@
},
"Generates a new resource repository class": {
"scope": "typescript",
"prefix": "grrc",
"prefix": "grr",
"body": [
"import { MongooseRepository } from \"@/infra/database/repository\";",
"import { Service } from \"diod\";",
Expand Down Expand Up @@ -184,17 +184,24 @@
},
"Generates a new resource mongoose schema": {
"scope": "typescript",
"prefix": "grms",
"prefix": "grs",
"body": [
"import { Schema } from 'mongoose';",
"",
"import { BaseEntityProps } from '@/infra/entity/entity';",
"",
"import { ${1}Props } from './types';",
"",
"/**",
" * Represents the properties of a ${1} schema.",
" */",
"export type ${1}SchemaProps = BaseEntityProps & ${1}Props;",
"",
"/**",
" * Represents the ${1} schema.",
" */",
"export const ${1}Schema = new Schema<${1}SchemaProps>({",
" id: { type: String, required: true },",
" id: { type: String, required: true, unique: true, index: true },",
" // TODO: fill in the rest",
" createdAt: { type: Date, required: true },",
" updatedAt: { type: Date, required: true },",
Expand All @@ -204,21 +211,28 @@
"description": "Generates a new mongoose schema"
},
"Generates resource types": {
"scope": "typescript",
"prefix": "grt",
"body": [
"import { Override } from '@/utils/override';",
"",
"/**",
" * Represents the properties of a ${1}.",
" */",
"export type ${1}Props = {",
" // TODO: add fields here",
" // TODO: add fields",
"};",
"",
"/**",
" * Represents the properties for creating a ${1}.",
" */",
"export type Create${1}Props = ${1}Props & {",
" // TODO: add additional fields",
"};"
"export type Create${1}Props = Override<",
" ${1}Props,",
" {",
" // TODO: add fields to override",
" }",
">;",
""
],
"description": "Generates resource types"
}
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
20 changes: 20 additions & 0 deletions pkg/api/.swcrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"jsc": {
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"target": "es2021",
"keepClassNames": true,
"loose": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"module": {
"type": "commonjs"
},
"sourceMaps": true
}
10 changes: 8 additions & 2 deletions pkg/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@
"test": "ts-mocha --paths src/**/*.test.ts",
"depcheck": "depcheck",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint --fix . --ext .ts"
"lint:fix": "eslint --fix . --ext .ts",
"generate:client-tmdb": "npx @hey-api/openapi-ts -i \"https://developer.themoviedb.org/openapi/64542913e1f86100738e227f\" -o \"./src/infra/tmdb/client\" -c axios --name TheMovieDatabase --schemas true --services true --useOptions",
"generate:client-plex": "npx @hey-api/openapi-ts -i \"https://raw.githubusercontent.com/LukeHagar/plex-api-spec/main/plex-media-server-spec-dereferenced.yaml\" -o \"./src/infra/plex\" -c axios --name PlexClient --schemas true --services true --useOptions",
"generate:client-plextv": "npx @hey-api/openapi-ts -i \"https://raw.githubusercontent.com/LukeHagar/plex-api-spec/main/plex-tv-spec-dereferenced.yaml\" -o \"./src/infra/plextv\" -c axios --name PlexTvClient --schemas true --services true --useOptions",
"generate:client-radarr": "npx @hey-api/openapi-ts -i \"https://raw.githubusercontent.com/Radarr/Radarr/develop/src/Radarr.Api.V3/openapi.json\" -o \"./src/infra/servarr/radarr\" -c axios --name RadarrV3Client --schemas true --services true --useOptions",
"generate:client-sonarr": "npx @hey-api/openapi-ts -i \"https://raw.githubusercontent.com/Sonarr/Sonarr/develop/src/Sonarr.Api.V3/openapi.json\" -o \"./src/infra/servarr/sonarr\" -c axios --name SonarrV3Client --schemas true --services true --useOptions"
},
"author": "",
"license": "MIT",
Expand All @@ -32,7 +37,7 @@
"bcryptjs": "2.4.3",
"bluebird": "^3.7.2",
"bson": "^5.0.1",
"cache-manager": "5.2.0",
"cache-manager": "5.5.2",
"diod": "^2.0.0",
"dotenv": "^16.0.3",
"event-dispatch": "^0.4.1",
Expand Down Expand Up @@ -70,6 +75,7 @@
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.0",
"sanitize-filename": "^1.6.3",
"ts-migrate-mongoose": "^3.6.4",
"ts-node": "^10.9.1",
"tsc-alias": "^1.7.0",
"tsyringe": "^4.7.0",
Expand Down
26 changes: 26 additions & 0 deletions pkg/api/src/api/http/responseHandler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
import { StatusCodes } from 'http-status-codes';
import { DefaultContext } from 'koa';

declare global {
namespace Koa {
interface Context {
success: ({
statusCode,
data,
}: {
statusCode: number;
data?: any;
}) => void;
error: ({
statusCode,
code,
message,
}: {
statusCode: number;
code: string;
message: string | undefined;
}) => void;
ok: (params: any) => void;
created: (params: any) => void;
accepted: (params: any) => void;
}
}
}

export default () => async (ctx: DefaultContext, next: () => Promise<any>) => {
ctx.success = ({ statusCode, data = undefined }: any) => {
const status = 'success';
Expand Down
13 changes: 8 additions & 5 deletions pkg/api/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,22 @@ import cors from '@/api/middleware/cors';
import errorHandler from '@/api/middleware/errorHandling';
import api from '@/api/routes/api';
import web from '@/api/routes/web';
import { config } from '@/config/index';
import {
HTTP_ADDR,
HTTP_BASE_PATH,
HTTP_PORT,
HTTP_TRUSTED_PROXIES,
} from '@/infra/config/env';
import { getFromContainer } from '@/infra/container/container';
import { SettingsService } from '@/services/settings/settings';

import responseHandler from './http/responseHandler';
import logging from './middleware/logging';
import options from './middleware/options';

const routes = (): Koa => {
const routes = (keys: string[]): Koa => {
const app = new Koa();
app.keys = keys;

// web/frontend/reac
web(app);
Expand All @@ -35,13 +37,14 @@ const routes = (): Koa => {
return app;
};

export const createKoaServer = () => {
export const createKoaServer = async () => {
let server: Server<typeof IncomingMessage, typeof ServerResponse>;

const app = new Koa();
const settings = await getFromContainer(SettingsService).getSettings();

// Set security keys
app.keys = config.get('petio.keys');
app.keys = settings.appKeys;

// Enable trusted proxies
if (HTTP_TRUSTED_PROXIES.length > 0) {
Expand All @@ -60,7 +63,7 @@ export const createKoaServer = () => {
].forEach((middleware) => app.use(middleware));

// Mount endpoints
app.use(mount(HTTP_BASE_PATH, routes()));
app.use(mount(HTTP_BASE_PATH, routes(settings.appKeys)));

let serverShuttingDown: any;

Expand Down
14 changes: 9 additions & 5 deletions pkg/api/src/api/middleware/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import * as HttpStatus from 'http-status-codes';
import jwt from 'jsonwebtoken';
import { Context, Next } from 'koa';

import { getFromContainer } from '@/infra/container/container';
import loggerMain from '@/infra/logger/logger';
import { UserModel } from '@/models/user';
import { UserMapper } from '@/resources/user/mapper';
import { UserRepository } from '@/resources/user/repository';

const logger = loggerMain.child({ module: 'middleware.auth' });

Expand Down Expand Up @@ -37,12 +39,14 @@ export async function authenticate(ctx: Context) {
removeCookie(ctx);
throw new Error(`id missing from jwt data`);
}

const resp = await UserModel.findOne({ _id: (jwtData as any).id }).exec();
if (!resp) {
const userRepo = await getFromContainer(UserRepository).findOne({
_id: jwtData.id,
});
if (userRepo.isNone()) {
throw new Error('no user found');
}
userData = resp.toJSON();
const userResult = userRepo.unwrap();
userData = getFromContainer(UserMapper).toResponse(userResult);
} catch (error) {
logger.debug('user not found in db', error);
throw new Error(`AUTH: User not found in DB - route ${ctx.path}`);
Expand Down
53 changes: 30 additions & 23 deletions pkg/api/src/api/middleware/errorHandling.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,39 @@
import { StatusCodes } from 'http-status-codes';
import { DefaultContext } from 'koa';
import HttpError from "../http/errors/http";
import NotFound from "../http/errors/notFound";

import { getFromContainer } from '@/infra/container/container';
import { Logger } from '@/infra/logger/logger';

import HttpError from '../http/errors/http';
import NotFound from '../http/errors/notFound';

export default () => async (ctx: DefaultContext, next: () => Promise<any>) => {
try {
await next();
await next();

if (!ctx.body
&& (!ctx.status
|| ctx.status === StatusCodes.NOT_FOUND
|| ctx.status === StatusCodes.METHOD_NOT_ALLOWED)) {
throw new NotFound();
}
if (
!ctx.body &&
(!ctx.status ||
ctx.status === StatusCodes.NOT_FOUND ||
ctx.status === StatusCodes.METHOD_NOT_ALLOWED)
) {
throw new NotFound();
}
} catch (err) {
if (err instanceof HttpError) {
ctx.error({
statusCode: err.statusCode,
code: err.code,
message: err.message,
});
} else {
ctx.error({
status: StatusCodes.INTERNAL_SERVER_ERROR,
code: 'UNKNOWN_ERROR',
message: 'The server encountered an unknown error.',
});
}
ctx.app.emit('error', err, ctx);
getFromContainer(Logger).debug(`http error`, err);
if (err instanceof HttpError) {
ctx.error({
statusCode: err.statusCode,
code: err.code,
message: err.message,
});
} else {
ctx.error({
status: StatusCodes.INTERNAL_SERVER_ERROR,
code: 'UNKNOWN_ERROR',
message: `The server encountered an unknown error: ${err.message}`,
});
}
ctx.app.emit('error', err, ctx);
}
};
11 changes: 6 additions & 5 deletions pkg/api/src/api/middleware/setup.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { StatusCodes } from 'http-status-codes';
import { Context, Next } from 'koa';

import { HasConfig } from '@/config/index';
import { getFromContainer } from '@/infra/container/container';
import { SettingsService } from '@/services/settings/settings';

export default async (ctx: Context, next: Next) => {
const exists = await HasConfig();
if (!exists) {
const {path} = ctx;
const settings = await getFromContainer(SettingsService).getSettings();
if (!settings.initialSetup) {
const { path } = ctx;
if (path.startsWith('/api')) {
if (
path !== '/' &&
!path.includes('/api/setup') &&
path !== '/api/config'
) {
ctx.status = StatusCodes.UNAUTHORIZED;
ctx.status = StatusCodes.LOCKED;
ctx.body = 'you need to complete setup to access this url';
return;
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/api/src/api/routes/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import show from '@/api/routes/show';
import top from '@/api/routes/top';
import trending from '@/api/routes/trending';
import user from '@/api/routes/user';
import { config as conf } from '@/config/index';

const api = new Router({ prefix: '/api' });

Expand All @@ -41,7 +40,8 @@ export default (app: Koa, subpath: string) => {
app.use(setupMiddleware);
api.use(
jwt({
secret: conf.get('petio.keys'),
// TODO: fix this and generate keys again
secret: app.keys as string[],
cookie: 'petio_jwt',
debug: true,
}).unless({
Expand Down
4 changes: 2 additions & 2 deletions pkg/api/src/api/routes/batch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { movieLookup } from '@/services/tmdb/movie';
import { showLookup } from '@/services/tmdb/show';

const handleTv = async (ctx: Context) => {
const {ids} = ctx.request.body;
const { ids } = ctx.request.body;
const min = ctx.request.body.min === undefined ? true : ctx.request.body.min;
const output = await Promise.all(
ids.map(async (id) => {
Expand All @@ -20,7 +20,7 @@ const handleTv = async (ctx: Context) => {
};

const handleMovie = async (ctx: Context) => {
const {ids} = ctx.request.body;
const { ids } = ctx.request.body;
const min = ctx.request.body.min === undefined ? true : ctx.request.body.min;
const output = await Promise.all(
ids.map(async (id): Promise<any> => {
Expand Down
Loading

0 comments on commit 5ef7647

Please sign in to comment.