diff --git a/.gitignore b/.gitignore index e6e7ad24..80f1cfe5 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,9 @@ client/public/plugins/ # Backend backend/plugins/ +# Docs +docs/ + # local env files .env.local .env.*.local diff --git a/README.md b/README.md index 7b8d0d7c..86fde3df 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ - - + + Shows a black logo in light color mode and a white one in dark color mode.
diff --git a/backend/services/api.js b/backend/services/api.js new file mode 100644 index 00000000..1334c0f1 --- /dev/null +++ b/backend/services/api.js @@ -0,0 +1,24 @@ +const mongoose = require("mongoose"); +const Schema = mongoose.Schema; + +class BackendApi { + /** + * Plugin + * @param {plugin} Plugin instance + */ + constructor(plugin){ + this.plugin = plugin; + } + + createRoute(){ + + } + + createModel(name, schema){ + return mongoose.model(name, new Schema(schema)) + } +}; + +module.exports = { + BackendApi +} \ No newline at end of file diff --git a/backend/services/plugins.js b/backend/services/plugins.js index 5c9f8c92..7e0cb209 100644 --- a/backend/services/plugins.js +++ b/backend/services/plugins.js @@ -1,6 +1,6 @@ const fs = require('fs'); const path = require('path') -const Api = {} +const Api = require('./api').Api const basePath = path.resolve(__dirname, '../') console.log(basePath) @@ -25,7 +25,7 @@ function init(){ // Execute main Object.keys(plugins).forEach(k => { - plugins[k].Main(Api) + plugins[k].Main(new Api(k)) }) } diff --git a/build.sh b/build.sh new file mode 100755 index 00000000..f5a47307 --- /dev/null +++ b/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +node prebuild.js +npm run generate-docs +cp -r media docs/dragonroll/1.0.0/ \ No newline at end of file diff --git a/client/src/services/Api.js b/client/src/services/Api.js index b9948726..ef480e9a 100644 --- a/client/src/services/Api.js +++ b/client/src/services/Api.js @@ -1,13 +1,23 @@ -import axios from 'axios'; +import * as Dragonroll from "@/services/Dragonroll" +import * as Chat from "@/services/Chat" +import * as ContextMenu from "@/services/ContextMenu" +import * as Map from "@/services/Map" +import * as Modules from "@/services/Modules" +import * as Sound from "@/services/Sound" +import * as Tooltip from "@/services/Tooltip" +import * as Windows from "@/services/Windows" -import { backendUrl } from './BackendURL'; +const Api = { + Dragonroll, + Chat, + ContextMenu, + Map, + Modules, + Sound, + Tooltip, + Windows +} -export default () => { - return axios.create({ - baseURL: backendUrl, - headers: { - 'Authorization': "Bearer " + localStorage.getItem('token'), - "Access-Control-Allow-Origin": "*", - } - }); +export { + Api } \ No newline at end of file diff --git a/client/src/services/Campaign.js b/client/src/services/Campaign.js index a867db3d..81f39db0 100644 --- a/client/src/services/Campaign.js +++ b/client/src/services/Campaign.js @@ -6,7 +6,7 @@ import { GetUser } from "./User"; import { chat } from './Chat'; import { ClearAll, CreateWindow } from './Windows'; -import Api from '@/services/Api'; +import Server from '@/services/Server'; import { GetCampaign } from './Dragonroll'; let _currentCampaign = null; @@ -37,7 +37,7 @@ function DisplayCampaign(data = _currentCampaign){ } function UpdateCampaignData(data){ - Api().put('/campaign/update?campaign=' + GetCampaign()._id, {campaign: data}).then(response => { + Server().put('/campaign/update?campaign=' + GetCampaign()._id, {campaign: data}).then(response => { }); } diff --git a/client/src/services/Data.js b/client/src/services/Data.js index 9801d585..15f921bd 100644 --- a/client/src/services/Data.js +++ b/client/src/services/Data.js @@ -1,4 +1,4 @@ -import Api from '@/services/Api' +import Server from '@/services/Server' import { GetCampaign } from "./Dragonroll"; import { socket } from './Socket'; import { reactive } from 'vue'; @@ -12,7 +12,7 @@ function InitData(){ } function FetchConcepts(){ - Api().get('/concept/list?campaign=' + GetCampaign()._id).then(response => { + Server().get('/concept/list?campaign=' + GetCampaign()._id).then(response => { data.value.concepts = response.data.data; }).catch((err) => console.log(err)); } @@ -27,7 +27,7 @@ socket.on('update-concepts', () => { }); let GetConcepts = () => data.value.concepts; -let GetConcept = (id) => Api().get('/concept/get?campaign=' + GetCampaign()._id + "&id=" + id) +let GetConcept = (id) => Server().get('/concept/get?campaign=' + GetCampaign()._id + "&id=" + id) export { diff --git a/client/src/services/Map.js b/client/src/services/Map.js index 505193e2..f094162a 100644 --- a/client/src/services/Map.js +++ b/client/src/services/Map.js @@ -1,6 +1,6 @@ import { initCustomFormatter, ref, toRaw } from 'vue'; -import Api from '@/services/Api' +import Server from '@/services/Server' import { _SendMap, GetCampaign } from './Dragonroll'; import { backendUrl } from './BackendURL'; import { socket } from './Socket'; @@ -213,7 +213,7 @@ function GetMap(id){ function UpdateMapList(){ return new Promise((resolve, reject) => { - Api().get('/maps/list?campaign=' + GetCampaign()._id).then(response => { + Server().get('/maps/list?campaign=' + GetCampaign()._id).then(response => { mapList.value = response.data.data; resolve(); }).catch((err) => console.log(err)); @@ -237,7 +237,7 @@ function RenameMap(id, new_title){ } function SaveMap(id){ - Api().post('/maps/update?campaign=' + GetCampaign()._id + "&map=" + id, {data: currentMap}).then(response => { + Server().post('/maps/update?campaign=' + GetCampaign()._id + "&map=" + id, {data: currentMap}).then(response => { console.log("Map updated"); }).catch(err => console.log(err)); } @@ -263,7 +263,7 @@ function UploadResource(image){ const formData = new FormData(); formData.append("image", dataURLtoFile(image.src)); - Api().post('/maps/create-resource?campaign=' + GetCampaign()._id, formData, { + Server().post('/maps/create-resource?campaign=' + GetCampaign()._id, formData, { headers: { "Content-Type": "multipart/form-data"} }).then(response => { resolve(response.data.data); @@ -272,7 +272,7 @@ function UploadResource(image){ } function CreateMap(){ - Api().post('/maps/create', { + Server().post('/maps/create', { campaign: GetCampaign()._id, data: currentMap, }).then(response => { diff --git a/client/src/services/Plugins.js b/client/src/services/Plugins.js index b4503c23..fac74277 100644 --- a/client/src/services/Plugins.js +++ b/client/src/services/Plugins.js @@ -1,13 +1,5 @@ import { GetPluginPaths } from "./Resources" - -import * as Dragonroll from "@/services/Dragonroll" -import * as Chat from "@/services/Chat" -import * as ContextMenu from "@/services/ContextMenu" -import * as Map from "@/services/Map" -import * as Modules from "@/services/Modules" -import * as Sound from "@/services/Sound" -import * as Tooltip from "@/services/Tooltip" -import * as Windows from "@/services/Windows" +import { Api } from '@/services/Api' let pluginInfo = [] @@ -31,16 +23,7 @@ async function FetchPlugins(){ }); import(/* @vite-ignore */ `../../plugins/${pluginName}/${pluginData.client.entrypoint}`).then(module => { - module.Main({ - Dragonroll, - Chat, - ContextMenu, - Map, - Modules, - Sound, - Tooltip, - Windows - }); + module.Main(Api); }) } } diff --git a/client/src/services/Server.js b/client/src/services/Server.js new file mode 100644 index 00000000..b9948726 --- /dev/null +++ b/client/src/services/Server.js @@ -0,0 +1,13 @@ +import axios from 'axios'; + +import { backendUrl } from './BackendURL'; + +export default () => { + return axios.create({ + baseURL: backendUrl, + headers: { + 'Authorization': "Bearer " + localStorage.getItem('token'), + "Access-Control-Allow-Origin": "*", + } + }); +} \ No newline at end of file diff --git a/client/src/services/User.js b/client/src/services/User.js index 85f2da91..b2f0e38e 100644 --- a/client/src/services/User.js +++ b/client/src/services/User.js @@ -1,5 +1,5 @@ import { ref } from 'vue'; -import Api from '@/services/Api' +import Server from '@/services/Server' const UserStatus = ref(0); @@ -20,7 +20,7 @@ function SetUser(token){ } async function HasAdmin(){ - let response = await Api().get('/user/has-admin'); + let response = await Server().get('/user/has-admin'); return response.data.status != "init"; } @@ -29,7 +29,7 @@ function SetUserSetting(key, value){ let user = GetUser() if(!user.settings) user.settings = {}; user.settings[key] = value; - Api().post('/user/update-settings', {settings: user.settings}).then(response => { + Server().post('/user/update-settings', {settings: user.settings}).then(response => { resolve(response.data.settings); }); }); @@ -37,7 +37,7 @@ function SetUserSetting(key, value){ function GetUserSetting(key){ return new Promise((resolve, reject) => { - Api().get('/user/get-settings').then(response => { + Server().get('/user/get-settings').then(response => { if(response.data.settings) resolve(response.data.settings[key]); else resolve(undefined); diff --git a/client/src/views/HomeView.vue b/client/src/views/HomeView.vue index ebb8889f..4ceabea1 100644 --- a/client/src/views/HomeView.vue +++ b/client/src/views/HomeView.vue @@ -5,7 +5,7 @@ const { t } = useI18n() import { onMounted } from 'vue'; import WindowManager from '@/views/managers/WindowManager.vue' -import Api from '@/services/Api' +import Server from '@/services/Server' import { CreateWindow } from '@/services/Windows' import { GetUser, HasAdmin, LoadUser } from '@/services/User.js' import { DisplayToast, SetEmitter } from '@/services/Dragonroll'; @@ -35,7 +35,7 @@ async function DisplayFirstWindow(){ // Check if we have a link if(route.query.setupCode){ // Let's try to activate it - Api().get('/user/verify-setup?code=' + route.query.setupCode).then(res => { + Server().get('/user/verify-setup?code=' + route.query.setupCode).then(res => { if(res.data.code){ // Yep exists CreateWindow('setup_account', { diff --git a/client/src/views/partials/CampaignEntry.vue b/client/src/views/partials/CampaignEntry.vue index c7a07ba0..10f87181 100644 --- a/client/src/views/partials/CampaignEntry.vue +++ b/client/src/views/partials/CampaignEntry.vue @@ -2,7 +2,7 @@ import { onMounted, ref } from 'vue'; -import Api from '@/services/Api' +import Server from '@/services/Server' import { AddSound } from '../../services/Sound'; import { ConnectToCampaign, DisplayCampaign } from '../../services/Campaign'; diff --git a/client/src/views/partials/EditUserPartial.vue b/client/src/views/partials/EditUserPartial.vue index 7640ccb9..4a0bdbc2 100644 --- a/client/src/views/partials/EditUserPartial.vue +++ b/client/src/views/partials/EditUserPartial.vue @@ -2,7 +2,7 @@ import { onMounted, ref } from 'vue'; import { GetUser, LogoutUser } from '@/services/User' -import Api from '@/services/Api' +import Server from '@/services/Server' import useEmitter from '@/services/Emitter'; import { ClearWindows, CreateWindow, CreateChildWindow, ClearWindow } from '../../services/Windows'; @@ -14,7 +14,7 @@ username.value = GetUser().username; function retrieveAvatar(){ let userAvatarDisplay = document.getElementById("upload-image"); - Api().get('/user/retrieve-avatar?username=' + GetUser().username).then((response) => { + Server().get('/user/retrieve-avatar?username=' + GetUser().username).then((response) => { if(response.data.image) userAvatarDisplay.src = backendUrl + "public/" + response.data.image; }).catch((err) => console.log("Internal error")); } @@ -53,7 +53,7 @@ onMounted(() => { formData.append("image", image); - Api().post('/user/upload-avatar', formData, { + Server().post('/user/upload-avatar', formData, { headers: { "Content-Type": "multipart/form-data" } }).then((response) => { retrieveAvatar(); diff --git a/client/src/views/partials/PlayerEntry.vue b/client/src/views/partials/PlayerEntry.vue index 742f8ca3..dbd60c0c 100644 --- a/client/src/views/partials/PlayerEntry.vue +++ b/client/src/views/partials/PlayerEntry.vue @@ -1,6 +1,6 @@