@dargmuesli/nuxt-vio 8.2.3 → 8.3.3

Sign up to get free protection for your applications and to get access to all the features.
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.3",
3
+ "version": "8.3.3",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/dargmuesli/vio.git"
@@ -12,7 +12,7 @@
12
12
  "engines": {
13
13
  "node": "20"
14
14
  },
15
- "packageManager": "pnpm@8.9.0",
15
+ "packageManager": "pnpm@8.9.2",
16
16
  "files": [
17
17
  "assets",
18
18
  "components",
@@ -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",
@@ -65,61 +67,70 @@
65
67
  "test:e2e": "playwright test"
66
68
  },
67
69
  "dependencies": {
68
- "@axe-core/playwright": "4.7.3",
69
- "@dargmuesli/nuxt-cookie-control": "7.0.0-beta.1",
70
+ "@axe-core/playwright": "4.8.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",
80
- "@pinia/nuxt": "0.4.11",
81
- "@playwright/test": "1.38.1",
82
+ "@nuxtseo/module": "2.0.0-beta.39",
83
+ "@pinia/nuxt": "0.5.1",
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
- "jose": "4.15.2",
105
- "lint-staged": "14.0.1",
110
+ "jose": "4.15.4",
111
+ "lint-staged": "15.0.2",
106
112
  "lodash-es": "4.17.21",
107
- "nuxt": "3.7.4",
108
- "pinia": "2.1.6",
113
+ "nuxt": "3.8.0",
114
+ "nuxt-security": "1.0.0-rc.2",
115
+ "ofetch": "1.3.3",
116
+ "pinia": "2.1.7",
109
117
  "prettier": "3.0.3",
110
- "prettier-plugin-tailwindcss": "0.5.5",
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": {
123
- "playwright-core": "1.38.1"
134
+ "playwright-core": "1.39.0"
124
135
  }
125
136
  }
@@ -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(' ')};`), '')