Skip to content

Commit d3d84a8

Browse files
committed
feat: initial setup for "create" cmd in cli
1 parent 81c29c0 commit d3d84a8

File tree

4 files changed

+131
-1
lines changed

4 files changed

+131
-1
lines changed

cmd/create.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
7+
"github.com/AlecAivazis/survey/v2"
8+
"github.com/spf13/cobra"
9+
)
10+
11+
var createCmd = &cobra.Command{
12+
Use: "create",
13+
Short: "Create a new application",
14+
Long: "Commands for creating new Kernel applications",
15+
RunE: runCreateApp,
16+
}
17+
18+
func init() {
19+
createCmd.Flags().String("name", "", "Name of the application")
20+
createCmd.Flags().String("language", "", "Language of the application")
21+
createCmd.Flags().String("template", "", "Template to use for the application")
22+
}
23+
24+
const defaultAppName = "my-kernel-app"
25+
26+
// projectNameValidator ensures the project name is safe for file systems and package managers.
27+
func projectNameValidator(val any) error {
28+
str, ok := val.(string)
29+
if !ok {
30+
return fmt.Errorf("invalid input type")
31+
}
32+
33+
// Project name must be non-empty
34+
if len(str) == 0 {
35+
return fmt.Errorf("project name cannot be empty")
36+
}
37+
38+
// Validate project name: only letters, numbers, underscores, and hyphens
39+
// This regex prevents special characters that might break shell commands or filesystem paths.
40+
matched, err := regexp.MatchString(`^[A-Za-z\-_\d]+$`, str)
41+
if err != nil {
42+
return err
43+
}
44+
if !matched {
45+
return fmt.Errorf("project name may only include letters, numbers, underscores, and hyphens")
46+
}
47+
return nil
48+
}
49+
50+
// promptForAppName prompts the user for the application name if not provided
51+
func promptForAppName(providedAppName string) (string, error) {
52+
if providedAppName != "" {
53+
return providedAppName, nil
54+
}
55+
56+
var appName string
57+
prompt := &survey.Input{
58+
Message: "What is the name of your project?",
59+
Default: defaultAppName,
60+
}
61+
62+
err := survey.AskOne(prompt, &appName, survey.WithValidator(projectNameValidator))
63+
if err != nil {
64+
return "", err
65+
}
66+
67+
return appName, nil
68+
}
69+
70+
func runCreateApp(cmd *cobra.Command, args []string) error {
71+
providedAppName, _ := cmd.Flags().GetString("name")
72+
language, _ := cmd.Flags().GetString("language")
73+
template, _ := cmd.Flags().GetString("template")
74+
75+
// Prompt for app name if not provided
76+
appName, err := promptForAppName(providedAppName)
77+
if err != nil {
78+
return fmt.Errorf("failed to get app name: %w", err)
79+
}
80+
81+
fmt.Printf("Creating application '%s' with language '%s' and template '%s'...\n", appName, language, template)
82+
83+
// TODO: prompt the user for the language of the app, suggest a default language (typescript)
84+
// TODO: prompt the user for the template of the app, suggest a default template (sample-app)
85+
86+
// TODO: create the project structure
87+
88+
// print "Creating a new TypeScript Sample App" or similar. Essentially the language and template name combined.
89+
90+
/*
91+
Print the following:
92+
✔ TypeScript environment set up successfully
93+
94+
🎉 Kernel app created successfully!
95+
96+
Next steps:
97+
brew install onkernel/tap/kernel
98+
cd my-kernel-app
99+
kernel login # or: export KERNEL_API_KEY=<YOUR_API_KEY>
100+
kernel deploy index.ts
101+
kernel invoke ts-basic get-page-title --payload '{"url": "https://www.google.com"}'
102+
# Do this in a separate tab
103+
kernel login # or: export KERNEL_API_KEY=<YOUR_API_KEY>
104+
kernel logs ts-basic --follow
105+
*/
106+
107+
return nil
108+
}

cmd/root.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ func isAuthExempt(cmd *cobra.Command) bool {
7979
}
8080
for c := cmd; c != nil; c = c.Parent() {
8181
switch c.Name() {
82-
case "login", "logout", "auth", "help", "completion":
82+
case "login", "logout", "auth", "help", "completion",
83+
"create":
8384
return true
8485
}
8586
}
@@ -128,6 +129,7 @@ func init() {
128129
rootCmd.AddCommand(profilesCmd)
129130
rootCmd.AddCommand(proxies.ProxiesCmd)
130131
rootCmd.AddCommand(extensionsCmd)
132+
rootCmd.AddCommand(createCmd)
131133

132134
rootCmd.PersistentPostRunE = func(cmd *cobra.Command, args []string) error {
133135
// running synchronously so we never slow the command

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ require (
2424
atomicgo.dev/cursor v0.2.0 // indirect
2525
atomicgo.dev/keyboard v0.2.9 // indirect
2626
atomicgo.dev/schedule v0.1.0 // indirect
27+
github.com/AlecAivazis/survey/v2 v2.3.7 // indirect
2728
github.com/charmbracelet/colorprofile v0.3.0 // indirect
2829
github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.1 // indirect
2930
github.com/charmbracelet/x/ansi v0.8.0 // indirect
@@ -37,9 +38,13 @@ require (
3738
github.com/godbus/dbus/v5 v5.1.0 // indirect
3839
github.com/gookit/color v1.5.4 // indirect
3940
github.com/inconshreveable/mousetrap v1.1.0 // indirect
41+
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
4042
github.com/lithammer/fuzzysearch v1.1.8 // indirect
4143
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
44+
github.com/mattn/go-colorable v0.1.2 // indirect
45+
github.com/mattn/go-isatty v0.0.8 // indirect
4246
github.com/mattn/go-runewidth v0.0.16 // indirect
47+
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
4348
github.com/muesli/cancelreader v0.2.2 // indirect
4449
github.com/muesli/mango v0.1.0 // indirect
4550
github.com/muesli/mango-cobra v1.2.0 // indirect

go.sum

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8=
88
atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ=
99
atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs=
1010
atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU=
11+
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
12+
github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
1113
github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs=
1214
github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8=
1315
github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII=
@@ -19,6 +21,7 @@ github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi
1921
github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY=
2022
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
2123
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
24+
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
2225
github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk=
2326
github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
2427
github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
@@ -43,6 +46,7 @@ github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNE
4346
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
4447
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
4548
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
49+
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
4650
github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0=
4751
github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8=
4852
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
@@ -60,10 +64,13 @@ github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQ
6064
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
6165
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
6266
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
67+
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
6368
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
6469
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
6570
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
6671
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
72+
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
73+
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
6774
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
6875
github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
6976
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
@@ -78,9 +85,15 @@ github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8
7885
github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=
7986
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
8087
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
88+
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
89+
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
90+
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
91+
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
8192
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
8293
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
8394
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
95+
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
96+
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
8497
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
8598
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
8699
github.com/muesli/mango v0.1.0 h1:DZQK45d2gGbql1arsYA4vfg4d7I9Hfx5rX/GCmzsAvI=
@@ -161,6 +174,7 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
161174
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
162175
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
163176
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
177+
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
164178
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
165179
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
166180
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -183,6 +197,7 @@ golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
183197
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
184198
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
185199
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
200+
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
186201
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
187202
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
188203
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=

0 commit comments

Comments
 (0)