Skip to content

refactor(projects:create): usability improvements#945

Draft
mttdnt wants to merge 6 commits intomainfrom
projects-create-usability
Draft

refactor(projects:create): usability improvements#945
mttdnt wants to merge 6 commits intomainfrom
projects-create-usability

Conversation

@mttdnt
Copy link
Copy Markdown
Contributor

@mttdnt mttdnt commented Apr 14, 2026

Summary

  • --yes requires project name — no more silent "My Sanity Project" in CI
  • --dataset uses shared getDatasetFlag — consistent with other commands
  • --dataset-visibility declares dependsOn: ['dataset'] — oclif enforces the relationship
  • JSON output is complete — includes org, dataset, manageUrl, and warnings array for partial failures
  • Org resolution decoupled — composes listOrganizationsresolveOrganizationByIdpromptForOrganization instead of monolithic getOrganization action. Spinner lives in the command.

Test plan

  • sanity projects create interactive flow works end-to-end
  • sanity projects create "My Project" --yes --organization=<org> works
  • sanity projects create "My Project" --json returns complete JSON
  • --dataset-visibility without --dataset errors
  • --yes without project name errors

🤖 Generated with Claude Code

@claude
Copy link
Copy Markdown

claude Bot commented Apr 14, 2026

Claude finished @mttdnt's task in 2m 24s —— View job


PR Review

  • Read repo guidelines and changed files
  • Check for changeset
  • Post review findings

Issues

1. Missing changeset

This PR changes user-facing behavior in packages/:

  • --yes now errors without a project name (behavior change for existing CI scripts that rely on the silent default)
  • --dataset gains a -d shorthand via getDatasetFlag
  • JSON output adds manageUrl, organizationName, organizationId, and warnings fields

A patch changeset is required. The existing .changeset/ entries are from unrelated commits.


2. --yes flag description is now wrongcreate.ts:88

description:
  'Skip prompts and use defaults (project: "My Sanity Project", dataset: production, visibility: public)',

The description still mentions "My Sanity Project" as the default, but --yes without a project name now errors. The description should reflect the new behavior, e.g.: 'Skip prompts and use defaults. Requires a project name argument.'

Fix this →


3. listDatasets is called unconditionally in handleDatasetCreationcreate.ts:171

const existingDatasets = await listDatasets(projectId)       // always called
const existingDatasetNames = existingDatasets.map(...)

if (!datasetName && !this.isUnattended()) {                  // only needed here
  // ...may call promptForDatasetName({}, existingDatasetNames)
}

existingDatasetNames is only used inside the interactive block. When --dataset is not set and the command is in unattended mode, this fires an unnecessary API request. Move the listDatasets call inside the interactive block:

if (!datasetName && !this.isUnattended()) {
  const existingDatasets = await listDatasets(projectId)
  const existingDatasetNames = existingDatasets.map((ds) => ds.name)
  // ... rest of interactive flow
}

Fix this →


4. PROJECTS-CREATE.md should not be committed

The file at repo root is a design artifact / usability study. It references implementation details, describes old code (e.g. the getOrganization 6-module pipeline that was just deleted), and doesn't belong in the committed codebase. Remove it before merging.

Fix this →

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 14, 2026

📦 Bundle Stats — @sanity/cli

Compared against main (82dbcc60)

@sanity/cli

Metric Value vs main (82dbcc6)
Internal (raw) 2.1 KB -
Internal (gzip) 799 B -
Bundled (raw) 10.94 MB -
Bundled (gzip) 2.05 MB -
Import time 826ms -1ms, -0.2%

bin:sanity

Metric Value vs main (82dbcc6)
Internal (raw) 975 B -
Internal (gzip) 460 B -
Bundled (raw) 9.84 MB -
Bundled (gzip) 1.77 MB -
Import time 1.97s +15ms, +0.8%

🗺️ View treemap · Artifacts

Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

📦 Bundle Stats — @sanity/cli-core

Compared against main (82dbcc60)

Metric Value vs main (82dbcc6)
Internal (raw) 93.8 KB -
Internal (gzip) 21.9 KB -
Bundled (raw) 21.62 MB -
Bundled (gzip) 3.42 MB -
Import time 788ms +9ms, +1.1%

🗺️ View treemap · Artifacts

Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

📦 Bundle Stats — create-sanity

Compared against main (82dbcc60)

Metric Value vs main (82dbcc6)
Internal (raw) 976 B -
Internal (gzip) 507 B -
Bundled (raw) 50.7 KB -
Bundled (gzip) 12.6 KB -
Import time ❌ ChildProcess denied: node -
Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 14, 2026

Coverage Delta

File Statements
packages/@sanity/cli/src/actions/organizations/resolveOrganizationById.ts 100.0% (new)
packages/@sanity/cli/src/commands/datasets/create.ts 100.0% (±0%)
packages/@sanity/cli/src/commands/projects/create.ts 95.7% (- 2.6%)
packages/@sanity/cli/src/prompts/promptForOrganization.ts 100.0% (new)

Comparing 4 changed files against main @ e4d8427b39af8c8b1a7672e3bb943fc8d7e75297

Overall Coverage

Metric Coverage
Statements 83.0% (- 0.0%)
Branches 73.0% (- 0.1%)
Functions 82.8% (- 0.0%)
Lines 83.4% (- 0.0%)

mttdnt and others added 5 commits April 16, 2026 10:37
…imitives

Extract organization resolution from the monolithic getOrganization action
into reusable primitives that projects:create composes directly:

- resolveOrganizationById: pure function for --organization flag lookup
- promptForOrganization: prompt-layer org selection with grant-aware display
- promptForNewOrganization: create-first-org flow

This moves spinner/UI concerns into the command and keeps actions focused
on business logic. Reverts getOrganization.ts and init.ts to main state
so this change is scoped to projects:create only.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
No callers remain — init imports the individual pieces directly,
and projects:create now composes primitives.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move resolveOrganizationById inside the spinner try/catch so the
spinner shows a failure mark instead of a false checkmark when the
requested organization is not found.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@mttdnt mttdnt force-pushed the projects-create-usability branch from 4414b18 to 8466e10 Compare April 16, 2026 14:38
…itives

Both `datasets create` and `projects create` now compose
`determineDatasetAclMode` + `createDataset` service directly instead
of going through the bundled action. Spinners and success logs live
in the commands.

Also fixes `projects create` not passing `forcePublic` when user
picks default config — visibility prompt was shown regardless.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

1 participant