From ad4eef17f550ebf7fa9723655ade6cdfc44aaaa4 Mon Sep 17 00:00:00 2001 From: goynov Date: Wed, 27 Nov 2024 12:46:03 +0200 Subject: [PATCH] annotations --- .docs/build-diagrams.bat | 12 +- backend/app/App.js | 117 +++++++++++++++++- backend/app/Config.js | 89 ++++++++++++- backend/app/Db.js | 84 +++++++++---- backend/app/WebServer.js | 11 ++ backend/app/bl/GameObjectsManager.js | 13 +- backend/app/bl/RulesManager.js | 6 + backend/controllers/AssetController.js | 17 ++- .../controllers/api/GameObjectsController.js | 34 ++++- backend/controllers/api/GamesController.js | 47 +++++++ backend/controllers/api/RulesController.js | 60 +++++++++ .../controllers/api/ScenariosController.js | 60 +++++++++ 12 files changed, 514 insertions(+), 36 deletions(-) diff --git a/.docs/build-diagrams.bat b/.docs/build-diagrams.bat index 9ffe4ae..0485014 100644 --- a/.docs/build-diagrams.bat +++ b/.docs/build-diagrams.bat @@ -1,7 +1,17 @@ call jsdoc ../backend/app/App.js -t "./diagram-template/" -d "./out/App.h" + call jsdoc ../backend/app/Config.js -t "./diagram-template/" -d "./out/Config.h" call jsdoc ../backend/app/Db.js -t "./diagram-template/" -d "./out/Db.h" +call jsdoc ../backend/app/WebServer.js -t "./diagram-template/" -d "./out/WebServer.h" + call jsdoc ../backend/app/bl/GamesManager.js -t "./diagram-template/" -d "./out/bl/GamesManager.h" call jsdoc ../backend/app/bl/RulesManager.js -t "./diagram-template/" -d "./out/bl/RulesManager.h" call jsdoc ../backend/app/bl/GameObjectsManager.js -t "./diagram-template/" -d "./out/bl/GameObjectsManager.h" -call jsdoc ../backend/app/bl/ScenariosManager.js -t "./diagram-template/" -d "./out/bl/ScenariosManager.h" \ No newline at end of file +call jsdoc ../backend/app/bl/ScenariosManager.js -t "./diagram-template/" -d "./out/bl/ScenariosManager.h" + +call jsdoc ../backend/controllers/api/GameObjectsController.js -t "./diagram-template/" -d "./out/controllers/api/GameObjectsController.h" +call jsdoc ../backend/controllers/api/GamesController.js -t "./diagram-template/" -d "./out/controllers/api/GamesController.h" +call jsdoc ../backend/controllers/api/RulesController.js -t "./diagram-template/" -d "./out/controllers/api/RulesController.h" +call jsdoc ../backend/controllers/api/ScenariosController.js -t "./diagram-template/" -d "./out/controllers/api/ScenariosController.h" + +call jsdoc ../backend/controllers/AssetController.js -t "./diagram-template/" -d "./out/controllers/AssetController.h" \ No newline at end of file diff --git a/backend/app/App.js b/backend/app/App.js index dec5d67..410907f 100644 --- a/backend/app/App.js +++ b/backend/app/App.js @@ -2,7 +2,7 @@ import path, { dirname } from 'path'; import { fileURLToPath } from 'url'; /** - * Main backend application + * Main backend application class */ class App{ constructor(){ @@ -73,4 +73,119 @@ class App{ } } + +/* The following are pseudo in order to keep documentation aligned to the code */ + +/** + * The core application plugins + */ +class AppCore{ + /** + * The configuration plugin instance + * @type Config + */ + config = undefined; + + /** + * The database plugin instance + * @type Db + */ + db = undefined; + + /** + * The web server plugin instance + * @type WebServer + */ + webServer = undefined; +} + +/** + * The main logical part application plugins + */ +class AppManagement { + + /** + * Game objects manager plugin instance + * @type GameObjectsManager + */ + gameObject = undefined; + + /** + * Games manager plugin instance + * @type GamesManager + */ + games = undefined; + + /** + * Rules manager plugin instance + * @type RulesManager + */ + rules = undefined; + + /** + * Scenarios manager plugin instance + * @type ScenariosManager + */ + scenarios = undefined; +} + +/** + * The main application controller plugin instances + */ +class AppControllerApi { + + /** + * Game objects controller plugin instance + * @type GameObjectsController + */ + gameObjectsApi = undefined; + + /** + * Games controller plugin instance + * @type GamesController + */ + gamesApi = undefined; + + /** + * Rules controller plugin instance + * @type RulesController + */ + rulesApi = undefined; + + /** + * Scenarios controller plugin instance + * @type ScenariosController + */ + scenariosApi = undefined; + + /** + * Asset controller plugin instance + * @type AssetController + */ + assetApi = undefined; +} + +class AppConcrete { + /** + * Application core plugins + * @type AppCore + * @memberof App + */ + core = undefined; + + /** + * Application management plugins + * @type AppManagement + * @memberof App + */ + management = undefined; + + /** + * Application controller API plugins + * @type AppControllerApi + * @memberof App + */ + controller = undefined +} + export default App; \ No newline at end of file diff --git a/backend/app/Config.js b/backend/app/Config.js index 8584c71..ee43397 100644 --- a/backend/app/Config.js +++ b/backend/app/Config.js @@ -6,16 +6,40 @@ import path from 'path' class Config{ name = 'config'; + /** + * @class File system options , repository setup + * @alias FileSystemOptions + * @memberof Config + */ fs = { + /** Repository path + * @type {string} + * @memberof FileSystemOptions + */ repo: null } + + /** + * @class Database options + * @alias DatabaseOptions + * @memberof Config + */ db = { + /** Database name + * @type {string} + * @memberof DatabaseOptions + */ name:'pronature', + + /** Database connection string + * @type {string} + * @memberof DatabaseOptions + */ url: "mongodb://127.0.0.1:27017/pronature" } /** - * @class web site options + * @class Web site endpoint options * @alias SiteOptions * @memberof Config */ @@ -25,38 +49,97 @@ class Config{ * @memberof SiteOptions */ host:'https://localhost:5173', + + /** Whether to use SSL + * @type {boolean} + * @memberof SiteOptions + */ ssl: true, + + /** Port to use + * @type {Number} + * @memberof SiteOptions + */ port: 3000, + /** - * @class certificate data + * @class Certificate data * @alias CertificateOptions * @memberof SiteOptions */ certificate: { /** - * Certificate key + * Certificate private key * @type {string} * @memberof CertificateOptions */ key: './.cert/dev-key.pem', + + /** + * Certificate public key + * @type {string} + * @memberof CertificateOptions + */ cert: './.cert/dev-cert.pem', + + /** + * PK Passphrase + * @type {string} + * @memberof CertificateOptions + */ passphrase: 'parola' }, } + + /** + * @class Access management options + * @alias AccessManagementOptions + * @memberof Config + */ am = { + /** + * Salt, a string to be used in order to make a more complex password hash + * @type {string} + * @memberof AccessManagementOptions + */ salt : 'P@ssSal7y!!', + + /** + * @class Cookie options + * @alias CookieOptions + * @memberof AccessManagementOptions + */ cookie: { + /** + * Cookie secret + * @type {string} + * @memberof CookieOptions + */ secret: 'S3cret4C00k!ie$', + + /** + * Cookie max age (in seconds) + * @type {Number} + * @memberof CookieOptions + */ maxAge: 1000 * 60 * 60 * 24 * 7 } } + /** + * Initializes the configuration + * @param {App} app The application + */ async init(app){ if (!this.fs.repo){ this.fs.repo = path.resolve(`${app.root}/repo`) + '/'; } } + /** + * Starts the configuration plugin + * @param {App} app the application instance + */ async start(app){ } diff --git a/backend/app/Db.js b/backend/app/Db.js index 06187c1..a093e53 100644 --- a/backend/app/Db.js +++ b/backend/app/Db.js @@ -8,10 +8,19 @@ let dbo; */ class Db { name = 'db'; + + /** + * Initializes the database plugin + * @param {App} app The application instance + */ init(app){ } + /** + * Starts the database plugin + * @param {App} app The application instance + */ async start(app){ db = await MongoClient.connect(app.config.db.url, {maxPoolSize: 256}); try { @@ -74,6 +83,12 @@ class Db { } } + /** + * Performs a database aggregation according to a given pipeline + * @param {string} collection Database collection name + * @param {Object} specs aggregation definition (the pipeline) + * @returns {Object[]} Array of records + */ async aggregate(collection, specs){ try { let cursor = dbo.collection(collection); @@ -84,6 +99,13 @@ class Db { } } + /** + * Finds the distinct values for a specified field across a single collection + * @param {string} collection Database collection name + * @param {Object} key The target field for the distinction + * @param {Object} query filter to be applied + * @returns {Object[]} + */ async distinct(collection, key, query){ try { return await dbo.collection(collection).distinct(key, query); @@ -91,6 +113,13 @@ class Db { } } + /** + * Updates a record in database by given key and value + * @param {Object} collection DB collection + * @param {Object} key The key/query which identifies the record to be updated + * @param {Object} value The new value for the record + * @returns {Object} The result from the update operation + */ async update(collection, key, value){ let r; try { @@ -101,6 +130,13 @@ class Db { } } + /** + * Performs partial update on a record by given key and partial value + * @param {Object} collection Database collection + * @param {Object} key The key/query which identifies the record to be updated + * @param {Object} value The partial value to be updated + * @returns {Object} The result from the update operation + */ async updateSet(collection, key, value){ let r; try { @@ -110,6 +146,11 @@ class Db { } } + /** + * Removes a record from the database by given key + * @param {Object} collection Database collection + * @param {Object} key The key/query which identifies the record to be updated + */ async remove(collection, key){ try { await dbo.collection(collection).deleteMany(key); @@ -117,27 +158,28 @@ class Db { } } - convertToObjectId(object, key, recursive, result){ - if (object && object[key]){ - if (Array.isArray(object[key])){ - object[key].forEach((v, i, a)=>{ - a[i] = this.ObjectId(v); - result && result.push(a[i]); - }) - }else{ - let oid = this.ObjectId(object[key]) - object[key] = oid; - result && result.push(oid); - } - } - if (recursive){ - for (var k in object){ - if (typeof(object[k]) == 'object'){ - this.convertToObjectId(object[k], key, recursive, result); - } - } - } - } + + // convertToObjectId(object, key, recursive, result){ + // if (object && object[key]){ + // if (Array.isArray(object[key])){ + // object[key].forEach((v, i, a)=>{ + // a[i] = this.ObjectId(v); + // result && result.push(a[i]); + // }) + // }else{ + // let oid = this.ObjectId(object[key]) + // object[key] = oid; + // result && result.push(oid); + // } + // } + // if (recursive){ + // for (var k in object){ + // if (typeof(object[k]) == 'object'){ + // this.convertToObjectId(object[k], key, recursive, result); + // } + // } + // } + // } sanitizeQuery(q){ if (!q) return; diff --git a/backend/app/WebServer.js b/backend/app/WebServer.js index 7859ce0..86d7e56 100644 --- a/backend/app/WebServer.js +++ b/backend/app/WebServer.js @@ -8,9 +8,16 @@ import cookieParser from 'cookie-parser'; import helmet from 'helmet'; import { v4 as uuidv4 } from 'uuid'; +/** + * The Web Server class, manages all request from the web pllatform, manages the APIs + */ class WebServer { name = 'webServer'; + /** + * Initializes the web server plugin + * @param {App} app The application instance + */ async init(app) { const xapp = express(); this.xapp = xapp; @@ -61,6 +68,10 @@ class WebServer { app.config.am.helmet && xapp.use(helmet(app.config.am.helmet)); } + /** + * Starts the web server plugin + * @param {App} app The application instance + */ async start(app) { let indexFile = app.root + '/index.html'; diff --git a/backend/app/bl/GameObjectsManager.js b/backend/app/bl/GameObjectsManager.js index 2507f23..e399d8b 100644 --- a/backend/app/bl/GameObjectsManager.js +++ b/backend/app/bl/GameObjectsManager.js @@ -8,7 +8,7 @@ import path from 'path'; const collection = 'assets'; /** - * Application layer manager + * Game objects manager */ class GameObjectsManager{ name = 'gameObject'; @@ -157,7 +157,7 @@ class GameObjectsManager{ } /** - * GameObject entity + * GameObject entity, can be: panorama picture, 3d environment, 3d object, 2d object (picture), a player (3d), audio or video asset */ class GameObject { /** @@ -166,9 +166,16 @@ class GameObject { */ name = null; + /** + * Game object type + * @type string + */ type = null; - + /** + * Associated file + * @type File + */ file = null; } diff --git a/backend/app/bl/RulesManager.js b/backend/app/bl/RulesManager.js index 744bf09..c492648 100644 --- a/backend/app/bl/RulesManager.js +++ b/backend/app/bl/RulesManager.js @@ -77,6 +77,12 @@ class Rule { */ name = null; + /** + * Rule definition + * @type Object + */ + name = null; + } export { RulesManager } \ No newline at end of file diff --git a/backend/controllers/AssetController.js b/backend/controllers/AssetController.js index ecbc918..f6e5af1 100644 --- a/backend/controllers/AssetController.js +++ b/backend/controllers/AssetController.js @@ -1,14 +1,29 @@ import express from 'express'; +/** + * Asset controller plugin + */ class AssetController{ - name = 'assetController' + name = 'assetApi' route = '/asset' + /** + * Initializes the AssetController plugin + * @param {App} app The application instance + */ init(app){ const router = express.Router(); const {config} = app; + /** + * API: GET /asset/:type/:id Retrieve asset by type and ID + * @function read + * @param {string} type Type can be "source", "default" or "thumb" + * @param {string} id The name of the asset + * @returns File + * @memberof AssetController + */ router.get('/:where/:id(*)', async (req, res)=>{ res.sendFile(config.fs.repo + req.params.where + '/' + req.params.id, (err)=>{ if (err){ diff --git a/backend/controllers/api/GameObjectsController.js b/backend/controllers/api/GameObjectsController.js index 0ac9d17..944c1fc 100644 --- a/backend/controllers/api/GameObjectsController.js +++ b/backend/controllers/api/GameObjectsController.js @@ -2,17 +2,27 @@ import express from 'express'; import multipart from 'connect-multiparty'; const multipartMiddleware = multipart(); + +/** + * GameObjectsController. API for the game objects manager + */ class GameObjectsController{ name = 'gameObjectsApi' route = '/api/game-object' + /** + * Initializes the GameObjectsController plugin + * @param {App} app The application instance + */ init(app){ const { gameObject } = app; const router = express.Router(); /** - * Create & update + * API: PUT /api/game-object/ Create or update game object + * @function createOrUpdate + * @memberof GameObjectsController */ router.put('/', multipartMiddleware, async (req, res)=>{ try{ @@ -26,22 +36,34 @@ class GameObjectsController{ }); /** - * List + * API: POST /api/game-object/ List game objects by given criteria + * @function list + * @returns {GameObject[]} + * @memberof GameObjectsController */ router.post('/', async (req, res)=>{ let result = await gameObject.list(req.body); res.json(result); }) - router.get('/', async (req, res)=>{ - - }) - + /** + * API: GET /api/game-object/:id Retrieve game object by ID + * @function read + * @param {string} id The id of the game object + * @returns {GameObject} + * @memberof GameObjectsController + */ router.get('/:id', async (req, res)=>{ let object = await gameObject.read(parseInt(req.params.id)); res.json(object); }) + /** + * API: DELETE /api/game-object/:id Delete game object by ID + * @function remove + * @param {string} id The id of the game object + * @memberof GameObjectsController + */ router.delete('/:id', async (req, res)=>{ await gameObject.remove(req.params.id); res.json({status: 'OK'}); diff --git a/backend/controllers/api/GamesController.js b/backend/controllers/api/GamesController.js index 842fbc5..47e4a35 100644 --- a/backend/controllers/api/GamesController.js +++ b/backend/controllers/api/GamesController.js @@ -1,12 +1,59 @@ import express from 'express'; +/** + * GamesController. API for the games manager + */ class GamesController{ name = 'gamesApi' route = '/api/game' + /** + * Initializes the GamesController plugin + * @param {App} app The application instance + */ init(app){ const router = express.Router(); + const { games } = app; + + /** + * API: PUT /api/game/ Create or update game + * @function createOrUpdate + * @memberof GamesController + */ + router.put('/', async (req, res)=>{ + + }); + + /** + * API: POST /api/game/ List games by given criteria + * @function list + * @returns {Game[]} + * @memberof GamesController + */ + router.post('/', async (req, res)=>{ + }) + + /** + * API: GET /api/game/:id Retrieve game by ID + * @function read + * @param {string} id The id of the game + * @returns {Game} + * @memberof GamesController + */ + router.get('/:id', async (req, res)=>{ + }) + + /** + * API: DELETE /api/game/:id Delete game by ID + * @function remove + * @param {string} id The id of the game + * @memberof GamesController + */ + router.delete('/:id', async (req, res)=>{ + }) + + app.webServer.xapp.use(this.route, router); } } diff --git a/backend/controllers/api/RulesController.js b/backend/controllers/api/RulesController.js index e69de29..be14e05 100644 --- a/backend/controllers/api/RulesController.js +++ b/backend/controllers/api/RulesController.js @@ -0,0 +1,60 @@ +import express from 'express'; + +/** + * RulesController. API for the game rules manager + */ +class RulesController{ + + name = 'rulesApi' + route = '/api/rule' + + /** + * Initializes the RulesController plugin + * @param {App} app The application instance + */ + init(app){ + const router = express.Router(); + const { rules } = app; + + /** + * API: PUT /api/rule/ Create or update rule + * @function createOrUpdate + * @memberof RulesController + */ + router.put('/', async (req, res)=>{ + + }); + + /** + * API: POST /api/rule/ List rules by given criteria + * @function list + * @returns {Rule[]} + * @memberof RulesController + */ + router.post('/', async (req, res)=>{ + }) + + /** + * API: GET /api/rule/:id Retrieve rule by ID + * @function read + * @param {string} id The id of the rule + * @returns {Rule} + * @memberof RulesController + */ + router.get('/:id', async (req, res)=>{ + }) + + /** + * API: DELETE /api/rule/:id Delete rule by ID + * @function remove + * @param {string} id The id of the rule + * @memberof RulesController + */ + router.delete('/:id', async (req, res)=>{ + }) + + app.webServer.xapp.use(this.route, router); + } +} + +export { RulesController } \ No newline at end of file diff --git a/backend/controllers/api/ScenariosController.js b/backend/controllers/api/ScenariosController.js index e69de29..e737874 100644 --- a/backend/controllers/api/ScenariosController.js +++ b/backend/controllers/api/ScenariosController.js @@ -0,0 +1,60 @@ +import express from 'express'; + +/** + * ScenariosController. API for the scenarios manager + */ +class ScenariosController{ + + name = 'scenariosApi' + route = '/api/scenario' + + /** + * Initializes the ScenariosController plugin + * @param {App} app The application instance + */ + init(app){ + const router = express.Router(); + const { scenarios } = app; + + /** + * API: PUT /api/scenario/ Create or update scenario + * @function createOrUpdate + * @memberof ScenariosController + */ + router.put('/', async (req, res)=>{ + + }); + + /** + * API: POST /api/scenario/ List scenarios by given criteria + * @function list + * @returns {Scenario[]} + * @memberof ScenariosController + */ + router.post('/', async (req, res)=>{ + }) + + /** + * API: GET /api/scenario/:id Retrieve scenario by ID + * @function read + * @param {string} id The id of the scenario + * @returns {Scenario} + * @memberof ScenariosController + */ + router.get('/:id', async (req, res)=>{ + }) + + /** + * API: DELETE /api/scenario/:id Delete scenario by ID + * @function remove + * @param {string} id The id of the scenario + * @memberof ScenariosController + */ + router.delete('/:id', async (req, res)=>{ + }) + + app.webServer.xapp.use(this.route, router); + } +} + +export { ScenariosController } \ No newline at end of file