new services + new scripts

This commit is contained in:
Yanis Rigaudeau 2022-10-14 18:49:09 +02:00
parent 8866784d49
commit 5538a042df
Signed by: yanis
GPG Key ID: 4DD2841DF1C94D83
23 changed files with 200 additions and 126 deletions

View File

@ -1,15 +1,21 @@
import Server, { Services } from './framework/express/server'; import Server from './framework/express/server';
import Mongo from './framework/mongo/mongo';
import ip from 'ip'; import ip from 'ip';
import UserModel from './framework/mongo/user';
import { MongoClient } from 'mongodb';
const PORT = 8000; const PORT = 8000;
const MONGOURI = 'mongodb://localhost:27017'; const MONGOURI = 'mongodb://localhost:27017';
const DBNAME = 'dev'; const DBNAME = 'dev';
const mongo = new Mongo(MONGOURI); export type Services = {
userModel: UserModel;
};
const mongo = new MongoClient(MONGOURI);
const db = mongo.db(DBNAME);
const services: Services = { const services: Services = {
db: mongo.getDb(DBNAME), userModel: new UserModel(db),
}; };
const server = new Server(services); const server = new Server(services);

View File

@ -1,4 +1,10 @@
import { UserCtor, UserInfo } from '@core'; import {
UserCtor,
UserInfo,
UserInfoWithPassword,
UserWithPasswordCtor,
} from '@core';
import { createHash, Hash } from 'crypto';
import { Entity } from './entity'; import { Entity } from './entity';
export class User extends Entity implements UserInfo { export class User extends Entity implements UserInfo {
@ -12,7 +18,18 @@ export class User extends Entity implements UserInfo {
Info(): UserInfo { Info(): UserInfo {
return { return {
uuid: this.uuid,
name: this.name, name: this.name,
}; };
} }
} }
export class UserWithPassword extends User implements UserInfoWithPassword {
password: Hash;
constructor(raw: UserWithPasswordCtor) {
super(raw);
this.password = createHash('sha256').update(`${this.uuid}+${raw.password}`);
}
}

View File

@ -1,5 +1,5 @@
import { Router } from 'express'; import { Router } from 'express';
import { Services } from './server'; import { Services } from '../../app';
import * as user from './user'; import * as user from './user';
export function getRoutes(services: Services) { export function getRoutes(services: Services) {

View File

@ -2,11 +2,7 @@ import express, { Express } from 'express';
import cors from 'cors'; import cors from 'cors';
import * as router from './router'; import * as router from './router';
import { BeforeEach } from './middleware'; import { BeforeEach } from './middleware';
import { Db } from 'mongodb'; import { Services } from '../../app';
export type Services = {
db: Db;
};
class Server { class Server {
private app: Express; private app: Express;

View File

@ -1,7 +1,7 @@
import { RequestHandler, Router } from 'express'; import { RequestHandler, Router } from 'express';
import { Services } from '../../app';
import { Create } from '../../functions/user'; import { Create } from '../../functions/user';
import { getId } from './middleware'; import { getId } from './middleware';
import { Services } from './server';
export function LoginHandler(services: Services): RequestHandler { export function LoginHandler(services: Services): RequestHandler {
return async (req, res) => { return async (req, res) => {

View File

@ -1,15 +0,0 @@
import { MongoClient, Db } from 'mongodb';
class Mongo {
private client: MongoClient;
constructor(uri: string) {
this.client = new MongoClient(uri);
}
getDb(dbName: string): Db {
return this.client.db(dbName);
}
}
export default Mongo;

View File

@ -1,28 +1,22 @@
import { Collection, Db } from 'mongodb';
import { User } from '../../entities/user'; import { User } from '../../entities/user';
import { Services } from '../express/server';
export function Create( class UserModel {
services: Services, private collection: Collection<User>;
): (tracker: string, user: User) => Promise<User> {
const { db } = services;
const coll = db.collection<User>('users');
const readUser = Read(services);
return async (tracker, user) => { constructor(db: Db) {
await coll.insertOne(user); this.collection = db.collection<User>('users');
return readUser(tracker, user.uuid); }
};
}
export function Read( public async create(tracker: string, user: User) {
services: Services, await this.collection.insertOne(user);
): (tracker: string, uuid: string) => Promise<User> { return this.read(tracker, user.uuid);
const { db } = services; }
const coll = db.collection<User>('users');
return async (tracker, uuid) => {
const user = await coll.findOne({ uuid });
public async read(tracker: string, uuid: string) {
const user = await this.collection.findOne({ uuid });
return new User(user || { name: 'not found' }); return new User(user || { name: 'not found' });
}; }
} }
export default UserModel;

View File

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

3
apps.json Normal file
View File

@ -0,0 +1,3 @@
{
"apps": ["core", "api", "www"]
}

View File

@ -1,8 +0,0 @@
#!/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 build')
os.chdir('..')

13
core/package-lock.json generated
View File

@ -8,10 +8,17 @@
"name": "core", "name": "core",
"version": "1.0.0", "version": "1.0.0",
"devDependencies": { "devDependencies": {
"@types/node": "^18.8.4",
"prettier": "^2.7.1", "prettier": "^2.7.1",
"typescript": "^4.8.3" "typescript": "^4.8.3"
} }
}, },
"node_modules/@types/node": {
"version": "18.8.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.4.tgz",
"integrity": "sha512-WdlVphvfR/GJCLEMbNA8lJ0lhFNBj4SW3O+O5/cEGw9oYrv0al9zTwuQsq+myDUXgNx2jgBynoVgZ2MMJ6pbow==",
"dev": true
},
"node_modules/prettier": { "node_modules/prettier": {
"version": "2.7.1", "version": "2.7.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
@ -42,6 +49,12 @@
} }
}, },
"dependencies": { "dependencies": {
"@types/node": {
"version": "18.8.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.4.tgz",
"integrity": "sha512-WdlVphvfR/GJCLEMbNA8lJ0lhFNBj4SW3O+O5/cEGw9oYrv0al9zTwuQsq+myDUXgNx2jgBynoVgZ2MMJ6pbow==",
"dev": true
},
"prettier": { "prettier": {
"version": "2.7.1", "version": "2.7.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",

View File

@ -9,6 +9,7 @@
"prettier": "prettier -w ./src" "prettier": "prettier -w ./src"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^18.8.4",
"prettier": "^2.7.1", "prettier": "^2.7.1",
"typescript": "^4.8.3" "typescript": "^4.8.3"
} }

View File

@ -1,11 +1,19 @@
import { EntityInfo } from './entity'; import { EntityInfo } from './entity';
import { Hash } from 'crypto';
export type UserInfo = { export type UserInfo = {
uuid: string;
name: string; name: string;
}; };
export type UserInfoWithPassword = {
password: Hash;
} & UserInfo;
export type User = UserInfo & EntityInfo; export type User = UserInfo & EntityInfo;
export type UserWithPassword = UserInfoWithPassword & EntityInfo;
export type CreateUserBody = { export type CreateUserBody = {
name: string; name: string;
password: string; password: string;
@ -14,3 +22,7 @@ export type CreateUserBody = {
export type LoginUserBody = CreateUserBody; export type LoginUserBody = CreateUserBody;
export type UserCtor = Partial<User>; export type UserCtor = Partial<User>;
export type UserWithPasswordCtor = {
password: string;
} & Partial<Omit<UserWithPassword, 'password'>>;

View File

@ -1,8 +0,0 @@
#!/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 ci')
os.chdir('..')

View File

@ -1,8 +0,0 @@
#!/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('..')

12
scripts/build.py Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/python
import os
import json
apps = json.load(open('apps.json'))['apps']
print(len(apps), 'apps:', apps)
for app in apps:
os.chdir(app)
os.system('npm run build')
os.chdir('..')

View File

@ -2,8 +2,8 @@
useradd node -md /home/node -s /usr/sbin/nologin useradd node -md /home/node -s /usr/sbin/nologin
python3 install.py python3 scripts/install.py
python3 build.py python3 scripts/build.py
rm -r /var/www/html/* rm -r /var/www/html/*
mv www/public/* /var/www/html mv www/public/* /var/www/html

12
scripts/install.py Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/python
import os
import json
apps = json.load(open('apps.json'))['apps']
print(len(apps), 'apps:', apps)
for app in apps:
os.chdir(app)
os.system('npm ci')
os.chdir('..')

12
scripts/prettier.py Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/python
import os
import json
apps = json.load(open('apps.json'))['apps']
print(len(apps), 'apps:', apps)
for app in apps:
os.chdir(app)
os.system('npm run prettier')
os.chdir('..')

18
www/package-lock.json generated
View File

@ -19,6 +19,7 @@
"@tsconfig/svelte": "^2.0.0", "@tsconfig/svelte": "^2.0.0",
"@types/three": "^0.144.0", "@types/three": "^0.144.0",
"prettier": "^2.7.1", "prettier": "^2.7.1",
"prettier-plugin-svelte": "^2.8.0",
"rollup": "^2.3.4", "rollup": "^2.3.4",
"rollup-plugin-css-only": "^3.1.0", "rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-livereload": "^2.0.0", "rollup-plugin-livereload": "^2.0.0",
@ -1027,6 +1028,16 @@
"url": "https://github.com/prettier/prettier?sponsor=1" "url": "https://github.com/prettier/prettier?sponsor=1"
} }
}, },
"node_modules/prettier-plugin-svelte": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-2.8.0.tgz",
"integrity": "sha512-QlXv/U3bUszks3XYDPsk1fsaQC+fo2lshwKbcbO+lrSVdJ+40mB1BfL8OCAk1W9y4pJxpqO/4gqm6NtF3zNGCw==",
"dev": true,
"peerDependencies": {
"prettier": "^1.16.4 || ^2.0.0",
"svelte": "^3.2.0"
}
},
"node_modules/queue-microtask": { "node_modules/queue-microtask": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@ -2381,6 +2392,13 @@
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
"dev": true "dev": true
}, },
"prettier-plugin-svelte": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-2.8.0.tgz",
"integrity": "sha512-QlXv/U3bUszks3XYDPsk1fsaQC+fo2lshwKbcbO+lrSVdJ+40mB1BfL8OCAk1W9y4pJxpqO/4gqm6NtF3zNGCw==",
"dev": true,
"requires": {}
},
"queue-microtask": { "queue-microtask": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",

View File

@ -18,6 +18,7 @@
"@tsconfig/svelte": "^2.0.0", "@tsconfig/svelte": "^2.0.0",
"@types/three": "^0.144.0", "@types/three": "^0.144.0",
"prettier": "^2.7.1", "prettier": "^2.7.1",
"prettier-plugin-svelte": "^2.8.0",
"rollup": "^2.3.4", "rollup": "^2.3.4",
"rollup-plugin-css-only": "^3.1.0", "rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-livereload": "^2.0.0", "rollup-plugin-livereload": "^2.0.0",

View File

@ -1,30 +1,30 @@
<script lang="ts"> <script lang="ts">
// export let name: string; // export let name: string;
import Test3D from "./components/test3D.svelte"; import Test3D from './components/test3D.svelte';
</script> </script>
<main> <main>
<Test3D></Test3D> <Test3D />
</main> </main>
<style> <style>
main { main {
text-align: center; text-align: center;
padding: 1em; padding: 1em;
max-width: 240px; max-width: 240px;
margin: 0 auto; margin: 0 auto;
} }
h1 { h1 {
color: #ff3e00; color: #ff3e00;
text-transform: uppercase; text-transform: uppercase;
font-size: 4em; font-size: 4em;
font-weight: 100; font-weight: 100;
} }
@media (min-width: 640px) { @media (min-width: 640px) {
main { main {
max-width: none; max-width: none;
} }
} }
</style> </style>

View File

@ -1,51 +1,68 @@
<script lang="ts"> <script lang="ts">
//import { onMount } from "lifecycle"; //import { onMount } from "lifecycle";
import { beforeUpdate, afterUpdate } from 'svelte'; import { beforeUpdate, afterUpdate } from 'svelte';
import * as Three from 'three'; import * as Three from 'three';
let innerWidth: number = 0; let innerWidth: number = 0;
let innerHeight: number = 0; let innerHeight: number = 0;
let scene: Three.Scene = new Three.Scene(); let scene: Three.Scene = new Three.Scene();
let camera: Three.PerspectiveCamera = new Three.PerspectiveCamera(75, innerWidth/innerHeight, 0.1, 1000); let camera: Three.PerspectiveCamera = new Three.PerspectiveCamera(
75,
innerWidth / innerHeight,
0.1,
1000,
);
let renderer: Three.WebGLRenderer = new Three.WebGLRenderer(); let renderer: Three.WebGLRenderer = new Three.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight); renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement); document.body.appendChild(renderer.domElement);
let box: Three.BoxGeometry = new Three.BoxGeometry(1,1,1); let box: Three.BoxGeometry = new Three.BoxGeometry(1, 1, 1);
let mat: Three.MeshBasicMaterial = new Three.MeshBasicMaterial({ color: 0x00ff00 }); let mat: Three.MeshBasicMaterial = new Three.MeshBasicMaterial({
color: 0x00ff00,
});
let cube = new Three.Mesh(box, mat); let cube = new Three.Mesh(box, mat);
scene.add(cube); scene.add(cube);
camera.position.z = 5; camera.position.z = 5;
camera.setViewOffset(window.innerWidth, window.innerHeight, 0, 0, window.innerWidth, window.innerHeight) camera.setViewOffset(
renderer.setSize(window.innerWidth, window.innerHeight); window.innerWidth,
window.innerHeight,
0,
0,
window.innerWidth,
window.innerHeight,
);
renderer.setSize(window.innerWidth, window.innerHeight);
function animate() { function animate() {
requestAnimationFrame(animate); requestAnimationFrame(animate);
cube.rotation.x += 0.02; cube.rotation.x += 0.02;
cube.rotation.y += 0.02; cube.rotation.y += 0.02;
renderer.render(scene, camera);
renderer.render(scene, camera); }
}; animate();
animate();
beforeUpdate(() => { beforeUpdate(() => {});
})
afterUpdate(() => { afterUpdate(() => {
camera.setViewOffset(window.innerWidth, window.innerHeight, 0, 0, window.innerWidth, window.innerHeight) camera.setViewOffset(
renderer.setSize(window.innerWidth, window.innerHeight); window.innerWidth,
}) window.innerHeight,
0,
0,
window.innerWidth,
window.innerHeight,
);
renderer.setSize(window.innerWidth, window.innerHeight);
});
</script> </script>
<svelte:window bind:innerWidth bind:innerHeight/> <svelte:window bind:innerWidth bind:innerHeight />
<style> <style>
html, html,
@ -58,8 +75,8 @@
body { body {
position: relative; position: relative;
margin: 0; margin: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
</style> </style>