Skip to content

Commit

Permalink
fix(collection): path route matching
Browse files Browse the repository at this point in the history
Co-authored-by: Farnabaz <farnabaz@gmail.com>
  • Loading branch information
larbish and farnabaz committed Nov 25, 2024
1 parent a2e5c9f commit 8ae885d
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 30 deletions.
55 changes: 40 additions & 15 deletions src/runtime/internal/studio/collection.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,60 @@
import { minimatch } from 'minimatch'
import type { CollectionInfo } from '@nuxt/content'
// import { joinURL, withoutLeadingSlash } from 'ufo'
import type { CollectionInfo, ResolvedCollectionSource } from '@nuxt/content'
import { joinURL } from 'ufo'
import type { JsonSchema7ObjectType } from 'zod-to-json-schema'
import { getOrderedSchemaKeys } from '../schema'
// import { parseSourceBase } from './utils'
import { parseSourceBase } from './utils'
import { withoutRoot } from './files'

export const getCollectionByPath = (path: string, collections: Record<string, CollectionInfo>): CollectionInfo => {
return Object.values(collections).find((collection) => {
export const getCollectionByFilePath = (path: string, collections: Record<string, CollectionInfo>): { collection: CollectionInfo, matchedSource: ResolvedCollectionSource } => {
let matchedSource: ResolvedCollectionSource
const collection = Object.values(collections).find((collection) => {
if (!collection.source || collection.source.length === 0) {
return
}

const pathWithoutRoot = withoutRoot(path)
const paths = pathWithoutRoot === '/' ? ['index.yml', 'index.yaml', 'index.md', 'index.json'] : [pathWithoutRoot]
return paths.some((p) => {
matchedSource = collection.source.find(source => minimatch(p, source.include))
return matchedSource
})
})

// TODO HANDLE PREFIX
// const prefix = withoutLeadingSlash(collection.source.prefix)
return {
collection,
matchedSource,
}
}

// if (!pathWithoutRoot.startsWith(prefix)) {
// return false
// }
export const getCollectionByRoutePath = (routePath: string, collections: Record<string, CollectionInfo>): { collection: CollectionInfo, matchedSource: ResolvedCollectionSource } => {
let matchedSource: ResolvedCollectionSource
const collection = Object.values(collections).find((collection) => {
if (!collection.source || collection.source.length === 0) {
return
}

// const { fixed } = parseSourceBase(collection.source)
matchedSource = collection.source.find((source) => {
if (!routePath.startsWith(source.prefix)) {
return
}

// path = joinURL(fixed, pathWithoutRoot.substring(withoutLeadingSlash(collection.source.prefix).length))
const pathWithoutPrefix = routePath.substring(source.prefix.length)

const paths = pathWithoutRoot === '/' ? ['index.yml', 'index.yaml', 'index.md', 'index.json'] : [pathWithoutRoot]
return paths.some((p) => {
return collection.source.some(source => minimatch(p, source.include))
const { fixed } = parseSourceBase(source)

const path = joinURL(fixed, pathWithoutPrefix)

return minimatch(path, source.include)
})

return matchedSource
})

return {
collection,
matchedSource,
}
}

export function generateCollectionInsert(collection: CollectionInfo, data: Record<string, unknown>) {
Expand Down
13 changes: 10 additions & 3 deletions src/runtime/internal/studio/compatibility.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import type { CollectionInfo, DraftSyncFile } from '@nuxt/content'
import type { CollectionInfo, DraftSyncFile, ResolvedCollectionSource } from '@nuxt/content'
import type { JsonSchema7ObjectType } from 'zod-to-json-schema'
import { join } from 'pathe'
import { parseSourceBase } from './utils'

export const v2ToV3ParsedFile = (file: DraftSyncFile, collection: CollectionInfo) => {
export const v2ToV3ParsedFile = (file: DraftSyncFile, collection: CollectionInfo, source: ResolvedCollectionSource) => {
const { fixed } = parseSourceBase(source)
const path = file.parsed._path.substring(fixed.length)
const pathInCollection = join(source?.prefix || '', path)

// TODO - Handle data collections (remove path...)
const mappedFile: Record<string, unknown> = {
id: file.parsed._id,
stem: file.parsed._stem,
meta: {},
extension: file.parsed._extension,
path: file.parsed._path,
path: pathInCollection,
}

const properties = (collection.schema.definitions[collection.name] as JsonSchema7ObjectType).properties
Expand Down
22 changes: 11 additions & 11 deletions src/runtime/internal/studio/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { withLeadingSlash } from 'ufo'
import StudioPreviewMode from '../../components/StudioPreviewMode.vue'
import { loadDatabaseAdapter } from '../database.client'
import { v2ToV3ParsedFile } from './compatibility'
import { getCollectionByPath, generateCollectionInsert, generateRecordDeletion, generateRecordSelectByColumn, generateRecordUpdate } from './collection'
import { getCollectionByFilePath, generateCollectionInsert, generateRecordDeletion, generateRecordSelectByColumn, generateRecordUpdate, getCollectionByRoutePath } from './collection'
import { createSingleton, deepAssign, deepDelete, defu, generateStemFromPath, mergeDraft, StudioConfigFiles, withoutRoot } from './utils'
import { callWithNuxt, refreshNuxtData } from '#app'
import { useAppConfig, useNuxtApp, useRuntimeConfig, useRoute, useRouter, ref } from '#imports'
Expand Down Expand Up @@ -43,15 +43,15 @@ const initializePreview = async (data: DraftSyncData) => {

const syncDraftFile = async (collections: Record<string, CollectionInfo>, file: DraftSyncFile) => {
// Fetch corresponding collection
const collection = getCollectionByPath(file.path, collections)
const { collection, matchedSource } = getCollectionByFilePath(file.path, collections)
if (!collection) {
console.warn(`Studio Preview: collection not found for file: ${file.path}, skipping insertion.`)
return
}

const db = loadDatabaseAdapter(collection.name)

const v3File = v2ToV3ParsedFile(file, collection)
const v3File = v2ToV3ParsedFile(file, collection, matchedSource)

const query = generateCollectionInsert(collection, v3File)

Expand Down Expand Up @@ -167,7 +167,7 @@ export function initIframeCommunication() {
return
}

const collection = getCollectionByPath(withoutRoot(path), collections)
const { collection } = getCollectionByFilePath(withoutRoot(path), collections)
if (!collection) {
console.warn(`Studio Preview: collection not found for file: ${path}, skipping navigation.`)
return
Expand Down Expand Up @@ -205,15 +205,15 @@ export function initIframeCommunication() {
}

async function handleFileUpdate(file: PreviewFile, navigate: boolean) {
const collection = getCollectionByPath(file.path, collections)
const { collection, matchedSource } = getCollectionByFilePath(file.path, collections)
if (!collection) {
console.warn(`Studio Preview: collection not found for file: ${file.path}, skipping update.`)
return
}

const stem = generateStemFromPath(file.path)

const v3File = v2ToV3ParsedFile({ path: file.path, parsed: file.parsed }, collection)
const v3File = v2ToV3ParsedFile({ path: file.path, parsed: file.parsed }, collection, matchedSource)

const query = generateRecordUpdate(collection, stem, v3File)

Expand All @@ -240,7 +240,7 @@ export function initIframeCommunication() {
}

async function handleFileDeletion(path: string) {
const collection = getCollectionByPath(withoutRoot(path), collections)
const { collection } = getCollectionByFilePath(withoutRoot(path), collections)
if (!collection) {
console.warn(`Studio Preview: collection not found for file: ${path}, skipping deletion.`)
return
Expand All @@ -261,23 +261,23 @@ export function initIframeCommunication() {
return
}

const currentPath = route.path
const routePath = route.path

const collection = getCollectionByPath(currentPath, collections)
const { collection } = getCollectionByRoutePath(routePath, collections)
if (!collection || collection.type !== 'page') {
return
}

const db = loadDatabaseAdapter(collection.name)

const query = generateRecordSelectByColumn(collection, 'path', currentPath)
const query = generateRecordSelectByColumn(collection, 'path', routePath)

const file = await db.first(query) as { path: string }
if (!file || !file.path) {
return
}

window.openFileInStudio(currentPath)
window.openFileInStudio(routePath)
}

nuxtApp.hook('page:finish', () => {
Expand Down
2 changes: 1 addition & 1 deletion src/types/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export interface CollectionInfo {
name: string
pascalName: string
tableName: string
source: CollectionSource[]
source: ResolvedCollectionSource[]
type: CollectionType
schema: JsonSchema7Type & {
$schema?: string
Expand Down

0 comments on commit 8ae885d

Please sign in to comment.