feat: Realtime Functionality
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2024-03-23 17:40:59 +01:00
parent d6ec298e56
commit 5f1e3ee176
20 changed files with 759 additions and 116 deletions

View File

@@ -1,5 +1,5 @@
import { ofetch } from 'ofetch'
import type { FetchOptions } from 'ofetch';
import type { FetchOptions } from 'ofetch'
export default defineNuxtPlugin({
name: 'app',
@@ -10,10 +10,10 @@ export default defineNuxtPlugin({
const auth = useAuthStore()
nuxtApp.provide('storage', (path: string): string => {
if (!path) return ''
if (!path) { return '' }
return path.startsWith('http://') || path.startsWith('https://') ?
path
return path.startsWith('http://') || path.startsWith('https://')
? path
: config.public.storageBase + path
})
@@ -21,45 +21,54 @@ export default defineNuxtPlugin({
// Initial headers with Accept
const initialHeaders = {
...headers,
'Accept': 'application/json',
};
Accept: 'application/json',
}
// Conditionally add server-specific headers
if (process.server) {
const serverHeaders = {
'referer': useRequestURL().toString(),
referer: useRequestURL().toString(),
...useRequestHeaders(['x-forwarded-for', 'user-agent', 'referer']),
};
Object.assign(initialHeaders, serverHeaders);
}
Object.assign(initialHeaders, serverHeaders)
}
// Conditionally add authorization header if logged in
if (auth.isLoggedIn) {
const authHeaders = {
'Authorization': `Bearer ${auth.token}`,
};
Object.assign(initialHeaders, authHeaders);
Authorization: `Bearer ${auth.token}`,
}
Object.assign(initialHeaders, authHeaders)
}
return initialHeaders;
// Conditionally add X-Socket-ID header if socket is connected
if (auth.isLoggedIn && auth.socketId) {
console.log('auth.socketId', auth.socketId)
const socketHeaders = {
'X-Socket-ID': auth.socketId,
}
Object.assign(initialHeaders, socketHeaders)
}
return initialHeaders
}
function buildBaseURL(baseURL: string): string {
if (baseURL) return baseURL;
if (baseURL) { return baseURL }
return process.server ?
config.apiLocal + config.public.apiPrefix
: config.public.apiBase + config.public.apiPrefix;
return process.server
? config.apiLocal + config.public.apiPrefix
: config.public.apiBase + config.public.apiPrefix
}
function buildSecureMethod(options: FetchOptions): void {
if (process.server) return;
if (process.server) { return }
const method = options.method?.toLowerCase() ?? 'get'
if (options.body instanceof FormData && method === 'put') {
options.method = 'POST';
options.body.append('_method', 'PUT');
options.method = 'POST'
options.body.append('_method', 'PUT')
}
}
@@ -67,27 +76,27 @@ export default defineNuxtPlugin({
return !baseURL
&& !path.startsWith('/_nuxt')
&& !path.startsWith('http://')
&& !path.startsWith('https://');
&& !path.startsWith('https://')
}
globalThis.$fetch = ofetch.create({
retry: false,
onRequest({ request, options }) {
if (!isRequestWithAuth(options.baseURL ?? '', request.toString())) return
if (!isRequestWithAuth(options.baseURL ?? '', request.toString())) { return }
options.credentials = 'include';
options.credentials = 'include'
options.baseURL = buildBaseURL(options.baseURL ?? '');
options.headers = buildHeaders(options.headers);
options.baseURL = buildBaseURL(options.baseURL ?? '')
options.headers = buildHeaders(options.headers)
buildSecureMethod(options);
buildSecureMethod(options)
},
onRequestError({ error }) {
if (process.server) return;
if (process.server) { return }
if (error.name === 'AbortError') return;
if (error.name === 'AbortError') { return }
useToast().add({
icon: 'i-heroicons-exclamation-circle-solid',
@@ -110,7 +119,8 @@ export default defineNuxtPlugin({
color: 'primary',
})
}
} else if (response.status !== 422) {
}
else if (response.status !== 422) {
if (process.client) {
useToast().add({
icon: 'i-heroicons-exclamation-circle-solid',
@@ -119,11 +129,11 @@ export default defineNuxtPlugin({
})
}
}
}
},
} as FetchOptions)
if (auth.isLoggedIn) {
await auth.fetchUser();
await auth.fetchUser()
}
},
})

View File

@@ -0,0 +1,55 @@
import Echo from 'laravel-echo'
import Pusher from 'pusher-js'
declare global {
interface Window {
Pusher: typeof Pusher
}
}
window.Pusher = Pusher
export default defineNuxtPlugin(() => {
const runtimeConfig = useRuntimeConfig()
const authStore = useAuthStore()
const echo = new Echo({
broadcaster: runtimeConfig.public.echo.broadcaster,
key: runtimeConfig.public.echo.key,
cluster: 'mt1',
wsHost: runtimeConfig.public.echo.wsHost,
wsPort: runtimeConfig.public.echo.wsPort,
wssPort: runtimeConfig.public.echo.wsPort,
forceTLS: false,
encrypted: runtimeConfig.public.echo.encrypted,
disableStats: runtimeConfig.public.echo.disableStats,
enabledTransports: ['ws', 'wss'],
authorizer: (channel: { name: any }) => {
return {
authorize: async (socketId: string, callback: (error: any, respnse?: any) => void) => {
try {
const response = await $fetch(`/broadcasting/auth`, {
method: 'POST',
body: {
socket_id: socketId,
channel_name: channel.name,
},
})
callback(null, response)
}
catch (error) {
callback(error)
}
},
}
},
})
authStore.socketId = echo.socketId()
// Make Echo instance available through the Nuxt app
return {
provide: {
echo,
},
}
})