feat(trail): drop attachment and watcher commands for now · Entire
feat(trail): drop attachment and watcher commands for now
3fced2a→main·
computermode·1w ago·8 files·+1 added/-383 removed
Scope this PR to metadata, approvals, and discussion threads. Attachment (raw-binary upload) and watchers (presence-based) support is removed for a later change.
Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Sessions
01KX6VR2GWJFA44C0255JA7E57View transcript
[?
CLI Trail Commands and UI ParityClaude Code·Opus 4.8·2 steps](/content/gh/entireio/cli/session/a7c8f6a2-7a40-4558-aba8-a31927cc21d3#timeline-01KX6VR2GWJFA44C0255JA7E57/index.html)
Changes
8
cmd/entire/cli
api
Dtrail_attachment_types.go-29
Mtrail_thread_types_test.go-18
Dtrail_watcher_types.go-8
Dtrail_attachment_cmd.go-184
Mtrail_cmd.go-2
Mtrail_collaboration_cmd_test.go-58
Mtrail_comment_cmd.go+1/-2
package api
// TrailAttachment is a trail attachment (v1: images only). The server strips
// the internal r2_key; there is no URL field — a serve URL is built from the
// id and a variant. Width/Height/CreatedByUserID/DeletedAt are nullable.
type TrailAttachment struct {
ID string `json:"id"`
TrailID string `json:"trail_id"`
RepoID string `json:"repo_id"`
Kind string `json:"kind"`
ContentType string `json:"content_type"`
Filename string `json:"filename"`
SizeBytes int64 `json:"size_bytes"`
Width *int `json:"width"`
Height *int `json:"height"`
CreatedByUserID *string `json:"created_by_user_id"`
CreatedAt string `json:"created_at"`
DeletedAt *string `json:"deleted_at"`
}
// TrailAttachmentsResponse is the response from GET .../:number/attachments.
type TrailAttachmentsResponse struct {
Attachments []TrailAttachment `json:"attachments"`
}
// TrailAttachmentUploadResponse is the response from POST .../:number/attachments.
type TrailAttachmentUploadResponse struct {
Attachment TrailAttachment `json:"attachment"`
}
Dcmd/entire/cli/api/trail_attachment_types.go-29
package api
// TrailWatchersResponse is the response from GET /api/v1/trails/:trail_id/watchers.
// Watchers are the user IDs of clients currently connected to the trail's live
// event stream (presence-based, not a persisted subscription list).
type TrailWatchersResponse struct {
Watchers []string `json:"watchers"`
}
Dcmd/entire/cli/api/trail_watcher_types.go-8
package cli
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
"github.com/entireio/cli/cmd/entire/cli/api"
"github.com/spf13/cobra"
)
// trailAttachmentsPath builds the attachments collection path for a trail number.
func trailAttachmentsPath(forge, owner, repo string, number int) string {
return trailNumberPath(forge, owner, repo, number) + "/attachments"
}
// detectAttachmentContentType returns the image MIME type for a file's bytes,
// accepting only PNG and JPEG (the only kinds the server stores). It errors on
// anything else so the CLI fails fast with a clear message.
func detectAttachmentContentType(data []byte) (string, error) {
ct := http.DetectContentType(data)
switch ct {
case "image/png", "image/jpeg":
return ct, nil
default:
return "", fmt.Errorf("unsupported attachment type %q: only PNG and JPEG images are supported", ct)
}
}
// trailAttachmentURL builds the public inline-variant serve URL for an
// attachment. The host/owner/repo segments are decorative server-side; the id
// alone resolves the attachment.
func trailAttachmentURL(forge, owner, repo, id string) string {
return strings.TrimRight(api.BaseURL(), "/") +
"/api/v1/trails/" + forge + "/" + owner + "/" + repo + "/attachments/" + id + "/inline"
}
Dcmd/entire/cli/trail_attachment_cmd.go-184
package cli
import (
"context"
"errors"
"fmt"
"strings"
"github.com/entireio/cli/cmd/entire/cli/api"
"github.com/spf13/cobra"
)
// withNumberedTrail resolves a numbered trail (by --trail selector or current
// branch / --branch) and invokes fn inside an authenticated API context. It
// centralizes the resolution boilerplate shared by the comment and attachment
// subtrees.
func withNumberedTrail(cmd *cobra.Command, fn func(ctx context.Context, client *api.Client, found *api.TrailResource, forge, owner, repo string) error) error {
...
}
Dcmd/entire/cli/trail_cmd.go-2
package cli
// trailWatchersPath returns the watchers path, keyed by the trail's UUID (not
// its number, unlike the other trail subresources).
func trailWatchersPath(trailID string) string {
return "/api/v1/trails/" + trailID + "/watchers"
}
Dcmd/entire/cli/trail_watchers_cmd.go-82
package cli
import (
"context"
"errors"
"fmt"
"strings"
"github.com/entireio/cli/cmd/entire/cli/api"
"github.com/spf13/cobra"
)
func newTrailWatchersCmd() *cobra.Command {
...
}