feat: more fluent vuejs app error handler

This commit is contained in:
2025-12-15 19:45:53 +03:00
parent 9870f2f363
commit 955747334d
4 changed files with 70 additions and 5 deletions

View File

@@ -0,0 +1,19 @@
<template>
<div style="z-index: 99999" class="fixed top-0 left-0 w-full h-full bg-base-100">
<div class="flex flex-col items-center justify-center h-full">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-18">
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
<h1 class="font-semibold text-2xl mb-2">Магазин работает только внутри Telegram.</h1>
</div>
</div>
</template>
<script setup>
const props = defineProps({
error: Error,
});
</script>

View File

@@ -0,0 +1,30 @@
class AppError extends Error {
constructor(message, code = 'APP_ERROR') {
super(message);
this.name = this.constructor.name;
this.code = code;
// важно для наследования Error
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
}
}
class MaintenanceError extends AppError {
constructor(message = 'Application is under maintenance') {
super(message, 'MAINTENANCE');
}
}
class TelegramInitDataError extends AppError {
constructor(message = 'Application must be opened inside Telegram') {
super(message, 'NO_INIT_DATA');
}
}
export {
AppError,
MaintenanceError,
TelegramInitDataError,
};

View File

@@ -21,6 +21,8 @@ import {defaultConfig, plugin} from '@formkit/vue';
import config from './formkit.config.js'; import config from './formkit.config.js';
import {TC_PULSE_EVENTS} from "@/constants/tPulseEvents.js"; import {TC_PULSE_EVENTS} from "@/constants/tPulseEvents.js";
import {usePulseStore} from "@/stores/Pulse.js"; import {usePulseStore} from "@/stores/Pulse.js";
import {TelegramInitDataError} from '@/errors.js';
import WrongPlatformError from "@/WrongPlatformError.vue";
register(); register();
@@ -41,7 +43,7 @@ const appLoading = createApp(AppLoading);
appLoading.mount('#app'); appLoading.mount('#app');
function setTelegramUIColors() { function setTelegramUIColors() {
const daisyUIBgColor = getCssVarOklchRgb('--color-base-100'); const daisyUIBgColor = getCssVarOklchRgb('--color-base-200');
window.Telegram.WebApp.setHeaderColor(daisyUIBgColor); window.Telegram.WebApp.setHeaderColor(daisyUIBgColor);
window.Telegram.WebApp.setBackgroundColor(daisyUIBgColor); window.Telegram.WebApp.setBackgroundColor(daisyUIBgColor);
} }
@@ -56,7 +58,7 @@ settings.load()
.then(() => settings.ya_metrika_enabled && injectYaMetrika()) .then(() => settings.ya_metrika_enabled && injectYaMetrika())
.then(() => { .then(() => {
if (! window.Telegram.WebApp.initData) { if (! window.Telegram.WebApp.initData) {
throw new Error('Invalid init data. Application not in Telegram View'); throw new TelegramInitDataError('Invalid init data. Application not in Telegram View');
} }
}) })
.then(() => pulse.initFromStartParams()) .then(() => pulse.initFromStartParams())
@@ -113,7 +115,18 @@ settings.load()
}) })
.then(() => window.Telegram.WebApp.ready()) .then(() => window.Telegram.WebApp.ready())
.catch(error => { .catch(error => {
console.error(error); const code = error.code ?? error.response._data.code;
const errorApp = createApp(ApplicationError, {error}); let ErrorComponent;
switch (code) {
case 'NO_INIT_DATA':
ErrorComponent = WrongPlatformError;
break;
default:
ErrorComponent = ApplicationError;
}
const errorApp = createApp(ErrorComponent, { error });
errorApp.mount('#app-error'); errorApp.mount('#app-error');
}); });

View File

@@ -14,7 +14,10 @@ class CustomExceptionHandler implements ExceptionHandlerInterface
public function respond(Throwable $exception): ?JsonResponse public function respond(Throwable $exception): ?JsonResponse
{ {
if ($exception instanceof TelegramInvalidSignatureException) { if ($exception instanceof TelegramInvalidSignatureException) {
return new JsonResponse(['error' => 'Invalid Signature'], Response::HTTP_BAD_REQUEST); return new JsonResponse([
'error' => 'Invalid Signature',
'code' => 'NO_INIT_DATA',
], Response::HTTP_BAD_REQUEST);
} }
return null; return null;