Skip to content

Commit 02f5754

Browse files
akoclaude
andcommitted
fix: SHOW commands respect --json flag (issue #134)
All SHOW handlers that emitted "No X found." plain-text messages were returning early before calling writeResult(), producing no output in JSON mode. Fix applied across 10 files: Pattern A (gate empty-state message, fall through to writeResult): showODataClients, showODataServices, showExternalEntities, showExternalActions, showRestClients, showPublishedRestServices, showContractEntities/Actions/Channels/Messages, showConstants, showConstantValues, showDatabaseConnections, showBusinessEventServices/Events, showLanguages Pattern B (also gate header text): showFeaturesAll, showFeaturesInArea, showFeaturesAddedSince Pattern C (convert raw fmt.Fprintf to writeResult): showProjectSecurity → TableResult ["Property", "Value"] showDemoUsers → empty TableResult when disabled in JSON mode showAccessOnMicroflow → TableResult ["Module", "Role"] showAccessOnPage → TableResult ["Module", "Role"] Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 2b7aa1d commit 02f5754

10 files changed

Lines changed: 89 additions & 25 deletions

mdl/executor/cmd_businessevents.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func showBusinessEventServices(ctx *ExecContext, inModule string) error {
3838
filtered = append(filtered, svc)
3939
}
4040

41-
if len(filtered) == 0 {
41+
if len(filtered) == 0 && ctx.Format != FormatJSON {
4242
if inModule != "" {
4343
fmt.Fprintf(ctx.Output, "No business event services found in module %s\n", inModule)
4444
} else {
@@ -150,7 +150,7 @@ func showBusinessEvents(ctx *ExecContext, inModule string) error {
150150
}
151151
}
152152

153-
if len(rows) == 0 {
153+
if len(rows) == 0 && ctx.Format != FormatJSON {
154154
if inModule != "" {
155155
fmt.Fprintf(ctx.Output, "No business events found in module %s\n", inModule)
156156
} else {

mdl/executor/cmd_constants.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func showConstants(ctx *ExecContext, moduleName string) error {
6060
rows = append(rows, row{qualifiedName, modName, c.Name, folderPath, typeStr, defaultStr, exposed})
6161
}
6262

63-
if len(rows) == 0 {
63+
if len(rows) == 0 && ctx.Format != FormatJSON {
6464
fmt.Fprintln(ctx.Output, "No constants found.")
6565
return nil
6666
}
@@ -378,7 +378,7 @@ func showConstantValues(ctx *ExecContext, moduleName string) error {
378378
})
379379
}
380380

381-
if len(consts) == 0 {
381+
if len(consts) == 0 && ctx.Format != FormatJSON {
382382
fmt.Fprintln(ctx.Output, "No constants found.")
383383
return nil
384384
}

mdl/executor/cmd_contract.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func showContractEntities(ctx *ExecContext, name *ast.QualifiedName) error {
5555
}
5656
}
5757

58-
if len(rows) == 0 {
58+
if len(rows) == 0 && ctx.Format != FormatJSON {
5959
fmt.Fprintf(ctx.Output, "No entity types found in contract for %s.\n", svcQN)
6060
return nil
6161
}
@@ -85,7 +85,7 @@ func showContractActions(ctx *ExecContext, name *ast.QualifiedName) error {
8585
return err
8686
}
8787

88-
if len(doc.Actions) == 0 {
88+
if len(doc.Actions) == 0 && ctx.Format != FormatJSON {
8989
fmt.Fprintf(ctx.Output, "No actions/functions found in contract for %s.\n", svcQN)
9090
return nil
9191
}
@@ -1256,7 +1256,7 @@ func showContractChannels(ctx *ExecContext, name *ast.QualifiedName) error {
12561256
return err
12571257
}
12581258

1259-
if len(doc.Channels) == 0 {
1259+
if len(doc.Channels) == 0 && ctx.Format != FormatJSON {
12601260
fmt.Fprintf(ctx.Output, "No channels found in contract for %s.\n", svcQN)
12611261
return nil
12621262
}
@@ -1295,7 +1295,7 @@ func showContractMessages(ctx *ExecContext, name *ast.QualifiedName) error {
12951295
return err
12961296
}
12971297

1298-
if len(doc.Messages) == 0 {
1298+
if len(doc.Messages) == 0 && ctx.Format != FormatJSON {
12991299
fmt.Fprintf(ctx.Output, "No messages found in contract for %s.\n", svcQN)
13001300
return nil
13011301
}

mdl/executor/cmd_dbconnection.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ func showDatabaseConnections(ctx *ExecContext, moduleName string) error {
155155
rows = append(rows, row{qualifiedName, modName, conn.Name, folderPath, conn.DatabaseType, len(conn.Queries)})
156156
}
157157

158-
if len(rows) == 0 {
158+
if len(rows) == 0 && ctx.Format != FormatJSON {
159159
fmt.Fprintln(ctx.Output, "No database connections found.")
160160
return nil
161161
}

mdl/executor/cmd_features.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,14 @@ func execShowFeatures(ctx *ExecContext, s *ast.ShowFeaturesStmt) error {
9191

9292
func showFeaturesAll(ctx *ExecContext, reg *versions.Registry, pv versions.SemVer) error {
9393
features := reg.FeaturesForVersion(pv)
94-
if len(features) == 0 {
94+
if len(features) == 0 && ctx.Format != FormatJSON {
9595
fmt.Fprintf(ctx.Output, "No features found for version %s\n", pv)
9696
return nil
9797
}
9898

99-
fmt.Fprintf(ctx.Output, "Features for Mendix %s:\n\n", pv)
99+
if ctx.Format != FormatJSON {
100+
fmt.Fprintf(ctx.Output, "Features for Mendix %s:\n\n", pv)
101+
}
100102

101103
available, unavailable := 0, 0
102104
tr := &TableResult{
@@ -125,15 +127,17 @@ func showFeaturesAll(ctx *ExecContext, reg *versions.Registry, pv versions.SemVe
125127

126128
func showFeaturesInArea(ctx *ExecContext, reg *versions.Registry, pv versions.SemVer, area string) error {
127129
features := reg.FeaturesInArea(area, pv)
128-
if len(features) == 0 {
130+
if len(features) == 0 && ctx.Format != FormatJSON {
129131
// Check if the area exists at all.
130132
areas := reg.Areas()
131133
fmt.Fprintf(ctx.Output, "No features found in area %q for version %s\n", area, pv)
132134
fmt.Fprintf(ctx.Output, "Available areas: %s\n", strings.Join(areas, ", "))
133135
return nil
134136
}
135137

136-
fmt.Fprintf(ctx.Output, "Features in %s for Mendix %s:\n\n", area, pv)
138+
if ctx.Format != FormatJSON {
139+
fmt.Fprintf(ctx.Output, "Features in %s for Mendix %s:\n\n", area, pv)
140+
}
137141

138142
tr := &TableResult{
139143
Columns: []string{"Feature", "Available", "Since", "Notes"},
@@ -157,12 +161,14 @@ func showFeaturesInArea(ctx *ExecContext, reg *versions.Registry, pv versions.Se
157161

158162
func showFeaturesAddedSince(ctx *ExecContext, reg *versions.Registry, sinceV versions.SemVer) error {
159163
added := reg.FeaturesAddedSince(sinceV)
160-
if len(added) == 0 {
164+
if len(added) == 0 && ctx.Format != FormatJSON {
161165
fmt.Fprintf(ctx.Output, "No new features found since %s\n", sinceV)
162166
return nil
163167
}
164168

165-
fmt.Fprintf(ctx.Output, "Features added since Mendix %s:\n\n", sinceV)
169+
if ctx.Format != FormatJSON {
170+
fmt.Fprintf(ctx.Output, "Features added since Mendix %s:\n\n", sinceV)
171+
}
166172

167173
tr := &TableResult{
168174
Columns: []string{"Feature", "Area", "Since", "Notes"},

mdl/executor/cmd_languages.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func showLanguages(ctx *ExecContext) error {
2626
return mdlerrors.NewBackend("query languages", err)
2727
}
2828

29-
if len(result.Rows) == 0 {
29+
if len(result.Rows) == 0 && ctx.Format != FormatJSON {
3030
fmt.Fprintln(ctx.Output, "No translatable strings found. Run REFRESH CATALOG FULL to populate the strings table.")
3131
return nil
3232
}

mdl/executor/cmd_odata.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func showODataClients(ctx *ExecContext, moduleName string) error {
7878
rows = append(rows, row{modName, qn, svc.Version, svc.ODataVersion, url, validated})
7979
}
8080

81-
if len(rows) == 0 {
81+
if len(rows) == 0 && ctx.Format != FormatJSON {
8282
fmt.Fprintln(ctx.Output, "No consumed OData services found.")
8383
return nil
8484
}
@@ -257,7 +257,7 @@ func showODataServices(ctx *ExecContext, moduleName string) error {
257257
rows = append(rows, row{modName, qn, svc.Path, svc.Version, svc.ODataVersion, esCount, authStr})
258258
}
259259

260-
if len(rows) == 0 {
260+
if len(rows) == 0 && ctx.Format != FormatJSON {
261261
fmt.Fprintln(ctx.Output, "No published OData services found.")
262262
return nil
263263
}
@@ -499,7 +499,7 @@ func showExternalEntities(ctx *ExecContext, moduleName string) error {
499499
}
500500
}
501501

502-
if len(rows) == 0 {
502+
if len(rows) == 0 && ctx.Format != FormatJSON {
503503
fmt.Fprintln(ctx.Output, "No external entities found.")
504504
return nil
505505
}
@@ -615,7 +615,7 @@ func showExternalActions(ctx *ExecContext, moduleName string) error {
615615
extractActions(nf.ObjectCollection, modName, nf.Name)
616616
}
617617

618-
if len(actionMap) == 0 {
618+
if len(actionMap) == 0 && ctx.Format != FormatJSON {
619619
fmt.Fprintln(ctx.Output, "No external actions found.")
620620
return nil
621621
}

mdl/executor/cmd_published_rest.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func showPublishedRestServices(ctx *ExecContext, moduleName string) error {
5757
rows = append(rows, row{modName, qn, path, svc.Version, len(svc.Resources), opCount})
5858
}
5959

60-
if len(rows) == 0 {
60+
if len(rows) == 0 && ctx.Format != FormatJSON {
6161
fmt.Fprintln(ctx.Output, "No published REST services found.")
6262
return nil
6363
}

mdl/executor/cmd_rest_clients.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func showRestClients(ctx *ExecContext, moduleName string) error {
6464
rows = append(rows, row{modName, qn, baseUrl, auth, len(svc.Operations)})
6565
}
6666

67-
if len(rows) == 0 {
67+
if len(rows) == 0 && ctx.Format != FormatJSON {
6868
fmt.Fprintln(ctx.Output, "No consumed REST services found.")
6969
return nil
7070
}

mdl/executor/cmd_security.go

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,37 @@ func showProjectSecurity(ctx *ExecContext) error {
2020
return mdlerrors.NewBackend("read project security", err)
2121
}
2222

23+
if ctx.Format == FormatJSON {
24+
result := &TableResult{
25+
Columns: []string{"Property", "Value"},
26+
}
27+
result.Rows = append(result.Rows,
28+
[]any{"SecurityLevel", security.SecurityLevelDisplay(ps.SecurityLevel)},
29+
[]any{"CheckSecurity", fmt.Sprintf("%v", ps.CheckSecurity)},
30+
[]any{"StrictMode", fmt.Sprintf("%v", ps.StrictMode)},
31+
[]any{"DemoUsersEnabled", fmt.Sprintf("%v", ps.EnableDemoUsers)},
32+
[]any{"GuestAccess", fmt.Sprintf("%v", ps.EnableGuestAccess)},
33+
[]any{"UserRoles", fmt.Sprintf("%d", len(ps.UserRoles))},
34+
[]any{"DemoUsers", fmt.Sprintf("%d", len(ps.DemoUsers))},
35+
)
36+
if ps.AdminUserName != "" {
37+
result.Rows = append(result.Rows, []any{"AdminUser", ps.AdminUserName})
38+
}
39+
if ps.GuestUserRole != "" {
40+
result.Rows = append(result.Rows, []any{"GuestUserRole", ps.GuestUserRole})
41+
}
42+
if ps.PasswordPolicy != nil {
43+
pp := ps.PasswordPolicy
44+
result.Rows = append(result.Rows,
45+
[]any{"PasswordPolicy.MinimumLength", fmt.Sprintf("%d", pp.MinimumLength)},
46+
[]any{"PasswordPolicy.RequireDigit", fmt.Sprintf("%v", pp.RequireDigit)},
47+
[]any{"PasswordPolicy.RequireMixedCase", fmt.Sprintf("%v", pp.RequireMixedCase)},
48+
[]any{"PasswordPolicy.RequireSymbol", fmt.Sprintf("%v", pp.RequireSymbol)},
49+
)
50+
}
51+
return writeResult(ctx, result)
52+
}
53+
2354
fmt.Fprintf(ctx.Output, "Security Level: %s\n", security.SecurityLevelDisplay(ps.SecurityLevel))
2455
fmt.Fprintf(ctx.Output, "Check Security: %v\n", ps.CheckSecurity)
2556
fmt.Fprintf(ctx.Output, "Strict Mode: %v\n", ps.StrictMode)
@@ -115,9 +146,12 @@ func showDemoUsers(ctx *ExecContext) error {
115146
}
116147

117148
if !ps.EnableDemoUsers {
118-
fmt.Fprintln(ctx.Output, "Demo users are disabled.")
119-
fmt.Fprintln(ctx.Output, "Enable with: ALTER PROJECT SECURITY DEMO USERS ON;")
120-
return nil
149+
if ctx.Format != FormatJSON {
150+
fmt.Fprintln(ctx.Output, "Demo users are disabled.")
151+
fmt.Fprintln(ctx.Output, "Enable with: ALTER PROJECT SECURITY DEMO USERS ON;")
152+
return nil
153+
}
154+
return writeResult(ctx, &TableResult{Columns: []string{"User Name", "User Roles"}})
121155
}
122156

123157
result := &TableResult{
@@ -263,6 +297,18 @@ func showAccessOnMicroflow(ctx *ExecContext, name *ast.QualifiedName) error {
263297
for _, mf := range mfs {
264298
modName := h.GetModuleName(h.FindModuleID(mf.ContainerID))
265299
if modName == name.Module && mf.Name == name.Name {
300+
if ctx.Format == FormatJSON {
301+
result := &TableResult{Columns: []string{"Module", "Role"}}
302+
for _, role := range mf.AllowedModuleRoles {
303+
parts := strings.SplitN(string(role), ".", 2)
304+
mod, r := "", string(role)
305+
if len(parts) == 2 {
306+
mod, r = parts[0], parts[1]
307+
}
308+
result.Rows = append(result.Rows, []any{mod, r})
309+
}
310+
return writeResult(ctx, result)
311+
}
266312
if len(mf.AllowedModuleRoles) == 0 {
267313
fmt.Fprintf(ctx.Output, "No module roles granted execute access on %s.%s\n", modName, mf.Name)
268314
return nil
@@ -297,6 +343,18 @@ func showAccessOnPage(ctx *ExecContext, name *ast.QualifiedName) error {
297343
for _, pg := range pages {
298344
modName := h.GetModuleName(h.FindModuleID(pg.ContainerID))
299345
if modName == name.Module && pg.Name == name.Name {
346+
if ctx.Format == FormatJSON {
347+
result := &TableResult{Columns: []string{"Module", "Role"}}
348+
for _, role := range pg.AllowedRoles {
349+
parts := strings.SplitN(string(role), ".", 2)
350+
mod, r := "", string(role)
351+
if len(parts) == 2 {
352+
mod, r = parts[0], parts[1]
353+
}
354+
result.Rows = append(result.Rows, []any{mod, r})
355+
}
356+
return writeResult(ctx, result)
357+
}
300358
if len(pg.AllowedRoles) == 0 {
301359
fmt.Fprintf(ctx.Output, "No module roles granted view access on %s.%s\n", modName, pg.Name)
302360
return nil

0 commit comments

Comments
 (0)