Files
notebrook-notes/frontend-vue/src/services/api.ts

158 lines
4.4 KiB
TypeScript

import type { Channel, Message, ExtendedMessage, FileAttachment } from '@/types'
class ApiService {
private baseUrl = import.meta.env.DEV ? 'http://localhost:3000' : ''
private token = ''
setToken(token: string) {
this.token = token
console.log('API service token set:', token ? `${token.substring(0, 10)}...` : 'null')
}
setBaseUrl(url: string) {
this.baseUrl = url
console.log('API service base URL set:', url)
}
private getHeaders(): HeadersInit {
return {
'Authorization': this.token,
'Content-Type': 'application/json'
}
}
private getFormHeaders(): HeadersInit {
return {
'Authorization': this.token
}
}
private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
const url = `${this.baseUrl}${endpoint}`
const headers = {
...this.getHeaders(),
...options.headers
}
console.log('Making API request to:', url, 'with headers:', headers)
const response = await fetch(url, {
...options,
headers
})
if (!response.ok) {
console.error('API request failed:', response.status, response.statusText)
throw new Error(`API request failed: ${response.status} ${response.statusText}`)
}
return response.json()
}
// Authentication
async checkToken(): Promise<boolean> {
try {
const response = await fetch(`${this.baseUrl}/check-token`, {
headers: { Authorization: this.token }
})
return response.ok
} catch {
return false
}
}
// Channels
async getChannels(): Promise<{ channels: Channel[] }> {
return this.request('/channels')
}
async createChannel(name: string): Promise<Channel> {
return this.request('/channels', {
method: 'POST',
body: JSON.stringify({ name })
})
}
async updateChannel(channelId: number, name: string): Promise<{ message: string }> {
return this.request(`/channels/${channelId}`, {
method: 'PUT',
body: JSON.stringify({ name })
})
}
async deleteChannel(channelId: number): Promise<{ message: string }> {
return this.request(`/channels/${channelId}`, {
method: 'DELETE'
})
}
async mergeChannels(sourceChannelId: number, targetChannelId: number): Promise<{ message: string }> {
return this.request(`/channels/${sourceChannelId}/merge`, {
method: 'PUT',
body: JSON.stringify({ targetChannelId: targetChannelId.toString() })
})
}
// Messages
async getMessages(channelId: number): Promise<{ messages: ExtendedMessage[] }> {
return this.request(`/channels/${channelId}/messages`)
}
async createMessage(channelId: number, content: string): Promise<Message> {
return this.request(`/channels/${channelId}/messages`, {
method: 'POST',
body: JSON.stringify({ content })
})
}
async updateMessage(channelId: number, messageId: number, content: string): Promise<{ id: string, content: string }> {
return this.request(`/channels/${channelId}/messages/${messageId}`, {
method: 'PUT',
body: JSON.stringify({ content })
})
}
async deleteMessage(channelId: number, messageId: number): Promise<{ message: string }> {
return this.request(`/channels/${channelId}/messages/${messageId}`, {
method: 'DELETE'
})
}
// Files
async uploadFile(channelId: number, messageId: number, file: File): Promise<FileAttachment> {
const formData = new FormData()
formData.append('file', file)
const response = await fetch(`${this.baseUrl}/channels/${channelId}/messages/${messageId}/files`, {
method: 'POST',
headers: this.getFormHeaders(),
body: formData
})
if (!response.ok) {
throw new Error(`File upload failed: ${response.status} ${response.statusText}`)
}
return response.json()
}
async getFiles(channelId: number, messageId: number): Promise<{ files: FileAttachment[] }> {
return this.request(`/channels/${channelId}/messages/${messageId}/files`)
}
// Search
async search(query: string, channelId?: number): Promise<{ results: Message[] }> {
const params = new URLSearchParams({ query })
if (channelId) {
params.append('channelId', channelId.toString())
}
return this.request(`/search?${params.toString()}`)
}
// File URL helper
getFileUrl(filePath: string): string {
return `${this.baseUrl}/uploads/${filePath.replace(/^.*\/uploads\//, '')}`
}
}
export const apiService = new ApiService()