dragonroll/backend/services/api.js

268 lines
6.6 KiB
JavaScript
Raw Normal View History

2024-10-05 10:57:47 +00:00
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
2024-10-14 13:50:47 +00:00
const express = require('express');
2024-10-05 12:31:09 +00:00
/**
2024-10-05 17:27:28 +00:00
* Class for managing the backend api
* @hideconstructor
2024-10-05 12:31:09 +00:00
*/
2024-10-05 17:27:28 +00:00
class BackendApi {
#_plugin;
#_router;
2024-10-14 17:25:46 +00:00
#_expressRouter;
#_internalSocket;
#_socket;
2024-10-05 17:27:28 +00:00
/**
* This object is already created for you
* @param {plugin} Plugin instance
*/
constructor(plugin, router, internalSocket){
2024-10-05 17:27:28 +00:00
this.#_plugin = plugin;
2024-10-14 17:25:46 +00:00
this.#_expressRouter = router;
this.#_internalSocket = internalSocket;
this.#_socket = new BackendSocket(`plugin/${plugin.package}`, internalSocket);
2024-10-14 17:25:46 +00:00
this.#_router = new BackendRouter(`plugin/${plugin.package}`, this.#_expressRouter);
2024-10-05 17:27:28 +00:00
}
2024-10-05 12:31:09 +00:00
2024-10-05 17:27:28 +00:00
/**
* Gets the router for your plugin
* @type {BackendRouter}
*/
get router(){
return this.#_router;
}
get socket(){
return this.#_socket;
}
get _socket(){
return internalSocket;
2024-10-14 13:50:47 +00:00
}
2024-10-05 17:27:28 +00:00
/**
* Returns a new database model for the plugin
* @param {String} name
* @param {Object} schema
2024-10-06 15:43:44 +00:00
* @returns {BackendModel}
* @example
* let itemModel = Api.createModel('Item', {
* name: {type: String, required: true, default: "New Item"},
* description: {type: String}
* type: {type: String, required: true, default: "Misc Item"},
* image: { type: String }
* });
2024-10-05 17:27:28 +00:00
*/
createModel(name, schema){
2024-10-14 13:50:47 +00:00
return new BackendModel(name, this.#_plugin.package, schema);
}
createModule(id){
return new BackendModule(this.#_plugin, id, this.#_expressRouter, this.#_internalSocket);
2024-10-05 17:27:28 +00:00
}
};
/**
* This class registers routes to the backend that can be accessed from the frontend
* @hideconstructor
*/
class BackendRouter {
#_root;
2024-10-14 17:25:46 +00:00
#_expressRouter
2024-10-05 17:27:28 +00:00
2024-10-14 17:25:46 +00:00
constructor(path, expressRouter){
this.#_root = `/${path}`;
this.#_expressRouter = expressRouter;
2024-10-05 12:31:09 +00:00
}
/**
* Hola
2024-10-05 17:27:28 +00:00
* @param {String} route
2024-10-05 12:31:09 +00:00
*/
2024-10-14 13:50:47 +00:00
get(route, callback){
2024-10-14 17:25:46 +00:00
this.#_expressRouter.get(this.#_root + route, callback);
2024-10-05 12:31:09 +00:00
}
/**
* @param {String} route
*
*/
2024-10-14 13:50:47 +00:00
post(route, callback){
2024-10-14 17:25:46 +00:00
this.#_expressRouter.post(this.#_root + route, callback);
2024-10-05 12:31:09 +00:00
}
/**
* @param {String} route
*
*/
2024-10-14 13:50:47 +00:00
put(route, callback){
2024-10-14 17:25:46 +00:00
this.#_expressRouter.put(this.#_root + route, callback);
2024-10-05 12:31:09 +00:00
}
/**
* @param {String} route
*
*/
2024-10-14 13:50:47 +00:00
delete(route, callback){
2024-10-14 17:25:46 +00:00
this.#_expressRouter.delete(this.#_root + route, callback);
2024-10-05 12:31:09 +00:00
}
2024-10-06 15:43:44 +00:00
/**
* Creates backend REST routes for the specified model. These routes are located
* relative to the plugin base route:
* - `/<plugin>/<model>` (POST) - Creates the element
* - `/<plugin>/<model>` (GET) - Gets a list with elements
* - `?id=<id>` return the document with that id
* - `?<paramName>=<paramValue>` returns all documents that match this criteria
* - `/<plugin>/<model>` (UPDATE) - Updates a element by id
* - `/<plugin>/<model>` (DELETE) - Deletes an element
* @param {BackendModel} model
*/
createModelRoutes(model, path){
}
2024-10-05 12:31:09 +00:00
}
2024-10-14 13:50:47 +00:00
class BackendModule {
#_plugin;
#_id;
#_router;
#_socket;
#_internalSocket;
2024-10-14 13:50:47 +00:00
constructor(plugin, id, expressRouter, internalSocket){
2024-10-14 13:50:47 +00:00
this.#_plugin = plugin;
this.#_id = id;
this.#_internalSocket = internalSocket;
2024-10-14 17:25:46 +00:00
this.#_router = new BackendRouter(`module/${plugin.package}/${id}`, expressRouter)
this.#_socket = new BackendSocket(`module/${plugin.package}/${id}`, this.#_internalSocket);
2024-10-14 13:50:47 +00:00
}
get router(){
return this.#_router;
}
get socket(){
return this.#_socket;
}
2024-10-14 18:02:53 +00:00
// Creates a model for the Module
2024-10-14 13:50:47 +00:00
createModel(name, schema){
return new BackendModel(name, `${this.#_plugin.package}/${this.#_id}`, schema);
}
}
2024-10-05 17:27:28 +00:00
/**
* @hideconstructor
*/
2024-10-05 23:36:18 +00:00
class BackendModel {
2024-10-05 17:27:28 +00:00
#_name;
2024-10-14 13:50:47 +00:00
#_prefix;
2024-10-05 17:27:28 +00:00
#_schema;
2024-10-14 13:50:47 +00:00
2024-10-06 15:43:44 +00:00
#_mongoSchema;
2024-10-05 10:57:47 +00:00
2024-10-14 13:50:47 +00:00
constructor(name, prefix, schema){
2024-10-05 17:27:28 +00:00
this.#_name = name;
2024-10-14 13:50:47 +00:00
this.#_prefix = prefix;
this.#_schema = ParseSchema(schema);
this.#_mongoSchema = mongoose.model(`${prefix}/${name}`, new Schema(schema));
2024-10-06 15:43:44 +00:00
}
/**
* Finds and returns a promise with the result of the query
* @param {Object} params
* @returns {Promise<Object>}
*/
find(params){
return this.#_mongoSchema.find(params);
}
/**
* Finds one element and returns a promise with the result of the query
* @param {Object} params
* @returns {Promise<Object>}
*/
findOne(params){
return this.#_mongoSchema.findOne(params);
}
/**
* Finds an element by id and returns a promise with the result of the query
* @param {String} id
* @returns {Promise<Object>}
*/
findById(id){
return this.#_mongoSchema.findById(id);
}
/**
* Creates an element given the data and returns a promise with the result of the operation
* @param {Object} data
* @returns {Promise<Object>}
*/
create(data){
return this.#_mongoSchema.create(data);
}
/**
* Updates an element given the parameters with the given data and returns a promise with the result of the operation
* @param {Object} params
* @param {Object} data
* @returns {Promise<Object>}
*/
updateOne(params, data){
return this.#_mongoSchema.updateOne(params, data);
}
/**
* Updates elements given the parameters with the given data and returns a promise with the result of the operation
* @param {Object} params
* @param {Object} data
* @returns {Promise<Object>}
*/
updateMany(params, data){
return this.#_mongoSchema.updateMany(params, data);
2024-10-05 10:57:47 +00:00
}
};
class BackendSocket {
#_prefix;
#_internalSocket;
constructor(prefix, internalSocket){
this.#_prefix = prefix;
this.#_internalSocket = internalSocket;
}
on(msg, callback){
this.#_internalSocket[`${this.#_prefix}/${msg}`] = callback;
}
}
2024-10-14 13:50:47 +00:00
function ParseSchema(schema){
const typeTable = {
String: String,
Object: Object,
ObjectId: mongoose.Types.ObjectId,
Boolean: Boolean,
Date: Date,
};
let newSchema = structuredClone(schema);
2024-10-06 15:43:44 +00:00
2024-10-14 13:50:47 +00:00
// 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];
2024-10-06 15:43:44 +00:00
}
2024-10-14 13:50:47 +00:00
return newSchema;
2024-10-06 15:43:44 +00:00
}
2024-10-05 10:57:47 +00:00
module.exports = {
2024-10-05 17:27:28 +00:00
BackendApi
2024-10-05 10:57:47 +00:00
}