diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml index 4cfa67d..bf4105a 100644 --- a/.idea/material_theme_project_new.xml +++ b/.idea/material_theme_project_new.xml @@ -3,7 +3,9 @@ diff --git a/apps/backend/package.json b/apps/backend/package.json index ced3a46..6fa64dc 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", + "ascii-table": "^0.0.9", "glob": "^10.4.2", "mongodb": "^6.7.0", "pg": "^8.11.3", diff --git a/apps/backend/src/app.module.ts b/apps/backend/src/app.module.ts index 2fab81f..6edf59d 100644 --- a/apps/backend/src/app.module.ts +++ b/apps/backend/src/app.module.ts @@ -1,4 +1,4 @@ -import { Module, type Type } from '@nestjs/common'; +import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { User } from './entities/user.entity'; import { PluginModule } from "./common/plugins/plugin.module"; diff --git a/apps/backend/src/common/plugins/plugin.interface.ts b/apps/backend/src/common/plugins/plugin.interface.ts index 3c8e041..ffe1d28 100644 --- a/apps/backend/src/common/plugins/plugin.interface.ts +++ b/apps/backend/src/common/plugins/plugin.interface.ts @@ -1,5 +1,3 @@ -import {INestApplication} from "@nestjs/common"; - export interface Plugin { - register(app: INestApplication): void + register(): 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 index f4ac565..6f0ee98 100644 --- a/apps/backend/src/common/plugins/plugin.loader.ts +++ b/apps/backend/src/common/plugins/plugin.loader.ts @@ -1,9 +1,9 @@ import { glob } from 'glob'; import { join } from 'path'; -export async function loadPlugins(): Promise { +export async function loadPlugins(): Promise { return new Promise(async (resolve, reject) => { - const files = await glob('homespace-shared/plugins/**/*.plugin.{ts,js}'); + const files = await glob('../shared/plugins/**/*.plugin.{ts,js}'); console.log(files) diff --git a/apps/backend/src/common/plugins/plugin.module.ts b/apps/backend/src/common/plugins/plugin.module.ts index 97c7c09..a8ab660 100644 --- a/apps/backend/src/common/plugins/plugin.module.ts +++ b/apps/backend/src/common/plugins/plugin.module.ts @@ -1,6 +1,5 @@ -import { Module, DynamicModule, Global, type Type } from '@nestjs/common'; +import { Module, DynamicModule, Global } from '@nestjs/common'; import { PluginService } from './plugin.service'; -import { type Plugin } from './plugin.interface'; import { loadPlugins } from './plugin.loader'; @Global() @@ -9,8 +8,14 @@ export class PluginModule { static async register(): Promise { const plugins = await loadPlugins(); + const pluginModules = plugins.map(pluginClass => { + const pluginInstance = new pluginClass(); + return pluginInstance.getModule(); + }) + return { module: PluginModule, + imports: [...pluginModules], providers: [ PluginService, ...plugins, diff --git a/apps/backend/src/common/plugins/plugin.service.ts b/apps/backend/src/common/plugins/plugin.service.ts index ea9c1df..b7bc7c6 100644 --- a/apps/backend/src/common/plugins/plugin.service.ts +++ b/apps/backend/src/common/plugins/plugin.service.ts @@ -1,18 +1,14 @@ -import {Injectable, OnModuleInit, Inject, type Type, INestApplication} from '@nestjs/common'; +import { Injectable, OnModuleInit, Inject, type Type } from '@nestjs/common'; import { type Plugin } from './plugin.interface'; @Injectable() -export class PluginService { - private plugins: Type[] = []; +export class PluginService implements OnModuleInit { + constructor(@Inject('PLUGIN_PROVIDERS') private readonly pluginProviders: Type[]) {} - constructor(@Inject('PLUGIN_PROVIDERS') private readonly pluginProviders: Type[]) { - this.plugins = pluginProviders; - } - - initializePlugins(app: INestApplication) { - this.plugins.forEach(plugin => { + onModuleInit() { + this.pluginProviders.forEach(plugin => { const pluginInstance = new plugin(); - pluginInstance.register(app); + pluginInstance.register(); }); } } \ No newline at end of file diff --git a/apps/backend/src/main.ts b/apps/backend/src/main.ts index 8eb642d..71df0f3 100644 --- a/apps/backend/src/main.ts +++ b/apps/backend/src/main.ts @@ -1,13 +1,9 @@ import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; -import { PluginService } from "./common/plugins/plugin.service"; async function bootstrap() { const app = await NestFactory.create(AppModule); - const pluginService = app.get(PluginService); - pluginService.initializePlugins(app); - await app.listen(4300); } diff --git a/apps/frontend/.env.development b/apps/frontend/.env.development new file mode 100644 index 0000000..a77284a --- /dev/null +++ b/apps/frontend/.env.development @@ -0,0 +1,4 @@ +# .env.development +VITE_APP_TITLE=HomeSpace +VITE_APP_DESC='The HomeSpace project' +VITE_APP_URL=http://localhost:5173/ \ No newline at end of file diff --git a/apps/frontend/.env.production b/apps/frontend/.env.production new file mode 100644 index 0000000..4d7afbc --- /dev/null +++ b/apps/frontend/.env.production @@ -0,0 +1,4 @@ +# .env.production +VITE_APP_TITLE=HomeSpace +VITE_APP_DESC='The HomeSpace project' +VITE_APP_URL=https://homespace.thevoid.cafe \ No newline at end of file diff --git a/apps/frontend/.gitignore b/apps/frontend/.gitignore new file mode 100644 index 0000000..0cadcc4 --- /dev/null +++ b/apps/frontend/.gitignore @@ -0,0 +1,25 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +!.vscode/tasks.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? \ No newline at end of file diff --git a/apps/frontend/index.html b/apps/frontend/index.html new file mode 100644 index 0000000..d4d309b --- /dev/null +++ b/apps/frontend/index.html @@ -0,0 +1,18 @@ + + + + + + + %VITE_APP_TITLE% + + + + + + + +
+ + + \ No newline at end of file diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 1417fef..e4f98a0 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -1,4 +1,22 @@ { "name": "homespace-frontend", - "version": "0.0.1" + "private": true, + "version": "0.0.1", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vue-tsc && vite build", + "preview": "vite preview" + }, + "devDependencies": { + "@types/node": "^20.14.9", + "@vitejs/plugin-vue": "^5.0.5", + "typescript": "^5.5.2", + "vite": "^5.3.2", + "vue-tsc": "^2.0.22" + }, + "dependencies": { + "vue": "^3.4.31", + "vue-router": "^4.4.0" + } } \ No newline at end of file diff --git a/apps/frontend/public/vite.png b/apps/frontend/public/vite.png new file mode 100644 index 0000000..7859316 Binary files /dev/null and b/apps/frontend/public/vite.png differ diff --git a/apps/frontend/public/vite.svg b/apps/frontend/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/apps/frontend/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/frontend/src/App.vue b/apps/frontend/src/App.vue new file mode 100644 index 0000000..64c9f44 --- /dev/null +++ b/apps/frontend/src/App.vue @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/apps/frontend/src/assets/vue.svg b/apps/frontend/src/assets/vue.svg new file mode 100644 index 0000000..770e9d3 --- /dev/null +++ b/apps/frontend/src/assets/vue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/frontend/src/components/HelloWorld.vue b/apps/frontend/src/components/HelloWorld.vue new file mode 100644 index 0000000..df8ed84 --- /dev/null +++ b/apps/frontend/src/components/HelloWorld.vue @@ -0,0 +1,38 @@ + + + + + \ No newline at end of file diff --git a/apps/frontend/src/main.js b/apps/frontend/src/main.js deleted file mode 100644 index e69de29..0000000 diff --git a/apps/frontend/src/main.ts b/apps/frontend/src/main.ts new file mode 100644 index 0000000..f32225b --- /dev/null +++ b/apps/frontend/src/main.ts @@ -0,0 +1,8 @@ +import { createApp } from 'vue' +import './style.css' +import App from './App.vue' +import { router } from './router.ts'; + +createApp(App) + .use(router) + .mount('#app') \ No newline at end of file diff --git a/apps/frontend/src/router.ts b/apps/frontend/src/router.ts new file mode 100644 index 0000000..b06babd --- /dev/null +++ b/apps/frontend/src/router.ts @@ -0,0 +1,14 @@ +import { createWebHistory, createRouter } from 'vue-router' + +import HomeView from './routes/HomeView.vue' +import AboutView from './routes/AboutView.vue' + +const routes = [ + { path: '/', component: HomeView }, + { path: '/about', component: AboutView }, +] + +export const router = createRouter({ + history: createWebHistory(), + routes, +}) \ No newline at end of file diff --git a/apps/frontend/src/routes/AboutView.vue b/apps/frontend/src/routes/AboutView.vue new file mode 100644 index 0000000..3af429b --- /dev/null +++ b/apps/frontend/src/routes/AboutView.vue @@ -0,0 +1,6 @@ + + + diff --git a/apps/frontend/src/routes/HomeView.vue b/apps/frontend/src/routes/HomeView.vue new file mode 100644 index 0000000..38d69cb --- /dev/null +++ b/apps/frontend/src/routes/HomeView.vue @@ -0,0 +1,6 @@ + + + diff --git a/apps/frontend/src/style.css b/apps/frontend/src/style.css new file mode 100644 index 0000000..25356ed --- /dev/null +++ b/apps/frontend/src/style.css @@ -0,0 +1,79 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +.card { + padding: 2em; +} + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} \ No newline at end of file diff --git a/apps/frontend/src/vite-env.d.ts b/apps/frontend/src/vite-env.d.ts new file mode 100644 index 0000000..151aa68 --- /dev/null +++ b/apps/frontend/src/vite-env.d.ts @@ -0,0 +1 @@ +/// \ No newline at end of file diff --git a/apps/frontend/tsconfig.json b/apps/frontend/tsconfig.json new file mode 100644 index 0000000..ee019e9 --- /dev/null +++ b/apps/frontend/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"], + "references": [{ "path": "./tsconfig.node.json" }] +} \ No newline at end of file diff --git a/apps/frontend/tsconfig.node.json b/apps/frontend/tsconfig.node.json new file mode 100644 index 0000000..f5c7296 --- /dev/null +++ b/apps/frontend/tsconfig.node.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + /* Paths */ + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + }, + "include": [ + "vite.config.ts" + ] +} \ No newline at end of file diff --git a/apps/frontend/vite.config.ts b/apps/frontend/vite.config.ts new file mode 100644 index 0000000..dee1613 --- /dev/null +++ b/apps/frontend/vite.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import path from 'node:path' + +// https://vitejs.dev/config/ +export default defineConfig({ + resolve: { + alias: { + '@': path.resolve(__dirname, './src') + } + }, + plugins: [vue()] +}) \ No newline at end of file diff --git a/apps/shared/plugins/example-plugin/example-plugin.plugin.ts b/apps/shared/plugins/example-plugin/example-plugin.plugin.ts index dbcfac3..9ea02a8 100644 --- a/apps/shared/plugins/example-plugin/example-plugin.plugin.ts +++ b/apps/shared/plugins/example-plugin/example-plugin.plugin.ts @@ -1,8 +1,38 @@ -// Todo: create example plugin -import { type Plugin } from "homespace-backend/src/common/plugins/plugin.interface"; +import { type Plugin } from 'homespace-backend/src/common/plugins/plugin.interface'; +import { Injectable, Controller, Get, Module, Logger } from '@nestjs/common'; -export class ExamplePlugin implements Plugin { - register() { - console.log("plugin registered: ExamplePlugin"); +// Service +@Injectable() +class ExampleService { + getData(): { plugin: string } { + return { plugin: "example-plugin" }; } -} \ No newline at end of file +} + +// Controller +@Controller('example') +class ExampleController { + constructor(private readonly exampleService: ExampleService) {} + + @Get() + getExampleData(): { plugin: string } { + return this.exampleService.getData(); + } +} + +// Plugin +export class ExamplePlugin implements Plugin { + getModule() { + @Module({ + controllers: [ExampleController], + providers: [ExampleService], + }) + class ExampleModule {} + + return ExampleModule; + } + + register(): void { + Logger.log('Example Plugin Registered', 'ExamplePlugin'); + } +} diff --git a/apps/shared/plugins/example-plugin/tsconfig.json b/apps/shared/plugins/example-plugin/tsconfig.json new file mode 100644 index 0000000..d0aa348 --- /dev/null +++ b/apps/shared/plugins/example-plugin/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "ES2021", + "sourceMap": true, + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": false, + "noImplicitAny": false, + "strictBindCallApply": false, + "forceConsistentCasingInFileNames": false, + "noFallthroughCasesInSwitch": false + } +} diff --git a/bun.lockb b/bun.lockb index d941ab8..d8a3d69 100755 Binary files a/bun.lockb and b/bun.lockb differ