Skip to content

Commit

Permalink
Start backend implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
henriqueleite42 committed Nov 23, 2023
1 parent 3d135cc commit 1bdf7f7
Show file tree
Hide file tree
Showing 38 changed files with 1,325 additions and 27 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ module.exports = {
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
"@typescript-eslint/no-unused-vars": ["error", {varsIgnorePattern: /^_/}]
},
};
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"cSpell.words": ["dbdocs", "dbml", "nestjs", "openapi", "redocly"],
"cSpell.words": ["dbdocs", "dbml", "Mikro", "nestjs", "openapi", "redocly"],

// Add a vertical line on the 80 characters limit
"editor.rulers": [80],
Expand Down
15 changes: 12 additions & 3 deletions database.dbml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ enum timezone {
"America/Sao_Paulo" [note: '-03:00']
}

enum sign_in_provider {
"GOOGLE"
}

Table accounts {
id char(16) [pk]
email varchar(150) [unique]
Expand All @@ -42,16 +46,21 @@ Table accounts {
note: "Contains user's sign in information"
}

Table google {
account_id char(16) [pk] // See Ref google.account_id
Table sign_in_providers {
account_id char(16) [not null] // See Ref google.account_id
provider sign_in_provider [not null]
access_token varchar [not null]
refresh_token varchar [not null]
expires_at timestamp [not null]

note: "Contains user's link to google account"

indexes {
(account_id, provider) [pk]
}
}

Ref: accounts.id - google.account_id [delete: restrict]
Ref: accounts.id < sign_in_provider.account_id [delete: cascade]

Table configs {
account_id char(16) [pk] // See Ref configs.account_id
Expand Down
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@
"dependencies": {
"@aws-sdk/client-s3": "^3.456.0",
"@aws-sdk/client-ses": "^3.454.0",
"@mikro-orm/core": "^5.9.4",
"@mikro-orm/nestjs": "^5.2.2",
"@mikro-orm/postgresql": "^5.9.4",
"@mikro-orm/reflection": "^5.9.4",
"@nestjs/common": "^10.2.10",
"@nestjs/core": "^10.2.10",
"@nestjs/platform-express": "^10.2.10",
"@techmmunity/utils": "^1.10.1",
"change-case": "^5.2.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"jsonwebtoken": "^9.0.2",
Expand Down
10 changes: 10 additions & 0 deletions src/adapters/email.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export interface SendInput {
from: string;
to: string;
title: string;
body: string;
}

export interface EmailAdapter {
send: (i: SendInput) => Promise<void>;
}
19 changes: 19 additions & 0 deletions src/adapters/file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Readable } from 'stream';

export interface SaveInput {
folder: string;
filePath: `/${string}`;
file: Buffer;
metadata?: Record<string, string>;
}

export interface GetInput {
folder: string;
filePath: `/${string}`;
}

export interface FileAdapter {
save: (i: SaveInput) => Promise<string>;

getReadStream: (i: GetInput) => Promise<Readable>;
}
3 changes: 3 additions & 0 deletions src/adapters/id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface IdAdapter {
gen: () => string;
}
20 changes: 20 additions & 0 deletions src/adapters/implementations/jwt.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Injectable } from '@nestjs/common';
import { GenInput, GenOutput, TokenAdapter } from '../token';
import { sign } from 'jsonwebtoken';

@Injectable()
export class JWTAdapter implements TokenAdapter {
gen({ id }: GenInput): GenOutput {
const accessToken = sign(
{
sub: id,
},
process.env['JWT_SECRET'],
);

return {
accessToken,
expiresAt: '',
};
}
}
49 changes: 49 additions & 0 deletions src/adapters/implementations/s3.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Injectable } from '@nestjs/common';
import { FileAdapter, GetInput, SaveInput } from '../file';
import {
GetObjectCommand,
PutObjectCommand,
S3Client,
} from '@aws-sdk/client-s3';
import { Readable } from 'stream';

@Injectable()
export class S3Adapter implements FileAdapter {
private client: S3Client;

constructor() {
this.client = new S3Client({
endpoint: process.env['AWS_ENDPOINT'],
region: process.env['AWS_DEFAULT_REGION'],
credentials: {
secretAccessKey: process.env['AWS_SECRET_ACCESS_KEY'],
accessKeyId: process.env['AWS_ACCESS_KEY_ID'],
},
forcePathStyle: process.env['NODE_ENV'] !== 'production',
});
}

async save({ folder, filePath, file, metadata }: SaveInput) {
await this.client.send(
new PutObjectCommand({
Bucket: folder,
Key: filePath.replace(/^\//, ''),
Body: file,
Metadata: metadata,
}),
);

return filePath;
}

async getReadStream({ folder, filePath }: GetInput): Promise<Readable> {
const file = await this.client.send(
new GetObjectCommand({
Bucket: folder,
Key: filePath.replace(/^\//, ''),
}),
);

return file.Body! as Readable;
}
}
20 changes: 20 additions & 0 deletions src/adapters/implementations/semver.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Injectable } from '@nestjs/common';
import { IsLatestInput, LatestInput, VersionAdapter } from '../version';

import { gt, rsort } from 'semver';

@Injectable()
export class SemVerAdapter implements VersionAdapter {
latest({ versions }: LatestInput): string {
const [latestSemVer] = rsort(versions);

return latestSemVer;
}

isGt({ toValidate, compareWith }: IsLatestInput): boolean {
if (!compareWith) return true;
if (!toValidate) return false;

return gt(toValidate, compareWith);
}
}
35 changes: 35 additions & 0 deletions src/adapters/implementations/ses.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { SESClient, SendEmailCommand } from '@aws-sdk/client-ses';
import { Injectable } from '@nestjs/common';
import { EmailAdapter, SendInput } from '../email';

@Injectable()
export class SESAdapter implements EmailAdapter {
private client: SESClient;

constructor() {
this.client = new SESClient();
}

async send({ from, to, title, body }: SendInput) {
await this.client.send(
new SendEmailCommand({
Source: from,
Destination: {
ToAddresses: [to],
},
Message: {
Subject: {
Data: title,
Charset: 'UTF-8',
},
Body: {
Html: {
Data: body,
Charset: 'UTF-8',
},
},
},
}),
);
}
}
10 changes: 10 additions & 0 deletions src/adapters/implementations/uid-secret.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { uid } from 'uid/single';
import { Injectable } from '@nestjs/common';
import { SecretAdapter } from '../secret';

@Injectable()
export class UIDSecretAdapter implements SecretAdapter {
gen(): string {
return uid(32);
}
}
10 changes: 10 additions & 0 deletions src/adapters/implementations/uid.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { uid } from 'uid/secure';
import { Injectable } from '@nestjs/common';
import { IdAdapter } from '../id';

@Injectable()
export class UIDAdapter implements IdAdapter {
gen(): string {
return uid(16);
}
}
49 changes: 49 additions & 0 deletions src/adapters/implementations/utils.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Injectable } from '@nestjs/common';
import {
PaginationInput,
PaginationOutput,
UtilsAdapter as UtilsAdapterType,
} from '../utils';

@Injectable()
export class UtilsAdapter implements UtilsAdapterType {
pagination({
page: originalPage,
limit: originalLimit,
}: PaginationInput): PaginationOutput {
const page = originalPage || 1;
const limit = originalLimit || 15;

return {
paging: {
curPage: page,
nextPage: page + 1,
prevPage: page === 1 ? undefined : page - 1,
limit,
},
limit,
offset: (page - 1) * limit,
};
}

formatMoney(valueNumber: number): string {
const value = valueNumber.toString();

const decimalsStart = value.length - 2;

const formatter = new Intl.NumberFormat('pt-BR', {
style: 'currency',
currency: 'BRL',
});

return formatter.format(
parseFloat(
[
value.substring(0, decimalsStart),
'.',
value.substring(decimalsStart),
].join(''),
),
);
}
}
3 changes: 3 additions & 0 deletions src/adapters/secret.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface SecretAdapter {
gen: () => string;
}
20 changes: 20 additions & 0 deletions src/adapters/token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export interface TokenPayload {
sub: string; // Account ID
}

export interface UserData {
accountId: string;
}

export interface GenInput {
id: string;
}

export interface GenOutput {
accessToken: string;
expiresAt: string; // ISO date
}

export interface TokenAdapter {
gen: (i: GenInput) => GenOutput;
}
18 changes: 18 additions & 0 deletions src/adapters/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { PaginatedItems } from 'src/types/paginated-items';

export interface PaginationInput {
page?: number;
limit?: number;
}

export interface PaginationOutput {
paging: PaginatedItems<any>['paging'];
offset: number;
limit: number;
}

export interface UtilsAdapter {
pagination: (i: PaginationInput) => PaginationOutput;

formatMoney: (i: number) => string;
}
14 changes: 14 additions & 0 deletions src/adapters/version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export interface LatestInput {
versions: Array<string>;
}

export interface IsLatestInput {
toValidate: string | undefined;
compareWith: string | undefined;
}

export interface VersionAdapter {
latest: (i: LatestInput) => string;

isGt: (i: IsLatestInput) => boolean;
}
27 changes: 27 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Module } from '@nestjs/common';
import { AccountModule } from './usecases/account/account.module';
import { TermsModule } from './usecases/terms/terms.module';
import { DocumentModule } from './usecases/document/document.module';
import { NotificationModule } from './usecases/notification/notification.module';
import { StoreModule } from './usecases/store/store.module';
import { ProductModule } from './usecases/product/product.module';
import { ContentModule } from './usecases/content/content.module';
import { SaleModule } from './usecases/sale/sale.module';
import { TransactionModule } from './usecases/transaction/transaction.module';
import { PostgresModule } from './repositories/postgres';

@Module({
imports: [
PostgresModule,
AccountModule,
TermsModule,
DocumentModule,
NotificationModule,
StoreModule,
ProductModule,
ContentModule,
SaleModule,
TransactionModule,
],
})
export class AppModule {}
Loading

0 comments on commit 1bdf7f7

Please sign in to comment.