Skip to content

Commit

Permalink
✨ api cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
acidjazz committed Oct 8, 2023
1 parent 1be069f commit 62f002a
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 56 deletions.
6 changes: 1 addition & 5 deletions client/components/header/HeaderProfile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,7 @@ const profileGroup = [
{
icon: 'i-mdi-logout',
label: 'Logout',
click: async () => {
await useApi().logout()
useToast().add({ icon: 'i-mdi-logout', title: 'Logged out', })
}
click: async () => await useApi().logout()
},
],
]
Expand Down
67 changes: 29 additions & 38 deletions client/lib/api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import type { Notification } from '@nuxt/ui/dist/runtime/types'
import { reactive, ref } from 'vue'

import { NitroFetchRequest, $Fetch } from "nitropack";


import Echo from 'laravel-echo'
import Pusher from 'pusher-js'
import { NuxtApp } from '#app'
Expand Down Expand Up @@ -65,6 +68,7 @@ export default class Api {
constructor(config: AuthConfig) {
this.config = { ...authConfigDefaults, ...config }
}

setNuxtApp(nuxtApp:NuxtApp) {
this.nuxtApp = nuxtApp
}
Expand Down Expand Up @@ -110,73 +114,61 @@ export default class Api {
Object.assign(this.$user, result.user)
this.setEcho()
if (!discreet)
useToast().add({ icon: 'i-mdi-check-bold', color: 'green', title: 'Login Successful' })
useToast().add({ icon: 'i-mdi-check-bold', color: 'green', title: 'Login Successful', timeout: 1 })
if (result.action && result.action.action === 'redirect')
return result.action.url
return this.config.redirect.login
}

private fetchOptions(params?: SearchParameters, method = 'GET') {
const fetchOptions = this.config.fetchOptions
fetchOptions.headers = {
Accept: 'application/json',
Authorization: `Bearer ${this.token.value || ''}`,
Referer: this.config.webURL,
}
fetchOptions.method = method
fetchOptions.onRequest = () => this.nuxtApp?.callHook('page:start')
fetchOptions.onResponse = () => this.nuxtApp?.callHook('page:finish')
fetchOptions.onResponseError = this.toastError
delete this.config.fetchOptions.body
delete this.config.fetchOptions.params
if (params) {
if (method === 'POST' || method === 'PUT')
this.config.fetchOptions.body = params
else
this.config.fetchOptions.params = params
}
return this.config.fetchOptions
public fetch <Results>(params?: SearchParameters, method = 'GET'): $Fetch<Results, NitroFetchRequest> {
const nuxtApp = this.nuxtApp
return $fetch.create({
baseURL: this.config.apiURL,
method,
params: method === 'GET' ? params : undefined,
body: ['POST','PUT'].includes(method) ? params : undefined,
headers: {Accept: 'application/json', Authorization: `Bearer ${this.token.value}`},
onRequest() { nuxtApp?.callHook('page:start') },
onResponse() { nuxtApp?.callHook('page:finish') },
})
}


public async setUser(): Promise<boolean> {
try {
const result = await $fetch<api.MetApiResults & { data: models.User }>('/me', this.fetchOptions())
const result = await this.index<api.MetApiResponse & { data: models.User }>('/me')
if (!result || !result.status || result.status !== 'success') return false
Object.assign(this.$user, result.data)
} catch (e) { this.invalidate() }
} catch (e) { console.log(this.token.value, e.response._data) }
this.setEcho()
return true
}

public async index<Results>(endpoint: string, params?: SearchParameters): Promise<Results> {
return await $fetch<Results>(endpoint, this.fetchOptions(params))
}

public async get<Results>(endpoint: string, params?: SearchParameters): Promise<Results> {
return await $fetch<Results>(endpoint, this.fetchOptions(params))
public async index<Results>(endpoint: string, params?: SearchParameters): Promise<Results | undefined> {
return await this.fetch<Results>(params)(endpoint)
}

public async update<Response>(endpoint: string, params?: SearchParameters): Promise<Response | undefined> {
return await $fetch<Response>(endpoint, this.fetchOptions(params, 'PUT'))
return await this.fetch<Response>(params, 'PUT')(endpoint)
}

public async store<Response>(endpoint: string, params?: SearchParameters): Promise<Response | undefined> {
return await $fetch<Response>(endpoint, this.fetchOptions(params, 'POST'))
return await this.fetch<Response>(params, 'POST')(endpoint)
}

public async delete<Response>(endpoint: string, params?: SearchParameters): Promise<Response | undefined> {
return await $fetch<Response>(endpoint, this.fetchOptions(params, 'DELETE'))
return await this.fetch<Response>(params, 'DELETE')(endpoint)
}

public async attempt(token: string | string[]): Promise<UserLogin> {
if (Array.isArray(token))
token = token.join('')

return (await $fetch<api.MetApiResponse & { data: UserLogin }>(`/login/${token}`, this.fetchOptions())).data
return (await this.fetch<api.MetApiResponse & { data: UserLogin }>([])(`/login/${token}`)).data
}

public upload(url: string, params?: SearchParameters) {
return $fetch(url, { method: 'PUT', body: params })
public upload(endpoint: string, params?: SearchParameters) {
return this.fetch(params, 'PUT')(endpoint)
}

public async toastError(error: any): Promise<any> {
Expand All @@ -202,8 +194,7 @@ export default class Api {

if (error.response?._data.exception) {
useToast().add({
ui: {'width': 'sm:w-1/2'},
icon: 'i-mdi-alert',
icon: 'i-mdi-document',
color: 'red',
title: `
<b>[${error.response._data.exception}]</b><br />
Expand All @@ -226,7 +217,7 @@ export default class Api {
public async logout(): Promise<void> {
if (this.$echo)
this.$echo.disconnect()
const response = (await $fetch<api.MetApiResponse>('/logout', this.fetchOptions()))
const response = (await this.fetch<api.MetApiResponse>([])('/logout'))
useToast().add({ icon: 'i-mdi-check-bold', color: 'green', title: response.data.message, timeout: 1 })
await this.invalidate()
}
Expand Down
2 changes: 1 addition & 1 deletion client/middleware/auth.global.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import Menu from '@/lib/menu'

export default defineNuxtRouteMiddleware(async (to, from) => {
await useLnUtils().sleep(100)
const api = useApi()
await api.checkUser()
const menu = new Menu(api)
const item = menu.items().find(item => item.to === to.path)
// console.log(`loggedIn: ${ api.loggedIn.value } - ${ api.$user.name }`)
if (item && item.gated === true && api.loggedIn.value === false) {
useToast().add({ icon: 'i-mdi-lock', color: 'red', title: 'Access Denied', })
return navigateTo('/')
Expand Down
7 changes: 4 additions & 3 deletions client/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ setCrumbs([{ name: 'List of Users', to: '/', icon: 'i-mdi-account-group' }])
const loading = ref(false)
const users = ref<models.UserResults>(undefined)
const users = ref<models.UserResults>()
const get = async () => {
loading.value = true
users.value = undefined
users.value = await useApi().index<models.UserResults>('/example', { count: 9 })
users.value = await useApi().index<models.UserResults>('/example', { count: 9 }) as models.UserResults
loading.value = false
}
const error = async () => await useApi().get('/error')
const error = async () => await useApi().index('/error')
const start = () => {
useNuxtApp().callHook('page:start').catch(() => { })
Expand Down
9 changes: 5 additions & 4 deletions client/types/api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,22 @@ declare global {
options: Record<string, unknown>
params: Record<string, unknown>
}

interface MetApiData {
success: boolean
type: 'success' | 'failure'
message: string
data: unknown
}
export interface MetApiResponse {

export interface MetApiResponse {
status: 'success' | 'failure'
benchmark: number
success: boolean
message: string
type: 'success' | 'failure'
query: MetApiQuery
data: MetApiData

}

export type Me = Modify<api.MetApiResponse, { data: models.User }>

export interface MetApiResults {
Expand Down
1 change: 1 addition & 0 deletions client/types/models.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ declare global {
notifications: DatabaseNotifications
}
export type Users = User[]
export type UserResult = Modify<api.MetApiResults, { data: User }>
export type UserResults = Modify<api.MetApiResults, { data: Users }>

}
Expand Down
10 changes: 5 additions & 5 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,18 @@
### Installation

* clone from GitHub
* run `yarn` and `composer install` to install all of your deps
* run `pnpm i` and `composer install` to install all of your deps
* copy `.env.example` to `.env` and configure it to your likings
* TL;DR
```bash
git clone git@github.com:fumeapp/laranuxt.git; cd laranuxt; yarn; c****omposer install; cp .env.example .env;
git clone git@github.com:fumeapp/laranuxt.git; cd laranuxt; pnpm i; composer install; cp .env.example .env;
```
* Feel free to delete excess media in `/resources/`


### Local Environment
* run `yarn dev` in one terminal for our nuxt dev setup
* run `yarn api` (alias for `./artisan serve`) in another terminal for our laravel API
* run `pnpm run dev` in one terminal for our nuxt dev setup
* run `pnpm run api` (alias for `./artisan serve`) in another terminal for our laravel API

### Api and Authentication

Expand All @@ -68,7 +68,7 @@ console.log(api.$user.name);
const redirect = await api.login(result)
if (redirect) await router.push({path: redirect})
```
* Once logged on, you have the boolean `api.loggedIn` and the object `api.$user`
* Once logged on, you have the ref<boolean> `api.loggedIn` and the object `api.$user`
```html
<img class="w-8 h-8 rounded-full bg-blue-400" :src="api.$user.avatar" alt="User Avatar">
```
Expand Down

0 comments on commit 62f002a

Please sign in to comment.