@dargmuesli/nuxt-vio 3.0.0-beta.2 → 3.0.0-beta.21
Sign up to get free protection for your applications and to get access to all the features.
- package/app.config.ts +32 -33
- package/assets/css/tailwind.css +24 -9
- package/components/vio/_/VioApp.vue +14 -2
- package/components/vio/_/VioError.vue +4 -1
- package/components/vio/_/VioLink.vue +7 -5
- package/components/vio/form/VioForm.vue +2 -2
- package/components/vio/form/input/VioFormInput.vue +5 -5
- package/components/vio/form/input/state/VioFormInputStateError.vue +1 -1
- package/components/vio/form/input/state/VioFormInputStateInfo.vue +1 -1
- package/components/vio/icon/IconArrowRight.vue +2 -2
- package/components/vio/icon/IconCalendar.vue +2 -2
- package/components/vio/icon/IconCheckCircle.vue +2 -2
- package/components/vio/icon/IconDownload.vue +2 -2
- package/components/vio/icon/IconExclamationCircle.vue +2 -2
- package/components/vio/icon/IconHome.vue +2 -2
- package/components/vio/icon/IconHourglass.vue +2 -2
- package/components/vio/layout/VioLayoutBreadcrumbs.vue +1 -1
- package/components/vio/layout/VioLayoutFooter.vue +3 -3
- package/components/vio/layout/VioLayoutFooterCategory.vue +1 -1
- package/components/vio/loader/indicator/VioLoaderIndicator.vue +2 -2
- package/components/vio/loader/indicator/VioLoaderIndicatorPing.vue +2 -2
- package/components/vio/page/VioPageLegalNotice.vue +11 -9
- package/components/vio/page/VioPagePrivacyPolicy.vue +20 -13
- package/composables/useAppLayout.ts +11 -17
- package/composables/useFavicons.ts +3 -31
- package/composables/useGetServiceHref.ts +2 -28
- package/composables/useHeadDefault.ts +13 -26
- package/composables/usePolyfills.ts +23 -0
- package/locales/de.json +1 -1
- package/locales/en.json +1 -1
- package/nuxt.config.ts +152 -147
- package/package.json +33 -33
- package/plugins/dayjs.ts +6 -6
- package/plugins/gtag.client.ts +4 -1
- package/server/middleware/headers.ts +1 -1
- package/server/tsconfig.json +1 -1
- package/server/utils/util.ts +2 -0
- package/store/auth.ts +32 -0
- package/tailwind.config.ts +3 -3
- package/types/api.d.ts +9 -0
- package/types/fetch.d.ts +8 -0
- package/types/modules/gql.d.ts +6 -0
- package/types/modules/graphql.d.ts +6 -0
- package/utils/constants.ts +51 -0
- package/utils/networking.ts +44 -9
- package/utils/routing.ts +4 -2
- package/LICENSE +0 -674
- package/components/vio/icon/IconLogo.vue +0 -17
- package/components/vio/layout/VioLayoutHeader.vue +0 -98
package/plugins/dayjs.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import dayjs
|
1
|
+
import dayjs from 'dayjs'
|
2
2
|
|
3
3
|
// workaround for [1]
|
4
4
|
import de from 'dayjs/locale/de'
|
@@ -10,13 +10,13 @@ import timezone from 'dayjs/plugin/timezone'
|
|
10
10
|
import utc from 'dayjs/plugin/utc'
|
11
11
|
|
12
12
|
export default defineNuxtPlugin((_nuxtApp) => {
|
13
|
-
extend(isSameOrBefore)
|
14
|
-
extend(localizedFormat)
|
15
|
-
extend(timezone)
|
16
|
-
extend(utc)
|
13
|
+
dayjs.extend(isSameOrBefore)
|
14
|
+
dayjs.extend(localizedFormat)
|
15
|
+
dayjs.extend(timezone)
|
16
|
+
dayjs.extend(utc)
|
17
17
|
|
18
18
|
// workaround for [1]
|
19
|
-
locale(de)
|
19
|
+
dayjs.locale(de)
|
20
20
|
// dayjs.locale(en) makes `format` error
|
21
21
|
|
22
22
|
return {
|
package/plugins/gtag.client.ts
CHANGED
@@ -10,7 +10,10 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|
10
10
|
{
|
11
11
|
bootstrap: !!cookieControl.cookiesEnabledIds.value?.includes('ga'),
|
12
12
|
config: {
|
13
|
-
id: config.public.googleAnalyticsId,
|
13
|
+
id: config.public.vio.googleAnalyticsId,
|
14
|
+
params: {
|
15
|
+
cookie_flags: 'secure;samesite=strict',
|
16
|
+
},
|
14
17
|
},
|
15
18
|
},
|
16
19
|
router,
|
@@ -21,7 +21,7 @@ export default defineEventHandler(async (event) => {
|
|
21
21
|
// );
|
22
22
|
// };
|
23
23
|
|
24
|
-
const setRequestHeader = (event: H3Event, name: string, value
|
24
|
+
const setRequestHeader = (event: H3Event, name: string, value?: string) => {
|
25
25
|
event.node.req.headers[name] = value
|
26
26
|
}
|
27
27
|
|
package/server/tsconfig.json
CHANGED
package/store/auth.ts
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
import { decodeJwt, JWTPayload } from 'jose'
|
2
|
+
import { defineStore } from 'pinia'
|
3
|
+
import { ref } from 'vue'
|
4
|
+
|
5
|
+
export const useVioAuthStore = defineStore('vio-auth', () => {
|
6
|
+
const jwt = ref<string>()
|
7
|
+
const jwtDecoded = ref<JWTPayload>()
|
8
|
+
const signedInUsername = ref<string>()
|
9
|
+
|
10
|
+
const jwtRemove = () => jwtSet(undefined)
|
11
|
+
|
12
|
+
const jwtSet = (jwtNew?: string) => {
|
13
|
+
const jwtDecodedNew = jwtNew !== undefined ? decodeJwt(jwtNew) : undefined
|
14
|
+
|
15
|
+
jwt.value = jwtNew
|
16
|
+
jwtDecoded.value = jwtDecodedNew
|
17
|
+
signedInUsername.value =
|
18
|
+
jwtDecodedNew?.role === 'vio_account' &&
|
19
|
+
jwtDecodedNew.exp !== undefined &&
|
20
|
+
jwtDecodedNew.exp > Math.floor(Date.now() / 1000)
|
21
|
+
? (jwtDecodedNew.username as string | undefined)
|
22
|
+
: undefined
|
23
|
+
}
|
24
|
+
|
25
|
+
return {
|
26
|
+
jwt,
|
27
|
+
jwtDecoded,
|
28
|
+
signedInUsername,
|
29
|
+
jwtRemove,
|
30
|
+
jwtSet,
|
31
|
+
}
|
32
|
+
})
|
package/tailwind.config.ts
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
import { Config } from 'tailwindcss'
|
2
|
-
import colors from 'tailwindcss/colors'
|
3
|
-
import { PluginAPI } from 'tailwindcss/types/config'
|
4
1
|
import formsPlugin from '@tailwindcss/forms'
|
5
2
|
import typographyPlugin from '@tailwindcss/typography'
|
3
|
+
import type { Config } from 'tailwindcss'
|
4
|
+
import colors from 'tailwindcss/colors'
|
5
|
+
import type { PluginAPI } from 'tailwindcss/types/config'
|
6
6
|
|
7
7
|
const heading = (theme: PluginAPI['theme']): Record<string, string> => ({
|
8
8
|
fontWeight: theme('fontWeight.bold'),
|
package/types/api.d.ts
ADDED
package/types/fetch.d.ts
ADDED
package/utils/constants.ts
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
export const SITE_NAME = 'Vio'
|
2
2
|
|
3
|
+
export const BASE_URL =
|
4
|
+
(process.env.NUXT_PUBLIC_STACK_DOMAIN ? 'https' : 'http') +
|
5
|
+
'://' +
|
6
|
+
(process.env.NUXT_PUBLIC_STACK_DOMAIN ||
|
7
|
+
`${process.env.HOST || 'localhost'}:${
|
8
|
+
!process.env.NODE_ENV || process.env.NODE_ENV === 'development'
|
9
|
+
? '3000'
|
10
|
+
: '3001'
|
11
|
+
}`)
|
12
|
+
export const CACHE_VERSION = 'bOXMwoKlJr'
|
3
13
|
export const COOKIE_PREFIX = SITE_NAME.toLocaleLowerCase()
|
4
14
|
export const COOKIE_SEPARATOR = '_'
|
5
15
|
export const FETCH_RETRY_AMOUNT = 3
|
@@ -29,3 +39,44 @@ export const I18N_VUE_CONFIG = {
|
|
29
39
|
export const TIMEZONE_COOKIE_NAME = [COOKIE_PREFIX, 'tz'].join(COOKIE_SEPARATOR)
|
30
40
|
export const TIMEZONE_HEADER_KEY = `X-${SITE_NAME}-Timezone`
|
31
41
|
export const VALIDATION_SUGGESTION_TITLE_LENGTH_MAXIMUM = 300
|
42
|
+
export const VIO_NUXT_BASE_CONFIG = ({
|
43
|
+
baseUrl,
|
44
|
+
siteName,
|
45
|
+
stagingHost,
|
46
|
+
}: {
|
47
|
+
baseUrl?: string
|
48
|
+
siteName: string
|
49
|
+
stagingHost?: string
|
50
|
+
}) =>
|
51
|
+
({
|
52
|
+
app: {
|
53
|
+
head: {
|
54
|
+
title: SITE_NAME, // fallback data to prevent invalid html at generation
|
55
|
+
},
|
56
|
+
},
|
57
|
+
runtimeConfig: {
|
58
|
+
public: {
|
59
|
+
i18n: {
|
60
|
+
...(baseUrl ? { baseUrl } : {}),
|
61
|
+
},
|
62
|
+
vio: {
|
63
|
+
...(stagingHost
|
64
|
+
? {
|
65
|
+
stagingHost:
|
66
|
+
process.env.NODE_ENV !== 'production' &&
|
67
|
+
!process.env.NUXT_PUBLIC_STACK_DOMAIN
|
68
|
+
? stagingHost
|
69
|
+
: undefined,
|
70
|
+
}
|
71
|
+
: {}),
|
72
|
+
},
|
73
|
+
},
|
74
|
+
},
|
75
|
+
|
76
|
+
// modules
|
77
|
+
i18n: I18N_MODULE_CONFIG, // `langDir`, `lazy` and `locales` must be configured to extend a layer having lazy-loaded translations (https://v8.i18n.nuxtjs.org/guide/layers#locales)
|
78
|
+
site: {
|
79
|
+
name: siteName,
|
80
|
+
...(baseUrl ? { url: baseUrl } : {}),
|
81
|
+
},
|
82
|
+
}) as Parameters<typeof defineNuxtConfig>[0]
|
package/utils/networking.ts
CHANGED
@@ -60,9 +60,6 @@ export const getCombinedErrorMessages = (
|
|
60
60
|
return errorMessages
|
61
61
|
}
|
62
62
|
|
63
|
-
export const getCspAsString = (csp = {} as Record<string, Array<string>>) =>
|
64
|
-
Object.keys(csp).reduce((p, c) => (p += `${c} ${csp[c].join(' ')};`), '')
|
65
|
-
|
66
63
|
export const getDomainTldPort = (host: string) => {
|
67
64
|
const hostParts = host.split('.')
|
68
65
|
|
@@ -80,10 +77,48 @@ export const getHost = (req: IncomingMessage) => {
|
|
80
77
|
return req.headers.host
|
81
78
|
}
|
82
79
|
|
83
|
-
export const
|
84
|
-
|
85
|
-
|
86
|
-
|
80
|
+
export const getServiceHref = ({
|
81
|
+
host,
|
82
|
+
isSsr = true,
|
83
|
+
name,
|
84
|
+
port,
|
85
|
+
stagingHost,
|
86
|
+
}: {
|
87
|
+
host: string
|
88
|
+
isSsr?: boolean
|
89
|
+
name?: string
|
90
|
+
port?: number
|
91
|
+
stagingHost?: string
|
92
|
+
}) => {
|
93
|
+
const nameSubdomain = name?.replaceAll('_', '-')
|
94
|
+
const nameSubdomainString = nameSubdomain ? `${nameSubdomain}.` : ''
|
95
|
+
const portString = port ? `:${port}` : ''
|
96
|
+
|
97
|
+
if (stagingHost) {
|
98
|
+
return `https://${nameSubdomainString}${stagingHost}`
|
99
|
+
} else if (isSsr && process.server) {
|
100
|
+
return `http://${name}${portString}`
|
101
|
+
} else {
|
102
|
+
return `https://${nameSubdomainString}${getDomainTldPort(host)}`
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
export const getTimezone = async (event: H3Event) => {
|
107
|
+
const timezoneCookie = getCookie(event, TIMEZONE_COOKIE_NAME)
|
108
|
+
|
109
|
+
if (timezoneCookie) {
|
110
|
+
return timezoneCookie
|
111
|
+
}
|
112
|
+
|
113
|
+
if (event.node.req.headers['x-real-ip']) {
|
114
|
+
const ipApiResult = await ofetch<{ timezone: string }>(
|
87
115
|
`http://ip-api.com/json/${event.node.req.headers['x-real-ip']}`,
|
88
|
-
)
|
89
|
-
|
116
|
+
).catch(() => {})
|
117
|
+
|
118
|
+
if (ipApiResult) {
|
119
|
+
return ipApiResult.timezone
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
return undefined
|
124
|
+
}
|
package/utils/routing.ts
CHANGED
@@ -1,2 +1,4 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
import { RouteLocationRaw } from '#vue-router'
|
2
|
+
|
3
|
+
export const append = (path: string, pathToAppend?: RouteLocationRaw) =>
|
4
|
+
path + (path.endsWith('/') ? '' : '/') + (pathToAppend ?? '')
|