Documentation
¶
Overview ¶
Package cmd contains core TypeGo CLI commands.
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var BuildCmd = &cobra.Command{ Use: "build [file]", Short: "Build and bundle a TypeScript file for production", Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { filename := args[0] absPath, _ := filepath.Abs(filename) fmt.Printf("📦 Building %s...\n", absPath) res, _ := compiler.Compile(absPath, nil) tmpDir := ".typego_build_tmp" if err := os.MkdirAll(tmpDir, 0755); err != nil { fmt.Printf("Error creating temp dir: %v\n", err) os.Exit(1) } defer os.RemoveAll(tmpDir) fetcher, err := linker.NewFetcher() if err != nil { fmt.Printf("Failed to init fetcher: %v\n", err) os.Exit(1) } defer fetcher.Cleanup() virtualModules := make(map[string]string) var bindBlock string if res != nil { for _, imp := range res.Imports { if len(imp) > 3 && imp[:3] == "go:" { cleanImp := imp[3:] fmt.Printf("🔍 Inspecting %s...\n", cleanImp) _ = fetcher.Get(cleanImp) info, err := linker.Inspect(cleanImp, fetcher.TempDir) if err != nil { fmt.Printf("Warning: Could not inspect %s: %v\n", cleanImp, err) continue } bindBlock += linker.GenerateShim(info, "pkg_"+info.Name) // Generate Virtual Module Content (Exports) var vmContent strings.Builder for _, fn := range info.Exports { vmContent.WriteString(fmt.Sprintf("export const %s = (globalThis as any)._go_hyper_%s.%s;\n", fn.Name, info.Name, fn.Name)) } virtualModules[imp] = vmContent.String() } } } fmt.Println("🔨 Compiling binary (Pass 2)...") res, err = compiler.Compile(absPath, virtualModules) if err != nil { fmt.Printf("Build Error: %v\n", err) os.Exit(1) } // Generate Import Block for Shim var importBlock strings.Builder for _, imp := range res.Imports { if len(imp) > 3 && imp[:3] == "go:" { cleanImp := imp[3:] if cleanImp == "fmt" || cleanImp == "os" { continue } importBlock.WriteString(fmt.Sprintf("\t\"%s\"\n", cleanImp)) } } shimContent := fmt.Sprintf(builder.ShimTemplate, importBlock.String(), fmt.Sprintf("%q", res.JS), bindBlock, MemoryLimit*1024*1024) shimPath := filepath.Join(tmpDir, "main.go") if err := os.WriteFile(shimPath, []byte(shimContent), 0644); err != nil { fmt.Printf("Error writing shim: %v\n", err) os.Exit(1) } goModContent := `module typego_app go 1.23.6 ` if err := os.WriteFile(filepath.Join(tmpDir, "go.mod"), []byte(goModContent), 0644); err != nil { fmt.Printf("Error writing go.mod: %v\n", err) os.Exit(1) } cwd, _ := os.Getwd() typegoRoot, isLocalDev := ecosystem.FindRepoRoot(cwd) if isLocalDev { fmt.Println("🔧 typego dev mode: using local source replacement at", typegoRoot) replaceCmd := exec.Command("go", "mod", "edit", "-replace", "github.com/repyh/typego="+typegoRoot) replaceCmd.Dir = tmpDir _ = replaceCmd.Run() } packages := []string{ "github.com/repyh/typego/bridge/core", "github.com/repyh/typego/bridge/polyfills", "github.com/repyh/typego/engine", "github.com/repyh/typego/eventloop", "github.com/dop251/goja", } for _, pkg := range packages { target := pkg if !isLocalDev { target = pkg + "@latest" } getCmd := exec.Command("go", "get", target) getCmd.Dir = tmpDir if isLocalDev { getCmd.Env = append(os.Environ(), "GOPROXY=off") } else { getCmd.Env = append(os.Environ(), "GOPROXY=direct") } _ = getCmd.Run() } outputName := buildOut if outputName == "" { outputName = "app.exe" } absOut, _ := filepath.Abs(outputName) fmt.Println("🧹 Resolving dependencies...") tidyCmd := exec.Command("go", "mod", "tidy") tidyCmd.Dir = tmpDir tidyCmd.Env = append(os.Environ(), "GOPROXY=direct") tidyCmd.Stdout = os.Stdout tidyCmd.Stderr = os.Stderr if err := tidyCmd.Run(); err != nil { fmt.Printf("go mod tidy failed: %v\n", err) os.Exit(1) } fmt.Println("🔨 Compiling binary...") buildCmd := exec.Command("go", "build", "-o", absOut, ".") buildCmd.Dir = tmpDir buildCmd.Stdout = os.Stdout buildCmd.Stderr = os.Stderr env := os.Environ() if buildTarget != "" { if target, ok := supportedTargets[buildTarget]; ok { fmt.Printf("🎯 Targeting %s/%s...\n", target.goos, target.goarch) env = append(env, "GOOS="+target.goos, "GOARCH="+target.goarch) env = append(env, "CGO_ENABLED=0") } else { fmt.Printf("Error: Unsupported target '%s'. Available targets:\n", buildTarget) for t := range supportedTargets { fmt.Printf(" - %s\n", t) } os.Exit(1) } } buildCmd.Env = env if err := buildCmd.Run(); err != nil { fmt.Printf("Compilation failed: %v\n", err) os.Exit(1) } fmt.Printf("✨ Binary created: %s\n", outputName) }, }
View Source
var DevCmd = &cobra.Command{ Use: "dev [file]", Short: "Start development server with hot-reload", Long: `Start a development server that watches for file changes and automatically restarts. Provides colored output and compilation timing.`, Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { filename := args[0] cwd, _ := os.Getwd() if ecosystem.IsHandoffRequired(cwd) { binaryPath, _ := ecosystem.GetJITBinaryPath(cwd) handoff := exec.Command(binaryPath, os.Args[1:]...) handoff.Stdout = os.Stdout handoff.Stderr = os.Stderr handoff.Stdin = os.Stdin handoff.Env = append(os.Environ(), ecosystem.HandoffEnvVar+"=true") if err := handoff.Run(); err != nil { if exitErr, ok := err.(*exec.ExitError); ok { os.Exit(exitErr.ExitCode()) } fmt.Printf("Handoff failed: %v\n", err) os.Exit(1) } os.Exit(0) } absPath, err := filepath.Abs(filename) if err != nil { printError("Failed to resolve path: %v", err) return } if _, err := os.Stat(absPath); os.IsNotExist(err) { printError("File not found: %s", filename) return } printBanner() printInfo("Watching %s", filepath.Base(filename)) printInfo("Press Ctrl+C to stop") fmt.Println() sig := make(chan os.Signal, 1) signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM) runDevProcess(absPath) lastMod := getDevLastMod(absPath) ticker := time.NewTicker(150 * time.Millisecond) defer ticker.Stop() for { select { case <-sig: fmt.Println() printWarning("Shutting down...") killDevProcess() printSuccess("Development server stopped") return case <-ticker.C: currentMod := getDevLastMod(absPath) if currentMod.After(lastMod) { fmt.Println() printInfo("Change detected, restarting...") killDevProcess() runDevProcess(absPath) lastMod = currentMod } } } }, }
View Source
var InitCmd = &cobra.Command{ Use: "init [name]", Short: "Initialize a new TypeGo project", Long: `Initialize a new TypeGo project with Go-first defaults. By default, npm is NOT initialized. Use --npm flag if you need npm packages. TypeScript type definitions are automatically generated. Examples: typego init # Initialize in current directory typego init my-app # Create my-app directory and initialize typego init --npm # Include npm/package.json setup`, Run: func(cmd *cobra.Command, args []string) { projectDir := "." if len(args) > 0 { projectDir = args[0] if err := os.MkdirAll(projectDir, 0755); err != nil { fmt.Printf("❌ Error creating project directory: %v\n", err) return } } fmt.Println("🚀 Creating TypeGo project...") fmt.Println() dirs := []string{ filepath.Join(projectDir, "src"), filepath.Join(projectDir, ".typego", "types"), } for _, dir := range dirs { if err := os.MkdirAll(dir, 0755); err != nil { fmt.Printf("❌ Error creating directory %s: %v\n", dir, err) return } } files := []struct { path string content string name string }{ {filepath.Join(projectDir, "src", "index.ts"), indexTemplate, "src/index.ts"}, {filepath.Join(projectDir, "typego.modules.json"), modulesTemplate, "typego.modules.json"}, {filepath.Join(projectDir, "tsconfig.json"), tsConfigTemplate, "tsconfig.json"}, } fmt.Println("📁 Created project structure:") for _, f := range files { if _, err := os.Stat(f.path); os.IsNotExist(err) { if err := os.WriteFile(f.path, []byte(f.content), 0644); err != nil { fmt.Printf("❌ Error creating %s: %v\n", f.name, err) return } fmt.Printf(" ├── %s\n", f.name) } else { fmt.Printf(" ├── %s (exists, skipped)\n", f.name) } } fmt.Println(" └── .typego/types/go.d.ts") typesCmd := exec.Command("typego", "types") typesCmd.Dir = projectDir if err := typesCmd.Run(); err != nil { fmt.Println(" ⚠️ Could not auto-generate types. Run 'typego types' manually.") } if initWithNpm { fmt.Println() fmt.Println("📦 Initializing npm (--npm flag)...") if _, err := os.Stat(filepath.Join(projectDir, "package.json")); os.IsNotExist(err) { npmInit := exec.Command("npm", "init", "-y") npmInit.Dir = projectDir if err := npmInit.Run(); err != nil { fmt.Printf(" ⚠️ npm init failed: %v\n", err) } else { npmInstall := exec.Command("npm", "install", "-D", "@types/node") npmInstall.Dir = projectDir if err := npmInstall.Run(); err != nil { fmt.Printf(" ⚠️ failed to install @types/node: %v\n", err) } else { fmt.Println(" ✅ Installed @types/node") } } } } fmt.Println() fmt.Println("📋 Next steps:") if projectDir != "." { fmt.Printf(" 1. cd %s\n", projectDir) fmt.Println(" 2. typego run src/index.ts") } else { fmt.Println(" 1. typego run src/index.ts") } fmt.Println() fmt.Println("💡 Tip: Add Go dependencies with 'typego add github.com/gin-gonic/gin'") }, }
View Source
var MemoryLimit uint64 = 128
MemoryLimit is exported for use by core commands (set in root.go)
View Source
var RunCmd = &cobra.Command{ Use: "run [file]", Short: "Run a TypeScript file", Long: `Run a TypeScript file using the TypeGo engine. By default, uses interpreter mode for fast execution (<1s startup). Use --compile to generate a standalone Go binary (slower, but more portable).`, Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { filename := args[0] cwd, _ := os.Getwd() if !compileMode && ecosystem.IsHandoffRequired(cwd) { binaryPath, _ := ecosystem.GetJITBinaryPath(cwd) handoff := exec.Command(binaryPath, os.Args[1:]...) handoff.Stdout = os.Stdout handoff.Stderr = os.Stderr handoff.Stdin = os.Stdin handoff.Env = append(os.Environ(), ecosystem.HandoffEnvVar+"=true") if err := handoff.Run(); err != nil { if exitErr, ok := err.(*exec.ExitError); ok { os.Exit(exitErr.ExitCode()) } fmt.Printf("Handoff failed: %v\n", err) os.Exit(1) } os.Exit(0) } if compileMode { runStandalone(filename) } else { if err := runInterpreter(filename); err != nil { fmt.Printf("Error: %v\n", err) os.Exit(1) } } }, }
View Source
var TypesCmd = &cobra.Command{ Use: "types [file]", Short: "Sync and update TypeGo ambient definitions", Run: func(cmd *cobra.Command, args []string) { fmt.Println("Syncing TypeGo definitions...") dtsPath := filepath.Join(".typego", "types", "go.d.ts") if err := os.MkdirAll(filepath.Dir(dtsPath), 0755); err != nil { fmt.Printf("Error: %v\n", err) return } // Read existing (target) file first, or use embedded default var currentContent []byte if existing, err := os.ReadFile(dtsPath); err == nil && len(existing) > 0 { currentContent = existing } else { currentContent = core.GlobalTypes } fetcher, err := linker.NewFetcher() if err != nil { fmt.Printf("Failed to init fetcher: %v\n", err) return } defer fetcher.Cleanup() fileSet := make(map[string]bool) if len(args) > 0 { absPath, _ := filepath.Abs(args[0]) fileSet[absPath] = true } else { err := filepath.WalkDir(".", func(path string, d os.DirEntry, err error) error { if err != nil { return err } if d.IsDir() { name := d.Name() if name == "node_modules" || name == ".typego" || name == ".git" || name == ".gemini" { return filepath.SkipDir } return nil } if filepath.Ext(path) == ".ts" { absPath, _ := filepath.Abs(path) fileSet[absPath] = true } return nil }) if err != nil { fmt.Printf("Error searching for TypeScript files: %v\n", err) } } goImports := make(map[string]bool) coreModules := []string{ "go:fmt", "go:os", "go:net/url", } for _, mod := range coreModules { goImports[mod] = true } for file := range fileSet { fmt.Printf("🔍 Scanning %s...\n", filepath.Base(file)) res, _ := compiler.Compile(file, nil) if res != nil { for _, imp := range res.Imports { if strings.HasPrefix(imp, "go:") || strings.HasPrefix(imp, "typego:") { goImports[imp] = true } } } } for imp := range goImports { if imp == "go:net/http" || imp == "go:sync" || imp == "typego:memory" || imp == "typego:worker" || imp == "go:memory" || imp == "go:crypto" { continue } fmt.Printf("📦 Generating types for %s...\n", imp) var pkgPath string if strings.HasPrefix(imp, "go:") { name := imp[3:] switch name { case "fmt", "os", "net/url": pkgPath = name default: pkgPath = name } } else if strings.HasPrefix(imp, "typego:") { continue } if pkgPath == "" { continue } isInternal := strings.HasPrefix(pkgPath, "github.com/repyh/typego") if !isInternal { if err := fetcher.Get(pkgPath); err != nil { fmt.Printf("Warning: Failed to fetch %s: %v\n", pkgPath, err) continue } } info, err := linker.Inspect(pkgPath, fetcher.TempDir) if err != nil { fmt.Printf("Failed to inspect %s: %v\n", pkgPath, err) continue } info.ImportPath = strings.TrimPrefix(imp, "go:") newTypeBlock := linker.GenerateTypes(info) pattern := fmt.Sprintf(`(?s)// MODULE: %s.*?// END: %s\n`, regexp.QuoteMeta(imp), regexp.QuoteMeta(imp)) re := regexp.MustCompile(pattern) if re.Match(currentContent) { currentContent = re.ReplaceAll(currentContent, []byte(newTypeBlock)) } else { currentContent = append(currentContent, []byte("\n"+newTypeBlock)...) } } currentContent = updateTypeBlock(currentContent, "go:net/http", string(bridge_net.HttpTypes)) currentContent = updateTypeBlock(currentContent, "go:sync", string(bridge_sync.Types)) currentContent = updateTypeBlock(currentContent, "go:memory", string(bridge_memory.Types)) currentContent = updateTypeBlock(currentContent, "typego:memory", string(bridge_memory.Types)) currentContent = updateTypeBlock(currentContent, "typego:worker", string(bridge_worker.Types)) currentContent = updateTypeBlock(currentContent, "go:crypto", string(bridge_crypto.Types)) if err := os.WriteFile(dtsPath, currentContent, 0644); err != nil { fmt.Printf("Error writing types: %v\n", err) return } fmt.Println("✅ Definitions synced to .typego/types/go.d.ts") }, }
View Source
var WatchCmd = &cobra.Command{ Use: "watch [file]", Short: "Run a file and restart on changes", Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { filename := args[0] absPath, err := filepath.Abs(filename) if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("👀 Watching %s...\n", filepath.Base(filename)) sig := make(chan os.Signal, 1) signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM) runProcess(absPath) lastMod := getLastMod(absPath) ticker := time.NewTicker(200 * time.Millisecond) defer ticker.Stop() for { select { case <-sig: fmt.Println("\nStopped watching.") killProcess() return case <-ticker.C: currentMod := getLastMod(absPath) if currentMod.After(lastMod) { fmt.Println("🔄 Change detected, restarting...") killProcess() runProcess(absPath) lastMod = currentMod } } } }, }
Functions ¶
This section is empty.
Types ¶
This section is empty.
Click to show internal directories.
Click to hide internal directories.