chore(io): Migrate internal/cmd/sdk, pkgcmd, and workspace to Medium abstraction

This commit is contained in:
Snider 2026-02-02 00:49:09 +00:00
parent d73ed87485
commit 3db61841bd
9 changed files with 43 additions and 29 deletions

View file

@ -9,6 +9,7 @@ import (
"strings"
"github.com/host-uk/core/pkg/i18n"
coreio "github.com/host-uk/core/pkg/io"
"github.com/host-uk/core/pkg/repos"
"github.com/spf13/cobra"
)
@ -73,12 +74,12 @@ func runPkgInstall(repoArg, targetDir string, addToRegistry bool) error {
repoPath := filepath.Join(targetDir, repoName)
if _, err := os.Stat(filepath.Join(repoPath, ".git")); err == nil {
if _, err := coreio.Local.List(filepath.Join(repoPath, ".git")); err == nil {
fmt.Printf("%s %s\n", dimStyle.Render(i18n.Label("skip")), i18n.T("cmd.pkg.install.already_exists", map[string]string{"Name": repoName, "Path": repoPath}))
return nil
}
if err := os.MkdirAll(targetDir, 0755); err != nil {
if err := coreio.Local.EnsureDir(targetDir); err != nil {
return fmt.Errorf("%s: %w", i18n.T("i18n.fail.create", "directory"), err)
}
@ -123,18 +124,17 @@ func addToRegistryFile(org, repoName string) error {
return nil
}
f, err := os.OpenFile(regPath, os.O_APPEND|os.O_WRONLY, 0644)
content, err := coreio.Local.Read(regPath)
if err != nil {
return err
}
defer f.Close()
repoType := detectRepoType(repoName)
entry := fmt.Sprintf("\n %s:\n type: %s\n description: (installed via core pkg install)\n",
repoName, repoType)
_, err = f.WriteString(entry)
return err
content += entry
return coreio.Local.Write(regPath, content)
}
func detectRepoType(name string) string {

View file

@ -3,12 +3,12 @@ package pkgcmd
import (
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/host-uk/core/pkg/i18n"
coreio "github.com/host-uk/core/pkg/io"
"github.com/host-uk/core/pkg/repos"
"github.com/spf13/cobra"
)
@ -58,7 +58,7 @@ func runPkgList() error {
for _, r := range allRepos {
repoPath := filepath.Join(basePath, r.Name)
exists := false
if _, err := os.Stat(filepath.Join(repoPath, ".git")); err == nil {
if _, err := coreio.Local.List(filepath.Join(repoPath, ".git")); err == nil {
exists = true
installed++
} else {
@ -147,7 +147,7 @@ func runPkgUpdate(packages []string, all bool) error {
for _, name := range toUpdate {
repoPath := filepath.Join(basePath, name)
if _, err := os.Stat(filepath.Join(repoPath, ".git")); os.IsNotExist(err) {
if _, err := coreio.Local.List(filepath.Join(repoPath, ".git")); err != nil {
fmt.Printf(" %s %s (%s)\n", dimStyle.Render("○"), name, i18n.T("cmd.pkg.update.not_installed"))
skipped++
continue
@ -219,7 +219,7 @@ func runPkgOutdated() error {
for _, r := range reg.List() {
repoPath := filepath.Join(basePath, r.Name)
if _, err := os.Stat(filepath.Join(repoPath, ".git")); os.IsNotExist(err) {
if _, err := coreio.Local.List(filepath.Join(repoPath, ".git")); err != nil {
notInstalled++
continue
}

View file

@ -2,9 +2,10 @@ package sdk
import (
"fmt"
"os"
"path/filepath"
"strings"
coreio "github.com/host-uk/core/pkg/io"
)
// commonSpecPaths are checked in order when no spec is configured.
@ -25,7 +26,7 @@ func (s *SDK) DetectSpec() (string, error) {
// 1. Check configured path
if s.config.Spec != "" {
specPath := filepath.Join(s.projectDir, s.config.Spec)
if _, err := os.Stat(specPath); err == nil {
if coreio.Local.IsFile(specPath) {
return specPath, nil
}
return "", fmt.Errorf("sdk.DetectSpec: configured spec not found: %s", s.config.Spec)
@ -34,7 +35,7 @@ func (s *SDK) DetectSpec() (string, error) {
// 2. Check common paths
for _, p := range commonSpecPaths {
specPath := filepath.Join(s.projectDir, p)
if _, err := os.Stat(specPath); err == nil {
if coreio.Local.IsFile(specPath) {
return specPath, nil
}
}
@ -51,12 +52,12 @@ func (s *SDK) DetectSpec() (string, error) {
// detectScramble checks for Laravel Scramble and exports the spec.
func (s *SDK) detectScramble() (string, error) {
composerPath := filepath.Join(s.projectDir, "composer.json")
if _, err := os.Stat(composerPath); err != nil {
if !coreio.Local.IsFile(composerPath) {
return "", fmt.Errorf("no composer.json")
}
// Check for scramble in composer.json
data, err := os.ReadFile(composerPath)
data, err := coreio.Local.Read(composerPath)
if err != nil {
return "", err
}
@ -71,8 +72,7 @@ func (s *SDK) detectScramble() (string, error) {
}
// containsScramble checks if composer.json includes scramble.
func containsScramble(data []byte) bool {
content := string(data)
func containsScramble(content string) bool {
return strings.Contains(content, "dedoc/scramble") ||
strings.Contains(content, "\"scramble\"")
}

View file

@ -62,7 +62,7 @@ func TestContainsScramble(t *testing.T) {
}
for _, tt := range tests {
assert.Equal(t, tt.expected, containsScramble([]byte(tt.data)))
assert.Equal(t, tt.expected, containsScramble(tt.data))
}
}

View file

@ -6,6 +6,8 @@ import (
"os"
"os/exec"
"path/filepath"
coreio "github.com/host-uk/core/pkg/io"
)
// GoGenerator generates Go SDKs from OpenAPI specs.
@ -34,7 +36,7 @@ func (g *GoGenerator) Install() string {
// Generate creates SDK from OpenAPI spec.
func (g *GoGenerator) Generate(ctx context.Context, opts Options) error {
if err := os.MkdirAll(opts.OutputDir, 0755); err != nil {
if err := coreio.Local.EnsureDir(opts.OutputDir); err != nil {
return fmt.Errorf("go.Generate: failed to create output dir: %w", err)
}
@ -61,7 +63,7 @@ func (g *GoGenerator) generateNative(ctx context.Context, opts Options) error {
}
goMod := fmt.Sprintf("module %s\n\ngo 1.21\n", opts.PackageName)
return os.WriteFile(filepath.Join(opts.OutputDir, "go.mod"), []byte(goMod), 0644)
return coreio.Local.Write(filepath.Join(opts.OutputDir, "go.mod"), goMod)
}
func (g *GoGenerator) generateDocker(ctx context.Context, opts Options) error {

View file

@ -6,6 +6,8 @@ import (
"os"
"os/exec"
"path/filepath"
coreio "github.com/host-uk/core/pkg/io"
)
// PHPGenerator generates PHP SDKs from OpenAPI specs.
@ -38,7 +40,7 @@ func (g *PHPGenerator) Generate(ctx context.Context, opts Options) error {
return fmt.Errorf("php.Generate: Docker is required but not available")
}
if err := os.MkdirAll(opts.OutputDir, 0755); err != nil {
if err := coreio.Local.EnsureDir(opts.OutputDir); err != nil {
return fmt.Errorf("php.Generate: failed to create output dir: %w", err)
}

View file

@ -6,6 +6,8 @@ import (
"os"
"os/exec"
"path/filepath"
coreio "github.com/host-uk/core/pkg/io"
)
// PythonGenerator generates Python SDKs from OpenAPI specs.
@ -34,7 +36,7 @@ func (g *PythonGenerator) Install() string {
// Generate creates SDK from OpenAPI spec.
func (g *PythonGenerator) Generate(ctx context.Context, opts Options) error {
if err := os.MkdirAll(opts.OutputDir, 0755); err != nil {
if err := coreio.Local.EnsureDir(opts.OutputDir); err != nil {
return fmt.Errorf("python.Generate: failed to create output dir: %w", err)
}

View file

@ -6,6 +6,8 @@ import (
"os"
"os/exec"
"path/filepath"
coreio "github.com/host-uk/core/pkg/io"
)
// TypeScriptGenerator generates TypeScript SDKs from OpenAPI specs.
@ -38,7 +40,7 @@ func (g *TypeScriptGenerator) Install() string {
// Generate creates SDK from OpenAPI spec.
func (g *TypeScriptGenerator) Generate(ctx context.Context, opts Options) error {
if err := os.MkdirAll(opts.OutputDir, 0755); err != nil {
if err := coreio.Local.EnsureDir(opts.OutputDir); err != nil {
return fmt.Errorf("typescript.Generate: failed to create output dir: %w", err)
}

View file

@ -5,6 +5,7 @@ import (
"os"
"path/filepath"
coreio "github.com/host-uk/core/pkg/io"
"gopkg.in/yaml.v3"
)
@ -28,9 +29,14 @@ func DefaultConfig() *WorkspaceConfig {
// Returns nil if no config file exists (caller should check for nil).
func LoadConfig(dir string) (*WorkspaceConfig, error) {
path := filepath.Join(dir, ".core", "workspace.yaml")
data, err := os.ReadFile(path)
data, err := coreio.Local.Read(path)
if err != nil {
if os.IsNotExist(err) {
// If using Local.Read, it returns error on not found.
// We can check if file exists first or handle specific error if exposed.
// Simplest is to check existence first or assume IsNotExist.
// Since we don't have easy IsNotExist check on coreio error returned yet (uses wrapped error),
// let's check IsFile first.
if !coreio.Local.IsFile(path) {
// Try parent directory
parent := filepath.Dir(dir)
if parent != dir {
@ -43,7 +49,7 @@ func LoadConfig(dir string) (*WorkspaceConfig, error) {
}
config := DefaultConfig()
if err := yaml.Unmarshal(data, config); err != nil {
if err := yaml.Unmarshal([]byte(data), config); err != nil {
return nil, fmt.Errorf("failed to parse workspace config: %w", err)
}
@ -57,7 +63,7 @@ func LoadConfig(dir string) (*WorkspaceConfig, error) {
// SaveConfig saves the configuration to the given directory's .core/workspace.yaml.
func SaveConfig(dir string, config *WorkspaceConfig) error {
coreDir := filepath.Join(dir, ".core")
if err := os.MkdirAll(coreDir, 0755); err != nil {
if err := coreio.Local.EnsureDir(coreDir); err != nil {
return fmt.Errorf("failed to create .core directory: %w", err)
}
@ -67,7 +73,7 @@ func SaveConfig(dir string, config *WorkspaceConfig) error {
return fmt.Errorf("failed to marshal workspace config: %w", err)
}
if err := os.WriteFile(path, data, 0644); err != nil {
if err := coreio.Local.Write(path, string(data)); err != nil {
return fmt.Errorf("failed to write workspace config: %w", err)
}
@ -82,7 +88,7 @@ func FindWorkspaceRoot() (string, error) {
}
for {
if _, err := os.Stat(filepath.Join(dir, ".core", "workspace.yaml")); err == nil {
if coreio.Local.IsFile(filepath.Join(dir, ".core", "workspace.yaml")) {
return dir, nil
}