Initial commit

This commit is contained in:
Mindboost
2025-07-01 10:53:26 +00:00
commit 38050e5c69
416 changed files with 48708 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
import { AVPlugin } from 'vue-audio-visual'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(AVPlugin)
})

4
plugins/PiniaPlugin.ts Normal file
View File

@@ -0,0 +1,4 @@
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
export default defineNuxtPlugin(({ $pinia }) => {
$pinia.use(piniaPluginPersistedstate)
})

39
plugins/axios.ts Normal file
View File

@@ -0,0 +1,39 @@
import axios, { type AxiosInstance, type AxiosRequestConfig } from 'axios'
import { mapState } from 'pinia'
import type { Logger } from 'pino'
import { useUserStore } from '~/stores/user'
export default defineNuxtPlugin(() => {
if (useRuntimeConfig().public.apiUrl === '') {
throw new Error('Please ensure that the apiUrl is set in .env File.')
}
const defaultUrl = useRuntimeConfig().public.apiUrl
// Access Pinia state
// @ts-ignore
const api: AxiosInstance = axios.create({
// @ts-ignore
baseURL: defaultUrl,
headers: {
common: {}
},
withCredentials: true
})
// @ts-ignore
api.interceptors.request.use((config: AxiosRequestConfig) => {
const logger = useNuxtApp().$logger as any
logger.info("BACKEND URL "+ defaultUrl)
config.baseURL = defaultUrl
const token = mapState(useUserStore, ['token']).token()
// @ts-ignore
config.headers.Authorization = 'Bearer ' + token
return config
})
return {
provide: {
axios: api
}
}
})

4
plugins/config.ts Normal file
View File

@@ -0,0 +1,4 @@
export default defineNuxtPlugin((_nuxtApp) => {
useRuntimeConfig()
// useNuxtApp().$logger.log('NOISESRC:', config.public.noise_src)
})

5
plugins/dexie.ts Normal file
View File

@@ -0,0 +1,5 @@
import { db } from '@/lib/db'
// Assuming dexie-db.ts is correctly set up and exported `db`
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.provide('db', db)
})

16
plugins/logger.client.ts Normal file
View File

@@ -0,0 +1,16 @@
import { pino } from 'pino'
export default defineNuxtPlugin(() => {
const logger = pino({
browser: {
asObject: true // JSON-Format für Logs im Browser
},
level: 'debug' // Logging-Level
})
return {
provide: {
logger // $logger global verfügbar machen
}
}
})

134
plugins/logger.server.ts Normal file
View File

@@ -0,0 +1,134 @@
import * as fs from 'fs'
import { createGzip } from 'zlib'
import { pino, transport } from 'pino'
import { createTransport } from 'nodemailer'
import { config } from 'dotenv'
export default defineNuxtPlugin(() => {
useNuxtApp().$logger.log('[logger.server.ts] Plugin geladen!')
// Format the Date in log file name
const getCurrentDate = () => {
const now = new Date()
const year = now.getFullYear()
const month = String(now.getMonth() + 1).padStart(2, '0') // Monat von 0-11
const day = String(now.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
}
config()
// Standardwerte für Konfiguration
const maxFiles = parseInt(process.env.LOG_MAX_FILES || '10') // Maximale Anzahl von Log-Dateien
const logDirectory = process.env.LOG_DIRECTORY || './logs' // Verzeichnis für Log-Dateien
const alertThreshold = parseInt(process.env.LOG_ALERT_THRESHOLD || '5') // Warnschwelle für Log-Dateien
const alertEmail =
process.env.LOG_ALERT_EMAIL || 'robert.rapp@mindboost.team' // E-Mail-Adresse für Warnungen
const checkInterval = parseInt(
process.env.LOG_CHECK_INTERVAL || (30 * 60 * 1000).toString()
) // Überwachungsintervall
const currentDate = getCurrentDate() // Format: 2023-11-27
// Sicherstellen, dass das Log-Verzeichnis existiert
if (!fs.existsSync(logDirectory)) {
fs.mkdirSync(logDirectory, { recursive: true })
}
// Transport für Pino
const pinotransport = transport({
target: 'pino/file',
options: {
destination: `${logDirectory}/app-${currentDate}.log`,
mkdir: true,
rotate: {
interval: '1d', // Log-Rotation täglich
size: '10M' // Maximalgröße für einzelne Logs
}
}
})
// Logger erstellen
const logger = pino(pinotransport)
// Funktion zur E-Mail-Benachrichtigung
async function sendAlertEmail (fileCount: number) {
const transporter = createTransport({
host: process.env.SMTP_HOST,
port: parseInt(process.env.SMTP_PORT || '465'),
secure: process.env.SMTP_SECURE === 'true', // TLS/SSL basierend auf ENV
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS
}
})
const message = {
from: process.env.SMTP_USER || 'app@mindboost.team',
to: alertEmail,
subject: 'Warnung: Hohe Anzahl von Log-Dateien',
text: `Es wurden heute bereits ${fileCount} Log-Dateien erstellt. Schau es dir bitte mal an.`
}
try {
await transporter.sendMail(message)
logger.info('Warn-E-Mail wurde erfolgreich gesendet.')
} catch (error) {
logger.error('Fehler beim Senden der Warn-E-Mail:', error)
}
}
// Funktion zur Überwachung der Log-Dateien
function monitorLogs () {
fs.readdir(logDirectory, (err, files) => {
if (err) {
logger.error('Fehler beim Lesen des Log-Verzeichnisses:', err)
return
}
const logFiles = files.filter(file => file.endsWith('.log'))
logger.info(`Aktuelle Anzahl von Log-Dateien: ${logFiles.length}`)
if (logFiles.length >= alertThreshold) {
sendAlertEmail(logFiles.length)
}
if (logFiles.length > maxFiles) {
zipOldLogs(logFiles)
}
})
}
// Funktion zum Zippen alter Logs
function zipOldLogs (logFiles: string[]) {
const filesToZip = logFiles.slice(0, logFiles.length - maxFiles)
filesToZip.forEach((file) => {
const inputPath = `${logDirectory}/${file}`
const outputPath = `${inputPath}.gz`
const gzip = createGzip()
const source = fs.createReadStream(inputPath)
const destination = fs.createWriteStream(outputPath)
source
.pipe(gzip)
.pipe(destination)
.on('finish', () => {
fs.unlinkSync(inputPath) // Originaldatei löschen
logger.info(`Log-Datei wurde erfolgreich gezippt: ${outputPath}`)
})
.on('error', (err) => {
logger.error(`Fehler beim Zippen der Log-Datei ${file}:`, err)
})
})
}
// Log-Rotation überwachen
pinotransport.on('drain', () => {
logger.info('Neue Log-Datei wurde erstellt oder rotiert.')
monitorLogs()
})
// Überwachung alle 30 Minuten ausführen
setInterval(monitorLogs, checkInterval)
return {
provide: {
logger
}
}
})

36
plugins/player.ts Normal file
View File

@@ -0,0 +1,36 @@
/** Dieses Plugin deckt die Applikationslogik für den Player ab. Dadurch soll verhindert werden, dass Logik in Componenten verbaut ist,
* die durch die mount und unmount Mechanismen durcheinander kommen würden. Das Plugin arbeitet eng mit dem audio-Store zusammen.
*
* Die benötigten Funktionen für die Navigationbar sowie das PlayerControls-Composable sind changeTrack zum Wechseln des Soundscapes
* inklusive der Interaktion mit dem Backend.
*
**/
export default defineNuxtPlugin(async () => {
const play = async () => {
}
const pause = async () => {
}
const next = async () => {
}
const previous = async () => {
}
// Expose methods to components
return {
provide: {
play,
pause,
next,
previous,
stop
}
}
})

46
plugins/player0.ts Normal file
View File

@@ -0,0 +1,46 @@
import { useAudioStore } from '~/stores/audio'
import { useUserStore } from '~/stores/user'
import { getSoundscapeByTitle } from '~/tracks.config'
const { waitForCanPlay } = useAudioReplacer()
/** Dieses Plugin deckt die Applikationslogik für den Player ab, dadurch soll verhindert werden, dass Logik in Componenten verbaut ist,
* die durch die mount und unmount Mechanismen durcheinander kommen, würden. Das Plugin arbeitet eng mit dem audio-Store zusammen.
*
* Die benötigten Funktionen für die Navigationbar sowie das PlayerControls-Composable sind changeTrack zum Wechseln des Soundscapes
* inklusive der Interaktion mit dem Backend.
*
**/
export default defineNuxtPlugin(() => {
const audioStore = useAudioStore()
const { $axios } = useNuxtApp() as any
// Initialize audio context on first user interaction
const initAudioOnInteraction = () => {
audioStore.initializeAudioContext()
document.removeEventListener('click', initAudioOnInteraction)
}
// Method to handle track changes
/**
* Change to the given track name. This function should be called when audio is stopped already.
* @param title
*/
const changeTrack = async (title:string) => {
const src = getSoundscapeByTitle(title)
const currentAudio = document.getElementById(title) as HTMLAudioElement
if(currentAudio) {
await waitForCanPlay(currentAudio)
} else {
}
}
// Expose methods to components
return {
provide: {
changeTrack
}
}
})

View File

@@ -0,0 +1,17 @@
import type { Logger } from "pino"
export default defineNuxtPlugin(() => {
const logger = useNuxtApp().$logger as Logger
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then((registration) => {
logger.info('[ServiceWorker] Registered with scope:', registration.scope)
})
.catch((error) => {
logger.error('[ServiceWorker] Registration failed:', error)
})
} else {
logger.warn('[ServiceWorker] Not supported in this browser.')
}
})

13
plugins/toastr.client.ts Normal file
View File

@@ -0,0 +1,13 @@
// @ts-ignore
// eslint-disable-next-line import/no-named-as-default
import Toaster from '@meforma/vue-toaster'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(Toaster, {
position: 'bottom-left',
duration: 2000,
queue: true,
max: 1,
pauseOnHover: false
})
})

View File

@@ -0,0 +1,6 @@
// @ts-ignore
import { Plugin } from 'vue-responsive-video-background-player'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(Plugin)
})