@quvel-kit/core 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +670 -0
- package/dist/auth/boot/defineAuthGuard.d.ts +54 -0
- package/dist/auth/boot/defineAuthGuard.d.ts.map +1 -0
- package/dist/auth/boot/defineAuthGuard.js +72 -0
- package/dist/auth/enums/AuthStatusEnum.d.ts +13 -0
- package/dist/auth/enums/AuthStatusEnum.d.ts.map +1 -0
- package/dist/auth/enums/AuthStatusEnum.js +13 -0
- package/dist/auth/index.d.ts +13 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +13 -0
- package/dist/auth/services/AuthGuard.d.ts +58 -0
- package/dist/auth/services/AuthGuard.d.ts.map +1 -0
- package/dist/auth/services/AuthGuard.js +51 -0
- package/dist/auth/services/AuthService.d.ts +52 -0
- package/dist/auth/services/AuthService.d.ts.map +1 -0
- package/dist/auth/services/AuthService.js +67 -0
- package/dist/auth/services/PasswordResetService.d.ts +34 -0
- package/dist/auth/services/PasswordResetService.d.ts.map +1 -0
- package/dist/auth/services/PasswordResetService.js +45 -0
- package/dist/auth/services/TwoFactorChallengeService.d.ts +22 -0
- package/dist/auth/services/TwoFactorChallengeService.d.ts.map +1 -0
- package/dist/auth/services/TwoFactorChallengeService.js +29 -0
- package/dist/auth/services/TwoFactorService.d.ts +64 -0
- package/dist/auth/services/TwoFactorService.d.ts.map +1 -0
- package/dist/auth/services/TwoFactorService.js +68 -0
- package/dist/auth/services/index.d.ts +8 -0
- package/dist/auth/services/index.d.ts.map +1 -0
- package/dist/auth/services/index.js +5 -0
- package/dist/auth/types/auth-meta.d.ts +54 -0
- package/dist/auth/types/auth-meta.d.ts.map +1 -0
- package/dist/auth/types/auth-meta.js +6 -0
- package/dist/auth/types/index.d.ts +5 -0
- package/dist/auth/types/index.d.ts.map +1 -0
- package/dist/auth/types/index.js +4 -0
- package/dist/auth/utils/auth-meta.d.ts +75 -0
- package/dist/auth/utils/auth-meta.d.ts.map +1 -0
- package/dist/auth/utils/auth-meta.js +93 -0
- package/dist/boot/quvel.d.ts +26 -0
- package/dist/boot/quvel.d.ts.map +1 -0
- package/dist/boot/quvel.js +38 -0
- package/dist/build/index.d.ts +9 -0
- package/dist/build/index.d.ts.map +1 -0
- package/dist/build/index.js +8 -0
- package/dist/build/loadEnv.d.ts +14 -0
- package/dist/build/loadEnv.d.ts.map +1 -0
- package/dist/build/loadEnv.js +33 -0
- package/dist/build/quasarConfig.d.ts +67 -0
- package/dist/build/quasarConfig.d.ts.map +1 -0
- package/dist/build/quasarConfig.js +126 -0
- package/dist/components/Common/TaskErrors.vue +47 -0
- package/dist/components/Inputs/BaseInput.vue +88 -0
- package/dist/components/Misc/ClientOnly.vue +22 -0
- package/dist/components/Transitions/FadeInOut.vue +9 -0
- package/dist/components/Transitions/SlowExpand.vue +13 -0
- package/dist/components/WebSocketChannelManager.vue +634 -0
- package/dist/components/index.d.ts +12 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +16 -0
- package/dist/composables/index.d.ts +19 -0
- package/dist/composables/index.d.ts.map +1 -0
- package/dist/composables/index.js +16 -0
- package/dist/composables/useClient.d.ts +16 -0
- package/dist/composables/useClient.d.ts.map +1 -0
- package/dist/composables/useClient.js +28 -0
- package/dist/composables/useMetaConfig.d.ts +14 -0
- package/dist/composables/useMetaConfig.d.ts.map +1 -0
- package/dist/composables/useMetaConfig.js +77 -0
- package/dist/composables/useQueryMessageHandler.d.ts +44 -0
- package/dist/composables/useQueryMessageHandler.d.ts.map +1 -0
- package/dist/composables/useQueryMessageHandler.js +74 -0
- package/dist/composables/useQuvel.d.ts +15 -0
- package/dist/composables/useQuvel.d.ts.map +1 -0
- package/dist/composables/useQuvel.js +38 -0
- package/dist/composables/useRecaptcha.d.ts +35 -0
- package/dist/composables/useRecaptcha.d.ts.map +1 -0
- package/dist/composables/useRecaptcha.js +87 -0
- package/dist/composables/useScopedService.d.ts +18 -0
- package/dist/composables/useScopedService.d.ts.map +1 -0
- package/dist/composables/useScopedService.js +25 -0
- package/dist/composables/useScript.d.ts +25 -0
- package/dist/composables/useScript.d.ts.map +1 -0
- package/dist/composables/useScript.js +106 -0
- package/dist/composables/useUrlQueryHandler.d.ts +38 -0
- package/dist/composables/useUrlQueryHandler.d.ts.map +1 -0
- package/dist/composables/useUrlQueryHandler.js +76 -0
- package/dist/composables/useWebSockets.d.ts +18 -0
- package/dist/composables/useWebSockets.d.ts.map +1 -0
- package/dist/composables/useWebSockets.js +55 -0
- package/dist/composables/useWindowEvent.d.ts +16 -0
- package/dist/composables/useWindowEvent.d.ts.map +1 -0
- package/dist/composables/useWindowEvent.js +27 -0
- package/dist/composables/useXsrf.d.ts +29 -0
- package/dist/composables/useXsrf.d.ts.map +1 -0
- package/dist/composables/useXsrf.js +59 -0
- package/dist/config/QuasarConfigBuilder.d.ts +100 -0
- package/dist/config/QuasarConfigBuilder.d.ts.map +1 -0
- package/dist/config/QuasarConfigBuilder.js +98 -0
- package/dist/config/i18n.d.ts +23 -0
- package/dist/config/i18n.d.ts.map +1 -0
- package/dist/config/i18n.js +43 -0
- package/dist/config/index.d.ts +8 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +7 -0
- package/dist/config/moduleTransformer.d.ts +18 -0
- package/dist/config/moduleTransformer.d.ts.map +1 -0
- package/dist/config/moduleTransformer.js +76 -0
- package/dist/config/quvel.d.ts +40 -0
- package/dist/config/quvel.d.ts.map +1 -0
- package/dist/config/quvel.js +59 -0
- package/dist/config/quvel.types.d.ts +59 -0
- package/dist/config/quvel.types.d.ts.map +1 -0
- package/dist/config/quvel.types.js +6 -0
- package/dist/container/ServiceContainer.d.ts +107 -0
- package/dist/container/ServiceContainer.d.ts.map +1 -0
- package/dist/container/ServiceContainer.js +201 -0
- package/dist/container/types/vue.d.ts +9 -0
- package/dist/container/types.d.ts +81 -0
- package/dist/container/types.d.ts.map +1 -0
- package/dist/container/types.js +1 -0
- package/dist/i18n/en-US/common.d.ts +19 -0
- package/dist/i18n/en-US/common.d.ts.map +1 -0
- package/dist/i18n/en-US/common.js +17 -0
- package/dist/i18n/en-US/index.d.ts +21 -0
- package/dist/i18n/en-US/index.d.ts.map +1 -0
- package/dist/i18n/en-US/index.js +4 -0
- package/dist/i18n/es-MX/common.d.ts +19 -0
- package/dist/i18n/es-MX/common.d.ts.map +1 -0
- package/dist/i18n/es-MX/common.js +17 -0
- package/dist/i18n/es-MX/index.d.ts +21 -0
- package/dist/i18n/es-MX/index.d.ts.map +1 -0
- package/dist/i18n/es-MX/index.js +4 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +67 -0
- package/dist/models/User.d.ts +32 -0
- package/dist/models/User.d.ts.map +1 -0
- package/dist/models/User.js +48 -0
- package/dist/module.d.ts +21 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +45 -0
- package/dist/modules/helpers.d.ts +30 -0
- package/dist/modules/helpers.d.ts.map +1 -0
- package/dist/modules/helpers.js +45 -0
- package/dist/modules/index.d.ts +8 -0
- package/dist/modules/index.d.ts.map +1 -0
- package/dist/modules/index.js +6 -0
- package/dist/modules/types.d.ts +141 -0
- package/dist/modules/types.d.ts.map +1 -0
- package/dist/modules/types.js +7 -0
- package/dist/pages/ErrorNotFound.vue +300 -0
- package/dist/pages/index.d.ts +7 -0
- package/dist/pages/index.d.ts.map +1 -0
- package/dist/pages/index.js +6 -0
- package/dist/services/ApiService.d.ts +90 -0
- package/dist/services/ApiService.d.ts.map +1 -0
- package/dist/services/ApiService.js +159 -0
- package/dist/services/I18nService.d.ts +67 -0
- package/dist/services/I18nService.d.ts.map +1 -0
- package/dist/services/I18nService.js +92 -0
- package/dist/services/LogService.d.ts +31 -0
- package/dist/services/LogService.d.ts.map +1 -0
- package/dist/services/LogService.js +49 -0
- package/dist/services/Service.d.ts +10 -0
- package/dist/services/Service.d.ts.map +1 -0
- package/dist/services/Service.js +8 -0
- package/dist/services/TaskService.d.ts +64 -0
- package/dist/services/TaskService.d.ts.map +1 -0
- package/dist/services/TaskService.js +188 -0
- package/dist/services/ThemeService.d.ts +28 -0
- package/dist/services/ThemeService.d.ts.map +1 -0
- package/dist/services/ThemeService.js +77 -0
- package/dist/services/ValidationService.d.ts +55 -0
- package/dist/services/ValidationService.d.ts.map +1 -0
- package/dist/services/ValidationService.js +81 -0
- package/dist/services/WebSocketService.d.ts +59 -0
- package/dist/services/WebSocketService.d.ts.map +1 -0
- package/dist/services/WebSocketService.js +148 -0
- package/dist/services/logger/BaseLogger.d.ts +35 -0
- package/dist/services/logger/BaseLogger.d.ts.map +1 -0
- package/dist/services/logger/BaseLogger.js +66 -0
- package/dist/services/logger/ConsoleLogger.d.ts +21 -0
- package/dist/services/logger/ConsoleLogger.d.ts.map +1 -0
- package/dist/services/logger/ConsoleLogger.js +60 -0
- package/dist/services/logger/NullLogger.d.ts +10 -0
- package/dist/services/logger/NullLogger.d.ts.map +1 -0
- package/dist/services/logger/NullLogger.js +10 -0
- package/dist/stores/plugins/serviceContainer.d.ts +10 -0
- package/dist/stores/plugins/serviceContainer.d.ts.map +1 -0
- package/dist/stores/plugins/serviceContainer.js +14 -0
- package/dist/stores/sessionStore.d.ts +71 -0
- package/dist/stores/sessionStore.d.ts.map +1 -0
- package/dist/stores/sessionStore.js +125 -0
- package/dist/types/app.types.d.ts +202 -0
- package/dist/types/app.types.d.ts.map +1 -0
- package/dist/types/app.types.js +6 -0
- package/dist/types/config.types.d.ts +2 -0
- package/dist/types/config.types.d.ts.map +1 -0
- package/dist/types/config.types.js +1 -0
- package/dist/types/global.d.ts +33 -0
- package/dist/types/i18n.types.d.ts +21 -0
- package/dist/types/i18n.types.d.ts.map +1 -0
- package/dist/types/i18n.types.js +6 -0
- package/dist/types/laravel.types.d.ts +167 -0
- package/dist/types/laravel.types.d.ts.map +1 -0
- package/dist/types/laravel.types.js +6 -0
- package/dist/types/logging.types.d.ts +81 -0
- package/dist/types/logging.types.d.ts.map +1 -0
- package/dist/types/logging.types.js +22 -0
- package/dist/types/pinia.d.ts +24 -0
- package/dist/types/scripts.types.d.ts +31 -0
- package/dist/types/scripts.types.d.ts.map +1 -0
- package/dist/types/scripts.types.js +6 -0
- package/dist/types/ssr.d.ts +11 -0
- package/dist/types/task.types.d.ts +121 -0
- package/dist/types/task.types.d.ts.map +1 -0
- package/dist/types/task.types.js +7 -0
- package/dist/types/theme.types.d.ts +13 -0
- package/dist/types/theme.types.d.ts.map +1 -0
- package/dist/types/theme.types.js +17 -0
- package/dist/types/user.types.d.ts +24 -0
- package/dist/types/user.types.d.ts.map +1 -0
- package/dist/types/user.types.js +1 -0
- package/dist/types/vue-shim.d.ts +11 -0
- package/dist/types/websocket.types.d.ts +62 -0
- package/dist/types/websocket.types.d.ts.map +1 -0
- package/dist/types/websocket.types.js +6 -0
- package/dist/utils/apiInterceptors.d.ts +76 -0
- package/dist/utils/apiInterceptors.d.ts.map +1 -0
- package/dist/utils/apiInterceptors.js +149 -0
- package/dist/utils/assets.d.ts +40 -0
- package/dist/utils/assets.d.ts.map +1 -0
- package/dist/utils/assets.js +340 -0
- package/dist/utils/axios.d.ts +19 -0
- package/dist/utils/axios.d.ts.map +1 -0
- package/dist/utils/axios.js +113 -0
- package/dist/utils/config.d.ts +16 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +48 -0
- package/dist/utils/container.d.ts +12 -0
- package/dist/utils/container.d.ts.map +1 -0
- package/dist/utils/container.js +11 -0
- package/dist/utils/deepMerge.d.ts +28 -0
- package/dist/utils/deepMerge.d.ts.map +1 -0
- package/dist/utils/deepMerge.js +59 -0
- package/dist/utils/envConfig.d.ts +73 -0
- package/dist/utils/envConfig.d.ts.map +1 -0
- package/dist/utils/envConfig.js +161 -0
- package/dist/utils/error.d.ts +44 -0
- package/dist/utils/error.d.ts.map +1 -0
- package/dist/utils/error.js +67 -0
- package/dist/utils/headers.d.ts +36 -0
- package/dist/utils/headers.d.ts.map +1 -0
- package/dist/utils/headers.js +54 -0
- package/dist/utils/i18n.d.ts +26 -0
- package/dist/utils/i18n.d.ts.map +1 -0
- package/dist/utils/i18n.js +56 -0
- package/dist/utils/index.d.ts +14 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +13 -0
- package/dist/utils/loading.d.ts +29 -0
- package/dist/utils/loading.d.ts.map +1 -0
- package/dist/utils/loading.js +46 -0
- package/dist/utils/logging.d.ts +20 -0
- package/dist/utils/logging.d.ts.map +1 -0
- package/dist/utils/logging.js +54 -0
- package/dist/utils/notify.d.ts +15 -0
- package/dist/utils/notify.d.ts.map +1 -0
- package/dist/utils/notify.js +30 -0
- package/dist/utils/object.d.ts +28 -0
- package/dist/utils/object.d.ts.map +1 -0
- package/dist/utils/object.js +48 -0
- package/dist/utils/pagination.d.ts +60 -0
- package/dist/utils/pagination.d.ts.map +1 -0
- package/dist/utils/pagination.js +252 -0
- package/dist/utils/paths.d.ts +54 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +48 -0
- package/dist/utils/platform.d.ts +25 -0
- package/dist/utils/platform.d.ts.map +1 -0
- package/dist/utils/platform.js +64 -0
- package/dist/utils/scripts.d.ts +20 -0
- package/dist/utils/scripts.d.ts.map +1 -0
- package/dist/utils/scripts.js +39 -0
- package/global.d.ts +29 -0
- package/package.json +119 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Composables
|
|
3
|
+
*
|
|
4
|
+
* Vue composables for the Quvel UI framework
|
|
5
|
+
*/
|
|
6
|
+
export { useQuvel, ContainerKey, setClientContainer } from './useQuvel.js';
|
|
7
|
+
export { useWindowEvent } from './useWindowEvent.js';
|
|
8
|
+
export { useClient } from './useClient.js';
|
|
9
|
+
export { useScript } from './useScript.js';
|
|
10
|
+
export { useMetaConfig } from './useMetaConfig.js';
|
|
11
|
+
export { useWebSockets } from './useWebSockets.js';
|
|
12
|
+
export { useScopedService } from './useScopedService.js';
|
|
13
|
+
export { useRecaptcha } from './useRecaptcha.js';
|
|
14
|
+
export { useXsrf } from './useXsrf.js';
|
|
15
|
+
export { useQueryMessageHandler, normalizeKey, mapStatusToType } from './useQueryMessageHandler.js';
|
|
16
|
+
export { useUrlQueryHandler } from './useUrlQueryHandler.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useClient Composable
|
|
3
|
+
*
|
|
4
|
+
* Provides client-side detection for SSR-aware components
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Detects if code is running on the client-side
|
|
8
|
+
*
|
|
9
|
+
* Returns a reactive ref that is false during SSR and true after mount on client
|
|
10
|
+
*
|
|
11
|
+
* @returns Object containing isClient state
|
|
12
|
+
*/
|
|
13
|
+
export declare function useClient(): {
|
|
14
|
+
isClient: import("vue").Ref<boolean, boolean>;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=useClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useClient.d.ts","sourceRoot":"","sources":["../../src/composables/useClient.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;;;GAMG;AACH,wBAAgB,SAAS;;EAgBxB"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useClient Composable
|
|
3
|
+
*
|
|
4
|
+
* Provides client-side detection for SSR-aware components
|
|
5
|
+
*/
|
|
6
|
+
import { ref, onMounted } from 'vue';
|
|
7
|
+
/**
|
|
8
|
+
* Detects if code is running on the client-side
|
|
9
|
+
*
|
|
10
|
+
* Returns a reactive ref that is false during SSR and true after mount on client
|
|
11
|
+
*
|
|
12
|
+
* @returns Object containing isClient state
|
|
13
|
+
*/
|
|
14
|
+
export function useClient() {
|
|
15
|
+
/**
|
|
16
|
+
* Flag indicating if the code is running on the client-side
|
|
17
|
+
*/
|
|
18
|
+
const isClient = ref(false);
|
|
19
|
+
/**
|
|
20
|
+
* Sets isClient to true when component is mounted (client-side only)
|
|
21
|
+
*/
|
|
22
|
+
onMounted(() => {
|
|
23
|
+
isClient.value = true;
|
|
24
|
+
});
|
|
25
|
+
return {
|
|
26
|
+
isClient,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useMetaConfig Composable
|
|
3
|
+
*
|
|
4
|
+
* Configure meta-tags for a page with app-level configuration support
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Configure meta tags for a page, allowing full customization
|
|
8
|
+
* Uses app meta configuration when available, falls back to defaults
|
|
9
|
+
*
|
|
10
|
+
* @param pageTitle - The page title
|
|
11
|
+
* @param overrides - Optional overrides to modify metadata
|
|
12
|
+
*/
|
|
13
|
+
export declare function useMetaConfig(pageTitle?: string, overrides?: Partial<unknown>): void;
|
|
14
|
+
//# sourceMappingURL=useMetaConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMetaConfig.d.ts","sourceRoot":"","sources":["../../src/composables/useMetaConfig.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAwEpF"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useMetaConfig Composable
|
|
3
|
+
*
|
|
4
|
+
* Configure meta-tags for a page with app-level configuration support
|
|
5
|
+
*/
|
|
6
|
+
import { useMeta } from 'quasar';
|
|
7
|
+
import { useQuvel } from './useQuvel.js';
|
|
8
|
+
/**
|
|
9
|
+
* Configure meta tags for a page, allowing full customization
|
|
10
|
+
* Uses app meta configuration when available, falls back to defaults
|
|
11
|
+
*
|
|
12
|
+
* @param pageTitle - The page title
|
|
13
|
+
* @param overrides - Optional overrides to modify metadata
|
|
14
|
+
*/
|
|
15
|
+
export function useMetaConfig(pageTitle, overrides) {
|
|
16
|
+
// Get app meta-configuration from the service container
|
|
17
|
+
const { config } = useQuvel();
|
|
18
|
+
const appMeta = config.meta || {};
|
|
19
|
+
// Use app configuration or fallback to defaults
|
|
20
|
+
const title = pageTitle ?? appMeta?.title ?? 'A Modern Hybrid App Framework';
|
|
21
|
+
// Create the title template function from app config or use default
|
|
22
|
+
const titleTemplate = appMeta?.titleTemplate
|
|
23
|
+
? (title) => appMeta.titleTemplate.replace('%s', title)
|
|
24
|
+
: (title) => `${title} - QuVel Kit`;
|
|
25
|
+
const description = appMeta?.description ??
|
|
26
|
+
'QuVel Kit is a Laravel & Quasar hybrid framework optimized for SSR and seamless development.';
|
|
27
|
+
const keywords = appMeta?.keywords ?? 'Quasar, Laravel, SSR, Hybrid, Framework';
|
|
28
|
+
const ogTitle = appMeta?.ogTitle ?? pageTitle ?? 'QuVel Kit';
|
|
29
|
+
const ogDescription = appMeta?.ogDescription ?? 'A powerful Laravel & Quasar SSR framework for building modern apps.';
|
|
30
|
+
const twitterTitle = appMeta?.twitterTitle ?? pageTitle ?? 'QuVel Kit';
|
|
31
|
+
const twitterDescription = appMeta?.twitterDescription ?? 'A Laravel & Quasar hybrid framework optimized for SSR.';
|
|
32
|
+
useMeta({
|
|
33
|
+
title,
|
|
34
|
+
titleTemplate,
|
|
35
|
+
meta: {
|
|
36
|
+
description: {
|
|
37
|
+
name: 'description',
|
|
38
|
+
content: description,
|
|
39
|
+
},
|
|
40
|
+
keywords: { name: 'keywords', content: keywords },
|
|
41
|
+
ogTitle: { property: 'og:title', content: ogTitle },
|
|
42
|
+
ogDescription: {
|
|
43
|
+
property: 'og:description',
|
|
44
|
+
content: ogDescription,
|
|
45
|
+
},
|
|
46
|
+
...(appMeta?.ogImage && {
|
|
47
|
+
ogImage: { property: 'og:image', content: appMeta.ogImage },
|
|
48
|
+
}),
|
|
49
|
+
ogType: { property: 'og:type', content: 'website' },
|
|
50
|
+
twitterCard: { name: 'twitter:card', content: 'summary_large_image' },
|
|
51
|
+
twitterTitle: { name: 'twitter:title', content: twitterTitle },
|
|
52
|
+
twitterDescription: {
|
|
53
|
+
name: 'twitter:description',
|
|
54
|
+
content: twitterDescription,
|
|
55
|
+
},
|
|
56
|
+
...(appMeta?.twitterImage && {
|
|
57
|
+
twitterImage: { name: 'twitter:image', content: appMeta.twitterImage },
|
|
58
|
+
}),
|
|
59
|
+
},
|
|
60
|
+
script: {
|
|
61
|
+
structuredData: {
|
|
62
|
+
type: 'application/ld+json',
|
|
63
|
+
innerHTML: JSON.stringify({
|
|
64
|
+
'@context': 'https://schema.org',
|
|
65
|
+
'@type': 'WebSite',
|
|
66
|
+
name: appMeta?.title ?? 'QuVel Kit',
|
|
67
|
+
url: config.frontend?.url ?? 'https://quvelkit.com',
|
|
68
|
+
description,
|
|
69
|
+
}),
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
htmlAttr: {
|
|
73
|
+
lang: 'en',
|
|
74
|
+
},
|
|
75
|
+
...(overrides || {}),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export type MessageHandlerOptions<T> = {
|
|
2
|
+
/** Query parameter key to check (default: 'message') */
|
|
3
|
+
key?: string;
|
|
4
|
+
/** Function to normalize the message value */
|
|
5
|
+
normalize?: (value: string) => T;
|
|
6
|
+
/** Function to determine notification type from normalized value */
|
|
7
|
+
type?: (normalized: string) => 'positive' | 'negative' | 'warning' | 'info';
|
|
8
|
+
/** i18n translation key prefix */
|
|
9
|
+
i18nPrefix?: string;
|
|
10
|
+
/** Notification timeout in ms (default: 8000) */
|
|
11
|
+
timeout?: number;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Generic composable to handle query-based messages
|
|
15
|
+
*
|
|
16
|
+
* Useful for displaying messages from redirects (e.g., OAuth callbacks, email verification).
|
|
17
|
+
* Automatically shows a notification if a matching query parameter exists, then removes
|
|
18
|
+
* the parameter from the URL.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* // Handle OAuth callback messages
|
|
23
|
+
* useQueryMessageHandler({
|
|
24
|
+
* key: 'message',
|
|
25
|
+
* i18nPrefix: 'auth.messages.',
|
|
26
|
+
* type: (msg) => msg.includes('success') ? 'positive' : 'negative'
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function useQueryMessageHandler<T = string>(options?: MessageHandlerOptions<T>): void;
|
|
31
|
+
/**
|
|
32
|
+
* Normalizes Laravel-style language keys to frontend format
|
|
33
|
+
*
|
|
34
|
+
* Backend: `module::key` → Frontend: `module.key`
|
|
35
|
+
*/
|
|
36
|
+
export declare function normalizeKey(key: string, prefix?: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Maps status keys to notification types
|
|
39
|
+
*
|
|
40
|
+
* Detects patterns like "status.success", "status.errors", etc.
|
|
41
|
+
* and returns the appropriate Quasar notification type.
|
|
42
|
+
*/
|
|
43
|
+
export declare function mapStatusToType(status: string): 'positive' | 'warning' | 'negative' | 'info';
|
|
44
|
+
//# sourceMappingURL=useQueryMessageHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useQueryMessageHandler.d.ts","sourceRoot":"","sources":["../../src/composables/useQueryMessageHandler.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,qBAAqB,CAAC,CAAC,IAAI;IACrC,wDAAwD;IACxD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,CAAC,CAAC;IACjC,oEAAoE;IACpE,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;IAC5E,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,GAAG,MAAM,EAAE,OAAO,GAAE,qBAAqB,CAAC,CAAC,CAAM,GAAG,IAAI,CAmC/F;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAW,GAAG,MAAM,CAErE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAa5F"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { onMounted } from 'vue';
|
|
2
|
+
import { useRoute, useRouter } from 'vue-router';
|
|
3
|
+
import { showNotification } from '../utils/notify.js';
|
|
4
|
+
import { useQuvel } from './useQuvel.js';
|
|
5
|
+
/**
|
|
6
|
+
* Generic composable to handle query-based messages
|
|
7
|
+
*
|
|
8
|
+
* Useful for displaying messages from redirects (e.g., OAuth callbacks, email verification).
|
|
9
|
+
* Automatically shows a notification if a matching query parameter exists, then removes
|
|
10
|
+
* the parameter from the URL.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* // Handle OAuth callback messages
|
|
15
|
+
* useQueryMessageHandler({
|
|
16
|
+
* key: 'message',
|
|
17
|
+
* i18nPrefix: 'auth.messages.',
|
|
18
|
+
* type: (msg) => msg.includes('success') ? 'positive' : 'negative'
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function useQueryMessageHandler(options = {}) {
|
|
23
|
+
const { key = 'message', normalize = normalizeKey, type = mapStatusToType, i18nPrefix = '', timeout = 8000, } = options;
|
|
24
|
+
const route = useRoute();
|
|
25
|
+
const router = useRouter();
|
|
26
|
+
const { i18n } = useQuvel();
|
|
27
|
+
onMounted(() => {
|
|
28
|
+
const { [key]: rawMessage, ...rest } = route.query;
|
|
29
|
+
if (typeof rawMessage !== 'string' || rawMessage.length === 0)
|
|
30
|
+
return;
|
|
31
|
+
try {
|
|
32
|
+
const normalized = normalize(decodeURIComponent(rawMessage));
|
|
33
|
+
const translationKey = i18nPrefix + normalized;
|
|
34
|
+
// Only show notification if translation exists
|
|
35
|
+
if (!i18n.te(translationKey)) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
showNotification(type(normalized), i18n.t(translationKey), { timeout });
|
|
39
|
+
// Remove the message from URL
|
|
40
|
+
router.replace({ query: rest }).catch(() => { });
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// Silently fail on decode/routing errors
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Normalizes Laravel-style language keys to frontend format
|
|
49
|
+
*
|
|
50
|
+
* Backend: `module::key` → Frontend: `module.key`
|
|
51
|
+
*/
|
|
52
|
+
export function normalizeKey(key, prefix = '') {
|
|
53
|
+
return key.replace(`${prefix}::`, `${prefix}.`);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Maps status keys to notification types
|
|
57
|
+
*
|
|
58
|
+
* Detects patterns like "status.success", "status.errors", etc.
|
|
59
|
+
* and returns the appropriate Quasar notification type.
|
|
60
|
+
*/
|
|
61
|
+
export function mapStatusToType(status) {
|
|
62
|
+
switch (true) {
|
|
63
|
+
case status.includes('status.success'):
|
|
64
|
+
return 'positive';
|
|
65
|
+
case status.includes('status.warnings'):
|
|
66
|
+
return 'warning';
|
|
67
|
+
case status.includes('status.errors'):
|
|
68
|
+
return 'negative';
|
|
69
|
+
case status.includes('status.info'):
|
|
70
|
+
return 'info';
|
|
71
|
+
default:
|
|
72
|
+
return 'info';
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ServiceContainer } from '../container/ServiceContainer.js';
|
|
2
|
+
/**
|
|
3
|
+
* Symbol for the Quvel service container key
|
|
4
|
+
*/
|
|
5
|
+
export declare const ContainerKey: unique symbol;
|
|
6
|
+
/**
|
|
7
|
+
* Assigns a singleton container in the browser
|
|
8
|
+
*/
|
|
9
|
+
export declare function setClientContainer(container: ServiceContainer): void;
|
|
10
|
+
/**
|
|
11
|
+
* Retrieves the Quvel service container
|
|
12
|
+
* Uses `ssrContext.$quvel` in SSR, singleton in the client
|
|
13
|
+
*/
|
|
14
|
+
export declare function useQuvel(): ServiceContainer;
|
|
15
|
+
//# sourceMappingURL=useQuvel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useQuvel.d.ts","sourceRoot":"","sources":["../../src/composables/useQuvel.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzE;;GAEG;AACH,eAAO,MAAM,YAAY,eAAmB,CAAC;AAO7C;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,gBAAgB,GAAG,IAAI,CAIpE;AAUD;;;GAGG;AACH,wBAAgB,QAAQ,IAAI,gBAAgB,CAmB3C"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useSSRContext } from 'vue';
|
|
2
|
+
/**
|
|
3
|
+
* Symbol for the Quvel service container key
|
|
4
|
+
*/
|
|
5
|
+
export const ContainerKey = Symbol('$quvel');
|
|
6
|
+
/**
|
|
7
|
+
* Holds the singleton service container in the client
|
|
8
|
+
*/
|
|
9
|
+
let clientContainer = null;
|
|
10
|
+
/**
|
|
11
|
+
* Assigns a singleton container in the browser
|
|
12
|
+
*/
|
|
13
|
+
export function setClientContainer(container) {
|
|
14
|
+
if (typeof window !== 'undefined') {
|
|
15
|
+
clientContainer = container;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Retrieves the Quvel service container
|
|
20
|
+
* Uses `ssrContext.$quvel` in SSR, singleton in the client
|
|
21
|
+
*/
|
|
22
|
+
export function useQuvel() {
|
|
23
|
+
if (typeof window === 'undefined') {
|
|
24
|
+
const context = useSSRContext();
|
|
25
|
+
if (context?.$quvel) {
|
|
26
|
+
return context.$quvel;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
throw new Error('SSR container not initialized. Ensure ssrContext is set in quvel boot file.');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
if (!clientContainer) {
|
|
34
|
+
throw new Error('Client container not initialized. Ensure quvel boot file ran.');
|
|
35
|
+
}
|
|
36
|
+
return clientContainer;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composable for handling Google reCAPTCHA v3
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* const { isLoaded, execute } = useRecaptcha();
|
|
7
|
+
*
|
|
8
|
+
* // Execute reCAPTCHA for a specific action
|
|
9
|
+
* const token = await execute('login');
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export declare function useRecaptcha(): {
|
|
13
|
+
isLoaded: import("vue").Ref<boolean, boolean>;
|
|
14
|
+
isLoading: import("vue").Ref<boolean, boolean>;
|
|
15
|
+
error: import("vue").Ref<Error | null, Error | null>;
|
|
16
|
+
load: () => Promise<void>;
|
|
17
|
+
unload: () => void;
|
|
18
|
+
execute: (action: string) => Promise<string>;
|
|
19
|
+
recaptchaKey: import("vue").ComputedRef<string>;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Global window augmentation for Google reCAPTCHA
|
|
23
|
+
*/
|
|
24
|
+
declare global {
|
|
25
|
+
interface Window {
|
|
26
|
+
grecaptcha: {
|
|
27
|
+
ready: (callback: () => void) => void;
|
|
28
|
+
execute: (siteKey: string, options: {
|
|
29
|
+
action: string;
|
|
30
|
+
}) => Promise<string>;
|
|
31
|
+
reset: () => void;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=useRecaptcha.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRecaptcha.d.ts","sourceRoot":"","sources":["../../src/composables/useRecaptcha.ts"],"names":[],"mappings":"AASA;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY;;;;;;sBA2CK,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;;EAkCxD;AAED;;GAEG;AACH,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,UAAU,EAAE;YACV,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;YACtC,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;gBAAE,MAAM,EAAE,MAAM,CAAA;aAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;YAC3E,KAAK,EAAE,MAAM,IAAI,CAAC;SACnB,CAAC;KACH;CACF"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { computed } from 'vue';
|
|
2
|
+
import { useScript } from './useScript.js';
|
|
3
|
+
import { useQuvel } from './useQuvel.js';
|
|
4
|
+
/**
|
|
5
|
+
* Script constants
|
|
6
|
+
*/
|
|
7
|
+
const SCRIPT_ID = 'google_recaptcha';
|
|
8
|
+
/**
|
|
9
|
+
* Composable for handling Google reCAPTCHA v3
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const { isLoaded, execute } = useRecaptcha();
|
|
14
|
+
*
|
|
15
|
+
* // Execute reCAPTCHA for a specific action
|
|
16
|
+
* const token = await execute('login');
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export function useRecaptcha() {
|
|
20
|
+
const { config } = useQuvel();
|
|
21
|
+
const recaptchaKey = computed(() => config.recaptchaGoogleSiteKey || '');
|
|
22
|
+
const recaptchaUrl = computed(() => `https://www.google.com/recaptcha/api.js?render=${recaptchaKey.value}`);
|
|
23
|
+
const { isLoaded, isLoading, error, load, unload } = useScript(SCRIPT_ID, recaptchaUrl.value, {
|
|
24
|
+
autoLoad: true,
|
|
25
|
+
autoUnload: true,
|
|
26
|
+
onUnload: () => {
|
|
27
|
+
// Cleanup global grecaptcha reference
|
|
28
|
+
if ('grecaptcha' in window) {
|
|
29
|
+
delete window.grecaptcha;
|
|
30
|
+
}
|
|
31
|
+
// Remove the badge injected by reCAPTCHA v3
|
|
32
|
+
const badge = document.querySelector('.grecaptcha-badge');
|
|
33
|
+
if (badge?.parentNode) {
|
|
34
|
+
badge.parentNode.removeChild(badge);
|
|
35
|
+
}
|
|
36
|
+
// Remove any iframes injected by Google
|
|
37
|
+
document.querySelectorAll('iframe[src*="recaptcha"]').forEach((iframe) => {
|
|
38
|
+
iframe.remove();
|
|
39
|
+
});
|
|
40
|
+
// Remove any scripts injected by Google
|
|
41
|
+
document.querySelectorAll('script[src*="recaptcha"]').forEach((script) => {
|
|
42
|
+
script.remove();
|
|
43
|
+
});
|
|
44
|
+
// Remove origin-trial meta tags
|
|
45
|
+
document.querySelectorAll('meta[http-equiv="origin-trial"]').forEach((meta) => {
|
|
46
|
+
meta.remove();
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
/**
|
|
51
|
+
* Executes a reCAPTCHA action and returns a token
|
|
52
|
+
*
|
|
53
|
+
* @param action - The action name for this reCAPTCHA execution
|
|
54
|
+
* @returns Promise that resolves to the reCAPTCHA token
|
|
55
|
+
*/
|
|
56
|
+
async function execute(action) {
|
|
57
|
+
if (!isLoaded.value) {
|
|
58
|
+
await load();
|
|
59
|
+
}
|
|
60
|
+
if (!window.grecaptcha) {
|
|
61
|
+
throw new Error('reCAPTCHA not available on window');
|
|
62
|
+
}
|
|
63
|
+
const siteKey = recaptchaKey.value;
|
|
64
|
+
if (!siteKey) {
|
|
65
|
+
throw new Error('reCAPTCHA site key not configured');
|
|
66
|
+
}
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
68
|
+
try {
|
|
69
|
+
window.grecaptcha.ready(() => {
|
|
70
|
+
window.grecaptcha.execute(siteKey, { action }).then(resolve).catch(reject);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
reject(err instanceof Error ? err : new Error('Failed to execute reCAPTCHA'));
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
isLoaded,
|
|
80
|
+
isLoading,
|
|
81
|
+
error,
|
|
82
|
+
load,
|
|
83
|
+
unload,
|
|
84
|
+
execute,
|
|
85
|
+
recaptchaKey,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useScopedService Composable
|
|
3
|
+
*
|
|
4
|
+
* Provides a component-scoped service instance
|
|
5
|
+
* The service is created if missing and cleaned up on component unmounted
|
|
6
|
+
*/
|
|
7
|
+
import type { ServiceClass } from '../container/types.js';
|
|
8
|
+
import type { Service } from '../services/Service.js';
|
|
9
|
+
/**
|
|
10
|
+
* Provides a component-scoped service instance
|
|
11
|
+
*
|
|
12
|
+
* Creates a service instance and is automatically cleaned up when the component unmounts
|
|
13
|
+
*
|
|
14
|
+
* @param ServiceClass - Service class constructor
|
|
15
|
+
* @returns Service instance
|
|
16
|
+
*/
|
|
17
|
+
export declare function useScopedService<T extends Service>(ServiceClass: ServiceClass<T>): T;
|
|
18
|
+
//# sourceMappingURL=useScopedService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useScopedService.d.ts","sourceRoot":"","sources":["../../src/composables/useScopedService.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAGtD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,OAAO,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAWpF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useScopedService Composable
|
|
3
|
+
*
|
|
4
|
+
* Provides a component-scoped service instance
|
|
5
|
+
* The service is created if missing and cleaned up on component unmounted
|
|
6
|
+
*/
|
|
7
|
+
import { onBeforeUnmount } from 'vue';
|
|
8
|
+
import { useQuvel } from './useQuvel.js';
|
|
9
|
+
/**
|
|
10
|
+
* Provides a component-scoped service instance
|
|
11
|
+
*
|
|
12
|
+
* Creates a service instance and is automatically cleaned up when the component unmounts
|
|
13
|
+
*
|
|
14
|
+
* @param ServiceClass - Service class constructor
|
|
15
|
+
* @returns Service instance
|
|
16
|
+
*/
|
|
17
|
+
export function useScopedService(ServiceClass) {
|
|
18
|
+
const container = useQuvel();
|
|
19
|
+
const service = container.get(ServiceClass);
|
|
20
|
+
const name = service.constructor.name;
|
|
21
|
+
onBeforeUnmount(() => {
|
|
22
|
+
container.removeService(name);
|
|
23
|
+
});
|
|
24
|
+
return service;
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useScript Composable
|
|
3
|
+
*
|
|
4
|
+
* Composable for dynamically loading external scripts.
|
|
5
|
+
* Provides a clean interface for loading, unloading, and managing external scripts
|
|
6
|
+
* in Vue components. Handles script lifecycle, loading states, and error handling.
|
|
7
|
+
*/
|
|
8
|
+
import type { ScriptOptions } from '../types/scripts.types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Dynamically loads and manages an external script
|
|
11
|
+
*
|
|
12
|
+
* @param scriptId - Unique identifier for the script element
|
|
13
|
+
* @param scriptUrl - URL of the script to load
|
|
14
|
+
* @param options - Configuration options for script loading behavior
|
|
15
|
+
* @returns Object containing script state and methods
|
|
16
|
+
*/
|
|
17
|
+
export declare function useScript(scriptId: string, scriptUrl: string, options?: ScriptOptions): {
|
|
18
|
+
isLoaded: import("vue").Ref<boolean, boolean>;
|
|
19
|
+
isLoading: import("vue").Ref<boolean, boolean>;
|
|
20
|
+
error: import("vue").Ref<Error | null, Error | null>;
|
|
21
|
+
load: () => Promise<void>;
|
|
22
|
+
unload: () => void;
|
|
23
|
+
reload: () => Promise<void>;
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=useScript.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useScript.d.ts","sourceRoot":"","sources":["../../src/composables/useScript.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB;;;;gBAUvE,OAAO,CAAC,IAAI,CAAC;kBAkDX,IAAI;kBAiBE,OAAO,CAAC,IAAI,CAAC;EAyBvC"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useScript Composable
|
|
3
|
+
*
|
|
4
|
+
* Composable for dynamically loading external scripts.
|
|
5
|
+
* Provides a clean interface for loading, unloading, and managing external scripts
|
|
6
|
+
* in Vue components. Handles script lifecycle, loading states, and error handling.
|
|
7
|
+
*/
|
|
8
|
+
import { ref, onBeforeUnmount } from 'vue';
|
|
9
|
+
import { loadScript, unloadScript } from '../utils/scripts.js';
|
|
10
|
+
/**
|
|
11
|
+
* Dynamically loads and manages an external script
|
|
12
|
+
*
|
|
13
|
+
* @param scriptId - Unique identifier for the script element
|
|
14
|
+
* @param scriptUrl - URL of the script to load
|
|
15
|
+
* @param options - Configuration options for script loading behavior
|
|
16
|
+
* @returns Object containing script state and methods
|
|
17
|
+
*/
|
|
18
|
+
export function useScript(scriptId, scriptUrl, options = {}) {
|
|
19
|
+
const isLoaded = ref(false);
|
|
20
|
+
const isLoading = ref(false);
|
|
21
|
+
const error = ref(null);
|
|
22
|
+
/**
|
|
23
|
+
* Loads the script if not already loaded
|
|
24
|
+
*
|
|
25
|
+
* @returns Promise resolving when script is loaded
|
|
26
|
+
*/
|
|
27
|
+
function load() {
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
if (isLoaded.value) {
|
|
30
|
+
resolve();
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (isLoading.value) {
|
|
34
|
+
const checkInterval = setInterval(() => {
|
|
35
|
+
if (isLoaded.value) {
|
|
36
|
+
clearInterval(checkInterval);
|
|
37
|
+
resolve();
|
|
38
|
+
}
|
|
39
|
+
if (error.value) {
|
|
40
|
+
clearInterval(checkInterval);
|
|
41
|
+
reject(error.value);
|
|
42
|
+
}
|
|
43
|
+
}, 100);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
isLoading.value = true;
|
|
47
|
+
try {
|
|
48
|
+
loadScript(scriptId, scriptUrl, () => {
|
|
49
|
+
isLoaded.value = true;
|
|
50
|
+
isLoading.value = false;
|
|
51
|
+
if (options.onLoad) {
|
|
52
|
+
options.onLoad();
|
|
53
|
+
}
|
|
54
|
+
resolve();
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
isLoading.value = false;
|
|
59
|
+
error.value = err instanceof Error ? err : new Error(`Failed to load script: ${scriptId}`);
|
|
60
|
+
if (options.onError) {
|
|
61
|
+
options.onError(error.value);
|
|
62
|
+
}
|
|
63
|
+
reject(error.value);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Unloads the script and resets the state
|
|
69
|
+
*/
|
|
70
|
+
function unload() {
|
|
71
|
+
unloadScript(scriptId);
|
|
72
|
+
if (options.onUnload) {
|
|
73
|
+
options.onUnload();
|
|
74
|
+
}
|
|
75
|
+
isLoaded.value = false;
|
|
76
|
+
isLoading.value = false;
|
|
77
|
+
error.value = null;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Reloads the script by unloading and loading it again
|
|
81
|
+
*
|
|
82
|
+
* @returns Promise resolving when script is reloaded
|
|
83
|
+
*/
|
|
84
|
+
async function reload() {
|
|
85
|
+
unload();
|
|
86
|
+
return load();
|
|
87
|
+
}
|
|
88
|
+
// Auto-load if requested
|
|
89
|
+
if (options.autoLoad) {
|
|
90
|
+
void load();
|
|
91
|
+
}
|
|
92
|
+
// Auto-unload on unmount unless disabled
|
|
93
|
+
if (options.autoUnload !== false) {
|
|
94
|
+
onBeforeUnmount(() => {
|
|
95
|
+
unload();
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
isLoaded,
|
|
100
|
+
isLoading,
|
|
101
|
+
error,
|
|
102
|
+
load,
|
|
103
|
+
unload,
|
|
104
|
+
reload,
|
|
105
|
+
};
|
|
106
|
+
}
|