Skip to content

Commit f0c3dfa

Browse files
authored
Add error validation for init prompts (#11)
1 parent ad114f9 commit f0c3dfa

File tree

1 file changed

+196
-41
lines changed

1 file changed

+196
-41
lines changed

cli/command/init/init.go

Lines changed: 196 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ import (
66
"fmt"
77
"os"
88
"path/filepath"
9+
"strings"
910
"wpm/cli/command"
10-
"wpm/pkg/validator"
1111

12+
"github.com/morikuni/aec"
1213
"github.com/pkg/errors"
1314
"github.com/spf13/cobra"
1415
)
@@ -22,13 +23,26 @@ const (
2223
defaultWP = "6.7"
2324
)
2425

26+
type packageInit struct {
27+
Name string `json:"name"`
28+
Version string `json:"version"`
29+
License string `json:"license"`
30+
Type string `json:"type"`
31+
Tags []string `json:"tags"`
32+
Platform struct {
33+
PHP string `json:"php"`
34+
WP string `json:"wp"`
35+
} `json:"platform"`
36+
}
37+
2538
type initOptions struct {
2639
yes bool
2740
}
2841

2942
type prompt struct {
30-
Msg string
31-
Default string
43+
Msg string
44+
Default string
45+
Validate func(string) error
3246
}
3347

3448
type promptField struct {
@@ -66,62 +80,183 @@ func runInit(ctx context.Context, wpmCli command.Cli, opts initOptions) error {
6680
}
6781

6882
basecwd := filepath.Base(cwd)
69-
wpmJsonInitData := validator.Package{
83+
wpmJsonInitData := packageInit{
7084
Name: basecwd,
7185
Version: defaultVersion,
7286
License: defaultLicense,
7387
Type: defaultType,
7488
Tags: []string{},
75-
Platform: validator.PackagePlatform{
89+
Platform: struct {
90+
PHP string `json:"php"`
91+
WP string `json:"wp"`
92+
}{
7693
PHP: defaultPHP,
7794
WP: defaultWP,
7895
},
7996
}
97+
ve, err := wpmCli.PackageValidator()
98+
if err != nil {
99+
return err
100+
}
80101

81102
// If not auto-confirmed, prompt the user for values
82103
if !opts.yes {
83104
prompts := []promptField{
84-
{"name", prompt{"package name", basecwd}},
85-
{"version", prompt{"version", defaultVersion}},
86-
{"license", prompt{"license", defaultLicense}},
87-
{"type", prompt{"type", defaultType}},
88-
{"php", prompt{"requires php", defaultPHP}},
89-
{"wp", prompt{"requires wp", defaultWP}},
105+
{
106+
"name",
107+
prompt{
108+
"package name",
109+
basecwd,
110+
func(val string) error {
111+
if val == "" {
112+
val = basecwd
113+
}
114+
115+
errs := ve.Var(val, "required,min=3,max=164,package_name_regex")
116+
if errs != nil {
117+
return errors.Errorf("invalid package name: \"%s\"", aec.Bold.Apply(val))
118+
}
119+
120+
wpmJsonInitData.Name = val
121+
122+
return nil
123+
},
124+
},
125+
},
126+
{
127+
"version",
128+
prompt{
129+
"version",
130+
defaultVersion,
131+
func(val string) error {
132+
if val == "" {
133+
val = defaultVersion
134+
}
135+
136+
errs := ve.Var(val, "required,semver,max=64")
137+
if errs != nil {
138+
return errors.Errorf("invalid version: \"%s\"", aec.Bold.Apply(val))
139+
}
140+
141+
wpmJsonInitData.Version = val
142+
143+
return nil
144+
},
145+
},
146+
},
147+
{
148+
"license",
149+
prompt{
150+
"license",
151+
defaultLicense,
152+
func(val string) error {
153+
if val == "" {
154+
val = defaultLicense
155+
}
156+
157+
wpmJsonInitData.License = val
158+
159+
return nil
160+
},
161+
},
162+
},
163+
{
164+
"type",
165+
prompt{
166+
"type",
167+
defaultType,
168+
func(val string) error {
169+
if val == "" {
170+
val = defaultType
171+
}
172+
173+
errs := ve.Var(val, "required,oneof=plugin theme mu-plugin drop-in")
174+
if errs != nil {
175+
return errors.Errorf("invalid type: \"%s\"", aec.Bold.Apply(val))
176+
}
177+
178+
wpmJsonInitData.Type = val
179+
180+
return nil
181+
},
182+
},
183+
},
184+
{
185+
"php",
186+
prompt{
187+
"requires php",
188+
defaultPHP,
189+
func(val string) error {
190+
if val == "" {
191+
val = defaultPHP
192+
}
193+
194+
var semverVal string
195+
196+
semverVal, err = formatSemver(val)
197+
if err != nil {
198+
return errors.Errorf("invalid php version: \"%s\"", aec.Bold.Apply(val))
199+
}
200+
201+
errs := ve.Var(semverVal, "required,semver")
202+
if errs != nil {
203+
return errors.Errorf("invalid php version: \"%s\"", aec.Bold.Apply(semverVal))
204+
}
205+
206+
wpmJsonInitData.Platform.PHP = val
207+
208+
return nil
209+
},
210+
},
211+
},
212+
{
213+
"wp",
214+
prompt{
215+
"requires wp",
216+
defaultWP,
217+
func(val string) error {
218+
if val == "" {
219+
val = defaultWP
220+
}
221+
222+
var semverVal string
223+
224+
semverVal, err = formatSemver(val)
225+
if err != nil {
226+
return errors.Errorf("invalid wp version: \"%s\"", aec.Bold.Apply(val))
227+
}
228+
229+
errs := ve.Var(semverVal, "required,semver")
230+
if errs != nil {
231+
return errors.Errorf("invalid wp version: \"%s\"", aec.Bold.Apply(semverVal))
232+
}
233+
234+
wpmJsonInitData.Platform.WP = val
235+
236+
return nil
237+
},
238+
},
239+
},
90240
}
91241

92242
for _, pf := range prompts {
93-
val, err := command.PromptForInput(ctx, wpmCli.In(), wpmCli.Out(), fmt.Sprintf("%s (%s): ", pf.Prompt.Msg, pf.Prompt.Default))
94-
if err != nil {
95-
return err
96-
}
97-
if val == "" {
98-
val = pf.Prompt.Default
99-
}
243+
var val string
244+
var err error
100245

101-
switch pf.Key {
102-
case "name":
103-
wpmJsonInitData.Name = val
104-
case "version":
105-
wpmJsonInitData.Version = val
106-
case "license":
107-
wpmJsonInitData.License = val
108-
case "type":
109-
wpmJsonInitData.Type = val
110-
case "php":
111-
wpmJsonInitData.Platform.PHP = val
112-
case "wp":
113-
wpmJsonInitData.Platform.WP = val
114-
}
115-
}
116-
}
246+
for {
247+
val, err = command.PromptForInput(ctx, wpmCli.In(), wpmCli.Out(), fmt.Sprintf("%s (%s): ", pf.Prompt.Msg, pf.Prompt.Default))
248+
if err != nil {
249+
return err
250+
}
117251

118-
ve, err := wpmCli.PackageValidator()
119-
if err != nil {
120-
return err
121-
}
252+
if err := pf.Prompt.Validate(val); err != nil {
253+
fmt.Fprintf(wpmCli.Err(), "%s\n", err)
254+
continue
255+
}
122256

123-
if err := validator.ValidatePackage(wpmJsonInitData, ve); err != nil {
124-
return err
257+
break
258+
}
259+
}
125260
}
126261

127262
if err := writeWpmJson(wpmCli, wpmJsonPath, wpmJsonInitData); err != nil {
@@ -131,7 +266,7 @@ func runInit(ctx context.Context, wpmCli command.Cli, opts initOptions) error {
131266
return nil
132267
}
133268

134-
func writeWpmJson(wpmCli command.Cli, path string, data validator.Package) error {
269+
func writeWpmJson(wpmCli command.Cli, path string, data packageInit) error {
135270
file, err := os.Create(path)
136271
if err != nil {
137272
return err
@@ -150,3 +285,23 @@ func writeWpmJson(wpmCli command.Cli, path string, data validator.Package) error
150285

151286
return nil
152287
}
288+
289+
func formatSemver(version string) (string, error) {
290+
parts := strings.Split(version, ".")
291+
292+
for _, part := range parts {
293+
if part == "" {
294+
return "", errors.New("empty part")
295+
}
296+
297+
if _, err := fmt.Sscanf(part, "%d", new(int)); err != nil {
298+
return "", err
299+
}
300+
}
301+
302+
for len(parts) < 3 {
303+
parts = append(parts, "0")
304+
}
305+
306+
return strings.Join(parts, "."), nil
307+
}

0 commit comments

Comments
 (0)