Add Sanity Plugin#71
Conversation
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 4 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Repository UI (base), Organization UI (inherited) Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughAdds a Sanity v1 plugin with token configuration, API-backed data streams, Project/Dataset/Member indexing, source scopes, default dashboards, authentication validation, and setup documentation. ChangesSanity v1 integration
Sequence Diagram(s)sequenceDiagram
participant PluginConfiguration
participant DataStreams
participant SanityAPI
PluginConfiguration->>DataStreams: Provide admin and project token settings
DataStreams->>SanityAPI: Request projects, datasets, stats, queries, and members
SanityAPI-->>DataStreams: Return project and dataset responses
DataStreams-->>PluginConfiguration: Expose filtered, mapped, and derived fields
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Comment |
d450360 to
b255f92
Compare
The Custom GROQ Query tile (and the stream's default query) previously fetched an arbitrary unordered slice of 20 documents, which surfaced whatever happened to come back first — including internal system.group documents. Order by _updatedAt descending before slicing and exclude system documents (ids under the "_." path) so the starting query shows the 20 most recently updated content documents, a far more useful default for content editors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The datasetStats stream returned Sanity's raw value/limit pairs, which made it hard to see at a glance how close a dataset is to its plan limits — the numbers needed manual arithmetic and the byte counts were unformatted. A post-request script now computes percent-of-limit columns for documents, fields, JSON size and releases (null when the limit is 0, which Sanity uses to mean "no limit"), stamps each row with the dataset's object name so multi-dataset tiles can tell rows apart, and explicit metadata formats the key columns as percentages and bytes. The Dataset dashboard gains a stats row built on these columns: three gauges (documents, fields and JSON size as % of limit) and a document count scalar. Verified against a real dataset sitting at 98% of its fields limit, which is exactly the situation these tiles exist to surface. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Projects dashboard was doing two jobs at once: it listed every project while its other tiles were scoped to a single project via the dashboard variable, which made the page read oddly. A new Overview dashboard now owns the org-wide view — project, dataset and document counts, total JSON stored, the all-projects blocks list, documents by dataset, and a per-dataset limit-usage table sorted so the datasets closest to a plan limit surface first. The layout follows the KPI-row- then-charts shape used by other plugins' overview dashboards. The Projects dashboard becomes a pure per-project drilldown (details, datasets, members) and Overview is first in the manifest so it's the landing page. Dataset-derived tiles only cover projects with a configured per-project token, since datasets of untokened projects are never imported as objects. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
When a per-project API token was missing or wrong, token-dependent
tiles surfaced Sanity's raw response ("Invalid authorization header -
please double-check token"), which says nothing about which project is
affected or how to fix it. The four content streams now carry an
errorHandling script that names the project and points at the Project
API tokens setting when no token is configured for it.
The token-presence check is resolved at request time via template
substitution, since the script sandbox itself cannot read the
data source config. When a token is configured and the request still
fails, the script falls back to Sanity's own error message (so GROQ
syntax errors etc. come through verbatim) and then to the HTTP status.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Previously every project the admin token could see was imported, so users could scope dashboards to projects the plugin had no content token for — objects that could never show dataset, member or content data. The listProjects stream (which backs the project import and config validation) now filters the management API response down to the projects configured under Project API tokens, so everything in the graph is actually queryable. Dropping the admin token entirely was considered, deriving projects purely from the configured token list, but the admin listing is what supplies project display names and creation dates, so it stays. The filter works because the post-request script context exposes the data source config (token values encrypted, project-ID keys readable). With untokened projects gone from the graph, the "requires a token" tile captions and Overview caveats added earlier no longer describe a reachable state and are removed; the Overview projects tiles instead note that only tokened projects are indexed, since the count no longer matches the organization's full project list. Existing untokened Project objects are pruned on the next import. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Overview dashboard's Projects tile was a blocks grid backed by the (now token-filtered) listProjects stream, so it only ever showed projects that were already fully configured — there was no way to see, at a glance, which of the organization's other projects still needed a token added. A new allProjects stream calls the same admin-token project listing but without the import-time token filter, and tags each row with a tokenStatus of "configured" or "missing" by checking it against the configured Project API tokens. The Overview Projects tile is now a table over this stream with a state-shaped Token Status column (a green/red health dot) alongside the project's ID, so a missing token is immediately visible and actionable — the ID is what you need to add it. listProjects keeps its existing filtered behaviour for indexing and config validation; duplicating the projects API call in a second stream was the simplest way to get an unfiltered view without weakening that filter or threading a "show all vs indexed only" flag through it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@plugins/Sanity/v1/dataStreams/datasets.json`:
- Around line 67-80: Move the uid and displayName transformations from the
computed valueExpression entries in datasets.json into the existing map in
datasets.js, deriving them from projectId, datasetId, and projectName. Declare
both fields as ordinary non-computed metadata fields while preserving their
names, string shapes, and hidden visibility.
- Around line 15-18: Escape the interpolated project name in the error message
within the errorHandling script so names containing apostrophes cannot break the
generated JavaScript string. Update the object.name insertion to use a
JSON-encoded value while preserving the existing no-token message and API error
handling behavior.
In `@plugins/Sanity/v1/dataStreams/listProjects.json`:
- Around line 40-42: Update the createdAt field definition in the project list
schema to use shape "date" instead of "string", allowing Sanity date-time values
to be parsed as dates while preserving its existing name and displayName.
In `@plugins/Sanity/v1/defaultContent/dataset.dash.json`:
- Around line 56-68: Add a concise explanatory description to the “Document Type
Counts” tile’s currently empty description field, documenting that the query
selects one representative document for each _type and counts matching
documents. Leave the query and surrounding data-stream configuration unchanged.
In `@plugins/Sanity/v1/defaultContent/overview.dash.json`:
- Line 4: Set the dashboard-level timeframe to "none" in
plugins/Sanity/v1/defaultContent/overview.dash.json (line 4),
plugins/Sanity/v1/defaultContent/projects.dash.json (line 4), and
plugins/Sanity/v1/defaultContent/dataset.dash.json (line 4), matching the
timeframe configured by every tile.
- Around line 20-46: Differentiate the duplicate dashboard tile titles by
renaming the scalar KPI using listProjects to “Monitored Projects” and the
org-wide table using allProjects to “All Projects”; update both title fields
while leaving their visualisations and data sources unchanged.
- Line 178: Replace the duplicated tile GUID in both
plugins/Sanity/v1/defaultContent/overview.dash.json:178-178 and
plugins/Sanity/v1/defaultContent/projects.dash.json:12-12 with distinct, newly
generated GUIDs, ensuring each tile has a unique "i" identifier.
In `@plugins/Sanity/v1/docs/README.md`:
- Around line 9-14: Update the Admin API token instructions in the README to
describe only organization-level or personal admin tokens with permission to
list projects; remove the project-token option and duplicated project-token
creation steps. Keep project-scoped token creation documented exclusively in the
Project API tokens section, and ensure the admin-token guidance matches the
listProjects authorization requirement.
In `@plugins/Sanity/v1/indexDefinitions/default.json`:
- Line 50: Update the membership identity mapping in the default index
definition so the ID combines sanityUserId with the membership resourceId,
rather than using sanityUserId alone. Ensure the composite identity is derived
and mapped consistently so the same user remains distinct across Projects.
🪄 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: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: 34d0939a-8f9c-4be7-913c-fd15ddd711fb
⛔ Files ignored due to path filters (1)
plugins/Sanity/v1/icon.svgis excluded by!**/*.svg
📒 Files selected for processing (22)
plugins/Sanity/v1/configValidation.jsonplugins/Sanity/v1/custom_types.jsonplugins/Sanity/v1/dataStreams/allProjects.jsonplugins/Sanity/v1/dataStreams/customQuery.jsonplugins/Sanity/v1/dataStreams/datasetStats.jsonplugins/Sanity/v1/dataStreams/datasets.jsonplugins/Sanity/v1/dataStreams/listProjects.jsonplugins/Sanity/v1/dataStreams/members.jsonplugins/Sanity/v1/dataStreams/scripts/allProjects.jsplugins/Sanity/v1/dataStreams/scripts/datasetStats.jsplugins/Sanity/v1/dataStreams/scripts/datasets.jsplugins/Sanity/v1/dataStreams/scripts/listProjects.jsplugins/Sanity/v1/dataStreams/scripts/members.jsplugins/Sanity/v1/defaultContent/dataset.dash.jsonplugins/Sanity/v1/defaultContent/manifest.jsonplugins/Sanity/v1/defaultContent/overview.dash.jsonplugins/Sanity/v1/defaultContent/projects.dash.jsonplugins/Sanity/v1/defaultContent/scopes.jsonplugins/Sanity/v1/docs/README.mdplugins/Sanity/v1/indexDefinitions/default.jsonplugins/Sanity/v1/metadata.jsonplugins/Sanity/v1/ui.json
The no-token error script interpolates {{object.name}} directly into
a single-quoted JavaScript string, so a project name containing an
apostrophe would break the generated script. JSON-encode the name at
template time instead, in both the datasets and members streams.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Both fields were computed metadata using mustache-style value expressions, but the coding guidelines prefer row transformations in the post-request script over value expressions for performance. The script already derives datasetId, projectName and projectId, so uid and displayName move alongside them and become plain metadata fields. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sanity returns createdAt as an ISO date-time, but the string shape prevented date inference. The datasets stream already declares its createdAt as a date; this makes the projects stream consistent. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The GROQ query behind the Document Type Counts tile samples one representative document per _type and counts matches, which is not obvious at a glance, and the tile description was empty. Explain the approach so dashboard maintainers don't have to re-derive it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All three dashboards declared a last24hours timeframe while every tile pins its own timeframe to none, so the dashboard time selector had no effect anywhere — an unadjusted boilerplate default. Setting the dashboard level to none reflects what the tiles actually use. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The overview dashboard had two tiles both titled "Projects": a KPI counting only the projects with a configured API token, and a table listing every project in the organization. Renaming them to "Monitored Projects" and "All Projects" makes the scope of each tile clear at a glance. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The overview Projects table tile and the Project Details tile on the projects dashboard shared the same "i" identifier, a copy/paste artifact. Both get freshly generated GUIDs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Admin API token section offered a project-scoped token as an option and then gave project-token creation steps, duplicating the Project API tokens section. A project token cannot list all the projects in an organization, so following those steps would break project listing. The steps now match the ui.json help text: use an organization token or a personal token from an admin account. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Member objects were indexed by sanityUserId alone, so a user with access to several projects collapsed into a single object and only one project's membership data (projectId, roles) survived the merge. Objects are now keyed by a composite of the user id and the project being imported, keeping each membership distinct. The project id comes from the import scope object rather than the memberships array so the id stays stable even if a membership entry is missing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@plugins/Sanity/v1/dataStreams/scripts/members.js`:
- Around line 5-12: Update the member mapping around the memberships handling to
select the membership whose resourceId matches object.rawId before indexing.
Normalize each user to that project’s membership and derive roles only from the
selected membership, rather than retaining all memberships or flattening their
roles, while preserving the membershipId construction.
🪄 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: Repository UI (base), Organization UI (inherited)
Review profile: ASSERTIVE
Plan: Pro
Run ID: 5eea1abf-fee3-407b-b063-4ba2b9149651
📒 Files selected for processing (10)
plugins/Sanity/v1/dataStreams/datasets.jsonplugins/Sanity/v1/dataStreams/listProjects.jsonplugins/Sanity/v1/dataStreams/members.jsonplugins/Sanity/v1/dataStreams/scripts/datasets.jsplugins/Sanity/v1/dataStreams/scripts/members.jsplugins/Sanity/v1/defaultContent/dataset.dash.jsonplugins/Sanity/v1/defaultContent/overview.dash.jsonplugins/Sanity/v1/defaultContent/projects.dash.jsonplugins/Sanity/v1/docs/README.mdplugins/Sanity/v1/indexDefinitions/default.json
The Access API returns each user's memberships across resources, but the members stream flattened roleNames over the whole array and the metadata read memberships.0.resourceId for the project. A user who belongs to several projects could therefore show another project's id and a merged role list. Each row now keeps only the membership whose resourceId matches the project being imported and derives its roles from that membership alone. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The datasets and members error handlers were single-line inline strings in the stream JSON, which is hard to read and edit. The deploy pipeline inlines any bare .js reference under dataStreams/scripts/ back into the config (the same mechanism postRequestScript uses, and the errorHandling/ folder the platform's own export produces), so the scripts now live as formatted files in scripts/errorHandling/ and the JSON just references them. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🧩 Plugin PR Summary📦 Modified Plugins
📋 Results
🔍 Validation Details✅
|
🔌 Plugin overview
🖼️ Plugin screenshots
Plugin configuration
Default dashboards
🧪 Testing
schemaVersion2.1) viasquaredup validate.listProjectsconfig-validation step against a live Sanity organization.Projectobjects, filtered to only those with a configured content token (verified: 13 visible projects reduced to the 3 actually tokened).errorHandling) when a project's token is invalid, instead of Sanity's raw auth error.Overview,Projects,Dataset) and that their scoped tiles resolve correctly for a tokened project/dataset._typein GROQ; on very large datasets this can be slow.📚 Checklist
Summary by CodeRabbit