Added Ts.ED

This commit is contained in:
2022-09-04 21:00:45 +02:00
parent d0b69d7ae1
commit f4162f7f06
45 changed files with 4046 additions and 0 deletions

54
backend/src/Server.ts Normal file
View File

@@ -0,0 +1,54 @@
import {join} from "path";
import {Configuration, Inject} from "@tsed/di";
import {PlatformApplication} from "@tsed/common";
import "@tsed/platform-express"; // /!\ keep this import
import bodyParser from "body-parser";
import compress from "compression";
import cookieParser from "cookie-parser";
import methodOverride from "method-override";
import cors from "cors";
import "@tsed/ajv";
import "@tsed/typegraphql";
import "./datasources/index";
import "./resolvers/index";
import {config} from "./config/index";
import * as rest from "./controllers/rest/index";
@Configuration({
...config,
acceptMimes: ["application/json"],
httpPort: process.env.PORT || 8083,
httpsPort: false, // CHANGE
componentsScan: false,
mount: {
"/rest": [
...Object.values(rest)
]
},
middlewares: [
cors(),
cookieParser(),
compress({}),
methodOverride(),
bodyParser.json(),
bodyParser.urlencoded({
extended: true
})
],
views: {
root: join(process.cwd(), "../views"),
extensions: {
ejs: "ejs"
}
},
exclude: [
"**/*.spec.ts"
]
})
export class Server {
@Inject()
protected app: PlatformApplication;
@Configuration()
protected settings: Configuration;
}

View File

@@ -0,0 +1,7 @@
import dotenv from "dotenv"
export const envs = {
...process.env,
...dotenv.config().parsed
};
export const isProduction = process.env.NODE_ENV === "production";

View File

@@ -0,0 +1,18 @@
import {readFileSync} from "fs";
import {envs} from "./envs/index";
import loggerConfig from "./logger/index";
const pkg = JSON.parse(readFileSync("./package.json", {encoding: "utf8"}));
export const config: Partial<TsED.Configuration> = {
version: pkg.version,
envs,
logger: loggerConfig,
graphql: {
default: {
path: "/graphql",
buildSchemaOptions: {
}
}
},
// additional shared configuration
};

View File

@@ -0,0 +1,24 @@
import {$log, PlatformLoggerSettings} from "@tsed/common";
import {isProduction} from "../envs/index";
if (isProduction) {
$log.appenders.set("stdout", {
type: "stdout",
levels: ["info", "debug"],
layout: {
type: "json"
}
});
$log.appenders.set("stderr", {
levels: ["trace", "fatal", "error", "warn"],
type: "stderr",
layout: {
type: "json"
}
});
}
export default <PlatformLoggerSettings> {
disableRoutesSummary: isProduction
};

View File

@@ -0,0 +1,10 @@
import {Controller} from "@tsed/di";
import {Get} from "@tsed/schema";
@Controller("/hello-world")
export class HelloWorldController {
@Get("/")
get() {
return "hello";
}
}

View File

@@ -0,0 +1,18 @@
import {DataSourceService} from "@tsed/typegraphql";
import {RESTDataSource} from "apollo-datasource-rest";
@DataSourceService()
export class MyDataSource extends RESTDataSource {
constructor() {
super();
this.baseURL = "http://localhost:8001";
}
willSendRequest(request: any) {
request.headers.set("Authorization", this.context.token);
}
getMyData(id: string) {
return this.get(`/rest/calendars/${id}`);
}
}

View File

@@ -0,0 +1 @@
export * from "./MyDataSource";

18
backend/src/index.ts Normal file
View File

@@ -0,0 +1,18 @@
import {$log} from "@tsed/common";
import { PlatformExpress } from "@tsed/platform-express";
import {Server} from "./Server";
async function bootstrap() {
try {
const platform = await PlatformExpress.bootstrap(Server);
await platform.listen();
process.on("SIGINT", () => {
platform.stop();
});
} catch (error) {
$log.error({event: "SERVER_BOOTSTRAP_ERROR", message: error.message, stack: error.stack});
}
}
bootstrap();

View File

@@ -0,0 +1,3 @@
export * from "./recipes/Recipe";
export * from "./recipes/RecipeNotFoundError";
export * from "./recipes/RecipeResolver";

View File

@@ -0,0 +1,27 @@
import {Field, ID, ObjectType} from "type-graphql";
@ObjectType({description: "Object representing cooking recipe"})
export class Recipe {
@Field((type) => ID)
id: string;
@Field()
title: string;
@Field({nullable: true})
description?: string;
@Field()
creationDate: Date;
@Field((type) => [String])
ingredients: string[];
constructor(options: Partial<Recipe> = {}) {
options.id && (this.id = options.id);
options.title && (this.title = options.title);
options.description && (this.description = options.description);
options.creationDate && (this.creationDate = options.creationDate);
options.ingredients && (this.ingredients = options.ingredients);
}
}

View File

@@ -0,0 +1,7 @@
import {NotFound} from "@tsed/exceptions";
export class RecipeNotFoundError extends NotFound {
constructor(private id: string) {
super("Recipe not found");
}
}

View File

@@ -0,0 +1,26 @@
import {ResolverService} from "@tsed/typegraphql";
import {Arg, Query} from "type-graphql";
import {RecipeService} from "../../services/RecipeService";
import {Recipe} from "./Recipe";
import {RecipeNotFoundError} from "./RecipeNotFoundError";
@ResolverService(Recipe)
export class RecipeResolver {
constructor(private recipeService: RecipeService) {}
@Query((returns) => Recipe)
async recipe(@Arg("id") id: string) {
const recipe = await this.recipeService.findById(id);
if (recipe === undefined) {
throw new RecipeNotFoundError(id);
}
return recipe;
}
@Query((returns) => [Recipe], {description: "Get all the recipes from around the world "})
async recipes(): Promise<Recipe[]> {
return this.recipeService.findAll({});
}
}

View File

@@ -0,0 +1,13 @@
import {Injectable} from "@tsed/di";
import {Recipe} from "../resolvers";
@Injectable()
export class RecipeService {
async findById(id: string) {
return new Recipe({id})
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async findAll(query: any) {
return []
}
}