@dargmuesli/nuxt-vio 17.0.4 → 18.0.1

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.
Files changed (109) hide show
  1. package/.config/lint.js +1 -2
  2. package/{components → app/components}/vio/_/VioApp.vue +7 -18
  3. package/{components → app/components}/vio/_/VioError.vue +1 -3
  4. package/{components → app/components}/vio/_/VioLink.vue +0 -2
  5. package/{components → app/components}/vio/form/VioForm.vue +0 -2
  6. package/{components → app/components}/vio/loader/Loader.vue +0 -2
  7. package/{components → app/components}/vio/page/VioPageLegalNotice.vue +0 -3
  8. package/{components → app/components}/vio/page/VioPagePrivacyPolicy.vue +0 -3
  9. package/app/composables/head.ts +115 -0
  10. package/app/composables/networking.ts +30 -0
  11. package/{error.vue → app/error.vue} +2 -1
  12. package/app/pages/legal-notice.vue +20 -0
  13. package/{pages → app/pages}/privacy-policy.vue +33 -16
  14. package/i18n/i18n.config.ts +0 -2
  15. package/i18n/locales/de.json +1 -0
  16. package/i18n/locales/en.json +1 -0
  17. package/nuxt.config.ts +16 -9
  18. package/package.json +18 -30
  19. package/server/middleware/headers.ts +0 -2
  20. package/server/plugins/security.ts +1 -2
  21. package/{composables/useGetServiceHref.ts → server/utils/networking.ts} +10 -1
  22. package/server/utils/testing.ts +0 -1
  23. package/server/utils/timezone.ts +0 -2
  24. package/{utils → shared/utils}/auth.ts +1 -2
  25. package/{utils → shared/utils}/constants.ts +6 -6
  26. package/{utils → shared/utils}/networking.ts +6 -7
  27. package/composables/useAppLayout.ts +0 -28
  28. package/composables/useFavicons.ts +0 -21
  29. package/composables/useHeadDefault.ts +0 -25
  30. package/composables/useHost.ts +0 -9
  31. package/composables/usePolyfills.ts +0 -28
  32. package/pages/legal-notice.vue +0 -3
  33. /package/{app.config.ts → app/app.config.ts} +0 -0
  34. /package/{assets → app/assets}/css/forms.css +0 -0
  35. /package/{assets → app/assets}/css/vio.css +0 -0
  36. /package/{components → app/components}/vio/button/VioButton.vue +0 -0
  37. /package/{components → app/components}/vio/button/VioButtonColored.vue +0 -0
  38. /package/{components → app/components}/vio/button/VioButtonHome.vue +0 -0
  39. /package/{components → app/components}/vio/button/VioButtonIcon.vue +0 -0
  40. /package/{components → app/components}/vio/button/VioButtonList.vue +0 -0
  41. /package/{components → app/components}/vio/button/VioButtonShare.vue +0 -0
  42. /package/{components → app/components}/vio/card/VioCard.vue +0 -0
  43. /package/{components → app/components}/vio/card/state/VioCardState.vue +0 -0
  44. /package/{components → app/components}/vio/card/state/VioCardStateAlert.vue +0 -0
  45. /package/{components → app/components}/vio/card/state/VioCardStateInfo.vue +0 -0
  46. /package/{components → app/components}/vio/form/VioFormCheckbox.vue +0 -0
  47. /package/{components → app/components}/vio/form/VioFormContact.vue +0 -0
  48. /package/{components → app/components}/vio/form/input/VioFormInput.vue +0 -0
  49. /package/{components → app/components}/vio/form/input/VioFormInputEmailAddress.vue +0 -0
  50. /package/{components → app/components}/vio/form/input/VioFormInputIconWrapper.vue +0 -0
  51. /package/{components → app/components}/vio/form/input/VioFormInputUrl.vue +0 -0
  52. /package/{components → app/components}/vio/form/input/state/VioFormInputState.vue +0 -0
  53. /package/{components → app/components}/vio/form/input/state/VioFormInputStateError.vue +0 -0
  54. /package/{components → app/components}/vio/form/input/state/VioFormInputStateInfo.vue +0 -0
  55. /package/{components → app/components}/vio/icon/VioIconArrowLeft.vue +0 -0
  56. /package/{components → app/components}/vio/icon/VioIconArrowRight.vue +0 -0
  57. /package/{components → app/components}/vio/icon/VioIconCalendar.vue +0 -0
  58. /package/{components → app/components}/vio/icon/VioIconChartBar.vue +0 -0
  59. /package/{components → app/components}/vio/icon/VioIconChatOutline.vue +0 -0
  60. /package/{components → app/components}/vio/icon/VioIconChatSolid.vue +0 -0
  61. /package/{components → app/components}/vio/icon/VioIconCheckCircle.vue +0 -0
  62. /package/{components → app/components}/vio/icon/VioIconContainer.vue +0 -0
  63. /package/{components → app/components}/vio/icon/VioIconDownload.vue +0 -0
  64. /package/{components → app/components}/vio/icon/VioIconExclamationCircle.vue +0 -0
  65. /package/{components → app/components}/vio/icon/VioIconHeart.vue +0 -0
  66. /package/{components → app/components}/vio/icon/VioIconHome.vue +0 -0
  67. /package/{components → app/components}/vio/icon/VioIconHourglass.vue +0 -0
  68. /package/{components → app/components}/vio/icon/VioIconLightbulb.vue +0 -0
  69. /package/{components → app/components}/vio/icon/VioIconMixcloud.vue +0 -0
  70. /package/{components → app/components}/vio/icon/VioIconMusic.vue +0 -0
  71. /package/{components → app/components}/vio/icon/VioIconPlay.vue +0 -0
  72. /package/{components → app/components}/vio/icon/VioIconShare.vue +0 -0
  73. /package/{components → app/components}/vio/icon/VioIconSignIn.vue +0 -0
  74. /package/{components → app/components}/vio/icon/VioIconTv.vue +0 -0
  75. /package/{components → app/components}/vio/layout/VioLayout.vue +0 -0
  76. /package/{components → app/components}/vio/layout/VioLayoutBreadcrumbs.vue +0 -0
  77. /package/{components → app/components}/vio/layout/VioLayoutFooter.vue +0 -0
  78. /package/{components → app/components}/vio/layout/VioLayoutFooterCategory.vue +0 -0
  79. /package/{components → app/components}/vio/layout/VioLayoutHr.vue +0 -0
  80. /package/{components → app/components}/vio/layout/VioLayoutProse.vue +0 -0
  81. /package/{components → app/components}/vio/layout/VioLayoutSpanList.vue +0 -0
  82. /package/{components → app/components}/vio/layout/VioLayoutTbody.vue +0 -0
  83. /package/{components → app/components}/vio/layout/VioLayoutThead.vue +0 -0
  84. /package/{components → app/components}/vio/loader/LoaderImage.vue +0 -0
  85. /package/{components → app/components}/vio/loader/indicator/LoaderIndicatorText.vue +0 -0
  86. /package/{components → app/components}/vio/loader/indicator/VioLoaderIndicator.vue +0 -0
  87. /package/{components → app/components}/vio/loader/indicator/VioLoaderIndicatorPing.vue +0 -0
  88. /package/{components → app/components}/vio/loader/indicator/VioLoaderIndicatorSpinner.vue +0 -0
  89. /package/{composables/useFireError.ts → app/composables/alert.ts} +0 -0
  90. /package/{composables → app/composables}/dateTime.ts +0 -0
  91. /package/{composables/useVioGtag.ts → app/composables/gtag.ts} +0 -0
  92. /package/{composables/useLoadingDoneIndicator.ts → app/composables/loading.ts} +0 -0
  93. /package/{composables/useStrapiFetch.ts → app/composables/strapi.ts} +0 -0
  94. /package/{composables → app/composables}/testing.ts +0 -0
  95. /package/{layouts → app/layouts}/default.vue +0 -0
  96. /package/{plugins → app/plugins}/dayjs.ts +0 -0
  97. /package/{plugins → app/plugins}/i18n.ts +0 -0
  98. /package/{store → app/stores}/auth.ts +0 -0
  99. /package/{types → shared/types}/api.d.ts +0 -0
  100. /package/{types → shared/types}/fetch.d.ts +0 -0
  101. /package/{types → shared/types}/i18n.d.ts +0 -0
  102. /package/{types → shared/types}/modules/gql.d.ts +0 -0
  103. /package/{types → shared/types}/modules/graphql.d.ts +0 -0
  104. /package/{utils → shared/utils}/form.ts +0 -0
  105. /package/{utils → shared/utils}/modal.ts +0 -0
  106. /package/{utils → shared/utils}/nuxt.ts +0 -0
  107. /package/{utils → shared/utils}/text.ts +0 -0
  108. /package/{utils → shared/utils}/timezone.ts +0 -0
  109. /package/{utils → shared/utils}/utils.ts +0 -0
package/.config/lint.js CHANGED
@@ -1,6 +1,5 @@
1
1
  // @ts-check
2
2
 
3
- // @ts-ignore
4
3
  import vueI18n from '@intlify/eslint-plugin-vue-i18n'
5
4
  import eslintPluginCompat from 'eslint-plugin-compat'
6
5
  import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
@@ -9,7 +8,7 @@ import globals from 'globals'
9
8
  import { createJiti } from 'jiti'
10
9
 
11
10
  const jiti = createJiti(import.meta.url)
12
- const constants = await jiti.import('../utils/constants.ts')
11
+ const constants = await jiti.import('../shared/utils/constants.ts')
13
12
  // @ts-ignore
14
13
  const POLYFILLS = constants.POLYFILLS
15
14
 
@@ -10,23 +10,19 @@
10
10
 
11
11
  <script setup lang="ts">
12
12
  interface Props {
13
- ogImageAlt: string
14
13
  ogImageComponent?: string
15
14
  }
16
15
  const props = withDefaults(defineProps<Props>(), {
17
16
  ogImageComponent: undefined,
18
17
  })
19
- const ogImageAltProp = toRef(() => props.ogImageAlt)
20
- const ogImageComponentProp = toRef(() => props.ogImageComponent)
21
18
 
22
19
  const { $dayjs } = useNuxtApp()
23
- const { locale } = useI18n()
24
- const siteConfig = useSiteConfig()
20
+ const { locale, t } = useI18n()
25
21
 
26
22
  const { loadingIds, indicateLoadingDone } = useLoadingDoneIndicator('app')
27
23
 
28
24
  // methods
29
- const init = () => {
25
+ const initialize = () => {
30
26
  $dayjs.locale(locale.value)
31
27
 
32
28
  if (import.meta.client) {
@@ -49,22 +45,15 @@ onMounted(() => indicateLoadingDone())
49
45
 
50
46
  // initialization
51
47
  defineOgImageComponent(
52
- ogImageComponentProp.value || 'NuxtSeo',
48
+ props.ogImageComponent || 'NuxtSeo',
49
+ {},
53
50
  {
54
- description: siteConfig.description,
55
- },
56
- {
57
- alt: ogImageAltProp.value,
51
+ alt: t('globalSeoOgImageAlt'),
58
52
  },
59
53
  )
60
54
  useAppLayout()
61
- useFavicons()
62
55
  usePolyfills()
63
- useSchemaOrg([
64
- defineWebSite({
65
- description: siteConfig.description,
66
- }),
67
- ])
56
+ useSchemaOrg([defineWebSite()])
68
57
  useVioGtag()
69
- init()
58
+ initialize()
70
59
  </script>
@@ -36,9 +36,7 @@ const title = `${props.statusCode ? `${props.statusCode} - ` : ''}${
36
36
  }`
37
37
 
38
38
  // initialization
39
- useHeadDefault({
40
- title,
41
- })
39
+ useHeadDefault({ title })
42
40
  </script>
43
41
 
44
42
  <i18n lang="yaml">
@@ -26,8 +26,6 @@
26
26
 
27
27
  <script setup lang="ts">
28
28
  import type { NuxtLinkProps } from '#app'
29
- import type { I18N_LOCALE_CODE } from '../../../types/i18n'
30
- import { append } from '../../../utils/utils' // TODO: wait for autoimport to be fixed and remove this import
31
29
 
32
30
  interface Props {
33
31
  ariaLabel?: string
@@ -43,8 +43,6 @@
43
43
  <script setup lang="ts">
44
44
  import type { BaseValidation } from '@vuelidate/core'
45
45
 
46
- import type { BackendError } from '../../../types/api'
47
-
48
46
  interface Props {
49
47
  errors?: BackendError[]
50
48
  errorsPgIds?: Record<string, string>
@@ -16,8 +16,6 @@
16
16
  <script setup lang="ts">
17
17
  import type { UnwrapRef } from 'vue'
18
18
 
19
- import type { ApiData } from '@dargmuesli/nuxt-vio/types/api'
20
-
21
19
  interface Props {
22
20
  api: UnwrapRef<ApiData>
23
21
  errorPgIds?: Record<string, string>
@@ -73,9 +73,6 @@ const { t } = useI18n()
73
73
 
74
74
  // data
75
75
  const title = t('title')
76
-
77
- // initialization
78
- useHeadDefault({ title })
79
76
  </script>
80
77
 
81
78
  <i18n lang="yaml">
@@ -507,9 +507,6 @@ const { t } = useI18n()
507
507
 
508
508
  // data
509
509
  const title = t('title')
510
-
511
- // initialization
512
- useHeadDefault({ title })
513
510
  </script>
514
511
 
515
512
  <i18n lang="yaml">
@@ -0,0 +1,115 @@
1
+ export const useAppLayout = () => {
2
+ const appConfig = useAppConfig()
3
+ const colorMode = useColorMode()
4
+ const siteConfig = useSiteConfig()
5
+
6
+ if (import.meta.server) {
7
+ // style
8
+ useHeadSafe({
9
+ bodyAttrs: {
10
+ class:
11
+ 'bg-background-bright dark:bg-background-dark text-text-dark dark:text-text-bright',
12
+ },
13
+ })
14
+
15
+ // favicon (https://vite-pwa-org.netlify.app/assets-generator/)
16
+ useHeadSafe({
17
+ link: [
18
+ {
19
+ href: `/site.webmanifest?v=${CACHE_VERSION}`,
20
+ rel: 'manifest',
21
+ },
22
+ {
23
+ href: `/favicon.ico?v=${CACHE_VERSION}`,
24
+ rel: 'icon',
25
+ sizes: '48x48',
26
+ },
27
+ {
28
+ href: `/assets/static/favicon/favicon.svg?v=${CACHE_VERSION}`,
29
+ rel: 'icon',
30
+ sizes: 'any',
31
+ type: 'image/svg+xml',
32
+ },
33
+ {
34
+ href: `/assets/static/favicon/apple-touch-icon-180x180.png?v=${CACHE_VERSION}`,
35
+ rel: 'apple-touch-icon',
36
+ },
37
+ ],
38
+ })
39
+
40
+ // i18n
41
+ useHeadSafe(useLocaleHead().value)
42
+ }
43
+
44
+ if (import.meta.client) {
45
+ // theme
46
+ const updateThemeColor = () => {
47
+ useSeoMeta({
48
+ themeColor: appConfig.vio.themeColor, // colorMode.value === 'dark' ? THEME_COLOR_DARK : THEME_COLOR,
49
+ })
50
+ }
51
+ updateThemeColor()
52
+ watch(() => colorMode.value, updateThemeColor)
53
+ }
54
+
55
+ // seo
56
+ useSeoMeta({
57
+ titleTemplate: (title) =>
58
+ TITLE_TEMPLATE({
59
+ siteName: siteConfig.name,
60
+ title,
61
+ }),
62
+ })
63
+ }
64
+
65
+ export const useHeadDefault = (input: Parameters<typeof useSeoMeta>[0]) => {
66
+ const siteConfig = useSiteConfig()
67
+
68
+ const description =
69
+ toValue(input.description) || (siteConfig.description as string)
70
+ const title = TITLE_TEMPLATE({
71
+ siteName: siteConfig.name,
72
+ title: toValue(input.title)?.toString() || undefined,
73
+ })
74
+
75
+ useSeoMeta({
76
+ ...(description
77
+ ? {
78
+ description,
79
+ ogDescription: description,
80
+ twitterDescription: description,
81
+ }
82
+ : {}),
83
+ ...(title ? { title, ogTitle: title, twitterTitle: title } : {}),
84
+ ...input,
85
+ })
86
+ }
87
+
88
+ const POLYFILLS_URL = `https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=${POLYFILLS.join(
89
+ '%2C',
90
+ )}&flags=gated`
91
+
92
+ export const usePolyfills = () => {
93
+ if (!POLYFILLS.length) return
94
+
95
+ if (import.meta.server) {
96
+ useHead({
97
+ link: [
98
+ {
99
+ rel: 'preload',
100
+ href: POLYFILLS_URL,
101
+ crossorigin: 'anonymous',
102
+ as: 'script',
103
+ 'data-testid': 'polyfill-preload',
104
+ },
105
+ ],
106
+ script: [
107
+ {
108
+ src: POLYFILLS_URL,
109
+ crossorigin: 'anonymous',
110
+ 'data-testid': 'polyfill-script',
111
+ },
112
+ ],
113
+ })
114
+ }
115
+ }
@@ -0,0 +1,30 @@
1
+ export const useGetServiceHref = () => {
2
+ const host = useHost()
3
+ const runtimeConfig = useRuntimeConfig()
4
+
5
+ return ({
6
+ isSsr = true,
7
+ name,
8
+ port,
9
+ }: {
10
+ isSsr?: boolean
11
+ name?: string
12
+ port?: number
13
+ }) =>
14
+ getServiceHref({
15
+ host,
16
+ isSsr,
17
+ name,
18
+ port,
19
+ stagingHost: runtimeConfig.public.vio.stagingHost,
20
+ })
21
+ }
22
+
23
+ export const useHost = () => {
24
+ const { ssrContext } = useNuxtApp()
25
+ const host = ssrContext ? getHost(ssrContext.event) : location.host
26
+
27
+ if (!host) throw new Error('Host is not given!')
28
+
29
+ return host
30
+ }
@@ -24,7 +24,8 @@ const errorProp = toRef(() => props.error)
24
24
  // initialization
25
25
  useAppLayout()
26
26
 
27
- useServerHeadSafe({
27
+ useHeadDefault({
28
28
  title: `${errorProp.value.statusCode} - ${errorProp.value.message}`,
29
29
  })
30
+ defineOgImageComponent('NuxtSeo', {}, {})
30
31
  </script>
@@ -0,0 +1,20 @@
1
+ <template>
2
+ <VioPageLegalNotice />
3
+ </template>
4
+
5
+ <script setup lang="ts">
6
+ const { t } = useI18n()
7
+
8
+ // data
9
+ const title = t('title')
10
+
11
+ // initialization
12
+ useHeadDefault({ title })
13
+ </script>
14
+
15
+ <i18n lang="yaml">
16
+ de:
17
+ title: Impressum
18
+ en:
19
+ title: Legal notice
20
+ </i18n>
@@ -35,23 +35,40 @@
35
35
  log: true,
36
36
  contactForm: true,
37
37
  contactExternal: true,
38
- comments: {
39
- ip: true,
40
- subscribe: true,
41
- storageDuration: true,
42
- legalBasis: true,
43
- },
44
- },
45
- newsletter: {
46
- data: true,
47
- },
48
- pluginsTools: {
49
- youTube: true,
50
- googleWebFonts: true,
51
- fontAwesome: true,
52
- googleMaps: true,
53
- googleReCaptcha: true,
38
+ // comments: {
39
+ // ip: true,
40
+ // subscribe: true,
41
+ // storageDuration: true,
42
+ // legalBasis: true,
43
+ // },
54
44
  },
45
+ // newsletter: {
46
+ // data: true,
47
+ // },
48
+ // pluginsTools: {
49
+ // youTube: true,
50
+ // googleWebFonts: true,
51
+ // fontAwesome: true,
52
+ // googleMaps: true,
53
+ // googleReCaptcha: true,
54
+ // },
55
55
  }"
56
56
  />
57
57
  </template>
58
+
59
+ <script setup lang="ts">
60
+ const { t } = useI18n()
61
+
62
+ // data
63
+ const title = t('title')
64
+
65
+ // initialization
66
+ useHeadDefault({ title })
67
+ </script>
68
+
69
+ <i18n lang="yaml">
70
+ de:
71
+ title: Datenschutzerklärung
72
+ en:
73
+ title: Privacy Policy
74
+ </i18n>
@@ -1,3 +1 @@
1
- import { I18N_VUE_CONFIG } from '../utils/constants'
2
-
3
1
  export default defineI18nConfig(() => I18N_VUE_CONFIG)
@@ -1,4 +1,5 @@
1
1
  {
2
+ "globalSeoOgImageAlt": "Social Preview Image für eine Vio Webseite.",
2
3
  "globalPlaceholderEmailAddress": "e-mail{'@'}adres.se",
3
4
  "globalPlaceholderUrl": "https://websei.te",
4
5
  "globalStatusError": "Fehler",
@@ -1,4 +1,5 @@
1
1
  {
2
+ "globalSeoOgImageAlt": "Social Preview Image for a Vio webpage.",
2
3
  "globalPlaceholderEmailAddress": "email{'@'}addre.ss",
3
4
  "globalPlaceholderUrl": "https://websi.te",
4
5
  "globalStatusError": "Error",
package/nuxt.config.ts CHANGED
@@ -3,12 +3,12 @@ import { defu } from 'defu'
3
3
 
4
4
  import {
5
5
  SITE_URL,
6
- SITE_NAME,
6
+ VIO_SITE_NAME,
7
7
  TIMEZONE_COOKIE_NAME,
8
8
  GTAG_COOKIE_ID,
9
- GET_CSP,
10
- } from './utils/constants'
11
- import { VIO_NUXT_BASE_CONFIG } from './utils/nuxt'
9
+ VIO_GET_CSP,
10
+ } from './shared/utils/constants'
11
+ import { VIO_NUXT_BASE_CONFIG } from './shared/utils/nuxt'
12
12
 
13
13
  export default defineNuxtConfig(
14
14
  defu(
@@ -18,7 +18,6 @@ export default defineNuxtConfig(
18
18
  htmlAttrs: {
19
19
  lang: 'en', // fallback data to prevent invalid html at generation
20
20
  },
21
- titleTemplate: '%s', // fully set in `composables/useAppLayout.ts`
22
21
  },
23
22
  pageTransition: {
24
23
  name: 'layout',
@@ -40,6 +39,9 @@ export default defineNuxtConfig(
40
39
  enabled: true,
41
40
  },
42
41
  },
42
+ future: {
43
+ compatibilityVersion: 4,
44
+ },
43
45
  modules: [
44
46
  '@dargmuesli/nuxt-cookie-control',
45
47
  '@nuxt/devtools',
@@ -71,7 +73,7 @@ export default defineNuxtConfig(
71
73
  "'unsafe-inline'", // nuxt-color-mode (https://github.com/nuxt-modules/color-mode/issues/266), runtimeConfig (static)
72
74
  ],
73
75
  },
74
- GET_CSP(SITE_URL),
76
+ VIO_GET_CSP(SITE_URL),
75
77
  nuxtConfigSecurityHeaders.contentSecurityPolicy,
76
78
  )
77
79
  }
@@ -120,6 +122,12 @@ export default defineNuxtConfig(
120
122
  },
121
123
  },
122
124
  vite: {
125
+ optimizeDeps: {
126
+ include: [
127
+ '@dargmuesli/nuxt-cookie-control/runtime/types',
128
+ '@vuelidate/validators',
129
+ ],
130
+ },
123
131
  plugins: [tailwindcss()],
124
132
  },
125
133
 
@@ -198,7 +206,7 @@ export default defineNuxtConfig(
198
206
  initMode: 'manual',
199
207
  },
200
208
  htmlValidator: {
201
- // failOnError: true, // TODO: enable once headers match requirements (https://github.com/unjs/unhead/issues/199#issuecomment-1815728703)
209
+ failOnError: true,
202
210
  logLevel: 'warning',
203
211
  },
204
212
  i18n: {
@@ -247,7 +255,6 @@ export default defineNuxtConfig(
247
255
  strict: true,
248
256
  },
249
257
  site: {
250
- id: 'vio',
251
258
  url: SITE_URL,
252
259
  },
253
260
  sitemap: {
@@ -309,7 +316,7 @@ export default defineNuxtConfig(
309
316
  },
310
317
  },
311
318
  VIO_NUXT_BASE_CONFIG({
312
- siteName: SITE_NAME,
319
+ siteName: VIO_SITE_NAME,
313
320
  stagingHost: 'localhost:3000',
314
321
  }),
315
322
  ),
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "dependencies": {
3
- "@dargmuesli/nuxt-cookie-control": "8.5.3",
3
+ "@dargmuesli/nuxt-cookie-control": "8.5.4",
4
4
  "@eslint/compat": "1.2.7",
5
5
  "@heroicons/vue": "2.2.0",
6
6
  "@http-util/status-i18n": "0.9.0",
7
7
  "@intlify/eslint-plugin-vue-i18n": "4.0.0",
8
- "@nuxt/devtools": "2.2.1",
9
- "@nuxt/eslint": "1.1.0",
10
- "@nuxt/image": "1.9.0",
8
+ "@nuxt/devtools": "2.3.0",
9
+ "@nuxt/eslint": "1.2.0",
10
+ "@nuxt/image": "1.10.0",
11
11
  "@nuxtjs/color-mode": "3.5.2",
12
12
  "@nuxtjs/html-validator": "2.1.0",
13
- "@nuxtjs/i18n": "9.2.1",
14
- "@nuxtjs/seo": "2.2.0",
13
+ "@nuxtjs/i18n": "9.3.2",
14
+ "@nuxtjs/seo": "3.0.1",
15
15
  "@pinia/nuxt": "0.10.1",
16
16
  "@tailwindcss/forms": "0.5.10",
17
17
  "@tailwindcss/typography": "0.5.16",
18
- "@tailwindcss/vite": "4.0.11",
18
+ "@tailwindcss/vite": "4.0.14",
19
19
  "@types/lodash-es": "4.17.12",
20
20
  "@urql/core": "5.1.1",
21
21
  "@urql/vue": "1.4.3",
@@ -23,39 +23,37 @@
23
23
  "@vuelidate/validators": "2.0.4",
24
24
  "clipboardy": "4.0.0",
25
25
  "dayjs": "2.0.0-alpha.4",
26
- "eslint": "9.21.0",
27
- "eslint-config-prettier": "10.0.2",
26
+ "eslint": "9.22.0",
27
+ "eslint-config-prettier": "10.1.1",
28
28
  "eslint-plugin-compat": "6.0.2",
29
29
  "eslint-plugin-prettier": "5.2.3",
30
30
  "eslint-plugin-yml": "1.17.0",
31
31
  "globals": "16.0.0",
32
32
  "jiti": "2.4.2",
33
- "jose": "6.0.8",
33
+ "jose": "6.0.10",
34
34
  "nuxt-gtag": "3.0.2",
35
35
  "nuxt-security": "2.2.0",
36
36
  "sweetalert2": "11.17.2",
37
37
  "vue-tsc": "2.2.8"
38
38
  },
39
39
  "devDependencies": {
40
- "@unhead/vue": "1.11.20",
41
40
  "@urql/devtools": "2.0.3",
42
41
  "@urql/exchange-graphcache": "7.2.3",
43
- "consola": "3.4.0",
42
+ "consola": "3.4.2",
44
43
  "defu": "6.1.4",
45
44
  "h3": "1.15.1",
46
45
  "lodash-es": "4.17.21",
47
- "nuxt": "3.15.4",
46
+ "nuxt": "3.16.1",
48
47
  "pinia": "3.0.1",
49
48
  "prettier": "3.5.3",
50
49
  "prettier-plugin-tailwindcss": "0.6.11",
51
50
  "serve": "14.2.4",
52
51
  "sharp": "0.33.5",
53
- "stylelint": "16.15.0",
52
+ "stylelint": "16.16.0",
54
53
  "stylelint-config-recommended-vue": "1.6.0",
55
54
  "stylelint-config-standard": "37.0.0",
56
55
  "stylelint-no-unsupported-browser-features": "8.0.4",
57
- "tailwindcss": "4.0.11",
58
- "unhead": "1.11.20",
56
+ "tailwindcss": "4.0.14",
59
57
  "vue": "3.5.13",
60
58
  "vue-router": "4.5.0"
61
59
  },
@@ -64,27 +62,17 @@
64
62
  },
65
63
  "files": [
66
64
  ".config",
67
- "assets",
68
- "components",
69
- "composables",
65
+ "app",
70
66
  "i18n",
71
- "layouts",
72
- "pages",
73
- "plugins",
74
67
  "server",
75
- "store",
76
- "types",
77
- "utils",
78
- "app.config.ts",
79
- "error.vue",
80
- "i18n.config.ts",
68
+ "shared",
81
69
  "nuxt.config.ts",
82
70
  "package.json"
83
71
  ],
84
72
  "main": "nuxt.config.ts",
85
73
  "name": "@dargmuesli/nuxt-vio",
86
74
  "peerDependencies": {
87
- "nuxt": "3.15.4",
75
+ "nuxt": "3.16.0",
88
76
  "vue": "3.5.13",
89
77
  "vue-router": "4.5.0"
90
78
  },
@@ -116,5 +104,5 @@
116
104
  "start:static": "serve .playground/.output/public --ssl-cert ./.config/certificates/ssl.crt --ssl-key ./.config/certificates/ssl.key"
117
105
  },
118
106
  "type": "module",
119
- "version": "17.0.4"
107
+ "version": "18.0.1"
120
108
  }
@@ -1,5 +1,3 @@
1
- import type { AppConfig } from '../../app.config'
2
-
3
1
  export default defineEventHandler(async (event) => {
4
2
  const config = useAppConfig() as AppConfig
5
3
 
@@ -1,6 +1,5 @@
1
1
  import { defu } from 'defu'
2
2
  import type { NuxtOptions } from 'nuxt/schema'
3
- import { GET_CSP } from '../../utils/constants'
4
3
 
5
4
  // remove invalid `'none'`s and duplicates
6
5
  export const cleanupCsp = (
@@ -36,7 +35,7 @@ export default defineNitroPlugin((nitroApp) => {
36
35
  defu(
37
36
  {
38
37
  headers: {
39
- contentSecurityPolicy: GET_CSP(siteUrl),
38
+ contentSecurityPolicy: VIO_GET_CSP(siteUrl),
40
39
  },
41
40
  },
42
41
  routeRules['/**'],
@@ -17,5 +17,14 @@ export const useGetServiceHref = () => {
17
17
  name,
18
18
  port,
19
19
  stagingHost: runtimeConfig.public.vio.stagingHost,
20
- })
20
+ }).toString()
21
+ }
22
+
23
+ export const useHost = () => {
24
+ const event = useEvent()
25
+ const host = getHost(event)
26
+
27
+ if (!host) throw new Error('Host is not given!')
28
+
29
+ return host
21
30
  }
@@ -1,5 +1,4 @@
1
1
  import type { H3Event } from 'h3'
2
- import { TESTING_COOKIE_NAME } from '../../utils/constants'
3
2
 
4
3
  export const isTestingServer = (event?: H3Event) => {
5
4
  const isTestingByRuntimeConfig = useRuntimeConfig().public.vio.isTesting
@@ -1,7 +1,5 @@
1
1
  import type { H3Event } from 'h3'
2
2
 
3
- import { TIMEZONE_COOKIE_NAME } from '../../utils/constants'
4
-
5
3
  // TODO: rename to `getTimezone` (https://github.com/nuxt/cli/issues/266)
6
4
  export const getTimezoneServer = async (event: H3Event) => {
7
5
  const timezoneBySsr = event.context.$timezone
@@ -3,8 +3,7 @@ import { consola } from 'consola'
3
3
  import { type H3Event, setCookie } from 'h3'
4
4
  import { decodeJwt } from 'jose'
5
5
 
6
- import { useVioAuthStore } from '../store/auth'
7
- import { JWT_NAME } from './constants'
6
+ import { useVioAuthStore } from '../../app/stores/auth'
8
7
 
9
8
  export const getJwtFromCookie = () => {
10
9
  const cookie = useCookie(JWT_NAME())
@@ -2,19 +2,19 @@ import { DEFAULTS } from '@dargmuesli/nuxt-cookie-control/runtime/types'
2
2
  import { helpers } from '@vuelidate/validators'
3
3
  import { defu } from 'defu'
4
4
 
5
- export const SITE_NAME = 'Vio'
5
+ export const VIO_SITE_NAME = 'Vio'
6
6
 
7
7
  export const SITE_URL =
8
8
  process.env.SITE_URL ||
9
9
  process.env.NUXT_PUBLIC_SITE_URL ||
10
10
  `https://${process.env.HOST || 'localhost'}:${process.env.PORT || '3000'}`
11
- export const CACHE_VERSION = 'bOXMwoKlJr'
11
+ export const CACHE_VERSION = 'zeMtipb6C9'
12
12
  export const COOKIE_CONTROL_CONSENT_COOKIE_NAME =
13
13
  DEFAULTS.cookieNameIsConsentGiven
14
- export const COOKIE_PREFIX = SITE_NAME.toLocaleLowerCase()
14
+ export const COOKIE_PREFIX = VIO_SITE_NAME.toLocaleLowerCase()
15
15
  export const COOKIE_SEPARATOR = '_'
16
16
  export const FETCH_RETRY_AMOUNT = 3
17
- export const GET_CSP = (siteUrl: string) =>
17
+ export const VIO_GET_CSP = (siteUrl: string) =>
18
18
  defu(
19
19
  {
20
20
  // Cloudflare
@@ -108,7 +108,7 @@ export const GET_CSP = (siteUrl: string) =>
108
108
  // nuxt
109
109
  ...(process.env.NODE_ENV === 'development'
110
110
  ? {
111
- 'frame-src': `${siteUrl}/__nuxt_devtools__/client/`, // devtools
111
+ 'frame-src': [`${siteUrl}/__nuxt_devtools__/client/`], // devtools
112
112
  }
113
113
  : {}),
114
114
  'connect-src': [
@@ -167,7 +167,7 @@ export const REGEX_UUID =
167
167
  /^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$/
168
168
  export const TESTING_COOKIE_NAME = 'vio_is-testing'
169
169
  export const TIMEZONE_COOKIE_NAME = [COOKIE_PREFIX, 'tz'].join(COOKIE_SEPARATOR)
170
- export const TIMEZONE_HEADER_KEY = `X-${SITE_NAME}-Timezone`
170
+ export const TIMEZONE_HEADER_KEY = `X-${VIO_SITE_NAME}-Timezone`
171
171
  export const TITLE_TEMPLATE = ({
172
172
  siteName,
173
173
  title,
@@ -2,8 +2,6 @@ import type { CombinedError } from '@urql/core'
2
2
  import type { H3Event } from 'h3'
3
3
  import type { Ref } from 'vue'
4
4
 
5
- import type { ApiData, BackendError } from '../types/api'
6
-
7
5
  export const getApiDataDefault = (): ApiData =>
8
6
  computed(() =>
9
7
  reactive({
@@ -63,15 +61,16 @@ export const getCombinedErrorMessages = (
63
61
  return errorMessages
64
62
  }
65
63
 
66
- export const getDomainTldPort = (host: string) => {
64
+ export const getRootHost = (host: string) => {
67
65
  const hostParts = host.split('.')
66
+ const hostPartsLast = hostParts[hostParts.length - 1]
68
67
 
69
- if (/^localhost(:[0-9]+)?$/.test(hostParts[hostParts.length - 1]))
70
- return hostParts[hostParts.length - 1]
68
+ if (hostPartsLast && /^localhost(:[0-9]+)?$/.test(hostPartsLast))
69
+ return hostPartsLast
71
70
 
72
71
  if (hostParts.length === 1) return hostParts[0]
73
72
 
74
- return `${hostParts[hostParts.length - 2]}.${hostParts[hostParts.length - 1]}`
73
+ return `${hostParts[hostParts.length - 2]}.${hostPartsLast}`
75
74
  }
76
75
 
77
76
  export const getHost = (event: H3Event) => {
@@ -106,6 +105,6 @@ export const getServiceHref = ({
106
105
  } else if (isSsr && process.server) {
107
106
  return `http://${name}${portString}`
108
107
  } else {
109
- return `https://${nameSubdomainString}${getDomainTldPort(host)}`
108
+ return `https://${nameSubdomainString}${getRootHost(host)}`
110
109
  }
111
110
  }
@@ -1,28 +0,0 @@
1
- export const useAppLayout = () => {
2
- const appConfig = useAppConfig()
3
- const siteConfig = useSiteConfig()
4
-
5
- useServerHeadSafe({
6
- ...useLocaleHead().value,
7
- bodyAttrs: {
8
- class:
9
- 'bg-background-bright dark:bg-background-dark text-text-dark dark:text-text-bright',
10
- },
11
- })
12
-
13
- // adding `Server` leads incorrect title template on hydration
14
- useSeoMeta({
15
- titleTemplate: (title) =>
16
- TITLE_TEMPLATE({
17
- siteName: siteConfig.name,
18
- title,
19
- }),
20
- })
21
-
22
- if (appConfig.vio.themeColor) {
23
- useServerSeoMeta({
24
- msapplicationTileColor: appConfig.vio.themeColor,
25
- themeColor: appConfig.vio.themeColor,
26
- })
27
- }
28
- }
@@ -1,21 +0,0 @@
1
- export const useFavicons = () => {
2
- const appConfig = useAppConfig()
3
-
4
- useServerHeadSafe({
5
- link: [
6
- {
7
- href: `/site.webmanifest?v=${CACHE_VERSION}`,
8
- rel: 'manifest',
9
- },
10
- {
11
- color: appConfig.vio.themeColor,
12
- href: `/assets/static/favicon/safari-pinned-tab.svg?v=${CACHE_VERSION}`,
13
- rel: 'mask-icon',
14
- },
15
- {
16
- href: `/favicon.ico?v=${CACHE_VERSION}`,
17
- rel: 'shortcut icon',
18
- },
19
- ],
20
- })
21
- }
@@ -1,25 +0,0 @@
1
- import type { UseSeoMetaInput } from '@unhead/vue'
2
-
3
- export const useHeadDefault = (input: UseSeoMetaInput) => {
4
- const siteConfig = useSiteConfig()
5
-
6
- const description = input.description || siteConfig.description
7
- const title = TITLE_TEMPLATE({
8
- siteName: siteConfig.name,
9
- title: input.title?.toString(),
10
- })
11
-
12
- // can't be server side or it won't update on the client
13
- useSeoMeta({
14
- ...(description
15
- ? {
16
- description,
17
- ogDescription: description,
18
- twitterDescription: description,
19
- }
20
- : {}),
21
- msapplicationConfig: `/assets/static/favicon/browserconfig.xml?v=${CACHE_VERSION}`,
22
- ...(title ? { title, ogTitle: title, twitterTitle: title } : {}),
23
- ...input,
24
- })
25
- }
@@ -1,9 +0,0 @@
1
- export const useHost = () => {
2
- const { ssrContext } = useNuxtApp()
3
-
4
- if (ssrContext) {
5
- return getHost(ssrContext.event)
6
- } else {
7
- return location.host
8
- }
9
- }
@@ -1,28 +0,0 @@
1
- import { POLYFILLS } from '../utils/constants'
2
-
3
- export const usePolyfills = () => {
4
- if (!POLYFILLS.length) return
5
-
6
- const polyfillsUrl = `https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=${POLYFILLS.join(
7
- '%2C',
8
- )}&flags=gated`
9
-
10
- useServerHead({
11
- link: [
12
- {
13
- rel: 'preload',
14
- href: polyfillsUrl,
15
- crossorigin: 'anonymous',
16
- as: 'script',
17
- 'data-testid': 'polyfill-preload',
18
- },
19
- ],
20
- script: [
21
- {
22
- src: polyfillsUrl,
23
- crossorigin: 'anonymous',
24
- 'data-testid': 'polyfill-script',
25
- },
26
- ],
27
- })
28
- }
@@ -1,3 +0,0 @@
1
- <template>
2
- <VioPageLegalNotice />
3
- </template>
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes