@dargmuesli/nuxt-vio 3.0.0-beta.1 → 3.0.0-beta.11
Sign up to get free protection for your applications and to get access to all the features.
- package/app.config.ts +32 -33
- package/components/{_ → vio/_}/VioApp.vue +22 -5
- package/components/{_ → vio/_}/VioError.vue +1 -1
- package/components/{_ → vio/_}/VioLink.vue +2 -2
- package/components/{form → vio/form}/VioForm.vue +2 -2
- package/components/{form → vio/form}/input/VioFormInput.vue +2 -2
- package/components/{layout → vio/layout}/VioLayout.vue +1 -1
- package/components/{layout → vio/layout}/VioLayoutFooter.vue +1 -1
- package/components/{layout → vio/layout}/VioLayoutFooterCategory.vue +1 -1
- package/components/{layout → vio/layout}/VioLayoutHeader.vue +1 -1
- package/components/{loader → vio/loader}/indicator/VioLoaderIndicator.vue +2 -2
- package/components/{loader → vio/loader}/indicator/VioLoaderIndicatorPing.vue +2 -2
- package/components/{page → vio/page}/VioPageLegalNotice.vue +9 -7
- package/components/{page → vio/page}/VioPagePrivacyPolicy.vue +18 -11
- 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/error.vue +2 -0
- package/locales/de.json +1 -1
- package/locales/en.json +1 -1
- package/nuxt.config.ts +19 -9
- package/package.json +21 -22
- package/plugins/dayjs.ts +6 -18
- package/plugins/gtag.client.ts +3 -0
- 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 -5
- 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 +1 -0
- package/utils/networking.ts +44 -9
- package/LICENSE +0 -674
- package/composables/useHeadLayout.ts +0 -67
- /package/components/{button → vio/button}/VioButton.vue +0 -0
- /package/components/{button → vio/button}/VioButtonColored.vue +0 -0
- /package/components/{card → vio/card}/VioCard.vue +0 -0
- /package/components/{card → vio/card}/state/VioCardState.vue +0 -0
- /package/components/{card → vio/card}/state/VioCardStateAlert.vue +0 -0
- /package/components/{form → vio/form}/VioFormCheckbox.vue +0 -0
- /package/components/{form → vio/form}/input/VioFormInputIconWrapper.vue +0 -0
- /package/components/{form → vio/form}/input/VioFormInputUrl.vue +0 -0
- /package/components/{form → vio/form}/input/state/VioFormInputState.vue +0 -0
- /package/components/{form → vio/form}/input/state/VioFormInputStateError.vue +0 -0
- /package/components/{form → vio/form}/input/state/VioFormInputStateInfo.vue +0 -0
- /package/components/{icon → vio/icon}/IconArrowRight.vue +0 -0
- /package/components/{icon → vio/icon}/IconCalendar.vue +0 -0
- /package/components/{icon → vio/icon}/IconChatOutline.vue +0 -0
- /package/components/{icon → vio/icon}/IconChatSolid.vue +0 -0
- /package/components/{icon → vio/icon}/IconCheckCircle.vue +0 -0
- /package/components/{icon → vio/icon}/IconContainer.vue +0 -0
- /package/components/{icon → vio/icon}/IconDownload.vue +0 -0
- /package/components/{icon → vio/icon}/IconExclamationCircle.vue +0 -0
- /package/components/{icon → vio/icon}/IconHome.vue +0 -0
- /package/components/{icon → vio/icon}/IconHourglass.vue +0 -0
- /package/components/{icon → vio/icon}/IconLightbulb.vue +0 -0
- /package/components/{icon → vio/icon}/IconLogo.vue +0 -0
- /package/components/{icon → vio/icon}/IconMixcloud.vue +0 -0
- /package/components/{icon → vio/icon}/IconMusic.vue +0 -0
- /package/components/{icon → vio/icon}/IconPlay.vue +0 -0
- /package/components/{icon → vio/icon}/IconShare.vue +0 -0
- /package/components/{layout → vio/layout}/VioLayoutBreadcrumbs.vue +0 -0
- /package/components/{layout → vio/layout}/VioLayoutHr.vue +0 -0
- /package/components/{layout → vio/layout}/VioLayoutSpanList.vue +0 -0
- /package/components/{loader → vio/loader}/indicator/VioLoaderIndicatorSpinner.vue +0 -0
package/nuxt.config.ts
CHANGED
@@ -11,7 +11,8 @@ import {
|
|
11
11
|
const currentDir = dirname(fileURLToPath(import.meta.url))
|
12
12
|
|
13
13
|
const BASE_URL =
|
14
|
-
'https
|
14
|
+
(process.env.NUXT_PUBLIC_STACK_DOMAIN ? 'https' : 'http') +
|
15
|
+
'://' +
|
15
16
|
(process.env.NUXT_PUBLIC_STACK_DOMAIN ||
|
16
17
|
`${process.env.HOST || 'localhost'}:${
|
17
18
|
!process.env.NODE_ENV || process.env.NODE_ENV === 'development'
|
@@ -22,22 +23,30 @@ const BASE_URL =
|
|
22
23
|
// https://v3.nuxtjs.org/api/configuration/nuxt.config
|
23
24
|
export default defineNuxtConfig({
|
24
25
|
alias: {
|
25
|
-
|
26
|
-
|
26
|
+
dayjs: 'dayjs',
|
27
|
+
sweetalert2: 'sweetalert2',
|
28
|
+
}, // TODO: remove (https://github.com/nuxt/nuxt/issues/19426)
|
27
29
|
app: {
|
28
30
|
head: {
|
29
31
|
htmlAttrs: {
|
30
32
|
lang: 'en', // fallback data to prevent invalid html at generation
|
31
33
|
},
|
32
|
-
titleTemplate: `%s`,
|
33
34
|
title: SITE_NAME, // fallback data to prevent invalid html at generation
|
35
|
+
titleTemplate: '%s', // fully set in `composables/useAppLayout.ts`
|
34
36
|
},
|
35
37
|
pageTransition: {
|
36
38
|
name: 'layout',
|
37
39
|
},
|
38
40
|
},
|
41
|
+
devtools: {
|
42
|
+
enabled: process.env.NODE_ENV !== 'production',
|
43
|
+
timeline: {
|
44
|
+
enabled: true,
|
45
|
+
},
|
46
|
+
},
|
39
47
|
modules: [
|
40
48
|
'@dargmuesli/nuxt-cookie-control',
|
49
|
+
'@nuxt/image',
|
41
50
|
'@nuxtjs/color-mode',
|
42
51
|
'@nuxtjs/html-validator',
|
43
52
|
'@nuxtjs/i18n',
|
@@ -59,13 +68,12 @@ export default defineNuxtConfig({
|
|
59
68
|
stagingHost:
|
60
69
|
process.env.NODE_ENV !== 'production' &&
|
61
70
|
!process.env.NUXT_PUBLIC_STACK_DOMAIN
|
62
|
-
? '
|
71
|
+
? 'localhost:3000'
|
63
72
|
: undefined,
|
64
73
|
},
|
65
74
|
},
|
66
75
|
typescript: {
|
67
76
|
shim: false,
|
68
|
-
strict: true,
|
69
77
|
// tsConfig: {
|
70
78
|
// compilerOptions: {
|
71
79
|
// esModuleInterop: true,
|
@@ -136,7 +144,7 @@ export default defineNuxtConfig({
|
|
136
144
|
locales: ['en', 'de'],
|
137
145
|
},
|
138
146
|
htmlValidator: {
|
139
|
-
//
|
147
|
+
failOnError: false, // TODO: fix invalid html in nuxt html template (https://github.com/nuxt/nuxt/issues/22526)
|
140
148
|
logLevel: 'warning',
|
141
149
|
},
|
142
150
|
i18n: {
|
@@ -148,7 +156,8 @@ export default defineNuxtConfig({
|
|
148
156
|
},
|
149
157
|
},
|
150
158
|
linkChecker: {
|
151
|
-
|
159
|
+
debug: process.env.NODE_ENV === 'development',
|
160
|
+
failOnError: true,
|
152
161
|
},
|
153
162
|
seoKit: {
|
154
163
|
splash: false,
|
@@ -156,10 +165,11 @@ export default defineNuxtConfig({
|
|
156
165
|
site: {
|
157
166
|
debug: process.env.NODE_ENV === 'development',
|
158
167
|
name: SITE_NAME,
|
168
|
+
titleSeparator: '·',
|
159
169
|
url: BASE_URL,
|
160
170
|
},
|
161
171
|
sitemap: {
|
162
|
-
exclude: ['/api/**'],
|
172
|
+
exclude: ['/api/pages/**'],
|
163
173
|
},
|
164
174
|
tailwindcss: {
|
165
175
|
cssPath: join(currentDir, './assets/css/tailwind.css'),
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@dargmuesli/nuxt-vio",
|
3
|
-
"version": "3.0.0-beta.
|
3
|
+
"version": "3.0.0-beta.11",
|
4
4
|
"type": "module",
|
5
5
|
"publishConfig": {
|
6
6
|
"access": "public"
|
@@ -15,9 +15,11 @@
|
|
15
15
|
"composables",
|
16
16
|
"layouts",
|
17
17
|
"locales",
|
18
|
-
"server",
|
19
18
|
"pages",
|
20
19
|
"plugins",
|
20
|
+
"server",
|
21
|
+
"store",
|
22
|
+
"types",
|
21
23
|
"utils",
|
22
24
|
"app.config.ts",
|
23
25
|
"error.vue",
|
@@ -25,50 +27,49 @@
|
|
25
27
|
"nuxt.config.ts",
|
26
28
|
"tailwind.config.ts"
|
27
29
|
],
|
28
|
-
"main": "
|
30
|
+
"main": "nuxt.config.ts",
|
29
31
|
"scripts": {
|
30
|
-
"
|
31
|
-
"
|
32
|
-
"generate": "
|
33
|
-
"preview": "nuxi preview .playground",
|
34
|
-
"prepare": "pnpm husky install && pnpm nuxt prepare .playground",
|
35
|
-
"lint": "pnpm lint:js && pnpm lint:ts && pnpm lint:style",
|
32
|
+
"build": "nuxt build .playground",
|
33
|
+
"dev": "nuxt dev .playground",
|
34
|
+
"generate": "nuxt generate .playground",
|
36
35
|
"lint:fix": "pnpm lint:js --fix && pnpm lint:ts --fix && pnpm lint:style --fix",
|
37
36
|
"lint:js": "eslint --cache --ext .js,.ts,.vue --ignore-path .gitignore .",
|
38
|
-
"lint:staged": "
|
37
|
+
"lint:staged": "lint-staged",
|
39
38
|
"lint:style": "stylelint **/*.{vue,css} --ignore-path .gitignore",
|
40
|
-
"lint:ts": "nuxt typecheck"
|
39
|
+
"lint:ts": "nuxt typecheck",
|
40
|
+
"lint": "pnpm lint:js && pnpm lint:ts && pnpm lint:style",
|
41
|
+
"prepare": "nuxt prepare .playground",
|
42
|
+
"preview": "nuxt preview .playground"
|
41
43
|
},
|
42
44
|
"dependencies": {
|
43
45
|
"@dargmuesli/nuxt-cookie-control": "6.1.5",
|
44
|
-
"@dargmuesli/nuxt-vio": "link:",
|
45
46
|
"@http-util/status-i18n": "0.7.0",
|
47
|
+
"@nuxt/image": "1.0.0-rc.1",
|
46
48
|
"@nuxtjs/color-mode": "3.3.0",
|
47
49
|
"@nuxtjs/html-validator": "1.5.2",
|
48
50
|
"@nuxtjs/i18n": "8.0.0-rc.2",
|
49
51
|
"@nuxtjs/tailwindcss": "6.8.0",
|
50
52
|
"@pinia/nuxt": "0.4.11",
|
51
53
|
"@tailwindcss/forms": "0.5.4",
|
52
|
-
"@tailwindcss/line-clamp": "0.4.4",
|
53
54
|
"@tailwindcss/typography": "0.5.9",
|
54
55
|
"@urql/core": "4.1.1",
|
55
56
|
"@urql/devtools": "2.0.3",
|
56
57
|
"@urql/exchange-graphcache": "6.3.1",
|
57
58
|
"@urql/vue": "1.1.2",
|
58
59
|
"@vuelidate/core": "2.0.3",
|
60
|
+
"@vuelidate/validators": "2.0.3",
|
59
61
|
"clipboard": "2.0.11",
|
60
|
-
"dayjs": "
|
62
|
+
"dayjs": "2.0.0-alpha.4",
|
61
63
|
"is-https": "4.0.0",
|
62
64
|
"jose": "4.14.4",
|
63
|
-
"marked": "7.0.
|
65
|
+
"marked": "7.0.1",
|
64
66
|
"nuxt-seo-kit-module": "2.0.0-beta.9",
|
65
67
|
"pinia": "2.1.6",
|
66
68
|
"sweetalert2": "11.7.20",
|
67
|
-
"vue-gtag": "2.0.1"
|
69
|
+
"vue-gtag": "2.0.1",
|
70
|
+
"vue-tsc": "1.8.8"
|
68
71
|
},
|
69
72
|
"devDependencies": {
|
70
|
-
"@commitlint/cli": "17.6.7",
|
71
|
-
"@commitlint/config-conventional": "17.6.7",
|
72
73
|
"@intlify/eslint-plugin-vue-i18n": "3.0.0-next.3",
|
73
74
|
"@nuxtjs/eslint-config-typescript": "12.0.0",
|
74
75
|
"@types/marked": "5.0.1",
|
@@ -78,17 +79,15 @@
|
|
78
79
|
"eslint-plugin-nuxt": "4.0.0",
|
79
80
|
"eslint-plugin-prettier": "5.0.0",
|
80
81
|
"eslint-plugin-yml": "1.8.0",
|
81
|
-
"husky": "8.0.3",
|
82
82
|
"lint-staged": "13.2.3",
|
83
83
|
"nuxt": "3.6.5",
|
84
84
|
"prettier": "3.0.1",
|
85
|
+
"prettier-plugin-tailwindcss": "0.5.3",
|
85
86
|
"stylelint": "15.10.2",
|
86
87
|
"stylelint-config-recommended-vue": "1.5.0",
|
87
88
|
"stylelint-config-standard": "34.0.0",
|
88
89
|
"stylelint-no-unsupported-browser-features": "7.0.0",
|
89
90
|
"tailwindcss": "3.3.3",
|
90
|
-
"
|
91
|
-
"vue": "3.3.4",
|
92
|
-
"vue-tsc": "1.8.8"
|
91
|
+
"vue": "3.3.4"
|
93
92
|
}
|
94
93
|
}
|
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 {
|
@@ -26,18 +26,6 @@ export default defineNuxtPlugin((_nuxtApp) => {
|
|
26
26
|
}
|
27
27
|
})
|
28
28
|
|
29
|
-
// declare module '#app' {
|
30
|
-
// interface NuxtApp {
|
31
|
-
// $dayjs: DayjsFn
|
32
|
-
// }
|
33
|
-
// }
|
34
|
-
|
35
|
-
// declare module 'nuxt/dist/app/nuxt' {
|
36
|
-
// interface NuxtApp {
|
37
|
-
// $dayjs: DayjsFn
|
38
|
-
// }
|
39
|
-
// }
|
40
|
-
|
41
29
|
/*
|
42
30
|
[1]
|
43
31
|
https://github.com/nuxt/framework/issues/7534#issuecomment-1248596609
|
package/plugins/gtag.client.ts
CHANGED
@@ -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,9 +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
|
-
import lineClampPlugin from '@tailwindcss/line-clamp'
|
6
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'
|
7
6
|
|
8
7
|
const heading = (theme: PluginAPI['theme']): Record<string, string> => ({
|
9
8
|
fontWeight: theme('fontWeight.bold'),
|
@@ -54,7 +53,6 @@ export default {
|
|
54
53
|
darkMode: 'class',
|
55
54
|
plugins: [
|
56
55
|
formsPlugin,
|
57
|
-
lineClampPlugin,
|
58
56
|
typographyPlugin,
|
59
57
|
({ addBase, addComponents, addUtilities, theme }: PluginAPI) => {
|
60
58
|
addBase({
|
package/types/api.d.ts
ADDED
package/types/fetch.d.ts
ADDED
package/utils/constants.ts
CHANGED
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
|
+
}
|