Backend dynamic routing
Some checks failed
test / run-tests-client (push) Successful in 43s
test / run-tests-backend (push) Failing after 15s

This commit is contained in:
BinarySandia04 2024-10-14 15:50:47 +02:00
parent c6e07e7b41
commit d005aa3cc1
5 changed files with 147 additions and 63 deletions

View File

@ -73,8 +73,6 @@ app.use('/user', require('./routes/user'));
checkAuth = passport.authenticate('jwt', {session: false}); checkAuth = passport.authenticate('jwt', {session: false});
app.use(checkAuth); app.use(checkAuth);
if(process.env.NODE_ENV != 'test')
pluginManager.init();
// ROUTES WITH AUTH // ROUTES WITH AUTH
app.use('/campaign', require('./routes/campaign')); app.use('/campaign', require('./routes/campaign'));
@ -83,9 +81,46 @@ app.use('/concept', require('./routes/concept'))
app.use('/admin', require('./routes/admin')) app.use('/admin', require('./routes/admin'))
// GET localhost:8081/concept/list // GET localhost:8081/concept/list
const pluginData = pluginManager.init();
app.use('/', pluginData.router);
// SETUP IO // SETUP IO
require('./io/campaign')(socket.getIo()); require('./io/campaign')(socket.getIo());
// DEBUG ROUTER
function print (path, layer) {
if (layer.route) {
layer.route.stack.forEach(print.bind(null, path.concat(split(layer.route.path))))
} else if (layer.name === 'router' && layer.handle.stack) {
layer.handle.stack.forEach(print.bind(null, path.concat(split(layer.regexp))))
} else if (layer.method) {
console.log('%s /%s',
layer.method.toUpperCase(),
path.concat(split(layer.regexp)).filter(Boolean).join('/'))
}
}
function split (thing) {
if (typeof thing === 'string') {
return thing.split('/')
} else if (thing.fast_slash) {
return ''
} else {
var match = thing.toString()
.replace('\\/?', '')
.replace('(?=\\/|$)', '$')
.match(/^\/\^((?:\\[.*+?^${}()|[\]\\\/]|[^.*+?^${}()|[\]\\\/])*)\$\//)
return match
? match[1].replace(/\\(.)/g, '$1').split('/')
: '<complex:' + thing.toString() + '>'
}
}
app._router.stack.forEach(print.bind(null, []))
// END DEBUG
// LISTEN // LISTEN
server.listen(PORT, () => { server.listen(PORT, () => {
console.log("Dragonroll backend started"); console.log("Dragonroll backend started");

View File

@ -1,6 +1,9 @@
const mongoose = require("mongoose"); const mongoose = require("mongoose");
const Schema = mongoose.Schema; const Schema = mongoose.Schema;
const express = require('express');
const router = express.Router();
/** /**
* Class for managing the backend api * Class for managing the backend api
* @hideconstructor * @hideconstructor
@ -15,7 +18,7 @@ class BackendApi {
*/ */
constructor(plugin){ constructor(plugin){
this.#_plugin = plugin; this.#_plugin = plugin;
this.#_router = new BackendRouter(plugin.package); this.#_router = new BackendRouter(`/plugin/${plugin.package}`);
} }
/** /**
@ -26,6 +29,10 @@ class BackendApi {
return this.#_router; return this.#_router;
} }
get _router(){
return router;
}
/** /**
* Returns a new database model for the plugin * Returns a new database model for the plugin
* @param {String} name * @param {String} name
@ -40,7 +47,11 @@ class BackendApi {
* }); * });
*/ */
createModel(name, schema){ createModel(name, schema){
return new BackendModel(name, this.#_plugin, schema); return new BackendModel(name, this.#_plugin.package, schema);
}
createModule(id){
return new BackendModule(this.#_plugin, id);
} }
}; };
@ -59,32 +70,32 @@ class BackendRouter {
* Hola * Hola
* @param {String} route * @param {String} route
*/ */
get(route){ get(route, callback){
router.get(this.#_root + route, callback);
} }
/** /**
* @param {String} route * @param {String} route
* *
*/ */
post(route){ post(route, callback){
router.post(this.#_root + route, callback);
} }
/** /**
* @param {String} route * @param {String} route
* *
*/ */
put(route){ put(route, callback){
router.put(this.#_root + route, callback);
} }
/** /**
* @param {String} route * @param {String} route
* *
*/ */
delete(route){ delete(route, callback){
router.delete(this.#_root + route, callback);
} }
/** /**
@ -103,20 +114,41 @@ class BackendRouter {
} }
} }
class BackendModule {
#_plugin;
#_id;
#_router;
constructor(plugin, id){
this.#_plugin = plugin;
this.#_id = id;
this.#_router = new BackendRouter(`/module/${plugin.package}/${id}`)
}
get router(){
return this.#_router;
}
createModel(name, schema){
return new BackendModel(name, `${this.#_plugin.package}/${this.#_id}`, schema);
}
}
/** /**
* @hideconstructor * @hideconstructor
*/ */
class BackendModel { class BackendModel {
#_name; #_name;
#_plugin; #_prefix;
#_schema; #_schema;
#_mongoSchema; #_mongoSchema;
constructor(name, plugin, schema){ constructor(name, prefix, schema){
this.#_name = name; this.#_name = name;
this.#_plugin = plugin; this.#_prefix = prefix;
this.#_schema = schema; this.#_schema = ParseSchema(schema);
this.#_mongoSchema = mongoose.model(`${plugin}/${name}`, new Schema(schema)); this.#_mongoSchema = mongoose.model(`${prefix}/${name}`, new Schema(schema));
} }
/** /**
@ -176,19 +208,27 @@ class BackendModel {
} }
}; };
/** function ParseSchema(schema){
* @hideconstructor const typeTable = {
*/ String: String,
class BackendModelDocument { Object: Object,
ObjectId: mongoose.Types.ObjectId,
Boolean: Boolean,
save(){ Date: Date,
};
let newSchema = structuredClone(schema);
// Codi molt guai
for(const key in newSchema){
if(Array.isArray(newSchema[key].type))
newSchema[key][0].type = [ typeTable[newSchema[key][0].type] ];
else
newSchema[key].type = typeTable[newSchema[key].type];
} }
return newSchema;
} }
module.exports = { module.exports = {
BackendApi BackendApi
} }

View File

@ -1,6 +1,8 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path') const path = require('path')
const BackendApi = require('./api').BackendApi const BackendApi = require('./api').BackendApi
const express = require('express');
const router = express.Router();
const basePath = path.resolve(__dirname, '../') const basePath = path.resolve(__dirname, '../')
console.log(basePath) console.log(basePath)
@ -25,8 +27,16 @@ function init(){
// Execute main // Execute main
Object.keys(plugins).forEach(k => { Object.keys(plugins).forEach(k => {
plugins[k].payload.Main(new BackendApi(plugins[k].info)) let pluginApi = new BackendApi(plugins[k].info);
}) plugins[k].payload.Main(pluginApi);
router.use(pluginApi._router);
});
return {
router
}
} }
module.exports = { module.exports = {

View File

@ -24,7 +24,7 @@ class ClientApi {
*/ */
constructor(plugin){ constructor(plugin){
this.#_plugin = plugin this.#_plugin = plugin
this.#_router = new ClientRouter(plugin.package) this.#_router = new ClientRouter(`/plugin/${plugin.package}`)
this.#_windows = new ClientWindows(plugin.package) this.#_windows = new ClientWindows(plugin.package)
this.#_socket = new ClientSocket(plugin.package) this.#_socket = new ClientSocket(plugin.package)
} }
@ -144,6 +144,8 @@ class ClientView {
class ClientModule { class ClientModule {
#_plugin; #_plugin;
#_id; #_id;
#_router;
#_title; #_title;
#_description; #_description;
#_version; #_version;
@ -153,13 +155,12 @@ class ClientModule {
#_init; #_init;
#_exit; #_exit;
#_character_sheet;
#_item_sheet;
#_item_prompt;
constructor(plugin, id){ constructor(plugin, id){
this.#_plugin = plugin; this.#_plugin = plugin;
this.#_id = id; this.#_id = id;
this.#_router = new ClientRouter(`/module/${plugin.package}/${id}`);
} }
/** /**
@ -196,34 +197,14 @@ class ClientModule {
set exit(exit){ this.#_exit = exit; } set exit(exit){ this.#_exit = exit; }
/**
*
* @param {ClientView} window
*/
setCharacterSheet(window){
this.#_character_sheet = window;
}
/**
*
* @param {ClientView} window
*/
setItemSheet(window){
this.#_item_sheet = window;
}
/**
*
* @param {ClientView} window
*/
setItemPrompt(window){
this.#_item_prompt = window;
}
setButtons(buttons){ setButtons(buttons){
this.#_buttons = buttons; this.#_buttons = buttons;
} }
get router(){
return this.#_router;
}
/** /**
* Gets the module info in a json format * Gets the module info in a json format
* @returns {Object} * @returns {Object}
@ -236,11 +217,6 @@ class ClientModule {
version: this.#_version, version: this.#_version,
color: this.#_color, color: this.#_color,
icon: this.#_icon, icon: this.#_icon,
windows: {
character_sheet: this.#_character_sheet,
item_sheet: this.#_item_sheet,
create_item_prompt: this.#_item_prompt,
},
init: this.#_init, init: this.#_init,
exit: () => {}, exit: () => {},
buttons: this.#_buttons buttons: this.#_buttons

View File

@ -1,6 +1,29 @@
// Entrypoint // Entrypoint
function Main(Api){ let Api;
function Main(api){
Api = api;
console.log("Hello World from backend!"); console.log("Hello World from backend!");
// Create our module in the backend. We only need the package name, it must be equal to the one that
// we made inside the client
let dndModule = Api.createModule('dnd-5e');
let itemModel = Api.createModel("item", {
name: { type: "String", required: true, default: "New Concept"},
type: { type: "String", required: true, default: "Concept" },
info: { type: "Object" }, // For preview only
data: { type: "Object" }, // Advanced item
book: { type: "ObjectId", ref: "Book"},
campaign: { type: "ObjectId", ref: "Campaign"},
});
dndModule.router.get('/test', (req, res) => {
console.log("FUNCIONA!!!!");
})
// Api.router.createModelRoutes(itemModel, 'item');
} }
export { Main }; export { Main, Api };