From c315cc2bcc01356ce1fabc46fc9520349484a085 Mon Sep 17 00:00:00 2001 From: Jarek Rozanski Date: Wed, 29 Jan 2025 01:01:34 +0100 Subject: [PATCH] Refactoring Nuxt plugin --- README.md | 28 ++++++++++------ package.json | 13 ++++---- playground/app.vue | 36 -------------------- playground/components/sample-tracker.vue | 11 +++++++ playground/nuxt.config.ts | 15 ++++++--- playground/package.json | 4 --- playground/pages/index.vue | 7 ++++ src/module.ts | 35 ++++++++------------ src/runtime/composables/useWaa.ts | 8 ----- src/runtime/composables/useWideAngle.ts | 27 +++++++++++++++ src/runtime/plugin.client.ts | 42 ++++++++++++++---------- src/types.ts | 5 +++ 12 files changed, 122 insertions(+), 109 deletions(-) delete mode 100644 playground/app.vue create mode 100644 playground/components/sample-tracker.vue delete mode 100644 playground/package.json create mode 100644 playground/pages/index.vue delete mode 100644 src/runtime/composables/useWaa.ts create mode 100644 src/runtime/composables/useWideAngle.ts create mode 100644 src/types.ts diff --git a/README.md b/README.md index 810c79d..5cd5b83 100644 --- a/README.md +++ b/README.md @@ -87,11 +87,21 @@ export default defineNuxtConfig({ # Usage -The Wide Angle Analytics provides an instance of `waa` which can be then injected to your component. +The Wide Angle Analytics provides a composable which can be used in your component. ```javascript -const waa = useWaa(); -waa.dispatchEvent('purchase', {'basket_element': 'dress'}, {'basket_item_price': 123.44}); + + + + ``` You will find a fully functional example in this [repository](playground/app.vue). @@ -132,16 +142,14 @@ Example: ``` @@ -196,9 +204,9 @@ Example usage: ```vue - - diff --git a/playground/components/sample-tracker.vue b/playground/components/sample-tracker.vue new file mode 100644 index 0000000..95b3c49 --- /dev/null +++ b/playground/components/sample-tracker.vue @@ -0,0 +1,11 @@ + + + diff --git a/playground/nuxt.config.ts b/playground/nuxt.config.ts index 1c2483a..26526db 100644 --- a/playground/nuxt.config.ts +++ b/playground/nuxt.config.ts @@ -1,12 +1,17 @@ +// https://nuxt.com/docs/api/configuration/nuxt-config export default defineNuxtConfig({ - modules: ['../src/module'], + devtools: { enabled: true }, + compatibilityDate: "2025-01-28", + modules: ['wideangle-nuxt'], + // ssr: false, runtimeConfig: { public: { wideangle: { - siteId: "7982G3B9ACB1BF4380", - fingerprint: true, - supressDnt: true + siteId: "8D27G3B9ACA01F4241", + domain: "events.wideangle.test", + fingerprint: false, + suppressDnt: true } } } -}); +}) diff --git a/playground/package.json b/playground/package.json deleted file mode 100644 index 6a7f1ae..0000000 --- a/playground/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "private": true, - "name": "wideangle-playground" -} diff --git a/playground/pages/index.vue b/playground/pages/index.vue new file mode 100644 index 0000000..69ee7a6 --- /dev/null +++ b/playground/pages/index.vue @@ -0,0 +1,7 @@ + + diff --git a/src/module.ts b/src/module.ts index cdd70f7..5417971 100644 --- a/src/module.ts +++ b/src/module.ts @@ -1,6 +1,5 @@ -import { defineNuxtModule, addPlugin, addImports, createResolver, useLogger } from '@nuxt/kit' +import { defineNuxtModule, addPlugin, addImportsDir, createResolver, useLogger } from '@nuxt/kit' import { defu } from 'defu' -import { fileURLToPath } from 'url' const logger = useLogger('nuxt:wideangle') @@ -20,40 +19,32 @@ export default defineNuxtModule({ name: 'wideangle', configKey: 'wideangle', compatibility: { - nuxt: '>=3' - } + nuxt: '>=3', + }, }, defaults: { - domain: "stats.wideangle.co", + domain: 'stats.wideangle.co', fingerprint: false, suppressDnt: false, includeParams: [], excludePaths: [], ignoreHash: false, - consentMarker: null + consentMarker: undefined, }, - setup (options, nuxt) { - const runtimeDir = fileURLToPath(new URL('./runtime', import.meta.url)) - + setup(options, nuxt) { + const resolver = createResolver(import.meta.url) nuxt.options.runtimeConfig.public.wideangle = defu( nuxt.options.runtimeConfig.public.wideangle, options, ) - nuxt.options.build.transpile.push(runtimeDir); - const resolver = createResolver(import.meta.url); + nuxt.options.build.transpile.push(resolver.resolve('./runtime')) - logger.info('Adding Wide Angle Analytics runtime plugin'); + logger.info('Adding Wide Angle Analytics (useWideAngle) import') + addImportsDir(resolver.resolve('./runtime/composables')) - addImports({ - name: "useWaaEvent", - as: "useWaaEvent", - from: resolver.resolve('./runtime/composables/useWaaEvent') - }); + logger.info('Adding Wide Angle Analytics runtime plugin') + addPlugin(resolver.resolve('./runtime/plugin.client')) - addPlugin({ - src: resolver.resolve('./runtime/plugin.client') - }); - - } + }, }) diff --git a/src/runtime/composables/useWaa.ts b/src/runtime/composables/useWaa.ts deleted file mode 100644 index 3d6f53e..0000000 --- a/src/runtime/composables/useWaa.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { useNuxtApp } from '#imports'; - -function useWaa() { - const waa = useNuxtApp().$waa; - return waa.value; -} - -export useWaa; diff --git a/src/runtime/composables/useWideAngle.ts b/src/runtime/composables/useWideAngle.ts new file mode 100644 index 0000000..1c9ab74 --- /dev/null +++ b/src/runtime/composables/useWideAngle.ts @@ -0,0 +1,27 @@ +import {useNuxtApp} from '#imports' +import type {WideAngleApi} from "~/src/types"; + +class NoOpWideAngleAnalyticsApi implements WideAngleApi { + dispatchEvent(name: string, params: any, values: any): void { + console.debug(`[WideAngleApi#dispatchEvent] Defaulting to NoOp Wide Angle call with name "${name}", params: ${JSON.stringify(params)}, values: ${JSON.stringify(params)}`); + } + + recordConsent(subjectsId: string): void { + console.debug(`[WideAngleApi#recordConsent] Defaulting to NoOp Wide Angle call with ${subjectsId}`); + } + + revokeConsent() { + console.debug(`[WideAngleApi#revokeConsent] Defaulting to NoOp Wide Angle call`); + } +} + +const noOpWideAngleApi = new NoOpWideAngleAnalyticsApi(); + +export function useWideAngle() { + const { $waa } = useNuxtApp() + if ($waa) { + return $waa.value; + } else { + return noOpWideAngleApi; + } +} diff --git a/src/runtime/plugin.client.ts b/src/runtime/plugin.client.ts index c44cddc..4ba97cf 100644 --- a/src/runtime/plugin.client.ts +++ b/src/runtime/plugin.client.ts @@ -1,30 +1,36 @@ -import { defineNuxtPlugin, useRuntimeConfig } from '#imports'; -import { ref } from 'vue'; -import { initWideAngle } from 'wideangle-vuejs'; +import { type Ref, ref} from 'vue' +import { initWideAngle } from 'wideangle-vuejs' +import { defineNuxtPlugin, type NuxtApp } from '#app' +import { useRuntimeConfig } from "#imports"; +import type { WideAngleApi } from "~/src/types"; -export default defineNuxtPlugin(() => { - if(import.meta.server) { - console.warn("[WAA] Plugin will not be enabled on server side."); - return; +export default defineNuxtPlugin(async (_nuxtApp) => { + + if (import.meta.server) { + console.warn('[WAA] Plugin will not be enabled on server side.') + return } const { wideangle: options } = useRuntimeConfig().public - console.debug(`[WAA] Initializing Wide Angle Analytics with: ${JSON.stringify(options)}`); - if(options.siteId == null) { - throw new Error("[WAA] Wide Angle Analytics requires the site ID."); + console.debug(`[WAA] Initializing Wide Angle Analytics with: ${JSON.stringify(options)}`) + + if (options.siteId == null) { + throw new Error('[WAA] Wide Angle Analytics requires the site ID.') } + const waa = ref() + initWideAngle(options) - .then(waaInstance => { - waa.value = waaInstance; - console.debug("[WAA] Wide Angle Analytics instance available"); - }).catch(e => { console.error("[WAA] Failed to load Wide Angle Plugin", e)}); + .then((waaInstance) => { + waa.value = waaInstance + console.debug('[WAA] Wide Angle Analytics instance available') + }).catch((e) => { + console.error('[WAA] Failed to load Wide Angle Plugin', e) + }) return { provide: { - waa - } + waa: waa as Ref, + }, } }) - - diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..d326b5a --- /dev/null +++ b/src/types.ts @@ -0,0 +1,5 @@ +export interface WideAngleApi { + dispatchEvent(name: string, params: any, values: any) : void; + recordConsent(subjectsId: string) : void; + revokeConsent() : void; +}