Skip to content

Commit

Permalink
✨ here goes nothing
Browse files Browse the repository at this point in the history
  • Loading branch information
acidjazz committed Aug 13, 2024
1 parent 9e002e6 commit fd118ae
Show file tree
Hide file tree
Showing 22 changed files with 443 additions and 553 deletions.
3 changes: 1 addition & 2 deletions app/components/header/HeaderAuth.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<script setup lang="ts">
const { user } = useApi()
const { user } = await useUserSession()
const items = [
[
{
Expand Down
3 changes: 0 additions & 3 deletions app/components/layout/LayoutLogin.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
<script setup lang="ts">
import type { User } from '~/types/models.d.ts'
const emit = defineEmits(['login'])
const loading = ref(false)
interface Provider {
Expand Down Expand Up @@ -58,7 +56,6 @@ function login(name: string): void {
}
async function handleMessage(evt: { data: { user: User, token: string } }) {
useApi().setUser(evt.data.user, evt.data.token)
useApi().success('logged in')
emit('login')
await refreshNuxtData()
Expand Down
76 changes: 19 additions & 57 deletions app/composables/api.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import type { ZodIssue } from 'zod'
import type { User } from '~/types/models'
import type { MetapiResponse } from '~/types/metapi'
import type { FetchOptions } from 'ofetch'
import type { Form } from '#ui/types/form'
import type { UseFetchOptions } from '#app'

const user = ref<User | undefined>(undefined)
const silent = ref(false)
const hash = ref<string | undefined>(undefined)

const form = ref<Form<any>>()

export const useApi = () => {
hash.value = useCookie('token', cookieOptions).value
const success = (message: string) =>
useToast().add({ icon: 'i-mdi-check-bold', title: message, color: 'emerald', timeout: 2000 })

Expand All @@ -27,75 +23,41 @@ export const useApi = () => {
)
}

const fetch = $fetch.create({
headers: { Accept: 'application/json', Authentication: `Bearer: ${hash.value}` },
onResponse: ({ response }) => {
if (silent.value) {
silent.value = false
return
}
if (response?._data?.meta.success && response?._data?.meta?.detail)
success(response._data.meta.detail)
if (!response?._data?.meta.success && response?._data?.meta?.detail)
danger(response._data.meta.detail)
if (!response?._data?.meta.success && response?._data?.meta?.detail && form.value)
form.value?.setErrors(response._data.meta.detail.map((err: ZodIssue) => ({
message: err.message,
path: err.path[0],
})))
},
})

const api = <T>(
const fetch = <T>(
url: string | (() => string),
options?: Omit<UseFetchOptions<T>, 'default'> & { default: () => T | Ref<T> },
) => {
return useFetch(url, {
) =>
useFetch(url, {
...options,
$fetch: fetch,
onResponse: ({ response }) => {
if (silent.value) {
silent.value = false
return
}
if (response?._data?.meta.success && response?._data?.meta?.detail)
success(response._data.meta.detail)
if (!response?._data?.meta.success && response?._data?.meta?.detail)
danger(response._data.meta.detail)
if (!response?._data?.meta.success && response?._data?.meta?.detail && form.value)
form.value?.setErrors(response._data.meta.detail.map((err: ZodIssue) => ({
message: err.message,
path: err.path[0],
})))
},
})
}

const setForm = (frm?: Form<any>) => {
form.value = frm
return { fetch }
}

const setUser = (usr: User, token: string) => {
user.value = usr
const tokenCookie = useCookie('token', cookieOptions)
tokenCookie.value = token
hash.value = tokenCookie.value
}
const checkUser = async () => {
if (user.value) return

if (!hash.value) return

silent.value = true
try {
const { data } = await fetch<MetapiResponse<User>>('/api/me')
user.value = data
}
// eslint-disable-next-line unused-imports/no-unused-vars
catch (e) {}
}

const logout = async () => {
await fetch('/api/logout')
user.value = undefined
const tokenCookie = useCookie('token', cookieOptions)
tokenCookie.value = undefined
await navigateTo('/')
}

return {
fetch,
api,
setUser,
setForm,
checkUser,
user,
logout,
success,
}
Expand Down
6 changes: 2 additions & 4 deletions app/middleware/auth.global.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
export default defineNuxtRouteMiddleware(async (to, _from) => {
// if (import.meta.server) return
const token = useCookie('token', cookieOptions)
await useApi().checkUser()
const { loggedIn } = useUserSession()

useCrumb().init().add('Home')

Expand All @@ -14,5 +12,5 @@ export default defineNuxtRouteMiddleware(async (to, _from) => {
]

if (gatedRoutes.some(route => to.path.startsWith(route)))
if (!useApi().user.value) return await navigateTo('/')
if (!loggedIn.value) return await navigateTo('/')
})
27 changes: 13 additions & 14 deletions app/pages/home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Cartridge, Pen } from '@prisma/client'
import type { MetapiResponse } from '~/types/metapi'
const { data: page } = await useAsyncData('index', () => queryContent('/').findOne())
if (!page.value)
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
Expand All @@ -14,10 +15,10 @@ useSeoMeta({
ogDescription: page.value.description,
})
const { user } = useApi()
const { loggedIn } = useUserSession()
const { data: pens, refresh: pensRefresh } = await useApi().api<MetapiResponse<Pen[]>>('/api/pen')
const { data: cartridges, refresh: cartridgesRefresh } = await useApi().api<MetapiResponse<Cartridge[]>>('/api/cartridge')
const { data: pens, refresh: pensRefresh } = await useApi().fetch<MetapiResponse<Pen[]>>('/api/pen')
const { data: cartridges, refresh: cartridgesRefresh } = await useApi().fetch<MetapiResponse<Cartridge[]>>('/api/cartridge')
const reload = async () => {
await pensRefresh()
Expand All @@ -26,15 +27,13 @@ const reload = async () => {
</script>

<template>
<client-only>
<div v-if="user && pens?.data.length === 0" class="w-full max-w-md mx-auto">
<u-alert
icon="i-mdi-clock"
title="Awaiting Implementation"
description="We are still setting up your account, check back soon!"
:actions="[{ label: 'Refresh', icon: 'i-mdi-refresh', onClick: reload, variant: 'solid' }]"
/>
</div>
<pen-list v-else-if="pens && cartridges" :pens="pens?.data" :cartridges="cartridges?.data" readonly />
</client-only>
<div v-if="loggedIn && pens?.data.length === 0" class="w-full max-w-md mx-auto">
<u-alert
icon="i-mdi-clock"
title="Awaiting Implementation"
description="We are still setting up your account, check back soon!"
:actions="[{ label: 'Refresh', icon: 'i-mdi-refresh', onClick: reload, variant: 'solid' }]"
/>
</div>
<pen-list v-else-if="pens && cartridges" :pens="pens?.data" :cartridges="cartridges?.data" readonly />
</template>
4 changes: 2 additions & 2 deletions app/pages/tokens.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ useSeoMeta({
ogDescription: page.value.description,
})
const { data: tokens, refresh } = await useApi().api<MetapiResponse<Token[]>>('/api/token')
const { data: tokens, refresh } = await useApi().fetch<MetapiResponse<Token[]>>('/api/token')
</script>

<template>
<token-list :tokens="tokens.data" @reload="refresh" />
<token-list :tokens="tokens?.data" @reload="refresh" />
</template>
4 changes: 2 additions & 2 deletions app/pages/users/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import type { Pen } from '@prisma/client'
import { formatDistance } from 'date-fns'
import type { MetapiResponse } from '~/types/metapi'
import type { Cartridge, User } from '~/types/models'
import type { User } from '~/types/models'
useCrumb().add('Users')
Expand All @@ -29,7 +29,7 @@ const columns = [
},
]
const { data: users, refresh } = await useApi().api<MetapiResponse<User>>('/api/user')
const { data: users } = await useApi().fetch<MetapiResponse<User>>('/api/user')
</script>

<template>
Expand Down
3 changes: 3 additions & 0 deletions app/types/auth.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
declare module '#auth-utils' {
interface User extends import('~/types/models').User
}
1 change: 1 addition & 0 deletions app/types/models.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface UserPayload {
export interface User extends PrismaUser {
payload: UserPayload
isAdmin: boolean
hash: string
}

export interface Shot extends PrismaShot {
Expand Down
9 changes: 8 additions & 1 deletion nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@
export default defineNuxtConfig({
devtools: { enabled: true },
extends: ['@nuxt/ui-pro'],
modules: ['@nuxt/ui', '@prisma/nuxt', '@nuxt/eslint', '@nuxt/content', '@nuxt/image'],
modules: [
'@nuxt/ui',
'@prisma/nuxt',
'@nuxt/eslint',
'@nuxt/content',
'@nuxt/image',
'nuxt-auth-utils',
],
eslint: {
config: {
standalone: false,
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@
"@prisma/nuxt": "^0.0.35",
"@types/ua-parser-js": "^0.7.39",
"nuxt": "^3.12.4",
"nuxt-auth-utils": "^0.3.2",
"openid-client": "^5.6.5",
"prisma": "^5.18.0",
"ua-parser-js": "^1.0.38",
"zod": "^3.23.8"
}
},
"packageManager": "[email protected]+sha1.4a6f863625170af87d027789f72662e0601ecb57"
}
Loading

0 comments on commit fd118ae

Please sign in to comment.