Skip to content

Commit

Permalink
fix: Custom drivers failed on build (#2193)
Browse files Browse the repository at this point in the history
Co-authored-by: yarrow.love <creator@shareable.vision>
  • Loading branch information
shareable-vision and yarrow.love committed Aug 24, 2023
1 parent b32562e commit 5002a37
Show file tree
Hide file tree
Showing 24 changed files with 494 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ export default defineNuxtModule<ModuleOptions>({
base: resolve(nuxt.options.buildDir, 'content-cache')
}
for (const [key, source] of Object.entries(sources)) {
storage.mount(key, getMountDriver(source))
storage.mount(key, await getMountDriver(source))
}
let keys = await storage.getKeys('content:source')

Expand Down
5 changes: 2 additions & 3 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,14 @@ const unstorageDrivers = {
/**
* Resolve driver of a mount.
*/
export function getMountDriver (mount: MountOptions) {
export async function getMountDriver (mount: MountOptions) {
const dirverName = mount.driver as keyof typeof unstorageDrivers
if (unstorageDrivers[dirverName]) {
return unstorageDrivers[dirverName](mount as any)
}

try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
return require(mount.driver).default(mount as any)
return (await import(mount.driver)).default(mount as any)
} catch (e) {
// eslint-disable-next-line no-console
console.error("Couldn't load driver", mount.driver)
Expand Down
21 changes: 21 additions & 0 deletions test/custom-driver.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { fileURLToPath } from 'url'
import { test, describe, expect } from 'vitest'
import { setup } from '@nuxt/test-utils'

describe('Building with custom driver', async () => {
let builds: boolean
try {
await setup({
rootDir: fileURLToPath(new URL('./fixtures/custom-driver', import.meta.url)),
server: true,
dev: false
})
builds = true
} catch {
builds = false
}

test('Builds succeeds', () => {
expect(builds).toBe(true)
})
})
1 change: 1 addition & 0 deletions test/fixtures/custom-driver/.nuxtrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
imports.autoImport=false
19 changes: 19 additions & 0 deletions test/fixtures/custom-driver/addons/nitro-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { defineNitroPlugin } from 'nitropack/dist/runtime/plugin'

export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('content:file:beforeParse', (file) => {
if (file._id.endsWith('.md')) {
if (file.body.startsWith('---')) {
const lines = file.body.split('\n')
lines.splice(1, 0, '__beforeParse: true')
file.body = lines.join('\n')
} else {
file.body = '---\n__beforeParse: true\n---\n' + file.body
}
}
})

nitroApp.hooks.hook('content:file:afterParse', (file) => {
file.__afterParse = true
})
})
30 changes: 30 additions & 0 deletions test/fixtures/custom-driver/components/PropLogger.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<template>
<div>
<div class="prop-a">
{{ a }}
</div>
<div class="prop-b">
{{ b }}
</div>
<div class="prop-c">
{{ c }}
</div>
</div>
</template>

<script setup lang="ts">
defineProps({
a: {
type: String,
default: 'EMPTY'
},
b: {
type: String,
default: 'EMPTY'
},
c: {
type: String,
default: 'EMPTY'
}
})
</script>
5 changes: 5 additions & 0 deletions test/fixtures/custom-driver/components/content/Alert.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<div>
<ContentSlot :use="$slots.default" />
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<p>
[Paragraph] <slot />
</p>
</template>
14 changes: 14 additions & 0 deletions test/fixtures/custom-driver/components/content/TestMarkdown.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<template>
<div>
<h1 class="text-3xl font-bold text-primary-900 dark:text-primary-100">
<ContentSlot :use="$slots.title" unwrap="p">
Default title
</ContentSlot>
</h1>
<p>
<ContentSlot :use="$slots.default" unwrap="p">
Default paragraph
</ContentSlot>
</p>
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Components inside content

::lorem-ipsum
::
104 changes: 104 additions & 0 deletions test/fixtures/custom-driver/drivers/github.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { defineDriver } from 'unstorage'
import { $fetch } from 'ofetch'
import { joinURL } from 'ufo'
const defaultOptions = {
repo: '',
branch: 'main',
ttl: 600,
dir: '',
apiURL: 'https://api.github.com',
cdnURL: 'https://raw.githubusercontent.com'
}
const DRIVER_NAME = 'github'
export default defineDriver((_opts) => {
const opts = { ...defaultOptions, ..._opts }
const rawUrl = joinURL(opts.cdnURL, opts.repo, opts.branch, opts.dir)
let files = {}
let lastCheck = 0
let syncPromise
const syncFiles = async () => {
if (!opts.repo) {
throw new Error('[unstorage] [github] \'repo\' is required.')
}
if (lastCheck + opts.ttl * 1e3 > Date.now()) {
return
}
if (!syncPromise) {
syncPromise = fetchFiles(opts)
}
files = await syncPromise
lastCheck = Date.now()
syncPromise = undefined
}
return {
name: DRIVER_NAME,
options: opts,
async getKeys () {
await syncFiles()
return Object.keys(files)
},
async hasItem (key) {
await syncFiles()
return key in files
},
async getItem (key) {
await syncFiles()
const item = files[key]
if (!item) {
return null
}
if (!item.body) {
try {
item.body = await $fetch(key.replace(/:/g, '/'), {
baseURL: rawUrl,
headers: opts.token
? { Authorization: `token ${opts.token}` }
: undefined
})
} catch {
throw new Error(`[unstorage] [github] Failed to fetch '${key}'.`)
}
}
return item.body
},
async getMeta (key) {
await syncFiles()
const item = files[key]
return item ? item.meta : null
}
}
})

async function fetchFiles (opts) {
const withTrailingSlash = string => string.endsWith('/') ? string : `${string}/`

const prefix = withTrailingSlash(opts.dir).replace(/^\//, '')
const files = {}
try {
const trees = await $fetch(
`/repos/${opts.repo}/git/trees/${opts.branch}?recursive=1`,
{
baseURL: opts.apiURL,
headers: opts.token
? { Authorization: `token ${opts.token}` }
: undefined
}
)
for (const node of trees.tree) {
if (node.type !== 'blob' || !node.path.startsWith(prefix)) {
continue
}
const key = node.path.substring(prefix.length).replace(/\//g, ':')
files[key] = {
meta: {
sha: node.sha,
mode: node.mode,
size: node.size
}
}
}
return files
} catch (error) {
throw new Error('[unstorage] [github] Failed to fetch git tree.')
}
}
66 changes: 66 additions & 0 deletions test/fixtures/custom-driver/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { resolve } from 'pathe'
import contentModule from '../../..'
// import customDriver from './drivers/github.mjs'
// resolve('drivers', 'github.mjs')

export default defineNuxtConfig({
nitro: {
plugins: [
'~/addons/nitro-plugin.ts'
]
},
components: {
dirs: [
{
path: resolve(__dirname, './components'),
global: true
},
{
path: resolve(__dirname, './content'),
global: true,
pathPrefix: false,
prefix: ''
}
]
},
modules: [contentModule],
content: {
sources: {
github: {
prefix: '/',
driver: resolve(__dirname, 'drivers', 'github.mjs'),
repo: 'nuxt/content',
branch: 'main',
dir: '/test/fixtures/basic/content'
}
},
ignores: ['.*\\.vue'],
navigation: {
fields: ['icon']
},
highlight: {
theme: {
default: 'github-light',
dark: 'github-dark'
}
},
markdown: {
// Object syntax can be used to override default options
remarkPlugins: {
// override remark-emoji options
'remark-emoji': {
emoticon: true
},
// disable remark-gfm
'remark-gfm': false,
// add remark-oembed
'remark-oembed': {}
},
// Array syntax can be used to add plugins
rehypePlugins: [
'rehype-figure',
['rehype-wrap-all', [{ selector: 'ol', wrapper: 'p' }, { selector: 'ul', wrapper: 'p' }]]
]
}
}
})
3 changes: 3 additions & 0 deletions test/fixtures/custom-driver/pages/[...slug].vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
<ContentDoc />
</template>
3 changes: 3 additions & 0 deletions test/fixtures/custom-driver/pages/bypass-head.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
<ContentDoc path="/head" :head="false" />
</template>
20 changes: 20 additions & 0 deletions test/fixtures/custom-driver/pages/dogs-list.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script setup lang="ts">
const query = {
path: '/dogs',
limit: 10,
where: [{
_partial: false
}]
}
</script>

<template>
<ContentList :query="query">
<template #default="{ list }">
[{{ list.map(i => i.title).join(',') }}]
</template>
<template #not-found>
<p>No articles found</p>
</template>
</ContentList>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
<ContentDoc :path="'/'" :components="{ p: 'CustomProseP' }" />
</template>
45 changes: 45 additions & 0 deletions test/fixtures/custom-driver/pages/features/empty-slot.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<template>
<div>
<ContentRenderer :value="nullishDocument">
<template #empty>
Nullish Document!!!
</template>
</ContentRenderer>

<ContentRenderer :value="emptyChild">
<template #empty>
Empty Child!!!
</template>
</ContentRenderer>
</div>
</template>

<script setup>
const nullishDocument = null
const emptyChild = {
_path: '/_markdown',
_dir: '',
_draft: false,
_partial: true,
_locale: 'en',
_empty: true,
title: 'Markdown',
description: '',
body: {
type: 'root',
children: [],
toc: {
title: '',
searchDepth: 2,
depth: 2,
links: []
}
},
_type: 'markdown',
_id: 'content:_markdown.md',
_source: 'content',
_file: '_markdown.md',
_extension: 'md'
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
<ContentDoc path="/cats/persian" />
</template>

0 comments on commit 5002a37

Please sign in to comment.