chore(portal,operator): upgrade to Nuxt 4

Upgrade both Nuxt apps to Nuxt 4.4.6 (vue-tsc 3, TypeScript 5.6, undici 7) and add a root tsconfig.json to each app. Fix the strict-null / noUncheckedIndexedAccess errors surfaced by Nuxt 4's stricter generated tsconfig and vue-tsc 3. Drop the nuxt-oidc-auth pnpm patch (Nuxt 4 fixes the prepare:types crash natively).
This commit is contained in:
Ronni Baslund
2026-05-30 08:02:43 +02:00
parent 0bd4e5498e
commit 17ffd95a70
25 changed files with 888 additions and 706 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ const initials = computed(() =>
.split(' ')
.filter(Boolean)
.slice(0, 2)
.map((p) => p[0].toUpperCase())
.map((p) => p.charAt(0).toUpperCase())
.join(''),
)
+3 -2
View File
@@ -18,9 +18,10 @@ try { oidc = useOidcAuth() } catch { oidc = null }
const open = ref(false)
const rootRef = ref<HTMLElement | null>(null)
const displayName = computed(() => {
const displayName = computed<string>(() => {
const u = oidc?.user?.value
return u?.userInfo?.name || u?.userName || 'Anne Hansen'
const name = (u?.userInfo as { name?: string } | undefined)?.name
return name || (u?.userName as string | undefined) || 'Anne Hansen'
})
const email = computed(() => {
const u = oidc?.user?.value
@@ -1,20 +1,17 @@
<script setup lang="ts">
<script setup lang="ts" generic="T extends { id: string; current?: boolean; trusted?: boolean }">
// "..." menu for a single device row. The menu is teleported to <body> so it
// escapes any overflow/clip on the table — same pattern as the React design
// source. Closes on outside-click, Escape, or scroll.
//
// Generic over the device type so the emitted payload keeps the caller's full
// device shape (label, os, …) instead of narrowing to a subset.
interface DeviceLike {
id: string
current?: boolean
trusted?: boolean
}
const props = defineProps<{ device: DeviceLike }>()
defineProps<{ device: T }>()
const emit = defineEmits<{
rename: [DeviceLike]
trust: [DeviceLike]
history: [DeviceLike]
revoke: [DeviceLike]
rename: [T]
trust: [T]
history: [T]
revoke: [T]
}>()
const open = ref(false)
@@ -24,7 +24,7 @@ const emit = defineEmits<{ 'update:modelValue': [Presence] }>()
const open = ref(false)
const rootRef = ref<HTMLElement | null>(null)
const current = computed(() => opts.find((o) => o.value === props.modelValue) ?? opts[0])
const current = computed(() => opts.find((o) => o.value === props.modelValue) ?? opts[0]!)
function pick(v: Presence) {
emit('update:modelValue', v)
+2 -1
View File
@@ -36,7 +36,8 @@ const geometry = computed(() => {
})
const line = pts.map(([x, y], i) => `${i === 0 ? 'M' : 'L'} ${x.toFixed(1)} ${y.toFixed(1)}`).join(' ')
const area = `${line} L ${props.width} ${props.height} L 0 ${props.height} Z`
const last = { x: pts[pts.length - 1][0], y: pts[pts.length - 1][1] }
const lastPt = pts[pts.length - 1]!
const last = { x: lastPt[0], y: lastPt[1] }
return { line, area, last, min, max }
})
</script>