Documentation
¶
Overview ¶
Package codemod provides helpers for codemods and project automation.
Package codemod provides helpers for codemods and project automation. This file contains the copilot command and related functionality.
Package codemod provides helpers for codemods and project automation. This file contains the lint-setup command and related functionality.
Package codemod provides helpers for codemods and project automation. This file contains the prettier formatting command.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var CodemodCmd = &cobra.Command{
Use: "codemod",
Short: "Helpers for codemods and project automation",
Long: `Run codemods or setup helpers for various project types.`,
}
CodemodCmd is the root command for codemod-related helpers and automation.
var CopilotSetupCmd = &cobra.Command{ Use: "copilot", Short: "Setup custom Copilot instructions file", Long: `Create a base custom Copilot instructions file at .github/copilot-instructions.md. By default, this command assumes you are in the root of a Git repository. Use --force to bypass this check.`, Run: func(cmd *cobra.Command, _args []string) { force, _ := cmd.Flags().GetBool("force") if !force { if !isGitRepository() { log.Error("Not in a Git repository. Use --force to bypass this check.") return } } if err := createCopilotInstructions(); err != nil { log.Error("Failed to create Copilot instructions: %v", err) return } log.Success("Copilot instructions file created at .github/copilot-instructions.md") }, }
CopilotSetupCmd creates a base custom Copilot instructions file in .github/copilot-instructions.md.
var LintSetupCmd = &cobra.Command{ Use: "lint-setup", Short: "Setup linting and formatting for a Node.js project", Long: `Install and configure linting, formatting, and pre-commit hooks for a Node.js project (eslint, prettier, husky, etc).`, Run: func(cmd *cobra.Command, _args []string) { if _, err := os.Stat("package.json"); errors.Is(err, os.ErrNotExist) { log.Error("package.json not found in current directory") return } if err := installLintDependencies(echo); err != nil { log.Error("package manager install failed: %v", err) return } if err := writeESLintConfig(echo); err != nil { log.Error("Failed to write eslint.config.mjs: %v", err) return } if err := updatePackageJSON(); err != nil { log.Error("Failed to update package.json: %v", err) return } if err := setupHusky(); err != nil { log.Error("Failed to set up Husky: %v", err) return } if !echo { checkRedundantDependencies() } log.Success("Linting, formatting, and pre-commit hooks are set up!") }, }
LintSetupCmd sets up linting, formatting, and pre-commit hooks for a Node.js project.
var NativeCmd = &cobra.Command{ Use: "native [projectName]", Short: "Bootstrap a new React Native Expo project with gvtech-design", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { projectName := args[0] targetDir := filepath.Join(os.Getenv("PWD"), projectName) if _, err := os.Stat(targetDir); !os.IsNotExist(err) { return fmt.Errorf("directory %s already exists", projectName) } fmt.Printf("🚀 Bootstrapping Native project: %s...\n", projectName) createCmd := execCommand("bunx", "create-expo-app@latest", projectName) createCmd.Stdout = log.Writer() createCmd.Stderr = log.ErrorWriter() if err := createCmd.Run(); err != nil { return fmt.Errorf("failed to create expo app: %w", err) } log.Info("Installing gvtech-design Native dependencies...") installCmd := execCommand( "bun", "add", "nativewind@^4.2.2", "tailwindcss@^3.4.1", "react-native-reanimated@^4.3.1", "lucide-react-native", "@gv-tech/ui-native", "@gv-tech/ui-core", "@gv-tech/design-tokens", "clsx", "tailwind-merge", ) installCmd.Dir = targetDir installCmd.Stdout = log.Writer() installCmd.Stderr = log.ErrorWriter() if err := installCmd.Run(); err != nil { return fmt.Errorf("failed to install dependencies: %w", err) } log.Info("Configuring Tailwind & NativeWind...") tailwindConfig := `/** @type {import('tailwindcss').Config} */ module.exports = { content: [ "./app/**/*.{js,jsx,ts,tsx}", "./components/**/*.{js,jsx,ts,tsx}", "./node_modules/@gv-tech/ui-native/src/**/*.{js,jsx,ts,tsx}" ], presets: [require("nativewind/preset")], theme: { extend: {}, }, plugins: [], }; ` if err := os.WriteFile( filepath.Join(targetDir, "tailwind.config.js"), []byte(tailwindConfig), 0o644, ); err != nil { return fmt.Errorf("failed to write tailwind.config.js: %w", err) } babelConfig := `module.exports = function (api) { api.cache(true); return { presets: [ ["babel-preset-expo", { jsxImportSource: "nativewind" }], "nativewind/babel", ], plugins: [ "react-native-reanimated/plugin", ], }; }; ` if err := os.WriteFile(filepath.Join(targetDir, "babel.config.js"), []byte(babelConfig), 0o644); err != nil { return fmt.Errorf("failed to write babel.config.js: %w", err) } appIndex := `import { View } from "react-native"; import { Text } from "@gv-tech/ui-native/Text"; import { Button } from "@gv-tech/ui-native/Button"; export default function Index() { return ( <View className="flex-1 justify-center items-center p-4"> <Text className="text-2xl font-bold mb-4">gvtech-design Native</Text> <Button onPress={() => console.log("Pressed")}> <Text>Click Me</Text> </Button> </View> ); } ` appDir := filepath.Join(targetDir, "app") if err := os.MkdirAll(appDir, 0o755); err != nil { return fmt.Errorf("failed to create app dir: %w", err) } if err := os.WriteFile(filepath.Join(appDir, "index.tsx"), []byte(appIndex), 0o644); err != nil { return fmt.Errorf("failed to write app/index.tsx: %w", err) } log.Info("Native project %s bootstrapped successfully!", projectName) return nil }, }
var PrettierCmd = &cobra.Command{ Use: "prettier [path]", Short: "Format code with prettier using @eng618/prettier-config", Long: `Format code with prettier, automatically installing @eng618/prettier-config if not available. If no path is provided, formats the current directory.`, Run: func(cmd *cobra.Command, args []string) { targetPath := "." if len(args) > 0 { targetPath = args[0] } if err := runPrettier(targetPath); err != nil { log.Error("Failed to run prettier: %v", err) return } log.Success("Prettier formatting completed!") }, }
PrettierCmd formats the current directory with prettier, installing @eng618/prettier-config if needed.
var WebCmd = &cobra.Command{ Use: "web [projectName]", Short: "Bootstrap a new React web project with gvtech-design", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { projectName := args[0] targetDir := filepath.Join(os.Getenv("PWD"), projectName) if _, err := os.Stat(targetDir); !os.IsNotExist(err) { return fmt.Errorf("directory %s already exists", projectName) } log.Info("Bootstrapping Web project: %s...", projectName) createCmd := execCommand("bun", "create", "vite", projectName, "--template", "react-ts") createCmd.Stdout = log.Writer() createCmd.Stderr = log.ErrorWriter() if err := createCmd.Run(); err != nil { return fmt.Errorf("failed to create vite app: %w", err) } log.Info("Installing gvtech-design Web dependencies...") installCmd := execCommand( "bun", "add", "tailwindcss", "@tailwindcss/vite", "@gv-tech/ui-web", "@gv-tech/ui-core", "@gv-tech/design-tokens", "clsx", "tailwind-merge", "lucide-react", ) installCmd.Dir = targetDir installCmd.Stdout = log.Writer() installCmd.Stderr = log.ErrorWriter() if err := installCmd.Run(); err != nil { return fmt.Errorf("failed to install dependencies: %w", err) } log.Info("Configuring Tailwind...") viteConfig := `import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' // https://vite.dev/config/ export default defineConfig({ plugins: [ tailwindcss(), react() ], }) ` if err := os.WriteFile(filepath.Join(targetDir, "vite.config.ts"), []byte(viteConfig), 0o644); err != nil { return fmt.Errorf("failed to write vite.config.ts: %w", err) } indexCss := `@import "tailwindcss"; /* * This imports the design tokens from gvtech-design * In a real app you might want to import the CSS directly if provided by the package */ @layer theme { :root { /* Define base tokens here or import from @gv-tech/design-tokens */ } } ` if err := os.WriteFile(filepath.Join(targetDir, "src", "index.css"), []byte(indexCss), 0o644); err != nil { return fmt.Errorf("failed to write index.css: %w", err) } appTsx := `import { useState } from 'react' import { Button } from '@gv-tech/ui-web/Button' function App() { const [count, setCount] = useState(0) return ( <div className="flex flex-col items-center justify-center min-h-screen p-4 bg-background"> <h1 className="text-4xl font-bold mb-8">gvtech-design Web</h1> <div className="flex flex-col items-center gap-4"> <Button onClick={() => setCount((c) => c + 1)}> Count is {count} </Button> </div> </div> ) } export default App ` if err := os.WriteFile(filepath.Join(targetDir, "src", "App.tsx"), []byte(appTsx), 0o644); err != nil { return fmt.Errorf("failed to write App.tsx: %w", err) } log.Info("Web project %s bootstrapped successfully!", projectName) return nil }, }
Functions ¶
This section is empty.
Types ¶
This section is empty.