Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions src/utils/config.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { loadConfig, watchConfig, createDefineConfig } from 'c12'
import { relative } from 'pathe'
import { hasNuxtModule, useNuxt } from '@nuxt/kit'
import type { Nuxt } from '@nuxt/schema'
import type { DefinedCollection, ModuleOptions } from '../types'
import { defineCollection, resolveCollections } from './collection'
import { logger } from './dev'
import { resolveStudioCollection } from './studio'

type NuxtContentConfig = {
collections: Record<string, DefinedCollection>
}

const defaultConfig: NuxtContentConfig = {
collections: {
content: defineCollection({
type: 'page',
source: '**/*',
}),
},
}
const createDefaultCollections = (): NuxtContentConfig['collections'] => ({
content: defineCollection({
type: 'page',
source: '**/*',
}),
})

export const defineContentConfig = createDefineConfig<NuxtContentConfig>()

Expand Down Expand Up @@ -68,7 +68,14 @@ export async function loadContentConfig(nuxt: Nuxt, options?: ModuleOptions) {
logger.warn('No content configuration found, falling back to default collection. In order to have full control over your collections, create the config file in project root. See: https://content.nuxt.com/docs/getting-started/installation')
}

const collections = resolveCollections(hasNoCollections ? defaultConfig.collections : collectionsConfig)
const finalCollectionsConfig = hasNoCollections ? createDefaultCollections() : collectionsConfig

// If nuxt-studio is installed, automatically configure studio collection
if (hasNuxtModule('nuxt-studio', nuxt || useNuxt())) {
resolveStudioCollection(nuxt, finalCollectionsConfig)
}

const collections = resolveCollections(finalCollectionsConfig)

return { collections }
}
68 changes: 68 additions & 0 deletions src/utils/studio.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { z } from 'zod'
import type { Nuxt } from '@nuxt/schema'
import type { DefinedCollection } from '../types'
import { defineCollection } from './collection'

interface StudioAIConfig {
apiKey?: string
context?: {
title?: string
description?: string
tone?: string
style?: string
collection?: {
name?: string
folder?: string
}
}
}

const DEFAULT_STUDIO_COLLECTION_NAME = 'studio'
const DEFAULT_STUDIO_COLLECTION_FOLDER = '.studio'

/**
* Resolves studio collection configuration when nuxt-studio is installed.
* Automatically creates a studio collection and adds exclude patterns to other collections.
*/
export function resolveStudioCollection(
nuxt: Nuxt,
collectionsConfig: Record<string, DefinedCollection>,
): void {
/* @ts-expect-error - studio is not typed */
const studioAIConfig: StudioAIConfig = nuxt.options.studio?.ai || {}
if (!studioAIConfig.apiKey) {
return
}

const studioCollectionName = studioAIConfig.context?.collection?.name || DEFAULT_STUDIO_COLLECTION_NAME
const studioFolder = studioAIConfig.context?.collection?.folder || DEFAULT_STUDIO_COLLECTION_FOLDER
const studioPattern = `${studioFolder}/**`

// Add studio collection if it doesn't exist
if (!collectionsConfig[studioCollectionName]) {
collectionsConfig[studioCollectionName] = defineCollection({
type: 'data',
source: studioPattern,
schema: z.object({
rawbody: z.string(),
}),
})
}

// Add exclude pattern to all existing collections except studio
for (const [name, collection] of Object.entries(collectionsConfig)) {
if (name === studioCollectionName || !collection.source) {
continue
}

// Add exclude pattern to each source
for (const source of collection.source) {
if (!source.exclude) {
source.exclude = []
}
if (!source.exclude.includes(studioPattern)) {
source.exclude.push(studioPattern)
}
}
}
}
2 changes: 1 addition & 1 deletion test/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('basic', async () => {
describe('`content.config.ts`', async () => {
test('Default collection is defined', async () => {
const rootDir = resolver.resolve('./fixtures/basic')
const config = await loadContentConfig({ options: { _layers: [{ config: { rootDir } }] } } as Nuxt)
const config = await loadContentConfig({ options: { _installedModules: [], modules: [], _layers: [{ config: { rootDir } }] } } as Nuxt)

// Pages collection + info collection
expect(config.collections.length).toBe(2)
Expand Down
2 changes: 1 addition & 1 deletion test/csv.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('csv single-file collection', async () => {
describe('`content.config.ts`', async () => {
test('single-file csv source is resolved', async () => {
const rootDir = resolver.resolve('./fixtures/csv')
const config = await loadContentConfig({ options: { _layers: [{ config: { rootDir } }] } } as Nuxt)
const config = await loadContentConfig({ options: { _installedModules: [], modules: [], _layers: [{ config: { rootDir } }] } } as Nuxt)

expect(config.collections.map(c => c.name)).toContain('people')

Expand Down
2 changes: 1 addition & 1 deletion test/empty.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe('empty', async () => {
})
test('Default collection is defined', async () => {
const rootDir = resolver.resolve('./fixtures/empty')
const config = await loadContentConfig({ options: { _layers: [{ config: { rootDir } }] } } as Nuxt)
const config = await loadContentConfig({ options: { _installedModules: [], modules: [], _layers: [{ config: { rootDir } }] } } as Nuxt)

// Pages collection + info collection
expect(config.collections.length).toBe(2)
Expand Down
Loading