Skip to content

Conversation

@hendrikheil
Copy link
Contributor

This PR adds support for prefix in source for collections, which fixes the problem reported in #56

The way this is implemented is to add a new id property to TreeItem, which allows the Studio app to rely on native IDs from nuxt/content, without having to duplicate or match the logic for generating those IDs. As a neat side effect, this might bring some slight performance benefits as some operations in the file tree no longer have to iterate. Also this removes a bunch of items.collection![0] assertions, which is nice too.

I think its noteworthy to say that generateIdFromFsPath from tree.ts still remains as there are some collection decoupled operations that still benefit from the basic idea of the function, however for collection item operations, I think it should be avoided.

The primary issue of generating the file path from the ID is also fixed by ensuring that the fixed part of the include pattern is not removed if the prefix is /.

Note: This is not yet an ideal solution as

  1. Users might want to define alternative prefixes than /
  2. Data collectione receive a prefix defined as /{collectionName}, so this might need to be collection type aware. As per the Nuxt Content documentation, only page collections take use of the prefix, see https://github.com/nuxt/content/blob/87a2530e01b012be993d40eac3b310fdf5190882/docs/content/docs/2.collections/3.sources.md?plain=1#L45
  3. Nuxt Studio currently breaks when trying to edit data collections, as it tries to navigate the page to a route that doesnt exist

@vercel
Copy link

vercel bot commented Nov 6, 2025

@hendrikheil is attempting to deploy a commit to the Nuxt Team on Vercel.

A member of the Team first needs to authorize it.

@hendrikheil hendrikheil marked this pull request as draft November 6, 2025 22:50
children: [],
prefix: dirPrefix,
collections: [dbItem.id.split('/')[0]],
id: dirFsPath,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
id: dirFsPath,
id: joinURL(dbItem.id.split('/')[0], dirFsPath),

Directory items are assigned id: dirFsPath without including the collection prefix, which breaks the revert, rename, and delete operations on directories and their descendants because the ID matching logic in findDescendantsFromId will fail.

View Details

Analysis

Directory ID mismatch breaks revert, rename, and delete operations

What fails: Directory items in buildTree() receive IDs without collection prefixes (e.g., blog/posts) while file items get full database IDs (e.g., content/blog/posts/file.md), causing findDescendantsFromId() to fail when performing operations on directories and their descendants.

How to reproduce:

  1. Create files in collection: content/blog/posts/file1.md, content/blog/posts/file2.md
  2. Call findDescendantsFromId(draftItems, 'blog/posts') to find directory descendants
  3. Result: 0 descendants found (should find 2 files)

What happens: findDescendantsFromId() uses item.id.startsWith(id + '/') but fails because file IDs like content/blog/posts/file1.md don't start with blog/posts/. Directory operations (revert, rename, delete) fail to find and process nested files.

Expected: Directory IDs should include collection prefix (content/blog/posts) to match their descendant file IDs, allowing findDescendantsFromId() to correctly identify directory contents.

@larbish
Copy link
Contributor

larbish commented Nov 7, 2025

Well, what you’re proposing in your PR is actually what we had before this change: https://github.com/nuxt-content/studio/pull/38/files 😄

Why we removed it:
id is a Nuxt Content DB field (unique identifier for a db document) while the tree represents a visual structure containing both files AND folders.

We have to remember that file actions (delete, rename, revert, etc.) can also apply to folders (and therefore to all files inside them or drafted items in case of revert).
At first, we thought it wouldn’t be an issue and that creating a "virtual" idfor folders could work. And it actually did, thanks to that folder id we were able to find and apply the same action to all child files sharing this id.

BUT we then realized this only works when all files inside the folder belong to the same collection which isn’t always the case. Since a folder can contain files from multiple collections we need to loop over them to generate this “virtual” id and find all descendants => this is what the Vercel bot pointed out in your PR

CleanShot_2025-11-07_at_12 07 402x

This is why at the end we choose to keep this id only on file ONLY storage => SQLight db (nuxt content document) and IndexedDb (draft storage) but not in the tree which has its own logic and do not rely on file only.

@hendrikheil
Copy link
Contributor Author

I'll close this PR. Like you said, the approach I went with in this approach doesn't work for multi-sourced files. I still generally like the idea of keeping the logic for id <-> fsPath central, but I'm not sure it's easily achieved.

@hendrikheil hendrikheil closed this Nov 7, 2025
@hendrikheil hendrikheil deleted the fix/handle-prefix-in-source branch November 7, 2025 12:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants