diff --git a/app/components/AttachmentItem.vue b/app/components/AttachmentItem.vue index 51177f9..ad47598 100644 --- a/app/components/AttachmentItem.vue +++ b/app/components/AttachmentItem.vue @@ -6,8 +6,9 @@ diff --git a/app/pages/index.vue b/app/pages/index.vue index f2bdca6..8c4da15 100644 --- a/app/pages/index.vue +++ b/app/pages/index.vue @@ -42,6 +42,7 @@ import { computed, onMounted, ref } from 'vue' import { useUserStore } from '~/stores/user' import { useSolarNetwork } from '~/composables/useSolarNetwork' +import type { SnVersion, SnActivity } from '~/types/api' import PostEditor from '~/components/PostEditor.vue' import PostItem from '~/components/PostItem.vue' @@ -50,17 +51,17 @@ const router = useRouter() const userStore = useUserStore() -const version = ref(null) +const version = ref(null) async function fetchVersion() { const api = useSolarNetwork() const resp = await api('/sphere/version') - version.value = resp + version.value = resp as SnVersion } onMounted(() => fetchVersion()) const loading = ref(false) -const activites = ref([]) +const activites = ref([]) const activitesLast = computed(() => activites.value[Math.max(activites.value.length - 1, 0)]) const activitesHasMore = ref(true) @@ -74,7 +75,7 @@ async function fetchActivites() { ? '/sphere/activities' : `/sphere/activities?cursor=${new Date(activitesLast.value.created_at).toISOString()}`, ) - const data = resp + const data = resp as SnActivity[] activites.value = [...activites.value, ...data] activitesHasMore.value = data[0]?.type != 'empty' loading.value = false diff --git a/app/stores/pub.ts b/app/stores/pub.ts index 45e7cc9..82278cf 100644 --- a/app/stores/pub.ts +++ b/app/stores/pub.ts @@ -1,14 +1,15 @@ import { defineStore } from 'pinia' import { ref } from 'vue' import { useSolarNetwork } from '~/composables/useSolarNetwork' +import type { SnPublisher } from '~/types/api' export const usePubStore = defineStore('pub', () => { - const publishers = ref([]) + const publishers = ref([]) async function fetchPublishers() { const api = useSolarNetwork() const resp = await api('/publishers') - publishers.value = resp as any[] + publishers.value = resp as SnPublisher[] } return { publishers, fetchPublishers } diff --git a/app/stores/user.ts b/app/stores/user.ts index f399293..a63e8fa 100644 --- a/app/stores/user.ts +++ b/app/stores/user.ts @@ -1,10 +1,11 @@ import { defineStore } from 'pinia' import { ref, computed } from 'vue' import { useSolarNetwork } from '~/composables/useSolarNetwork' +import type { SnAccount } from '~/types/api' export const useUserStore = defineStore('user', () => { // State - const user = ref(null) + const user = ref(null) const isLoading = ref(false) const error = ref(null) @@ -20,9 +21,9 @@ export const useUserStore = defineStore('user', () => { try { const response = await api('/id/accounts/me') - user.value = response - } catch (e: any) { - error.value = e.message + user.value = response as SnAccount + } catch (e: unknown) { + error.value = e instanceof Error ? e.message : 'An error occurred' user.value = null // Clear user data on error } finally { isLoading.value = false diff --git a/app/types/api/activity.ts b/app/types/api/activity.ts new file mode 100644 index 0000000..cf903b2 --- /dev/null +++ b/app/types/api/activity.ts @@ -0,0 +1,14 @@ +import type { SnPost } from './post' + +// Activity interface (main response structure) +export interface SnActivity { + id: string; + type: string; + resource_identifier: string; + meta: Record; + data: SnPost; + visibility: number; + created_at: string; + updated_at: string; + deleted_at: string | null; +} diff --git a/app/types/api/index.ts b/app/types/api/index.ts new file mode 100644 index 0000000..b403f8d --- /dev/null +++ b/app/types/api/index.ts @@ -0,0 +1,6 @@ +// Re-export all types from separate files for easy importing +export type { SnFileMeta, SnAttachment, SnPost } from './post' +export type { SnVerification, SnPublisher } from './publisher' +export type { SnActivity } from './activity' +export type { SnVersion } from './version' +export type { SnAccountLink, SnAccountBadge, SnAccountPerkSubscription, SnAccountProfile, SnAccount } from './user' diff --git a/app/types/api/post.ts b/app/types/api/post.ts new file mode 100644 index 0000000..97d6bc0 --- /dev/null +++ b/app/types/api/post.ts @@ -0,0 +1,83 @@ +// File metadata interface +import type { SnPublisher } from './publisher' + +export interface SnFileMeta { + blur?: string; + exif?: Record; + xres?: number; + yres?: number; + bands?: number; + ratio?: number; + width?: number; + coding?: number; + format?: number | string; + height?: number; + xoffset?: number; + yoffset?: number; + filename?: string | null; + orientation?: number; + 'vips-loader'?: string; + interpretation?: number; + 'bits-per-sample'?: number; + 'resolution-unit'?: string; +} + +// Attachment interface +export interface SnAttachment { + id: string; + name: string; + file_meta: SnFileMeta; + user_meta: Record | null; + sensitive_marks: string[]; + mime_type: string; + hash: string; + size: number; + has_compression: boolean; + created_at: string; + updated_at: string; + deleted_at: string | null; +} + +// Post interface +export interface SnPost { + id: string; + title: string; + description: string; + slug: string | null; + edited_at: string | null; + published_at: string; + visibility: number; + content: string; + type: number; + pin_mode: unknown | null; + meta: unknown | null; + sensitive_marks: string[]; + embed_view: unknown | null; + views_unique: number; + views_total: number; + upvotes: number; + downvotes: number; + awarded_score: number; + reactions_count: Record; + replies_count: number; + reactions_made: Record; + replied_gone: boolean; + forwarded_gone: boolean; + replied_post_id: string | null; + replied_post: SnPost | null; + forwarded_post_id: string | null; + forwarded_post: SnPost | null; + realm_id: string | null; + realm: unknown | null; + attachments: SnAttachment[]; + publisher_id: string; + publisher: SnPublisher; + awards: unknown | null; + tags: string[]; + categories: string[]; + is_truncated: boolean; + resource_identifier: string; + created_at: string; + updated_at: string; + deleted_at: string | null; +} diff --git a/app/types/api/publisher.ts b/app/types/api/publisher.ts new file mode 100644 index 0000000..8b5f278 --- /dev/null +++ b/app/types/api/publisher.ts @@ -0,0 +1,30 @@ +import type { SnAttachment } from './post' + +// Verification interface +export interface SnVerification { + type: number; + title: string; + description: string; + verified_by: string; +} + +// Publisher interface +export interface SnPublisher { + id: string; + type: number; + name: string; + nick: string; + bio: string; + picture_id: string; + background_id: string; + picture: SnAttachment | null; + background: SnAttachment | null; + verification: SnVerification | null; + account_id: string; + realm_id: string | null; + account: unknown | null; + resource_identifier: string; + created_at: string; + updated_at: string; + deleted_at: string | null; +} diff --git a/app/types/api/user.ts b/app/types/api/user.ts new file mode 100644 index 0000000..3b24f57 --- /dev/null +++ b/app/types/api/user.ts @@ -0,0 +1,92 @@ +import type { SnAttachment } from './post' +import type { SnVerification } from './publisher' + +// Account link interface +export interface SnAccountLink { + name: string; + url: string; +} + +// Account badge interface +export interface SnAccountBadge { + id: string; + type: string; + label: string | null; + caption: string | null; + meta: Record; + activated_at: string; + expired_at: string | null; + account_id: string; + created_at: string; + updated_at: string; + deleted_at: string | null; +} + +// Account perk subscription interface +export interface SnAccountPerkSubscription { + id: string; + identifier: string; + begun_at: string; + ended_at: string; + is_active: boolean; + is_available: boolean; + is_free_trial: boolean; + status: number; + base_price: number; + final_price: number; + renewal_at: string; + account_id: string; + display_name: string; + created_at: string; + updated_at: string; + deleted_at: string | null; +} + +// Account profile interface +export interface SnAccountProfile { + id: string; + first_name: string; + middle_name: string; + last_name: string; + bio: string; + gender: string; + pronouns: string; + time_zone: string; + location: string; + links: SnAccountLink[]; + birthday: string; + last_seen_at: string; + verification: SnVerification | null; + active_badge: unknown | null; + experience: number; + level: number; + social_credits: number; + social_credits_level: number; + leveling_progress: number; + picture: SnAttachment | null; + background: SnAttachment | null; + account_id: string; + resource_identifier: string; + created_at: string; + updated_at: string; + deleted_at: string | null; +} + +// Account interface +export interface SnAccount { + id: string; + name: string; + nick: string; + language: string; + region: string; + activated_at: string; + is_superuser: boolean; + automated_id: string | null; + profile: SnAccountProfile; + contacts: unknown[]; + badges: SnAccountBadge[]; + perk_subscription: SnAccountPerkSubscription | null; + created_at: string; + updated_at: string; + deleted_at: string | null; +} diff --git a/app/types/api/version.ts b/app/types/api/version.ts new file mode 100644 index 0000000..f7e5687 --- /dev/null +++ b/app/types/api/version.ts @@ -0,0 +1,6 @@ +// Version interface +export interface SnVersion { + version: string; + commit: string; + updatedAt: string; +} diff --git a/eslint.config.mjs b/eslint.config.mjs index 042ccb5..a252638 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -5,7 +5,8 @@ export default withNuxt( // Your custom configs here { rules: { - 'vue/multi-word-component-names': 'off' + 'vue/multi-word-component-names': 'off', + 'vue/no-v-html': 'off' } } )