@datametria/vue-components
Version:
DATAMETRIA Vue.js 3 Component Library with Multi-Brand Theming - 51 components + 10 composables with theming support, WCAG 2.2 AA, dark mode, responsive system
79 lines (66 loc) • 1.74 kB
text/typescript
import { ref } from 'vue'
export interface ApiConfig {
baseURL?: string
timeout?: number
headers?: Record<string, string>
}
export function useAPI(config: ApiConfig = {}) {
const loading = ref(false)
const error = ref<string | null>(null)
const data = ref<any>(null)
const request = async (url: string, options: RequestInit = {}) => {
loading.value = true
error.value = null
try {
const fullUrl = config.baseURL ? `${config.baseURL}${url}` : url
const response = await fetch(fullUrl, {
...options,
headers: {
'Content-Type': 'application/json',
...config.headers,
...options.headers
}
})
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
}
const result = await response.json()
data.value = result
return result
} catch (err) {
error.value = (err as Error).message || 'Request failed'
throw err
} finally {
loading.value = false
}
}
const get = (url: string, options?: RequestInit) => {
return request(url, { ...options, method: 'GET' })
}
const post = (url: string, body: any, options?: RequestInit) => {
return request(url, {
...options,
method: 'POST',
body: JSON.stringify(body)
})
}
const put = (url: string, body: any, options?: RequestInit) => {
return request(url, {
...options,
method: 'PUT',
body: JSON.stringify(body)
})
}
const del = (url: string, options?: RequestInit) => {
return request(url, { ...options, method: 'DELETE' })
}
return {
loading,
error,
data,
get,
post,
put,
delete: del
}
}