api entities

This commit is contained in:
Yanis Rigaudeau 2022-10-11 12:18:12 +02:00
parent 63478aa887
commit 8866784d49
Signed by: yanis
GPG Key ID: 4DD2841DF1C94D83
19 changed files with 106 additions and 21 deletions

2
.gitignore vendored
View File

@ -3,3 +3,5 @@
**/node_modules **/node_modules
**/public/build **/public/build
**/dist **/dist
!.prettierrc.json

5
api/.prettierrc.json Normal file
View File

@ -0,0 +1,5 @@
{
"semi": true,
"trailingComma": "all",
"singleQuote": true
}

View File

@ -4,15 +4,18 @@ import ip from 'ip';
const PORT = 8000; const PORT = 8000;
const MONGOURI = 'mongodb://localhost:27017'; const MONGOURI = 'mongodb://localhost:27017';
const DBNAME = 'dev';
const mongo = new Mongo(MONGOURI); const mongo = new Mongo(MONGOURI);
const services: Services = { const services: Services = {
db: mongo.getDb(), db: mongo.getDb(DBNAME),
}; };
const server = new Server(services); const server = new Server(services);
server.start(PORT, () => server.start(PORT, () =>
console.log(`Running on http://${ip.address()}:${PORT}`), console.log(
`Running on http://127.0.0.1:${PORT} http://${ip.address()}:${PORT}`,
),
); );

View File

@ -0,0 +1,14 @@
import { EntityCtor, EntityInfo } from '@core';
import { randomUUID } from 'crypto';
export class Entity implements EntityInfo {
uuid: string;
createdAt: Date;
updatedAt: Date;
constructor(raw: EntityCtor) {
this.uuid = raw.uuid || randomUUID();
this.createdAt = raw.createdAt || new Date();
this.updatedAt = raw.updatedAt || new Date();
}
}

18
api/src/entities/user.ts Normal file
View File

@ -0,0 +1,18 @@
import { UserCtor, UserInfo } from '@core';
import { Entity } from './entity';
export class User extends Entity implements UserInfo {
name: string;
constructor(raw: UserCtor) {
super(raw);
this.name = raw.name ? raw.name : '';
}
Info(): UserInfo {
return {
name: this.name,
};
}
}

View File

@ -1,6 +1,10 @@
import { RequestHandler } from 'express'; import { Request, RequestHandler } from 'express';
import { randomUUID } from 'crypto'; import { randomUUID } from 'crypto';
export function getId(req: Request): string {
return req.get('request-id') || 'unknown';
}
export function BeforeEach(): RequestHandler { export function BeforeEach(): RequestHandler {
return (req, res, next) => { return (req, res, next) => {
req.headers['request-id'] = randomUUID(); req.headers['request-id'] = randomUUID();

View File

@ -1,5 +1,6 @@
import { RequestHandler, Router } from 'express'; import { RequestHandler, Router } from 'express';
import { Create } from '../../functions/user'; import { Create } from '../../functions/user';
import { getId } from './middleware';
import { Services } from './server'; import { Services } from './server';
export function LoginHandler(services: Services): RequestHandler { export function LoginHandler(services: Services): RequestHandler {
@ -12,7 +13,7 @@ export function CreateHandler(services: Services): RequestHandler {
const createUser = Create(services); const createUser = Create(services);
return async (req, res) => { return async (req, res) => {
const user = await createUser(req.get('request-id'), req.body); const user = await createUser(getId(req), req.body);
res.send(user); res.send(user);
}; };

View File

@ -2,14 +2,13 @@ import { MongoClient, Db } from 'mongodb';
class Mongo { class Mongo {
private client: MongoClient; private client: MongoClient;
private dbName: string;
constructor(uri: string) { constructor(uri: string) {
this.client = new MongoClient(uri); this.client = new MongoClient(uri);
} }
getDb(): Db { getDb(dbName: string): Db {
return this.client.db(this.dbName); return this.client.db(dbName);
} }
} }

View File

@ -1,16 +1,28 @@
import { CreateUserBody, User, UserInfo } from '@core'; import { User } from '../../entities/user';
import { Services } from '../express/server'; import { Services } from '../express/server';
export function Create( export function Create(
services: Services, services: Services,
): (tracker: string, user: CreateUserBody) => Promise<UserInfo> { ): (tracker: string, user: User) => Promise<User> {
const { db } = services; const { db } = services;
const coll = db.collection('users'); const coll = db.collection<User>('users');
const readUser = Read(services);
return async (tracker, user) => { return async (tracker, user) => {
await coll.insertOne(user); await coll.insertOne(user);
return { return readUser(tracker, user.uuid);
name: 'test', };
}; }
export function Read(
services: Services,
): (tracker: string, uuid: string) => Promise<User> {
const { db } = services;
const coll = db.collection<User>('users');
return async (tracker, uuid) => {
const user = await coll.findOne({ uuid });
return new User(user || { name: 'not found' });
}; };
} }

View File

@ -1,13 +1,15 @@
import { CreateUserBody, UserInfo } from '@core'; import { CreateUserBody, UserInfo } from '@core';
import { User } from '../entities/user';
import { Services } from '../framework/express/server'; import { Services } from '../framework/express/server';
import * as mongo from '../framework/mongo/user'; import * as mongo from '../framework/mongo/user';
export function Create( export function Create(
services: Services, services: Services,
): (tracker: string, user: CreateUserBody) => Promise<UserInfo> { ): (tracker: string, raw: CreateUserBody) => Promise<UserInfo> {
const createUser = mongo.Create(services); const createUser = mongo.Create(services);
return async (tracker, user) => { return async (tracker, raw) => {
return createUser(tracker, user); const user = await createUser(tracker, new User(raw));
return user.Info();
}; };
} }

View File

@ -6,6 +6,7 @@
"moduleResolution": "node", "moduleResolution": "node",
"outDir": "dist", "outDir": "dist",
"sourceMap": false, "sourceMap": false,
"strictNullChecks": true,
"paths": { "paths": {
"@core": ["../core/src"] "@core": ["../core/src"]
} }

5
core/.prettierrc.json Normal file
View File

@ -0,0 +1,5 @@
{
"semi": true,
"trailingComma": "all",
"singleQuote": true
}

View File

@ -1,5 +1,7 @@
export type Entity = { export type EntityInfo = {
uuid: string; uuid: string;
createdAt: Date; createdAt: Date;
updatedAt: Date; updatedAt: Date;
}; };
export type EntityCtor = Partial<EntityInfo>;

View File

@ -1,2 +1,2 @@
export * from "./user"; export * from './user';
export * from "./entity"; export * from './entity';

View File

@ -1,10 +1,10 @@
import { Entity } from "./entity"; import { EntityInfo } from './entity';
export type UserInfo = { export type UserInfo = {
name: string; name: string;
}; };
export type User = UserInfo & Entity; export type User = UserInfo & EntityInfo;
export type CreateUserBody = { export type CreateUserBody = {
name: string; name: string;
@ -12,3 +12,5 @@ export type CreateUserBody = {
}; };
export type LoginUserBody = CreateUserBody; export type LoginUserBody = CreateUserBody;
export type UserCtor = Partial<User>;

View File

@ -4,6 +4,7 @@
"declarationMap": true, "declarationMap": true,
"composite": true, "composite": true,
"sourceMap": false, "sourceMap": false,
"strictNullChecks": true,
"outDir": "dist" "outDir": "dist"
}, },
"include": ["src/**/*"], "include": ["src/**/*"],

8
prettier.py Executable file
View File

@ -0,0 +1,8 @@
#!/usr/bin/python
import os
for dir in os.listdir('.'):
if os.path.isdir(dir) and not dir.startswith('.'):
os.chdir(dir)
os.system('npm run prettier')
os.chdir('..')

5
www/.prettierrc.json Normal file
View File

@ -0,0 +1,5 @@
{
"semi": true,
"trailingComma": "all",
"singleQuote": true
}

View File

@ -2,6 +2,7 @@
"extends": "@tsconfig/svelte/tsconfig.json", "extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"sourceMap": false, "sourceMap": false,
"strictNullChecks": true,
"paths": { "paths": {
"@core": ["../core/src"] "@core": ["../core/src"]
} }