From 0e363e58df2f4267d0ed9469ec90017d0ac18a6e Mon Sep 17 00:00:00 2001 From: TheArcaneBrony Date: Sat, 13 Aug 2022 08:54:50 +0200 Subject: [PATCH] Update plugin loading, update example plugin, add ci task for testing if builds work --- .github/workflows/test_build.yml | 29 +++++ scripts/build.js | 116 ++++++++++++++++++++ src/Server.ts | 0 src/plugins/example-plugin/ExamplePlugin.ts | 7 ++ src/plugins/example-plugin/plugin.json | 10 ++ src/util/index.ts | 8 +- src/util/plugin/Plugin.ts | 9 +- src/util/plugin/PluginLoader.ts | 4 +- src/util/plugin/PluginManifest.ts | 1 + 9 files changed, 178 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/test_build.yml create mode 100644 scripts/build.js create mode 100644 src/Server.ts create mode 100644 src/plugins/example-plugin/ExamplePlugin.ts create mode 100644 src/plugins/example-plugin/plugin.json diff --git a/.github/workflows/test_build.yml b/.github/workflows/test_build.yml new file mode 100644 index 000000000..dd8744e09 --- /dev/null +++ b/.github/workflows/test_build.yml @@ -0,0 +1,29 @@ +on: + workflow_dispatch: + push: + paths: + - "**" + +name: Test Build + +jobs: + insiders-build: + strategy: + matrix: + os: [windows, macos, ubuntu] + include: + - os: windows + - os: macos + - os: ubuntu + runs-on: ${{ matrix.os }}-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + env: + MONGOMS_VERSION: 4.4.3 + with: + node-version: 18 + - run: | + cd bundle + npm run setup + npm run build clean logerrors pretty-errors propagate-err diff --git a/scripts/build.js b/scripts/build.js new file mode 100644 index 000000000..7421aa4fb --- /dev/null +++ b/scripts/build.js @@ -0,0 +1,116 @@ +const { execSync } = require("child_process"); +const path = require("path"); +const fs = require("fs"); +const { argv, stdout, exit } = require("process"); +const { execIn, parts, getDirs, walk, sanitizeVarName } = require("./utils"); + +if (argv.includes("help")) { + console.log(`Fosscord build script help: +Arguments: + clean Cleans up previous builds + verbose Enable verbose logging + logerrors Log build errors to console + pretty-errors Pretty-print build errors + silent No output to console or files. + propagate-err Exit script with error code if build fails.`); + exit(0); +} + +let steps = 5, + i = 0; +if (argv.includes("clean")) steps++; + +const verbose = argv.includes("verbose") || argv.includes("v"); +const logerr = argv.includes("logerrors"); +const pretty = argv.includes("pretty-errors"); +const silent = argv.includes("silent"); + +if (silent) console.error = console.log = function () {}; + +if (argv.includes("clean")) { + console.log(`[${++i}/${steps}] Cleaning...`); + let d = "../" + "/dist"; + if (fs.existsSync(d)) { + fs.rmSync(d, { recursive: true }); + if (verbose) console.log(`Deleted ${d}!`); + } +} + +console.log(`[${++i}/${steps}] Compiling src files ...`); + +let buildFlags = ""; +if (pretty) buildFlags += "--pretty "; + +console.log(`[${++i}/${steps}] Building plugin index...`); +let pluginDir = path.join(__dirname, "..", "src", "plugins"); +let output = 'import { Plugin } from "util/plugin";\n'; + +const dirs = fs.readdirSync(pluginDir).filter((x) => { + try { + fs.readdirSync(path.join(pluginDir, x)); + return true; + } catch (e) { + return false; + } +}); +dirs.forEach((x) => { + let pluginManifest = require(path.join(pluginDir, x, "plugin.json")); + output += `import * as ${sanitizeVarName(x)} from "./${x}/${pluginManifest.mainClass}";\n`; +}); +output += `\nexport const PluginIndex: any = {\n`; +dirs.forEach((x) => { + output += ` "${x}": new ${sanitizeVarName(x)}.default(),\n`; //ctor test: '${path.resolve(path.join(pluginDir, x))}', require('./${x}/plugin.json') +}); +output += `};`; + +fs.writeFileSync(path.join(__dirname, "..", "src", "plugins", "PluginIndex.ts"), output); + +if (!argv.includes("copyonly")) { + console.log(`[${++i}/${steps}] Compiling source code...`); + + let buildFlags = ""; + if (pretty) buildFlags += "--pretty "; + + try { + execSync( + 'node "' + + path.join(__dirname, "..", "node_modules", "typescript", "lib", "tsc.js") + + '" -p "' + + path.join(__dirname, "..") + + '" ' + + buildFlags, + { + cwd: path.join(__dirname, ".."), + shell: true, + env: process.env, + encoding: "utf8" + } + ); + } catch (error) { + if (verbose || logerr) { + error.stdout.split(/\r?\n/).forEach((line) => { + let _line = line.replace("dist/", "", 1); + if (!pretty && _line.includes(".ts(")) { + //reformat file path for easy jumping + _line = _line.replace("(", ":", 1).replace(",", ":", 1).replace(")", "", 1); + } + console.error(_line); + }); + } + console.error(`Build failed! Please check build.log for info!`); + if (!silent) { + if (pretty) fs.writeFileSync("build.log.ansi", error.stdout); + fs.writeFileSync( + "build.log", + error.stdout.replaceAll(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "") + ); + } + throw error; + } +} + +console.log(`[${++i}/${steps}] Copying plugin data...`); +let pluginFiles = walk(pluginDir).filter((x) => !x.endsWith(".ts")); +pluginFiles.forEach((x) => { + fs.copyFileSync(x, x.replace("src", "dist")); +}); diff --git a/src/Server.ts b/src/Server.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/plugins/example-plugin/ExamplePlugin.ts b/src/plugins/example-plugin/ExamplePlugin.ts new file mode 100644 index 000000000..e6f706574 --- /dev/null +++ b/src/plugins/example-plugin/ExamplePlugin.ts @@ -0,0 +1,7 @@ +import { Plugin } from "@fosscord/util"; + +export default class TestPlugin extends Plugin { + onPluginLoaded(): void { + console.log("Hello from test plugin! IT WORKS!!!!!!!"); + } +} \ No newline at end of file diff --git a/src/plugins/example-plugin/plugin.json b/src/plugins/example-plugin/plugin.json new file mode 100644 index 000000000..2fcb7a008 --- /dev/null +++ b/src/plugins/example-plugin/plugin.json @@ -0,0 +1,10 @@ +{ + "id": "example-plugin", + "name": "Fosscord example plugin", + "authors": [ + "The Arcane Brony" + ], + "repository": "https://github.com/fosscord/fosscord-server", + "license": "", + "index": "ExamplePlugin.js" +} diff --git a/src/util/index.ts b/src/util/index.ts index 9a84d1af2..802e6f5b2 100644 --- a/src/util/index.ts +++ b/src/util/index.ts @@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 Spacebar and Spacebar Contributors - + This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ @@ -29,3 +29,5 @@ export * from "./imports"; export * from "./config"; export * from "./connections"; export * from "./Signing"; +export * from "./schemas"; +export * from "./plugin"; \ No newline at end of file diff --git a/src/util/plugin/Plugin.ts b/src/util/plugin/Plugin.ts index 96e058436..1c86a0067 100644 --- a/src/util/plugin/Plugin.ts +++ b/src/util/plugin/Plugin.ts @@ -6,7 +6,14 @@ type PluginEvents = { loaded: () => void; }; -export class Plugin extends (EventEmitter as new () => TypedEventEmitter) { +//this doesnt work, check later: + //(EventEmitter as new () => TypedEventEmitter) { +export class Plugin extends EventEmitter { + private _untypedOn = this.on + private _untypedEmit = this.emit + public on = (event: K, listener: PluginEvents[K]): this => this._untypedOn(event, listener) + public emit = (event: K, ...args: Parameters): boolean => this._untypedEmit(event, ...args) + async init() { // insert default config into database? } diff --git a/src/util/plugin/PluginLoader.ts b/src/util/plugin/PluginLoader.ts index b46ef269a..e69cb4998 100644 --- a/src/util/plugin/PluginLoader.ts +++ b/src/util/plugin/PluginLoader.ts @@ -2,7 +2,7 @@ import path from "path"; import fs from "fs"; import { Plugin, PluginManifest } from "./"; -const root = process.env.PLUGIN_LOCATION || "../plugins"; +const root = process.env.PLUGIN_LOCATION || "dist/plugins"; let pluginsLoaded = false; export class PluginLoader { @@ -24,7 +24,7 @@ export class PluginLoader { console.log( `Plugin info: ${manifest.name} (${manifest.id}), written by ${manifest.authors}, available at ${manifest.repository}` ); - const module_ = require(path.join(modPath, "dist", "index.js")) as Plugin; + const module_ = require(path.join(modPath, manifest.index)) as Plugin; try { await module_.init(); module_.emit("loaded"); diff --git a/src/util/plugin/PluginManifest.ts b/src/util/plugin/PluginManifest.ts index b171956b4..01b2b0844 100644 --- a/src/util/plugin/PluginManifest.ts +++ b/src/util/plugin/PluginManifest.ts @@ -6,4 +6,5 @@ export class PluginManifest { license: string; version: string // semver versionCode: number // integer + index: string; } \ No newline at end of file