diff --git a/cmd/page.go b/cmd/page.go index 983bcde..18033f5 100644 --- a/cmd/page.go +++ b/cmd/page.go @@ -323,14 +323,22 @@ Examples: }, } -var pageDeleteCmd = &cobra.Command{ - Use: "delete ", - Short: "Delete (archive) a page", - Long: `Archive a Notion page (soft delete). +var pageArchiveCmd = &cobra.Command{ + Use: "archive ", + Aliases: []string{"delete", "trash"}, + Short: "Archive a page (soft delete, reversible)", + Long: `Archive a Notion page. + +This is a soft delete — the page moves to the workspace trash but can be +brought back with 'notion page restore'. Despite the legacy 'delete' +alias, no content is removed permanently. + +Aliases: archive | delete | trash Examples: - notion page delete abc123 - notion page delete https://notion.so/My-Page-abc123`, + notion page archive abc123 + notion page trash https://notion.so/My-Page-abc123 + notion page delete abc123 # still works for back-compat`, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { token, err := getToken() @@ -348,7 +356,7 @@ Examples: data, err := c.Patch("/v1/pages/"+pageID, body) if err != nil { - return fmt.Errorf("delete page: %w", err) + return fmt.Errorf("archive page: %w", err) } if outputFormat == "json" { @@ -359,11 +367,16 @@ Examples: return render.JSON(result) } - fmt.Println("✓ Page archived") + fmt.Println("✓ Page archived (run 'notion page restore' to undo)") return nil }, } +// pageDeleteCmd is kept as a standalone var pointing at the same RunE +// purely so existing tests / scripts that reference the variable name +// still compile. The user-facing command is aliased via pageArchiveCmd. +var pageDeleteCmd = pageArchiveCmd + var pageMoveCmd = &cobra.Command{ Use: "move ", Short: "Move a page to a new parent", @@ -573,7 +586,7 @@ Examples: var pageRestoreCmd = &cobra.Command{ Use: "restore ", Short: "Restore an archived page", - Long: `Unarchive a Notion page (reverse of delete). + Long: `Unarchive a Notion page (reverse of archive / delete / trash). Examples: notion page restore abc123`, @@ -943,7 +956,7 @@ func init() { pageCmd.AddCommand(pageViewCmd) pageCmd.AddCommand(pageListCmd) pageCmd.AddCommand(pageCreateCmd) - pageCmd.AddCommand(pageDeleteCmd) + pageCmd.AddCommand(pageArchiveCmd) pageCmd.AddCommand(pageRestoreCmd) pageCmd.AddCommand(pageMoveCmd) pageCmd.AddCommand(pageOpenCmd) diff --git a/cmd/page_archive_test.go b/cmd/page_archive_test.go new file mode 100644 index 0000000..34011b1 --- /dev/null +++ b/cmd/page_archive_test.go @@ -0,0 +1,43 @@ +package cmd + +import "testing" + +func TestPageArchiveCommandAliases(t *testing.T) { + // The canonical command is `archive`; `delete` and `trash` are aliases. + wantAliases := map[string]bool{"delete": true, "trash": true} + got := map[string]bool{} + for _, a := range pageArchiveCmd.Aliases { + got[a] = true + } + if len(got) != len(wantAliases) { + t.Errorf("aliases = %v, want %v", pageArchiveCmd.Aliases, []string{"delete", "trash"}) + } + for a := range wantAliases { + if !got[a] { + t.Errorf("missing alias %q", a) + } + } +} + +func TestPageArchiveCommandNameIsCanonical(t *testing.T) { + // `Use:` should start with "archive", making that the primary term in + // --help output. The old "delete" lives only as an alias. + if got := pageArchiveCmd.Name(); got != "archive" { + t.Errorf("canonical name = %q, want 'archive'", got) + } +} + +func TestPageArchiveResolvesViaAlias(t *testing.T) { + // Cobra resolves an alias by matching against command.Aliases. + // Each alias must route to the same cobra.Command. + for _, alias := range []string{"delete", "trash", "archive"} { + cmd, _, err := pageCmd.Find([]string{alias}) + if err != nil { + t.Errorf("alias %q: Find returned error: %v", alias, err) + continue + } + if cmd != pageArchiveCmd { + t.Errorf("alias %q resolved to %q, want the archive command", alias, cmd.Name()) + } + } +}