Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions internal/api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,11 @@ type Credential struct {

// Variable represents an n8n variable
type Variable struct {
ID string `json:"id,omitempty"`
Key string `json:"key"`
Value string `json:"value"`
Type string `json:"type,omitempty"`
ID string `json:"id,omitempty"`
Key string `json:"key"`
Value string `json:"value"`
Type string `json:"type,omitempty"`
ProjectID string `json:"projectId,omitempty"`
}

// ListResult contains paginated list results
Expand Down Expand Up @@ -683,15 +684,18 @@ func (c *Client) TriggerWebhook(path, method string) ([]byte, error) {

// --- Variables ---

// ListVariables returns all variables
func (c *Client) ListVariables(limit int, cursor string) ([]Variable, error) {
// ListVariables returns all variables, optionally filtered by project.
func (c *Client) ListVariables(limit int, cursor string, projectID string) ([]Variable, error) {
Comment thread
fank marked this conversation as resolved.
params := url.Values{}
if limit > 0 {
params.Set("limit", strconv.Itoa(limit))
}
if cursor != "" {
params.Set("cursor", cursor)
}
if projectID != "" {
params.Set("projectId", projectID)
}

path := "/variables"
if len(params) > 0 {
Expand All @@ -713,9 +717,12 @@ func (c *Client) ListVariables(limit int, cursor string) ([]Variable, error) {
return resp.Data, nil
}

// CreateVariable creates a new variable
func (c *Client) CreateVariable(key, value string) error {
// CreateVariable creates a new variable, optionally scoped to a project.
func (c *Client) CreateVariable(key, value, projectID string) error {
body := map[string]string{"key": key, "value": value}
if projectID != "" {
body["projectId"] = projectID
}
_, err := c.request(http.MethodPost, "/variables", body)
return err
}
Expand Down
47 changes: 37 additions & 10 deletions internal/cmd/variable/variable.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ func NewVariableCmd() *cobra.Command {
Long: `List, create, update, and delete n8n environment variables.`,
}

cmd.PersistentFlags().String("project", "", "Project ID (omit for global variables)")

cmd.AddCommand(newListCmd())
cmd.AddCommand(newGetCmd())
cmd.AddCommand(newCreateCmd())
Expand Down Expand Up @@ -53,7 +55,8 @@ func newListCmd() *cobra.Command {
return err
}

vars, err := client.ListVariables(0, "")
projectID, _ := cmd.Flags().GetString("project")
vars, err := client.ListVariables(0, "", projectID)
if err != nil {
return fmt.Errorf("failed to list variables: %w", err)
}
Expand All @@ -68,14 +71,34 @@ func newListCmd() *cobra.Command {
return nil
}

fmt.Printf("%-8s %-40s %s\n", "ID", "KEY", "VALUE")
fmt.Printf("%-8s %-40s %s\n", strings.Repeat("-", 8), strings.Repeat("-", 40), strings.Repeat("-", 50))
hasProject := false
for _, v := range vars {
if v.ProjectID != "" {
hasProject = true
break
}
}

if hasProject {
fmt.Printf("%-8s %-18s %-40s %s\n", "ID", "PROJECT", "KEY", "VALUE")
fmt.Printf("%-8s %-18s %-40s %s\n",
strings.Repeat("-", 8), strings.Repeat("-", 18),
strings.Repeat("-", 40), strings.Repeat("-", 50))
} else {
fmt.Printf("%-8s %-40s %s\n", "ID", "KEY", "VALUE")
fmt.Printf("%-8s %-40s %s\n", strings.Repeat("-", 8), strings.Repeat("-", 40), strings.Repeat("-", 50))
}

for _, v := range vars {
value := v.Value
if len(value) > 50 {
value = value[:47] + "..."
}
fmt.Printf("%-8s %-40s %s\n", v.ID, v.Key, value)
if hasProject {
fmt.Printf("%-8s %-18s %-40s %s\n", v.ID, v.ProjectID, v.Key, value)
} else {
fmt.Printf("%-8s %-40s %s\n", v.ID, v.Key, value)
}
}
Comment thread
fank marked this conversation as resolved.

return nil
Expand All @@ -96,7 +119,8 @@ func newGetCmd() *cobra.Command {
return err
}

vars, err := client.ListVariables(0, "")
projectID, _ := cmd.Flags().GetString("project")
vars, err := client.ListVariables(0, "", projectID)
if err != nil {
return fmt.Errorf("failed to list variables: %w", err)
}
Expand Down Expand Up @@ -147,7 +171,8 @@ special shell characters (e.g. n8nctl var create key --value 'b!xyz').`,
return fmt.Errorf("value is required: pass as second argument or use --value")
}

if err := client.CreateVariable(key, value); err != nil {
projectID, _ := cmd.Flags().GetString("project")
if err := client.CreateVariable(key, value, projectID); err != nil {
return fmt.Errorf("failed to create variable: %w", err)
}

Expand Down Expand Up @@ -188,8 +213,9 @@ special shell characters (e.g. n8nctl var update key --value 'b!xyz').`,
return fmt.Errorf("value is required: pass as second argument or use --value")
}

// Resolve key to ID
vars, err := client.ListVariables(0, "")
// Resolve key to ID within the given project scope.
projectID, _ := cmd.Flags().GetString("project")
vars, err := client.ListVariables(0, "", projectID)
if err != nil {
return fmt.Errorf("failed to list variables: %w", err)
}
Expand Down Expand Up @@ -224,8 +250,9 @@ func newDeleteCmd() *cobra.Command {
return err
}

// Resolve key to ID
vars, err := client.ListVariables(0, "")
// Resolve key to ID within the given project scope.
projectID, _ := cmd.Flags().GetString("project")
vars, err := client.ListVariables(0, "", projectID)
if err != nil {
return fmt.Errorf("failed to list variables: %w", err)
}
Expand Down
Loading