Skip to content

Commit b717b5d

Browse files
committed
feat(readme): new component to display readme
1 parent 89af75c commit b717b5d

File tree

10 files changed

+163
-14
lines changed

10 files changed

+163
-14
lines changed

playground/components/Navigation.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ const nav = [
66
name: 'Repository',
77
path: '/'
88
},
9+
{
10+
name: 'Readme',
11+
path: '/readme'
12+
},
913
{
1014
name: 'Releases',
1115
path: '/releases'

playground/pages/contributors.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
<script setup lang="ts">
2+
const owner = 'nuxt-community'
3+
const repo = 'supabase-module'
4+
</script>
5+
16
<template>
27
<div>
38
<!-- Fetch from config:
@@ -21,8 +26,3 @@
2126
</GithubContributors>
2227
</div>
2328
</template>
24-
25-
<script setup lang="ts">
26-
const owner = 'nuxt-community'
27-
const repo = 'supabase-module'
28-
</script>

playground/pages/last-release.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
<script setup lang="ts">
2+
const owner = 'nuxt-community'
3+
const repo = 'supabase-module'
4+
</script>
5+
16
<template>
27
<div>
38
<!-- Fetch repository from config:
@@ -47,8 +52,3 @@
4752
</GithubLastRelease>
4853
</div>
4954
</template>
50-
51-
<script setup lang="ts">
52-
const owner = 'nuxt-community'
53-
const repo = 'supabase-module'
54-
</script>

playground/pages/readme.vue

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<script setup lang="ts">
2+
const owner = 'nuxt-community'
3+
const repo = 'supabase-module'
4+
</script>
5+
6+
<template>
7+
<!-- Fetch readme from config:
8+
<GithubReadme v-slot="{ readme }">
9+
<ContentRenderer :value="readme" />
10+
</GithubReadme> -->
11+
12+
Fetch readme from query: {{ owner }} / {{ repo }}
13+
<GithubReadme v-slot="{ readme }" :query="{ owner, repo}">
14+
<ContentRenderer :value="readme" />
15+
</GithubReadme>
16+
</template>

src/module.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ export default defineNuxtModule<ModuleOptions>({
103103
handler: resolveModule('./server/api/repository', { paths: runtimeDir })
104104
})
105105

106+
// Setup readme file API
107+
nitroConfig.handlers.push({
108+
route: '/api/_github/readme',
109+
handler: resolveModule('./server/api/readme', { paths: runtimeDir })
110+
})
111+
106112
// Repository component
107113
addComponent({
108114
name: 'GithubRepository',
@@ -117,6 +123,13 @@ export default defineNuxtModule<ModuleOptions>({
117123
global: true
118124
})
119125

126+
// GithubReadme component
127+
addComponent({
128+
name: 'GithubReadme',
129+
filePath: resolveModule('./components/GithubReadme', { paths: runtimeDir }),
130+
global: true
131+
})
132+
120133
// Setup releases API
121134
if (options.releases) {
122135
// Last release (pre-render friendly)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { defineComponent, useSlots, PropType } from 'vue'
2+
import { useGithub } from '../composables/useGithub'
3+
import { GithubRepositoryOptions } from '../types'
4+
// @ts-ignore
5+
import { useAsyncData } from '#imports'
6+
7+
export default defineComponent({
8+
props: {
9+
query: {
10+
type: Object as PropType<GithubRepositoryOptions>,
11+
required: false,
12+
default: () => ({})
13+
}
14+
},
15+
async setup (props) {
16+
const { fetchReadme } = useGithub()
17+
18+
const { data: readme, refresh, pending } = await useAsyncData('github-repository-component', () => fetchReadme(props.query))
19+
20+
return {
21+
readme,
22+
refresh,
23+
pending
24+
}
25+
},
26+
render ({ readme, refresh, pending }) {
27+
const slots = useSlots()
28+
29+
return slots?.default?.({ readme, refresh, pending })
30+
}
31+
})

src/runtime/composables/useGithub.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { withQuery, QueryObject } from 'ufo'
2-
import { GithubRepositoryOptions, GithubContributorsQuery, GithubReleasesQuery, GithubRepository, GithubRawRelease, GithubRawContributors } from '../types'
3-
2+
import type { ParsedContent } from '@nuxt/content/dist/runtime/types'
3+
import type { GithubRepositoryOptions, GithubContributorsQuery, GithubReleasesQuery, GithubRepository, GithubRawRelease, GithubRawContributors } from '../types'
44
export const useGithub = () => {
55
const fetchRepository = (query: GithubRepositoryOptions): Promise<GithubRepository> => {
66
const url = withQuery('/api/_github/repository', query as QueryObject)
@@ -26,11 +26,17 @@ export const useGithub = () => {
2626
return $fetch(url, { responseType: 'json' })
2727
}
2828

29+
const fetchReadme = (query: GithubRepositoryOptions): Promise<ParsedContent> => {
30+
const url = withQuery('/api/_github/readme', query as QueryObject)
31+
return $fetch(url, { responseType: 'json' })
32+
}
33+
2934
return {
3035
fetchRepository,
3136
fetchReleases,
3237
fetchLastRelease,
3338
fetchContributors,
34-
fetchFileContributors
39+
fetchFileContributors,
40+
fetchReadme
3541
}
3642
}

src/runtime/server/api/readme.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { useQuery } from 'h3'
2+
import { overrideConfig, fetchReadme } from '../utils/queries'
3+
import type { ModuleOptions } from '../../../module'
4+
import { GithubRepositoryOptions, GithubRepositoryReadme } from '../../types'
5+
import { parseContent } from '#content/server'
6+
// @ts-ignore
7+
// @ts-ignore
8+
import * as imports from '#imports'
9+
10+
let handler
11+
if (process.env.NODE_ENV === 'development') {
12+
// @ts-ignore
13+
// eslint-disable-next-line import/namespace
14+
handler = imports.defineEventHandler
15+
} else {
16+
// @ts-ignore
17+
// eslint-disable-next-line import/namespace
18+
handler = imports.defineCachedEventHandler
19+
}
20+
21+
export default handler(
22+
async ({ req }) => {
23+
const moduleConfig: ModuleOptions = imports.useRuntimeConfig().github
24+
25+
// Get query
26+
const query = useQuery(req) as GithubRepositoryOptions
27+
28+
// Merge query in base config
29+
const githubConfig = overrideConfig(moduleConfig, query)
30+
31+
if (!githubConfig.owner || !githubConfig.repo || !githubConfig.api) { return [] }
32+
33+
// Fetches releases from GitHub
34+
const readme = await fetchReadme(githubConfig) as GithubRepositoryReadme
35+
36+
return await parseContent(`${githubConfig.owner}:${githubConfig.repo}:readme.md`, Buffer.from(readme.content, 'base64').toString())
37+
},
38+
{
39+
maxAge: 60 // cache for one minute
40+
}
41+
)

src/runtime/server/utils/queries.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { defu } from 'defu'
44
import type {
55
ModuleOptions
66
} from '../../../module'
7-
import { GithubRawRelease, GithubRepositoryOptions, GithubRawContributors, GithubContributorsQuery, GithubReleasesQuery } from '../../types'
7+
import { GithubRawRelease, GithubRepositoryOptions, GithubRawContributors, GithubContributorsQuery, GithubReleasesQuery, GithubRepositoryReadme } from '../../types'
88
import { parseContent } from '#content/server'
99
function isBot (user) {
1010
return user.login.includes('[bot]') || user.login.includes('-bot') || user.login.includes('.bot')
@@ -223,3 +223,27 @@ export async function fetchReleases (query: Partial<GithubReleasesQuery>, { api,
223223

224224
return releases
225225
}
226+
227+
export async function fetchReadme ({ api, owner, repo, token }: GithubRepositoryOptions) {
228+
const url = `${api}/repos/${owner}/${repo}/readme`
229+
230+
const readme = await $fetch<GithubRepositoryReadme>(url, {
231+
headers: {
232+
Authorization: token ? `token ${token}` : undefined
233+
}
234+
}).catch((_) => {
235+
/*
236+
237+
// eslint-disable-next-line no-console
238+
console.warn(`Cannot fetch GitHub readme on ${url} [${err.response?.status || 500}]`)
239+
240+
// eslint-disable-next-line no-console
241+
console.info('If your repository is private, make sure to provide GITHUB_TOKEN environment in `.env`')
242+
243+
*/
244+
245+
return {}
246+
})
247+
248+
return readme
249+
}

src/runtime/types/repository.d.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,20 @@ export interface GithubRepositoryOptions {
66
token?: string
77
}
88

9+
export interface GithubRepositoryReadme {
10+
name: string
11+
path: string
12+
sha: string
13+
size: number
14+
url: string
15+
html_url: string
16+
git_url: string
17+
download_url: string
18+
type: 'file'
19+
content: string,
20+
encoding: 'base64'
21+
}
22+
923
export interface GithubRepositoryOwner {
1024
login: string
1125
id: number

0 commit comments

Comments
 (0)