refactor(init): move init logic to action pattern#845
Conversation
|
Claude finished @mttdnt's task in 3m 28s —— View job PR Review
ChangesetThis PR is tagged as a refactor, but the latest commit ( Issues1. if (dataset && opts.unattended) {
return {datasetName: dataset, userAction: 'none'}
}In unattended mode with 2. Inconsistency in Three code paths for unattended + projectId behave inconsistently:
The middle case throws even when a specific if (projects.length === 0 && unattended && !projectId) {
throw new InitError('No projects found for current user', 1)
}3. Missing test for the restored unattended behavior The commit |
This stack of pull requests is managed by Graphite. Learn more about stacking. |
📦 Bundle Stats —
|
| Metric | Value | vs main (e902217) | vs v6.2.1 |
|---|---|---|---|
| Internal (raw) | 2.1 KB | - | - |
| Internal (gzip) | 799 B | - | - |
| Bundled (raw) | 11.06 MB | - | +9.12 MB, +470.6% |
| Bundled (gzip) | 2.07 MB | - | +1.60 MB, +335.8% |
| Import time | 844ms | +0ms, +0.0% | +27ms, +3.3% |
bin:sanity
| Metric | Value | vs main (e902217) | vs v6.2.1 |
|---|---|---|---|
| Internal (raw) | 975 B | - | - |
| Internal (gzip) | 460 B | - | - |
| Bundled (raw) | 9.83 MB | - | +9.12 MB, +1286.7% |
| Bundled (gzip) | 1.77 MB | - | +1.60 MB, +940.0% |
| Import time | NaNs | - | NaNs, NaN% |
🗺️ 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 (e9022171) · v1.2.1 (npm)
| Metric | Value | vs main (e902217) | vs v1.2.1 |
|---|---|---|---|
| Internal (raw) | 92.2 KB | - | +3.9 KB, +4.4% |
| Internal (gzip) | 21.6 KB | - | +1.1 KB, +5.5% |
| Bundled (raw) | 21.64 MB | - | +9.08 MB, +72.3% |
| Bundled (gzip) | 3.43 MB | - | +1.58 MB, +85.9% |
| Import time | 790ms | +3ms, +0.4% | +39ms, +5.2% |
🗺️ 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.
Coverage Delta
Comparing 11 changed files against main @ Overall Coverage
|
📦 Bundle Stats —
|
| Metric | Value | vs main (9a7e204) |
|---|---|---|
| Internal (raw) | 2.1 KB | - |
| Internal (gzip) | 799 B | - |
| Bundled (raw) | 10.94 MB | - |
| Bundled (gzip) | 2.05 MB | - |
| Import time | 837ms | +5ms, +0.5% |
bin:sanity
| Metric | Value | vs main (9a7e204) |
|---|---|---|
| Internal (raw) | 975 B | - |
| Internal (gzip) | 460 B | - |
| Bundled (raw) | 9.84 MB | - |
| Bundled (gzip) | 1.77 MB | - |
| Import time | 2.01s | +20ms, +1.0% |
🗺️ 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 (9a7e2044)
| Metric | Value | vs main (9a7e204) |
|---|---|---|
| Internal (raw) | 93.1 KB | - |
| Internal (gzip) | 21.9 KB | - |
| Bundled (raw) | 21.62 MB | - |
| Bundled (gzip) | 3.42 MB | - |
| Import time | 811ms | +17ms, +2.2% |
🗺️ 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 (9a7e2044)
| Metric | Value | vs main (9a7e204) |
|---|---|---|
| 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.
Coverage Delta
Comparing 11 changed files against main @ Overall Coverage
|
Coverage Delta
Comparing 11 changed files against main @ Overall Coverage
|
Behavior present on main but lost when bundled-create was rebased (commits predate these fixes): - Pass --missing to dataset import - Allow --bare mode without --output-path in unattended mode - Default to "production" dataset in unattended mode without --dataset Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…d tests
- Restore configureAppProject trace calls dropped during extraction
(thread `trace` param into promptForAppTemplateSetup)
- Replace `throw new InitError('', 0)` with plain `return` on --env path
(it's a normal success path, not an error)
- Remove exitCode===0 special-case from command wrapper
- Add ConfigureAppProjectStep to telemetry union type
- Port 4 new test files from #845: flagsToInitOptions, initAction,
initError, init.command
- Update 2 existing tests: --env path no longer throws
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…d tests
- Restore configureAppProject trace calls dropped during extraction
(thread `trace` param into promptForAppTemplateSetup)
- Replace `throw new InitError('', 0)` with plain `return` on --env path
(it's a normal success path, not an error)
- Remove exitCode===0 special-case from command wrapper
- Add ConfigureAppProjectStep to telemetry union type
- Port 4 new test files from #845: flagsToInitOptions, initAction,
initError, init.command
- Update 2 existing tests: --env path no longer throws
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
#999) * refactor(cli): extract init command body into framework-agnostic initAction Moves ~1100 lines of logic out of the oclif InitCommand into actions/init/initAction.ts, leaving init.ts as a thin wrapper that maps oclif flags → InitOptions and catches InitError. Flow files (initApp, initStudio, initNextJs, scaffoldTemplate) now accept `options: InitOptions` instead of individual flag params, and throw InitError directly instead of receiving an `error` callback. Zero test assertion changes — all 14 init test files pass as-is. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(cli): clean up init telemetry types - Make `visibility` optional in `CreateOrSelectDatasetStep` (can be undefined in unattended mode) - Remove dead `ConfigureAppProjectStep` interface (no trace.log call exists for it) - Remove unnecessary `as 'private' | 'public'` cast now that the type accepts undefined Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback — restore telemetry, fix env path, add tests - Restore configureAppProject trace calls dropped during extraction (thread `trace` param into promptForAppTemplateSetup) - Replace `throw new InitError('', 0)` with plain `return` on --env path (it's a normal success path, not an error) - Remove exitCode===0 special-case from command wrapper - Add ConfigureAppProjectStep to telemetry union type - Port 4 new test files from #845: flagsToInitOptions, initAction, initError, init.command - Update 2 existing tests: --env path no longer throws Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(cli): close remaining oclif decoupling gaps in init flow files - bootstrapTemplate: make overwriteFiles/useTypeScript optional - initHelpers: use InitContext['output'] instead of Output - initNextJs: throw InitError instead of output.error(), pass options directly - initStudio: dynamic import for ImportDatasetCommand, use workDir over process.cwd() - initApp: use workDir over process.cwd() - scaffoldTemplate: remove as boolean casts and unnecessary try/catch Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback — clean up test names, static import, tighten useTypeScript type - Rename describe blocks to simpler names (mcpMode resolution, error handling) - Use static import for InitError instead of dynamic import - Make useTypeScript a required boolean since flagOrDefault always returns boolean Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: update selectTemplate tests for refactored options signature Tests from #1004 used the old flat-argument signature; wrap in options object to match the current selectTemplate interface. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(cli): split initAction.ts into plan/ and project/ modules Extract helper functions from the 1175-line initAction.ts into one-function-per-file modules under plan/ and project/ subdirectories. initAction.ts now contains only the main orchestrator, flag validation, and auth — down to ~300 lines. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: forward datasetDefault to app template dataset creation The refactor from class methods to standalone functions dropped the implicit this.flags['dataset-default'] read that getOrCreateDataset relied on. Thread datasetDefault through getProjectDetails → promptForAppTemplateSetup → getOrCreateDataset so --dataset-default applies to app templates again. Adds a regression test exercising the app template + --dataset-default code path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(cli): replace preferred-pm with local implementation (#984) * fix(cli): replace preferred-pm with local implementation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): address review feedback for preferredPm Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): detect pnpm-workspace.yaml in parent directory walk-up Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): normalize path separators for workspace glob matching on windows Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): continue workspace walk-up when inner workspace globs don't match When a nested package.json has a workspaces field whose globs don't match the target path, continue traversing parent directories instead of returning null. Also simplify error handling in detectFromNodeModules to swallow all read errors for best-effort detection. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): remove continue that caused infinite loop in workspace walk-up The continue statement skipped dir = path.dirname(dir) at the bottom of the while loop, causing an infinite loop when a workspace's globs didn't match the target path. Removing it lets the code fall through to the directory advancement naturally. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): skip chmod-based permission test on Windows chmod doesn't enforce read permissions on Windows, so the file remains readable and the test returns 'pnpm' instead of falling through to 'npm'. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): remove circular import and add malformed package.json test Address PR review feedback: inline DetectablePackageManager type to break circular dependency between preferredPm and packageManagerChoice, and add test covering malformed package.json handling in workspace walk-up. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ci: split e2e workflow into PR and scheduled runs (#995) Move registry-mode e2e tests and Slack failure notifications into a dedicated hourly scheduled workflow. The PR/push workflow now only runs in pack mode. Post-release dispatch in release.yml updated to target the new scheduled workflow with `latest` instead of a specific version. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(cli): replace default namespace imports with named imports (#993) Use named imports for semver, nock, and typescript to resolve 167 import-x/no-named-as-default-member lint warnings. Also replace one `as any` with a proper type cast. CJS modules (json5, dotenv, tar-fs, tar-stream) are left unchanged since they don't support named ESM imports at runtime. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): default to TypeScript in unattended mode for sanity init (#1004) * fix(cli): default to TypeScript in unattended mode for sanity init When running sanity init in unattended mode (non-interactive terminal or --yes flag), the CLI now defaults to TypeScript when --typescript or --no-typescript is not explicitly provided, matching the interactive prompt default. Uses the existing flagOrDefault/shouldPrompt helpers already used by initNextJs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update auto-generated changeset for PR #1004 --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com> * refactor(cli): extract init command into framework-agnostic initAction (#999) * refactor(cli): extract init command body into framework-agnostic initAction Moves ~1100 lines of logic out of the oclif InitCommand into actions/init/initAction.ts, leaving init.ts as a thin wrapper that maps oclif flags → InitOptions and catches InitError. Flow files (initApp, initStudio, initNextJs, scaffoldTemplate) now accept `options: InitOptions` instead of individual flag params, and throw InitError directly instead of receiving an `error` callback. Zero test assertion changes — all 14 init test files pass as-is. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(cli): clean up init telemetry types - Make `visibility` optional in `CreateOrSelectDatasetStep` (can be undefined in unattended mode) - Remove dead `ConfigureAppProjectStep` interface (no trace.log call exists for it) - Remove unnecessary `as 'private' | 'public'` cast now that the type accepts undefined Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback — restore telemetry, fix env path, add tests - Restore configureAppProject trace calls dropped during extraction (thread `trace` param into promptForAppTemplateSetup) - Replace `throw new InitError('', 0)` with plain `return` on --env path (it's a normal success path, not an error) - Remove exitCode===0 special-case from command wrapper - Add ConfigureAppProjectStep to telemetry union type - Port 4 new test files from #845: flagsToInitOptions, initAction, initError, init.command - Update 2 existing tests: --env path no longer throws Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(cli): close remaining oclif decoupling gaps in init flow files - bootstrapTemplate: make overwriteFiles/useTypeScript optional - initHelpers: use InitContext['output'] instead of Output - initNextJs: throw InitError instead of output.error(), pass options directly - initStudio: dynamic import for ImportDatasetCommand, use workDir over process.cwd() - initApp: use workDir over process.cwd() - scaffoldTemplate: remove as boolean casts and unnecessary try/catch Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback — clean up test names, static import, tighten useTypeScript type - Rename describe blocks to simpler names (mcpMode resolution, error handling) - Use static import for InitError instead of dynamic import - Make useTypeScript a required boolean since flagOrDefault always returns boolean Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: update selectTemplate tests for refactored options signature Tests from #1004 used the old flat-argument signature; wrap in options object to match the current selectTemplate interface. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(cli): split initAction.ts into plan/ and project/ modules Extract helper functions from the 1175-line initAction.ts into one-function-per-file modules under plan/ and project/ subdirectories. initAction.ts now contains only the main orchestrator, flag validation, and auth — down to ~300 lines. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: forward datasetDefault to app template dataset creation The refactor from class methods to standalone functions dropped the implicit this.flags['dataset-default'] read that getOrCreateDataset relied on. Thread datasetDefault through getProjectDetails → promptForAppTemplateSetup → getOrCreateDataset so --dataset-default applies to app templates again. Adds a regression test exercising the app template + --dataset-default code path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Binoy Patel <me@binoy.io> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com> Co-authored-by: Matthew Dent <mttdnt@gmail.com>
* fix(cli): replace preferred-pm with local implementation (#984) * fix(cli): replace preferred-pm with local implementation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): address review feedback for preferredPm Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): detect pnpm-workspace.yaml in parent directory walk-up Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): normalize path separators for workspace glob matching on windows Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): continue workspace walk-up when inner workspace globs don't match When a nested package.json has a workspaces field whose globs don't match the target path, continue traversing parent directories instead of returning null. Also simplify error handling in detectFromNodeModules to swallow all read errors for best-effort detection. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): remove continue that caused infinite loop in workspace walk-up The continue statement skipped dir = path.dirname(dir) at the bottom of the while loop, causing an infinite loop when a workspace's globs didn't match the target path. Removing it lets the code fall through to the directory advancement naturally. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): skip chmod-based permission test on Windows chmod doesn't enforce read permissions on Windows, so the file remains readable and the test returns 'pnpm' instead of falling through to 'npm'. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): remove circular import and add malformed package.json test Address PR review feedback: inline DetectablePackageManager type to break circular dependency between preferredPm and packageManagerChoice, and add test covering malformed package.json handling in workspace walk-up. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ci: split e2e workflow into PR and scheduled runs (#995) Move registry-mode e2e tests and Slack failure notifications into a dedicated hourly scheduled workflow. The PR/push workflow now only runs in pack mode. Post-release dispatch in release.yml updated to target the new scheduled workflow with `latest` instead of a specific version. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(cli): replace default namespace imports with named imports (#993) Use named imports for semver, nock, and typescript to resolve 167 import-x/no-named-as-default-member lint warnings. Also replace one `as any` with a proper type cast. CJS modules (json5, dotenv, tar-fs, tar-stream) are left unchanged since they don't support named ESM imports at runtime. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): default to TypeScript in unattended mode for sanity init (#1004) * fix(cli): default to TypeScript in unattended mode for sanity init When running sanity init in unattended mode (non-interactive terminal or --yes flag), the CLI now defaults to TypeScript when --typescript or --no-typescript is not explicitly provided, matching the interactive prompt default. Uses the existing flagOrDefault/shouldPrompt helpers already used by initNextJs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update auto-generated changeset for PR #1004 --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com> * refactor(cli): extract init command into framework-agnostic initAction (#999) * refactor(cli): extract init command body into framework-agnostic initAction Moves ~1100 lines of logic out of the oclif InitCommand into actions/init/initAction.ts, leaving init.ts as a thin wrapper that maps oclif flags → InitOptions and catches InitError. Flow files (initApp, initStudio, initNextJs, scaffoldTemplate) now accept `options: InitOptions` instead of individual flag params, and throw InitError directly instead of receiving an `error` callback. Zero test assertion changes — all 14 init test files pass as-is. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(cli): clean up init telemetry types - Make `visibility` optional in `CreateOrSelectDatasetStep` (can be undefined in unattended mode) - Remove dead `ConfigureAppProjectStep` interface (no trace.log call exists for it) - Remove unnecessary `as 'private' | 'public'` cast now that the type accepts undefined Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback — restore telemetry, fix env path, add tests - Restore configureAppProject trace calls dropped during extraction (thread `trace` param into promptForAppTemplateSetup) - Replace `throw new InitError('', 0)` with plain `return` on --env path (it's a normal success path, not an error) - Remove exitCode===0 special-case from command wrapper - Add ConfigureAppProjectStep to telemetry union type - Port 4 new test files from #845: flagsToInitOptions, initAction, initError, init.command - Update 2 existing tests: --env path no longer throws Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(cli): close remaining oclif decoupling gaps in init flow files - bootstrapTemplate: make overwriteFiles/useTypeScript optional - initHelpers: use InitContext['output'] instead of Output - initNextJs: throw InitError instead of output.error(), pass options directly - initStudio: dynamic import for ImportDatasetCommand, use workDir over process.cwd() - initApp: use workDir over process.cwd() - scaffoldTemplate: remove as boolean casts and unnecessary try/catch Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback — clean up test names, static import, tighten useTypeScript type - Rename describe blocks to simpler names (mcpMode resolution, error handling) - Use static import for InitError instead of dynamic import - Make useTypeScript a required boolean since flagOrDefault always returns boolean Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: update selectTemplate tests for refactored options signature Tests from #1004 used the old flat-argument signature; wrap in options object to match the current selectTemplate interface. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(cli): split initAction.ts into plan/ and project/ modules Extract helper functions from the 1175-line initAction.ts into one-function-per-file modules under plan/ and project/ subdirectories. initAction.ts now contains only the main orchestrator, flag validation, and auth — down to ~300 lines. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: forward datasetDefault to app template dataset creation The refactor from class methods to standalone functions dropped the implicit this.flags['dataset-default'] read that getOrCreateDataset relied on. Thread datasetDefault through getProjectDetails → promptForAppTemplateSetup → getOrCreateDataset so --dataset-default applies to app templates again. Adds a regression test exercising the app template + --dataset-default code path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Binoy Patel <me@binoy.io> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com> Co-authored-by: Matthew Dent <mttdnt@gmail.com>

refactor(init): move init logic to action pattern (#748)
refactor(init): split init flows into separate functions (#753)