feat(cli): top-level goten init + plugin registry - #29
Merged
Conversation
Closes #25. Adds `goten init` — a top-level CLI subcommand that bootstraps a new project by copying embedded migration SQL files for core + any plugins declared in goten.config.yaml. Idempotent: identical destinations are skipped, divergent ones require --force. The synthetic default config kicks in when no goten.config.yaml exists yet, so this works from a clean directory. Plugin registry is a hardcoded map keyed by shorthand name. Adding a new official plugin = one line in cmd/goten/registry.go. `migrations.plugins:` now accepts shorthand (`- username`) or explicit path (`- ./plugins/username/migrations`); both are honored by `init` and by the existing migrate up/down/status flow via the new resolvePluginEntry helper (replaces inline path-base logic in discovery.go). Steps from the issue: - 1.1 Expose goten.CoreMigrationsFS via //go:embed - 1.2 Export usernameplugin.MigrationsFS - 1.3 Plugin registry in cmd/goten/registry.go - 1.4 resolvePluginEntry shared by init + discovery - 1.5 runInit / cmdInit with --force flag - 1.6 Wire init as top-level subcommand - 1.7 8 new init tests + 1 resolver test, all existing tests still pass - 1.8 CHANGELOG entry Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #25.
Summary
Adds
goten init— top-level CLI subcommand that bootstraps a project's migrations from embedded SQL files for core + any plugins declared ingoten.config.yaml. Inspired bynpx @better-auth/cli generate.Why
Until now, a new project had to
git clonethe goten repo orcurlthe raw migration files off GitHub.goten initremoves that friction and is idempotent — re-running after adding a plugin only writes the new files.Design notes
username). 3rd-party plugins are explicitly out of scope; unknown names error with the available list.migrations.plugins:accepts both forms — shorthand- username(new) auto-resolves to./plugins/username/migrations; full path- ./plugins/username/migrations(existing) still works. Auto-detected byresolvePluginEntrybased on presence of/or\. This is shared by bothinitand the existing discovery walker, somigrate up/down/statusbenefits too.--force; missing → written. Per-section summary printed.goten.config.yamlfalls back to a synthetic default (./migrations/, no plugins) soinitworks as the very first step in a new project.Steps (matching #25's checklist)
goten.CoreMigrationsFSvia//go:embedusernameplugin.MigrationsFSresolvePluginEntryshared betweeninitanddiscovery.gorunInit/cmdInitwith--forceflagTest plan
go test ./cmd/goten/...— all green; 9 new tests:TestRunInit_CoreOnly_FreshProject— fresh dir, no plugins, core files appear with embed-identical content.TestRunInit_CoreAndUsername_Shorthand—plugins: [username]shorthand resolves correctly.TestRunInit_CoreAndUsername_FullPath— backwards-compat with explicit path.TestRunInit_Idempotent— second run reports "0 written".TestRunInit_ConflictWithoutForce— pre-existing different content errors and mentions--force; original file untouched.TestRunInit_ConflictWithForce—--forceoverwrites to match embed.TestRunInit_UnknownPlugin— error names the unknown plugin AND lists available plugins.TestRunInit_NoConfigFile_FreshBootstrap— works with no config file at all (synthetic default).TestResolvePluginEntry— table-driven test of the shorthand/path resolver.make build— all six modules compile.mktemp -d, runinit, check files; re-run, output says "0 written, 2 skipped".🤖 Generated with Claude Code