feat(cross-dataset-duplicator): add migrationFilters config option#1229
feat(cross-dataset-duplicator): add migrationFilters config option#1229stipsan wants to merge 2 commits into
Conversation
Port of sanity-io/cross-dataset-duplicator#53 by @Nathan-Heller. Adds a `migrationFilters` plugin config option to restrict which Datasets and Projects are allowed as Migration destinations for a given source Dataset. When a target omits `projectId`, only Workspaces in the same Project as the source are allowed. This helps prevent accidental duplication to the wrong Dataset.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: 48bbfdd The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Pull request overview
Adds a new migrationFilters configuration option to @sanity/cross-dataset-duplicator to allow-list valid migration destinations per source dataset (optionally across projects), and wires this into the destination UI with unit-tested decision logic.
Changes:
- Introduces new public types (
MigrationTarget,MigrationFilter) and addsmigrationFilters?to plugin config. - Implements
isAllowedMigrationTarget()helper (with unit tests) and uses it to disable disallowed workspace destinations in the duplicator UI. - Documents the new option in the README and adds a changeset for a minor release.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| plugins/@sanity/cross-dataset-duplicator/src/types/index.ts | Adds public types for migration filtering and exposes migrationFilters on PluginConfig. |
| plugins/@sanity/cross-dataset-duplicator/src/helpers/constants.ts | Extends default config with migrationFilters: []. |
| plugins/@sanity/cross-dataset-duplicator/src/helpers/migrationFilters.ts | Adds the allow/deny decision helper for migration targets. |
| plugins/@sanity/cross-dataset-duplicator/src/helpers/migrationFilters.test.ts | Adds unit tests covering migration filter behaviors and edge cases. |
| plugins/@sanity/cross-dataset-duplicator/src/components/Duplicator.tsx | Applies migration filtering to workspace options and adjusts “current workspace” labeling/source selection. |
| plugins/@sanity/cross-dataset-duplicator/README.md | Documents migrationFilters and updates future ideas list. |
| .changeset/cross-dataset-duplicator-migration-filters.md | Declares a minor version bump and credits the original author. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <Select readOnly value={currentWorkspace?.name}> | ||
| {workspacesOptions | ||
| .filter((space) => space.disabled) | ||
| .map((space) => ( |
| <Flex gap={3}> | ||
| <Stack style={{flex: 1}} gap={3}> | ||
| <Label>Duplicate from</Label> | ||
| <Select readOnly value={workspacesOptions.find((space) => space.disabled)?.name}> | ||
| <Select readOnly value={currentWorkspace?.name}> |
Ports sanity-io/cross-dataset-duplicator#53 by @Nathan-Heller into the monorepo.
What
Adds a new optional
migrationFiltersplugin config option to@sanity/cross-dataset-duplicator. It restricts which Datasets (and Projects) are allowed as Migration destinations for a given source Dataset, preventing accidental duplication to the wrong Dataset (e.g. by mistakenly selecting the wrong target).projectId, only Workspaces in the same Project as the source are allowed.projectId, that Project must match (enables cross-project allow-listing).Walkthrough
Demo (filter allows only the
testdataset): theTo Destinationdropdown offers the allowedCross Dataset Duplicator Targetand the Duplicate button updates accordingly.cross_dataset_duplicator_migration_filters_demo.mp4
The three screenshots below were captured with a small temporary debug panel (not committed) that printed each Workspace's computed
disabledstate, so the native<select>disabled states could be verified reliably end-to-end (config → context → component):No filter →
testtarget enabled:No migrationFilters: test target enabled
Filter excludes
test(targets: [{dataset: 'staging'}]) →testtarget disabled:Filter excludes test: test target disabled
Filter allows
test(targets: [{dataset: 'test'}]) →testtarget enabled again:Filter allows test: test target enabled
Changes
src/types/index.ts— new exported@publictypesMigrationTargetandMigrationFilter; addedmigrationFilters?toPluginConfig.src/helpers/constants.ts— addedmigrationFilters: []toDEFAULT_CONFIG.src/helpers/migrationFilters.ts— new pureisAllowedMigrationTarget()helper holding the decision logic (extracted so it is unit-testable).src/components/Duplicator.tsx— disables disallowed destinations, derives the source ascurrentWorkspace, and only labels the actual current Workspace as(Current).README.md— documents the option and removes the now-implemented "allowed migrations" future-idea bullet.src/helpers/migrationFilters.test.ts— unit tests covering all branches.Note on the port
The monorepo's
Duplicator.tsxhad already diverged from upstream, so the change was adapted rather than applied verbatim. The upstream PR's same-project fallback (|| workspace.projectId === sourceProjectId) was applied only when a target omitsprojectId, matching the PR's own inline comment and second commit message ("when filter is configured and projectId is omitted, limit targets to those in the same project"). The behaviour is otherwise identical.Testing
pnpm formatpnpm lintpnpm buildpnpm test run(895 tests; 10 new migration-filter unit tests)pnpm knip(only pre-existing@sanity/visioncatalog warning /@types/nodemonhint)Crediting
@Nathan-Heller(git commit --author).author: @Nathan-Hellerso the release changelog credits the original author.To show artifacts inline, enable in settings.