refactor(init): move init logic to action pattern#748
refactor(init): move init logic to action pattern#748rexxars wants to merge 13 commits intobundled-createfrom
Conversation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move all business logic from the oclif InitCommand class into a pure initAction(options, context) function. InitCommand becomes a thin wrapper that parses flags and delegates. This enables the standalone create-sanity bundling planned in Phase 3. - Created initAction.ts with all extracted private methods as module-level functions - Added argType and reconfigure fields to InitOptions for argument and deprecated flag validation - Updated flagsToInitOptions to accept oclif args parameter - Made bootstrapTemplate accept optional overwriteFiles and useTypeScript to match pre-existing runtime behavior - InitCommand.run() now catches InitError and translates to oclif error/exit calls Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use dynamic import for ImportDatasetCommand to avoid pulling oclif into the initAction bundle - Replace process.cwd() with workDir from context in two spots - Fix JSDoc brace escaping in initError.ts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 3 focused tests that call initAction() directly with plain objects, validating the extraction works standalone without going through oclif. This provides a foundation for the future create-sanity entry point. Tests cover: - Deprecated reconfigure flag throws InitError - Bare mode outputs project details and returns cleanly - Unauthenticated unattended mode throws InitError Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The ImportDatasetCommand dynamic import is deliberate to keep initAction decoupled from oclif. Will be replaced with npx spawn in Phase 3. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Claude finished @rexxars's task in 3m 13s —— View job Code Review
1.
Additionally, Fix: add 2.
const {ImportDatasetCommand} = await import('../../commands/datasets/import.js')
await ImportDatasetCommand.run([...], {root: outputPath})The stated goal of this refactor is to decouple 3. Silent
Consider throwing when the project isn't found in unattended mode: if (!proj) {
throw new InitError(
`Given project ID (${projectId}) not found, or you do not have access to it`,
1,
)
}The existing catch block at lines 806-821 already handles the case where the API call itself fails, so this wouldn't regress offline/error-tolerant scenarios. |
Coverage Delta
Comparing 6 changed files against main @ Overall Coverage
|
- Wrap getCliUser() in try-catch after login, re-throw as InitError - Replace throw-as-control-flow (InitError with exitCode 0) with plain return - both the --env path and doInitNextJs now return normally instead of using exceptions for successful early exits - Fix missing .js extension on type-only import in types.ts - Remove dead exitCode === 0 handling from InitCommand Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add trace.complete() to all early-return paths (bare mode, Next.js init, env-only mode) so telemetry is not silently dropped - Add explicit return undefined in verifyCoupon/verifyPlan when falling through to default plan, instead of implicit undefined - Add init.command.test.ts covering mcpMode computation and error handling in InitCommand.run(), restoring 100% coverage Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The visibility field is `'private' | 'public' | undefined` but was cast to `'private' | 'public'`, silently hiding the undefined case. Make the telemetry type optional to match reality and drop the cast. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove no-op try/catch around bootstrapTemplate that only re-threw - Add missing bun case for next-sanity@11 installation in Next.js flow Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace redundant detectedFramework.slug check with existing isNextJs - Extract error message properly in CORS origin error to avoid [object Object] Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Description
Note
This is a PR that goes into the
bundled-createbranch - notmain. We want to do a series of proper tests as these changes are rather large. And so we need to do a full alpha release to try this out, but I still want to get your opinions and feedback on the refactor one step at a time. This is part 1 of a largerinit/create-sanityrefactor - the goal being to ship a much smallercreate-sanitymodule, while still allowingsanity initto work as before.This moves the init command logic out of the actual oclif "command" and into an action. The rationale behind this is two-fold:
create-sanitycommand not rely on@sanity/cliin its entirety, but instead ship only the parts that we need for theinitportion. By relying on oclif internals, this is harder to do: ideally (sinceinitis a single command) we could not rely on the entire oclif framework for it but instead parse args and call the action logic directly, then post create we have the entire CLI available for use. For this to work, we need the init logic "core" to be tree-shakeable and use the minimal amount of dependencies for those operations, so we can bundle it all into one file and shipcreate-sanitywithout dependencies.What to review
This is quite a big change and it is almost unreasonable to manually review the move from the
commands/init.tstoactions/*- this was all done my opus and I'm having to rely on manual and automatic tests here.