@dargmuesli/nuxt-vio 8.2.4 → 8.3.3

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.
package/app.config.ts CHANGED
@@ -6,27 +6,11 @@ export default defineAppConfig({
6
6
  headers: {
7
7
  csp: {
8
8
  default: {
9
- 'Cross-Origin-Opener-Policy': 'same-origin',
10
- // 'Cross-Origin-Embedder-Policy', 'require-corp') // https://stackoverflow.com/questions/71904052/getting-notsameoriginafterdefaultedtosameoriginbycoep-error-with-helmet
11
- 'Cross-Origin-Resource-Policy': 'same-origin',
12
- // 'Expect-CT', 'max-age=0') // deprecated (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expect-CT)
13
9
  NEL: '\'{"report_to":"default","max_age":31536000,"include_subdomains":true}\'',
14
- 'Origin-Agent-Cluster': '?1',
15
- 'Permissions-Policy': '',
16
- 'Referrer-Policy': 'no-referrer',
17
10
  'Report-To':
18
11
  '\'{"group":"default":"max_age":31536000:"endpoints":[{"url":"https://dargmuesli.report-uri.com/a/d/g"}]:"include_subdomains":true}\'',
19
- 'X-Content-Type-Options': 'nosniff',
20
- 'X-DNS-Prefetch-Control': 'off',
21
- 'X-Download-Options': 'noopen',
22
- 'X-Frame-Options': 'SAMEORIGIN',
23
- 'X-Permitted-Cross-Domain-Policies': 'none',
24
- 'X-XSS-Protection': '1; mode=block', // TODO: set back to `0` once CSP does not use `unsafe-*` anymore (https://github.com/maevsi/maevsi/issues/1047)
25
- },
26
- production: {
27
- 'Strict-Transport-Security':
28
- 'max-age=31536000; includeSubDomains; preload',
29
12
  },
13
+ production: {} as Record<string, string>,
30
14
  },
31
15
  },
32
16
  },
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div>
3
- <h1>{{ `${statusCode ? `${statusCode} - ` : ''}${statusReason}` }}</h1>
3
+ <h1>{{ title }}</h1>
4
4
  <div>
5
5
  {{ description }}
6
6
  </div>
@@ -29,9 +29,14 @@ const props = withDefaults(defineProps<Props>(), {
29
29
  const runtimeConfig = useRuntimeConfig()
30
30
  const { locale, t } = useI18n()
31
31
 
32
- // computations
33
- const statusReason = computed(() => {
34
- return status(props.statusCode, locale.value) || t('error')
32
+ // data
33
+ const title = `${props.statusCode ? `${props.statusCode} - ` : ''}${
34
+ status(props.statusCode, locale.value) || t('error')
35
+ }`
36
+
37
+ // initialization
38
+ useHeadDefault({
39
+ title,
35
40
  })
36
41
  </script>
37
42
 
@@ -25,7 +25,7 @@
25
25
  </template>
26
26
 
27
27
  <script setup lang="ts">
28
- import { NuxtLinkProps } from '#app'
28
+ import type { NuxtLinkProps } from '#app'
29
29
 
30
30
  interface Props {
31
31
  ariaLabel?: string
@@ -14,9 +14,9 @@
14
14
  </template>
15
15
 
16
16
  <script setup lang="ts">
17
- import { UnwrapRef } from 'vue'
17
+ import type { UnwrapRef } from 'vue'
18
18
 
19
- import { ApiData } from '@dargmuesli/nuxt-vio/types/api'
19
+ import type { ApiData } from '@dargmuesli/nuxt-vio/types/api'
20
20
 
21
21
  interface Props {
22
22
  api: UnwrapRef<ApiData>
@@ -1,4 +1,4 @@
1
- import { Dayjs } from 'dayjs'
1
+ import type { Dayjs } from 'dayjs'
2
2
 
3
3
  export const useDateTime = () => {
4
4
  const { $dayjs, ssrContext } = useNuxtApp()
@@ -1,6 +1,6 @@
1
1
  import { consola } from 'consola'
2
2
  import Swal from 'sweetalert2'
3
- import { Ref } from 'vue'
3
+ import type { Ref } from 'vue'
4
4
 
5
5
  export const useFireError = () => {
6
6
  const { t } = useI18n()
package/error.vue CHANGED
@@ -10,7 +10,7 @@
10
10
  </template>
11
11
 
12
12
  <script setup lang="ts">
13
- import { NuxtError } from 'nuxt/app'
13
+ import type { NuxtError } from 'nuxt/app'
14
14
 
15
15
  interface Props {
16
16
  error: NuxtError
package/nuxt.config.ts CHANGED
@@ -43,6 +43,7 @@ export default defineNuxtConfig(
43
43
  },
44
44
  modules: [
45
45
  '@dargmuesli/nuxt-cookie-control',
46
+ '@nuxt/devtools',
46
47
  '@nuxt/image',
47
48
  '@nuxtjs/color-mode',
48
49
  '@nuxtjs/html-validator',
@@ -50,6 +51,7 @@ export default defineNuxtConfig(
50
51
  '@nuxtjs/tailwindcss',
51
52
  '@nuxtseo/module',
52
53
  '@pinia/nuxt',
54
+ 'nuxt-security',
53
55
  ],
54
56
  nitro: {
55
57
  compressPublicAssets: true,
@@ -136,6 +138,118 @@ export default defineNuxtConfig(
136
138
  linkChecker: {
137
139
  failOnError: true,
138
140
  },
141
+ robots: {
142
+ credits: false,
143
+ },
144
+ security: {
145
+ headers: {
146
+ contentSecurityPolicy: defu(
147
+ {
148
+ // Google Analytics 4 (https://developers.google.com/tag-platform/tag-manager/web/csp)
149
+ 'connect-src': [
150
+ 'https://*.analytics.google.com',
151
+ 'https://*.google-analytics.com',
152
+ 'https://*.googletagmanager.com',
153
+ ],
154
+ 'img-src': [
155
+ 'https://*.google-analytics.com',
156
+ 'https://*.googletagmanager.com',
157
+ ],
158
+ 'script-src-elem': ['https://*.googletagmanager.com'],
159
+ },
160
+ {
161
+ // vio
162
+ 'manifest-src': [`${SITE_URL}/site.webmanifest`],
163
+ 'script-src-elem': [
164
+ 'https://polyfill.io/v3/polyfill.min.js', // ESLint plugin compat
165
+ ],
166
+ },
167
+ {
168
+ // @nuxt/devtools
169
+ 'frame-src': [
170
+ ...(process.env.NODE_ENV === 'development'
171
+ ? ['http://localhost:3000/__nuxt_devtools__/client/']
172
+ : []),
173
+ ],
174
+ },
175
+ {
176
+ // nuxt-link-checker
177
+ 'connect-src': [
178
+ ...(process.env.NODE_ENV === 'development'
179
+ ? ['http://localhost:3000/api/__link_checker__/inspect']
180
+ : []),
181
+ ],
182
+ },
183
+ {
184
+ // nuxt-simple-sitemap
185
+ 'script-src-elem': [`${SITE_URL}/__sitemap__/style.xsl`],
186
+ },
187
+ {
188
+ // nuxt
189
+ 'connect-src': [
190
+ ...(process.env.NODE_ENV === 'development'
191
+ ? [
192
+ 'http://localhost:3000/_nuxt/', // Nuxt development
193
+ 'https://localhost:3000/_nuxt/', // Nuxt development
194
+ 'ws://localhost:3000/_nuxt/', // Nuxt development
195
+ 'wss://localhost:3000/_nuxt/', // Nuxt development
196
+ ]
197
+ : ["'self'"]), // Nuxt build metadata and payloads
198
+ ],
199
+ 'img-src': [
200
+ "'self'", // TODO: replace with `"'nonce-{{nonce}}'",`
201
+ 'data:', // external link icon
202
+ ],
203
+ 'script-src-elem': ["'nonce-{{nonce}}'"],
204
+ 'style-src': [
205
+ // TODO: replace with `style-src-elem` once Webkit supports it
206
+ "'self'", // TODO: replace with `"'nonce-{{nonce}}'",` (https://github.com/vitejs/vite/pull/11864)
207
+ "'unsafe-inline'", // TODO: replace with `"'nonce-{{nonce}}'",` (https://github.com/vitejs/vite/pull/11864)
208
+ ],
209
+ },
210
+ {
211
+ // base
212
+ 'base-uri': ["'none'"], // does not fallback to `default-src`
213
+ 'child-src': [],
214
+ 'connect-src': [],
215
+ 'default-src': ["'none'"],
216
+ 'font-src': [],
217
+ 'form-action': ["'none'"], // does not fallback to `default-src`
218
+ 'frame-ancestors': ["'none'"], // does not fallback to `default-src`
219
+ 'frame-src': [],
220
+ 'img-src': [],
221
+ 'media-src': [],
222
+ 'navigate-to': [],
223
+ 'object-src': [],
224
+ 'prefetch-src': [],
225
+ 'report-to': [],
226
+ 'report-uri': [],
227
+ sandbox: [],
228
+ 'script-src': [],
229
+ 'script-src-attr': [],
230
+ 'script-src-elem': [],
231
+ 'style-src': [],
232
+ 'style-src-attr': [],
233
+ 'style-src-elem': [],
234
+ 'upgrade-insecure-requests': false, // TODO: set to `process.env.NODE_ENV === 'production'` or `true` when tests run on https
235
+ 'worker-src': [],
236
+ },
237
+ ),
238
+ crossOriginEmbedderPolicy: false, // https://stackoverflow.com/questions/71904052/getting-notsameoriginafterdefaultedtosameoriginbycoep-error-with-helmet
239
+ strictTransportSecurity:
240
+ process.env.NODE_ENV === 'production'
241
+ ? {
242
+ maxAge: 31536000,
243
+ includeSubdomains: true,
244
+ preload: true,
245
+ }
246
+ : false,
247
+ xXSSProtection: '1; mode=block', // TODO: set back to `0` once CSP does not use `unsafe-*` anymore (https://github.com/maevsi/maevsi/issues/1047)
248
+ },
249
+ nonce: {
250
+ enabled: true,
251
+ },
252
+ },
139
253
  seo: {
140
254
  splash: false,
141
255
  },
@@ -145,6 +259,7 @@ export default defineNuxtConfig(
145
259
  url: SITE_URL,
146
260
  },
147
261
  sitemap: {
262
+ credits: false,
148
263
  exclude: I18N_MODULE_CONFIG.locales.map(
149
264
  (locale) =>
150
265
  `/${locale.code !== 'en' ? `${locale.code}/` : ''}api/pages/**`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dargmuesli/nuxt-vio",
3
- "version": "8.2.4",
3
+ "version": "8.3.3",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/dargmuesli/vio.git"
@@ -37,6 +37,7 @@
37
37
  "build": "pnpm run build:node",
38
38
  "build:node": "nuxt build .playground",
39
39
  "build:static": "nuxt generate .playground",
40
+ "build:static:test": "cross-env NODE_ENV=production SITE_URL=http://localhost:3002 pnpm run build:static",
40
41
  "dev": "pnpm run start:dev",
41
42
  "generate": "pnpm run build:static",
42
43
  "lint:fix": "pnpm run lint:js --fix && pnpm run lint:ts --fix && pnpm run lint:style --fix",
@@ -50,6 +51,7 @@
50
51
  "start:dev": "nuxt dev .playground",
51
52
  "start:node": "node .playground/.output/server/index.mjs",
52
53
  "start:static": "serve .playground/.output/public",
54
+ "start:static:test": "cross-env NODE_ENV=production PORT=3002 SITE_URL=http://localhost:3002 pnpm run start:static",
53
55
  "test:e2e:docker:br": "pnpm run test:e2e:docker:build && pnpm run test:e2e:docker:run",
54
56
  "test:e2e:docker:build": "docker build -t test-e2e_base --build-arg UID=$(id -u) --build-arg GID=$(id -g) --target test-e2e_base ..",
55
57
  "test:e2e:docker:run": "docker run --rm -v \"$PWD/..:/srv/app\" -v \"$(pnpm store path):/srv/.pnpm-store\" test-e2e_base",
@@ -66,57 +68,66 @@
66
68
  },
67
69
  "dependencies": {
68
70
  "@axe-core/playwright": "4.8.1",
69
- "@dargmuesli/nuxt-cookie-control": "7.0.0-beta.1",
71
+ "@dargmuesli/nuxt-cookie-control": "7.0.1",
70
72
  "@heroicons/vue": "2.0.18",
71
73
  "@http-util/status-i18n": "0.8.1",
72
74
  "@intlify/eslint-plugin-vue-i18n": "3.0.0-next.4",
73
- "@nuxt/image": "1.0.0-rc.3",
75
+ "@nuxt/devtools": "1.0.0",
76
+ "@nuxt/image": "1.0.0",
74
77
  "@nuxtjs/color-mode": "3.3.0",
75
78
  "@nuxtjs/eslint-config-typescript": "12.1.0",
76
79
  "@nuxtjs/html-validator": "1.5.2",
77
- "@nuxtjs/i18n": "8.0.0-rc.5",
80
+ "@nuxtjs/i18n": "npm:@nuxtjs/i18n-edge@8.0.0-rc.5-28296269.d5d5540",
78
81
  "@nuxtjs/tailwindcss": "6.8.0",
79
- "@nuxtseo/module": "2.0.0-beta.37",
82
+ "@nuxtseo/module": "2.0.0-beta.39",
80
83
  "@pinia/nuxt": "0.5.1",
81
84
  "@playwright/test": "1.39.0",
82
85
  "@tailwindcss/forms": "0.5.6",
83
86
  "@tailwindcss/typography": "0.5.10",
84
- "@types/cookie": "0.5.2",
85
- "@types/lodash-es": "4.17.9",
86
- "@urql/core": "4.1.3",
87
+ "@types/lodash-es": "4.17.10",
88
+ "@unhead/vue": "1.7.4",
89
+ "@urql/core": "4.1.4",
87
90
  "@urql/devtools": "2.0.3",
88
91
  "@urql/exchange-graphcache": "6.3.3",
89
92
  "@urql/vue": "1.1.2",
90
93
  "@vuelidate/core": "2.0.3",
91
94
  "@vuelidate/validators": "2.0.4",
92
95
  "clipboard": "2.0.11",
93
- "cookie": "0.5.0",
96
+ "consola": "3.2.3",
97
+ "cookie-es": "1.0.0",
94
98
  "cross-env": "7.0.3",
95
99
  "dayjs": "2.0.0-alpha.4",
96
- "eslint": "8.51.0",
100
+ "defu": "6.1.2",
101
+ "eslint": "8.52.0",
97
102
  "eslint-config-prettier": "9.0.0",
98
103
  "eslint-plugin-compat": "4.2.0",
99
104
  "eslint-plugin-nuxt": "4.0.0",
100
105
  "eslint-plugin-prettier": "5.0.1",
101
106
  "eslint-plugin-yml": "1.10.0",
107
+ "h3": "1.8.2",
102
108
  "is-https": "4.0.0",
103
109
  "jiti": "1.20.0",
104
110
  "jose": "4.15.4",
105
- "lint-staged": "15.0.1",
111
+ "lint-staged": "15.0.2",
106
112
  "lodash-es": "4.17.21",
107
- "nuxt": "3.7.4",
113
+ "nuxt": "3.8.0",
114
+ "nuxt-security": "1.0.0-rc.2",
115
+ "ofetch": "1.3.3",
108
116
  "pinia": "2.1.7",
109
117
  "prettier": "3.0.3",
110
118
  "prettier-plugin-tailwindcss": "0.5.6",
111
119
  "serve": "14.2.1",
112
- "stylelint": "15.10.3",
120
+ "stylelint": "15.11.0",
113
121
  "stylelint-config-recommended-vue": "1.5.0",
114
122
  "stylelint-config-standard": "34.0.0",
115
123
  "stylelint-no-unsupported-browser-features": "7.0.0",
116
124
  "sweetalert2": "11.7.32",
117
125
  "tailwindcss": "3.3.3",
118
- "vue": "3.3.4",
126
+ "ufo": "1.3.1",
127
+ "unhead": "1.7.4",
128
+ "vue": "3.3.6",
119
129
  "vue-gtag": "2.0.1",
130
+ "vue-router": "4.2.5",
120
131
  "vue-tsc": "1.8.19"
121
132
  },
122
133
  "peerDependencies": {
@@ -87,7 +87,7 @@ export default defineConfig({
87
87
  NUXT_PUBLIC_VIO_IS_TESTING: 'true',
88
88
  },
89
89
  timeout: process.env.NODE_ENV === 'production' ? 10000 : 100000,
90
- url: process.env.SITE_URL || SITE_URL,
90
+ url: SITE_URL,
91
91
  reuseExistingServer: !process.env.CI,
92
92
  },
93
93
 
@@ -1,26 +1,15 @@
1
1
  import { appendHeader, defineEventHandler } from 'h3'
2
2
  import type { H3Event } from 'h3'
3
- import { AppConfig } from 'nuxt/schema'
3
+ import type { AppConfig } from 'nuxt/schema'
4
4
 
5
5
  import { TIMEZONE_HEADER_KEY } from '../../utils/constants'
6
6
  import { getTimezone } from '../../utils/networking'
7
7
 
8
8
  export default defineEventHandler(async (event) => {
9
9
  setRequestHeader(event, TIMEZONE_HEADER_KEY, await getTimezone(event))
10
- // setContentSecurityPolicy(event);
11
10
  setResponseHeaders(event)
12
11
  })
13
12
 
14
- // const setContentSecurityPolicy = (event: H3Event) => {
15
- // const config = useAppConfig();
16
-
17
- // appendHeader(
18
- // event,
19
- // "Content-Security-Policy",
20
- // getCspAsString(config.public.vio.server.middleware.headers.csp)
21
- // );
22
- // };
23
-
24
13
  const setRequestHeader = (event: H3Event, name: string, value?: string) => {
25
14
  event.node.req.headers[name] = value
26
15
  }
package/store/auth.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { decodeJwt, JWTPayload } from 'jose'
1
+ import { decodeJwt, type JWTPayload } from 'jose'
2
2
  import { defineStore } from 'pinia'
3
3
  import { ref } from 'vue'
4
4
 
package/utils/auth.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { IncomingMessage, ServerResponse } from 'node:http'
2
2
 
3
3
  import { consola } from 'consola'
4
- import { parse, serialize } from 'cookie'
4
+ import { parse, serialize } from 'cookie-es'
5
5
  import { decodeJwt } from 'jose'
6
- import { Store } from 'pinia'
6
+ import type { Store } from 'pinia'
7
7
 
8
8
  import { useVioAuthStore } from '../store/auth'
9
9
  import { xhrPromise } from '../utils/networking'
@@ -2,7 +2,7 @@ import { CombinedError } from '@urql/core'
2
2
  import { H3Event, getCookie } from 'h3'
3
3
 
4
4
  import { ofetch } from 'ofetch'
5
- import { Ref } from 'vue'
5
+ import { type Ref } from 'vue'
6
6
 
7
7
  import type { ApiData, BackendError } from '../types/api'
8
8
  import { TIMEZONE_COOKIE_NAME } from './constants'
package/utils/utils.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { RouteLocationRaw } from '#vue-router'
1
+ import { type RouteLocationRaw } from '#vue-router'
2
2
 
3
3
  export const append = (path: string, pathToAppend?: RouteLocationRaw) =>
4
4
  path + (path.endsWith('/') ? '' : '/') + (pathToAppend ?? '')
@@ -1,2 +0,0 @@
1
- export const getCspAsString = (csp = {} as Record<string, Array<string>>) =>
2
- Object.keys(csp).reduce((p, c) => (p += `${c} ${csp[c].join(' ')};`), '')