diff --git a/.gitignore b/.gitignore
index 03642d8..a58b7b4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
.devenv
.devenv.flake.nix
-.idea
\ No newline at end of file
+.idea
+node_modules
\ No newline at end of file
diff --git a/.idea/discord.xml b/.idea/discord.xml
index 30bab2a..d8e9561 100644
--- a/.idea/discord.xml
+++ b/.idea/discord.xml
@@ -1,7 +1,7 @@
-
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index afbe93f..35eb1dd 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,6 +2,5 @@
-
\ No newline at end of file
diff --git a/apps/backend/package.json b/apps/backend/package.json
index da69ca7..ced3a46 100644
--- a/apps/backend/package.json
+++ b/apps/backend/package.json
@@ -16,6 +16,7 @@
"@nestjs/core": "^10.0.0",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/typeorm": "^10.0.1",
+ "glob": "^10.4.2",
"mongodb": "^6.7.0",
"pg": "^8.11.3",
"typeorm": "^0.3.17"
diff --git a/apps/backend/src/app.controller.ts b/apps/backend/src/app.controller.ts
deleted file mode 100644
index ae7af0a..0000000
--- a/apps/backend/src/app.controller.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { Controller, Get } from '@nestjs/common';
-import { AppService } from './app.service';
-
-@Controller()
-export class AppController {
- constructor(private readonly appService: AppService) {}
-
- @Get()
- createUser() {
- return this.appService.createUser();
- }
-}
diff --git a/apps/backend/src/app.module.ts b/apps/backend/src/app.module.ts
index 7c9a4e6..2fab81f 100644
--- a/apps/backend/src/app.module.ts
+++ b/apps/backend/src/app.module.ts
@@ -1,8 +1,7 @@
-import { Module } from '@nestjs/common';
+import { Module, type Type } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
-import { AppController } from './app.controller';
-import { AppService } from './app.service';
import { User } from './entities/user.entity';
+import { PluginModule } from "./common/plugins/plugin.module";
const userForFeature = TypeOrmModule.forFeature([User]);
@@ -10,18 +9,20 @@ const userForFeature = TypeOrmModule.forFeature([User]);
imports: [
TypeOrmModule.forRoot({
type: "mongodb",
- host: "localhost",
+ host: "127.0.0.1",
port: 27017,
username: "homespace",
password: "homespace",
- database: "homespace",
+ database: "test",
+ authSource: "admin",
synchronize: true,
logging: false,
entities: [User],
}),
userForFeature,
+ PluginModule.register()
],
- controllers: [AppController],
- providers: [AppService],
+ controllers: [],
+ providers: [],
})
export class AppModule {}
diff --git a/apps/backend/src/app.service.ts b/apps/backend/src/app.service.ts
deleted file mode 100644
index 58a6ac5..0000000
--- a/apps/backend/src/app.service.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { Injectable } from '@nestjs/common';
-import { InjectRepository } from '@nestjs/typeorm';
-import type { Repository } from 'typeorm';
-import { User } from './entities/user.entity';
-
-@Injectable()
-export class AppService {
- constructor(
- @InjectRepository(User)
- private readonly userRepository: Repository,
- ) {}
-
- async createUser() {
- const user = this.userRepository.create({
- firstName: 'Johannes',
- lastName: 'Reckers',
- age: 18,
- });
-
- const entity = await this.userRepository.save(user);
- return entity;
- }
-}
diff --git a/apps/backend/src/common/plugins/plugin.interface.ts b/apps/backend/src/common/plugins/plugin.interface.ts
index ffe1d28..3c8e041 100644
--- a/apps/backend/src/common/plugins/plugin.interface.ts
+++ b/apps/backend/src/common/plugins/plugin.interface.ts
@@ -1,3 +1,5 @@
+import {INestApplication} from "@nestjs/common";
+
export interface Plugin {
- register(): void
+ register(app: INestApplication): void
}
\ No newline at end of file
diff --git a/apps/backend/src/common/plugins/plugin.loader.ts b/apps/backend/src/common/plugins/plugin.loader.ts
new file mode 100644
index 0000000..f4ac565
--- /dev/null
+++ b/apps/backend/src/common/plugins/plugin.loader.ts
@@ -0,0 +1,20 @@
+import { glob } from 'glob';
+import { join } from 'path';
+
+export async function loadPlugins(): Promise {
+ return new Promise(async (resolve, reject) => {
+ const files = await glob('homespace-shared/plugins/**/*.plugin.{ts,js}');
+
+ console.log(files)
+
+ const plugins = [];
+ for (const file of files) {
+ const filePath = join(process.cwd(), file);
+ const pluginModule = await import(filePath);
+ const pluginClass = Object.values(pluginModule)[0];
+ plugins.push(pluginClass);
+ }
+
+ resolve(plugins);
+ });
+}
diff --git a/apps/backend/src/common/plugins/plugin.module.ts b/apps/backend/src/common/plugins/plugin.module.ts
new file mode 100644
index 0000000..97c7c09
--- /dev/null
+++ b/apps/backend/src/common/plugins/plugin.module.ts
@@ -0,0 +1,25 @@
+import { Module, DynamicModule, Global, type Type } from '@nestjs/common';
+import { PluginService } from './plugin.service';
+import { type Plugin } from './plugin.interface';
+import { loadPlugins } from './plugin.loader';
+
+@Global()
+@Module({})
+export class PluginModule {
+ static async register(): Promise {
+ const plugins = await loadPlugins();
+
+ return {
+ module: PluginModule,
+ providers: [
+ PluginService,
+ ...plugins,
+ {
+ provide: 'PLUGIN_PROVIDERS',
+ useValue: plugins,
+ },
+ ],
+ exports: [PluginService],
+ };
+ }
+}
\ No newline at end of file
diff --git a/apps/backend/src/common/plugins/plugin.service.ts b/apps/backend/src/common/plugins/plugin.service.ts
index 77be46c..ea9c1df 100644
--- a/apps/backend/src/common/plugins/plugin.service.ts
+++ b/apps/backend/src/common/plugins/plugin.service.ts
@@ -1,15 +1,18 @@
-import { Injectable, OnModuleInit } from "@nestjs/common";
+import {Injectable, OnModuleInit, Inject, type Type, INestApplication} from '@nestjs/common';
import { type Plugin } from './plugin.interface';
@Injectable()
-export class PluginService implements OnModuleInit {
- private plugins: Plugin[] = [];
+export class PluginService {
+ private plugins: Type[] = [];
- public registerPlugin(plugin: Plugin) {
- this.plugins.push(plugin);
+ constructor(@Inject('PLUGIN_PROVIDERS') private readonly pluginProviders: Type[]) {
+ this.plugins = pluginProviders;
}
- onModuleInit() {
- this.plugins.forEach((plugin) => plugin.register());
+ initializePlugins(app: INestApplication) {
+ this.plugins.forEach(plugin => {
+ const pluginInstance = new plugin();
+ pluginInstance.register(app);
+ });
}
}
\ No newline at end of file
diff --git a/apps/backend/src/main.ts b/apps/backend/src/main.ts
index 3fb330f..8eb642d 100644
--- a/apps/backend/src/main.ts
+++ b/apps/backend/src/main.ts
@@ -1,12 +1,12 @@
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
-import { PluginService } from './common/plugins/plugin.service';
+import { PluginService } from "./common/plugins/plugin.service";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const pluginService = app.get(PluginService);
- pluginService.onModuleInit(); // Initialize plugins
+ pluginService.initializePlugins(app);
await app.listen(4300);
}
diff --git a/apps/shared/package.json b/apps/shared/package.json
new file mode 100644
index 0000000..5083a4e
--- /dev/null
+++ b/apps/shared/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "homespace-shared",
+ "version": "0.0.1",
+ "workspaces": [
+ "plugins/*"
+ ]
+}
\ No newline at end of file
diff --git a/custom/plugins/blmedia-example/apps/frontend/src/main.js b/apps/shared/plugins/example-plugin/apps/frontend/src/main.js
similarity index 100%
rename from custom/plugins/blmedia-example/apps/frontend/src/main.js
rename to apps/shared/plugins/example-plugin/apps/frontend/src/main.js
diff --git a/apps/shared/plugins/example-plugin/example-plugin.plugin.ts b/apps/shared/plugins/example-plugin/example-plugin.plugin.ts
new file mode 100644
index 0000000..dbcfac3
--- /dev/null
+++ b/apps/shared/plugins/example-plugin/example-plugin.plugin.ts
@@ -0,0 +1,8 @@
+// Todo: create example plugin
+import { type Plugin } from "homespace-backend/src/common/plugins/plugin.interface";
+
+export class ExamplePlugin implements Plugin {
+ register() {
+ console.log("plugin registered: ExamplePlugin");
+ }
+}
\ No newline at end of file
diff --git a/custom/plugins/blmedia-example/package.json b/apps/shared/plugins/example-plugin/package.json
similarity index 67%
rename from custom/plugins/blmedia-example/package.json
rename to apps/shared/plugins/example-plugin/package.json
index 7add712..6a6f3d9 100644
--- a/custom/plugins/blmedia-example/package.json
+++ b/apps/shared/plugins/example-plugin/package.json
@@ -1,5 +1,5 @@
{
- "name": "blmedia-example",
+ "name": "example-plugin",
"version": "0.0.1",
"workspaces": [
"apps/*"
diff --git a/bun.lockb b/bun.lockb
index b2dbe57..d941ab8 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/custom/plugins/blmedia-example/blmedia-example.plugin.ts b/custom/plugins/blmedia-example/blmedia-example.plugin.ts
deleted file mode 100644
index fab40f0..0000000
--- a/custom/plugins/blmedia-example/blmedia-example.plugin.ts
+++ /dev/null
@@ -1 +0,0 @@
-// Todo: create example plugin
\ No newline at end of file