@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.
Files changed (70) hide show
  1. package/app.config.ts +32 -33
  2. package/components/{_ → vio/_}/VioApp.vue +22 -5
  3. package/components/{_ → vio/_}/VioError.vue +1 -1
  4. package/components/{_ → vio/_}/VioLink.vue +2 -2
  5. package/components/{form → vio/form}/VioForm.vue +2 -2
  6. package/components/{form → vio/form}/input/VioFormInput.vue +2 -2
  7. package/components/{layout → vio/layout}/VioLayout.vue +1 -1
  8. package/components/{layout → vio/layout}/VioLayoutFooter.vue +1 -1
  9. package/components/{layout → vio/layout}/VioLayoutFooterCategory.vue +1 -1
  10. package/components/{layout → vio/layout}/VioLayoutHeader.vue +1 -1
  11. package/components/{loader → vio/loader}/indicator/VioLoaderIndicator.vue +2 -2
  12. package/components/{loader → vio/loader}/indicator/VioLoaderIndicatorPing.vue +2 -2
  13. package/components/{page → vio/page}/VioPageLegalNotice.vue +9 -7
  14. package/components/{page → vio/page}/VioPagePrivacyPolicy.vue +18 -11
  15. package/composables/useAppLayout.ts +11 -17
  16. package/composables/useFavicons.ts +3 -31
  17. package/composables/useGetServiceHref.ts +2 -28
  18. package/composables/useHeadDefault.ts +13 -26
  19. package/composables/usePolyfills.ts +23 -0
  20. package/error.vue +2 -0
  21. package/locales/de.json +1 -1
  22. package/locales/en.json +1 -1
  23. package/nuxt.config.ts +19 -9
  24. package/package.json +21 -22
  25. package/plugins/dayjs.ts +6 -18
  26. package/plugins/gtag.client.ts +3 -0
  27. package/server/middleware/headers.ts +1 -1
  28. package/server/tsconfig.json +1 -1
  29. package/server/utils/util.ts +2 -0
  30. package/store/auth.ts +32 -0
  31. package/tailwind.config.ts +3 -5
  32. package/types/api.d.ts +9 -0
  33. package/types/fetch.d.ts +8 -0
  34. package/types/modules/gql.d.ts +6 -0
  35. package/types/modules/graphql.d.ts +6 -0
  36. package/utils/constants.ts +1 -0
  37. package/utils/networking.ts +44 -9
  38. package/LICENSE +0 -674
  39. package/composables/useHeadLayout.ts +0 -67
  40. /package/components/{button → vio/button}/VioButton.vue +0 -0
  41. /package/components/{button → vio/button}/VioButtonColored.vue +0 -0
  42. /package/components/{card → vio/card}/VioCard.vue +0 -0
  43. /package/components/{card → vio/card}/state/VioCardState.vue +0 -0
  44. /package/components/{card → vio/card}/state/VioCardStateAlert.vue +0 -0
  45. /package/components/{form → vio/form}/VioFormCheckbox.vue +0 -0
  46. /package/components/{form → vio/form}/input/VioFormInputIconWrapper.vue +0 -0
  47. /package/components/{form → vio/form}/input/VioFormInputUrl.vue +0 -0
  48. /package/components/{form → vio/form}/input/state/VioFormInputState.vue +0 -0
  49. /package/components/{form → vio/form}/input/state/VioFormInputStateError.vue +0 -0
  50. /package/components/{form → vio/form}/input/state/VioFormInputStateInfo.vue +0 -0
  51. /package/components/{icon → vio/icon}/IconArrowRight.vue +0 -0
  52. /package/components/{icon → vio/icon}/IconCalendar.vue +0 -0
  53. /package/components/{icon → vio/icon}/IconChatOutline.vue +0 -0
  54. /package/components/{icon → vio/icon}/IconChatSolid.vue +0 -0
  55. /package/components/{icon → vio/icon}/IconCheckCircle.vue +0 -0
  56. /package/components/{icon → vio/icon}/IconContainer.vue +0 -0
  57. /package/components/{icon → vio/icon}/IconDownload.vue +0 -0
  58. /package/components/{icon → vio/icon}/IconExclamationCircle.vue +0 -0
  59. /package/components/{icon → vio/icon}/IconHome.vue +0 -0
  60. /package/components/{icon → vio/icon}/IconHourglass.vue +0 -0
  61. /package/components/{icon → vio/icon}/IconLightbulb.vue +0 -0
  62. /package/components/{icon → vio/icon}/IconLogo.vue +0 -0
  63. /package/components/{icon → vio/icon}/IconMixcloud.vue +0 -0
  64. /package/components/{icon → vio/icon}/IconMusic.vue +0 -0
  65. /package/components/{icon → vio/icon}/IconPlay.vue +0 -0
  66. /package/components/{icon → vio/icon}/IconShare.vue +0 -0
  67. /package/components/{layout → vio/layout}/VioLayoutBreadcrumbs.vue +0 -0
  68. /package/components/{layout → vio/layout}/VioLayoutHr.vue +0 -0
  69. /package/components/{layout → vio/layout}/VioLayoutSpanList.vue +0 -0
  70. /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
- sweetalert2: 'sweetalert2', // TODO: remove (https://github.com/nuxt/nuxt/issues/19426)
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
- ? 'jonas-thelemann.de'
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
- // failOnError: true,
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
- failOnError: false, // TODO: enable (https://github.com/harlan-zw/nuxt-seo-kit/issues/4#issuecomment-1434522124)
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.1",
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": "./nuxt.config.ts",
30
+ "main": "nuxt.config.ts",
29
31
  "scripts": {
30
- "dev": "nuxi dev .playground",
31
- "build": "nuxi build .playground",
32
- "generate": "nuxi generate .playground",
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": "pnpm 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": "1.11.9",
62
+ "dayjs": "2.0.0-alpha.4",
61
63
  "is-https": "4.0.0",
62
64
  "jose": "4.14.4",
63
- "marked": "7.0.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
- "typescript": "5.1.6",
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, { extend, locale } from '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
@@ -11,6 +11,9 @@ export default defineNuxtPlugin((nuxtApp) => {
11
11
  bootstrap: !!cookieControl.cookiesEnabledIds.value?.includes('ga'),
12
12
  config: {
13
13
  id: config.public.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: string) => {
24
+ const setRequestHeader = (event: H3Event, name: string, value?: string) => {
25
25
  event.node.req.headers[name] = value
26
26
  }
27
27
 
@@ -1,3 +1,3 @@
1
1
  {
2
- "extends": "../.nuxt/tsconfig.server.json"
2
+ "extends": "../.playground/.nuxt/tsconfig.server.json"
3
3
  }
@@ -0,0 +1,2 @@
1
+ export const getCspAsString = (csp = {} as Record<string, Array<string>>) =>
2
+ Object.keys(csp).reduce((p, c) => (p += `${c} ${csp[c].join(' ')};`), '')
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
+ })
@@ -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
@@ -0,0 +1,9 @@
1
+ import type { CombinedError } from '@urql/core'
2
+
3
+ export type ApiData = ComputedRef<{
4
+ data?: Object
5
+ errors: BackendError[]
6
+ isFetching: boolean
7
+ }>
8
+
9
+ export type BackendError = CombinedError | { errcode: string; message: string }
@@ -0,0 +1,8 @@
1
+ export interface StrapiResult<T> {
2
+ data: CollectionItem<T>[]
3
+ meta: {
4
+ pagination: {
5
+ total: number
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,6 @@
1
+ declare module '*.gql' {
2
+ import { DocumentNode } from 'graphql'
3
+
4
+ const content: DocumentNode
5
+ export default content
6
+ }
@@ -0,0 +1,6 @@
1
+ declare module '*.graphql' {
2
+ import { DocumentNode } from 'graphql'
3
+
4
+ const content: DocumentNode
5
+ export default content
6
+ }
@@ -1,5 +1,6 @@
1
1
  export const SITE_NAME = 'Vio'
2
2
 
3
+ export const CACHE_VERSION = 'bOXMwoKlJr'
3
4
  export const COOKIE_PREFIX = SITE_NAME.toLocaleLowerCase()
4
5
  export const COOKIE_SEPARATOR = '_'
5
6
  export const FETCH_RETRY_AMOUNT = 3
@@ -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 getTimezone = async (event: H3Event) =>
84
- getCookie(event, TIMEZONE_COOKIE_NAME) ||
85
- (
86
- await ofetch(
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
- ).timezone
116
+ ).catch(() => {})
117
+
118
+ if (ipApiResult) {
119
+ return ipApiResult.timezone
120
+ }
121
+ }
122
+
123
+ return undefined
124
+ }