Initial commit
This commit is contained in:
5
plugins/AudioVisual.client.ts
Normal file
5
plugins/AudioVisual.client.ts
Normal 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
4
plugins/PiniaPlugin.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
||||
export default defineNuxtPlugin(({ $pinia }) => {
|
||||
$pinia.use(piniaPluginPersistedstate)
|
||||
})
|
39
plugins/axios.ts
Normal file
39
plugins/axios.ts
Normal 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
4
plugins/config.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export default defineNuxtPlugin((_nuxtApp) => {
|
||||
useRuntimeConfig()
|
||||
// useNuxtApp().$logger.log('NOISESRC:', config.public.noise_src)
|
||||
})
|
5
plugins/dexie.ts
Normal file
5
plugins/dexie.ts
Normal 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
16
plugins/logger.client.ts
Normal 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
134
plugins/logger.server.ts
Normal 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
36
plugins/player.ts
Normal 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
46
plugins/player0.ts
Normal 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
|
||||
}
|
||||
}
|
||||
})
|
17
plugins/serviceworker.client.ts
Normal file
17
plugins/serviceworker.client.ts
Normal 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
13
plugins/toastr.client.ts
Normal 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
|
||||
})
|
||||
})
|
6
plugins/vue-video-background.client.ts
Normal file
6
plugins/vue-video-background.client.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
// @ts-ignore
|
||||
import { Plugin } from 'vue-responsive-video-background-player'
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
nuxtApp.vueApp.use(Plugin)
|
||||
})
|
Reference in New Issue
Block a user