Skip to content

Commit cd1f9a5

Browse files
feat: set up typescript types for database objects
1 parent b4aaa97 commit cd1f9a5

File tree

4 files changed

+116
-10
lines changed

4 files changed

+116
-10
lines changed

components/FeaturedProjects.vue

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,10 @@
3232
</div>
3333
</template>
3434

35-
<script setup>
36-
const { data: projects, pending, error } = await useLazyAsyncData('projects', async () => {
37-
const client = useSupabaseClient()
35+
<script setup lang="ts">
36+
import type { Project, Database } from '~/types/supabase'
37+
const { data: projects, pending, error } = await useLazyAsyncData<Project[]>('projects', async () => {
38+
const client = useSupabaseClient<Database>()
3839
const { data, error } = await client
3940
.from('projects')
4041
.select('*')

components/ProjectsList.vue

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,9 @@
104104
</div>
105105
</template>
106106

107-
<script setup>
107+
<script setup lang="ts">
108108
import { ref, computed } from '#imports'
109+
import type { Project, ProjectWithTags, Tag, Database } from '~/types/supabase'
109110
110111
const searchQuery = ref('')
111112
const selectedStage = ref('')
@@ -128,7 +129,7 @@ const stageClasses = {
128129
'Drifting': 'bg-red-100 text-red-800'
129130
}
130131
131-
const formatDate = (dateString) => {
132+
const formatDate = (dateString: string | null) => {
132133
if (!dateString) return 'N/A'
133134
return new Date(dateString).toLocaleDateString('en-US', {
134135
year: 'numeric',
@@ -137,8 +138,8 @@ const formatDate = (dateString) => {
137138
})
138139
}
139140
140-
const { data: projects, pending, error } = await useLazyAsyncData('all-projects', async () => {
141-
const client = useSupabaseClient()
141+
const { data: projects, pending, error } = await useLazyAsyncData<ProjectWithTags[]>('all-projects', async () => {
142+
const client = useSupabaseClient<Database>()
142143
const { data, error } = await client
143144
.from('projects')
144145
.select(`
@@ -157,18 +158,18 @@ const { data: projects, pending, error } = await useLazyAsyncData('all-projects'
157158
throw error
158159
}
159160
160-
return data?.map(project => ({
161+
return data?.map((project: Project & { project_tags: { tags: Tag }[] }) => ({
161162
...project,
162163
tags: project.project_tags
163164
?.map(pt => pt.tags)
164-
.filter(tag => tag.class === 'tech') || []
165+
.filter((tag): tag is Tag => tag.class === 'tech') || []
165166
}))
166167
})
167168
168169
const filteredProjects = computed(() => {
169170
if (!projects.value) return []
170171
171-
return projects.value.filter(project => {
172+
return projects.value.filter((project: ProjectWithTags) => {
172173
const matchesSearch = !searchQuery.value ||
173174
project.title.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
174175
project.readme?.toLowerCase().includes(searchQuery.value.toLowerCase())

types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './supabase'

types/supabase.ts

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/**
2+
* Generated types for Supabase schema
3+
*/
4+
5+
/**
6+
* Project stage enum type
7+
*/
8+
export type ProjectStage =
9+
| 'Hibernating'
10+
| 'Prototyping'
11+
| 'Commenting'
12+
| 'Testing'
13+
| 'Maintaining'
14+
| 'Drifting'
15+
16+
/**
17+
* Tag class enum type
18+
*/
19+
export type TagClass =
20+
| 'tech'
21+
| 'topic'
22+
| 'event'
23+
24+
/**
25+
* Project model
26+
*/
27+
export interface Project {
28+
id: number
29+
title: string
30+
handle: string
31+
created_at: string
32+
creator_id: number | null
33+
revision_id: number | null
34+
modified_at: string | null
35+
modifier_id: number | null
36+
maintainer_id: number | null
37+
users_url: string | null
38+
developers_url: string | null
39+
readme: string | null
40+
next_update: number | null
41+
stage: ProjectStage
42+
chat_channel: string | null
43+
}
44+
45+
/**
46+
* Tag model
47+
*/
48+
export interface Tag {
49+
id: number
50+
class: TagClass
51+
created_at: string
52+
creator_id: number | null
53+
title: string
54+
handle: string
55+
description: string | null
56+
items_count: number | null
57+
}
58+
59+
/**
60+
* Project tags junction model
61+
*/
62+
export interface ProjectTag {
63+
project_id: number
64+
tag_id: number
65+
}
66+
67+
/**
68+
* Transformed project with nested tags
69+
*/
70+
export interface ProjectWithTags extends Omit<Project, 'project_tags'> {
71+
tags: Tag[]
72+
}
73+
74+
/**
75+
* Database schema type
76+
*/
77+
export interface Database {
78+
public: {
79+
Tables: {
80+
projects: {
81+
Row: Project
82+
Insert: Omit<Project, 'id' | 'created_at'>
83+
Update: Partial<Omit<Project, 'id' | 'created_at'>>
84+
}
85+
tags: {
86+
Row: Tag
87+
Insert: Omit<Tag, 'id' | 'created_at'>
88+
Update: Partial<Omit<Tag, 'id' | 'created_at'>>
89+
}
90+
project_tags: {
91+
Row: ProjectTag
92+
Insert: ProjectTag
93+
Update: Partial<ProjectTag>
94+
}
95+
}
96+
Views: {}
97+
Functions: {}
98+
Enums: {
99+
project_stage: ProjectStage
100+
tag_class: TagClass
101+
}
102+
}
103+
}

0 commit comments

Comments
 (0)