fix(preview): skip collections without source in preview template#3771
Conversation
The internal `info` collection (created by `resolveCollections()`) has `source: undefined`. The previous `collection.source?.filter(...) || []` fallback produced `source: []` in the serialized preview payload, which violates the `ResolvedCollectionSource[]` contract and crashes downstream consumers (nuxt-studio) that access `source[0].include` and `source[0].prefix`. The `info` collection is internal and cannot be edited from the preview/studio UI, so it should not appear in the preview manifest at all. This skips such collections entirely and also simplifies the remote-collection filter to a straightforward `!source.repository` predicate. Resolves nuxt#3767
|
@humanbird is attempting to deploy a commit to the Nuxt Team on Vercel. A member of the Team first needs to authorize it. |
commit: |
`@nuxt/content` v3 exposes an internal `info` collection whose `source` is serialized as an empty array (`source: []`) in the preview manifest. Studio iterates every collection via `parseSourceBase`, `generateIdFromFsPath`, and `generateFsPathFromId`, which all assumed at least one `ResolvedCollectionSource` entry and crashed with `TypeError: Cannot read properties of undefined (reading 'include' | 'prefix')` as soon as the editor tried to list content. The upstream payload fix is in nuxt/content#3771, but the guards here are still the correct shape defensively — Studio should tolerate any future source-less collection without corrupting the editor. - `parseSourceBase` now short-circuits to empty `fixed`/`dynamic` when the source (or its `include`) is missing. - `getCollectionSourceById` skips sources without `include` during matching instead of throwing. - `generateIdFromFsPath` falls back to `join(name, path)` when the collection has no source. - `generateFsPathFromId` returns the raw path when no source is given. Resolves nuxt-content#425
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/utils/templates.ts`:
- Around line 227-228: The current mapping that sets "source:
collection.source.filter(source => !source.repository)" can produce an empty
array for fully remote collections, recreating an invalid CollectionInfo.source
shape; update the logic where collections are transformed (the mapping that
assigns source) to first compute filteredSources = collection.source.filter(s =>
!s.repository) and then skip/omit the entire collection if
filteredSources.length === 0 (or do not set CollectionInfo.source) so
remote-only collections are not emitted with source: [] — adjust the transform
that creates CollectionInfo/source accordingly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 9bb8414c-f24c-4ec4-a2d6-a754096e59e7
📒 Files selected for processing (1)
src/utils/templates.ts
CodeRabbit flagged that filtering out remote sources could still produce `source: []` when a collection's sources are *all* remote. Compute the filtered local sources first and skip the collection entirely if nothing remains, so the invariant "if a collection appears in the preview manifest, it has at least one local source" holds for both the no-source case (e.g. the internal `info` collection) and the remote-only case.
|
Good catch by @coderabbitai — pushed cba6554 to also cover the remote-only case. The logic now computes
|
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 3413
The reuse of If you found this review helpful, would you consider giving us a shout-out on X? Thank you for using CodeRabbit! |
🔗 Linked issue
Resolves #3767 (and unblocks nuxt-content/nuxt-studio#425)
❓ Type of change
📚 Description
The internal
infocollection (created byresolveCollections()insrc/utils/collection.ts) hassource: undefined. WhenpreviewTemplateserialized this collection it producedsource: []in the preview manifest:undefined?.filter(...)→undefined, then the|| []fallback kicks in, so the info collection ends up with an emptysourcearray — which violates theResolvedCollectionSource[]contract (at least one source is expected) and crashes downstream consumers that readsource[0].includeandsource[0].prefix(most visiblynuxt-studio, see nuxt-content/nuxt-studio#425).This PR skips source-less collections entirely in the preview manifest, since they cannot be edited from the preview/studio UI anyway. It also simplifies the remote-collection filter to a straightforward
!source.repositorypredicate (the previous? undefined : collection.sourcepattern was hard to read and the branch that returnedcollection.sourcewas only truthy by accident).Before / After
For a Nuxt 4 project with
@nuxt/contentv3 plus any user-defined collection,/__preview.jsonpreviously contained:{ "info": { "source": [], "type": "data", ... }, "pages": { "source": [{ "include": "**", "prefix": "/", ... }], ... } }After this PR the
infokey is omitted entirely. User-visible collections are unaffected.📝 Checklist