Skip to content

Commit

Permalink
Initial Setup
Browse files Browse the repository at this point in the history
  • Loading branch information
henriqueleite42 committed Oct 18, 2021
1 parent 20cb78d commit 3b54027
Show file tree
Hide file tree
Showing 43 changed files with 920 additions and 607 deletions.
2 changes: 2 additions & 0 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DYNAMODB_ACCESS_KEY_ID=
DYNAMODB_SECRET_ACCESS_KEY=
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ lerna-debug.log*
# Enviroment
*.env*
!.env.docker
!.env.sample

# Core
src/core
Expand Down
15 changes: 4 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
# Techmmunity - Base Project Serverless
# Techmmunity - Course Service

[![CodeFactor](https://www.codefactor.io/repository/github/techmmunity/base-project-serverless/badge)](https://www.codefactor.io/repository/github/techmmunity/base-project-serverless)
[![CodeFactor](https://www.codefactor.io/repository/github/techmmunity/course-service/badge)](https://www.codefactor.io/repository/github/techmmunity/course-service)
[![DeepScan grade](https://deepscan.io/api/teams/13883/projects/17602/branches/407704/badge/grade.svg)](https://deepscan.io/dashboard#view=project&tid=13883&pid=17602&bid=407704)
[![Coverage Status](https://coveralls.io/repos/github/techmmunity/base-project-serverless/badge.svg?branch=master)](https://coveralls.io/github/techmmunity/base-project-serverless?branch=master)
[![tests](https://github.com/techmmunity/base-project-serverless/actions/workflows/tests.yml/badge.svg)](https://github.com/techmmunity/base-project-serverless/actions/workflows/tests.yml)

## TODO

- [ ] Add Dynamo Integration
- [ ] Config Serverless Framework correctly
- [ ] Test Cognito Integration
- [ ] Add Unit Tests
[![Coverage Status](https://coveralls.io/repos/github/techmmunity/course-service/badge.svg?branch=master)](https://coveralls.io/github/techmmunity/course-service?branch=master)
[![tests](https://github.com/techmmunity/course-service/actions/workflows/tests.yml/badge.svg)](https://github.com/techmmunity/course-service/actions/workflows/tests.yml)
14 changes: 8 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
{
"name": "base-project-serverless",
"name": "course-service",
"version": "1.0.0",
"description": "Techmmunity Base Project For Serverless Projects",
"description": "Course Service",
"author": "Techmmunity",
"private": false,
"license": "Apache-2.0",
"dependencies": {
"@nestjs/common": "^8.0.0",
"@nestjs/core": "^8.0.0",
"@nestjs/platform-express": "^8.1.1",
"@techmmunity/symbiosis": "^0.0.7",
"@techmmunity/symbiosis-dynamodb": "^0.0.2",
"@techmmunity/symbiosis-nestjs": "^0.0.1",
"@techmmunity/symbiosis": "^0.0.11",
"@techmmunity/symbiosis-dynamodb": "^0.0.4",
"@techmmunity/symbiosis-nestjs": "^0.0.3",
"@techmmunity/utils": "^1.1.0",
"@vendia/serverless-express": "^4.5.2",
"aws-lambda": "^1.0.6",
"dayjs": "^1.10.7",
Expand All @@ -35,6 +36,7 @@
"@types/node": "^16.0.0",
"@types/supertest": "^2.0.11",
"@types/uuid": "^8.3.1",
"env-cmd": "^10.1.0",
"eslint": "^8.0.1",
"husky": "^7.0.2",
"jest": "^27.0.6",
Expand Down Expand Up @@ -64,7 +66,7 @@
"start:prod": "node dist/index.js",
"format": "eslint . --fix --quiet",
"lint": "eslint . --quiet",
"dev": "serverless offline",
"dev": "env-cmd serverless offline",
"test": "jest",
"test:cov": "jest --coverage",
"update-dependencies": "yarn upgrade-interactive --latest",
Expand Down
5 changes: 3 additions & 2 deletions serverless.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { v1 } from "./src/v1";
import type { AWS } from "@serverless/typescript";

const serverlessConfiguration: AWS = {
service: "base-project-serverless",
service: "course-service",
frameworkVersion: "2",
useDotenv: true,
package: {
Expand All @@ -16,7 +16,6 @@ const serverlessConfiguration: AWS = {
webpackConfig: "./webpack.config.js",
includeModules: true,
},
optimize: ["swagger-ui-dist"]
},
plugins: ["serverless-webpack", "serverless-offline"],
provider: {
Expand All @@ -28,6 +27,8 @@ const serverlessConfiguration: AWS = {
},
environment: {
AWS_NODEJS_CONNECTION_REUSE_ENABLED: "1",
DYNAMODB_ACCESS_KEY_ID: process.env.DYNAMODB_ACCESS_KEY_ID!,
DYNAMODB_SECRET_ACCESS_KEY: process.env.DYNAMODB_SECRET_ACCESS_KEY!,
},
lambdaHashingVersion: "20201221",
},
Expand Down
7 changes: 4 additions & 3 deletions src/helpers/make-handler.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-console */
import { NestFactory } from "@nestjs/core";
import serverlessExpress from "@vendia/serverless-express";
import type { Handler } from "aws-lambda";
Expand All @@ -6,7 +7,7 @@ let cachedServer: Handler;

const isWarmUp = (event: any) => event.source === "serverless-plugin-warmup";

const bootstrap = async (module: any, version: string): Promise<Handler> => {
const bootstrap = async (module: any): Promise<Handler> => {
const nestApp = await NestFactory.create(module);

nestApp.enableCors();
Expand All @@ -19,7 +20,7 @@ const bootstrap = async (module: any, version: string): Promise<Handler> => {
};

export const makeHandler =
(module: any, version: string): Handler =>
(module: any): Handler =>
async (event, context, callback) => {
// https://github.com/vendia/serverless-express/issues/86
event.path = event.pathParameters.proxy;
Expand All @@ -35,7 +36,7 @@ export const makeHandler =

if (!cachedServer) {
// eslint-disable-next-line require-atomic-updates
cachedServer = await bootstrap(module, version);
cachedServer = await bootstrap(module);
}

return cachedServer(event, context, callback);
Expand Down
14 changes: 14 additions & 0 deletions src/v1/api/course/course.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Body, Controller, Post } from "@nestjs/common";
import { CourseService } from "./course.service";
import { V1CreateCourseInputSchema } from "./service/create/schemas/input.schema";
import { API_VERSION } from "v1/config";

@Controller(`${API_VERSION}/course`)
export class CourseController {
public constructor(private readonly exampleService: CourseService) {}

@Post()
public create(@Body() data: V1CreateCourseInputSchema) {
return this.exampleService.create(data);
}
}
14 changes: 14 additions & 0 deletions src/v1/api/course/course.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Module } from "@nestjs/common";
import { SymbiosisModule } from "@techmmunity/symbiosis-nestjs";

import { CourseEntity } from "v1/entities/course";

import { CourseService } from "./course.service";
import { CourseController } from "./course.controller";

@Module({
imports: [SymbiosisModule.forFeature([CourseEntity])],
providers: [CourseService],
controllers: [CourseController],
})
export class CourseModule {}
24 changes: 24 additions & 0 deletions src/v1/api/course/course.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@techmmunity/symbiosis-nestjs";

import { CourseEntity, CourseRepository } from "v1/entities/course";

import { create } from "./service/create";
import { V1CreateCourseInputSchema } from "./service/create/schemas/input.schema";

@Injectable()
export class CourseService {
public constructor(
@InjectRepository(CourseEntity)
private readonly courseRepository: CourseRepository,
) {}

public create(params: V1CreateCourseInputSchema) {
return create(
{
courseRepository: this.courseRepository,
},
params,
);
}
}
17 changes: 17 additions & 0 deletions src/v1/api/course/service/create/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { CourseRepository } from "v1/entities/course";
import { V1CreateCourseInputSchema } from "./schemas/input.schema";

import { validate } from "./validate";

interface Injectables {
courseRepository: CourseRepository;
}

export const create = async (
{ courseRepository }: Injectables,
params: V1CreateCourseInputSchema,
) => {
const data = await validate(params);

return courseRepository.save(data);
};
68 changes: 68 additions & 0 deletions src/v1/api/course/service/create/schemas/input.schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { ResourceTypeEnum } from "v1/enums/resource-type";
import { SeniorityEnum } from "v1/enums/seniority";

class V1CreateCourseEpisodeQuizAnswerInputSchema {
public answer: string;
}

class V1CreateCourseEpisodeQuizInputSchema {
public question: string;

public shortDescription: string;

public rightAnswerId: string;

public answers: Array<V1CreateCourseEpisodeQuizAnswerInputSchema>;
}

class V1CreateCourseEpisodeResourceInputSchema {
public type: ResourceTypeEnum;

public url?: string;

public title?: string;

public description?: string;
}

class V1CreateCourseEpisodeVideoInputSchema {
public durationInSeconds: number;

public previewImageUrl: string;

public url: string;

public version: number;
}

class V1CreateCourseEpisodeInputSchema {
public name: string;

public note: string;

public video: V1CreateCourseEpisodeVideoInputSchema;

public resources: Array<V1CreateCourseEpisodeResourceInputSchema>;

public quizzes: Array<V1CreateCourseEpisodeQuizInputSchema>;
}

export class V1CreateCourseInputSchema {
public name: string;

public description: string;

public mustKnowBefore?: Array<string>;

public whereToGoAfter?: Array<string>;

public available?: boolean;

public seniority: SeniorityEnum;

public toolkit: Array<string>;

public tags: Array<string>;

public episodes: Array<V1CreateCourseEpisodeInputSchema>;
}
3 changes: 3 additions & 0 deletions src/v1/api/course/service/create/schemas/output.schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export class V1CreateCourseOutputSchema {
public thisIsAnParam: string;
}
86 changes: 86 additions & 0 deletions src/v1/api/course/service/create/validate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/* eslint-disable @typescript-eslint/no-magic-numbers */

import { fields } from "v1/validation/fields";
import { V1CreateCourseInputSchema } from "./schemas/input.schema";

import { makeValidate } from "v1/validation/validate";
import { yup } from "v1/utils/yup";

const { episodes } = fields;

const schema = yup
.object()
.required()
.strict()
.shape({
name: fields.name.required(),
description: fields.description.required(),
mustKnowBefore: fields.mustKnowBefore.notRequired(),
whereToGoAfter: fields.whereToGoAfter.notRequired(),
available: fields.available.notRequired(),
seniority: fields.seniority.required(),
toolkit: fields.toolkit.required().min(1),
tags: fields.tags.required().min(1),
episodes: yup
.array()
.strict()
.required()
.of(
yup
.object()
.strict()
.required()
.shape({
name: episodes.name.required(),
note: episodes.note.required(),
video: yup.object().strict().required().shape({
durationInSeconds: episodes.video.durationInSeconds.required(),
previewImageUrl: episodes.video.previewImageUrl.required(),
url: episodes.video.url.required(),
version: episodes.video.version.required(),
}),
resources: yup
.array()
.strict()
.required()
.of(
yup.object().strict().required().shape({
title: episodes.resources.title.notRequired(),
description: episodes.resources.description.notRequired(),
url: episodes.resources.url.notRequired(),
previewImageUrl:
episodes.resources.previewImageUrl.notRequired(),
type: episodes.resources.type.required(),
}),
),
quizzes: yup
.array()
.strict()
.required()
.of(
yup
.object()
.strict()
.required()
.shape({
question: episodes.quizzes.question.required(),
rightAnswerId: episodes.quizzes.rightAnswerId.required(),
shortDescription:
episodes.quizzes.shortDescription.required(),
answers: yup
.array()
.strict()
.required()
.of(
yup.object().strict().required().shape({
answer: episodes.quizzes.answers.answer.required(),
}),
)
.min(2),
}),
),
}),
),
});

export const validate = makeValidate<V1CreateCourseInputSchema>(schema);
14 changes: 0 additions & 14 deletions src/v1/api/example/example.controller.ts

This file was deleted.

17 changes: 0 additions & 17 deletions src/v1/api/example/example.entity.ts

This file was deleted.

Loading

0 comments on commit 3b54027

Please sign in to comment.