diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..df471c6 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,24 @@ +name: CI + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: 1.22 + + - name: Install dependencies + run: go mod tidy + + - name: Run tests + run: go test ./... diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..3a107e8 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,21 @@ +name: Deploy Documentation + +on: + push: + branches: + - main + +permissions: + contents: write + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + with: + python-version: 3.x + - run: pip install mkdocs-material + - run: go run ./cmd/core dev docgen + - run: mkdocs gh-deploy --force diff --git a/cmd/core-gui/main.go b/cmd/core-gui/main.go index 3d107b3..f15a36d 100644 --- a/cmd/core-gui/main.go +++ b/cmd/core-gui/main.go @@ -4,13 +4,7 @@ import ( "embed" "log" - "github.com/Snider/Core" - "github.com/Snider/Core/config" - "github.com/Snider/Core/crypt" - "github.com/Snider/Core/display" - "github.com/Snider/Core/help" - "github.com/Snider/Core/i18n" - "github.com/Snider/Core/workspace" + "github.com/Snider/Core/pkg/runtime" "github.com/wailsapp/wails/v3/pkg/application" ) @@ -18,32 +12,21 @@ import ( var assets embed.FS func main() { - app := application.New(application.Options{ Assets: application.AssetOptions{ Handler: application.AssetFileServerFS(assets), }, }) - coreService, err := core.New( - core.WithWails(app), - core.WithAssets(assets), - core.WithService(config.Register), - core.WithService(display.Register), - core.WithService(crypt.Register), - core.WithService(help.Register), - core.WithService(i18n.Register), - core.WithService(workspace.Register), - core.WithServiceLock(), - ) + rt, err := runtime.New(app) if err != nil { - log.Fatalf("Failed to initialize Core services: %v", err) + log.Fatal(err) } - app.RegisterService(application.NewService(coreService)) + app.Services.Add(application.NewService(rt)) err = app.Run() if err != nil { - panic(err) + log.Fatal(err) } } diff --git a/cmd/core-website/docs/core/config.md b/cmd/core-website/docs/core/config.md deleted file mode 100644 index 9926548..0000000 --- a/cmd/core-website/docs/core/config.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Core.Config ---- - -# Core.Config - -Short: App config and UI state persistence. - -## Overview -Stores and retrieves configuration, including window positions/sizes and user prefs. - -## Setup -```go -import ( - "github.com/Snider/Core" - "github.com/Snider/Core/config" -) -// Example of static dependency injection -configService, err := config.New() -if err != nil { - // handle error -} -app := core.New( - core.WithService(configService), - core.WithServiceLock(), -) - -// Example of dynamic dependency injection (used with core.WithService) -// app := core.New( -// core.WithService(config.Register), -// core.WithServiceLock(), -// ) -``` - -## Use -- Persist UI state automatically when using `Core.Display`. -- Read/write your own settings via the config API. diff --git a/cmd/core-website/docs/core/crypt.md b/cmd/core-website/docs/core/crypt.md deleted file mode 100644 index eb2b460..0000000 --- a/cmd/core-website/docs/core/crypt.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Core.Crypt ---- - -# Core.Crypt - -Short: Keys, encrypt/decrypt, sign/verify. - -## Overview -Simple wrappers around OpenPGP for common crypto tasks. - -## Setup -```go -import ( - "github.com/Snider/Core" - "github.com/Snider/Core/crypt" -) - -app := core.New( - core.WithService(crypt.Register), - core.WithServiceLock(), -) -``` - -## Use -- Generate keys -- Encrypt/decrypt data -- Sign/verify messages - -## Notes -- Uses [Proton Mail](https://pr.tn/ref/VZFX8H2VDCFG) OpenPGP fork. diff --git a/cmd/core-website/docs/core/display.md b/cmd/core-website/docs/core/display.md deleted file mode 100644 index 18ca7ac..0000000 --- a/cmd/core-website/docs/core/display.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Core.Display ---- - -# Core.Display - -Short: Windows, tray, and window state. - -## Overview -Manages Wails windows, remembers positions/sizes, exposes JS bindings, and integrates with `Core.Config` for persistence. - -## Setup -```go -import ( - "github.com/Snider/Core" - "github.com/Snider/Core/display" - "github.com/Snider/Core/config" - "github.com/wailsapp/wails/v3/pkg/application" -) - -configService, err := config.New() -if err != nil { - // handle error -} -displayService, err := display.New(configService) -if err != nil { - // handle error -} -app := core.New( - core.WithService(displayService), - core.WithServiceLock(), -) - -// Example of dynamic dependency injection (used with core.WithService) -// app := core.New( -// core.WithService(display.Register), -// core.WithServiceLock(), -// ) -``` - -## Use -- The main application window is typically managed by the `Display` service's `ServiceStartup`. -- To open additional windows or control existing ones, send `core.Message` actions. -- Save/restore state automatically when `Core.Config` is present. - -## Notes -- The `Display` service integrates with `Core.Config` to persist window states. -- Window management is primarily done through `core.ACTION` messages. diff --git a/cmd/core-website/docs/core/help.md b/cmd/core-website/docs/core/help.md deleted file mode 100644 index 7b5c5c6..0000000 --- a/cmd/core-website/docs/core/help.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Core.Help ---- - -# Core.Help - -Short: In‑app help and deep‑links. - -## Overview -Renders MkDocs content inside your app. Opens specific sections in new windows for contextual help. - -## Setup -```go -import ( - "github.com/Snider/Core" - "github.com/Snider/Core/help" -) - -core.New( - core.WithService(help.Register), - core.WithServiceLock(), -) -``` - -## Use -- Open docs home in a window: `help.Show()` -- Open a section: `help.ShowAt("core/display#setup")` -- Use short, descriptive headings to create stable anchors. - -## Notes -- Docs are built with MkDocs Material and included in the demo app assets. -- When viewed in the app, this documentation is served from Core.Help and is bundled into the app binary by default. diff --git a/cmd/core-website/docs/core/io.md b/cmd/core-website/docs/core/io.md deleted file mode 100644 index b4bd8d5..0000000 --- a/cmd/core-website/docs/core/io.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: Core.IO ---- - -# Core.IO - -Short: Local/remote filesystem helpers. - -## Overview -Abstracts filesystems (local, SFTP, WebDAV) behind a unified API for reading/writing and listing. - -## Setup -```go -import ( - "github.com/Snider/Core" - "github.com/Snider/Core/io" - "github.com/Snider/Core/io/sftp" - "github.com/Snider/Core/io/webdav" -) - -// Example of creating a local medium (pre-initialized) -localMedium := io.Local - -// Example of creating an SFTP medium -sftpConfig := sftp.ConnectionConfig{ - // ... configure SFTP connection -} -sftpMedium, err := io.NewSFTPMedium(sftpConfig) -if err != nil { - // handle error -} - -// Example of creating a WebDAV medium -webdavConfig := webdav.ConnectionConfig{ - // ... configure WebDAV connection -} -webdavMedium, err := io.NewWebDAVMedium(webdavConfig) -if err != nil { - // handle error -} - -// You can then pass these mediums to services that require an io.Medium -// For example, if a service's New function accepts an io.Medium: -// myService := myservice.New(localMedium) - -// If a service registers with core.WithService and needs an io.Medium, -// it would typically receive it during its ServiceStartup or via its New constructor. - -// The core.Core itself does not directly register io.Medium implementations -// as services in the same way as other modules, but rather consumes them. -app := core.New( - // ... other services - core.WithServiceLock(), -) -``` - -## Use -- Access the local filesystem: `io.Local` -- Create SFTP/WebDAV mediums: `io.NewSFTPMedium(...)`, `io.NewWebDAVMedium(...)` -- Read/write files using a `Medium`: `medium.Read(path)`, `medium.Write(path, data)` -- List directories (if supported by `Medium` implementation): `medium.List(path)` (Note: `List` is not currently in the `Medium` interface, but `FileGet`, `FileSet`, `EnsureDir`, `IsFile` are) -- Copy files between mediums: `io.Copy(sourceMedium, sourcePath, destMedium, destPath)` - -## Notes -- See package `pkg/io/sftp` and `pkg/io/webdav` for specific medium configurations. diff --git a/cmd/core-website/docs/core/workspace.md b/cmd/core-website/docs/core/workspace.md deleted file mode 100644 index 1f6c977..0000000 --- a/cmd/core-website/docs/core/workspace.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Core.Workspace ---- - -# Core.Workspace - -Short: Manages user workspaces. - -## Overview -Provides functionality for creating, switching, and managing isolated user workspaces, including file storage and cryptographic operations within those workspaces. - -## Setup -```go -import ( - "github.com/Snider/Core" - "github.com/Snider/Core/workspace" - "github.com/Snider/Core/io" -) - -workspaceService, err := workspace.New() -if err != nil { - // handle error -} -app := core.New( - core.WithService(workspaceService), - core.WithServiceLock(), -) - -// Example of dynamic dependency injection (used with core.WithService) -// If using dynamic injection, the io.Medium dependency would be resolved -// during ServiceStartup, typically by another service providing it. -// app := core.New( -// core.WithService(workspace.Register), -// core.WithServiceLock(), -// ) -``` - -## Use -- Create a new workspace: `ws.CreateWorkspace("my-project", "my-password")` -- Switch to an existing workspace: `ws.SwitchWorkspace("my-project-id")` -- Get a file from the active workspace: `ws.WorkspaceFileGet("config.json")` -- Set a file in the active workspace: `ws.WorkspaceFileSet("data.txt", "some content")` - -## Notes -- Workspaces are obfuscated and secured with OpenPGP. -- Integrates with `Core.Config` for workspace directory management. diff --git a/cmd/core/cmd/docgen.go b/cmd/core/cmd/docgen.go new file mode 100644 index 0000000..465e3b3 --- /dev/null +++ b/cmd/core/cmd/docgen.go @@ -0,0 +1,185 @@ +package cmd + +import ( + "bytes" + "fmt" + "go/ast" + "go/doc" + "go/parser" + "go/token" + "os" + "path/filepath" + "strings" + "text/template" + + "github.com/leaanthony/clir" +) + +func AddDocGenCommand(parent *clir.Command) { + cmd := parent.NewSubCommand("docgen", "Generates Markdown documentation for the public API of the services.") + cmd.Action(func() error { + return runDocGen() + }) +} + +func runDocGen() error { + const pkgDir = "pkg" + const outDir = "docs/services" + + if err := os.MkdirAll(outDir, 0755); err != nil { + return fmt.Errorf("failed to create output directory: %w", err) + } + + dirs, err := os.ReadDir(pkgDir) + if err != nil { + return fmt.Errorf("failed to read pkg directory: %w", err) + } + + for _, dir := range dirs { + if !dir.IsDir() { + continue + } + serviceName := dir.Name() + servicePath := filepath.Join(pkgDir, serviceName) + + if err := generateDocsForService(servicePath, serviceName, outDir); err != nil { + fmt.Printf("Warning: Could not generate docs for service '%s': %v\n", serviceName, err) + } + } + + fmt.Println("Documentation generated successfully in", outDir) + return nil +} + +func generateDocsForService(servicePath, serviceName, outDir string) error { + fset := token.NewFileSet() + filter := func(info os.FileInfo) bool { + return !strings.HasSuffix(info.Name(), "_test.go") + } + pkgs, err := parser.ParseDir(fset, servicePath, filter, parser.ParseComments) + if err != nil { + return fmt.Errorf("failed to parse directory %s: %w", servicePath, err) + } + + internalPath := filepath.Join(servicePath, "internal") + if _, err := os.Stat(internalPath); err == nil { + pkgs, err = parser.ParseDir(fset, internalPath, nil, parser.ParseComments) + if err != nil { + return fmt.Errorf("failed to parse internal directory %s: %w", internalPath, err) + } + } + + var pkg *ast.Package + for _, p := range pkgs { + pkg = p + break + } + if pkg == nil { + return fmt.Errorf("no package found in %s", servicePath) + } + + docPkg := doc.New(pkg, "./", doc.AllDecls) + + md, err := generateMarkdown(docPkg) + if err != nil { + return fmt.Errorf("failed to generate markdown: %w", err) + } + + outFile := filepath.Join(outDir, serviceName+".md") + return os.WriteFile(outFile, []byte(md), 0644) +} + +const docTemplate = `--- +title: {{ .Name }} +--- +# Service: ` + "`" + `{{ .Name }}` + "`" + ` + +{{ .Doc }} + +{{if .Consts}} +## Constants +{{range .Consts}} +` + "```go" + ` +{{- range .Names }}{{ . }}{{ end }} +` + "```" + ` +{{ .Doc }} +{{end}}{{end}} + +{{if .Types}} +## Types +{{range .Types}} +### ` + "`" + `type {{ .Name }}` + "`" + ` +` + "```go" + ` +type {{ .Name }} {{.Decl | formatNode}} +` + "```" + ` +{{ .Doc }} + +{{if .Methods}} +#### Methods +{{range .Methods}} +- ` + "`" + `{{ .Name }}({{ .Decl.Type.Params | formatParams }}) {{ .Decl.Type.Results | formatParams }}` + "`" + `: {{ .Doc | oneLine }} +{{end}}{{end}} + +{{end}}{{end}} + +{{if .Funcs}} +## Functions +{{range .Funcs}} +- ` + "`" + `{{ .Name }}({{ .Decl.Type.Params | formatParams }}) {{ .Decl.Type.Results | formatParams }}` + "`" + `: {{ .Doc | oneLine }} +{{end}}{{end}} +` + +func generateMarkdown(pkg *doc.Package) (string, error) { + funcMap := template.FuncMap{ + "oneLine": func(s string) string { + return strings.TrimSpace(strings.Replace(s, "\n", " ", -1)) + }, + "formatNode": func(decl *ast.GenDecl) string { + if len(decl.Specs) == 0 { + return "" + } + spec := decl.Specs[0].(*ast.TypeSpec) + return nodeToString(spec.Type) + }, + "formatParams": func(fieldList *ast.FieldList) string { + if fieldList == nil { + return "" + } + var params []string + for _, p := range fieldList.List { + var names []string + for _, name := range p.Names { + names = append(names, name.Name) + } + typeStr := nodeToString(p.Type) + if len(names) > 0 { + params = append(params, strings.Join(names, ", ")+" "+typeStr) + } else { + params = append(params, typeStr) + } + } + return strings.Join(params, ", ") + }, + } + + tmpl, err := template.New("doc").Funcs(funcMap).Parse(docTemplate) + if err != nil { + return "", err + } + + var buf bytes.Buffer + if err := tmpl.Execute(&buf, pkg); err != nil { + return "", err + } + + return buf.String(), nil +} + +func nodeToString(node ast.Node) string { + var buf bytes.Buffer + err := ast.Fprint(&buf, token.NewFileSet(), node, nil) + if err != nil { + return "" + } + return buf.String() +} diff --git a/cmd/core/cmd/root.go b/cmd/core/cmd/root.go index cbadbb1..5cc58c4 100644 --- a/cmd/core/cmd/root.go +++ b/cmd/core/cmd/root.go @@ -69,6 +69,7 @@ func Execute() error { AddAPICommands(devCmd) AddTestGenCommand(devCmd) AddSyncCommand(devCmd) + AddDocGenCommand(devCmd) AddBuildCommand(app) AddTviewCommand(app) // Run the application diff --git a/cmd/core/go.mod b/cmd/core/go.mod index 032e9ae..b8e8832 100644 --- a/cmd/core/go.mod +++ b/cmd/core/go.mod @@ -3,12 +3,13 @@ module github.com/Snider/Core/cmd/core go 1.23.0 require ( - github.com/charmbracelet/bubbletea v0.26.6 github.com/charmbracelet/lipgloss v1.1.0 github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be github.com/leaanthony/clir v1.7.0 + github.com/leaanthony/debme v1.2.1 + github.com/leaanthony/gosod v1.0.4 github.com/rivo/tview v0.42.0 - github.com/spf13/cobra v1.8.0 + golang.org/x/net v0.25.0 golang.org/x/text v0.21.0 ) @@ -18,23 +19,14 @@ require ( github.com/charmbracelet/x/ansi v0.8.0 // indirect github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect github.com/charmbracelet/x/term v0.2.1 // indirect - github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/gdamore/encoding v1.0.1 // indirect github.com/gdamore/tcell/v2 v2.8.1 // indirect - github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/leaanthony/debme v1.2.1 // indirect - github.com/leaanthony/gosod v1.0.4 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-localereader v0.0.1 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect - github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/termenv v0.16.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/spf13/pflag v1.0.5 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.33.0 // indirect golang.org/x/term v0.32.0 // indirect ) diff --git a/cmd/core/go.sum b/cmd/core/go.sum index ad84172..ff8622b 100644 --- a/cmd/core/go.sum +++ b/cmd/core/go.sum @@ -1,7 +1,5 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= -github.com/charmbracelet/bubbletea v0.26.6 h1:zTCWSuST+3yZYZnVSvbXwKOPRSNZceVeqpzOLN2zq1s= -github.com/charmbracelet/bubbletea v0.26.6/go.mod h1:dz8CWPlfCCGLFbBlTY4N7bjLiyOGDJEnd2Muu7pOWhk= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= @@ -14,36 +12,28 @@ github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQ github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL2kskAlV9ckgEsNQXscjIaLiOYiZ75d4e94E6dcQ= github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= -github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw= github.com/gdamore/encoding v1.0.1/go.mod h1:0Z0cMFinngz9kS1QfMjCP8TY7em3bZYeeklsSDPivEo= github.com/gdamore/tcell/v2 v2.8.1 h1:KPNxyqclpWpWQlPLx6Xui1pMk8S+7+R37h3g07997NU= github.com/gdamore/tcell/v2 v2.8.1/go.mod h1:bj8ori1BG3OYMjmb3IklZVWfZUJ1UBQt9JXrOCOhGWw= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/leaanthony/clir v1.7.0 h1:xiAnhl7ryPwuH3ERwPWZp/pCHk8wTeiwuAOt6MiNyAw= github.com/leaanthony/clir v1.7.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc= github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA= github.com/leaanthony/gosod v1.0.4 h1:YLAbVyd591MRffDgxUOU1NwLhT9T1/YiwjKZpkNFeaI= github.com/leaanthony/gosod v1.0.4/go.mod h1:GKuIL0zzPj3O1SdWQOdgURSuhkF+Urizzxh26t9f1cw= +github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY= github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= +github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= +github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= -github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= -github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= -github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= -github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/rivo/tview v0.42.0 h1:b/ftp+RxtDsHSaynXTbJb+/n/BxDEi+W3UfF5jILK6c= @@ -52,11 +42,6 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -79,6 +64,7 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -86,12 +72,10 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -131,5 +115,3 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/cmd/examples/core-task-change/main.go b/cmd/examples/core-task-change/main.go index b2cf5cb..f15a36d 100644 --- a/cmd/examples/core-task-change/main.go +++ b/cmd/examples/core-task-change/main.go @@ -2,12 +2,9 @@ package main import ( "embed" + "log" - "github.com/Snider/Core" - "github.com/Snider/Core/config" - "github.com/Snider/Core/crypt" - "github.com/Snider/Core/display" - "github.com/Snider/Core/help" + "github.com/Snider/Core/pkg/runtime" "github.com/wailsapp/wails/v3/pkg/application" ) @@ -15,27 +12,21 @@ import ( var assets embed.FS func main() { - app := application.New(application.Options{ Assets: application.AssetOptions{ Handler: application.AssetFileServerFS(assets), }, }) - coreService := core.New( - core.WithWails(app), - core.WithAssets(assets), - core.WithService(config.New), - core.WithService(display.New), - core.WithService(crypt.New), - core.WithService(help.New), - core.WithServiceLock(), - ) - - app.RegisterService(application.NewService(coreService)) - - err := app.Run() + rt, err := runtime.New(app) if err != nil { - panic(err) + log.Fatal(err) + } + + app.Services.Add(application.NewService(rt)) + + err = app.Run() + if err != nil { + log.Fatal(err) } } diff --git a/config/config.go b/config/config.go deleted file mode 100644 index 67c5ed4..0000000 --- a/config/config.go +++ /dev/null @@ -1,27 +0,0 @@ -// package config provides the public API for the config service. -package config - -import ( - // Import the internal implementation with an alias. - impl "github.com/Snider/Core/pkg/config" - - // Import the core contracts to re-export the interface. - "github.com/Snider/Core/pkg/core" -) - -// New is a public function that points to the real function in the implementation package. -var New = impl.New - -// Register is a public function that points to the real function in the implementation package. -var Register = impl.Register - -// Options is the public type for the Options service. It is a type alias -// to the underlying implementation, making it transparent to the user. -type Options = impl.Options - -// Service is the public type for the Service service. It is a type alias -// to the underlying implementation, making it transparent to the user. -type Service = impl.Service - -// Config is the public interface for the config service. -type Config = core.Config diff --git a/config/config_test.go b/config/config_test.go deleted file mode 100644 index ce9f74c..0000000 --- a/config/config_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package config_test - -import ( - "testing" - - "github.com/Snider/Core/config" - "github.com/Snider/Core/pkg/core" -) - -// TestNew ensures that the public constructor New is available. -func TestNew(t *testing.T) { - if config.New == nil { - t.Fatal("config.New constructor is nil") - } - // Note: This is a basic check. Some services may require a core instance - // or other arguments. This test can be expanded as needed. -} - -// TestRegister ensures that the public factory Register is available. -func TestRegister(t *testing.T) { - if config.Register == nil { - t.Fatal("config.Register factory is nil") - } -} - -// TestInterfaceCompliance ensures that the public Service type correctly -// implements the public Config interface. This is a compile-time check. -func TestInterfaceCompliance(t *testing.T) { - // This is a compile-time check. If it compiles, the test passes. - var _ core.Config = (*config.Service)(nil) -} diff --git a/core.go b/core.go deleted file mode 100644 index 1929b0c..0000000 --- a/core.go +++ /dev/null @@ -1,69 +0,0 @@ -// Package core provides the primary public API for the Core framework. -// It acts as a facade, re-exporting types and functions from the internal -// core package to provide a clean, root-level import path. -package core - -import ( - // Import the internal core package which contains the actual definitions. - impl "github.com/Snider/Core/pkg/core" -) - -// --- Primary Types & Constructors --- - -// Core is the main application container. -type Core = impl.Core - -// New is the primary constructor for the Core framework. -var New = impl.New - -// --- Core Options --- - -// WithService is a helper function to create a service option. -var WithService = impl.WithService - -// WithWails provides the Wails application instance to the core. -var WithWails = impl.WithWails - -// WithAssets provides the application's assets to the core. -var WithAssets = impl.WithAssets - -// WithServiceLock prevents new services from being registered after startup. -var WithServiceLock = impl.WithServiceLock - -// --- Service Runtime --- - -// Runtime is a helper struct embedded in services to provide access to the core application. -type Runtime[T any] = impl.Runtime[T] - -// NewRuntime creates a new Runtime instance for a service. -func NewRuntime[T any](c *Core, opts T) *Runtime[T] { - return impl.NewRuntime(c, opts) -} - -// --- Messages & Actions --- - -// Message is the interface for all IPC messages. -type Message = impl.Message - -// ActionServiceStartup is a message sent when services should perform their startup tasks. -type ActionServiceStartup = impl.ActionServiceStartup - -// --- Service Interfaces (from pkg/core/interfaces.go) --- - -// Config is the public interface for the configuration service. -type Config = *impl.Config - -// Display is the public interface for the display service. -type Display = impl.Display - -// Help is the public interface for the help service. -type Help = impl.Help - -// Crypt is the public interface for the cryptography service. -type Crypt = impl.Crypt - -// I18n is the public interface for the internationalization service. -type I18n = impl.I18n - -// Workspace is the public interface for the workspace service. -type Workspace = impl.Workspace diff --git a/core_test.go b/core_test.go deleted file mode 100644 index 1560c5a..0000000 --- a/core_test.go +++ /dev/null @@ -1,125 +0,0 @@ -package core_test - -import ( - "go/parser" - "go/token" - "os" - "path/filepath" - "strings" - "testing" -) - -// TestPublicAPICompleteness dynamically discovers all public services and ensures -// their top-level API packages are in sync with their internal implementations. -func TestPublicAPICompleteness(t *testing.T) { - pkgDir := "pkg" - - // 1. Discover all potential service packages in the pkg/ directory. - internalDirs, err := os.ReadDir(pkgDir) - if err != nil { - t.Fatalf("Failed to read pkg directory: %v", err) - } - - var allMissingSymbols []string - - for _, dir := range internalDirs { - if !dir.IsDir() || dir.Name() == "core" { - continue // Skip files and the core package itself - } - - serviceName := dir.Name() - topLevelDir := serviceName - - // 2. Check if a corresponding top-level public API directory exists. - if _, err := os.Stat(topLevelDir); os.IsNotExist(err) { - continue // Not a public service, so we skip it. - } - - // 3. Define paths for public and internal Go files. - publicFile := filepath.Join(topLevelDir, serviceName+".go") - internalFile := filepath.Join(pkgDir, serviceName, serviceName+".go") - - // Ensure both files exist before trying to parse them. - if _, err := os.Stat(publicFile); os.IsNotExist(err) { - t.Logf("Skipping service '%s': public API file not found at %s", serviceName, publicFile) - continue - } - if _, err := os.Stat(internalFile); os.IsNotExist(err) { - t.Logf("Skipping service '%s': internal implementation file not found at %s", serviceName, internalFile) - continue - } - - // 4. Compare the exported symbols. - missing, err := compareExports(publicFile, internalFile) - if err != nil { - t.Errorf("Error comparing exports for service '%s': %v", serviceName, err) - continue - } - - if len(missing) > 0 { - msg := "- Service: " + serviceName + "\n - Missing: " + strings.Join(missing, ", ") - allMissingSymbols = append(allMissingSymbols, msg) - } - } - - // 5. Report all discrepancies at the end. - if len(allMissingSymbols) > 0 { - t.Errorf("Public APIs are out of sync with internal implementations:\n\n%s", - strings.Join(allMissingSymbols, "\n")) - } -} - -// compareExports takes two file paths, parses them, and returns a list of -// symbols that are exported in the internal file but not the public one. -func compareExports(publicFile, internalFile string) ([]string, error) { - publicAPI, err := getExportedSymbols(publicFile) - if err != nil { - return nil, err - } - - internalImpl, err := getExportedSymbols(internalFile) - if err != nil { - return nil, err - } - - publicSymbols := make(map[string]bool) - for _, sym := range publicAPI { - publicSymbols[sym] = true - } - - var missingSymbols []string - for _, internalSym := range internalImpl { - // The public API re-exports the interface from core, so we don't expect it here. - if internalSym == "Config" { - continue - } - if !publicSymbols[internalSym] { - missingSymbols = append(missingSymbols, internalSym) - } - } - - return missingSymbols, nil -} - -// getExportedSymbols parses a Go file and returns a slice of its exported symbol names. -func getExportedSymbols(path string) ([]string, error) { - absPath, err := filepath.Abs(path) - if err != nil { - return nil, err - } - - fset := token.NewFileSet() - node, err := parser.ParseFile(fset, absPath, nil, parser.AllErrors) - if err != nil { - return nil, err - } - - var symbols []string - for name, obj := range node.Scope.Objects { - if token.IsExported(name) { - symbols = append(symbols, obj.Name) - } - } - - return symbols, nil -} diff --git a/crypt/crypt.go b/crypt/crypt.go deleted file mode 100644 index ba0328d..0000000 --- a/crypt/crypt.go +++ /dev/null @@ -1,46 +0,0 @@ -// package crypt provides the public API for the crypt service. -package crypt - -import ( - // Import the internal implementation with an alias. - impl "github.com/Snider/Core/pkg/crypt" - - // Import the core contracts to re-export the interface. - "github.com/Snider/Core/pkg/core" -) - -// Service is the public type for the Service service. It is a type alias -// to the underlying implementation, making it transparent to the user. -type Service = impl.Service - -// Options is the public type for the Options service. It is a type alias -// to the underlying implementation, making it transparent to the user. -type Options = impl.Options - -// HashType is the public type for the HashType service. It is a type alias -// to the underlying implementation, making it transparent to the user. -type HashType = impl.HashType - -// LTHN is a public constant that points to the real constant in the implementation package. -const LTHN = impl.LTHN - -// SHA512 is a public constant that points to the real constant in the implementation package. -const SHA512 = impl.SHA512 - -// SHA256 is a public constant that points to the real constant in the implementation package. -const SHA256 = impl.SHA256 - -// SHA1 is a public constant that points to the real constant in the implementation package. -const SHA1 = impl.SHA1 - -// MD5 is a public constant that points to the real constant in the implementation package. -const MD5 = impl.MD5 - -// New is a public function that points to the real function in the implementation package. -var New = impl.New - -// Register is a public function that points to the real function in the implementation package. -var Register = impl.Register - -// Crypt is the public interface for the crypt service. -type Crypt = core.Crypt diff --git a/crypt/crypt_test.go b/crypt/crypt_test.go deleted file mode 100644 index 3f31be2..0000000 --- a/crypt/crypt_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package crypt_test - -import ( - "testing" - - "github.com/Snider/Core/crypt" - "github.com/Snider/Core/pkg/core" -) - -// TestNew ensures that the public constructor New is available. -func TestNew(t *testing.T) { - if crypt.New == nil { - t.Fatal("crypt.New constructor is nil") - } - // Note: This is a basic check. Some services may require a core instance - // or other arguments. This test can be expanded as needed. -} - -// TestRegister ensures that the public factory Register is available. -func TestRegister(t *testing.T) { - if crypt.Register == nil { - t.Fatal("crypt.Register factory is nil") - } -} - -// TestInterfaceCompliance ensures that the public Service type correctly -// implements the public Crypt interface. This is a compile-time check. -func TestInterfaceCompliance(t *testing.T) { - // This is a compile-time check. If it compiles, the test passes. - var _ core.Crypt = (*crypt.Service)(nil) -} diff --git a/display/display.go b/display/display.go deleted file mode 100644 index 0d82365..0000000 --- a/display/display.go +++ /dev/null @@ -1,31 +0,0 @@ -// package display provides the public API for the display service. -package display - -import ( - // Import the internal implementation with an alias. - impl "github.com/Snider/Core/pkg/display" - - // Import the core contracts to re-export the interface. - "github.com/Snider/Core/pkg/core" -) - -// Options is the public type for the Options service. It is a type alias -// to the underlying implementation, making it transparent to the user. -type Options = impl.Options - -// Service is the public type for the Service service. It is a type alias -// to the underlying implementation, making it transparent to the user. -type Service = impl.Service - -// WindowOption is the public type for the WindowOption service. It is a type alias -// to the underlying implementation, making it transparent to the user. -type WindowOption = impl.WindowOption - -// New is a public function that points to the real function in the implementation package. -var New = impl.New - -// Register is a public function that points to the real function in the implementation package. -var Register = impl.Register - -// Display is the public interface for the display service. -type Display = core.Display diff --git a/display/display_test.go b/display/display_test.go deleted file mode 100644 index 628627e..0000000 --- a/display/display_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package display_test - -import ( - "testing" - - "github.com/Snider/Core/display" - "github.com/Snider/Core/pkg/core" -) - -// TestNew ensures that the public constructor New is available. -func TestNew(t *testing.T) { - if display.New == nil { - t.Fatal("display.New constructor is nil") - } - // Note: This is a basic check. Some services may require a core instance - // or other arguments. This test can be expanded as needed. -} - -// TestRegister ensures that the public factory Register is available. -func TestRegister(t *testing.T) { - if display.Register == nil { - t.Fatal("display.Register factory is nil") - } -} - -// TestInterfaceCompliance ensures that the public Service type correctly -// implements the public Display interface. This is a compile-time check. -func TestInterfaceCompliance(t *testing.T) { - // This is a compile-time check. If it compiles, the test passes. - var _ core.Display = (*display.Service)(nil) -} diff --git a/docs/core/config.md b/docs/core/config.md deleted file mode 100644 index afd6d4b..0000000 --- a/docs/core/config.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Core.Config ---- - -# Core.Config - -Short: App config and UI state persistence. - -## Overview -Stores and retrieves configuration, including window positions/sizes and user prefs. - -## Setup -```go -import ( - "github.com/Snider/Core" - "github.com/Snider/Core/config" -) -// Example of static dependency injection -configService, err := config.New() -if err != nil { - // handle error -} -app := core.New( - core.WithService(configService), - core.WithServiceLock(), -) - -// Example of dynamic dependency injection (used with core.WithService) -// app := core.New( -// core.WithService(config.Register), -// core.WithServiceLock(), -// ) -``` - -## Use -- Persist UI state automatically when using `Core.Display`. -- Read/write your own settings via the config API. - -## API -- `New() (*Service, error)` -- `Register(c *core.Core) (any, error)` -- `(s *Service) Save() error` -- `(s *Service) Get(key string, out any) error` -- `(s *Service) Set(key string, v any) error` diff --git a/docs/core/crypt.md b/docs/core/crypt.md deleted file mode 100644 index 3d461c5..0000000 --- a/docs/core/crypt.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: Core.Crypt ---- - -# Core.Crypt - -Short: Keys, encrypt/decrypt, sign/verify. - -## Overview -Simple wrappers around OpenPGP for common crypto tasks. - -## Setup -```go -import ( - "github.com/Snider/Core" - "github.com/Snider/Core/crypt" -) - -app := core.New( - core.WithService(crypt.Register), - core.WithServiceLock(), -) -``` - -## Use -- Generate keys -- Encrypt/decrypt data -- Sign/verify messages - -## API -- `Register(c *core.Core) error` -- `GenerateKey(opts ...Option) (*Key, error)` -- `Encrypt(pub *Key, data []byte) ([]byte, error)` -- `Decrypt(priv *Key, data []byte) ([]byte, error)` -- `Sign(priv *Key, data []byte) ([]byte, error)` -- `Verify(pub *Key, data, sig []byte) error` - -## Notes -- Uses [Proton Mail](https://pr.tn/ref/VZFX8H2VDCFG) OpenPGP fork. - - diff --git a/docs/core/display.md b/docs/core/display.md deleted file mode 100644 index 7f5a157..0000000 --- a/docs/core/display.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Core.Display ---- - -# Core.Display - -Short: Windows, tray, and window state. - -## Overview -Manages Wails windows, remembers positions/sizes, exposes JS bindings, and integrates with `Core.Config` for persistence. - -## Setup -```go -import ( - core "github.com/Snider/Core" - display "github.com/Snider/Core/pkg/display" - "github.com/wailsapp/wails/v3/pkg/application" // For WebviewWindowOptions - config "github.com/Snider/Core/pkg/config" // Assuming config service is available -) - -// Example of static dependency injection -configService, err := config.New() -if err != nil { - // handle error -} -displayService, err := display.New(configService) -if err != nil { - // handle error -} -app := core.New( - core.WithService(displayService), - core.WithServiceLock(), -) - -// Example of dynamic dependency injection (used with core.WithService) -// app := core.New( -// core.WithService(display.Register), -// core.WithServiceLock(), -// ) -``` - -## Use -- The main application window is typically managed by the `Display` service's `ServiceStartup`. -- To open additional windows or control existing ones, send `core.Message` actions. -- Save/restore state automatically when `Core.Config` is present. - -## API -- `New(cfg core.Config) (*Service, error)` -- `Register(c *core.Core) (any, error)` -- `(s *Service) ServiceName() string` -- `(s *Service) HandleIPCEvents(c *core.Core, msg core.Message) error` -- `(s *Service) ShowEnvironmentDialog()` -- `(s *Service) ServiceStartup(context.Context, application.ServiceOptions) error` - -## Example: Opening a new window via Action -```go -// In another service or component that has access to core.Core -func (myService *MyService) OpenNewWindow() error { - // Option 1: Using ActionOpenWindow struct - action := display.ActionOpenWindow{ - WebviewWindowOptions: application.WebviewWindowOptions{ - Name: "myNewWindow", - Title: "My New Window", - Width: 800, - Height: 600, - URL: "/some-path", - }, - } - return myService.Core().ACTION(action) - - // Option 2: Using a map[string]any (less type-safe but flexible) - // msg := map[string]any{ - // "action": "display.open_window", - // "name": "myNewWindow", - // "options": map[string]any{ - // "Title": "My New Window", - // "Width": 800, - // "Height": 600, - // "URL": "/some-path", - // }, - // } - // return myService.Core().ACTION(msg) -} -``` - -## Notes -- The `Display` service integrates with `Core.Config` to persist window states. -- Window management is primarily done through `core.ACTION` messages. diff --git a/docs/core/help.md b/docs/core/help.md deleted file mode 100644 index 22d74f0..0000000 --- a/docs/core/help.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: Core.Help ---- - -# Core.Help - -Short: In‑app help and deep‑links. - -## Overview -Renders MkDocs content inside your app. Opens specific sections in new windows for contextual help. - -## Setup -```go -package demo -import ( - "github.com/Snider/Core" - "github.com/Snider/Core/pkg/help" -) - -core.New( - core.WithService(help.Register), - core.WithServiceLock(), -) -``` - -## Use -- Open docs home in a window: `help.Show()` -- Open a section: `help.ShowAt("core/display#setup")` -- Use short, descriptive headings to create stable anchors. - -## API -- `New(cfg core.Config, disp core.Display) (*Service, error)` -- `Register(c *core.Core) (any, error)` -- `(s *Service) Show() error` -- `(s *Service) ShowAt(anchor string) error` - -## Notes -- Docs are built with MkDocs Material and included in the demo app assets. -- When viewed in the app, this documentation is served from Core.Help and is bundled into the app binary by default. diff --git a/docs/core/index.md b/docs/core/index.md deleted file mode 100644 index b137259..0000000 --- a/docs/core/index.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Core ---- - -# Core - -Short: Framework bootstrap and service container. - -## What it is -Core wires modules together, provides lifecycle hooks, and locks the service graph for clarity and safety. - -## Setup -```go -import ( - "github.com/Snider/Core/" - "github.com/wailsapp/wails/v3/pkg/application" - // Import other service packages you want to register, e.g.: - // "github.com/Snider/Core/config" - // "github.com/Snider/Core/display" -) - -// Create a new Wails application instance (if not already available) -wailsApp := application.New(application.Options{}) - -// Initialize Core with services and options -coreApp, err := core.New( - core.WithWails(wailsApp), // Integrate Wails app - // Register services using their Register function or a direct instance: - // core.WithService(config.Register), // Dynamic registration - // core.WithService(func(c *core.Core) (any, error) { return myServiceInstance, nil }), // Static registration - core.WithServiceLock(), // Lock services after initialization -) -if err != nil { - // handle error -} - -// You can then run your Wails application -// if err := wailsApp.Run(context.Background()); err != nil { -// // handle error -// } -``` - -## Use -- Initialize the Core framework with `core.New()`. -- Register services using `core.WithService()`. -- Access registered services using `core.Service()` or `core.ServiceFor[T]()`. -- Send actions to services using `(c *Core) ACTION()`. - -## API - -### Functions -- `New(opts ...Option) (*Core, error)`: Initializes a new Core instance. -- `WithService(factory func(*Core) (any, error)) Option`: Registers a service with Core. -- `WithWails(app *application.App) Option`: Integrates a Wails application instance with Core. -- `WithAssets(fs embed.FS) Option`: Sets embedded file system assets for Core. -- `WithServiceLock() Option`: Locks the service graph after initialization. -- `App() *application.App`: Returns the global Wails application instance. -- `ServiceFor[T any](c *Core, name string) T`: Retrieves a registered service by name and asserts its type. - -### Methods on `*Core` -- `(c *Core) ServiceStartup(context.Context, application.ServiceOptions) error`: Handles service startup logic. -- `(c *Core) ACTION(msg Message) error`: Dispatches an action message to registered handlers. -- `(c *Core) RegisterAction(handler func(*Core, Message) error)`: Registers an action handler. -- `(c *Core) RegisterActions(handlers ...func(*Core, Message) error)`: Registers multiple action handlers. -- `(c *Core) RegisterService(name string, api any) error`: Registers a service with a given name. -- `(c *Core) Service(name string) any`: Retrieves a registered service by name. -- `(c *Core) Config() Config`: Returns the registered Config service. -- `(c *Core) Core() *Core`: Returns the Core instance itself. diff --git a/docs/core/io.md b/docs/core/io.md deleted file mode 100644 index c65aa7a..0000000 --- a/docs/core/io.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Core.IO ---- - -# Core.IO - -Short: Local/remote filesystem helpers. - -## Overview -Abstracts filesystems (local, SFTP, WebDAV) behind a unified API for reading/writing and listing. - -## Setup -```go -import ( - "github.com/Snider/Core" - "github.com/Snider/Core/io" - "github.com/Snider/Core/io/sftp" - "github.com/Snider/Core/io/webdav" -) - -// Example of creating a local medium (pre-initialized) -localMedium := io.Local - -// Example of creating an SFTP medium -sftpConfig := sftp.ConnectionConfig{ - // ... configure SFTP connection -} -sftpMedium, err := io.NewSFTPMedium(sftpConfig) -if err != nil { - // handle error -} - -// Example of creating a WebDAV medium -webdavConfig := webdav.ConnectionConfig{ - // ... configure WebDAV connection -} -webdavMedium, err := io.NewWebDAVMedium(webdavConfig) -if err != nil { - // handle error -} - -// You can then pass these mediums to services that require an io.Medium -// For example, if a service's New function accepts an io.Medium: -// myService := myservice.New(localMedium) - -// If a service registers with core.WithService and needs an io.Medium, -// it would typically receive it during its ServiceStartup or via its New constructor. - -// The core.Core itself does not directly register io.Medium implementations -// as services in the same way as other modules, but rather consumes them. -app := core.New( - // ... other services - core.WithServiceLock(), -) -``` - -## Use -- Access the local filesystem: `io.Local` -- Create SFTP/WebDAV mediums: `io.NewSFTPMedium(...)`, `io.NewWebDAVMedium(...)` -- Read/write files using a `Medium`: `medium.Read(path)`, `medium.Write(path, data)` -- List directories (if supported by `Medium` implementation): `medium.List(path)` (Note: `List` is not currently in the `Medium` interface, but `FileGet`, `FileSet`, `EnsureDir`, `IsFile` are) -- Copy files between mediums: `io.Copy(sourceMedium, sourcePath, destMedium, destPath)` - -## API - -### Functions -- `NewSFTPMedium(cfg sftp.ConnectionConfig) (Medium, error)` -- `NewWebDAVMedium(cfg webdav.ConnectionConfig) (Medium, error)` -- `Read(m Medium, path string) (string, error)` -- `Write(m Medium, path, content string) error` -- `EnsureDir(m Medium, path string) error` -- `IsFile(m Medium, path string) bool` -- `Copy(sourceMedium Medium, sourcePath string, destMedium Medium, destPath string) error` - -### Variables -- `var Local Medium` - -### Interfaces -- `Medium` interface: - - `Read(path string) (string, error)` - - `Write(path, content string) error` - - `EnsureDir(path string) error` - - `IsFile(path string) bool` - - `FileGet(path string) (string, error)` - - `FileSet(path, content string) error` - -## Notes -- See package `pkg/io/sftp` and `pkg/io/webdav` for specific medium configurations. diff --git a/docs/core/workspace.md b/docs/core/workspace.md deleted file mode 100644 index 37cbe3a..0000000 --- a/docs/core/workspace.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Core.Workspace ---- - -# Core.Workspace - -Short: Manages user workspaces. - -## Overview -Provides functionality for creating, switching, and managing isolated user workspaces, including file storage and cryptographic operations within those workspaces. - -## Setup -```go -import ( - "github.com/Snider/Core" - "github.com/Snider/Core/workspace" - "github.com/Snider/Core/io" -) - -workspaceService, err := workspace.New() -if err != nil { - // handle error -} -app := core.New( - core.WithService(workspaceService), - core.WithServiceLock(), -) - -// Example of dynamic dependency injection (used with core.WithService) -// If using dynamic injection, the io.Medium dependency would be resolved -// during ServiceStartup, typically by another service providing it. -// app := core.New( -// core.WithService(workspace.Register), -// core.WithServiceLock(), -// ) -``` - -## Use -- Create a new workspace: `ws.CreateWorkspace("my-project", "my-password")` -- Switch to an existing workspace: `ws.SwitchWorkspace("my-project-id")` -- Get a file from the active workspace: `ws.WorkspaceFileGet("config.json")` -- Set a file in the active workspace: `ws.WorkspaceFileSet("data.txt", "some content")` - -## API -- `New(medium io.Medium) (*Service, error)` -- `Register(c *core.Core) (any, error)` -- `(s *Service) HandleIPCEvents(c *core.Core, msg core.Message) error` -- `(s *Service) ServiceStartup(context.Context, application.ServiceOptions) error` -- `(s *Service) CreateWorkspace(identifier, password string) (string, error)` -- `(s *Service) SwitchWorkspace(name string) error` -- `(s *Service) WorkspaceFileGet(filename string) (string, error)` -- `(s *Service) WorkspaceFileSet(filename, content string) (string, error)` - -## Notes -- Workspaces are obfuscated and secured with OpenPGP. -- Integrates with `Core.Config` for workspace directory management. diff --git a/docs/index.md b/docs/index.md index 2a8f81d..02dfb7a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,79 +1,52 @@ ---- -title: Core.Help ---- +# Core Library Overview -# Overview +Core is an opinionated framework for building robust, production-grade Go desktop applications using the [Wails](https://wails.io/) framework. It provides a modular, service-based architecture that simplifies development and ensures maintainability. -Core is an opinionated framework for building Go desktop apps with Wails, providing a small set of focused modules you can mix into your app. It ships with sensible defaults and a demo app that doubles as in‑app help. +## Key Features -- Site: [https://dappco.re](https://dappco.re) -- Help: [https://core.help](https://core.help) -- Repo: [github.com:Snider/Core](https://github.com/Snider/Core) +- **Modular Architecture**: Core is divided into a set of independent services, each responsible for a specific domain (e.g., `config`, `crypt`, `display`). +- **Unified Runtime**: A central `Runtime` object initializes and manages the lifecycle of all services, providing a simple and consistent entry point for your application. +- **Dependency Injection**: Services are designed to be testable and decoupled, with dependencies injected at runtime. +- **Standardized Error Handling**: A custom error package (`pkg/e`) provides a consistent way to wrap and handle errors throughout the application. +- **Automated Documentation**: This documentation site is automatically generated from the Go source code, ensuring it stays in sync with the public API. -## Modules +## Getting Started -- Core — framework bootstrap and service container -- Core.Config — app and UI state persistence -- Core.Crypt — keys, encrypt/decrypt, sign/verify -- Core.Display — windows, tray, window state -- Core.Docs — in‑app help and deep‑links -- Core.IO — local/remote filesystem helpers -- Core.Workspace — projects and paths +To start using the Core library, initialize the runtime in your `main.go` file: -## Quick start ```go package main import ( + "embed" + "log" + + "github.com/Snider/Core/pkg/runtime" "github.com/wailsapp/wails/v3/pkg/application" - core "github.com/Snider/Core" ) +//go:embed all:public +var assets embed.FS + func main() { - app := core.New( - core.WithServiceLock(), - ) - wailsApp := application.NewWithOptions(&application.Options{ - Bind: []interface{}{app}, + app := application.New(application.Options{ + Assets: application.AssetOptions{ + Handler: application.AssetFileServerFS(assets), + }, }) - wailsApp.Run() + + rt, err := runtime.New(app) + if err != nil { + log.Fatal(err) + } + + app.Services.Add(application.NewService(rt)) + + err = app.Run() + if err != nil { + log.Fatal(err) + } } ``` -## Services -```go -package demo - -import ( - core "github.com/Snider/Core" -) - -// Register your service -func Register(c *core.Core) error { - return c.RegisterService("demo", &Demo{core: c}) -} -``` - -## Display example -```go -package display - -import ( - "context" - "github.com/wailsapp/wails/v3/pkg/application" -) - -// Open a window on startup -func (d *API) ServiceStartup(ctx context.Context, _ application.ServiceOptions) error { - d.OpenWindow( - OptName("main"), - OptHeight(900), - OptWidth(1280), - OptURL("/"), - OptTitle("Core"), - ) - return nil -} -``` - -See the left nav for detailed pages on each module. +For more detailed information on each service, see the **Services** section in the navigation. diff --git a/docs/services/config.md b/docs/services/config.md new file mode 100644 index 0000000..37ef944 --- /dev/null +++ b/docs/services/config.md @@ -0,0 +1,604 @@ +--- +title: internal +--- +# Service: `internal` + + + + +## Constants + +```goappName +``` + + +```goconfigFileName +``` + + + + +## Types + +### `type Options` +```go +type Options 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: nil + 5 . . Closing: - + 6 . } + 7 . Incomplete: false + 8 } + +``` +Options holds configuration for the config service. + + + + + +### `type Service` +```go +type Service 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 11) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: nil + 8 . . . . Type: *ast.StarExpr { + 9 . . . . . Star: - + 10 . . . . . X: *ast.IndexExpr { + 11 . . . . . . X: *ast.SelectorExpr { + 12 . . . . . . . X: *ast.Ident { + 13 . . . . . . . . NamePos: - + 14 . . . . . . . . Name: "core" + 15 . . . . . . . . Obj: nil + 16 . . . . . . . } + 17 . . . . . . . Sel: *ast.Ident { + 18 . . . . . . . . NamePos: - + 19 . . . . . . . . Name: "Runtime" + 20 . . . . . . . . Obj: nil + 21 . . . . . . . } + 22 . . . . . . } + 23 . . . . . . Lbrack: - + 24 . . . . . . Index: *ast.Ident { + 25 . . . . . . . NamePos: - + 26 . . . . . . . Name: "Options" + 27 . . . . . . . Obj: *ast.Object { + 28 . . . . . . . . Kind: type + 29 . . . . . . . . Name: "Options" + 30 . . . . . . . . Decl: *ast.TypeSpec { + 31 . . . . . . . . . Doc: nil + 32 . . . . . . . . . Name: *ast.Ident { + 33 . . . . . . . . . . NamePos: - + 34 . . . . . . . . . . Name: "Options" + 35 . . . . . . . . . . Obj: *(obj @ 27) + 36 . . . . . . . . . } + 37 . . . . . . . . . TypeParams: nil + 38 . . . . . . . . . Assign: - + 39 . . . . . . . . . Type: *ast.StructType { + 40 . . . . . . . . . . Struct: - + 41 . . . . . . . . . . Fields: *ast.FieldList { + 42 . . . . . . . . . . . Opening: - + 43 . . . . . . . . . . . List: nil + 44 . . . . . . . . . . . Closing: - + 45 . . . . . . . . . . } + 46 . . . . . . . . . . Incomplete: false + 47 . . . . . . . . . } + 48 . . . . . . . . . Comment: nil + 49 . . . . . . . . } + 50 . . . . . . . . Data: nil + 51 . . . . . . . . Type: nil + 52 . . . . . . . } + 53 . . . . . . } + 54 . . . . . . Rbrack: - + 55 . . . . . } + 56 . . . . } + 57 . . . . Tag: *ast.BasicLit { + 58 . . . . . ValuePos: - + 59 . . . . . Kind: STRING + 60 . . . . . Value: "`json:\"-\"`" + 61 . . . . } + 62 . . . . Comment: nil + 63 . . . } + 64 . . . 1: *ast.Field { + 65 . . . . Doc: *ast.CommentGroup { + 66 . . . . . List: []*ast.Comment (len = 1) { + 67 . . . . . . 0: *ast.Comment { + 68 . . . . . . . Slash: - + 69 . . . . . . . Text: "// Persistent fields, saved to config.json." + 70 . . . . . . } + 71 . . . . . } + 72 . . . . } + 73 . . . . Names: []*ast.Ident (len = 1) { + 74 . . . . . 0: *ast.Ident { + 75 . . . . . . NamePos: - + 76 . . . . . . Name: "ConfigPath" + 77 . . . . . . Obj: *ast.Object { + 78 . . . . . . . Kind: var + 79 . . . . . . . Name: "ConfigPath" + 80 . . . . . . . Decl: *(obj @ 64) + 81 . . . . . . . Data: nil + 82 . . . . . . . Type: nil + 83 . . . . . . } + 84 . . . . . } + 85 . . . . } + 86 . . . . Type: *ast.Ident { + 87 . . . . . NamePos: - + 88 . . . . . Name: "string" + 89 . . . . . Obj: nil + 90 . . . . } + 91 . . . . Tag: *ast.BasicLit { + 92 . . . . . ValuePos: - + 93 . . . . . Kind: STRING + 94 . . . . . Value: "`json:\"configPath,omitempty\"`" + 95 . . . . } + 96 . . . . Comment: nil + 97 . . . } + 98 . . . 2: *ast.Field { + 99 . . . . Doc: nil + 100 . . . . Names: []*ast.Ident (len = 1) { + 101 . . . . . 0: *ast.Ident { + 102 . . . . . . NamePos: - + 103 . . . . . . Name: "UserHomeDir" + 104 . . . . . . Obj: *ast.Object { + 105 . . . . . . . Kind: var + 106 . . . . . . . Name: "UserHomeDir" + 107 . . . . . . . Decl: *(obj @ 98) + 108 . . . . . . . Data: nil + 109 . . . . . . . Type: nil + 110 . . . . . . } + 111 . . . . . } + 112 . . . . } + 113 . . . . Type: *ast.Ident { + 114 . . . . . NamePos: - + 115 . . . . . Name: "string" + 116 . . . . . Obj: nil + 117 . . . . } + 118 . . . . Tag: *ast.BasicLit { + 119 . . . . . ValuePos: - + 120 . . . . . Kind: STRING + 121 . . . . . Value: "`json:\"userHomeDir,omitempty\"`" + 122 . . . . } + 123 . . . . Comment: nil + 124 . . . } + 125 . . . 3: *ast.Field { + 126 . . . . Doc: nil + 127 . . . . Names: []*ast.Ident (len = 1) { + 128 . . . . . 0: *ast.Ident { + 129 . . . . . . NamePos: - + 130 . . . . . . Name: "RootDir" + 131 . . . . . . Obj: *ast.Object { + 132 . . . . . . . Kind: var + 133 . . . . . . . Name: "RootDir" + 134 . . . . . . . Decl: *(obj @ 125) + 135 . . . . . . . Data: nil + 136 . . . . . . . Type: nil + 137 . . . . . . } + 138 . . . . . } + 139 . . . . } + 140 . . . . Type: *ast.Ident { + 141 . . . . . NamePos: - + 142 . . . . . Name: "string" + 143 . . . . . Obj: nil + 144 . . . . } + 145 . . . . Tag: *ast.BasicLit { + 146 . . . . . ValuePos: - + 147 . . . . . Kind: STRING + 148 . . . . . Value: "`json:\"rootDir,omitempty\"`" + 149 . . . . } + 150 . . . . Comment: nil + 151 . . . } + 152 . . . 4: *ast.Field { + 153 . . . . Doc: nil + 154 . . . . Names: []*ast.Ident (len = 1) { + 155 . . . . . 0: *ast.Ident { + 156 . . . . . . NamePos: - + 157 . . . . . . Name: "CacheDir" + 158 . . . . . . Obj: *ast.Object { + 159 . . . . . . . Kind: var + 160 . . . . . . . Name: "CacheDir" + 161 . . . . . . . Decl: *(obj @ 152) + 162 . . . . . . . Data: nil + 163 . . . . . . . Type: nil + 164 . . . . . . } + 165 . . . . . } + 166 . . . . } + 167 . . . . Type: *ast.Ident { + 168 . . . . . NamePos: - + 169 . . . . . Name: "string" + 170 . . . . . Obj: nil + 171 . . . . } + 172 . . . . Tag: *ast.BasicLit { + 173 . . . . . ValuePos: - + 174 . . . . . Kind: STRING + 175 . . . . . Value: "`json:\"cacheDir,omitempty\"`" + 176 . . . . } + 177 . . . . Comment: nil + 178 . . . } + 179 . . . 5: *ast.Field { + 180 . . . . Doc: nil + 181 . . . . Names: []*ast.Ident (len = 1) { + 182 . . . . . 0: *ast.Ident { + 183 . . . . . . NamePos: - + 184 . . . . . . Name: "ConfigDir" + 185 . . . . . . Obj: *ast.Object { + 186 . . . . . . . Kind: var + 187 . . . . . . . Name: "ConfigDir" + 188 . . . . . . . Decl: *(obj @ 179) + 189 . . . . . . . Data: nil + 190 . . . . . . . Type: nil + 191 . . . . . . } + 192 . . . . . } + 193 . . . . } + 194 . . . . Type: *ast.Ident { + 195 . . . . . NamePos: - + 196 . . . . . Name: "string" + 197 . . . . . Obj: nil + 198 . . . . } + 199 . . . . Tag: *ast.BasicLit { + 200 . . . . . ValuePos: - + 201 . . . . . Kind: STRING + 202 . . . . . Value: "`json:\"configDir,omitempty\"`" + 203 . . . . } + 204 . . . . Comment: nil + 205 . . . } + 206 . . . 6: *ast.Field { + 207 . . . . Doc: nil + 208 . . . . Names: []*ast.Ident (len = 1) { + 209 . . . . . 0: *ast.Ident { + 210 . . . . . . NamePos: - + 211 . . . . . . Name: "DataDir" + 212 . . . . . . Obj: *ast.Object { + 213 . . . . . . . Kind: var + 214 . . . . . . . Name: "DataDir" + 215 . . . . . . . Decl: *(obj @ 206) + 216 . . . . . . . Data: nil + 217 . . . . . . . Type: nil + 218 . . . . . . } + 219 . . . . . } + 220 . . . . } + 221 . . . . Type: *ast.Ident { + 222 . . . . . NamePos: - + 223 . . . . . Name: "string" + 224 . . . . . Obj: nil + 225 . . . . } + 226 . . . . Tag: *ast.BasicLit { + 227 . . . . . ValuePos: - + 228 . . . . . Kind: STRING + 229 . . . . . Value: "`json:\"dataDir,omitempty\"`" + 230 . . . . } + 231 . . . . Comment: nil + 232 . . . } + 233 . . . 7: *ast.Field { + 234 . . . . Doc: nil + 235 . . . . Names: []*ast.Ident (len = 1) { + 236 . . . . . 0: *ast.Ident { + 237 . . . . . . NamePos: - + 238 . . . . . . Name: "WorkspaceDir" + 239 . . . . . . Obj: *ast.Object { + 240 . . . . . . . Kind: var + 241 . . . . . . . Name: "WorkspaceDir" + 242 . . . . . . . Decl: *(obj @ 233) + 243 . . . . . . . Data: nil + 244 . . . . . . . Type: nil + 245 . . . . . . } + 246 . . . . . } + 247 . . . . } + 248 . . . . Type: *ast.Ident { + 249 . . . . . NamePos: - + 250 . . . . . Name: "string" + 251 . . . . . Obj: nil + 252 . . . . } + 253 . . . . Tag: *ast.BasicLit { + 254 . . . . . ValuePos: - + 255 . . . . . Kind: STRING + 256 . . . . . Value: "`json:\"workspaceDir,omitempty\"`" + 257 . . . . } + 258 . . . . Comment: nil + 259 . . . } + 260 . . . 8: *ast.Field { + 261 . . . . Doc: nil + 262 . . . . Names: []*ast.Ident (len = 1) { + 263 . . . . . 0: *ast.Ident { + 264 . . . . . . NamePos: - + 265 . . . . . . Name: "DefaultRoute" + 266 . . . . . . Obj: *ast.Object { + 267 . . . . . . . Kind: var + 268 . . . . . . . Name: "DefaultRoute" + 269 . . . . . . . Decl: *(obj @ 260) + 270 . . . . . . . Data: nil + 271 . . . . . . . Type: nil + 272 . . . . . . } + 273 . . . . . } + 274 . . . . } + 275 . . . . Type: *ast.Ident { + 276 . . . . . NamePos: - + 277 . . . . . Name: "string" + 278 . . . . . Obj: nil + 279 . . . . } + 280 . . . . Tag: *ast.BasicLit { + 281 . . . . . ValuePos: - + 282 . . . . . Kind: STRING + 283 . . . . . Value: "`json:\"default_route\"`" + 284 . . . . } + 285 . . . . Comment: nil + 286 . . . } + 287 . . . 9: *ast.Field { + 288 . . . . Doc: nil + 289 . . . . Names: []*ast.Ident (len = 1) { + 290 . . . . . 0: *ast.Ident { + 291 . . . . . . NamePos: - + 292 . . . . . . Name: "Features" + 293 . . . . . . Obj: *ast.Object { + 294 . . . . . . . Kind: var + 295 . . . . . . . Name: "Features" + 296 . . . . . . . Decl: *(obj @ 287) + 297 . . . . . . . Data: nil + 298 . . . . . . . Type: nil + 299 . . . . . . } + 300 . . . . . } + 301 . . . . } + 302 . . . . Type: *ast.ArrayType { + 303 . . . . . Lbrack: - + 304 . . . . . Len: nil + 305 . . . . . Elt: *ast.Ident { + 306 . . . . . . NamePos: - + 307 . . . . . . Name: "string" + 308 . . . . . . Obj: nil + 309 . . . . . } + 310 . . . . } + 311 . . . . Tag: *ast.BasicLit { + 312 . . . . . ValuePos: - + 313 . . . . . Kind: STRING + 314 . . . . . Value: "`json:\"features\"`" + 315 . . . . } + 316 . . . . Comment: nil + 317 . . . } + 318 . . . 10: *ast.Field { + 319 . . . . Doc: nil + 320 . . . . Names: []*ast.Ident (len = 1) { + 321 . . . . . 0: *ast.Ident { + 322 . . . . . . NamePos: - + 323 . . . . . . Name: "Language" + 324 . . . . . . Obj: *ast.Object { + 325 . . . . . . . Kind: var + 326 . . . . . . . Name: "Language" + 327 . . . . . . . Decl: *(obj @ 318) + 328 . . . . . . . Data: nil + 329 . . . . . . . Type: nil + 330 . . . . . . } + 331 . . . . . } + 332 . . . . } + 333 . . . . Type: *ast.Ident { + 334 . . . . . NamePos: - + 335 . . . . . Name: "string" + 336 . . . . . Obj: nil + 337 . . . . } + 338 . . . . Tag: *ast.BasicLit { + 339 . . . . . ValuePos: - + 340 . . . . . Kind: STRING + 341 . . . . . Value: "`json:\"language\"`" + 342 . . . . } + 343 . . . . Comment: nil + 344 . . . } + 345 . . } + 346 . . Closing: - + 347 . } + 348 . Incomplete: false + 349 } + +``` +Service provides access to the application's configuration. +It handles loading, saving, and providing access to configuration values. + + + +#### Methods + +- `Get(key 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, out 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "any" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: Get retrieves a configuration value by its key. + +- `IsFeatureEnabled(feature 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "bool" + 3 . Obj: nil + 4 } +`: IsFeatureEnabled checks if a specific feature is enabled in the config. + +- `Save() 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: Save writes the current configuration to config.json. + +- `Set(key 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, v 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "any" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: Set updates a configuration value and saves the config. + + + + + +## Functions + +- `Register(c 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "core" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "Core" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "any" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: Register is the constructor for dynamic dependency injection (used with core.WithService). It creates a Service instance and initializes its core.Runtime field. + +- `TestConfigService(t 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "testing" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "T" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +) `: + +- `TestIsFeatureEnabled(t 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "testing" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "T" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +) `: + +- `TestSet_Bad(t 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "testing" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "T" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +) `: + +- `TestSet_Good(t 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "testing" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "T" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +) `: + +- `TestSet_Ugly(t 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "testing" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "T" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +) `: + +- `setupTestEnv(t 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "testing" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "T" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, 0 *ast.FuncType { + 1 . Func: - + 2 . TypeParams: nil + 3 . Params: *ast.FieldList { + 4 . . Opening: - + 5 . . List: nil + 6 . . Closing: - + 7 . } + 8 . Results: nil + 9 } +`: setupTestEnv creates a temporary home directory for testing and ensures a clean environment. diff --git a/docs/services/core.md b/docs/services/core.md new file mode 100644 index 0000000..8e66b9d --- /dev/null +++ b/docs/services/core.md @@ -0,0 +1,3272 @@ +--- +title: core +--- +# Service: `core` + + + + + + +## Types + +### `type ActionDisplayOpenWindow` +```go +type ActionDisplayOpenWindow 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 2) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: []*ast.Ident (len = 1) { + 8 . . . . . 0: *ast.Ident { + 9 . . . . . . NamePos: - + 10 . . . . . . Name: "Name" + 11 . . . . . . Obj: *ast.Object { + 12 . . . . . . . Kind: var + 13 . . . . . . . Name: "Name" + 14 . . . . . . . Decl: *(obj @ 5) + 15 . . . . . . . Data: nil + 16 . . . . . . . Type: nil + 17 . . . . . . } + 18 . . . . . } + 19 . . . . } + 20 . . . . Type: *ast.Ident { + 21 . . . . . NamePos: - + 22 . . . . . Name: "string" + 23 . . . . . Obj: nil + 24 . . . . } + 25 . . . . Tag: nil + 26 . . . . Comment: nil + 27 . . . } + 28 . . . 1: *ast.Field { + 29 . . . . Doc: nil + 30 . . . . Names: []*ast.Ident (len = 1) { + 31 . . . . . 0: *ast.Ident { + 32 . . . . . . NamePos: - + 33 . . . . . . Name: "Options" + 34 . . . . . . Obj: *ast.Object { + 35 . . . . . . . Kind: var + 36 . . . . . . . Name: "Options" + 37 . . . . . . . Decl: *(obj @ 28) + 38 . . . . . . . Data: nil + 39 . . . . . . . Type: nil + 40 . . . . . . } + 41 . . . . . } + 42 . . . . } + 43 . . . . Type: *ast.SelectorExpr { + 44 . . . . . X: *ast.Ident { + 45 . . . . . . NamePos: - + 46 . . . . . . Name: "application" + 47 . . . . . . Obj: nil + 48 . . . . . } + 49 . . . . . Sel: *ast.Ident { + 50 . . . . . . NamePos: - + 51 . . . . . . Name: "WebviewWindowOptions" + 52 . . . . . . Obj: nil + 53 . . . . . } + 54 . . . . } + 55 . . . . Tag: nil + 56 . . . . Comment: nil + 57 . . . } + 58 . . } + 59 . . Closing: - + 60 . } + 61 . Incomplete: false + 62 } + +``` +ActionDisplayOpenWindow is a structured message for requesting a new window. + + + + + +### `type ActionServiceShutdown` +```go +type ActionServiceShutdown 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: nil + 5 . . Closing: - + 6 . } + 7 . Incomplete: false + 8 } + +``` + + + + + +### `type ActionServiceStartup` +```go +type ActionServiceStartup 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: nil + 5 . . Closing: - + 6 . } + 7 . Incomplete: false + 8 } + +``` + + + + + +### `type Config` +```go +type Config 0 *ast.InterfaceType { + 1 . Interface: - + 2 . Methods: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 2) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: []*ast.Ident (len = 1) { + 8 . . . . . 0: *ast.Ident { + 9 . . . . . . NamePos: - + 10 . . . . . . Name: "Get" + 11 . . . . . . Obj: *ast.Object { + 12 . . . . . . . Kind: func + 13 . . . . . . . Name: "Get" + 14 . . . . . . . Decl: *(obj @ 5) + 15 . . . . . . . Data: nil + 16 . . . . . . . Type: nil + 17 . . . . . . } + 18 . . . . . } + 19 . . . . } + 20 . . . . Type: *ast.FuncType { + 21 . . . . . Func: - + 22 . . . . . TypeParams: nil + 23 . . . . . Params: *ast.FieldList { + 24 . . . . . . Opening: - + 25 . . . . . . List: []*ast.Field (len = 2) { + 26 . . . . . . . 0: *ast.Field { + 27 . . . . . . . . Doc: nil + 28 . . . . . . . . Names: []*ast.Ident (len = 1) { + 29 . . . . . . . . . 0: *ast.Ident { + 30 . . . . . . . . . . NamePos: - + 31 . . . . . . . . . . Name: "key" + 32 . . . . . . . . . . Obj: *ast.Object { + 33 . . . . . . . . . . . Kind: var + 34 . . . . . . . . . . . Name: "key" + 35 . . . . . . . . . . . Decl: *(obj @ 26) + 36 . . . . . . . . . . . Data: nil + 37 . . . . . . . . . . . Type: nil + 38 . . . . . . . . . . } + 39 . . . . . . . . . } + 40 . . . . . . . . } + 41 . . . . . . . . Type: *ast.Ident { + 42 . . . . . . . . . NamePos: - + 43 . . . . . . . . . Name: "string" + 44 . . . . . . . . . Obj: nil + 45 . . . . . . . . } + 46 . . . . . . . . Tag: nil + 47 . . . . . . . . Comment: nil + 48 . . . . . . . } + 49 . . . . . . . 1: *ast.Field { + 50 . . . . . . . . Doc: nil + 51 . . . . . . . . Names: []*ast.Ident (len = 1) { + 52 . . . . . . . . . 0: *ast.Ident { + 53 . . . . . . . . . . NamePos: - + 54 . . . . . . . . . . Name: "out" + 55 . . . . . . . . . . Obj: *ast.Object { + 56 . . . . . . . . . . . Kind: var + 57 . . . . . . . . . . . Name: "out" + 58 . . . . . . . . . . . Decl: *(obj @ 49) + 59 . . . . . . . . . . . Data: nil + 60 . . . . . . . . . . . Type: nil + 61 . . . . . . . . . . } + 62 . . . . . . . . . } + 63 . . . . . . . . } + 64 . . . . . . . . Type: *ast.Ident { + 65 . . . . . . . . . NamePos: - + 66 . . . . . . . . . Name: "any" + 67 . . . . . . . . . Obj: nil + 68 . . . . . . . . } + 69 . . . . . . . . Tag: nil + 70 . . . . . . . . Comment: nil + 71 . . . . . . . } + 72 . . . . . . } + 73 . . . . . . Closing: - + 74 . . . . . } + 75 . . . . . Results: *ast.FieldList { + 76 . . . . . . Opening: - + 77 . . . . . . List: []*ast.Field (len = 1) { + 78 . . . . . . . 0: *ast.Field { + 79 . . . . . . . . Doc: nil + 80 . . . . . . . . Names: nil + 81 . . . . . . . . Type: *ast.Ident { + 82 . . . . . . . . . NamePos: - + 83 . . . . . . . . . Name: "error" + 84 . . . . . . . . . Obj: nil + 85 . . . . . . . . } + 86 . . . . . . . . Tag: nil + 87 . . . . . . . . Comment: nil + 88 . . . . . . . } + 89 . . . . . . } + 90 . . . . . . Closing: - + 91 . . . . . } + 92 . . . . } + 93 . . . . Tag: nil + 94 . . . . Comment: nil + 95 . . . } + 96 . . . 1: *ast.Field { + 97 . . . . Doc: nil + 98 . . . . Names: []*ast.Ident (len = 1) { + 99 . . . . . 0: *ast.Ident { + 100 . . . . . . NamePos: - + 101 . . . . . . Name: "Set" + 102 . . . . . . Obj: *ast.Object { + 103 . . . . . . . Kind: func + 104 . . . . . . . Name: "Set" + 105 . . . . . . . Decl: *(obj @ 96) + 106 . . . . . . . Data: nil + 107 . . . . . . . Type: nil + 108 . . . . . . } + 109 . . . . . } + 110 . . . . } + 111 . . . . Type: *ast.FuncType { + 112 . . . . . Func: - + 113 . . . . . TypeParams: nil + 114 . . . . . Params: *ast.FieldList { + 115 . . . . . . Opening: - + 116 . . . . . . List: []*ast.Field (len = 2) { + 117 . . . . . . . 0: *ast.Field { + 118 . . . . . . . . Doc: nil + 119 . . . . . . . . Names: []*ast.Ident (len = 1) { + 120 . . . . . . . . . 0: *ast.Ident { + 121 . . . . . . . . . . NamePos: - + 122 . . . . . . . . . . Name: "key" + 123 . . . . . . . . . . Obj: *ast.Object { + 124 . . . . . . . . . . . Kind: var + 125 . . . . . . . . . . . Name: "key" + 126 . . . . . . . . . . . Decl: *(obj @ 117) + 127 . . . . . . . . . . . Data: nil + 128 . . . . . . . . . . . Type: nil + 129 . . . . . . . . . . } + 130 . . . . . . . . . } + 131 . . . . . . . . } + 132 . . . . . . . . Type: *ast.Ident { + 133 . . . . . . . . . NamePos: - + 134 . . . . . . . . . Name: "string" + 135 . . . . . . . . . Obj: nil + 136 . . . . . . . . } + 137 . . . . . . . . Tag: nil + 138 . . . . . . . . Comment: nil + 139 . . . . . . . } + 140 . . . . . . . 1: *ast.Field { + 141 . . . . . . . . Doc: nil + 142 . . . . . . . . Names: []*ast.Ident (len = 1) { + 143 . . . . . . . . . 0: *ast.Ident { + 144 . . . . . . . . . . NamePos: - + 145 . . . . . . . . . . Name: "v" + 146 . . . . . . . . . . Obj: *ast.Object { + 147 . . . . . . . . . . . Kind: var + 148 . . . . . . . . . . . Name: "v" + 149 . . . . . . . . . . . Decl: *(obj @ 140) + 150 . . . . . . . . . . . Data: nil + 151 . . . . . . . . . . . Type: nil + 152 . . . . . . . . . . } + 153 . . . . . . . . . } + 154 . . . . . . . . } + 155 . . . . . . . . Type: *ast.Ident { + 156 . . . . . . . . . NamePos: - + 157 . . . . . . . . . Name: "any" + 158 . . . . . . . . . Obj: nil + 159 . . . . . . . . } + 160 . . . . . . . . Tag: nil + 161 . . . . . . . . Comment: nil + 162 . . . . . . . } + 163 . . . . . . } + 164 . . . . . . Closing: - + 165 . . . . . } + 166 . . . . . Results: *ast.FieldList { + 167 . . . . . . Opening: - + 168 . . . . . . List: []*ast.Field (len = 1) { + 169 . . . . . . . 0: *ast.Field { + 170 . . . . . . . . Doc: nil + 171 . . . . . . . . Names: nil + 172 . . . . . . . . Type: *ast.Ident { + 173 . . . . . . . . . NamePos: - + 174 . . . . . . . . . Name: "error" + 175 . . . . . . . . . Obj: nil + 176 . . . . . . . . } + 177 . . . . . . . . Tag: nil + 178 . . . . . . . . Comment: nil + 179 . . . . . . . } + 180 . . . . . . } + 181 . . . . . . Closing: - + 182 . . . . . } + 183 . . . . } + 184 . . . . Tag: nil + 185 . . . . Comment: nil + 186 . . . } + 187 . . } + 188 . . Closing: - + 189 . } + 190 . Incomplete: false + 191 } + +``` +Config provides access to application configuration. + + + + + +### `type Contract` +```go +type Contract 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 2) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: []*ast.Ident (len = 1) { + 8 . . . . . 0: *ast.Ident { + 9 . . . . . . NamePos: - + 10 . . . . . . Name: "DontPanic" + 11 . . . . . . Obj: *ast.Object { + 12 . . . . . . . Kind: var + 13 . . . . . . . Name: "DontPanic" + 14 . . . . . . . Decl: *(obj @ 5) + 15 . . . . . . . Data: nil + 16 . . . . . . . Type: nil + 17 . . . . . . } + 18 . . . . . } + 19 . . . . } + 20 . . . . Type: *ast.Ident { + 21 . . . . . NamePos: - + 22 . . . . . Name: "bool" + 23 . . . . . Obj: nil + 24 . . . . } + 25 . . . . Tag: nil + 26 . . . . Comment: nil + 27 . . . } + 28 . . . 1: *ast.Field { + 29 . . . . Doc: nil + 30 . . . . Names: []*ast.Ident (len = 1) { + 31 . . . . . 0: *ast.Ident { + 32 . . . . . . NamePos: - + 33 . . . . . . Name: "DisableLogging" + 34 . . . . . . Obj: *ast.Object { + 35 . . . . . . . Kind: var + 36 . . . . . . . Name: "DisableLogging" + 37 . . . . . . . Decl: *(obj @ 28) + 38 . . . . . . . Data: nil + 39 . . . . . . . Type: nil + 40 . . . . . . } + 41 . . . . . } + 42 . . . . } + 43 . . . . Type: *ast.Ident { + 44 . . . . . NamePos: - + 45 . . . . . Name: "bool" + 46 . . . . . Obj: nil + 47 . . . . } + 48 . . . . Tag: nil + 49 . . . . Comment: nil + 50 . . . } + 51 . . } + 52 . . Closing: - + 53 . } + 54 . Incomplete: false + 55 } + +``` + + + + + +### `type Core` +```go +type Core 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 10) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: []*ast.Ident (len = 1) { + 8 . . . . . 0: *ast.Ident { + 9 . . . . . . NamePos: - + 10 . . . . . . Name: "once" + 11 . . . . . . Obj: *ast.Object { + 12 . . . . . . . Kind: var + 13 . . . . . . . Name: "once" + 14 . . . . . . . Decl: *(obj @ 5) + 15 . . . . . . . Data: nil + 16 . . . . . . . Type: nil + 17 . . . . . . } + 18 . . . . . } + 19 . . . . } + 20 . . . . Type: *ast.SelectorExpr { + 21 . . . . . X: *ast.Ident { + 22 . . . . . . NamePos: - + 23 . . . . . . Name: "sync" + 24 . . . . . . Obj: nil + 25 . . . . . } + 26 . . . . . Sel: *ast.Ident { + 27 . . . . . . NamePos: - + 28 . . . . . . Name: "Once" + 29 . . . . . . Obj: nil + 30 . . . . . } + 31 . . . . } + 32 . . . . Tag: nil + 33 . . . . Comment: nil + 34 . . . } + 35 . . . 1: *ast.Field { + 36 . . . . Doc: nil + 37 . . . . Names: []*ast.Ident (len = 1) { + 38 . . . . . 0: *ast.Ident { + 39 . . . . . . NamePos: - + 40 . . . . . . Name: "initErr" + 41 . . . . . . Obj: *ast.Object { + 42 . . . . . . . Kind: var + 43 . . . . . . . Name: "initErr" + 44 . . . . . . . Decl: *(obj @ 35) + 45 . . . . . . . Data: nil + 46 . . . . . . . Type: nil + 47 . . . . . . } + 48 . . . . . } + 49 . . . . } + 50 . . . . Type: *ast.Ident { + 51 . . . . . NamePos: - + 52 . . . . . Name: "error" + 53 . . . . . Obj: nil + 54 . . . . } + 55 . . . . Tag: nil + 56 . . . . Comment: nil + 57 . . . } + 58 . . . 2: *ast.Field { + 59 . . . . Doc: nil + 60 . . . . Names: []*ast.Ident (len = 1) { + 61 . . . . . 0: *ast.Ident { + 62 . . . . . . NamePos: - + 63 . . . . . . Name: "App" + 64 . . . . . . Obj: *ast.Object { + 65 . . . . . . . Kind: var + 66 . . . . . . . Name: "App" + 67 . . . . . . . Decl: *(obj @ 58) + 68 . . . . . . . Data: nil + 69 . . . . . . . Type: nil + 70 . . . . . . } + 71 . . . . . } + 72 . . . . } + 73 . . . . Type: *ast.StarExpr { + 74 . . . . . Star: - + 75 . . . . . X: *ast.SelectorExpr { + 76 . . . . . . X: *ast.Ident { + 77 . . . . . . . NamePos: - + 78 . . . . . . . Name: "application" + 79 . . . . . . . Obj: nil + 80 . . . . . . } + 81 . . . . . . Sel: *ast.Ident { + 82 . . . . . . . NamePos: - + 83 . . . . . . . Name: "App" + 84 . . . . . . . Obj: nil + 85 . . . . . . } + 86 . . . . . } + 87 . . . . } + 88 . . . . Tag: nil + 89 . . . . Comment: nil + 90 . . . } + 91 . . . 3: *ast.Field { + 92 . . . . Doc: nil + 93 . . . . Names: []*ast.Ident (len = 1) { + 94 . . . . . 0: *ast.Ident { + 95 . . . . . . NamePos: - + 96 . . . . . . Name: "assets" + 97 . . . . . . Obj: *ast.Object { + 98 . . . . . . . Kind: var + 99 . . . . . . . Name: "assets" + 100 . . . . . . . Decl: *(obj @ 91) + 101 . . . . . . . Data: nil + 102 . . . . . . . Type: nil + 103 . . . . . . } + 104 . . . . . } + 105 . . . . } + 106 . . . . Type: *ast.SelectorExpr { + 107 . . . . . X: *ast.Ident { + 108 . . . . . . NamePos: - + 109 . . . . . . Name: "embed" + 110 . . . . . . Obj: nil + 111 . . . . . } + 112 . . . . . Sel: *ast.Ident { + 113 . . . . . . NamePos: - + 114 . . . . . . Name: "FS" + 115 . . . . . . Obj: nil + 116 . . . . . } + 117 . . . . } + 118 . . . . Tag: nil + 119 . . . . Comment: nil + 120 . . . } + 121 . . . 4: *ast.Field { + 122 . . . . Doc: nil + 123 . . . . Names: []*ast.Ident (len = 1) { + 124 . . . . . 0: *ast.Ident { + 125 . . . . . . NamePos: - + 126 . . . . . . Name: "serviceLock" + 127 . . . . . . Obj: *ast.Object { + 128 . . . . . . . Kind: var + 129 . . . . . . . Name: "serviceLock" + 130 . . . . . . . Decl: *(obj @ 121) + 131 . . . . . . . Data: nil + 132 . . . . . . . Type: nil + 133 . . . . . . } + 134 . . . . . } + 135 . . . . } + 136 . . . . Type: *ast.Ident { + 137 . . . . . NamePos: - + 138 . . . . . Name: "bool" + 139 . . . . . Obj: nil + 140 . . . . } + 141 . . . . Tag: nil + 142 . . . . Comment: nil + 143 . . . } + 144 . . . 5: *ast.Field { + 145 . . . . Doc: nil + 146 . . . . Names: []*ast.Ident (len = 1) { + 147 . . . . . 0: *ast.Ident { + 148 . . . . . . NamePos: - + 149 . . . . . . Name: "ipcMu" + 150 . . . . . . Obj: *ast.Object { + 151 . . . . . . . Kind: var + 152 . . . . . . . Name: "ipcMu" + 153 . . . . . . . Decl: *(obj @ 144) + 154 . . . . . . . Data: nil + 155 . . . . . . . Type: nil + 156 . . . . . . } + 157 . . . . . } + 158 . . . . } + 159 . . . . Type: *ast.SelectorExpr { + 160 . . . . . X: *ast.Ident { + 161 . . . . . . NamePos: - + 162 . . . . . . Name: "sync" + 163 . . . . . . Obj: nil + 164 . . . . . } + 165 . . . . . Sel: *ast.Ident { + 166 . . . . . . NamePos: - + 167 . . . . . . Name: "RWMutex" + 168 . . . . . . Obj: nil + 169 . . . . . } + 170 . . . . } + 171 . . . . Tag: nil + 172 . . . . Comment: nil + 173 . . . } + 174 . . . 6: *ast.Field { + 175 . . . . Doc: nil + 176 . . . . Names: []*ast.Ident (len = 1) { + 177 . . . . . 0: *ast.Ident { + 178 . . . . . . NamePos: - + 179 . . . . . . Name: "ipcHandlers" + 180 . . . . . . Obj: *ast.Object { + 181 . . . . . . . Kind: var + 182 . . . . . . . Name: "ipcHandlers" + 183 . . . . . . . Decl: *(obj @ 174) + 184 . . . . . . . Data: nil + 185 . . . . . . . Type: nil + 186 . . . . . . } + 187 . . . . . } + 188 . . . . } + 189 . . . . Type: *ast.ArrayType { + 190 . . . . . Lbrack: - + 191 . . . . . Len: nil + 192 . . . . . Elt: *ast.FuncType { + 193 . . . . . . Func: - + 194 . . . . . . TypeParams: nil + 195 . . . . . . Params: *ast.FieldList { + 196 . . . . . . . Opening: - + 197 . . . . . . . List: []*ast.Field (len = 2) { + 198 . . . . . . . . 0: *ast.Field { + 199 . . . . . . . . . Doc: nil + 200 . . . . . . . . . Names: nil + 201 . . . . . . . . . Type: *ast.StarExpr { + 202 . . . . . . . . . . Star: - + 203 . . . . . . . . . . X: *ast.Ident { + 204 . . . . . . . . . . . NamePos: - + 205 . . . . . . . . . . . Name: "Core" + 206 . . . . . . . . . . . Obj: *ast.Object { + 207 . . . . . . . . . . . . Kind: type + 208 . . . . . . . . . . . . Name: "Core" + 209 . . . . . . . . . . . . Decl: *ast.TypeSpec { + 210 . . . . . . . . . . . . . Doc: nil + 211 . . . . . . . . . . . . . Name: *ast.Ident { + 212 . . . . . . . . . . . . . . NamePos: - + 213 . . . . . . . . . . . . . . Name: "Core" + 214 . . . . . . . . . . . . . . Obj: *(obj @ 206) + 215 . . . . . . . . . . . . . } + 216 . . . . . . . . . . . . . TypeParams: nil + 217 . . . . . . . . . . . . . Assign: - + 218 . . . . . . . . . . . . . Type: *(obj @ 0) + 219 . . . . . . . . . . . . . Comment: nil + 220 . . . . . . . . . . . . } + 221 . . . . . . . . . . . . Data: nil + 222 . . . . . . . . . . . . Type: nil + 223 . . . . . . . . . . . } + 224 . . . . . . . . . . } + 225 . . . . . . . . . } + 226 . . . . . . . . . Tag: nil + 227 . . . . . . . . . Comment: nil + 228 . . . . . . . . } + 229 . . . . . . . . 1: *ast.Field { + 230 . . . . . . . . . Doc: nil + 231 . . . . . . . . . Names: nil + 232 . . . . . . . . . Type: *ast.Ident { + 233 . . . . . . . . . . NamePos: - + 234 . . . . . . . . . . Name: "Message" + 235 . . . . . . . . . . Obj: *ast.Object { + 236 . . . . . . . . . . . Kind: type + 237 . . . . . . . . . . . Name: "Message" + 238 . . . . . . . . . . . Decl: *ast.TypeSpec { + 239 . . . . . . . . . . . . Doc: nil + 240 . . . . . . . . . . . . Name: *ast.Ident { + 241 . . . . . . . . . . . . . NamePos: - + 242 . . . . . . . . . . . . . Name: "Message" + 243 . . . . . . . . . . . . . Obj: *(obj @ 235) + 244 . . . . . . . . . . . . } + 245 . . . . . . . . . . . . TypeParams: nil + 246 . . . . . . . . . . . . Assign: - + 247 . . . . . . . . . . . . Type: *ast.InterfaceType { + 248 . . . . . . . . . . . . . Interface: - + 249 . . . . . . . . . . . . . Methods: *ast.FieldList { + 250 . . . . . . . . . . . . . . Opening: - + 251 . . . . . . . . . . . . . . List: nil + 252 . . . . . . . . . . . . . . Closing: - + 253 . . . . . . . . . . . . . } + 254 . . . . . . . . . . . . . Incomplete: false + 255 . . . . . . . . . . . . } + 256 . . . . . . . . . . . . Comment: nil + 257 . . . . . . . . . . . } + 258 . . . . . . . . . . . Data: nil + 259 . . . . . . . . . . . Type: nil + 260 . . . . . . . . . . } + 261 . . . . . . . . . } + 262 . . . . . . . . . Tag: nil + 263 . . . . . . . . . Comment: nil + 264 . . . . . . . . } + 265 . . . . . . . } + 266 . . . . . . . Closing: - + 267 . . . . . . } + 268 . . . . . . Results: *ast.FieldList { + 269 . . . . . . . Opening: - + 270 . . . . . . . List: []*ast.Field (len = 1) { + 271 . . . . . . . . 0: *ast.Field { + 272 . . . . . . . . . Doc: nil + 273 . . . . . . . . . Names: nil + 274 . . . . . . . . . Type: *ast.Ident { + 275 . . . . . . . . . . NamePos: - + 276 . . . . . . . . . . Name: "error" + 277 . . . . . . . . . . Obj: nil + 278 . . . . . . . . . } + 279 . . . . . . . . . Tag: nil + 280 . . . . . . . . . Comment: nil + 281 . . . . . . . . } + 282 . . . . . . . } + 283 . . . . . . . Closing: - + 284 . . . . . . } + 285 . . . . . } + 286 . . . . } + 287 . . . . Tag: nil + 288 . . . . Comment: nil + 289 . . . } + 290 . . . 7: *ast.Field { + 291 . . . . Doc: nil + 292 . . . . Names: []*ast.Ident (len = 1) { + 293 . . . . . 0: *ast.Ident { + 294 . . . . . . NamePos: - + 295 . . . . . . Name: "serviceMu" + 296 . . . . . . Obj: *ast.Object { + 297 . . . . . . . Kind: var + 298 . . . . . . . Name: "serviceMu" + 299 . . . . . . . Decl: *(obj @ 290) + 300 . . . . . . . Data: nil + 301 . . . . . . . Type: nil + 302 . . . . . . } + 303 . . . . . } + 304 . . . . } + 305 . . . . Type: *ast.SelectorExpr { + 306 . . . . . X: *ast.Ident { + 307 . . . . . . NamePos: - + 308 . . . . . . Name: "sync" + 309 . . . . . . Obj: nil + 310 . . . . . } + 311 . . . . . Sel: *ast.Ident { + 312 . . . . . . NamePos: - + 313 . . . . . . Name: "RWMutex" + 314 . . . . . . Obj: nil + 315 . . . . . } + 316 . . . . } + 317 . . . . Tag: nil + 318 . . . . Comment: nil + 319 . . . } + 320 . . . 8: *ast.Field { + 321 . . . . Doc: nil + 322 . . . . Names: []*ast.Ident (len = 1) { + 323 . . . . . 0: *ast.Ident { + 324 . . . . . . NamePos: - + 325 . . . . . . Name: "services" + 326 . . . . . . Obj: *ast.Object { + 327 . . . . . . . Kind: var + 328 . . . . . . . Name: "services" + 329 . . . . . . . Decl: *(obj @ 320) + 330 . . . . . . . Data: nil + 331 . . . . . . . Type: nil + 332 . . . . . . } + 333 . . . . . } + 334 . . . . } + 335 . . . . Type: *ast.MapType { + 336 . . . . . Map: - + 337 . . . . . Key: *ast.Ident { + 338 . . . . . . NamePos: - + 339 . . . . . . Name: "string" + 340 . . . . . . Obj: nil + 341 . . . . . } + 342 . . . . . Value: *ast.Ident { + 343 . . . . . . NamePos: - + 344 . . . . . . Name: "any" + 345 . . . . . . Obj: nil + 346 . . . . . } + 347 . . . . } + 348 . . . . Tag: nil + 349 . . . . Comment: nil + 350 . . . } + 351 . . . 9: *ast.Field { + 352 . . . . Doc: nil + 353 . . . . Names: []*ast.Ident (len = 1) { + 354 . . . . . 0: *ast.Ident { + 355 . . . . . . NamePos: - + 356 . . . . . . Name: "servicesLocked" + 357 . . . . . . Obj: *ast.Object { + 358 . . . . . . . Kind: var + 359 . . . . . . . Name: "servicesLocked" + 360 . . . . . . . Decl: *(obj @ 351) + 361 . . . . . . . Data: nil + 362 . . . . . . . Type: nil + 363 . . . . . . } + 364 . . . . . } + 365 . . . . } + 366 . . . . Type: *ast.Ident { + 367 . . . . . NamePos: - + 368 . . . . . Name: "bool" + 369 . . . . . Obj: nil + 370 . . . . } + 371 . . . . Tag: nil + 372 . . . . Comment: nil + 373 . . . } + 374 . . } + 375 . . Closing: - + 376 . } + 377 . Incomplete: false + 378 } + +``` + + + +#### Methods + +- `ACTION(msg 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "Message" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: + +- `Config() 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "Config" + 3 . Obj: nil + 4 } +`: Config returns the registered Config service. + +- `Core() 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.Ident { + 3 . . NamePos: - + 4 . . Name: "Core" + 5 . . Obj: nil + 6 . } + 7 } +`: + +- `Display() 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "Display" + 3 . Obj: nil + 4 } +`: Display returns the registered Display service. + +- `RegisterAction(handler 0 *ast.FuncType { + 1 . Func: - + 2 . TypeParams: nil + 3 . Params: *ast.FieldList { + 4 . . Opening: - + 5 . . List: []*ast.Field (len = 2) { + 6 . . . 0: *ast.Field { + 7 . . . . Doc: nil + 8 . . . . Names: nil + 9 . . . . Type: *ast.StarExpr { + 10 . . . . . Star: - + 11 . . . . . X: *ast.Ident { + 12 . . . . . . NamePos: - + 13 . . . . . . Name: "Core" + 14 . . . . . . Obj: nil + 15 . . . . . } + 16 . . . . } + 17 . . . . Tag: nil + 18 . . . . Comment: nil + 19 . . . } + 20 . . . 1: *ast.Field { + 21 . . . . Doc: nil + 22 . . . . Names: nil + 23 . . . . Type: *ast.Ident { + 24 . . . . . NamePos: - + 25 . . . . . Name: "Message" + 26 . . . . . Obj: nil + 27 . . . . } + 28 . . . . Tag: nil + 29 . . . . Comment: nil + 30 . . . } + 31 . . } + 32 . . Closing: - + 33 . } + 34 . Results: *ast.FieldList { + 35 . . Opening: - + 36 . . List: []*ast.Field (len = 1) { + 37 . . . 0: *ast.Field { + 38 . . . . Doc: nil + 39 . . . . Names: nil + 40 . . . . Type: *ast.Ident { + 41 . . . . . NamePos: - + 42 . . . . . Name: "error" + 43 . . . . . Obj: nil + 44 . . . . } + 45 . . . . Tag: nil + 46 . . . . Comment: nil + 47 . . . } + 48 . . } + 49 . . Closing: - + 50 . } + 51 } +) `: + +- `RegisterActions(handlers 0 *ast.Ellipsis { + 1 . Ellipsis: - + 2 . Elt: *ast.FuncType { + 3 . . Func: - + 4 . . TypeParams: nil + 5 . . Params: *ast.FieldList { + 6 . . . Opening: - + 7 . . . List: []*ast.Field (len = 2) { + 8 . . . . 0: *ast.Field { + 9 . . . . . Doc: nil + 10 . . . . . Names: nil + 11 . . . . . Type: *ast.StarExpr { + 12 . . . . . . Star: - + 13 . . . . . . X: *ast.Ident { + 14 . . . . . . . NamePos: - + 15 . . . . . . . Name: "Core" + 16 . . . . . . . Obj: nil + 17 . . . . . . } + 18 . . . . . } + 19 . . . . . Tag: nil + 20 . . . . . Comment: nil + 21 . . . . } + 22 . . . . 1: *ast.Field { + 23 . . . . . Doc: nil + 24 . . . . . Names: nil + 25 . . . . . Type: *ast.Ident { + 26 . . . . . . NamePos: - + 27 . . . . . . Name: "Message" + 28 . . . . . . Obj: nil + 29 . . . . . } + 30 . . . . . Tag: nil + 31 . . . . . Comment: nil + 32 . . . . } + 33 . . . } + 34 . . . Closing: - + 35 . . } + 36 . . Results: *ast.FieldList { + 37 . . . Opening: - + 38 . . . List: []*ast.Field (len = 1) { + 39 . . . . 0: *ast.Field { + 40 . . . . . Doc: nil + 41 . . . . . Names: nil + 42 . . . . . Type: *ast.Ident { + 43 . . . . . . NamePos: - + 44 . . . . . . Name: "error" + 45 . . . . . . Obj: nil + 46 . . . . . } + 47 . . . . . Tag: nil + 48 . . . . . Comment: nil + 49 . . . . } + 50 . . . } + 51 . . . Closing: - + 52 . . } + 53 . } + 54 } +) `: + +- `RegisterService(name 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, api 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "any" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: + +- `Service(name 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "any" + 3 . Obj: nil + 4 } +`: + +- `ServiceShutdown(ctx 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "context" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "Context" + 9 . . Obj: nil + 10 . } + 11 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: + +- `ServiceStartup(ctx 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "context" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "Context" + 9 . . Obj: nil + 10 . } + 11 } +, options 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "application" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "ServiceOptions" + 9 . . Obj: nil + 10 . } + 11 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: + + + +### `type Crypt` +```go +type Crypt 0 *ast.InterfaceType { + 1 . Interface: - + 2 . Methods: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 2) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: []*ast.Ident (len = 1) { + 8 . . . . . 0: *ast.Ident { + 9 . . . . . . NamePos: - + 10 . . . . . . Name: "EncryptPGP" + 11 . . . . . . Obj: *ast.Object { + 12 . . . . . . . Kind: func + 13 . . . . . . . Name: "EncryptPGP" + 14 . . . . . . . Decl: *(obj @ 5) + 15 . . . . . . . Data: nil + 16 . . . . . . . Type: nil + 17 . . . . . . } + 18 . . . . . } + 19 . . . . } + 20 . . . . Type: *ast.FuncType { + 21 . . . . . Func: - + 22 . . . . . TypeParams: nil + 23 . . . . . Params: *ast.FieldList { + 24 . . . . . . Opening: - + 25 . . . . . . List: []*ast.Field (len = 3) { + 26 . . . . . . . 0: *ast.Field { + 27 . . . . . . . . Doc: nil + 28 . . . . . . . . Names: []*ast.Ident (len = 1) { + 29 . . . . . . . . . 0: *ast.Ident { + 30 . . . . . . . . . . NamePos: - + 31 . . . . . . . . . . Name: "writer" + 32 . . . . . . . . . . Obj: *ast.Object { + 33 . . . . . . . . . . . Kind: var + 34 . . . . . . . . . . . Name: "writer" + 35 . . . . . . . . . . . Decl: *(obj @ 26) + 36 . . . . . . . . . . . Data: nil + 37 . . . . . . . . . . . Type: nil + 38 . . . . . . . . . . } + 39 . . . . . . . . . } + 40 . . . . . . . . } + 41 . . . . . . . . Type: *ast.SelectorExpr { + 42 . . . . . . . . . X: *ast.Ident { + 43 . . . . . . . . . . NamePos: - + 44 . . . . . . . . . . Name: "io" + 45 . . . . . . . . . . Obj: nil + 46 . . . . . . . . . } + 47 . . . . . . . . . Sel: *ast.Ident { + 48 . . . . . . . . . . NamePos: - + 49 . . . . . . . . . . Name: "Writer" + 50 . . . . . . . . . . Obj: nil + 51 . . . . . . . . . } + 52 . . . . . . . . } + 53 . . . . . . . . Tag: nil + 54 . . . . . . . . Comment: nil + 55 . . . . . . . } + 56 . . . . . . . 1: *ast.Field { + 57 . . . . . . . . Doc: nil + 58 . . . . . . . . Names: []*ast.Ident (len = 2) { + 59 . . . . . . . . . 0: *ast.Ident { + 60 . . . . . . . . . . NamePos: - + 61 . . . . . . . . . . Name: "recipientPath" + 62 . . . . . . . . . . Obj: *ast.Object { + 63 . . . . . . . . . . . Kind: var + 64 . . . . . . . . . . . Name: "recipientPath" + 65 . . . . . . . . . . . Decl: *(obj @ 56) + 66 . . . . . . . . . . . Data: nil + 67 . . . . . . . . . . . Type: nil + 68 . . . . . . . . . . } + 69 . . . . . . . . . } + 70 . . . . . . . . . 1: *ast.Ident { + 71 . . . . . . . . . . NamePos: - + 72 . . . . . . . . . . Name: "data" + 73 . . . . . . . . . . Obj: *ast.Object { + 74 . . . . . . . . . . . Kind: var + 75 . . . . . . . . . . . Name: "data" + 76 . . . . . . . . . . . Decl: *(obj @ 56) + 77 . . . . . . . . . . . Data: nil + 78 . . . . . . . . . . . Type: nil + 79 . . . . . . . . . . } + 80 . . . . . . . . . } + 81 . . . . . . . . } + 82 . . . . . . . . Type: *ast.Ident { + 83 . . . . . . . . . NamePos: - + 84 . . . . . . . . . Name: "string" + 85 . . . . . . . . . Obj: nil + 86 . . . . . . . . } + 87 . . . . . . . . Tag: nil + 88 . . . . . . . . Comment: nil + 89 . . . . . . . } + 90 . . . . . . . 2: *ast.Field { + 91 . . . . . . . . Doc: nil + 92 . . . . . . . . Names: []*ast.Ident (len = 2) { + 93 . . . . . . . . . 0: *ast.Ident { + 94 . . . . . . . . . . NamePos: - + 95 . . . . . . . . . . Name: "signerPath" + 96 . . . . . . . . . . Obj: *ast.Object { + 97 . . . . . . . . . . . Kind: var + 98 . . . . . . . . . . . Name: "signerPath" + 99 . . . . . . . . . . . Decl: *(obj @ 90) + 100 . . . . . . . . . . . Data: nil + 101 . . . . . . . . . . . Type: nil + 102 . . . . . . . . . . } + 103 . . . . . . . . . } + 104 . . . . . . . . . 1: *ast.Ident { + 105 . . . . . . . . . . NamePos: - + 106 . . . . . . . . . . Name: "signerPassphrase" + 107 . . . . . . . . . . Obj: *ast.Object { + 108 . . . . . . . . . . . Kind: var + 109 . . . . . . . . . . . Name: "signerPassphrase" + 110 . . . . . . . . . . . Decl: *(obj @ 90) + 111 . . . . . . . . . . . Data: nil + 112 . . . . . . . . . . . Type: nil + 113 . . . . . . . . . . } + 114 . . . . . . . . . } + 115 . . . . . . . . } + 116 . . . . . . . . Type: *ast.StarExpr { + 117 . . . . . . . . . Star: - + 118 . . . . . . . . . X: *ast.Ident { + 119 . . . . . . . . . . NamePos: - + 120 . . . . . . . . . . Name: "string" + 121 . . . . . . . . . . Obj: nil + 122 . . . . . . . . . } + 123 . . . . . . . . } + 124 . . . . . . . . Tag: nil + 125 . . . . . . . . Comment: nil + 126 . . . . . . . } + 127 . . . . . . } + 128 . . . . . . Closing: - + 129 . . . . . } + 130 . . . . . Results: *ast.FieldList { + 131 . . . . . . Opening: - + 132 . . . . . . List: []*ast.Field (len = 2) { + 133 . . . . . . . 0: *ast.Field { + 134 . . . . . . . . Doc: nil + 135 . . . . . . . . Names: nil + 136 . . . . . . . . Type: *ast.Ident { + 137 . . . . . . . . . NamePos: - + 138 . . . . . . . . . Name: "string" + 139 . . . . . . . . . Obj: nil + 140 . . . . . . . . } + 141 . . . . . . . . Tag: nil + 142 . . . . . . . . Comment: nil + 143 . . . . . . . } + 144 . . . . . . . 1: *ast.Field { + 145 . . . . . . . . Doc: nil + 146 . . . . . . . . Names: nil + 147 . . . . . . . . Type: *ast.Ident { + 148 . . . . . . . . . NamePos: - + 149 . . . . . . . . . Name: "error" + 150 . . . . . . . . . Obj: nil + 151 . . . . . . . . } + 152 . . . . . . . . Tag: nil + 153 . . . . . . . . Comment: nil + 154 . . . . . . . } + 155 . . . . . . } + 156 . . . . . . Closing: - + 157 . . . . . } + 158 . . . . } + 159 . . . . Tag: nil + 160 . . . . Comment: nil + 161 . . . } + 162 . . . 1: *ast.Field { + 163 . . . . Doc: nil + 164 . . . . Names: []*ast.Ident (len = 1) { + 165 . . . . . 0: *ast.Ident { + 166 . . . . . . NamePos: - + 167 . . . . . . Name: "DecryptPGP" + 168 . . . . . . Obj: *ast.Object { + 169 . . . . . . . Kind: func + 170 . . . . . . . Name: "DecryptPGP" + 171 . . . . . . . Decl: *(obj @ 162) + 172 . . . . . . . Data: nil + 173 . . . . . . . Type: nil + 174 . . . . . . } + 175 . . . . . } + 176 . . . . } + 177 . . . . Type: *ast.FuncType { + 178 . . . . . Func: - + 179 . . . . . TypeParams: nil + 180 . . . . . Params: *ast.FieldList { + 181 . . . . . . Opening: - + 182 . . . . . . List: []*ast.Field (len = 2) { + 183 . . . . . . . 0: *ast.Field { + 184 . . . . . . . . Doc: nil + 185 . . . . . . . . Names: []*ast.Ident (len = 3) { + 186 . . . . . . . . . 0: *ast.Ident { + 187 . . . . . . . . . . NamePos: - + 188 . . . . . . . . . . Name: "recipientPath" + 189 . . . . . . . . . . Obj: *ast.Object { + 190 . . . . . . . . . . . Kind: var + 191 . . . . . . . . . . . Name: "recipientPath" + 192 . . . . . . . . . . . Decl: *(obj @ 183) + 193 . . . . . . . . . . . Data: nil + 194 . . . . . . . . . . . Type: nil + 195 . . . . . . . . . . } + 196 . . . . . . . . . } + 197 . . . . . . . . . 1: *ast.Ident { + 198 . . . . . . . . . . NamePos: - + 199 . . . . . . . . . . Name: "message" + 200 . . . . . . . . . . Obj: *ast.Object { + 201 . . . . . . . . . . . Kind: var + 202 . . . . . . . . . . . Name: "message" + 203 . . . . . . . . . . . Decl: *(obj @ 183) + 204 . . . . . . . . . . . Data: nil + 205 . . . . . . . . . . . Type: nil + 206 . . . . . . . . . . } + 207 . . . . . . . . . } + 208 . . . . . . . . . 2: *ast.Ident { + 209 . . . . . . . . . . NamePos: - + 210 . . . . . . . . . . Name: "passphrase" + 211 . . . . . . . . . . Obj: *ast.Object { + 212 . . . . . . . . . . . Kind: var + 213 . . . . . . . . . . . Name: "passphrase" + 214 . . . . . . . . . . . Decl: *(obj @ 183) + 215 . . . . . . . . . . . Data: nil + 216 . . . . . . . . . . . Type: nil + 217 . . . . . . . . . . } + 218 . . . . . . . . . } + 219 . . . . . . . . } + 220 . . . . . . . . Type: *ast.Ident { + 221 . . . . . . . . . NamePos: - + 222 . . . . . . . . . Name: "string" + 223 . . . . . . . . . Obj: nil + 224 . . . . . . . . } + 225 . . . . . . . . Tag: nil + 226 . . . . . . . . Comment: nil + 227 . . . . . . . } + 228 . . . . . . . 1: *ast.Field { + 229 . . . . . . . . Doc: nil + 230 . . . . . . . . Names: []*ast.Ident (len = 1) { + 231 . . . . . . . . . 0: *ast.Ident { + 232 . . . . . . . . . . NamePos: - + 233 . . . . . . . . . . Name: "signerPath" + 234 . . . . . . . . . . Obj: *ast.Object { + 235 . . . . . . . . . . . Kind: var + 236 . . . . . . . . . . . Name: "signerPath" + 237 . . . . . . . . . . . Decl: *(obj @ 228) + 238 . . . . . . . . . . . Data: nil + 239 . . . . . . . . . . . Type: nil + 240 . . . . . . . . . . } + 241 . . . . . . . . . } + 242 . . . . . . . . } + 243 . . . . . . . . Type: *ast.StarExpr { + 244 . . . . . . . . . Star: - + 245 . . . . . . . . . X: *ast.Ident { + 246 . . . . . . . . . . NamePos: - + 247 . . . . . . . . . . Name: "string" + 248 . . . . . . . . . . Obj: nil + 249 . . . . . . . . . } + 250 . . . . . . . . } + 251 . . . . . . . . Tag: nil + 252 . . . . . . . . Comment: nil + 253 . . . . . . . } + 254 . . . . . . } + 255 . . . . . . Closing: - + 256 . . . . . } + 257 . . . . . Results: *ast.FieldList { + 258 . . . . . . Opening: - + 259 . . . . . . List: []*ast.Field (len = 2) { + 260 . . . . . . . 0: *ast.Field { + 261 . . . . . . . . Doc: nil + 262 . . . . . . . . Names: nil + 263 . . . . . . . . Type: *ast.Ident { + 264 . . . . . . . . . NamePos: - + 265 . . . . . . . . . Name: "string" + 266 . . . . . . . . . Obj: nil + 267 . . . . . . . . } + 268 . . . . . . . . Tag: nil + 269 . . . . . . . . Comment: nil + 270 . . . . . . . } + 271 . . . . . . . 1: *ast.Field { + 272 . . . . . . . . Doc: nil + 273 . . . . . . . . Names: nil + 274 . . . . . . . . Type: *ast.Ident { + 275 . . . . . . . . . NamePos: - + 276 . . . . . . . . . Name: "error" + 277 . . . . . . . . . Obj: nil + 278 . . . . . . . . } + 279 . . . . . . . . Tag: nil + 280 . . . . . . . . Comment: nil + 281 . . . . . . . } + 282 . . . . . . } + 283 . . . . . . Closing: - + 284 . . . . . } + 285 . . . . } + 286 . . . . Tag: nil + 287 . . . . Comment: nil + 288 . . . } + 289 . . } + 290 . . Closing: - + 291 . } + 292 . Incomplete: false + 293 } + +``` +Crypt provides cryptographic functions. + + + + + +### `type Display` +```go +type Display 0 *ast.InterfaceType { + 1 . Interface: - + 2 . Methods: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 1) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: []*ast.Ident (len = 1) { + 8 . . . . . 0: *ast.Ident { + 9 . . . . . . NamePos: - + 10 . . . . . . Name: "OpenWindow" + 11 . . . . . . Obj: *ast.Object { + 12 . . . . . . . Kind: func + 13 . . . . . . . Name: "OpenWindow" + 14 . . . . . . . Decl: *(obj @ 5) + 15 . . . . . . . Data: nil + 16 . . . . . . . Type: nil + 17 . . . . . . } + 18 . . . . . } + 19 . . . . } + 20 . . . . Type: *ast.FuncType { + 21 . . . . . Func: - + 22 . . . . . TypeParams: nil + 23 . . . . . Params: *ast.FieldList { + 24 . . . . . . Opening: - + 25 . . . . . . List: []*ast.Field (len = 1) { + 26 . . . . . . . 0: *ast.Field { + 27 . . . . . . . . Doc: nil + 28 . . . . . . . . Names: []*ast.Ident (len = 1) { + 29 . . . . . . . . . 0: *ast.Ident { + 30 . . . . . . . . . . NamePos: - + 31 . . . . . . . . . . Name: "opts" + 32 . . . . . . . . . . Obj: *ast.Object { + 33 . . . . . . . . . . . Kind: var + 34 . . . . . . . . . . . Name: "opts" + 35 . . . . . . . . . . . Decl: *(obj @ 26) + 36 . . . . . . . . . . . Data: nil + 37 . . . . . . . . . . . Type: nil + 38 . . . . . . . . . . } + 39 . . . . . . . . . } + 40 . . . . . . . . } + 41 . . . . . . . . Type: *ast.Ellipsis { + 42 . . . . . . . . . Ellipsis: - + 43 . . . . . . . . . Elt: *ast.Ident { + 44 . . . . . . . . . . NamePos: - + 45 . . . . . . . . . . Name: "WindowOption" + 46 . . . . . . . . . . Obj: *ast.Object { + 47 . . . . . . . . . . . Kind: type + 48 . . . . . . . . . . . Name: "WindowOption" + 49 . . . . . . . . . . . Decl: *ast.TypeSpec { + 50 . . . . . . . . . . . . Doc: nil + 51 . . . . . . . . . . . . Name: *ast.Ident { + 52 . . . . . . . . . . . . . NamePos: - + 53 . . . . . . . . . . . . . Name: "WindowOption" + 54 . . . . . . . . . . . . . Obj: *(obj @ 46) + 55 . . . . . . . . . . . . } + 56 . . . . . . . . . . . . TypeParams: nil + 57 . . . . . . . . . . . . Assign: - + 58 . . . . . . . . . . . . Type: *ast.InterfaceType { + 59 . . . . . . . . . . . . . Interface: - + 60 . . . . . . . . . . . . . Methods: *ast.FieldList { + 61 . . . . . . . . . . . . . . Opening: - + 62 . . . . . . . . . . . . . . List: []*ast.Field (len = 1) { + 63 . . . . . . . . . . . . . . . 0: *ast.Field { + 64 . . . . . . . . . . . . . . . . Doc: nil + 65 . . . . . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 66 . . . . . . . . . . . . . . . . . 0: *ast.Ident { + 67 . . . . . . . . . . . . . . . . . . NamePos: - + 68 . . . . . . . . . . . . . . . . . . Name: "Apply" + 69 . . . . . . . . . . . . . . . . . . Obj: *ast.Object { + 70 . . . . . . . . . . . . . . . . . . . Kind: func + 71 . . . . . . . . . . . . . . . . . . . Name: "Apply" + 72 . . . . . . . . . . . . . . . . . . . Decl: *(obj @ 63) + 73 . . . . . . . . . . . . . . . . . . . Data: nil + 74 . . . . . . . . . . . . . . . . . . . Type: nil + 75 . . . . . . . . . . . . . . . . . . } + 76 . . . . . . . . . . . . . . . . . } + 77 . . . . . . . . . . . . . . . . } + 78 . . . . . . . . . . . . . . . . Type: *ast.FuncType { + 79 . . . . . . . . . . . . . . . . . Func: - + 80 . . . . . . . . . . . . . . . . . TypeParams: nil + 81 . . . . . . . . . . . . . . . . . Params: *ast.FieldList { + 82 . . . . . . . . . . . . . . . . . . Opening: - + 83 . . . . . . . . . . . . . . . . . . List: []*ast.Field (len = 1) { + 84 . . . . . . . . . . . . . . . . . . . 0: *ast.Field { + 85 . . . . . . . . . . . . . . . . . . . . Doc: nil + 86 . . . . . . . . . . . . . . . . . . . . Names: nil + 87 . . . . . . . . . . . . . . . . . . . . Type: *ast.StarExpr { + 88 . . . . . . . . . . . . . . . . . . . . . Star: - + 89 . . . . . . . . . . . . . . . . . . . . . X: *ast.Ident { + 90 . . . . . . . . . . . . . . . . . . . . . . NamePos: - + 91 . . . . . . . . . . . . . . . . . . . . . . Name: "WindowConfig" + 92 . . . . . . . . . . . . . . . . . . . . . . Obj: *ast.Object { + 93 . . . . . . . . . . . . . . . . . . . . . . . Kind: type + 94 . . . . . . . . . . . . . . . . . . . . . . . Name: "WindowConfig" + 95 . . . . . . . . . . . . . . . . . . . . . . . Decl: *ast.TypeSpec { + 96 . . . . . . . . . . . . . . . . . . . . . . . . Doc: nil + 97 . . . . . . . . . . . . . . . . . . . . . . . . Name: *ast.Ident { + 98 . . . . . . . . . . . . . . . . . . . . . . . . . NamePos: - + 99 . . . . . . . . . . . . . . . . . . . . . . . . . Name: "WindowConfig" + 100 . . . . . . . . . . . . . . . . . . . . . . . . . Obj: *(obj @ 92) + 101 . . . . . . . . . . . . . . . . . . . . . . . . } + 102 . . . . . . . . . . . . . . . . . . . . . . . . TypeParams: nil + 103 . . . . . . . . . . . . . . . . . . . . . . . . Assign: - + 104 . . . . . . . . . . . . . . . . . . . . . . . . Type: *ast.StructType { + 105 . . . . . . . . . . . . . . . . . . . . . . . . . Struct: - + 106 . . . . . . . . . . . . . . . . . . . . . . . . . Fields: *ast.FieldList { + 107 . . . . . . . . . . . . . . . . . . . . . . . . . . Opening: - + 108 . . . . . . . . . . . . . . . . . . . . . . . . . . List: []*ast.Field (len = 5) { + 109 . . . . . . . . . . . . . . . . . . . . . . . . . . . 0: *ast.Field { + 110 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Doc: nil + 111 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 112 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0: *ast.Ident { + 113 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . NamePos: - + 114 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Name: "Name" + 115 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obj: *ast.Object { + 116 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kind: var + 117 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Name: "Name" + 118 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Decl: *(obj @ 109) + 119 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Data: nil + 120 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Type: nil + 121 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 122 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 123 . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 124 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Type: *ast.Ident { + 125 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . NamePos: - + 126 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Name: "string" + 127 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obj: nil + 128 . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 129 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tag: nil + 130 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Comment: nil + 131 . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 132 . . . . . . . . . . . . . . . . . . . . . . . . . . . 1: *ast.Field { + 133 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Doc: nil + 134 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 135 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0: *ast.Ident { + 136 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . NamePos: - + 137 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Name: "Title" + 138 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obj: *ast.Object { + 139 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kind: var + 140 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Name: "Title" + 141 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Decl: *(obj @ 132) + 142 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Data: nil + 143 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Type: nil + 144 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 145 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 146 . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 147 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Type: *ast.Ident { + 148 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . NamePos: - + 149 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Name: "string" + 150 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obj: nil + 151 . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 152 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tag: nil + 153 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Comment: nil + 154 . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 155 . . . . . . . . . . . . . . . . . . . . . . . . . . . 2: *ast.Field { + 156 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Doc: nil + 157 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 158 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0: *ast.Ident { + 159 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . NamePos: - + 160 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Name: "URL" + 161 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obj: *ast.Object { + 162 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kind: var + 163 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Name: "URL" + 164 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Decl: *(obj @ 155) + 165 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Data: nil + 166 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Type: nil + 167 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 168 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 169 . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 170 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Type: *ast.Ident { + 171 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . NamePos: - + 172 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Name: "string" + 173 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obj: nil + 174 . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 175 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tag: nil + 176 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Comment: nil + 177 . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 178 . . . . . . . . . . . . . . . . . . . . . . . . . . . 3: *ast.Field { + 179 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Doc: nil + 180 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 181 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0: *ast.Ident { + 182 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . NamePos: - + 183 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Name: "Width" + 184 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obj: *ast.Object { + 185 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kind: var + 186 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Name: "Width" + 187 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Decl: *(obj @ 178) + 188 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Data: nil + 189 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Type: nil + 190 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 191 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 192 . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 193 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Type: *ast.Ident { + 194 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . NamePos: - + 195 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Name: "int" + 196 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obj: nil + 197 . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 198 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tag: nil + 199 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Comment: nil + 200 . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 201 . . . . . . . . . . . . . . . . . . . . . . . . . . . 4: *ast.Field { + 202 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Doc: nil + 203 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 204 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0: *ast.Ident { + 205 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . NamePos: - + 206 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Name: "Height" + 207 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obj: *ast.Object { + 208 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kind: var + 209 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Name: "Height" + 210 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Decl: *(obj @ 201) + 211 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Data: nil + 212 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Type: nil + 213 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 214 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 215 . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 216 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Type: *ast.Ident { + 217 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . NamePos: - + 218 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Name: "int" + 219 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obj: nil + 220 . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 221 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tag: nil + 222 . . . . . . . . . . . . . . . . . . . . . . . . . . . . Comment: *ast.CommentGroup { + 223 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . List: []*ast.Comment (len = 1) { + 224 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0: *ast.Comment { + 225 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Slash: - + 226 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Text: "// Add other common window options here as needed" + 227 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 228 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 229 . . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 230 . . . . . . . . . . . . . . . . . . . . . . . . . . . } + 231 . . . . . . . . . . . . . . . . . . . . . . . . . . } + 232 . . . . . . . . . . . . . . . . . . . . . . . . . . Closing: - + 233 . . . . . . . . . . . . . . . . . . . . . . . . . } + 234 . . . . . . . . . . . . . . . . . . . . . . . . . Incomplete: false + 235 . . . . . . . . . . . . . . . . . . . . . . . . } + 236 . . . . . . . . . . . . . . . . . . . . . . . . Comment: nil + 237 . . . . . . . . . . . . . . . . . . . . . . . } + 238 . . . . . . . . . . . . . . . . . . . . . . . Data: nil + 239 . . . . . . . . . . . . . . . . . . . . . . . Type: nil + 240 . . . . . . . . . . . . . . . . . . . . . . } + 241 . . . . . . . . . . . . . . . . . . . . . } + 242 . . . . . . . . . . . . . . . . . . . . } + 243 . . . . . . . . . . . . . . . . . . . . Tag: nil + 244 . . . . . . . . . . . . . . . . . . . . Comment: nil + 245 . . . . . . . . . . . . . . . . . . . } + 246 . . . . . . . . . . . . . . . . . . } + 247 . . . . . . . . . . . . . . . . . . Closing: - + 248 . . . . . . . . . . . . . . . . . } + 249 . . . . . . . . . . . . . . . . . Results: nil + 250 . . . . . . . . . . . . . . . . } + 251 . . . . . . . . . . . . . . . . Tag: nil + 252 . . . . . . . . . . . . . . . . Comment: nil + 253 . . . . . . . . . . . . . . . } + 254 . . . . . . . . . . . . . . } + 255 . . . . . . . . . . . . . . Closing: - + 256 . . . . . . . . . . . . . } + 257 . . . . . . . . . . . . . Incomplete: false + 258 . . . . . . . . . . . . } + 259 . . . . . . . . . . . . Comment: nil + 260 . . . . . . . . . . . } + 261 . . . . . . . . . . . Data: nil + 262 . . . . . . . . . . . Type: nil + 263 . . . . . . . . . . } + 264 . . . . . . . . . } + 265 . . . . . . . . } + 266 . . . . . . . . Tag: nil + 267 . . . . . . . . Comment: nil + 268 . . . . . . . } + 269 . . . . . . } + 270 . . . . . . Closing: - + 271 . . . . . } + 272 . . . . . Results: *ast.FieldList { + 273 . . . . . . Opening: - + 274 . . . . . . List: []*ast.Field (len = 1) { + 275 . . . . . . . 0: *ast.Field { + 276 . . . . . . . . Doc: nil + 277 . . . . . . . . Names: nil + 278 . . . . . . . . Type: *ast.Ident { + 279 . . . . . . . . . NamePos: - + 280 . . . . . . . . . Name: "error" + 281 . . . . . . . . . Obj: nil + 282 . . . . . . . . } + 283 . . . . . . . . Tag: nil + 284 . . . . . . . . Comment: nil + 285 . . . . . . . } + 286 . . . . . . } + 287 . . . . . . Closing: - + 288 . . . . . } + 289 . . . . } + 290 . . . . Tag: nil + 291 . . . . Comment: nil + 292 . . . } + 293 . . } + 294 . . Closing: - + 295 . } + 296 . Incomplete: false + 297 } + +``` +Display manages windows and UI. + + + + + +### `type Help` +```go +type Help 0 *ast.InterfaceType { + 1 . Interface: - + 2 . Methods: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 2) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: []*ast.Ident (len = 1) { + 8 . . . . . 0: *ast.Ident { + 9 . . . . . . NamePos: - + 10 . . . . . . Name: "Show" + 11 . . . . . . Obj: *ast.Object { + 12 . . . . . . . Kind: func + 13 . . . . . . . Name: "Show" + 14 . . . . . . . Decl: *(obj @ 5) + 15 . . . . . . . Data: nil + 16 . . . . . . . Type: nil + 17 . . . . . . } + 18 . . . . . } + 19 . . . . } + 20 . . . . Type: *ast.FuncType { + 21 . . . . . Func: - + 22 . . . . . TypeParams: nil + 23 . . . . . Params: *ast.FieldList { + 24 . . . . . . Opening: - + 25 . . . . . . List: nil + 26 . . . . . . Closing: - + 27 . . . . . } + 28 . . . . . Results: *ast.FieldList { + 29 . . . . . . Opening: - + 30 . . . . . . List: []*ast.Field (len = 1) { + 31 . . . . . . . 0: *ast.Field { + 32 . . . . . . . . Doc: nil + 33 . . . . . . . . Names: nil + 34 . . . . . . . . Type: *ast.Ident { + 35 . . . . . . . . . NamePos: - + 36 . . . . . . . . . Name: "error" + 37 . . . . . . . . . Obj: nil + 38 . . . . . . . . } + 39 . . . . . . . . Tag: nil + 40 . . . . . . . . Comment: nil + 41 . . . . . . . } + 42 . . . . . . } + 43 . . . . . . Closing: - + 44 . . . . . } + 45 . . . . } + 46 . . . . Tag: nil + 47 . . . . Comment: nil + 48 . . . } + 49 . . . 1: *ast.Field { + 50 . . . . Doc: nil + 51 . . . . Names: []*ast.Ident (len = 1) { + 52 . . . . . 0: *ast.Ident { + 53 . . . . . . NamePos: - + 54 . . . . . . Name: "ShowAt" + 55 . . . . . . Obj: *ast.Object { + 56 . . . . . . . Kind: func + 57 . . . . . . . Name: "ShowAt" + 58 . . . . . . . Decl: *(obj @ 49) + 59 . . . . . . . Data: nil + 60 . . . . . . . Type: nil + 61 . . . . . . } + 62 . . . . . } + 63 . . . . } + 64 . . . . Type: *ast.FuncType { + 65 . . . . . Func: - + 66 . . . . . TypeParams: nil + 67 . . . . . Params: *ast.FieldList { + 68 . . . . . . Opening: - + 69 . . . . . . List: []*ast.Field (len = 1) { + 70 . . . . . . . 0: *ast.Field { + 71 . . . . . . . . Doc: nil + 72 . . . . . . . . Names: []*ast.Ident (len = 1) { + 73 . . . . . . . . . 0: *ast.Ident { + 74 . . . . . . . . . . NamePos: - + 75 . . . . . . . . . . Name: "anchor" + 76 . . . . . . . . . . Obj: *ast.Object { + 77 . . . . . . . . . . . Kind: var + 78 . . . . . . . . . . . Name: "anchor" + 79 . . . . . . . . . . . Decl: *(obj @ 70) + 80 . . . . . . . . . . . Data: nil + 81 . . . . . . . . . . . Type: nil + 82 . . . . . . . . . . } + 83 . . . . . . . . . } + 84 . . . . . . . . } + 85 . . . . . . . . Type: *ast.Ident { + 86 . . . . . . . . . NamePos: - + 87 . . . . . . . . . Name: "string" + 88 . . . . . . . . . Obj: nil + 89 . . . . . . . . } + 90 . . . . . . . . Tag: nil + 91 . . . . . . . . Comment: nil + 92 . . . . . . . } + 93 . . . . . . } + 94 . . . . . . Closing: - + 95 . . . . . } + 96 . . . . . Results: *ast.FieldList { + 97 . . . . . . Opening: - + 98 . . . . . . List: []*ast.Field (len = 1) { + 99 . . . . . . . 0: *ast.Field { + 100 . . . . . . . . Doc: nil + 101 . . . . . . . . Names: nil + 102 . . . . . . . . Type: *ast.Ident { + 103 . . . . . . . . . NamePos: - + 104 . . . . . . . . . Name: "error" + 105 . . . . . . . . . Obj: nil + 106 . . . . . . . . } + 107 . . . . . . . . Tag: nil + 108 . . . . . . . . Comment: nil + 109 . . . . . . . } + 110 . . . . . . } + 111 . . . . . . Closing: - + 112 . . . . . } + 113 . . . . } + 114 . . . . Tag: nil + 115 . . . . Comment: nil + 116 . . . } + 117 . . } + 118 . . Closing: - + 119 . } + 120 . Incomplete: false + 121 } + +``` +Help manages the in-app documentation and help system. + + + + + +### `type I18n` +```go +type I18n 0 *ast.InterfaceType { + 1 . Interface: - + 2 . Methods: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 2) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: *ast.CommentGroup { + 7 . . . . . List: []*ast.Comment (len = 1) { + 8 . . . . . . 0: *ast.Comment { + 9 . . . . . . . Slash: - + 10 . . . . . . . Text: "// Translate returns the translated string for the given key." + 11 . . . . . . } + 12 . . . . . } + 13 . . . . } + 14 . . . . Names: []*ast.Ident (len = 1) { + 15 . . . . . 0: *ast.Ident { + 16 . . . . . . NamePos: - + 17 . . . . . . Name: "Translate" + 18 . . . . . . Obj: *ast.Object { + 19 . . . . . . . Kind: func + 20 . . . . . . . Name: "Translate" + 21 . . . . . . . Decl: *(obj @ 5) + 22 . . . . . . . Data: nil + 23 . . . . . . . Type: nil + 24 . . . . . . } + 25 . . . . . } + 26 . . . . } + 27 . . . . Type: *ast.FuncType { + 28 . . . . . Func: - + 29 . . . . . TypeParams: nil + 30 . . . . . Params: *ast.FieldList { + 31 . . . . . . Opening: - + 32 . . . . . . List: []*ast.Field (len = 1) { + 33 . . . . . . . 0: *ast.Field { + 34 . . . . . . . . Doc: nil + 35 . . . . . . . . Names: []*ast.Ident (len = 1) { + 36 . . . . . . . . . 0: *ast.Ident { + 37 . . . . . . . . . . NamePos: - + 38 . . . . . . . . . . Name: "key" + 39 . . . . . . . . . . Obj: *ast.Object { + 40 . . . . . . . . . . . Kind: var + 41 . . . . . . . . . . . Name: "key" + 42 . . . . . . . . . . . Decl: *(obj @ 33) + 43 . . . . . . . . . . . Data: nil + 44 . . . . . . . . . . . Type: nil + 45 . . . . . . . . . . } + 46 . . . . . . . . . } + 47 . . . . . . . . } + 48 . . . . . . . . Type: *ast.Ident { + 49 . . . . . . . . . NamePos: - + 50 . . . . . . . . . Name: "string" + 51 . . . . . . . . . Obj: nil + 52 . . . . . . . . } + 53 . . . . . . . . Tag: nil + 54 . . . . . . . . Comment: nil + 55 . . . . . . . } + 56 . . . . . . } + 57 . . . . . . Closing: - + 58 . . . . . } + 59 . . . . . Results: *ast.FieldList { + 60 . . . . . . Opening: - + 61 . . . . . . List: []*ast.Field (len = 1) { + 62 . . . . . . . 0: *ast.Field { + 63 . . . . . . . . Doc: nil + 64 . . . . . . . . Names: nil + 65 . . . . . . . . Type: *ast.Ident { + 66 . . . . . . . . . NamePos: - + 67 . . . . . . . . . Name: "string" + 68 . . . . . . . . . Obj: nil + 69 . . . . . . . . } + 70 . . . . . . . . Tag: nil + 71 . . . . . . . . Comment: nil + 72 . . . . . . . } + 73 . . . . . . } + 74 . . . . . . Closing: - + 75 . . . . . } + 76 . . . . } + 77 . . . . Tag: nil + 78 . . . . Comment: nil + 79 . . . } + 80 . . . 1: *ast.Field { + 81 . . . . Doc: *ast.CommentGroup { + 82 . . . . . List: []*ast.Comment (len = 1) { + 83 . . . . . . 0: *ast.Comment { + 84 . . . . . . . Slash: - + 85 . . . . . . . Text: "// SetLanguage changes the active language." + 86 . . . . . . } + 87 . . . . . } + 88 . . . . } + 89 . . . . Names: []*ast.Ident (len = 1) { + 90 . . . . . 0: *ast.Ident { + 91 . . . . . . NamePos: - + 92 . . . . . . Name: "SetLanguage" + 93 . . . . . . Obj: *ast.Object { + 94 . . . . . . . Kind: func + 95 . . . . . . . Name: "SetLanguage" + 96 . . . . . . . Decl: *(obj @ 80) + 97 . . . . . . . Data: nil + 98 . . . . . . . Type: nil + 99 . . . . . . } + 100 . . . . . } + 101 . . . . } + 102 . . . . Type: *ast.FuncType { + 103 . . . . . Func: - + 104 . . . . . TypeParams: nil + 105 . . . . . Params: *ast.FieldList { + 106 . . . . . . Opening: - + 107 . . . . . . List: []*ast.Field (len = 1) { + 108 . . . . . . . 0: *ast.Field { + 109 . . . . . . . . Doc: nil + 110 . . . . . . . . Names: []*ast.Ident (len = 1) { + 111 . . . . . . . . . 0: *ast.Ident { + 112 . . . . . . . . . . NamePos: - + 113 . . . . . . . . . . Name: "lang" + 114 . . . . . . . . . . Obj: *ast.Object { + 115 . . . . . . . . . . . Kind: var + 116 . . . . . . . . . . . Name: "lang" + 117 . . . . . . . . . . . Decl: *(obj @ 108) + 118 . . . . . . . . . . . Data: nil + 119 . . . . . . . . . . . Type: nil + 120 . . . . . . . . . . } + 121 . . . . . . . . . } + 122 . . . . . . . . } + 123 . . . . . . . . Type: *ast.Ident { + 124 . . . . . . . . . NamePos: - + 125 . . . . . . . . . Name: "string" + 126 . . . . . . . . . Obj: nil + 127 . . . . . . . . } + 128 . . . . . . . . Tag: nil + 129 . . . . . . . . Comment: nil + 130 . . . . . . . } + 131 . . . . . . } + 132 . . . . . . Closing: - + 133 . . . . . } + 134 . . . . . Results: *ast.FieldList { + 135 . . . . . . Opening: - + 136 . . . . . . List: []*ast.Field (len = 1) { + 137 . . . . . . . 0: *ast.Field { + 138 . . . . . . . . Doc: nil + 139 . . . . . . . . Names: nil + 140 . . . . . . . . Type: *ast.Ident { + 141 . . . . . . . . . NamePos: - + 142 . . . . . . . . . Name: "error" + 143 . . . . . . . . . Obj: nil + 144 . . . . . . . . } + 145 . . . . . . . . Tag: nil + 146 . . . . . . . . Comment: nil + 147 . . . . . . . } + 148 . . . . . . } + 149 . . . . . . Closing: - + 150 . . . . . } + 151 . . . . } + 152 . . . . Tag: nil + 153 . . . . Comment: nil + 154 . . . } + 155 . . } + 156 . . Closing: - + 157 . } + 158 . Incomplete: false + 159 } + +``` +I18n provides internationalization and localization services. + + + + + +### `type Message` +```go +type Message 0 *ast.InterfaceType { + 1 . Interface: - + 2 . Methods: *ast.FieldList { + 3 . . Opening: - + 4 . . List: nil + 5 . . Closing: - + 6 . } + 7 . Incomplete: false + 8 } + +``` + + + + + +### `type Option` +```go +type Option 0 *ast.FuncType { + 1 . Func: - + 2 . TypeParams: nil + 3 . Params: *ast.FieldList { + 4 . . Opening: - + 5 . . List: []*ast.Field (len = 1) { + 6 . . . 0: *ast.Field { + 7 . . . . Doc: nil + 8 . . . . Names: nil + 9 . . . . Type: *ast.StarExpr { + 10 . . . . . Star: - + 11 . . . . . X: *ast.Ident { + 12 . . . . . . NamePos: - + 13 . . . . . . Name: "Core" + 14 . . . . . . Obj: *ast.Object { + 15 . . . . . . . Kind: type + 16 . . . . . . . Name: "Core" + 17 . . . . . . . Decl: *ast.TypeSpec { + 18 . . . . . . . . Doc: nil + 19 . . . . . . . . Name: *ast.Ident { + 20 . . . . . . . . . NamePos: - + 21 . . . . . . . . . Name: "Core" + 22 . . . . . . . . . Obj: *(obj @ 14) + 23 . . . . . . . . } + 24 . . . . . . . . TypeParams: nil + 25 . . . . . . . . Assign: - + 26 . . . . . . . . Type: *ast.StructType { + 27 . . . . . . . . . Struct: - + 28 . . . . . . . . . Fields: *ast.FieldList { + 29 . . . . . . . . . . Opening: - + 30 . . . . . . . . . . List: []*ast.Field (len = 10) { + 31 . . . . . . . . . . . 0: *ast.Field { + 32 . . . . . . . . . . . . Doc: nil + 33 . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 34 . . . . . . . . . . . . . 0: *ast.Ident { + 35 . . . . . . . . . . . . . . NamePos: - + 36 . . . . . . . . . . . . . . Name: "once" + 37 . . . . . . . . . . . . . . Obj: *ast.Object { + 38 . . . . . . . . . . . . . . . Kind: var + 39 . . . . . . . . . . . . . . . Name: "once" + 40 . . . . . . . . . . . . . . . Decl: *(obj @ 31) + 41 . . . . . . . . . . . . . . . Data: nil + 42 . . . . . . . . . . . . . . . Type: nil + 43 . . . . . . . . . . . . . . } + 44 . . . . . . . . . . . . . } + 45 . . . . . . . . . . . . } + 46 . . . . . . . . . . . . Type: *ast.SelectorExpr { + 47 . . . . . . . . . . . . . X: *ast.Ident { + 48 . . . . . . . . . . . . . . NamePos: - + 49 . . . . . . . . . . . . . . Name: "sync" + 50 . . . . . . . . . . . . . . Obj: nil + 51 . . . . . . . . . . . . . } + 52 . . . . . . . . . . . . . Sel: *ast.Ident { + 53 . . . . . . . . . . . . . . NamePos: - + 54 . . . . . . . . . . . . . . Name: "Once" + 55 . . . . . . . . . . . . . . Obj: nil + 56 . . . . . . . . . . . . . } + 57 . . . . . . . . . . . . } + 58 . . . . . . . . . . . . Tag: nil + 59 . . . . . . . . . . . . Comment: nil + 60 . . . . . . . . . . . } + 61 . . . . . . . . . . . 1: *ast.Field { + 62 . . . . . . . . . . . . Doc: nil + 63 . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 64 . . . . . . . . . . . . . 0: *ast.Ident { + 65 . . . . . . . . . . . . . . NamePos: - + 66 . . . . . . . . . . . . . . Name: "initErr" + 67 . . . . . . . . . . . . . . Obj: *ast.Object { + 68 . . . . . . . . . . . . . . . Kind: var + 69 . . . . . . . . . . . . . . . Name: "initErr" + 70 . . . . . . . . . . . . . . . Decl: *(obj @ 61) + 71 . . . . . . . . . . . . . . . Data: nil + 72 . . . . . . . . . . . . . . . Type: nil + 73 . . . . . . . . . . . . . . } + 74 . . . . . . . . . . . . . } + 75 . . . . . . . . . . . . } + 76 . . . . . . . . . . . . Type: *ast.Ident { + 77 . . . . . . . . . . . . . NamePos: - + 78 . . . . . . . . . . . . . Name: "error" + 79 . . . . . . . . . . . . . Obj: nil + 80 . . . . . . . . . . . . } + 81 . . . . . . . . . . . . Tag: nil + 82 . . . . . . . . . . . . Comment: nil + 83 . . . . . . . . . . . } + 84 . . . . . . . . . . . 2: *ast.Field { + 85 . . . . . . . . . . . . Doc: nil + 86 . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 87 . . . . . . . . . . . . . 0: *ast.Ident { + 88 . . . . . . . . . . . . . . NamePos: - + 89 . . . . . . . . . . . . . . Name: "App" + 90 . . . . . . . . . . . . . . Obj: *ast.Object { + 91 . . . . . . . . . . . . . . . Kind: var + 92 . . . . . . . . . . . . . . . Name: "App" + 93 . . . . . . . . . . . . . . . Decl: *(obj @ 84) + 94 . . . . . . . . . . . . . . . Data: nil + 95 . . . . . . . . . . . . . . . Type: nil + 96 . . . . . . . . . . . . . . } + 97 . . . . . . . . . . . . . } + 98 . . . . . . . . . . . . } + 99 . . . . . . . . . . . . Type: *ast.StarExpr { + 100 . . . . . . . . . . . . . Star: - + 101 . . . . . . . . . . . . . X: *ast.SelectorExpr { + 102 . . . . . . . . . . . . . . X: *ast.Ident { + 103 . . . . . . . . . . . . . . . NamePos: - + 104 . . . . . . . . . . . . . . . Name: "application" + 105 . . . . . . . . . . . . . . . Obj: nil + 106 . . . . . . . . . . . . . . } + 107 . . . . . . . . . . . . . . Sel: *ast.Ident { + 108 . . . . . . . . . . . . . . . NamePos: - + 109 . . . . . . . . . . . . . . . Name: "App" + 110 . . . . . . . . . . . . . . . Obj: nil + 111 . . . . . . . . . . . . . . } + 112 . . . . . . . . . . . . . } + 113 . . . . . . . . . . . . } + 114 . . . . . . . . . . . . Tag: nil + 115 . . . . . . . . . . . . Comment: nil + 116 . . . . . . . . . . . } + 117 . . . . . . . . . . . 3: *ast.Field { + 118 . . . . . . . . . . . . Doc: nil + 119 . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 120 . . . . . . . . . . . . . 0: *ast.Ident { + 121 . . . . . . . . . . . . . . NamePos: - + 122 . . . . . . . . . . . . . . Name: "assets" + 123 . . . . . . . . . . . . . . Obj: *ast.Object { + 124 . . . . . . . . . . . . . . . Kind: var + 125 . . . . . . . . . . . . . . . Name: "assets" + 126 . . . . . . . . . . . . . . . Decl: *(obj @ 117) + 127 . . . . . . . . . . . . . . . Data: nil + 128 . . . . . . . . . . . . . . . Type: nil + 129 . . . . . . . . . . . . . . } + 130 . . . . . . . . . . . . . } + 131 . . . . . . . . . . . . } + 132 . . . . . . . . . . . . Type: *ast.SelectorExpr { + 133 . . . . . . . . . . . . . X: *ast.Ident { + 134 . . . . . . . . . . . . . . NamePos: - + 135 . . . . . . . . . . . . . . Name: "embed" + 136 . . . . . . . . . . . . . . Obj: nil + 137 . . . . . . . . . . . . . } + 138 . . . . . . . . . . . . . Sel: *ast.Ident { + 139 . . . . . . . . . . . . . . NamePos: - + 140 . . . . . . . . . . . . . . Name: "FS" + 141 . . . . . . . . . . . . . . Obj: nil + 142 . . . . . . . . . . . . . } + 143 . . . . . . . . . . . . } + 144 . . . . . . . . . . . . Tag: nil + 145 . . . . . . . . . . . . Comment: nil + 146 . . . . . . . . . . . } + 147 . . . . . . . . . . . 4: *ast.Field { + 148 . . . . . . . . . . . . Doc: nil + 149 . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 150 . . . . . . . . . . . . . 0: *ast.Ident { + 151 . . . . . . . . . . . . . . NamePos: - + 152 . . . . . . . . . . . . . . Name: "serviceLock" + 153 . . . . . . . . . . . . . . Obj: *ast.Object { + 154 . . . . . . . . . . . . . . . Kind: var + 155 . . . . . . . . . . . . . . . Name: "serviceLock" + 156 . . . . . . . . . . . . . . . Decl: *(obj @ 147) + 157 . . . . . . . . . . . . . . . Data: nil + 158 . . . . . . . . . . . . . . . Type: nil + 159 . . . . . . . . . . . . . . } + 160 . . . . . . . . . . . . . } + 161 . . . . . . . . . . . . } + 162 . . . . . . . . . . . . Type: *ast.Ident { + 163 . . . . . . . . . . . . . NamePos: - + 164 . . . . . . . . . . . . . Name: "bool" + 165 . . . . . . . . . . . . . Obj: nil + 166 . . . . . . . . . . . . } + 167 . . . . . . . . . . . . Tag: nil + 168 . . . . . . . . . . . . Comment: nil + 169 . . . . . . . . . . . } + 170 . . . . . . . . . . . 5: *ast.Field { + 171 . . . . . . . . . . . . Doc: nil + 172 . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 173 . . . . . . . . . . . . . 0: *ast.Ident { + 174 . . . . . . . . . . . . . . NamePos: - + 175 . . . . . . . . . . . . . . Name: "ipcMu" + 176 . . . . . . . . . . . . . . Obj: *ast.Object { + 177 . . . . . . . . . . . . . . . Kind: var + 178 . . . . . . . . . . . . . . . Name: "ipcMu" + 179 . . . . . . . . . . . . . . . Decl: *(obj @ 170) + 180 . . . . . . . . . . . . . . . Data: nil + 181 . . . . . . . . . . . . . . . Type: nil + 182 . . . . . . . . . . . . . . } + 183 . . . . . . . . . . . . . } + 184 . . . . . . . . . . . . } + 185 . . . . . . . . . . . . Type: *ast.SelectorExpr { + 186 . . . . . . . . . . . . . X: *ast.Ident { + 187 . . . . . . . . . . . . . . NamePos: - + 188 . . . . . . . . . . . . . . Name: "sync" + 189 . . . . . . . . . . . . . . Obj: nil + 190 . . . . . . . . . . . . . } + 191 . . . . . . . . . . . . . Sel: *ast.Ident { + 192 . . . . . . . . . . . . . . NamePos: - + 193 . . . . . . . . . . . . . . Name: "RWMutex" + 194 . . . . . . . . . . . . . . Obj: nil + 195 . . . . . . . . . . . . . } + 196 . . . . . . . . . . . . } + 197 . . . . . . . . . . . . Tag: nil + 198 . . . . . . . . . . . . Comment: nil + 199 . . . . . . . . . . . } + 200 . . . . . . . . . . . 6: *ast.Field { + 201 . . . . . . . . . . . . Doc: nil + 202 . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 203 . . . . . . . . . . . . . 0: *ast.Ident { + 204 . . . . . . . . . . . . . . NamePos: - + 205 . . . . . . . . . . . . . . Name: "ipcHandlers" + 206 . . . . . . . . . . . . . . Obj: *ast.Object { + 207 . . . . . . . . . . . . . . . Kind: var + 208 . . . . . . . . . . . . . . . Name: "ipcHandlers" + 209 . . . . . . . . . . . . . . . Decl: *(obj @ 200) + 210 . . . . . . . . . . . . . . . Data: nil + 211 . . . . . . . . . . . . . . . Type: nil + 212 . . . . . . . . . . . . . . } + 213 . . . . . . . . . . . . . } + 214 . . . . . . . . . . . . } + 215 . . . . . . . . . . . . Type: *ast.ArrayType { + 216 . . . . . . . . . . . . . Lbrack: - + 217 . . . . . . . . . . . . . Len: nil + 218 . . . . . . . . . . . . . Elt: *ast.FuncType { + 219 . . . . . . . . . . . . . . Func: - + 220 . . . . . . . . . . . . . . TypeParams: nil + 221 . . . . . . . . . . . . . . Params: *ast.FieldList { + 222 . . . . . . . . . . . . . . . Opening: - + 223 . . . . . . . . . . . . . . . List: []*ast.Field (len = 2) { + 224 . . . . . . . . . . . . . . . . 0: *ast.Field { + 225 . . . . . . . . . . . . . . . . . Doc: nil + 226 . . . . . . . . . . . . . . . . . Names: nil + 227 . . . . . . . . . . . . . . . . . Type: *ast.StarExpr { + 228 . . . . . . . . . . . . . . . . . . Star: - + 229 . . . . . . . . . . . . . . . . . . X: *ast.Ident { + 230 . . . . . . . . . . . . . . . . . . . NamePos: - + 231 . . . . . . . . . . . . . . . . . . . Name: "Core" + 232 . . . . . . . . . . . . . . . . . . . Obj: *(obj @ 14) + 233 . . . . . . . . . . . . . . . . . . } + 234 . . . . . . . . . . . . . . . . . } + 235 . . . . . . . . . . . . . . . . . Tag: nil + 236 . . . . . . . . . . . . . . . . . Comment: nil + 237 . . . . . . . . . . . . . . . . } + 238 . . . . . . . . . . . . . . . . 1: *ast.Field { + 239 . . . . . . . . . . . . . . . . . Doc: nil + 240 . . . . . . . . . . . . . . . . . Names: nil + 241 . . . . . . . . . . . . . . . . . Type: *ast.Ident { + 242 . . . . . . . . . . . . . . . . . . NamePos: - + 243 . . . . . . . . . . . . . . . . . . Name: "Message" + 244 . . . . . . . . . . . . . . . . . . Obj: *ast.Object { + 245 . . . . . . . . . . . . . . . . . . . Kind: type + 246 . . . . . . . . . . . . . . . . . . . Name: "Message" + 247 . . . . . . . . . . . . . . . . . . . Decl: *ast.TypeSpec { + 248 . . . . . . . . . . . . . . . . . . . . Doc: nil + 249 . . . . . . . . . . . . . . . . . . . . Name: *ast.Ident { + 250 . . . . . . . . . . . . . . . . . . . . . NamePos: - + 251 . . . . . . . . . . . . . . . . . . . . . Name: "Message" + 252 . . . . . . . . . . . . . . . . . . . . . Obj: *(obj @ 244) + 253 . . . . . . . . . . . . . . . . . . . . } + 254 . . . . . . . . . . . . . . . . . . . . TypeParams: nil + 255 . . . . . . . . . . . . . . . . . . . . Assign: - + 256 . . . . . . . . . . . . . . . . . . . . Type: *ast.InterfaceType { + 257 . . . . . . . . . . . . . . . . . . . . . Interface: - + 258 . . . . . . . . . . . . . . . . . . . . . Methods: *ast.FieldList { + 259 . . . . . . . . . . . . . . . . . . . . . . Opening: - + 260 . . . . . . . . . . . . . . . . . . . . . . List: nil + 261 . . . . . . . . . . . . . . . . . . . . . . Closing: - + 262 . . . . . . . . . . . . . . . . . . . . . } + 263 . . . . . . . . . . . . . . . . . . . . . Incomplete: false + 264 . . . . . . . . . . . . . . . . . . . . } + 265 . . . . . . . . . . . . . . . . . . . . Comment: nil + 266 . . . . . . . . . . . . . . . . . . . } + 267 . . . . . . . . . . . . . . . . . . . Data: nil + 268 . . . . . . . . . . . . . . . . . . . Type: nil + 269 . . . . . . . . . . . . . . . . . . } + 270 . . . . . . . . . . . . . . . . . } + 271 . . . . . . . . . . . . . . . . . Tag: nil + 272 . . . . . . . . . . . . . . . . . Comment: nil + 273 . . . . . . . . . . . . . . . . } + 274 . . . . . . . . . . . . . . . } + 275 . . . . . . . . . . . . . . . Closing: - + 276 . . . . . . . . . . . . . . } + 277 . . . . . . . . . . . . . . Results: *ast.FieldList { + 278 . . . . . . . . . . . . . . . Opening: - + 279 . . . . . . . . . . . . . . . List: []*ast.Field (len = 1) { + 280 . . . . . . . . . . . . . . . . 0: *ast.Field { + 281 . . . . . . . . . . . . . . . . . Doc: nil + 282 . . . . . . . . . . . . . . . . . Names: nil + 283 . . . . . . . . . . . . . . . . . Type: *ast.Ident { + 284 . . . . . . . . . . . . . . . . . . NamePos: - + 285 . . . . . . . . . . . . . . . . . . Name: "error" + 286 . . . . . . . . . . . . . . . . . . Obj: nil + 287 . . . . . . . . . . . . . . . . . } + 288 . . . . . . . . . . . . . . . . . Tag: nil + 289 . . . . . . . . . . . . . . . . . Comment: nil + 290 . . . . . . . . . . . . . . . . } + 291 . . . . . . . . . . . . . . . } + 292 . . . . . . . . . . . . . . . Closing: - + 293 . . . . . . . . . . . . . . } + 294 . . . . . . . . . . . . . } + 295 . . . . . . . . . . . . } + 296 . . . . . . . . . . . . Tag: nil + 297 . . . . . . . . . . . . Comment: nil + 298 . . . . . . . . . . . } + 299 . . . . . . . . . . . 7: *ast.Field { + 300 . . . . . . . . . . . . Doc: nil + 301 . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 302 . . . . . . . . . . . . . 0: *ast.Ident { + 303 . . . . . . . . . . . . . . NamePos: - + 304 . . . . . . . . . . . . . . Name: "serviceMu" + 305 . . . . . . . . . . . . . . Obj: *ast.Object { + 306 . . . . . . . . . . . . . . . Kind: var + 307 . . . . . . . . . . . . . . . Name: "serviceMu" + 308 . . . . . . . . . . . . . . . Decl: *(obj @ 299) + 309 . . . . . . . . . . . . . . . Data: nil + 310 . . . . . . . . . . . . . . . Type: nil + 311 . . . . . . . . . . . . . . } + 312 . . . . . . . . . . . . . } + 313 . . . . . . . . . . . . } + 314 . . . . . . . . . . . . Type: *ast.SelectorExpr { + 315 . . . . . . . . . . . . . X: *ast.Ident { + 316 . . . . . . . . . . . . . . NamePos: - + 317 . . . . . . . . . . . . . . Name: "sync" + 318 . . . . . . . . . . . . . . Obj: nil + 319 . . . . . . . . . . . . . } + 320 . . . . . . . . . . . . . Sel: *ast.Ident { + 321 . . . . . . . . . . . . . . NamePos: - + 322 . . . . . . . . . . . . . . Name: "RWMutex" + 323 . . . . . . . . . . . . . . Obj: nil + 324 . . . . . . . . . . . . . } + 325 . . . . . . . . . . . . } + 326 . . . . . . . . . . . . Tag: nil + 327 . . . . . . . . . . . . Comment: nil + 328 . . . . . . . . . . . } + 329 . . . . . . . . . . . 8: *ast.Field { + 330 . . . . . . . . . . . . Doc: nil + 331 . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 332 . . . . . . . . . . . . . 0: *ast.Ident { + 333 . . . . . . . . . . . . . . NamePos: - + 334 . . . . . . . . . . . . . . Name: "services" + 335 . . . . . . . . . . . . . . Obj: *ast.Object { + 336 . . . . . . . . . . . . . . . Kind: var + 337 . . . . . . . . . . . . . . . Name: "services" + 338 . . . . . . . . . . . . . . . Decl: *(obj @ 329) + 339 . . . . . . . . . . . . . . . Data: nil + 340 . . . . . . . . . . . . . . . Type: nil + 341 . . . . . . . . . . . . . . } + 342 . . . . . . . . . . . . . } + 343 . . . . . . . . . . . . } + 344 . . . . . . . . . . . . Type: *ast.MapType { + 345 . . . . . . . . . . . . . Map: - + 346 . . . . . . . . . . . . . Key: *ast.Ident { + 347 . . . . . . . . . . . . . . NamePos: - + 348 . . . . . . . . . . . . . . Name: "string" + 349 . . . . . . . . . . . . . . Obj: nil + 350 . . . . . . . . . . . . . } + 351 . . . . . . . . . . . . . Value: *ast.Ident { + 352 . . . . . . . . . . . . . . NamePos: - + 353 . . . . . . . . . . . . . . Name: "any" + 354 . . . . . . . . . . . . . . Obj: nil + 355 . . . . . . . . . . . . . } + 356 . . . . . . . . . . . . } + 357 . . . . . . . . . . . . Tag: nil + 358 . . . . . . . . . . . . Comment: nil + 359 . . . . . . . . . . . } + 360 . . . . . . . . . . . 9: *ast.Field { + 361 . . . . . . . . . . . . Doc: nil + 362 . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 363 . . . . . . . . . . . . . 0: *ast.Ident { + 364 . . . . . . . . . . . . . . NamePos: - + 365 . . . . . . . . . . . . . . Name: "servicesLocked" + 366 . . . . . . . . . . . . . . Obj: *ast.Object { + 367 . . . . . . . . . . . . . . . Kind: var + 368 . . . . . . . . . . . . . . . Name: "servicesLocked" + 369 . . . . . . . . . . . . . . . Decl: *(obj @ 360) + 370 . . . . . . . . . . . . . . . Data: nil + 371 . . . . . . . . . . . . . . . Type: nil + 372 . . . . . . . . . . . . . . } + 373 . . . . . . . . . . . . . } + 374 . . . . . . . . . . . . } + 375 . . . . . . . . . . . . Type: *ast.Ident { + 376 . . . . . . . . . . . . . NamePos: - + 377 . . . . . . . . . . . . . Name: "bool" + 378 . . . . . . . . . . . . . Obj: nil + 379 . . . . . . . . . . . . } + 380 . . . . . . . . . . . . Tag: nil + 381 . . . . . . . . . . . . Comment: nil + 382 . . . . . . . . . . . } + 383 . . . . . . . . . . } + 384 . . . . . . . . . . Closing: - + 385 . . . . . . . . . } + 386 . . . . . . . . . Incomplete: false + 387 . . . . . . . . } + 388 . . . . . . . . Comment: nil + 389 . . . . . . . } + 390 . . . . . . . Data: nil + 391 . . . . . . . Type: nil + 392 . . . . . . } + 393 . . . . . } + 394 . . . . } + 395 . . . . Tag: nil + 396 . . . . Comment: nil + 397 . . . } + 398 . . } + 399 . . Closing: - + 400 . } + 401 . Results: *ast.FieldList { + 402 . . Opening: - + 403 . . List: []*ast.Field (len = 1) { + 404 . . . 0: *ast.Field { + 405 . . . . Doc: nil + 406 . . . . Names: nil + 407 . . . . Type: *ast.Ident { + 408 . . . . . NamePos: - + 409 . . . . . Name: "error" + 410 . . . . . Obj: nil + 411 . . . . } + 412 . . . . Tag: nil + 413 . . . . Comment: nil + 414 . . . } + 415 . . } + 416 . . Closing: - + 417 . } + 418 } + +``` + + + + + +### `type Runtime` +```go +type Runtime 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 2) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: []*ast.Ident (len = 1) { + 8 . . . . . 0: *ast.Ident { + 9 . . . . . . NamePos: - + 10 . . . . . . Name: "core" + 11 . . . . . . Obj: *ast.Object { + 12 . . . . . . . Kind: var + 13 . . . . . . . Name: "core" + 14 . . . . . . . Decl: *(obj @ 5) + 15 . . . . . . . Data: nil + 16 . . . . . . . Type: nil + 17 . . . . . . } + 18 . . . . . } + 19 . . . . } + 20 . . . . Type: *ast.StarExpr { + 21 . . . . . Star: - + 22 . . . . . X: *ast.Ident { + 23 . . . . . . NamePos: - + 24 . . . . . . Name: "Core" + 25 . . . . . . Obj: nil + 26 . . . . . } + 27 . . . . } + 28 . . . . Tag: nil + 29 . . . . Comment: nil + 30 . . . } + 31 . . . 1: *ast.Field { + 32 . . . . Doc: nil + 33 . . . . Names: []*ast.Ident (len = 1) { + 34 . . . . . 0: *ast.Ident { + 35 . . . . . . NamePos: - + 36 . . . . . . Name: "opts" + 37 . . . . . . Obj: *ast.Object { + 38 . . . . . . . Kind: var + 39 . . . . . . . Name: "opts" + 40 . . . . . . . Decl: *(obj @ 31) + 41 . . . . . . . Data: nil + 42 . . . . . . . Type: nil + 43 . . . . . . } + 44 . . . . . } + 45 . . . . } + 46 . . . . Type: *ast.Ident { + 47 . . . . . NamePos: - + 48 . . . . . Name: "T" + 49 . . . . . Obj: *ast.Object { + 50 . . . . . . Kind: type + 51 . . . . . . Name: "T" + 52 . . . . . . Decl: *ast.Field { + 53 . . . . . . . Doc: nil + 54 . . . . . . . Names: []*ast.Ident (len = 1) { + 55 . . . . . . . . 0: *ast.Ident { + 56 . . . . . . . . . NamePos: - + 57 . . . . . . . . . Name: "T" + 58 . . . . . . . . . Obj: *(obj @ 49) + 59 . . . . . . . . } + 60 . . . . . . . } + 61 . . . . . . . Type: *ast.Ident { + 62 . . . . . . . . NamePos: - + 63 . . . . . . . . Name: "any" + 64 . . . . . . . . Obj: nil + 65 . . . . . . . } + 66 . . . . . . . Tag: nil + 67 . . . . . . . Comment: nil + 68 . . . . . . } + 69 . . . . . . Data: nil + 70 . . . . . . Type: nil + 71 . . . . . } + 72 . . . . } + 73 . . . . Tag: nil + 74 . . . . Comment: nil + 75 . . . } + 76 . . } + 77 . . Closing: - + 78 . } + 79 . Incomplete: false + 80 } + +``` +Runtime is a helper struct embedded in services to provide access to the core application. + + + +#### Methods + +- `Config() 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "Config" + 3 . Obj: nil + 4 } +`: Config returns the registered Config service from the core application. + +- `Core() 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.Ident { + 3 . . NamePos: - + 4 . . Name: "Core" + 5 . . Obj: nil + 6 . } + 7 } +`: Core returns the central core instance. + + + +### `type WindowConfig` +```go +type WindowConfig 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 5) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: []*ast.Ident (len = 1) { + 8 . . . . . 0: *ast.Ident { + 9 . . . . . . NamePos: - + 10 . . . . . . Name: "Name" + 11 . . . . . . Obj: *ast.Object { + 12 . . . . . . . Kind: var + 13 . . . . . . . Name: "Name" + 14 . . . . . . . Decl: *(obj @ 5) + 15 . . . . . . . Data: nil + 16 . . . . . . . Type: nil + 17 . . . . . . } + 18 . . . . . } + 19 . . . . } + 20 . . . . Type: *ast.Ident { + 21 . . . . . NamePos: - + 22 . . . . . Name: "string" + 23 . . . . . Obj: nil + 24 . . . . } + 25 . . . . Tag: nil + 26 . . . . Comment: nil + 27 . . . } + 28 . . . 1: *ast.Field { + 29 . . . . Doc: nil + 30 . . . . Names: []*ast.Ident (len = 1) { + 31 . . . . . 0: *ast.Ident { + 32 . . . . . . NamePos: - + 33 . . . . . . Name: "Title" + 34 . . . . . . Obj: *ast.Object { + 35 . . . . . . . Kind: var + 36 . . . . . . . Name: "Title" + 37 . . . . . . . Decl: *(obj @ 28) + 38 . . . . . . . Data: nil + 39 . . . . . . . Type: nil + 40 . . . . . . } + 41 . . . . . } + 42 . . . . } + 43 . . . . Type: *ast.Ident { + 44 . . . . . NamePos: - + 45 . . . . . Name: "string" + 46 . . . . . Obj: nil + 47 . . . . } + 48 . . . . Tag: nil + 49 . . . . Comment: nil + 50 . . . } + 51 . . . 2: *ast.Field { + 52 . . . . Doc: nil + 53 . . . . Names: []*ast.Ident (len = 1) { + 54 . . . . . 0: *ast.Ident { + 55 . . . . . . NamePos: - + 56 . . . . . . Name: "URL" + 57 . . . . . . Obj: *ast.Object { + 58 . . . . . . . Kind: var + 59 . . . . . . . Name: "URL" + 60 . . . . . . . Decl: *(obj @ 51) + 61 . . . . . . . Data: nil + 62 . . . . . . . Type: nil + 63 . . . . . . } + 64 . . . . . } + 65 . . . . } + 66 . . . . Type: *ast.Ident { + 67 . . . . . NamePos: - + 68 . . . . . Name: "string" + 69 . . . . . Obj: nil + 70 . . . . } + 71 . . . . Tag: nil + 72 . . . . Comment: nil + 73 . . . } + 74 . . . 3: *ast.Field { + 75 . . . . Doc: nil + 76 . . . . Names: []*ast.Ident (len = 1) { + 77 . . . . . 0: *ast.Ident { + 78 . . . . . . NamePos: - + 79 . . . . . . Name: "Width" + 80 . . . . . . Obj: *ast.Object { + 81 . . . . . . . Kind: var + 82 . . . . . . . Name: "Width" + 83 . . . . . . . Decl: *(obj @ 74) + 84 . . . . . . . Data: nil + 85 . . . . . . . Type: nil + 86 . . . . . . } + 87 . . . . . } + 88 . . . . } + 89 . . . . Type: *ast.Ident { + 90 . . . . . NamePos: - + 91 . . . . . Name: "int" + 92 . . . . . Obj: nil + 93 . . . . } + 94 . . . . Tag: nil + 95 . . . . Comment: nil + 96 . . . } + 97 . . . 4: *ast.Field { + 98 . . . . Doc: nil + 99 . . . . Names: []*ast.Ident (len = 1) { + 100 . . . . . 0: *ast.Ident { + 101 . . . . . . NamePos: - + 102 . . . . . . Name: "Height" + 103 . . . . . . Obj: *ast.Object { + 104 . . . . . . . Kind: var + 105 . . . . . . . Name: "Height" + 106 . . . . . . . Decl: *(obj @ 97) + 107 . . . . . . . Data: nil + 108 . . . . . . . Type: nil + 109 . . . . . . } + 110 . . . . . } + 111 . . . . } + 112 . . . . Type: *ast.Ident { + 113 . . . . . NamePos: - + 114 . . . . . Name: "int" + 115 . . . . . Obj: nil + 116 . . . . } + 117 . . . . Tag: nil + 118 . . . . Comment: *ast.CommentGroup { + 119 . . . . . List: []*ast.Comment (len = 1) { + 120 . . . . . . 0: *ast.Comment { + 121 . . . . . . . Slash: - + 122 . . . . . . . Text: "// Add other common window options here as needed" + 123 . . . . . . } + 124 . . . . . } + 125 . . . . } + 126 . . . } + 127 . . } + 128 . . Closing: - + 129 . } + 130 . Incomplete: false + 131 } + +``` +WindowConfig represents the configuration for a window. + + + + + +### `type WindowOption` +```go +type WindowOption 0 *ast.InterfaceType { + 1 . Interface: - + 2 . Methods: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 1) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: []*ast.Ident (len = 1) { + 8 . . . . . 0: *ast.Ident { + 9 . . . . . . NamePos: - + 10 . . . . . . Name: "Apply" + 11 . . . . . . Obj: *ast.Object { + 12 . . . . . . . Kind: func + 13 . . . . . . . Name: "Apply" + 14 . . . . . . . Decl: *(obj @ 5) + 15 . . . . . . . Data: nil + 16 . . . . . . . Type: nil + 17 . . . . . . } + 18 . . . . . } + 19 . . . . } + 20 . . . . Type: *ast.FuncType { + 21 . . . . . Func: - + 22 . . . . . TypeParams: nil + 23 . . . . . Params: *ast.FieldList { + 24 . . . . . . Opening: - + 25 . . . . . . List: []*ast.Field (len = 1) { + 26 . . . . . . . 0: *ast.Field { + 27 . . . . . . . . Doc: nil + 28 . . . . . . . . Names: nil + 29 . . . . . . . . Type: *ast.StarExpr { + 30 . . . . . . . . . Star: - + 31 . . . . . . . . . X: *ast.Ident { + 32 . . . . . . . . . . NamePos: - + 33 . . . . . . . . . . Name: "WindowConfig" + 34 . . . . . . . . . . Obj: *ast.Object { + 35 . . . . . . . . . . . Kind: type + 36 . . . . . . . . . . . Name: "WindowConfig" + 37 . . . . . . . . . . . Decl: *ast.TypeSpec { + 38 . . . . . . . . . . . . Doc: nil + 39 . . . . . . . . . . . . Name: *ast.Ident { + 40 . . . . . . . . . . . . . NamePos: - + 41 . . . . . . . . . . . . . Name: "WindowConfig" + 42 . . . . . . . . . . . . . Obj: *(obj @ 34) + 43 . . . . . . . . . . . . } + 44 . . . . . . . . . . . . TypeParams: nil + 45 . . . . . . . . . . . . Assign: - + 46 . . . . . . . . . . . . Type: *ast.StructType { + 47 . . . . . . . . . . . . . Struct: - + 48 . . . . . . . . . . . . . Fields: *ast.FieldList { + 49 . . . . . . . . . . . . . . Opening: - + 50 . . . . . . . . . . . . . . List: []*ast.Field (len = 5) { + 51 . . . . . . . . . . . . . . . 0: *ast.Field { + 52 . . . . . . . . . . . . . . . . Doc: nil + 53 . . . . . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 54 . . . . . . . . . . . . . . . . . 0: *ast.Ident { + 55 . . . . . . . . . . . . . . . . . . NamePos: - + 56 . . . . . . . . . . . . . . . . . . Name: "Name" + 57 . . . . . . . . . . . . . . . . . . Obj: *ast.Object { + 58 . . . . . . . . . . . . . . . . . . . Kind: var + 59 . . . . . . . . . . . . . . . . . . . Name: "Name" + 60 . . . . . . . . . . . . . . . . . . . Decl: *(obj @ 51) + 61 . . . . . . . . . . . . . . . . . . . Data: nil + 62 . . . . . . . . . . . . . . . . . . . Type: nil + 63 . . . . . . . . . . . . . . . . . . } + 64 . . . . . . . . . . . . . . . . . } + 65 . . . . . . . . . . . . . . . . } + 66 . . . . . . . . . . . . . . . . Type: *ast.Ident { + 67 . . . . . . . . . . . . . . . . . NamePos: - + 68 . . . . . . . . . . . . . . . . . Name: "string" + 69 . . . . . . . . . . . . . . . . . Obj: nil + 70 . . . . . . . . . . . . . . . . } + 71 . . . . . . . . . . . . . . . . Tag: nil + 72 . . . . . . . . . . . . . . . . Comment: nil + 73 . . . . . . . . . . . . . . . } + 74 . . . . . . . . . . . . . . . 1: *ast.Field { + 75 . . . . . . . . . . . . . . . . Doc: nil + 76 . . . . . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 77 . . . . . . . . . . . . . . . . . 0: *ast.Ident { + 78 . . . . . . . . . . . . . . . . . . NamePos: - + 79 . . . . . . . . . . . . . . . . . . Name: "Title" + 80 . . . . . . . . . . . . . . . . . . Obj: *ast.Object { + 81 . . . . . . . . . . . . . . . . . . . Kind: var + 82 . . . . . . . . . . . . . . . . . . . Name: "Title" + 83 . . . . . . . . . . . . . . . . . . . Decl: *(obj @ 74) + 84 . . . . . . . . . . . . . . . . . . . Data: nil + 85 . . . . . . . . . . . . . . . . . . . Type: nil + 86 . . . . . . . . . . . . . . . . . . } + 87 . . . . . . . . . . . . . . . . . } + 88 . . . . . . . . . . . . . . . . } + 89 . . . . . . . . . . . . . . . . Type: *ast.Ident { + 90 . . . . . . . . . . . . . . . . . NamePos: - + 91 . . . . . . . . . . . . . . . . . Name: "string" + 92 . . . . . . . . . . . . . . . . . Obj: nil + 93 . . . . . . . . . . . . . . . . } + 94 . . . . . . . . . . . . . . . . Tag: nil + 95 . . . . . . . . . . . . . . . . Comment: nil + 96 . . . . . . . . . . . . . . . } + 97 . . . . . . . . . . . . . . . 2: *ast.Field { + 98 . . . . . . . . . . . . . . . . Doc: nil + 99 . . . . . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 100 . . . . . . . . . . . . . . . . . 0: *ast.Ident { + 101 . . . . . . . . . . . . . . . . . . NamePos: - + 102 . . . . . . . . . . . . . . . . . . Name: "URL" + 103 . . . . . . . . . . . . . . . . . . Obj: *ast.Object { + 104 . . . . . . . . . . . . . . . . . . . Kind: var + 105 . . . . . . . . . . . . . . . . . . . Name: "URL" + 106 . . . . . . . . . . . . . . . . . . . Decl: *(obj @ 97) + 107 . . . . . . . . . . . . . . . . . . . Data: nil + 108 . . . . . . . . . . . . . . . . . . . Type: nil + 109 . . . . . . . . . . . . . . . . . . } + 110 . . . . . . . . . . . . . . . . . } + 111 . . . . . . . . . . . . . . . . } + 112 . . . . . . . . . . . . . . . . Type: *ast.Ident { + 113 . . . . . . . . . . . . . . . . . NamePos: - + 114 . . . . . . . . . . . . . . . . . Name: "string" + 115 . . . . . . . . . . . . . . . . . Obj: nil + 116 . . . . . . . . . . . . . . . . } + 117 . . . . . . . . . . . . . . . . Tag: nil + 118 . . . . . . . . . . . . . . . . Comment: nil + 119 . . . . . . . . . . . . . . . } + 120 . . . . . . . . . . . . . . . 3: *ast.Field { + 121 . . . . . . . . . . . . . . . . Doc: nil + 122 . . . . . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 123 . . . . . . . . . . . . . . . . . 0: *ast.Ident { + 124 . . . . . . . . . . . . . . . . . . NamePos: - + 125 . . . . . . . . . . . . . . . . . . Name: "Width" + 126 . . . . . . . . . . . . . . . . . . Obj: *ast.Object { + 127 . . . . . . . . . . . . . . . . . . . Kind: var + 128 . . . . . . . . . . . . . . . . . . . Name: "Width" + 129 . . . . . . . . . . . . . . . . . . . Decl: *(obj @ 120) + 130 . . . . . . . . . . . . . . . . . . . Data: nil + 131 . . . . . . . . . . . . . . . . . . . Type: nil + 132 . . . . . . . . . . . . . . . . . . } + 133 . . . . . . . . . . . . . . . . . } + 134 . . . . . . . . . . . . . . . . } + 135 . . . . . . . . . . . . . . . . Type: *ast.Ident { + 136 . . . . . . . . . . . . . . . . . NamePos: - + 137 . . . . . . . . . . . . . . . . . Name: "int" + 138 . . . . . . . . . . . . . . . . . Obj: nil + 139 . . . . . . . . . . . . . . . . } + 140 . . . . . . . . . . . . . . . . Tag: nil + 141 . . . . . . . . . . . . . . . . Comment: nil + 142 . . . . . . . . . . . . . . . } + 143 . . . . . . . . . . . . . . . 4: *ast.Field { + 144 . . . . . . . . . . . . . . . . Doc: nil + 145 . . . . . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 146 . . . . . . . . . . . . . . . . . 0: *ast.Ident { + 147 . . . . . . . . . . . . . . . . . . NamePos: - + 148 . . . . . . . . . . . . . . . . . . Name: "Height" + 149 . . . . . . . . . . . . . . . . . . Obj: *ast.Object { + 150 . . . . . . . . . . . . . . . . . . . Kind: var + 151 . . . . . . . . . . . . . . . . . . . Name: "Height" + 152 . . . . . . . . . . . . . . . . . . . Decl: *(obj @ 143) + 153 . . . . . . . . . . . . . . . . . . . Data: nil + 154 . . . . . . . . . . . . . . . . . . . Type: nil + 155 . . . . . . . . . . . . . . . . . . } + 156 . . . . . . . . . . . . . . . . . } + 157 . . . . . . . . . . . . . . . . } + 158 . . . . . . . . . . . . . . . . Type: *ast.Ident { + 159 . . . . . . . . . . . . . . . . . NamePos: - + 160 . . . . . . . . . . . . . . . . . Name: "int" + 161 . . . . . . . . . . . . . . . . . Obj: nil + 162 . . . . . . . . . . . . . . . . } + 163 . . . . . . . . . . . . . . . . Tag: nil + 164 . . . . . . . . . . . . . . . . Comment: *ast.CommentGroup { + 165 . . . . . . . . . . . . . . . . . List: []*ast.Comment (len = 1) { + 166 . . . . . . . . . . . . . . . . . . 0: *ast.Comment { + 167 . . . . . . . . . . . . . . . . . . . Slash: - + 168 . . . . . . . . . . . . . . . . . . . Text: "// Add other common window options here as needed" + 169 . . . . . . . . . . . . . . . . . . } + 170 . . . . . . . . . . . . . . . . . } + 171 . . . . . . . . . . . . . . . . } + 172 . . . . . . . . . . . . . . . } + 173 . . . . . . . . . . . . . . } + 174 . . . . . . . . . . . . . . Closing: - + 175 . . . . . . . . . . . . . } + 176 . . . . . . . . . . . . . Incomplete: false + 177 . . . . . . . . . . . . } + 178 . . . . . . . . . . . . Comment: nil + 179 . . . . . . . . . . . } + 180 . . . . . . . . . . . Data: nil + 181 . . . . . . . . . . . Type: nil + 182 . . . . . . . . . . } + 183 . . . . . . . . . } + 184 . . . . . . . . } + 185 . . . . . . . . Tag: nil + 186 . . . . . . . . Comment: nil + 187 . . . . . . . } + 188 . . . . . . } + 189 . . . . . . Closing: - + 190 . . . . . } + 191 . . . . . Results: nil + 192 . . . . } + 193 . . . . Tag: nil + 194 . . . . Comment: nil + 195 . . . } + 196 . . } + 197 . . Closing: - + 198 . } + 199 . Incomplete: false + 200 } + +``` +WindowOption configures window creation. + + + + + +### `type Workspace` +```go +type Workspace 0 *ast.InterfaceType { + 1 . Interface: - + 2 . Methods: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 4) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: []*ast.Ident (len = 1) { + 8 . . . . . 0: *ast.Ident { + 9 . . . . . . NamePos: - + 10 . . . . . . Name: "CreateWorkspace" + 11 . . . . . . Obj: *ast.Object { + 12 . . . . . . . Kind: func + 13 . . . . . . . Name: "CreateWorkspace" + 14 . . . . . . . Decl: *(obj @ 5) + 15 . . . . . . . Data: nil + 16 . . . . . . . Type: nil + 17 . . . . . . } + 18 . . . . . } + 19 . . . . } + 20 . . . . Type: *ast.FuncType { + 21 . . . . . Func: - + 22 . . . . . TypeParams: nil + 23 . . . . . Params: *ast.FieldList { + 24 . . . . . . Opening: - + 25 . . . . . . List: []*ast.Field (len = 1) { + 26 . . . . . . . 0: *ast.Field { + 27 . . . . . . . . Doc: nil + 28 . . . . . . . . Names: []*ast.Ident (len = 2) { + 29 . . . . . . . . . 0: *ast.Ident { + 30 . . . . . . . . . . NamePos: - + 31 . . . . . . . . . . Name: "identifier" + 32 . . . . . . . . . . Obj: *ast.Object { + 33 . . . . . . . . . . . Kind: var + 34 . . . . . . . . . . . Name: "identifier" + 35 . . . . . . . . . . . Decl: *(obj @ 26) + 36 . . . . . . . . . . . Data: nil + 37 . . . . . . . . . . . Type: nil + 38 . . . . . . . . . . } + 39 . . . . . . . . . } + 40 . . . . . . . . . 1: *ast.Ident { + 41 . . . . . . . . . . NamePos: - + 42 . . . . . . . . . . Name: "password" + 43 . . . . . . . . . . Obj: *ast.Object { + 44 . . . . . . . . . . . Kind: var + 45 . . . . . . . . . . . Name: "password" + 46 . . . . . . . . . . . Decl: *(obj @ 26) + 47 . . . . . . . . . . . Data: nil + 48 . . . . . . . . . . . Type: nil + 49 . . . . . . . . . . } + 50 . . . . . . . . . } + 51 . . . . . . . . } + 52 . . . . . . . . Type: *ast.Ident { + 53 . . . . . . . . . NamePos: - + 54 . . . . . . . . . Name: "string" + 55 . . . . . . . . . Obj: nil + 56 . . . . . . . . } + 57 . . . . . . . . Tag: nil + 58 . . . . . . . . Comment: nil + 59 . . . . . . . } + 60 . . . . . . } + 61 . . . . . . Closing: - + 62 . . . . . } + 63 . . . . . Results: *ast.FieldList { + 64 . . . . . . Opening: - + 65 . . . . . . List: []*ast.Field (len = 2) { + 66 . . . . . . . 0: *ast.Field { + 67 . . . . . . . . Doc: nil + 68 . . . . . . . . Names: nil + 69 . . . . . . . . Type: *ast.Ident { + 70 . . . . . . . . . NamePos: - + 71 . . . . . . . . . Name: "string" + 72 . . . . . . . . . Obj: nil + 73 . . . . . . . . } + 74 . . . . . . . . Tag: nil + 75 . . . . . . . . Comment: nil + 76 . . . . . . . } + 77 . . . . . . . 1: *ast.Field { + 78 . . . . . . . . Doc: nil + 79 . . . . . . . . Names: nil + 80 . . . . . . . . Type: *ast.Ident { + 81 . . . . . . . . . NamePos: - + 82 . . . . . . . . . Name: "error" + 83 . . . . . . . . . Obj: nil + 84 . . . . . . . . } + 85 . . . . . . . . Tag: nil + 86 . . . . . . . . Comment: nil + 87 . . . . . . . } + 88 . . . . . . } + 89 . . . . . . Closing: - + 90 . . . . . } + 91 . . . . } + 92 . . . . Tag: nil + 93 . . . . Comment: nil + 94 . . . } + 95 . . . 1: *ast.Field { + 96 . . . . Doc: nil + 97 . . . . Names: []*ast.Ident (len = 1) { + 98 . . . . . 0: *ast.Ident { + 99 . . . . . . NamePos: - + 100 . . . . . . Name: "SwitchWorkspace" + 101 . . . . . . Obj: *ast.Object { + 102 . . . . . . . Kind: func + 103 . . . . . . . Name: "SwitchWorkspace" + 104 . . . . . . . Decl: *(obj @ 95) + 105 . . . . . . . Data: nil + 106 . . . . . . . Type: nil + 107 . . . . . . } + 108 . . . . . } + 109 . . . . } + 110 . . . . Type: *ast.FuncType { + 111 . . . . . Func: - + 112 . . . . . TypeParams: nil + 113 . . . . . Params: *ast.FieldList { + 114 . . . . . . Opening: - + 115 . . . . . . List: []*ast.Field (len = 1) { + 116 . . . . . . . 0: *ast.Field { + 117 . . . . . . . . Doc: nil + 118 . . . . . . . . Names: []*ast.Ident (len = 1) { + 119 . . . . . . . . . 0: *ast.Ident { + 120 . . . . . . . . . . NamePos: - + 121 . . . . . . . . . . Name: "name" + 122 . . . . . . . . . . Obj: *ast.Object { + 123 . . . . . . . . . . . Kind: var + 124 . . . . . . . . . . . Name: "name" + 125 . . . . . . . . . . . Decl: *(obj @ 116) + 126 . . . . . . . . . . . Data: nil + 127 . . . . . . . . . . . Type: nil + 128 . . . . . . . . . . } + 129 . . . . . . . . . } + 130 . . . . . . . . } + 131 . . . . . . . . Type: *ast.Ident { + 132 . . . . . . . . . NamePos: - + 133 . . . . . . . . . Name: "string" + 134 . . . . . . . . . Obj: nil + 135 . . . . . . . . } + 136 . . . . . . . . Tag: nil + 137 . . . . . . . . Comment: nil + 138 . . . . . . . } + 139 . . . . . . } + 140 . . . . . . Closing: - + 141 . . . . . } + 142 . . . . . Results: *ast.FieldList { + 143 . . . . . . Opening: - + 144 . . . . . . List: []*ast.Field (len = 1) { + 145 . . . . . . . 0: *ast.Field { + 146 . . . . . . . . Doc: nil + 147 . . . . . . . . Names: nil + 148 . . . . . . . . Type: *ast.Ident { + 149 . . . . . . . . . NamePos: - + 150 . . . . . . . . . Name: "error" + 151 . . . . . . . . . Obj: nil + 152 . . . . . . . . } + 153 . . . . . . . . Tag: nil + 154 . . . . . . . . Comment: nil + 155 . . . . . . . } + 156 . . . . . . } + 157 . . . . . . Closing: - + 158 . . . . . } + 159 . . . . } + 160 . . . . Tag: nil + 161 . . . . Comment: nil + 162 . . . } + 163 . . . 2: *ast.Field { + 164 . . . . Doc: nil + 165 . . . . Names: []*ast.Ident (len = 1) { + 166 . . . . . 0: *ast.Ident { + 167 . . . . . . NamePos: - + 168 . . . . . . Name: "WorkspaceFileGet" + 169 . . . . . . Obj: *ast.Object { + 170 . . . . . . . Kind: func + 171 . . . . . . . Name: "WorkspaceFileGet" + 172 . . . . . . . Decl: *(obj @ 163) + 173 . . . . . . . Data: nil + 174 . . . . . . . Type: nil + 175 . . . . . . } + 176 . . . . . } + 177 . . . . } + 178 . . . . Type: *ast.FuncType { + 179 . . . . . Func: - + 180 . . . . . TypeParams: nil + 181 . . . . . Params: *ast.FieldList { + 182 . . . . . . Opening: - + 183 . . . . . . List: []*ast.Field (len = 1) { + 184 . . . . . . . 0: *ast.Field { + 185 . . . . . . . . Doc: nil + 186 . . . . . . . . Names: []*ast.Ident (len = 1) { + 187 . . . . . . . . . 0: *ast.Ident { + 188 . . . . . . . . . . NamePos: - + 189 . . . . . . . . . . Name: "filename" + 190 . . . . . . . . . . Obj: *ast.Object { + 191 . . . . . . . . . . . Kind: var + 192 . . . . . . . . . . . Name: "filename" + 193 . . . . . . . . . . . Decl: *(obj @ 184) + 194 . . . . . . . . . . . Data: nil + 195 . . . . . . . . . . . Type: nil + 196 . . . . . . . . . . } + 197 . . . . . . . . . } + 198 . . . . . . . . } + 199 . . . . . . . . Type: *ast.Ident { + 200 . . . . . . . . . NamePos: - + 201 . . . . . . . . . Name: "string" + 202 . . . . . . . . . Obj: nil + 203 . . . . . . . . } + 204 . . . . . . . . Tag: nil + 205 . . . . . . . . Comment: nil + 206 . . . . . . . } + 207 . . . . . . } + 208 . . . . . . Closing: - + 209 . . . . . } + 210 . . . . . Results: *ast.FieldList { + 211 . . . . . . Opening: - + 212 . . . . . . List: []*ast.Field (len = 2) { + 213 . . . . . . . 0: *ast.Field { + 214 . . . . . . . . Doc: nil + 215 . . . . . . . . Names: nil + 216 . . . . . . . . Type: *ast.Ident { + 217 . . . . . . . . . NamePos: - + 218 . . . . . . . . . Name: "string" + 219 . . . . . . . . . Obj: nil + 220 . . . . . . . . } + 221 . . . . . . . . Tag: nil + 222 . . . . . . . . Comment: nil + 223 . . . . . . . } + 224 . . . . . . . 1: *ast.Field { + 225 . . . . . . . . Doc: nil + 226 . . . . . . . . Names: nil + 227 . . . . . . . . Type: *ast.Ident { + 228 . . . . . . . . . NamePos: - + 229 . . . . . . . . . Name: "error" + 230 . . . . . . . . . Obj: nil + 231 . . . . . . . . } + 232 . . . . . . . . Tag: nil + 233 . . . . . . . . Comment: nil + 234 . . . . . . . } + 235 . . . . . . } + 236 . . . . . . Closing: - + 237 . . . . . } + 238 . . . . } + 239 . . . . Tag: nil + 240 . . . . Comment: nil + 241 . . . } + 242 . . . 3: *ast.Field { + 243 . . . . Doc: nil + 244 . . . . Names: []*ast.Ident (len = 1) { + 245 . . . . . 0: *ast.Ident { + 246 . . . . . . NamePos: - + 247 . . . . . . Name: "WorkspaceFileSet" + 248 . . . . . . Obj: *ast.Object { + 249 . . . . . . . Kind: func + 250 . . . . . . . Name: "WorkspaceFileSet" + 251 . . . . . . . Decl: *(obj @ 242) + 252 . . . . . . . Data: nil + 253 . . . . . . . Type: nil + 254 . . . . . . } + 255 . . . . . } + 256 . . . . } + 257 . . . . Type: *ast.FuncType { + 258 . . . . . Func: - + 259 . . . . . TypeParams: nil + 260 . . . . . Params: *ast.FieldList { + 261 . . . . . . Opening: - + 262 . . . . . . List: []*ast.Field (len = 1) { + 263 . . . . . . . 0: *ast.Field { + 264 . . . . . . . . Doc: nil + 265 . . . . . . . . Names: []*ast.Ident (len = 2) { + 266 . . . . . . . . . 0: *ast.Ident { + 267 . . . . . . . . . . NamePos: - + 268 . . . . . . . . . . Name: "filename" + 269 . . . . . . . . . . Obj: *ast.Object { + 270 . . . . . . . . . . . Kind: var + 271 . . . . . . . . . . . Name: "filename" + 272 . . . . . . . . . . . Decl: *(obj @ 263) + 273 . . . . . . . . . . . Data: nil + 274 . . . . . . . . . . . Type: nil + 275 . . . . . . . . . . } + 276 . . . . . . . . . } + 277 . . . . . . . . . 1: *ast.Ident { + 278 . . . . . . . . . . NamePos: - + 279 . . . . . . . . . . Name: "content" + 280 . . . . . . . . . . Obj: *ast.Object { + 281 . . . . . . . . . . . Kind: var + 282 . . . . . . . . . . . Name: "content" + 283 . . . . . . . . . . . Decl: *(obj @ 263) + 284 . . . . . . . . . . . Data: nil + 285 . . . . . . . . . . . Type: nil + 286 . . . . . . . . . . } + 287 . . . . . . . . . } + 288 . . . . . . . . } + 289 . . . . . . . . Type: *ast.Ident { + 290 . . . . . . . . . NamePos: - + 291 . . . . . . . . . Name: "string" + 292 . . . . . . . . . Obj: nil + 293 . . . . . . . . } + 294 . . . . . . . . Tag: nil + 295 . . . . . . . . Comment: nil + 296 . . . . . . . } + 297 . . . . . . } + 298 . . . . . . Closing: - + 299 . . . . . } + 300 . . . . . Results: *ast.FieldList { + 301 . . . . . . Opening: - + 302 . . . . . . List: []*ast.Field (len = 1) { + 303 . . . . . . . 0: *ast.Field { + 304 . . . . . . . . Doc: nil + 305 . . . . . . . . Names: nil + 306 . . . . . . . . Type: *ast.Ident { + 307 . . . . . . . . . NamePos: - + 308 . . . . . . . . . Name: "error" + 309 . . . . . . . . . Obj: nil + 310 . . . . . . . . } + 311 . . . . . . . . Tag: nil + 312 . . . . . . . . Comment: nil + 313 . . . . . . . } + 314 . . . . . . } + 315 . . . . . . Closing: - + 316 . . . . . } + 317 . . . . } + 318 . . . . Tag: nil + 319 . . . . Comment: nil + 320 . . . } + 321 . . } + 322 . . Closing: - + 323 . } + 324 . Incomplete: false + 325 } + +``` +Workspace manages user workspaces. + + + + + + + +## Functions + +- `App() 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "application" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "App" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +`: App returns the global application instance. + +- `MustServiceFor(c 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.Ident { + 3 . . NamePos: - + 4 . . Name: "Core" + 5 . . Obj: nil + 6 . } + 7 } +, name 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "T" + 3 . Obj: *ast.Object { + 4 . . Kind: type + 5 . . Name: "T" + 6 . . Decl: *ast.Field { + 7 . . . Doc: nil + 8 . . . Names: []*ast.Ident (len = 1) { + 9 . . . . 0: *ast.Ident { + 10 . . . . . NamePos: - + 11 . . . . . Name: "T" + 12 . . . . . Obj: *(obj @ 3) + 13 . . . . } + 14 . . . } + 15 . . . Type: *ast.Ident { + 16 . . . . NamePos: - + 17 . . . . Name: "any" + 18 . . . . Obj: nil + 19 . . . } + 20 . . . Tag: nil + 21 . . . Comment: nil + 22 . . } + 23 . . Data: nil + 24 . . Type: nil + 25 . } + 26 } +`: MustServiceFor retrieves a registered service by name and asserts its type to the given interface T. It panics if the service is not found or cannot be cast to T. + +- `ServiceFor(c 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.Ident { + 3 . . NamePos: - + 4 . . Name: "Core" + 5 . . Obj: nil + 6 . } + 7 } +, name 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "T" + 3 . Obj: *ast.Object { + 4 . . Kind: type + 5 . . Name: "T" + 6 . . Decl: *ast.Field { + 7 . . . Doc: nil + 8 . . . Names: []*ast.Ident (len = 1) { + 9 . . . . 0: *ast.Ident { + 10 . . . . . NamePos: - + 11 . . . . . Name: "T" + 12 . . . . . Obj: *(obj @ 3) + 13 . . . . } + 14 . . . } + 15 . . . Type: *ast.Ident { + 16 . . . . NamePos: - + 17 . . . . Name: "any" + 18 . . . . Obj: nil + 19 . . . } + 20 . . . Tag: nil + 21 . . . Comment: nil + 22 . . } + 23 . . Data: nil + 24 . . Type: nil + 25 . } + 26 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: ServiceFor retrieves a registered service by name and asserts its type to the given interface T. diff --git a/docs/services/crypt.md b/docs/services/crypt.md new file mode 100644 index 0000000..b664f8e --- /dev/null +++ b/docs/services/crypt.md @@ -0,0 +1,335 @@ +--- +title: internal +--- +# Service: `internal` + + + + + + +## Types + +### `type HashType` +```go +type HashType 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } + +``` +HashType defines the supported hashing algorithms. + + + + + +### `type Options` +```go +type Options 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: nil + 5 . . Closing: - + 6 . } + 7 . Incomplete: false + 8 } + +``` +Options holds configuration for the crypt service. + + + + + +### `type Service` +```go +type Service 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 1) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: nil + 8 . . . . Type: *ast.StarExpr { + 9 . . . . . Star: - + 10 . . . . . X: *ast.IndexExpr { + 11 . . . . . . X: *ast.SelectorExpr { + 12 . . . . . . . X: *ast.Ident { + 13 . . . . . . . . NamePos: - + 14 . . . . . . . . Name: "core" + 15 . . . . . . . . Obj: nil + 16 . . . . . . . } + 17 . . . . . . . Sel: *ast.Ident { + 18 . . . . . . . . NamePos: - + 19 . . . . . . . . Name: "Runtime" + 20 . . . . . . . . Obj: nil + 21 . . . . . . . } + 22 . . . . . . } + 23 . . . . . . Lbrack: - + 24 . . . . . . Index: *ast.Ident { + 25 . . . . . . . NamePos: - + 26 . . . . . . . Name: "Options" + 27 . . . . . . . Obj: *ast.Object { + 28 . . . . . . . . Kind: type + 29 . . . . . . . . Name: "Options" + 30 . . . . . . . . Decl: *ast.TypeSpec { + 31 . . . . . . . . . Doc: nil + 32 . . . . . . . . . Name: *ast.Ident { + 33 . . . . . . . . . . NamePos: - + 34 . . . . . . . . . . Name: "Options" + 35 . . . . . . . . . . Obj: *(obj @ 27) + 36 . . . . . . . . . } + 37 . . . . . . . . . TypeParams: nil + 38 . . . . . . . . . Assign: - + 39 . . . . . . . . . Type: *ast.StructType { + 40 . . . . . . . . . . Struct: - + 41 . . . . . . . . . . Fields: *ast.FieldList { + 42 . . . . . . . . . . . Opening: - + 43 . . . . . . . . . . . List: nil + 44 . . . . . . . . . . . Closing: - + 45 . . . . . . . . . . } + 46 . . . . . . . . . . Incomplete: false + 47 . . . . . . . . . } + 48 . . . . . . . . . Comment: nil + 49 . . . . . . . . } + 50 . . . . . . . . Data: nil + 51 . . . . . . . . Type: nil + 52 . . . . . . . } + 53 . . . . . . } + 54 . . . . . . Rbrack: - + 55 . . . . . } + 56 . . . . } + 57 . . . . Tag: nil + 58 . . . . Comment: nil + 59 . . . } + 60 . . } + 61 . . Closing: - + 62 . } + 63 . Incomplete: false + 64 } + +``` +Service provides cryptographic functions to the application. + + + +#### Methods + +- `DecryptPGP(recipientPath, message, passphrase 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, signerPath 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.Ident { + 3 . . NamePos: - + 4 . . Name: "string" + 5 . . Obj: nil + 6 . } + 7 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: DecryptPGP decrypts a PGP message, optionally verifying the signature. + +- `EncryptPGP(writer 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "io" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "Writer" + 9 . . Obj: nil + 10 . } + 11 } +, recipientPath, data 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, signerPath, signerPassphrase 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.Ident { + 3 . . NamePos: - + 4 . . Name: "string" + 5 . . Obj: nil + 6 . } + 7 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: EncryptPGP encrypts data for a recipient, optionally signing it. + +- `Fletcher16(payload 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "uint16" + 3 . Obj: nil + 4 } +`: Fletcher16 computes the Fletcher-16 checksum. + +- `Fletcher32(payload 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "uint32" + 3 . Obj: nil + 4 } +`: Fletcher32 computes the Fletcher-32 checksum. + +- `Fletcher64(payload 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "uint64" + 3 . Obj: nil + 4 } +`: Fletcher64 computes the Fletcher-64 checksum. + +- `Hash(lib 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "HashType" + 3 . Obj: *ast.Object { + 4 . . Kind: type + 5 . . Name: "HashType" + 6 . . Decl: *ast.TypeSpec { + 7 . . . Doc: nil + 8 . . . Name: *ast.Ident { + 9 . . . . NamePos: - + 10 . . . . Name: "HashType" + 11 . . . . Obj: *(obj @ 3) + 12 . . . } + 13 . . . TypeParams: nil + 14 . . . Assign: - + 15 . . . Type: *ast.Ident { + 16 . . . . NamePos: - + 17 . . . . Name: "string" + 18 . . . . Obj: nil + 19 . . . } + 20 . . . Comment: nil + 21 . . } + 22 . . Data: nil + 23 . . Type: nil + 24 . } + 25 } +, payload 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +`: Hash computes a hash of the payload using the specified algorithm. + +- `Luhn(payload 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "bool" + 3 . Obj: nil + 4 } +`: Luhn validates a number using the Luhn algorithm. + + + + + +## Functions + +- `Register(c 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "core" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "Core" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "any" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: Register is the constructor for dynamic dependency injection (used with core.WithService). It creates a Service instance and initializes its core.Runtime field. + +- `TestHash(t 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "testing" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "T" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +) `: + +- `TestLuhn(t 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "testing" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "T" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +) `: diff --git a/docs/services/display.md b/docs/services/display.md new file mode 100644 index 0000000..5375624 --- /dev/null +++ b/docs/services/display.md @@ -0,0 +1,635 @@ +--- +title: display +--- +# Service: `display` + + + + + + +## Types + +### `type ActionOpenWindow` +```go +type ActionOpenWindow 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 1) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: nil + 8 . . . . Type: *ast.SelectorExpr { + 9 . . . . . X: *ast.Ident { + 10 . . . . . . NamePos: - + 11 . . . . . . Name: "application" + 12 . . . . . . Obj: nil + 13 . . . . . } + 14 . . . . . Sel: *ast.Ident { + 15 . . . . . . NamePos: - + 16 . . . . . . Name: "WebviewWindowOptions" + 17 . . . . . . Obj: nil + 18 . . . . . } + 19 . . . . } + 20 . . . . Tag: nil + 21 . . . . Comment: nil + 22 . . . } + 23 . . } + 24 . . Closing: - + 25 . } + 26 . Incomplete: false + 27 } + +``` +ActionOpenWindow is an IPC message used to request a new window. + + + + + +### `type Options` +```go +type Options 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: nil + 5 . . Closing: - + 6 . } + 7 . Incomplete: false + 8 } + +``` +Options holds configuration for the display service. + + + + + +### `type Service` +```go +type Service 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 2) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: nil + 8 . . . . Type: *ast.StarExpr { + 9 . . . . . Star: - + 10 . . . . . X: *ast.IndexExpr { + 11 . . . . . . X: *ast.SelectorExpr { + 12 . . . . . . . X: *ast.Ident { + 13 . . . . . . . . NamePos: - + 14 . . . . . . . . Name: "core" + 15 . . . . . . . . Obj: nil + 16 . . . . . . . } + 17 . . . . . . . Sel: *ast.Ident { + 18 . . . . . . . . NamePos: - + 19 . . . . . . . . Name: "Runtime" + 20 . . . . . . . . Obj: nil + 21 . . . . . . . } + 22 . . . . . . } + 23 . . . . . . Lbrack: - + 24 . . . . . . Index: *ast.Ident { + 25 . . . . . . . NamePos: - + 26 . . . . . . . Name: "Options" + 27 . . . . . . . Obj: *ast.Object { + 28 . . . . . . . . Kind: type + 29 . . . . . . . . Name: "Options" + 30 . . . . . . . . Decl: *ast.TypeSpec { + 31 . . . . . . . . . Doc: nil + 32 . . . . . . . . . Name: *ast.Ident { + 33 . . . . . . . . . . NamePos: - + 34 . . . . . . . . . . Name: "Options" + 35 . . . . . . . . . . Obj: *(obj @ 27) + 36 . . . . . . . . . } + 37 . . . . . . . . . TypeParams: nil + 38 . . . . . . . . . Assign: - + 39 . . . . . . . . . Type: *ast.StructType { + 40 . . . . . . . . . . Struct: - + 41 . . . . . . . . . . Fields: *ast.FieldList { + 42 . . . . . . . . . . . Opening: - + 43 . . . . . . . . . . . List: nil + 44 . . . . . . . . . . . Closing: - + 45 . . . . . . . . . . } + 46 . . . . . . . . . . Incomplete: false + 47 . . . . . . . . . } + 48 . . . . . . . . . Comment: nil + 49 . . . . . . . . } + 50 . . . . . . . . Data: nil + 51 . . . . . . . . Type: nil + 52 . . . . . . . } + 53 . . . . . . } + 54 . . . . . . Rbrack: - + 55 . . . . . } + 56 . . . . } + 57 . . . . Tag: nil + 58 . . . . Comment: nil + 59 . . . } + 60 . . . 1: *ast.Field { + 61 . . . . Doc: nil + 62 . . . . Names: []*ast.Ident (len = 1) { + 63 . . . . . 0: *ast.Ident { + 64 . . . . . . NamePos: - + 65 . . . . . . Name: "config" + 66 . . . . . . Obj: *ast.Object { + 67 . . . . . . . Kind: var + 68 . . . . . . . Name: "config" + 69 . . . . . . . Decl: *(obj @ 60) + 70 . . . . . . . Data: nil + 71 . . . . . . . Type: nil + 72 . . . . . . } + 73 . . . . . } + 74 . . . . } + 75 . . . . Type: *ast.SelectorExpr { + 76 . . . . . X: *ast.Ident { + 77 . . . . . . NamePos: - + 78 . . . . . . Name: "core" + 79 . . . . . . Obj: nil + 80 . . . . . } + 81 . . . . . Sel: *ast.Ident { + 82 . . . . . . NamePos: - + 83 . . . . . . Name: "Config" + 84 . . . . . . Obj: nil + 85 . . . . . } + 86 . . . . } + 87 . . . . Tag: nil + 88 . . . . Comment: nil + 89 . . . } + 90 . . } + 91 . . Closing: - + 92 . } + 93 . Incomplete: false + 94 } + +``` +Service manages windowing, dialogs, and other visual elements. + + + +#### Methods + +- `HandleIPCEvents(c 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "core" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "Core" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +, msg 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "core" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "Message" + 9 . . Obj: nil + 10 . } + 11 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: HandleIPCEvents processes IPC messages and performs actions such as opening windows or initializing services based on message types. + +- `NewWithOptions(opts 0 *ast.Ellipsis { + 1 . Ellipsis: - + 2 . Elt: *ast.Ident { + 3 . . NamePos: - + 4 . . Name: "WindowOption" + 5 . . Obj: *ast.Object { + 6 . . . Kind: type + 7 . . . Name: "WindowOption" + 8 . . . Decl: *ast.TypeSpec { + 9 . . . . Doc: nil + 10 . . . . Name: *ast.Ident { + 11 . . . . . NamePos: - + 12 . . . . . Name: "WindowOption" + 13 . . . . . Obj: *(obj @ 5) + 14 . . . . } + 15 . . . . TypeParams: nil + 16 . . . . Assign: - + 17 . . . . Type: *ast.FuncType { + 18 . . . . . Func: - + 19 . . . . . TypeParams: nil + 20 . . . . . Params: *ast.FieldList { + 21 . . . . . . Opening: - + 22 . . . . . . List: []*ast.Field (len = 1) { + 23 . . . . . . . 0: *ast.Field { + 24 . . . . . . . . Doc: nil + 25 . . . . . . . . Names: nil + 26 . . . . . . . . Type: *ast.StarExpr { + 27 . . . . . . . . . Star: - + 28 . . . . . . . . . X: *ast.SelectorExpr { + 29 . . . . . . . . . . X: *ast.Ident { + 30 . . . . . . . . . . . NamePos: - + 31 . . . . . . . . . . . Name: "application" + 32 . . . . . . . . . . . Obj: nil + 33 . . . . . . . . . . } + 34 . . . . . . . . . . Sel: *ast.Ident { + 35 . . . . . . . . . . . NamePos: - + 36 . . . . . . . . . . . Name: "WebviewWindowOptions" + 37 . . . . . . . . . . . Obj: nil + 38 . . . . . . . . . . } + 39 . . . . . . . . . } + 40 . . . . . . . . } + 41 . . . . . . . . Tag: nil + 42 . . . . . . . . Comment: nil + 43 . . . . . . . } + 44 . . . . . . } + 45 . . . . . . Closing: - + 46 . . . . . } + 47 . . . . . Results: *ast.FieldList { + 48 . . . . . . Opening: - + 49 . . . . . . List: []*ast.Field (len = 1) { + 50 . . . . . . . 0: *ast.Field { + 51 . . . . . . . . Doc: nil + 52 . . . . . . . . Names: nil + 53 . . . . . . . . Type: *ast.Ident { + 54 . . . . . . . . . NamePos: - + 55 . . . . . . . . . Name: "error" + 56 . . . . . . . . . Obj: nil + 57 . . . . . . . . } + 58 . . . . . . . . Tag: nil + 59 . . . . . . . . Comment: nil + 60 . . . . . . . } + 61 . . . . . . } + 62 . . . . . . Closing: - + 63 . . . . . } + 64 . . . . } + 65 . . . . Comment: nil + 66 . . . } + 67 . . . Data: nil + 68 . . . Type: nil + 69 . . } + 70 . } + 71 } +) 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "application" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "WebviewWindow" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: NewWithOptions creates a new window by applying a series of options. + +- `NewWithStruct(options 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.Ident { + 3 . . NamePos: - + 4 . . Name: "Window" + 5 . . Obj: *ast.Object { + 6 . . . Kind: type + 7 . . . Name: "Window" + 8 . . . Decl: *ast.TypeSpec { + 9 . . . . Doc: nil + 10 . . . . Name: *ast.Ident { + 11 . . . . . NamePos: - + 12 . . . . . Name: "Window" + 13 . . . . . Obj: *(obj @ 5) + 14 . . . . } + 15 . . . . TypeParams: nil + 16 . . . . Assign: - + 17 . . . . Type: *ast.SelectorExpr { + 18 . . . . . X: *ast.Ident { + 19 . . . . . . NamePos: - + 20 . . . . . . Name: "application" + 21 . . . . . . Obj: nil + 22 . . . . . } + 23 . . . . . Sel: *ast.Ident { + 24 . . . . . . NamePos: - + 25 . . . . . . Name: "WebviewWindowOptions" + 26 . . . . . . Obj: nil + 27 . . . . . } + 28 . . . . } + 29 . . . . Comment: nil + 30 . . . } + 31 . . . Data: nil + 32 . . . Type: nil + 33 . . } + 34 . } + 35 } +) 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "application" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "WebviewWindow" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: NewWithStruct creates a new window using the provided options and returns its handle. + +- `NewWithURL(url 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "application" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "WebviewWindow" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: NewWithURL creates a new default window pointing to the specified URL. + +- `OpenWindow(opts 0 *ast.Ellipsis { + 1 . Ellipsis: - + 2 . Elt: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "core" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "WindowOption" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: OpenWindow creates a new window with the default options. + +- `SelectDirectory() 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: SelectDirectory opens a directory selection dialog and returns the selected path. + +- `ServiceName() 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +`: + +- `ServiceStartup( 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "context" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "Context" + 9 . . Obj: nil + 10 . } + 11 } +, 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "application" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "ServiceOptions" + 9 . . Obj: nil + 10 . } + 11 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: ServiceStartup initializes the display service and sets up the main application window and system tray. + +- `ShowEnvironmentDialog() `: ShowEnvironmentDialog displays a dialog containing detailed information about the application's runtime environment. + +- `Window() 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.Ident { + 3 . . NamePos: - + 4 . . Name: "Window" + 5 . . Obj: *ast.Object { + 6 . . . Kind: type + 7 . . . Name: "Window" + 8 . . . Decl: *ast.TypeSpec { + 9 . . . . Doc: nil + 10 . . . . Name: *ast.Ident { + 11 . . . . . NamePos: - + 12 . . . . . Name: "Window" + 13 . . . . . Obj: *(obj @ 5) + 14 . . . . } + 15 . . . . TypeParams: nil + 16 . . . . Assign: - + 17 . . . . Type: *ast.SelectorExpr { + 18 . . . . . X: *ast.Ident { + 19 . . . . . . NamePos: - + 20 . . . . . . Name: "application" + 21 . . . . . . Obj: nil + 22 . . . . . } + 23 . . . . . Sel: *ast.Ident { + 24 . . . . . . NamePos: - + 25 . . . . . . Name: "WebviewWindowOptions" + 26 . . . . . . Obj: nil + 27 . . . . . } + 28 . . . . } + 29 . . . . Comment: nil + 30 . . . } + 31 . . . Data: nil + 32 . . . Type: nil + 33 . . } + 34 . } + 35 } +`: + +- `buildMenu() `: buildMenu creates and sets the main application menu. + +- `handleOpenWindowAction(msg 0 *ast.MapType { + 1 . Map: - + 2 . Key: *ast.Ident { + 3 . . NamePos: - + 4 . . Name: "string" + 5 . . Obj: nil + 6 . } + 7 . Value: *ast.Ident { + 8 . . NamePos: - + 9 . . Name: "any" + 10 . . Obj: nil + 11 . } + 12 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: handleOpenWindowAction processes a message to configure and create a new window using specified name and options. + +- `monitorScreenChanges() `: monitorScreenChanges listens for theme change events and logs when screen configuration changes occur. + +- `systemTray() `: setupTray configures and creates the system tray icon and menu. + + + +### `type Window` +```go +type Window 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "application" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "WebviewWindowOptions" + 9 . . Obj: nil + 10 . } + 11 } + +``` + + + + + +### `type WindowOption` +```go +type WindowOption 0 *ast.FuncType { + 1 . Func: - + 2 . TypeParams: nil + 3 . Params: *ast.FieldList { + 4 . . Opening: - + 5 . . List: []*ast.Field (len = 1) { + 6 . . . 0: *ast.Field { + 7 . . . . Doc: nil + 8 . . . . Names: nil + 9 . . . . Type: *ast.StarExpr { + 10 . . . . . Star: - + 11 . . . . . X: *ast.SelectorExpr { + 12 . . . . . . X: *ast.Ident { + 13 . . . . . . . NamePos: - + 14 . . . . . . . Name: "application" + 15 . . . . . . . Obj: nil + 16 . . . . . . } + 17 . . . . . . Sel: *ast.Ident { + 18 . . . . . . . NamePos: - + 19 . . . . . . . Name: "WebviewWindowOptions" + 20 . . . . . . . Obj: nil + 21 . . . . . . } + 22 . . . . . } + 23 . . . . } + 24 . . . . Tag: nil + 25 . . . . Comment: nil + 26 . . . } + 27 . . } + 28 . . Closing: - + 29 . } + 30 . Results: *ast.FieldList { + 31 . . Opening: - + 32 . . List: []*ast.Field (len = 1) { + 33 . . . 0: *ast.Field { + 34 . . . . Doc: nil + 35 . . . . Names: nil + 36 . . . . Type: *ast.Ident { + 37 . . . . . NamePos: - + 38 . . . . . Name: "error" + 39 . . . . . Obj: nil + 40 . . . . } + 41 . . . . Tag: nil + 42 . . . . Comment: nil + 43 . . . } + 44 . . } + 45 . . Closing: - + 46 . } + 47 } + +``` + + + + + + + +## Functions + +- `Register(c 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "core" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "Core" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "any" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: Register is the constructor for dynamic dependency injection (used with core.WithService). It creates a Service instance and initializes its core.Runtime field. diff --git a/docs/services/e.md b/docs/services/e.md new file mode 100644 index 0000000..ef7542d --- /dev/null +++ b/docs/services/e.md @@ -0,0 +1,173 @@ +--- +title: e +--- +# Service: `e` + +Package e provides a standardized error handling mechanism for the Core library. +It allows for wrapping errors with contextual information, making it easier to +trace the origin of an error and provide meaningful feedback. + +The design of this package is influenced by the need for a simple, yet powerful +way to handle errors that can occur in different layers of the application, +from low-level file operations to high-level service interactions. + +The key features of this package are: + - Error wrapping: The Op and an optional Msg field provide context about + where and why an error occurred. + - Stack traces: By wrapping errors, we can build a logical stack trace + that is more informative than a raw stack trace. + - Consistent error handling: Encourages a uniform approach to error + handling across the entire codebase. + + + + + +## Types + +### `type Error` +```go +type Error 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 3) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: *ast.CommentGroup { + 7 . . . . . List: []*ast.Comment (len = 1) { + 8 . . . . . . 0: *ast.Comment { + 9 . . . . . . . Slash: - + 10 . . . . . . . Text: "// Op is the operation being performed, e.g., \"config.Load\"." + 11 . . . . . . } + 12 . . . . . } + 13 . . . . } + 14 . . . . Names: []*ast.Ident (len = 1) { + 15 . . . . . 0: *ast.Ident { + 16 . . . . . . NamePos: - + 17 . . . . . . Name: "Op" + 18 . . . . . . Obj: *ast.Object { + 19 . . . . . . . Kind: var + 20 . . . . . . . Name: "Op" + 21 . . . . . . . Decl: *(obj @ 5) + 22 . . . . . . . Data: nil + 23 . . . . . . . Type: nil + 24 . . . . . . } + 25 . . . . . } + 26 . . . . } + 27 . . . . Type: *ast.Ident { + 28 . . . . . NamePos: - + 29 . . . . . Name: "string" + 30 . . . . . Obj: nil + 31 . . . . } + 32 . . . . Tag: nil + 33 . . . . Comment: nil + 34 . . . } + 35 . . . 1: *ast.Field { + 36 . . . . Doc: *ast.CommentGroup { + 37 . . . . . List: []*ast.Comment (len = 1) { + 38 . . . . . . 0: *ast.Comment { + 39 . . . . . . . Slash: - + 40 . . . . . . . Text: "// Msg is a human-readable message explaining the error." + 41 . . . . . . } + 42 . . . . . } + 43 . . . . } + 44 . . . . Names: []*ast.Ident (len = 1) { + 45 . . . . . 0: *ast.Ident { + 46 . . . . . . NamePos: - + 47 . . . . . . Name: "Msg" + 48 . . . . . . Obj: *ast.Object { + 49 . . . . . . . Kind: var + 50 . . . . . . . Name: "Msg" + 51 . . . . . . . Decl: *(obj @ 35) + 52 . . . . . . . Data: nil + 53 . . . . . . . Type: nil + 54 . . . . . . } + 55 . . . . . } + 56 . . . . } + 57 . . . . Type: *ast.Ident { + 58 . . . . . NamePos: - + 59 . . . . . Name: "string" + 60 . . . . . Obj: nil + 61 . . . . } + 62 . . . . Tag: nil + 63 . . . . Comment: nil + 64 . . . } + 65 . . . 2: *ast.Field { + 66 . . . . Doc: *ast.CommentGroup { + 67 . . . . . List: []*ast.Comment (len = 1) { + 68 . . . . . . 0: *ast.Comment { + 69 . . . . . . . Slash: - + 70 . . . . . . . Text: "// Err is the underlying error that was wrapped." + 71 . . . . . . } + 72 . . . . . } + 73 . . . . } + 74 . . . . Names: []*ast.Ident (len = 1) { + 75 . . . . . 0: *ast.Ident { + 76 . . . . . . NamePos: - + 77 . . . . . . Name: "Err" + 78 . . . . . . Obj: *ast.Object { + 79 . . . . . . . Kind: var + 80 . . . . . . . Name: "Err" + 81 . . . . . . . Decl: *(obj @ 65) + 82 . . . . . . . Data: nil + 83 . . . . . . . Type: nil + 84 . . . . . . } + 85 . . . . . } + 86 . . . . } + 87 . . . . Type: *ast.Ident { + 88 . . . . . NamePos: - + 89 . . . . . Name: "error" + 90 . . . . . Obj: nil + 91 . . . . } + 92 . . . . Tag: nil + 93 . . . . Comment: nil + 94 . . . } + 95 . . } + 96 . . Closing: - + 97 . } + 98 . Incomplete: false + 99 } + +``` +Error represents a standardized error with operational context. + + + +#### Methods + +- `Error() 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +`: Error returns the string representation of the error. + +- `Unwrap() 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: Unwrap provides compatibility for Go's errors.Is and errors.As functions. + + + + + +## Functions + +- `E(op, msg 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, err 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: E is a helper function to create a new Error. This is the primary way to create errors that will be consumed by the system. For example: return e.E("config.Load", "failed to load config file", err) The 'op' parameter should be in the format of 'package.function' or 'service.method'. The 'msg' parameter should be a human-readable message that can be displayed to the user. The 'err' parameter is the underlying error that is being wrapped. diff --git a/docs/services/help.md b/docs/services/help.md new file mode 100644 index 0000000..eefb4ca --- /dev/null +++ b/docs/services/help.md @@ -0,0 +1,312 @@ +--- +title: help +--- +# Service: `help` + + + + + + +## Types + +### `type Options` +```go +type Options 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: nil + 5 . . Closing: - + 6 . } + 7 . Incomplete: false + 8 } + +``` +Options holds configuration for the help service. + + + + + +### `type Service` +```go +type Service 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 4) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: nil + 8 . . . . Type: *ast.StarExpr { + 9 . . . . . Star: - + 10 . . . . . X: *ast.IndexExpr { + 11 . . . . . . X: *ast.SelectorExpr { + 12 . . . . . . . X: *ast.Ident { + 13 . . . . . . . . NamePos: - + 14 . . . . . . . . Name: "core" + 15 . . . . . . . . Obj: nil + 16 . . . . . . . } + 17 . . . . . . . Sel: *ast.Ident { + 18 . . . . . . . . NamePos: - + 19 . . . . . . . . Name: "Runtime" + 20 . . . . . . . . Obj: nil + 21 . . . . . . . } + 22 . . . . . . } + 23 . . . . . . Lbrack: - + 24 . . . . . . Index: *ast.Ident { + 25 . . . . . . . NamePos: - + 26 . . . . . . . Name: "Options" + 27 . . . . . . . Obj: *ast.Object { + 28 . . . . . . . . Kind: type + 29 . . . . . . . . Name: "Options" + 30 . . . . . . . . Decl: *ast.TypeSpec { + 31 . . . . . . . . . Doc: nil + 32 . . . . . . . . . Name: *ast.Ident { + 33 . . . . . . . . . . NamePos: - + 34 . . . . . . . . . . Name: "Options" + 35 . . . . . . . . . . Obj: *(obj @ 27) + 36 . . . . . . . . . } + 37 . . . . . . . . . TypeParams: nil + 38 . . . . . . . . . Assign: - + 39 . . . . . . . . . Type: *ast.StructType { + 40 . . . . . . . . . . Struct: - + 41 . . . . . . . . . . Fields: *ast.FieldList { + 42 . . . . . . . . . . . Opening: - + 43 . . . . . . . . . . . List: nil + 44 . . . . . . . . . . . Closing: - + 45 . . . . . . . . . . } + 46 . . . . . . . . . . Incomplete: false + 47 . . . . . . . . . } + 48 . . . . . . . . . Comment: nil + 49 . . . . . . . . } + 50 . . . . . . . . Data: nil + 51 . . . . . . . . Type: nil + 52 . . . . . . . } + 53 . . . . . . } + 54 . . . . . . Rbrack: - + 55 . . . . . } + 56 . . . . } + 57 . . . . Tag: nil + 58 . . . . Comment: nil + 59 . . . } + 60 . . . 1: *ast.Field { + 61 . . . . Doc: nil + 62 . . . . Names: []*ast.Ident (len = 1) { + 63 . . . . . 0: *ast.Ident { + 64 . . . . . . NamePos: - + 65 . . . . . . Name: "config" + 66 . . . . . . Obj: *ast.Object { + 67 . . . . . . . Kind: var + 68 . . . . . . . Name: "config" + 69 . . . . . . . Decl: *(obj @ 60) + 70 . . . . . . . Data: nil + 71 . . . . . . . Type: nil + 72 . . . . . . } + 73 . . . . . } + 74 . . . . } + 75 . . . . Type: *ast.SelectorExpr { + 76 . . . . . X: *ast.Ident { + 77 . . . . . . NamePos: - + 78 . . . . . . Name: "core" + 79 . . . . . . Obj: nil + 80 . . . . . } + 81 . . . . . Sel: *ast.Ident { + 82 . . . . . . NamePos: - + 83 . . . . . . Name: "Config" + 84 . . . . . . Obj: nil + 85 . . . . . } + 86 . . . . } + 87 . . . . Tag: nil + 88 . . . . Comment: nil + 89 . . . } + 90 . . . 2: *ast.Field { + 91 . . . . Doc: nil + 92 . . . . Names: []*ast.Ident (len = 1) { + 93 . . . . . 0: *ast.Ident { + 94 . . . . . . NamePos: - + 95 . . . . . . Name: "display" + 96 . . . . . . Obj: *ast.Object { + 97 . . . . . . . Kind: var + 98 . . . . . . . Name: "display" + 99 . . . . . . . Decl: *(obj @ 90) + 100 . . . . . . . Data: nil + 101 . . . . . . . Type: nil + 102 . . . . . . } + 103 . . . . . } + 104 . . . . } + 105 . . . . Type: *ast.SelectorExpr { + 106 . . . . . X: *ast.Ident { + 107 . . . . . . NamePos: - + 108 . . . . . . Name: "core" + 109 . . . . . . Obj: nil + 110 . . . . . } + 111 . . . . . Sel: *ast.Ident { + 112 . . . . . . NamePos: - + 113 . . . . . . Name: "Display" + 114 . . . . . . Obj: nil + 115 . . . . . } + 116 . . . . } + 117 . . . . Tag: nil + 118 . . . . Comment: nil + 119 . . . } + 120 . . . 3: *ast.Field { + 121 . . . . Doc: nil + 122 . . . . Names: []*ast.Ident (len = 1) { + 123 . . . . . 0: *ast.Ident { + 124 . . . . . . NamePos: - + 125 . . . . . . Name: "assets" + 126 . . . . . . Obj: *ast.Object { + 127 . . . . . . . Kind: var + 128 . . . . . . . Name: "assets" + 129 . . . . . . . Decl: *(obj @ 120) + 130 . . . . . . . Data: nil + 131 . . . . . . . Type: nil + 132 . . . . . . } + 133 . . . . . } + 134 . . . . } + 135 . . . . Type: *ast.SelectorExpr { + 136 . . . . . X: *ast.Ident { + 137 . . . . . . NamePos: - + 138 . . . . . . Name: "embed" + 139 . . . . . . Obj: nil + 140 . . . . . } + 141 . . . . . Sel: *ast.Ident { + 142 . . . . . . NamePos: - + 143 . . . . . . Name: "FS" + 144 . . . . . . Obj: nil + 145 . . . . . } + 146 . . . . } + 147 . . . . Tag: nil + 148 . . . . Comment: nil + 149 . . . } + 150 . . } + 151 . . Closing: - + 152 . } + 153 . Incomplete: false + 154 } + +``` +Service manages the in-app help system. + + + +#### Methods + +- `HandleIPCEvents(c 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "core" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "Core" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +, msg 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "core" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "Message" + 9 . . Obj: nil + 10 . } + 11 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: HandleIPCEvents processes IPC messages, including injecting dependencies on startup. + +- `ServiceStartup( 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "context" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "Context" + 9 . . Obj: nil + 10 . } + 11 } +, 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "application" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "ServiceOptions" + 9 . . Obj: nil + 10 . } + 11 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: ServiceStartup is called when the app starts, after dependencies are injected. + +- `Show() 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: Show displays the help window. + +- `ShowAt(anchor 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: ShowAt displays a specific section of the help documentation. + + + + + +## Functions + +- `Register(c 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "core" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "Core" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "any" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: Register is the constructor for dynamic dependency injection (used with core.WithService). It creates a Service instance and initialises its core.Runtime field. Dependencies are injected during ServiceStartup. diff --git a/docs/services/i18n.md b/docs/services/i18n.md new file mode 100644 index 0000000..9ddc2f4 --- /dev/null +++ b/docs/services/i18n.md @@ -0,0 +1,378 @@ +--- +title: i18n +--- +# Service: `i18n` + + + + + + +## Types + +### `type Options` +```go +type Options 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: nil + 5 . . Closing: - + 6 . } + 7 . Incomplete: false + 8 } + +``` +Options holds configuration for the i18n service. + + + + + +### `type Service` +```go +type Service 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 4) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: nil + 8 . . . . Type: *ast.StarExpr { + 9 . . . . . Star: - + 10 . . . . . X: *ast.IndexExpr { + 11 . . . . . . X: *ast.SelectorExpr { + 12 . . . . . . . X: *ast.Ident { + 13 . . . . . . . . NamePos: - + 14 . . . . . . . . Name: "core" + 15 . . . . . . . . Obj: nil + 16 . . . . . . . } + 17 . . . . . . . Sel: *ast.Ident { + 18 . . . . . . . . NamePos: - + 19 . . . . . . . . Name: "Runtime" + 20 . . . . . . . . Obj: nil + 21 . . . . . . . } + 22 . . . . . . } + 23 . . . . . . Lbrack: - + 24 . . . . . . Index: *ast.Ident { + 25 . . . . . . . NamePos: - + 26 . . . . . . . Name: "Options" + 27 . . . . . . . Obj: *ast.Object { + 28 . . . . . . . . Kind: type + 29 . . . . . . . . Name: "Options" + 30 . . . . . . . . Decl: *ast.TypeSpec { + 31 . . . . . . . . . Doc: nil + 32 . . . . . . . . . Name: *ast.Ident { + 33 . . . . . . . . . . NamePos: - + 34 . . . . . . . . . . Name: "Options" + 35 . . . . . . . . . . Obj: *(obj @ 27) + 36 . . . . . . . . . } + 37 . . . . . . . . . TypeParams: nil + 38 . . . . . . . . . Assign: - + 39 . . . . . . . . . Type: *ast.StructType { + 40 . . . . . . . . . . Struct: - + 41 . . . . . . . . . . Fields: *ast.FieldList { + 42 . . . . . . . . . . . Opening: - + 43 . . . . . . . . . . . List: nil + 44 . . . . . . . . . . . Closing: - + 45 . . . . . . . . . . } + 46 . . . . . . . . . . Incomplete: false + 47 . . . . . . . . . } + 48 . . . . . . . . . Comment: nil + 49 . . . . . . . . } + 50 . . . . . . . . Data: nil + 51 . . . . . . . . Type: nil + 52 . . . . . . . } + 53 . . . . . . } + 54 . . . . . . Rbrack: - + 55 . . . . . } + 56 . . . . } + 57 . . . . Tag: nil + 58 . . . . Comment: nil + 59 . . . } + 60 . . . 1: *ast.Field { + 61 . . . . Doc: nil + 62 . . . . Names: []*ast.Ident (len = 1) { + 63 . . . . . 0: *ast.Ident { + 64 . . . . . . NamePos: - + 65 . . . . . . Name: "bundle" + 66 . . . . . . Obj: *ast.Object { + 67 . . . . . . . Kind: var + 68 . . . . . . . Name: "bundle" + 69 . . . . . . . Decl: *(obj @ 60) + 70 . . . . . . . Data: nil + 71 . . . . . . . Type: nil + 72 . . . . . . } + 73 . . . . . } + 74 . . . . } + 75 . . . . Type: *ast.StarExpr { + 76 . . . . . Star: - + 77 . . . . . X: *ast.SelectorExpr { + 78 . . . . . . X: *ast.Ident { + 79 . . . . . . . NamePos: - + 80 . . . . . . . Name: "i18n" + 81 . . . . . . . Obj: nil + 82 . . . . . . } + 83 . . . . . . Sel: *ast.Ident { + 84 . . . . . . . NamePos: - + 85 . . . . . . . Name: "Bundle" + 86 . . . . . . . Obj: nil + 87 . . . . . . } + 88 . . . . . } + 89 . . . . } + 90 . . . . Tag: nil + 91 . . . . Comment: nil + 92 . . . } + 93 . . . 2: *ast.Field { + 94 . . . . Doc: nil + 95 . . . . Names: []*ast.Ident (len = 1) { + 96 . . . . . 0: *ast.Ident { + 97 . . . . . . NamePos: - + 98 . . . . . . Name: "localizer" + 99 . . . . . . Obj: *ast.Object { + 100 . . . . . . . Kind: var + 101 . . . . . . . Name: "localizer" + 102 . . . . . . . Decl: *(obj @ 93) + 103 . . . . . . . Data: nil + 104 . . . . . . . Type: nil + 105 . . . . . . } + 106 . . . . . } + 107 . . . . } + 108 . . . . Type: *ast.StarExpr { + 109 . . . . . Star: - + 110 . . . . . X: *ast.SelectorExpr { + 111 . . . . . . X: *ast.Ident { + 112 . . . . . . . NamePos: - + 113 . . . . . . . Name: "i18n" + 114 . . . . . . . Obj: nil + 115 . . . . . . } + 116 . . . . . . Sel: *ast.Ident { + 117 . . . . . . . NamePos: - + 118 . . . . . . . Name: "Localizer" + 119 . . . . . . . Obj: nil + 120 . . . . . . } + 121 . . . . . } + 122 . . . . } + 123 . . . . Tag: nil + 124 . . . . Comment: nil + 125 . . . } + 126 . . . 3: *ast.Field { + 127 . . . . Doc: nil + 128 . . . . Names: []*ast.Ident (len = 1) { + 129 . . . . . 0: *ast.Ident { + 130 . . . . . . NamePos: - + 131 . . . . . . Name: "availableLangs" + 132 . . . . . . Obj: *ast.Object { + 133 . . . . . . . Kind: var + 134 . . . . . . . Name: "availableLangs" + 135 . . . . . . . Decl: *(obj @ 126) + 136 . . . . . . . Data: nil + 137 . . . . . . . Type: nil + 138 . . . . . . } + 139 . . . . . } + 140 . . . . } + 141 . . . . Type: *ast.ArrayType { + 142 . . . . . Lbrack: - + 143 . . . . . Len: nil + 144 . . . . . Elt: *ast.SelectorExpr { + 145 . . . . . . X: *ast.Ident { + 146 . . . . . . . NamePos: - + 147 . . . . . . . Name: "language" + 148 . . . . . . . Obj: nil + 149 . . . . . . } + 150 . . . . . . Sel: *ast.Ident { + 151 . . . . . . . NamePos: - + 152 . . . . . . . Name: "Tag" + 153 . . . . . . . Obj: nil + 154 . . . . . . } + 155 . . . . . } + 156 . . . . } + 157 . . . . Tag: nil + 158 . . . . Comment: nil + 159 . . . } + 160 . . } + 161 . . Closing: - + 162 . } + 163 . Incomplete: false + 164 } + +``` +Service provides internationalization and localization. + + + +#### Methods + +- `HandleIPCEvents(c 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "core" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "Core" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +, msg 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "core" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "Message" + 9 . . Obj: nil + 10 . } + 11 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: HandleIPCEvents processes IPC messages, including injecting dependencies on startup. + +- `ServiceStartup( 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "context" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "Context" + 9 . . Obj: nil + 10 . } + 11 } +, 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "application" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "ServiceOptions" + 9 . . Obj: nil + 10 . } + 11 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: ServiceStartup is called when the app starts, after dependencies are injected. + +- `SetLanguage(lang 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: + +- `Translate(messageID 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +`: + + + + + +## Functions + +- `Register(c 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "core" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "Core" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "any" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: Register is the constructor for dynamic dependency injection (used with core.WithService). It creates a Service instance and initializes its core.Runtime field. Dependencies are injected during ServiceStartup. + +- `detectLanguage(supported 0 *ast.ArrayType { + 1 . Lbrack: - + 2 . Len: nil + 3 . Elt: *ast.SelectorExpr { + 4 . . X: *ast.Ident { + 5 . . . NamePos: - + 6 . . . Name: "language" + 7 . . . Obj: nil + 8 . . } + 9 . . Sel: *ast.Ident { + 10 . . . NamePos: - + 11 . . . Name: "Tag" + 12 . . . Obj: nil + 13 . . } + 14 . } + 15 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: + +- `getAvailableLanguages() 0 *ast.ArrayType { + 1 . Lbrack: - + 2 . Len: nil + 3 . Elt: *ast.SelectorExpr { + 4 . . X: *ast.Ident { + 5 . . . NamePos: - + 6 . . . Name: "language" + 7 . . . Obj: nil + 8 . . } + 9 . . Sel: *ast.Ident { + 10 . . . NamePos: - + 11 . . . Name: "Tag" + 12 . . . Obj: nil + 13 . . } + 14 . } + 15 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: diff --git a/docs/services/io.md b/docs/services/io.md new file mode 100644 index 0000000..7179ea0 --- /dev/null +++ b/docs/services/io.md @@ -0,0 +1,797 @@ +--- +title: io +--- +# Service: `io` + + + + + + +## Types + +### `type Medium` +```go +type Medium 0 *ast.InterfaceType { + 1 . Interface: - + 2 . Methods: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 6) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: *ast.CommentGroup { + 7 . . . . . List: []*ast.Comment (len = 1) { + 8 . . . . . . 0: *ast.Comment { + 9 . . . . . . . Slash: - + 10 . . . . . . . Text: "// Read retrieves the content of a file as a string." + 11 . . . . . . } + 12 . . . . . } + 13 . . . . } + 14 . . . . Names: []*ast.Ident (len = 1) { + 15 . . . . . 0: *ast.Ident { + 16 . . . . . . NamePos: - + 17 . . . . . . Name: "Read" + 18 . . . . . . Obj: *ast.Object { + 19 . . . . . . . Kind: func + 20 . . . . . . . Name: "Read" + 21 . . . . . . . Decl: *(obj @ 5) + 22 . . . . . . . Data: nil + 23 . . . . . . . Type: nil + 24 . . . . . . } + 25 . . . . . } + 26 . . . . } + 27 . . . . Type: *ast.FuncType { + 28 . . . . . Func: - + 29 . . . . . TypeParams: nil + 30 . . . . . Params: *ast.FieldList { + 31 . . . . . . Opening: - + 32 . . . . . . List: []*ast.Field (len = 1) { + 33 . . . . . . . 0: *ast.Field { + 34 . . . . . . . . Doc: nil + 35 . . . . . . . . Names: []*ast.Ident (len = 1) { + 36 . . . . . . . . . 0: *ast.Ident { + 37 . . . . . . . . . . NamePos: - + 38 . . . . . . . . . . Name: "path" + 39 . . . . . . . . . . Obj: *ast.Object { + 40 . . . . . . . . . . . Kind: var + 41 . . . . . . . . . . . Name: "path" + 42 . . . . . . . . . . . Decl: *(obj @ 33) + 43 . . . . . . . . . . . Data: nil + 44 . . . . . . . . . . . Type: nil + 45 . . . . . . . . . . } + 46 . . . . . . . . . } + 47 . . . . . . . . } + 48 . . . . . . . . Type: *ast.Ident { + 49 . . . . . . . . . NamePos: - + 50 . . . . . . . . . Name: "string" + 51 . . . . . . . . . Obj: nil + 52 . . . . . . . . } + 53 . . . . . . . . Tag: nil + 54 . . . . . . . . Comment: nil + 55 . . . . . . . } + 56 . . . . . . } + 57 . . . . . . Closing: - + 58 . . . . . } + 59 . . . . . Results: *ast.FieldList { + 60 . . . . . . Opening: - + 61 . . . . . . List: []*ast.Field (len = 2) { + 62 . . . . . . . 0: *ast.Field { + 63 . . . . . . . . Doc: nil + 64 . . . . . . . . Names: nil + 65 . . . . . . . . Type: *ast.Ident { + 66 . . . . . . . . . NamePos: - + 67 . . . . . . . . . Name: "string" + 68 . . . . . . . . . Obj: nil + 69 . . . . . . . . } + 70 . . . . . . . . Tag: nil + 71 . . . . . . . . Comment: nil + 72 . . . . . . . } + 73 . . . . . . . 1: *ast.Field { + 74 . . . . . . . . Doc: nil + 75 . . . . . . . . Names: nil + 76 . . . . . . . . Type: *ast.Ident { + 77 . . . . . . . . . NamePos: - + 78 . . . . . . . . . Name: "error" + 79 . . . . . . . . . Obj: nil + 80 . . . . . . . . } + 81 . . . . . . . . Tag: nil + 82 . . . . . . . . Comment: nil + 83 . . . . . . . } + 84 . . . . . . } + 85 . . . . . . Closing: - + 86 . . . . . } + 87 . . . . } + 88 . . . . Tag: nil + 89 . . . . Comment: nil + 90 . . . } + 91 . . . 1: *ast.Field { + 92 . . . . Doc: *ast.CommentGroup { + 93 . . . . . List: []*ast.Comment (len = 1) { + 94 . . . . . . 0: *ast.Comment { + 95 . . . . . . . Slash: - + 96 . . . . . . . Text: "// Write saves the given content to a file, overwriting it if it exists." + 97 . . . . . . } + 98 . . . . . } + 99 . . . . } + 100 . . . . Names: []*ast.Ident (len = 1) { + 101 . . . . . 0: *ast.Ident { + 102 . . . . . . NamePos: - + 103 . . . . . . Name: "Write" + 104 . . . . . . Obj: *ast.Object { + 105 . . . . . . . Kind: func + 106 . . . . . . . Name: "Write" + 107 . . . . . . . Decl: *(obj @ 91) + 108 . . . . . . . Data: nil + 109 . . . . . . . Type: nil + 110 . . . . . . } + 111 . . . . . } + 112 . . . . } + 113 . . . . Type: *ast.FuncType { + 114 . . . . . Func: - + 115 . . . . . TypeParams: nil + 116 . . . . . Params: *ast.FieldList { + 117 . . . . . . Opening: - + 118 . . . . . . List: []*ast.Field (len = 1) { + 119 . . . . . . . 0: *ast.Field { + 120 . . . . . . . . Doc: nil + 121 . . . . . . . . Names: []*ast.Ident (len = 2) { + 122 . . . . . . . . . 0: *ast.Ident { + 123 . . . . . . . . . . NamePos: - + 124 . . . . . . . . . . Name: "path" + 125 . . . . . . . . . . Obj: *ast.Object { + 126 . . . . . . . . . . . Kind: var + 127 . . . . . . . . . . . Name: "path" + 128 . . . . . . . . . . . Decl: *(obj @ 119) + 129 . . . . . . . . . . . Data: nil + 130 . . . . . . . . . . . Type: nil + 131 . . . . . . . . . . } + 132 . . . . . . . . . } + 133 . . . . . . . . . 1: *ast.Ident { + 134 . . . . . . . . . . NamePos: - + 135 . . . . . . . . . . Name: "content" + 136 . . . . . . . . . . Obj: *ast.Object { + 137 . . . . . . . . . . . Kind: var + 138 . . . . . . . . . . . Name: "content" + 139 . . . . . . . . . . . Decl: *(obj @ 119) + 140 . . . . . . . . . . . Data: nil + 141 . . . . . . . . . . . Type: nil + 142 . . . . . . . . . . } + 143 . . . . . . . . . } + 144 . . . . . . . . } + 145 . . . . . . . . Type: *ast.Ident { + 146 . . . . . . . . . NamePos: - + 147 . . . . . . . . . Name: "string" + 148 . . . . . . . . . Obj: nil + 149 . . . . . . . . } + 150 . . . . . . . . Tag: nil + 151 . . . . . . . . Comment: nil + 152 . . . . . . . } + 153 . . . . . . } + 154 . . . . . . Closing: - + 155 . . . . . } + 156 . . . . . Results: *ast.FieldList { + 157 . . . . . . Opening: - + 158 . . . . . . List: []*ast.Field (len = 1) { + 159 . . . . . . . 0: *ast.Field { + 160 . . . . . . . . Doc: nil + 161 . . . . . . . . Names: nil + 162 . . . . . . . . Type: *ast.Ident { + 163 . . . . . . . . . NamePos: - + 164 . . . . . . . . . Name: "error" + 165 . . . . . . . . . Obj: nil + 166 . . . . . . . . } + 167 . . . . . . . . Tag: nil + 168 . . . . . . . . Comment: nil + 169 . . . . . . . } + 170 . . . . . . } + 171 . . . . . . Closing: - + 172 . . . . . } + 173 . . . . } + 174 . . . . Tag: nil + 175 . . . . Comment: nil + 176 . . . } + 177 . . . 2: *ast.Field { + 178 . . . . Doc: *ast.CommentGroup { + 179 . . . . . List: []*ast.Comment (len = 1) { + 180 . . . . . . 0: *ast.Comment { + 181 . . . . . . . Slash: - + 182 . . . . . . . Text: "// EnsureDir makes sure a directory exists, creating it if necessary." + 183 . . . . . . } + 184 . . . . . } + 185 . . . . } + 186 . . . . Names: []*ast.Ident (len = 1) { + 187 . . . . . 0: *ast.Ident { + 188 . . . . . . NamePos: - + 189 . . . . . . Name: "EnsureDir" + 190 . . . . . . Obj: *ast.Object { + 191 . . . . . . . Kind: func + 192 . . . . . . . Name: "EnsureDir" + 193 . . . . . . . Decl: *(obj @ 177) + 194 . . . . . . . Data: nil + 195 . . . . . . . Type: nil + 196 . . . . . . } + 197 . . . . . } + 198 . . . . } + 199 . . . . Type: *ast.FuncType { + 200 . . . . . Func: - + 201 . . . . . TypeParams: nil + 202 . . . . . Params: *ast.FieldList { + 203 . . . . . . Opening: - + 204 . . . . . . List: []*ast.Field (len = 1) { + 205 . . . . . . . 0: *ast.Field { + 206 . . . . . . . . Doc: nil + 207 . . . . . . . . Names: []*ast.Ident (len = 1) { + 208 . . . . . . . . . 0: *ast.Ident { + 209 . . . . . . . . . . NamePos: - + 210 . . . . . . . . . . Name: "path" + 211 . . . . . . . . . . Obj: *ast.Object { + 212 . . . . . . . . . . . Kind: var + 213 . . . . . . . . . . . Name: "path" + 214 . . . . . . . . . . . Decl: *(obj @ 205) + 215 . . . . . . . . . . . Data: nil + 216 . . . . . . . . . . . Type: nil + 217 . . . . . . . . . . } + 218 . . . . . . . . . } + 219 . . . . . . . . } + 220 . . . . . . . . Type: *ast.Ident { + 221 . . . . . . . . . NamePos: - + 222 . . . . . . . . . Name: "string" + 223 . . . . . . . . . Obj: nil + 224 . . . . . . . . } + 225 . . . . . . . . Tag: nil + 226 . . . . . . . . Comment: nil + 227 . . . . . . . } + 228 . . . . . . } + 229 . . . . . . Closing: - + 230 . . . . . } + 231 . . . . . Results: *ast.FieldList { + 232 . . . . . . Opening: - + 233 . . . . . . List: []*ast.Field (len = 1) { + 234 . . . . . . . 0: *ast.Field { + 235 . . . . . . . . Doc: nil + 236 . . . . . . . . Names: nil + 237 . . . . . . . . Type: *ast.Ident { + 238 . . . . . . . . . NamePos: - + 239 . . . . . . . . . Name: "error" + 240 . . . . . . . . . Obj: nil + 241 . . . . . . . . } + 242 . . . . . . . . Tag: nil + 243 . . . . . . . . Comment: nil + 244 . . . . . . . } + 245 . . . . . . } + 246 . . . . . . Closing: - + 247 . . . . . } + 248 . . . . } + 249 . . . . Tag: nil + 250 . . . . Comment: nil + 251 . . . } + 252 . . . 3: *ast.Field { + 253 . . . . Doc: *ast.CommentGroup { + 254 . . . . . List: []*ast.Comment (len = 1) { + 255 . . . . . . 0: *ast.Comment { + 256 . . . . . . . Slash: - + 257 . . . . . . . Text: "// IsFile checks if a path exists and is a regular file." + 258 . . . . . . } + 259 . . . . . } + 260 . . . . } + 261 . . . . Names: []*ast.Ident (len = 1) { + 262 . . . . . 0: *ast.Ident { + 263 . . . . . . NamePos: - + 264 . . . . . . Name: "IsFile" + 265 . . . . . . Obj: *ast.Object { + 266 . . . . . . . Kind: func + 267 . . . . . . . Name: "IsFile" + 268 . . . . . . . Decl: *(obj @ 252) + 269 . . . . . . . Data: nil + 270 . . . . . . . Type: nil + 271 . . . . . . } + 272 . . . . . } + 273 . . . . } + 274 . . . . Type: *ast.FuncType { + 275 . . . . . Func: - + 276 . . . . . TypeParams: nil + 277 . . . . . Params: *ast.FieldList { + 278 . . . . . . Opening: - + 279 . . . . . . List: []*ast.Field (len = 1) { + 280 . . . . . . . 0: *ast.Field { + 281 . . . . . . . . Doc: nil + 282 . . . . . . . . Names: []*ast.Ident (len = 1) { + 283 . . . . . . . . . 0: *ast.Ident { + 284 . . . . . . . . . . NamePos: - + 285 . . . . . . . . . . Name: "path" + 286 . . . . . . . . . . Obj: *ast.Object { + 287 . . . . . . . . . . . Kind: var + 288 . . . . . . . . . . . Name: "path" + 289 . . . . . . . . . . . Decl: *(obj @ 280) + 290 . . . . . . . . . . . Data: nil + 291 . . . . . . . . . . . Type: nil + 292 . . . . . . . . . . } + 293 . . . . . . . . . } + 294 . . . . . . . . } + 295 . . . . . . . . Type: *ast.Ident { + 296 . . . . . . . . . NamePos: - + 297 . . . . . . . . . Name: "string" + 298 . . . . . . . . . Obj: nil + 299 . . . . . . . . } + 300 . . . . . . . . Tag: nil + 301 . . . . . . . . Comment: nil + 302 . . . . . . . } + 303 . . . . . . } + 304 . . . . . . Closing: - + 305 . . . . . } + 306 . . . . . Results: *ast.FieldList { + 307 . . . . . . Opening: - + 308 . . . . . . List: []*ast.Field (len = 1) { + 309 . . . . . . . 0: *ast.Field { + 310 . . . . . . . . Doc: nil + 311 . . . . . . . . Names: nil + 312 . . . . . . . . Type: *ast.Ident { + 313 . . . . . . . . . NamePos: - + 314 . . . . . . . . . Name: "bool" + 315 . . . . . . . . . Obj: nil + 316 . . . . . . . . } + 317 . . . . . . . . Tag: nil + 318 . . . . . . . . Comment: nil + 319 . . . . . . . } + 320 . . . . . . } + 321 . . . . . . Closing: - + 322 . . . . . } + 323 . . . . } + 324 . . . . Tag: nil + 325 . . . . Comment: nil + 326 . . . } + 327 . . . 4: *ast.Field { + 328 . . . . Doc: *ast.CommentGroup { + 329 . . . . . List: []*ast.Comment (len = 1) { + 330 . . . . . . 0: *ast.Comment { + 331 . . . . . . . Slash: - + 332 . . . . . . . Text: "// FileGet is a convenience function that reads a file from the medium." + 333 . . . . . . } + 334 . . . . . } + 335 . . . . } + 336 . . . . Names: []*ast.Ident (len = 1) { + 337 . . . . . 0: *ast.Ident { + 338 . . . . . . NamePos: - + 339 . . . . . . Name: "FileGet" + 340 . . . . . . Obj: *ast.Object { + 341 . . . . . . . Kind: func + 342 . . . . . . . Name: "FileGet" + 343 . . . . . . . Decl: *(obj @ 327) + 344 . . . . . . . Data: nil + 345 . . . . . . . Type: nil + 346 . . . . . . } + 347 . . . . . } + 348 . . . . } + 349 . . . . Type: *ast.FuncType { + 350 . . . . . Func: - + 351 . . . . . TypeParams: nil + 352 . . . . . Params: *ast.FieldList { + 353 . . . . . . Opening: - + 354 . . . . . . List: []*ast.Field (len = 1) { + 355 . . . . . . . 0: *ast.Field { + 356 . . . . . . . . Doc: nil + 357 . . . . . . . . Names: []*ast.Ident (len = 1) { + 358 . . . . . . . . . 0: *ast.Ident { + 359 . . . . . . . . . . NamePos: - + 360 . . . . . . . . . . Name: "path" + 361 . . . . . . . . . . Obj: *ast.Object { + 362 . . . . . . . . . . . Kind: var + 363 . . . . . . . . . . . Name: "path" + 364 . . . . . . . . . . . Decl: *(obj @ 355) + 365 . . . . . . . . . . . Data: nil + 366 . . . . . . . . . . . Type: nil + 367 . . . . . . . . . . } + 368 . . . . . . . . . } + 369 . . . . . . . . } + 370 . . . . . . . . Type: *ast.Ident { + 371 . . . . . . . . . NamePos: - + 372 . . . . . . . . . Name: "string" + 373 . . . . . . . . . Obj: nil + 374 . . . . . . . . } + 375 . . . . . . . . Tag: nil + 376 . . . . . . . . Comment: nil + 377 . . . . . . . } + 378 . . . . . . } + 379 . . . . . . Closing: - + 380 . . . . . } + 381 . . . . . Results: *ast.FieldList { + 382 . . . . . . Opening: - + 383 . . . . . . List: []*ast.Field (len = 2) { + 384 . . . . . . . 0: *ast.Field { + 385 . . . . . . . . Doc: nil + 386 . . . . . . . . Names: nil + 387 . . . . . . . . Type: *ast.Ident { + 388 . . . . . . . . . NamePos: - + 389 . . . . . . . . . Name: "string" + 390 . . . . . . . . . Obj: nil + 391 . . . . . . . . } + 392 . . . . . . . . Tag: nil + 393 . . . . . . . . Comment: nil + 394 . . . . . . . } + 395 . . . . . . . 1: *ast.Field { + 396 . . . . . . . . Doc: nil + 397 . . . . . . . . Names: nil + 398 . . . . . . . . Type: *ast.Ident { + 399 . . . . . . . . . NamePos: - + 400 . . . . . . . . . Name: "error" + 401 . . . . . . . . . Obj: nil + 402 . . . . . . . . } + 403 . . . . . . . . Tag: nil + 404 . . . . . . . . Comment: nil + 405 . . . . . . . } + 406 . . . . . . } + 407 . . . . . . Closing: - + 408 . . . . . } + 409 . . . . } + 410 . . . . Tag: nil + 411 . . . . Comment: nil + 412 . . . } + 413 . . . 5: *ast.Field { + 414 . . . . Doc: *ast.CommentGroup { + 415 . . . . . List: []*ast.Comment (len = 1) { + 416 . . . . . . 0: *ast.Comment { + 417 . . . . . . . Slash: - + 418 . . . . . . . Text: "// FileSet is a convenience function that writes a file to the medium." + 419 . . . . . . } + 420 . . . . . } + 421 . . . . } + 422 . . . . Names: []*ast.Ident (len = 1) { + 423 . . . . . 0: *ast.Ident { + 424 . . . . . . NamePos: - + 425 . . . . . . Name: "FileSet" + 426 . . . . . . Obj: *ast.Object { + 427 . . . . . . . Kind: func + 428 . . . . . . . Name: "FileSet" + 429 . . . . . . . Decl: *(obj @ 413) + 430 . . . . . . . Data: nil + 431 . . . . . . . Type: nil + 432 . . . . . . } + 433 . . . . . } + 434 . . . . } + 435 . . . . Type: *ast.FuncType { + 436 . . . . . Func: - + 437 . . . . . TypeParams: nil + 438 . . . . . Params: *ast.FieldList { + 439 . . . . . . Opening: - + 440 . . . . . . List: []*ast.Field (len = 1) { + 441 . . . . . . . 0: *ast.Field { + 442 . . . . . . . . Doc: nil + 443 . . . . . . . . Names: []*ast.Ident (len = 2) { + 444 . . . . . . . . . 0: *ast.Ident { + 445 . . . . . . . . . . NamePos: - + 446 . . . . . . . . . . Name: "path" + 447 . . . . . . . . . . Obj: *ast.Object { + 448 . . . . . . . . . . . Kind: var + 449 . . . . . . . . . . . Name: "path" + 450 . . . . . . . . . . . Decl: *(obj @ 441) + 451 . . . . . . . . . . . Data: nil + 452 . . . . . . . . . . . Type: nil + 453 . . . . . . . . . . } + 454 . . . . . . . . . } + 455 . . . . . . . . . 1: *ast.Ident { + 456 . . . . . . . . . . NamePos: - + 457 . . . . . . . . . . Name: "content" + 458 . . . . . . . . . . Obj: *ast.Object { + 459 . . . . . . . . . . . Kind: var + 460 . . . . . . . . . . . Name: "content" + 461 . . . . . . . . . . . Decl: *(obj @ 441) + 462 . . . . . . . . . . . Data: nil + 463 . . . . . . . . . . . Type: nil + 464 . . . . . . . . . . } + 465 . . . . . . . . . } + 466 . . . . . . . . } + 467 . . . . . . . . Type: *ast.Ident { + 468 . . . . . . . . . NamePos: - + 469 . . . . . . . . . Name: "string" + 470 . . . . . . . . . Obj: nil + 471 . . . . . . . . } + 472 . . . . . . . . Tag: nil + 473 . . . . . . . . Comment: nil + 474 . . . . . . . } + 475 . . . . . . } + 476 . . . . . . Closing: - + 477 . . . . . } + 478 . . . . . Results: *ast.FieldList { + 479 . . . . . . Opening: - + 480 . . . . . . List: []*ast.Field (len = 1) { + 481 . . . . . . . 0: *ast.Field { + 482 . . . . . . . . Doc: nil + 483 . . . . . . . . Names: nil + 484 . . . . . . . . Type: *ast.Ident { + 485 . . . . . . . . . NamePos: - + 486 . . . . . . . . . Name: "error" + 487 . . . . . . . . . Obj: nil + 488 . . . . . . . . } + 489 . . . . . . . . Tag: nil + 490 . . . . . . . . Comment: nil + 491 . . . . . . . } + 492 . . . . . . } + 493 . . . . . . Closing: - + 494 . . . . . } + 495 . . . . } + 496 . . . . Tag: nil + 497 . . . . Comment: nil + 498 . . . } + 499 . . } + 500 . . Closing: - + 501 . } + 502 . Incomplete: false + 503 } + +``` +Medium defines the standard interface for a storage backend. +This allows for different implementations (e.g., local disk, S3, SFTP) +to be used interchangeably. + + + + + +### `type MockMedium` +```go +type MockMedium 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 2) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: []*ast.Ident (len = 1) { + 8 . . . . . 0: *ast.Ident { + 9 . . . . . . NamePos: - + 10 . . . . . . Name: "Files" + 11 . . . . . . Obj: *ast.Object { + 12 . . . . . . . Kind: var + 13 . . . . . . . Name: "Files" + 14 . . . . . . . Decl: *(obj @ 5) + 15 . . . . . . . Data: nil + 16 . . . . . . . Type: nil + 17 . . . . . . } + 18 . . . . . } + 19 . . . . } + 20 . . . . Type: *ast.MapType { + 21 . . . . . Map: - + 22 . . . . . Key: *ast.Ident { + 23 . . . . . . NamePos: - + 24 . . . . . . Name: "string" + 25 . . . . . . Obj: nil + 26 . . . . . } + 27 . . . . . Value: *ast.Ident { + 28 . . . . . . NamePos: - + 29 . . . . . . Name: "string" + 30 . . . . . . Obj: nil + 31 . . . . . } + 32 . . . . } + 33 . . . . Tag: nil + 34 . . . . Comment: nil + 35 . . . } + 36 . . . 1: *ast.Field { + 37 . . . . Doc: nil + 38 . . . . Names: []*ast.Ident (len = 1) { + 39 . . . . . 0: *ast.Ident { + 40 . . . . . . NamePos: - + 41 . . . . . . Name: "Dirs" + 42 . . . . . . Obj: *ast.Object { + 43 . . . . . . . Kind: var + 44 . . . . . . . Name: "Dirs" + 45 . . . . . . . Decl: *(obj @ 36) + 46 . . . . . . . Data: nil + 47 . . . . . . . Type: nil + 48 . . . . . . } + 49 . . . . . } + 50 . . . . } + 51 . . . . Type: *ast.MapType { + 52 . . . . . Map: - + 53 . . . . . Key: *ast.Ident { + 54 . . . . . . NamePos: - + 55 . . . . . . Name: "string" + 56 . . . . . . Obj: nil + 57 . . . . . } + 58 . . . . . Value: *ast.Ident { + 59 . . . . . . NamePos: - + 60 . . . . . . Name: "bool" + 61 . . . . . . Obj: nil + 62 . . . . . } + 63 . . . . } + 64 . . . . Tag: nil + 65 . . . . Comment: nil + 66 . . . } + 67 . . } + 68 . . Closing: - + 69 . } + 70 . Incomplete: false + 71 } + +``` +MockMedium implements the Medium interface for testing purposes. + + + +#### Methods + +- `EnsureDir(path 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: + +- `FileGet(path 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: + +- `FileSet(path, content 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: + +- `IsFile(path 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "bool" + 3 . Obj: nil + 4 } +`: + +- `Read(path 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: + +- `Write(path, content 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: + + + + + +## Functions + +- `Copy(sourceMedium 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "Medium" + 3 . Obj: nil + 4 } +, sourcePath 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, destMedium 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "Medium" + 3 . Obj: nil + 4 } +, destPath 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: Copy copies a file from a source medium to a destination medium. + +- `EnsureDir(m 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "Medium" + 3 . Obj: nil + 4 } +, path 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: EnsureDir ensures a directory exists on the given medium. + +- `IsFile(m 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "Medium" + 3 . Obj: nil + 4 } +, path 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "bool" + 3 . Obj: nil + 4 } +`: IsFile checks if a path is a file on the given medium. + +- `Read(m 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "Medium" + 3 . Obj: nil + 4 } +, path 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: Read retrieves the content of a file from the given medium. + +- `Write(m 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "Medium" + 3 . Obj: nil + 4 } +, path, content 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: Write saves content to a file on the given medium. diff --git a/docs/services/runtime.md b/docs/services/runtime.md new file mode 100644 index 0000000..ce30c75 --- /dev/null +++ b/docs/services/runtime.md @@ -0,0 +1,388 @@ +--- +title: runtime +--- +# Service: `runtime` + + + + + + +## Types + +### `type Runtime` +```go +type Runtime 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 8) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: []*ast.Ident (len = 1) { + 8 . . . . . 0: *ast.Ident { + 9 . . . . . . NamePos: - + 10 . . . . . . Name: "app" + 11 . . . . . . Obj: *ast.Object { + 12 . . . . . . . Kind: var + 13 . . . . . . . Name: "app" + 14 . . . . . . . Decl: *(obj @ 5) + 15 . . . . . . . Data: nil + 16 . . . . . . . Type: nil + 17 . . . . . . } + 18 . . . . . } + 19 . . . . } + 20 . . . . Type: *ast.StarExpr { + 21 . . . . . Star: - + 22 . . . . . X: *ast.SelectorExpr { + 23 . . . . . . X: *ast.Ident { + 24 . . . . . . . NamePos: - + 25 . . . . . . . Name: "application" + 26 . . . . . . . Obj: nil + 27 . . . . . . } + 28 . . . . . . Sel: *ast.Ident { + 29 . . . . . . . NamePos: - + 30 . . . . . . . Name: "App" + 31 . . . . . . . Obj: nil + 32 . . . . . . } + 33 . . . . . } + 34 . . . . } + 35 . . . . Tag: nil + 36 . . . . Comment: nil + 37 . . . } + 38 . . . 1: *ast.Field { + 39 . . . . Doc: nil + 40 . . . . Names: []*ast.Ident (len = 1) { + 41 . . . . . 0: *ast.Ident { + 42 . . . . . . NamePos: - + 43 . . . . . . Name: "Core" + 44 . . . . . . Obj: *ast.Object { + 45 . . . . . . . Kind: var + 46 . . . . . . . Name: "Core" + 47 . . . . . . . Decl: *(obj @ 38) + 48 . . . . . . . Data: nil + 49 . . . . . . . Type: nil + 50 . . . . . . } + 51 . . . . . } + 52 . . . . } + 53 . . . . Type: *ast.StarExpr { + 54 . . . . . Star: - + 55 . . . . . X: *ast.SelectorExpr { + 56 . . . . . . X: *ast.Ident { + 57 . . . . . . . NamePos: - + 58 . . . . . . . Name: "core" + 59 . . . . . . . Obj: nil + 60 . . . . . . } + 61 . . . . . . Sel: *ast.Ident { + 62 . . . . . . . NamePos: - + 63 . . . . . . . Name: "Core" + 64 . . . . . . . Obj: nil + 65 . . . . . . } + 66 . . . . . } + 67 . . . . } + 68 . . . . Tag: nil + 69 . . . . Comment: nil + 70 . . . } + 71 . . . 2: *ast.Field { + 72 . . . . Doc: nil + 73 . . . . Names: []*ast.Ident (len = 1) { + 74 . . . . . 0: *ast.Ident { + 75 . . . . . . NamePos: - + 76 . . . . . . Name: "Config" + 77 . . . . . . Obj: *ast.Object { + 78 . . . . . . . Kind: var + 79 . . . . . . . Name: "Config" + 80 . . . . . . . Decl: *(obj @ 71) + 81 . . . . . . . Data: nil + 82 . . . . . . . Type: nil + 83 . . . . . . } + 84 . . . . . } + 85 . . . . } + 86 . . . . Type: *ast.StarExpr { + 87 . . . . . Star: - + 88 . . . . . X: *ast.SelectorExpr { + 89 . . . . . . X: *ast.Ident { + 90 . . . . . . . NamePos: - + 91 . . . . . . . Name: "config" + 92 . . . . . . . Obj: nil + 93 . . . . . . } + 94 . . . . . . Sel: *ast.Ident { + 95 . . . . . . . NamePos: - + 96 . . . . . . . Name: "Service" + 97 . . . . . . . Obj: nil + 98 . . . . . . } + 99 . . . . . } + 100 . . . . } + 101 . . . . Tag: nil + 102 . . . . Comment: nil + 103 . . . } + 104 . . . 3: *ast.Field { + 105 . . . . Doc: nil + 106 . . . . Names: []*ast.Ident (len = 1) { + 107 . . . . . 0: *ast.Ident { + 108 . . . . . . NamePos: - + 109 . . . . . . Name: "Display" + 110 . . . . . . Obj: *ast.Object { + 111 . . . . . . . Kind: var + 112 . . . . . . . Name: "Display" + 113 . . . . . . . Decl: *(obj @ 104) + 114 . . . . . . . Data: nil + 115 . . . . . . . Type: nil + 116 . . . . . . } + 117 . . . . . } + 118 . . . . } + 119 . . . . Type: *ast.StarExpr { + 120 . . . . . Star: - + 121 . . . . . X: *ast.SelectorExpr { + 122 . . . . . . X: *ast.Ident { + 123 . . . . . . . NamePos: - + 124 . . . . . . . Name: "display" + 125 . . . . . . . Obj: nil + 126 . . . . . . } + 127 . . . . . . Sel: *ast.Ident { + 128 . . . . . . . NamePos: - + 129 . . . . . . . Name: "Service" + 130 . . . . . . . Obj: nil + 131 . . . . . . } + 132 . . . . . } + 133 . . . . } + 134 . . . . Tag: nil + 135 . . . . Comment: nil + 136 . . . } + 137 . . . 4: *ast.Field { + 138 . . . . Doc: nil + 139 . . . . Names: []*ast.Ident (len = 1) { + 140 . . . . . 0: *ast.Ident { + 141 . . . . . . NamePos: - + 142 . . . . . . Name: "Help" + 143 . . . . . . Obj: *ast.Object { + 144 . . . . . . . Kind: var + 145 . . . . . . . Name: "Help" + 146 . . . . . . . Decl: *(obj @ 137) + 147 . . . . . . . Data: nil + 148 . . . . . . . Type: nil + 149 . . . . . . } + 150 . . . . . } + 151 . . . . } + 152 . . . . Type: *ast.StarExpr { + 153 . . . . . Star: - + 154 . . . . . X: *ast.SelectorExpr { + 155 . . . . . . X: *ast.Ident { + 156 . . . . . . . NamePos: - + 157 . . . . . . . Name: "help" + 158 . . . . . . . Obj: nil + 159 . . . . . . } + 160 . . . . . . Sel: *ast.Ident { + 161 . . . . . . . NamePos: - + 162 . . . . . . . Name: "Service" + 163 . . . . . . . Obj: nil + 164 . . . . . . } + 165 . . . . . } + 166 . . . . } + 167 . . . . Tag: nil + 168 . . . . Comment: nil + 169 . . . } + 170 . . . 5: *ast.Field { + 171 . . . . Doc: nil + 172 . . . . Names: []*ast.Ident (len = 1) { + 173 . . . . . 0: *ast.Ident { + 174 . . . . . . NamePos: - + 175 . . . . . . Name: "Crypt" + 176 . . . . . . Obj: *ast.Object { + 177 . . . . . . . Kind: var + 178 . . . . . . . Name: "Crypt" + 179 . . . . . . . Decl: *(obj @ 170) + 180 . . . . . . . Data: nil + 181 . . . . . . . Type: nil + 182 . . . . . . } + 183 . . . . . } + 184 . . . . } + 185 . . . . Type: *ast.StarExpr { + 186 . . . . . Star: - + 187 . . . . . X: *ast.SelectorExpr { + 188 . . . . . . X: *ast.Ident { + 189 . . . . . . . NamePos: - + 190 . . . . . . . Name: "crypt" + 191 . . . . . . . Obj: nil + 192 . . . . . . } + 193 . . . . . . Sel: *ast.Ident { + 194 . . . . . . . NamePos: - + 195 . . . . . . . Name: "Service" + 196 . . . . . . . Obj: nil + 197 . . . . . . } + 198 . . . . . } + 199 . . . . } + 200 . . . . Tag: nil + 201 . . . . Comment: nil + 202 . . . } + 203 . . . 6: *ast.Field { + 204 . . . . Doc: nil + 205 . . . . Names: []*ast.Ident (len = 1) { + 206 . . . . . 0: *ast.Ident { + 207 . . . . . . NamePos: - + 208 . . . . . . Name: "I18n" + 209 . . . . . . Obj: *ast.Object { + 210 . . . . . . . Kind: var + 211 . . . . . . . Name: "I18n" + 212 . . . . . . . Decl: *(obj @ 203) + 213 . . . . . . . Data: nil + 214 . . . . . . . Type: nil + 215 . . . . . . } + 216 . . . . . } + 217 . . . . } + 218 . . . . Type: *ast.StarExpr { + 219 . . . . . Star: - + 220 . . . . . X: *ast.SelectorExpr { + 221 . . . . . . X: *ast.Ident { + 222 . . . . . . . NamePos: - + 223 . . . . . . . Name: "i18n" + 224 . . . . . . . Obj: nil + 225 . . . . . . } + 226 . . . . . . Sel: *ast.Ident { + 227 . . . . . . . NamePos: - + 228 . . . . . . . Name: "Service" + 229 . . . . . . . Obj: nil + 230 . . . . . . } + 231 . . . . . } + 232 . . . . } + 233 . . . . Tag: nil + 234 . . . . Comment: nil + 235 . . . } + 236 . . . 7: *ast.Field { + 237 . . . . Doc: nil + 238 . . . . Names: []*ast.Ident (len = 1) { + 239 . . . . . 0: *ast.Ident { + 240 . . . . . . NamePos: - + 241 . . . . . . Name: "Workspace" + 242 . . . . . . Obj: *ast.Object { + 243 . . . . . . . Kind: var + 244 . . . . . . . Name: "Workspace" + 245 . . . . . . . Decl: *(obj @ 236) + 246 . . . . . . . Data: nil + 247 . . . . . . . Type: nil + 248 . . . . . . } + 249 . . . . . } + 250 . . . . } + 251 . . . . Type: *ast.StarExpr { + 252 . . . . . Star: - + 253 . . . . . X: *ast.SelectorExpr { + 254 . . . . . . X: *ast.Ident { + 255 . . . . . . . NamePos: - + 256 . . . . . . . Name: "workspace" + 257 . . . . . . . Obj: nil + 258 . . . . . . } + 259 . . . . . . Sel: *ast.Ident { + 260 . . . . . . . NamePos: - + 261 . . . . . . . Name: "Service" + 262 . . . . . . . Obj: nil + 263 . . . . . . } + 264 . . . . . } + 265 . . . . } + 266 . . . . Tag: nil + 267 . . . . Comment: nil + 268 . . . } + 269 . . } + 270 . . Closing: - + 271 . } + 272 . Incomplete: false + 273 } + +``` +Runtime is the container that holds all instantiated services. +Its fields are the concrete types, allowing Wails to bind them directly. + + + +#### Methods + +- `ServiceName() 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +`: ServiceName returns the name of the service. This is used by Wails to identify the service. + +- `ServiceShutdown(ctx 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "context" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "Context" + 9 . . Obj: nil + 10 . } + 11 } +) `: ServiceShutdown is called by Wails at application shutdown. + +- `ServiceStartup(ctx 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "context" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "Context" + 9 . . Obj: nil + 10 . } + 11 } +, options 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "application" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "ServiceOptions" + 9 . . Obj: nil + 10 . } + 11 } +) `: ServiceStartup is called by Wails at application startup. + + + +### `type ServiceFactory` +```go +type ServiceFactory 0 *ast.FuncType { + 1 . Func: - + 2 . TypeParams: nil + 3 . Params: *ast.FieldList { + 4 . . Opening: - + 5 . . List: nil + 6 . . Closing: - + 7 . } + 8 . Results: *ast.FieldList { + 9 . . Opening: - + 10 . . List: []*ast.Field (len = 2) { + 11 . . . 0: *ast.Field { + 12 . . . . Doc: nil + 13 . . . . Names: nil + 14 . . . . Type: *ast.Ident { + 15 . . . . . NamePos: - + 16 . . . . . Name: "any" + 17 . . . . . Obj: nil + 18 . . . . } + 19 . . . . Tag: nil + 20 . . . . Comment: nil + 21 . . . } + 22 . . . 1: *ast.Field { + 23 . . . . Doc: nil + 24 . . . . Names: nil + 25 . . . . Type: *ast.Ident { + 26 . . . . . NamePos: - + 27 . . . . . Name: "error" + 28 . . . . . Obj: nil + 29 . . . . } + 30 . . . . Tag: nil + 31 . . . . Comment: nil + 32 . . . } + 33 . . } + 34 . . Closing: - + 35 . } + 36 } + +``` +ServiceFactory defines a function that creates a service instance. diff --git a/docs/services/workspace.md b/docs/services/workspace.md new file mode 100644 index 0000000..3d46c31 --- /dev/null +++ b/docs/services/workspace.md @@ -0,0 +1,628 @@ +--- +title: workspace +--- +# Service: `workspace` + + + + +## Constants + +```godefaultWorkspacelistFile +``` + + + + +## Types + +### `type Options` +```go +type Options 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: nil + 5 . . Closing: - + 6 . } + 7 . Incomplete: false + 8 } + +``` +Options holds configuration for the workspace service. + + + + + +### `type Service` +```go +type Service 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 4) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: nil + 8 . . . . Type: *ast.StarExpr { + 9 . . . . . Star: - + 10 . . . . . X: *ast.IndexExpr { + 11 . . . . . . X: *ast.SelectorExpr { + 12 . . . . . . . X: *ast.Ident { + 13 . . . . . . . . NamePos: - + 14 . . . . . . . . Name: "core" + 15 . . . . . . . . Obj: nil + 16 . . . . . . . } + 17 . . . . . . . Sel: *ast.Ident { + 18 . . . . . . . . NamePos: - + 19 . . . . . . . . Name: "Runtime" + 20 . . . . . . . . Obj: nil + 21 . . . . . . . } + 22 . . . . . . } + 23 . . . . . . Lbrack: - + 24 . . . . . . Index: *ast.Ident { + 25 . . . . . . . NamePos: - + 26 . . . . . . . Name: "Options" + 27 . . . . . . . Obj: *ast.Object { + 28 . . . . . . . . Kind: type + 29 . . . . . . . . Name: "Options" + 30 . . . . . . . . Decl: *ast.TypeSpec { + 31 . . . . . . . . . Doc: nil + 32 . . . . . . . . . Name: *ast.Ident { + 33 . . . . . . . . . . NamePos: - + 34 . . . . . . . . . . Name: "Options" + 35 . . . . . . . . . . Obj: *(obj @ 27) + 36 . . . . . . . . . } + 37 . . . . . . . . . TypeParams: nil + 38 . . . . . . . . . Assign: - + 39 . . . . . . . . . Type: *ast.StructType { + 40 . . . . . . . . . . Struct: - + 41 . . . . . . . . . . Fields: *ast.FieldList { + 42 . . . . . . . . . . . Opening: - + 43 . . . . . . . . . . . List: nil + 44 . . . . . . . . . . . Closing: - + 45 . . . . . . . . . . } + 46 . . . . . . . . . . Incomplete: false + 47 . . . . . . . . . } + 48 . . . . . . . . . Comment: nil + 49 . . . . . . . . } + 50 . . . . . . . . Data: nil + 51 . . . . . . . . Type: nil + 52 . . . . . . . } + 53 . . . . . . } + 54 . . . . . . Rbrack: - + 55 . . . . . } + 56 . . . . } + 57 . . . . Tag: nil + 58 . . . . Comment: nil + 59 . . . } + 60 . . . 1: *ast.Field { + 61 . . . . Doc: nil + 62 . . . . Names: []*ast.Ident (len = 1) { + 63 . . . . . 0: *ast.Ident { + 64 . . . . . . NamePos: - + 65 . . . . . . Name: "activeWorkspace" + 66 . . . . . . Obj: *ast.Object { + 67 . . . . . . . Kind: var + 68 . . . . . . . Name: "activeWorkspace" + 69 . . . . . . . Decl: *(obj @ 60) + 70 . . . . . . . Data: nil + 71 . . . . . . . Type: nil + 72 . . . . . . } + 73 . . . . . } + 74 . . . . } + 75 . . . . Type: *ast.StarExpr { + 76 . . . . . Star: - + 77 . . . . . X: *ast.Ident { + 78 . . . . . . NamePos: - + 79 . . . . . . Name: "Workspace" + 80 . . . . . . Obj: *ast.Object { + 81 . . . . . . . Kind: type + 82 . . . . . . . Name: "Workspace" + 83 . . . . . . . Decl: *ast.TypeSpec { + 84 . . . . . . . . Doc: nil + 85 . . . . . . . . Name: *ast.Ident { + 86 . . . . . . . . . NamePos: - + 87 . . . . . . . . . Name: "Workspace" + 88 . . . . . . . . . Obj: *(obj @ 80) + 89 . . . . . . . . } + 90 . . . . . . . . TypeParams: nil + 91 . . . . . . . . Assign: - + 92 . . . . . . . . Type: *ast.StructType { + 93 . . . . . . . . . Struct: - + 94 . . . . . . . . . Fields: *ast.FieldList { + 95 . . . . . . . . . . Opening: - + 96 . . . . . . . . . . List: []*ast.Field (len = 2) { + 97 . . . . . . . . . . . 0: *ast.Field { + 98 . . . . . . . . . . . . Doc: nil + 99 . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 100 . . . . . . . . . . . . . 0: *ast.Ident { + 101 . . . . . . . . . . . . . . NamePos: - + 102 . . . . . . . . . . . . . . Name: "Name" + 103 . . . . . . . . . . . . . . Obj: *ast.Object { + 104 . . . . . . . . . . . . . . . Kind: var + 105 . . . . . . . . . . . . . . . Name: "Name" + 106 . . . . . . . . . . . . . . . Decl: *(obj @ 97) + 107 . . . . . . . . . . . . . . . Data: nil + 108 . . . . . . . . . . . . . . . Type: nil + 109 . . . . . . . . . . . . . . } + 110 . . . . . . . . . . . . . } + 111 . . . . . . . . . . . . } + 112 . . . . . . . . . . . . Type: *ast.Ident { + 113 . . . . . . . . . . . . . NamePos: - + 114 . . . . . . . . . . . . . Name: "string" + 115 . . . . . . . . . . . . . Obj: nil + 116 . . . . . . . . . . . . } + 117 . . . . . . . . . . . . Tag: nil + 118 . . . . . . . . . . . . Comment: nil + 119 . . . . . . . . . . . } + 120 . . . . . . . . . . . 1: *ast.Field { + 121 . . . . . . . . . . . . Doc: nil + 122 . . . . . . . . . . . . Names: []*ast.Ident (len = 1) { + 123 . . . . . . . . . . . . . 0: *ast.Ident { + 124 . . . . . . . . . . . . . . NamePos: - + 125 . . . . . . . . . . . . . . Name: "Path" + 126 . . . . . . . . . . . . . . Obj: *ast.Object { + 127 . . . . . . . . . . . . . . . Kind: var + 128 . . . . . . . . . . . . . . . Name: "Path" + 129 . . . . . . . . . . . . . . . Decl: *(obj @ 120) + 130 . . . . . . . . . . . . . . . Data: nil + 131 . . . . . . . . . . . . . . . Type: nil + 132 . . . . . . . . . . . . . . } + 133 . . . . . . . . . . . . . } + 134 . . . . . . . . . . . . } + 135 . . . . . . . . . . . . Type: *ast.Ident { + 136 . . . . . . . . . . . . . NamePos: - + 137 . . . . . . . . . . . . . Name: "string" + 138 . . . . . . . . . . . . . Obj: nil + 139 . . . . . . . . . . . . } + 140 . . . . . . . . . . . . Tag: nil + 141 . . . . . . . . . . . . Comment: nil + 142 . . . . . . . . . . . } + 143 . . . . . . . . . . } + 144 . . . . . . . . . . Closing: - + 145 . . . . . . . . . } + 146 . . . . . . . . . Incomplete: false + 147 . . . . . . . . } + 148 . . . . . . . . Comment: nil + 149 . . . . . . . } + 150 . . . . . . . Data: nil + 151 . . . . . . . Type: nil + 152 . . . . . . } + 153 . . . . . } + 154 . . . . } + 155 . . . . Tag: nil + 156 . . . . Comment: nil + 157 . . . } + 158 . . . 2: *ast.Field { + 159 . . . . Doc: nil + 160 . . . . Names: []*ast.Ident (len = 1) { + 161 . . . . . 0: *ast.Ident { + 162 . . . . . . NamePos: - + 163 . . . . . . Name: "workspaceList" + 164 . . . . . . Obj: *ast.Object { + 165 . . . . . . . Kind: var + 166 . . . . . . . Name: "workspaceList" + 167 . . . . . . . Decl: *(obj @ 158) + 168 . . . . . . . Data: nil + 169 . . . . . . . Type: nil + 170 . . . . . . } + 171 . . . . . } + 172 . . . . } + 173 . . . . Type: *ast.MapType { + 174 . . . . . Map: - + 175 . . . . . Key: *ast.Ident { + 176 . . . . . . NamePos: - + 177 . . . . . . Name: "string" + 178 . . . . . . Obj: nil + 179 . . . . . } + 180 . . . . . Value: *ast.Ident { + 181 . . . . . . NamePos: - + 182 . . . . . . Name: "string" + 183 . . . . . . Obj: nil + 184 . . . . . } + 185 . . . . } + 186 . . . . Tag: nil + 187 . . . . Comment: *ast.CommentGroup { + 188 . . . . . List: []*ast.Comment (len = 1) { + 189 . . . . . . 0: *ast.Comment { + 190 . . . . . . . Slash: - + 191 . . . . . . . Text: "// Maps Workspace ID to Public Key" + 192 . . . . . . } + 193 . . . . . } + 194 . . . . } + 195 . . . } + 196 . . . 3: *ast.Field { + 197 . . . . Doc: nil + 198 . . . . Names: []*ast.Ident (len = 1) { + 199 . . . . . 0: *ast.Ident { + 200 . . . . . . NamePos: - + 201 . . . . . . Name: "medium" + 202 . . . . . . Obj: *ast.Object { + 203 . . . . . . . Kind: var + 204 . . . . . . . Name: "medium" + 205 . . . . . . . Decl: *(obj @ 196) + 206 . . . . . . . Data: nil + 207 . . . . . . . Type: nil + 208 . . . . . . } + 209 . . . . . } + 210 . . . . } + 211 . . . . Type: *ast.SelectorExpr { + 212 . . . . . X: *ast.Ident { + 213 . . . . . . NamePos: - + 214 . . . . . . Name: "io" + 215 . . . . . . Obj: nil + 216 . . . . . } + 217 . . . . . Sel: *ast.Ident { + 218 . . . . . . NamePos: - + 219 . . . . . . Name: "Medium" + 220 . . . . . . Obj: nil + 221 . . . . . } + 222 . . . . } + 223 . . . . Tag: nil + 224 . . . . Comment: nil + 225 . . . } + 226 . . } + 227 . . Closing: - + 228 . } + 229 . Incomplete: false + 230 } + +``` +Service manages user workspaces. + + + +#### Methods + +- `CreateWorkspace(identifier, password 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: CreateWorkspace creates a new, obfuscated workspace on the local medium. + +- `HandleIPCEvents(c 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "core" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "Core" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +, msg 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "core" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "Message" + 9 . . Obj: nil + 10 . } + 11 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: HandleIPCEvents processes IPC messages, including injecting dependencies on startup. + +- `ServiceStartup( 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "context" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "Context" + 9 . . Obj: nil + 10 . } + 11 } +, 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "application" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "ServiceOptions" + 9 . . Obj: nil + 10 . } + 11 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: ServiceStartup initializes the service, loading the workspace list. + +- `SwitchWorkspace(name 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: SwitchWorkspace changes the active workspace. + +- `WorkspaceFileGet(filename 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: WorkspaceFileGet retrieves a file from the active workspace. + +- `WorkspaceFileSet(filename, content 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: WorkspaceFileSet writes a file to the active workspace. + +- `getWorkspaceDir() 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: getWorkspaceDir retrieves the WorkspaceDir from the config service. + + + +### `type Workspace` +```go +type Workspace 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: []*ast.Field (len = 2) { + 5 . . . 0: *ast.Field { + 6 . . . . Doc: nil + 7 . . . . Names: []*ast.Ident (len = 1) { + 8 . . . . . 0: *ast.Ident { + 9 . . . . . . NamePos: - + 10 . . . . . . Name: "Name" + 11 . . . . . . Obj: *ast.Object { + 12 . . . . . . . Kind: var + 13 . . . . . . . Name: "Name" + 14 . . . . . . . Decl: *(obj @ 5) + 15 . . . . . . . Data: nil + 16 . . . . . . . Type: nil + 17 . . . . . . } + 18 . . . . . } + 19 . . . . } + 20 . . . . Type: *ast.Ident { + 21 . . . . . NamePos: - + 22 . . . . . Name: "string" + 23 . . . . . Obj: nil + 24 . . . . } + 25 . . . . Tag: nil + 26 . . . . Comment: nil + 27 . . . } + 28 . . . 1: *ast.Field { + 29 . . . . Doc: nil + 30 . . . . Names: []*ast.Ident (len = 1) { + 31 . . . . . 0: *ast.Ident { + 32 . . . . . . NamePos: - + 33 . . . . . . Name: "Path" + 34 . . . . . . Obj: *ast.Object { + 35 . . . . . . . Kind: var + 36 . . . . . . . Name: "Path" + 37 . . . . . . . Decl: *(obj @ 28) + 38 . . . . . . . Data: nil + 39 . . . . . . . Type: nil + 40 . . . . . . } + 41 . . . . . } + 42 . . . . } + 43 . . . . Type: *ast.Ident { + 44 . . . . . NamePos: - + 45 . . . . . Name: "string" + 46 . . . . . Obj: nil + 47 . . . . } + 48 . . . . Tag: nil + 49 . . . . Comment: nil + 50 . . . } + 51 . . } + 52 . . Closing: - + 53 . } + 54 . Incomplete: false + 55 } + +``` +Workspace represents a user's workspace. + + + + + +### `type localMedium` +```go +type localMedium 0 *ast.StructType { + 1 . Struct: - + 2 . Fields: *ast.FieldList { + 3 . . Opening: - + 4 . . List: nil + 5 . . Closing: - + 6 . } + 7 . Incomplete: false + 8 } + +``` +localMedium implements the Medium interface for the local disk. + + + +#### Methods + +- `EnsureDir(path 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: EnsureDir creates a directory on the local disk. + +- `FileGet(path 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: FileGet reads a file from the local disk. + +- `FileSet(path, content 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: FileSet writes a file to the local disk. + +- `IsFile(path 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "bool" + 3 . Obj: nil + 4 } +`: IsFile checks if a path exists and is a file on the local disk. + +- `Read(path 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: Read reads a file from the local disk. + +- `Write(path, content 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "string" + 3 . Obj: nil + 4 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: Write writes a file to the local disk. + + + + + +## Functions + +- `NewLocalMedium() 0 *ast.SelectorExpr { + 1 . X: *ast.Ident { + 2 . . NamePos: - + 3 . . Name: "io" + 4 . . Obj: nil + 5 . } + 6 . Sel: *ast.Ident { + 7 . . NamePos: - + 8 . . Name: "Medium" + 9 . . Obj: nil + 10 . } + 11 } +`: NewLocalMedium creates a new instance of the local storage medium. + +- `Register(c 0 *ast.StarExpr { + 1 . Star: - + 2 . X: *ast.SelectorExpr { + 3 . . X: *ast.Ident { + 4 . . . NamePos: - + 5 . . . Name: "core" + 6 . . . Obj: nil + 7 . . } + 8 . . Sel: *ast.Ident { + 9 . . . NamePos: - + 10 . . . Name: "Core" + 11 . . . Obj: nil + 12 . . } + 13 . } + 14 } +) 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "any" + 3 . Obj: nil + 4 } +, 0 *ast.Ident { + 1 . NamePos: - + 2 . Name: "error" + 3 . Obj: nil + 4 } +`: Register is the constructor for dynamic dependency injection (used with core.WithService). It creates a Service instance and initializes its core.Runtime field. Dependencies are injected during ServiceStartup. diff --git a/go.mod b/go.mod index eb8dec3..95fda7a 100644 --- a/go.mod +++ b/go.mod @@ -9,47 +9,48 @@ require ( github.com/pkg/sftp v1.13.10 github.com/skeema/knownhosts v1.3.2 github.com/stretchr/testify v1.11.1 - github.com/wailsapp/wails/v3 v3.0.0-alpha.36 + github.com/wailsapp/wails/v3 v3.0.0-alpha.37 golang.org/x/crypto v0.43.0 golang.org/x/text v0.30.0 ) require ( - dario.cat/mergo v1.0.1 // indirect + dario.cat/mergo v1.0.2 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/bep/debounce v1.2.1 // indirect - github.com/cloudflare/circl v1.6.0 // indirect - github.com/cyphar/filepath-securejoin v0.4.1 // indirect + github.com/cloudflare/circl v1.6.1 // indirect + github.com/cyphar/filepath-securejoin v0.5.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/ebitengine/purego v0.8.2 // indirect + github.com/ebitengine/purego v0.9.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.6.2 // indirect - github.com/go-git/go-git/v5 v5.13.2 // indirect + github.com/go-git/go-git/v5 v5.16.3 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/google/uuid v1.6.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect - github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 // indirect + github.com/kevinburke/ssh_config v1.4.0 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/kr/fs v0.1.0 // indirect github.com/leaanthony/go-ansi-parser v1.6.1 // indirect github.com/leaanthony/u v1.1.1 // indirect - github.com/lmittmann/tint v1.0.7 // indirect + github.com/lmittmann/tint v1.1.2 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/pjbgf/sha1cd v0.3.2 // indirect + github.com/pjbgf/sha1cd v0.5.0 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/samber/lo v1.49.1 // indirect - github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect + github.com/samber/lo v1.52.0 // indirect + github.com/sergi/go-diff v1.4.0 // indirect github.com/wailsapp/go-webview2 v1.0.22 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/net v0.45.0 // indirect + golang.org/x/net v0.46.0 // indirect golang.org/x/sys v0.37.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect diff --git a/go.sum b/go.sum index e73fba2..3d3b5ef 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= -dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= +dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= @@ -15,17 +15,17 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk= -github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= -github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= -github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= +github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= +github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= +github.com/cyphar/filepath-securejoin v0.5.1 h1:eYgfMq5yryL4fbWfkLpFFy2ukSELzaJOTaUTuh+oF48= +github.com/cyphar/filepath-securejoin v0.5.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= -github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/elazarl/goproxy v1.4.0 h1:4GyuSbFa+s26+3rmYNSuUVsx+HgPrV1bk1jXI0l9wjM= -github.com/elazarl/goproxy v1.4.0/go.mod h1:X/5W/t+gzDyLfHW4DrMdpjqYjpXsURlBt9lpBDxZZZQ= +github.com/ebitengine/purego v0.9.0 h1:mh0zpKBIXDceC63hpvPuGLiJ8ZAa3DfrFTudmfi8A4k= +github.com/ebitengine/purego v0.9.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= +github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= @@ -36,8 +36,8 @@ github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UN github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.13.2 h1:7O7xvsK7K+rZPKW6AQR1YyNhfywkv7B8/FsP3ki6Zv0= -github.com/go-git/go-git/v5 v5.13.2/go.mod h1:hWdW5P4YZRjmpGHwRH2v3zkWcNl6HeXaXQEMGb3NJ9A= +github.com/go-git/go-git/v5 v5.16.3 h1:Z8BtvxZ09bYm/yYNgPKCzgWtaRqDTgIKRgIRHBfU6Z8= +github.com/go-git/go-git/v5 v5.16.3/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= @@ -50,10 +50,12 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck= -github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= -github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= -github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ= +github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= +github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= +github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -67,8 +69,8 @@ github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= -github.com/lmittmann/tint v1.0.7 h1:D/0OqWZ0YOGZ6AyC+5Y2kD8PBEzBk6rFHVSfOqCkF9Y= -github.com/lmittmann/tint v1.0.7/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= +github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= @@ -80,8 +82,8 @@ github.com/nicksnyder/go-i18n/v2 v2.6.0 h1:C/m2NNWNiTB6SK4Ao8df5EWm3JETSTIGNXBpM github.com/nicksnyder/go-i18n/v2 v2.6.0/go.mod h1:88sRqr0C6OPyJn0/KRNaEz1uWorjxIKP7rUUcvycecE= github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= -github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= +github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0= +github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -93,12 +95,12 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= -github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= -github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= -github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw= +github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= +github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= +github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg= github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow= @@ -111,8 +113,8 @@ github.com/wailsapp/go-webview2 v1.0.22 h1:YT61F5lj+GGaat5OB96Aa3b4QA+mybD0Ggq6N github.com/wailsapp/go-webview2 v1.0.22/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= -github.com/wailsapp/wails/v3 v3.0.0-alpha.36 h1:GQ8vSrFgafITwMd/p4k+WBjG9K/anma9Pk2eJ/5CLsI= -github.com/wailsapp/wails/v3 v3.0.0-alpha.36/go.mod h1:7i8tSuA74q97zZ5qEJlcVZdnO+IR7LT2KU8UpzYMPsw= +github.com/wailsapp/wails/v3 v3.0.0-alpha.37 h1:/8Lpm36wq0nY6bwlwVW5oBX/CLYTT9Ke95gAemeCjK4= +github.com/wailsapp/wails/v3 v3.0.0-alpha.37/go.mod h1:7i8tSuA74q97zZ5qEJlcVZdnO+IR7LT2KU8UpzYMPsw= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -122,8 +124,8 @@ golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac h1:l5+whBCLH3iH2ZNHYLbAe58bo golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac/go.mod h1:hH+7mtFmImwwcMvScyxUhjuVHR3HGaDPMn9rMSUUbxo= golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= -golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/go.work.sum b/go.work.sum index 7ec8dca..20d0680 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,15 +1,27 @@ +atomicgo.dev/assert v0.0.2/go.mod h1:ut4NcI3QDdJtlmAxQULOmA13Gz6e2DWbSAS8RUOmNYQ= atomicgo.dev/cursor v0.2.0 h1:H6XN5alUJ52FZZUkI7AlJbUc1aW38GWZalpYRPpoPOw= atomicgo.dev/cursor v0.2.0/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU= atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8= atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ= atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs= atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= git.sr.ht/~jackmordaunt/go-toast/v2 v2.0.3 h1:N3IGoHHp9pb6mj1cbXbuaSXV/UMKwmbKLf53nQmtqMA= git.sr.ht/~jackmordaunt/go-toast/v2 v2.0.3/go.mod h1:QtOLZGz8olr4qH2vWK0QH0w0O4T9fEIjMuWpKUsH7nc= github.com/AlekSi/pointer v1.2.0 h1:glcy/gc4h8HnG2Z3ZECSzZ1IX1x2JxRVuDzaJwQE0+w= github.com/AlekSi/pointer v1.2.0/go.mod h1:gZGfd3dpW4vEc/UlyfKKi1roIqcCgwOIvb0tSNSBle0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Ladicle/tabwriter v1.0.0 h1:DZQqPvMumBDwVNElso13afjYLNp0Z7pHqHnu0r4t9Dg= github.com/Ladicle/tabwriter v1.0.0/go.mod h1:c4MdCjxQyTbGuQO/gvqJ+IA/89UEwrsD6hUCW98dyp4= +github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= +github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8= +github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII= +github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k= +github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI= +github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c= +github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE= +github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= @@ -18,26 +30,39 @@ github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7r github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= +github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= +github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f/go.mod h1:gcr0kNtGBqin9zDW9GOHcVntrwnjrK+qdJ06mWYBybw= +github.com/ProtonMail/gopenpgp/v2 v2.7.1/go.mod h1:/BU5gfAVwqyd8EfC3Eu7zmuhwYQpKs+cGD8M//iiaxs= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/chroma/v2 v2.15.0 h1:LxXTQHFoYrstG2nnV9y2X5O94sOBzf0CIUpSTbpxvMc= github.com/alecthomas/chroma/v2 v2.15.0/go.mod h1:gUhVLrPDXPtp/f+L1jo9xepo9gL4eLwRuGAunSZMkio= +github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/atterpac/refresh v0.8.6 h1:Q5miKV2qs9jW+USw8WZ/54Zz8/RSh/bOz5U6JvvDZmM= github.com/atterpac/refresh v0.8.6/go.mod h1:fJpWySLdpbANS8Ej5OvfZVZIVvi/9bmnhTjKS5EjQes= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCkcs2uw7w4= github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4= github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bwesterb/go-ristretto v1.2.3 h1:1w53tCkGhCQ5djbat3+MH0BAQ5Kfgbt56UZQ/JMzngw= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/caarlos0/go-version v0.2.0/go.mod h1:X+rI5VAtJDpcjCjeEIXpxGa5+rTcgur1FK66wS0/944= +github.com/caarlos0/testfs v0.4.4/go.mod h1:bRN55zgG4XCUVVHZCeU+/Tz1Q6AxEJOEJTliBy+1DMk= github.com/cavaliergopher/cpio v1.0.1 h1:KQFSeKmZhv0cr+kawA3a0xTQCU4QxXF1vhU7P7av2KM= github.com/cavaliergopher/cpio v1.0.1/go.mod h1:pBdaqQjnvXxdS/6CvNDwIANIFSP0xRKI16PX4xejRQc= github.com/chainguard-dev/git-urls v1.0.2 h1:pSpT7ifrpc5X55n4aTTm7FFUE+ZQHKiqpiwNkJrVcKQ= github.com/chainguard-dev/git-urls v1.0.2/go.mod h1:rbGgj10OS7UgZlbzdUQIQpT0k/D4+An04HJY7Ol+Y/o= +github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw= +github.com/charmbracelet/bubbletea v0.25.0/go.mod h1:EN3QDR1T5ZdWmdfDzYcqOCAps45+QIJbLOBxmVNWNNg= github.com/charmbracelet/glamour v0.9.0 h1:1Hm3wxww7qXvGI+Fb3zDmIZo5oDOvVOWJ4OrIB+ef7c= github.com/charmbracelet/glamour v0.9.0/go.mod h1:+SHvIS8qnwhgTpVMiXwn7OfGomSqff1cHBCI8jLOetk= github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99klV19u0QnhiizODirwVksQB91TJKV/UaTnACcG30= @@ -46,9 +71,13 @@ github.com/charmbracelet/x/input v0.1.0 h1:TEsGSfZYQyOtp+STIjyBq6tpRaorH0qpwZUj8 github.com/charmbracelet/x/input v0.1.0/go.mod h1:ZZwaBxPF7IG8gWWzPUVqHEtWhc1+HXJPNuerJGRGZ28= github.com/charmbracelet/x/windows v0.1.0 h1:gTaxdvzDM5oMa/I2ZNF7wN78X/atWemG9Wph7Ika2k4= github.com/charmbracelet/x/windows v0.1.0/go.mod h1:GLEO/l+lizvFDBPLIOk+49gdX49L9YWMB5t+DZd0jkQ= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= @@ -58,6 +87,9 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= @@ -68,14 +100,18 @@ github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/rpmpack v0.6.1-0.20240329070804-c2247cbb881a h1:JJBdjSfqSy3mnDT0940ASQFghwcZ4y4cb6ttjAoXqwE= github.com/google/rpmpack v0.6.1-0.20240329070804-c2247cbb881a/go.mod h1:uqVAUVQLq8UY2hCDfmJ/+rtO3aw7qyhc90rCVEabEfI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= +github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= +github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/goreleaser/chglog v0.6.2 h1:qroqdMHzwoAPTHHzJtbCfYbwg/yWJrNQApZ6IQAq8bU= github.com/goreleaser/chglog v0.6.2/go.mod h1:BP0xQQc6B8aM+4dhvSLlVTv0rvhuOF0JacDO1+h7L3U= github.com/goreleaser/fileglob v1.3.0 h1:/X6J7U8lbDpQtBvGcwwPS6OpzkNVlVEsFUVRx9+k+7I= @@ -84,28 +120,44 @@ github.com/goreleaser/nfpm/v2 v2.41.3 h1:IRRsqv5NgiCKUy57HjQgfVBFb44VH8+r1mWeEF8 github.com/goreleaser/nfpm/v2 v2.41.3/go.mod h1:0t54RfPX6/iKANsVLbB3XgtfQXzG1nS4HmSavN92qVY= github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/jackmordaunt/icns/v2 v2.2.7 h1:K/RbfvuzjmjVY5y4g+XENRs8ZZatwz4YnLHypa2KwQg= github.com/jackmordaunt/icns/v2 v2.2.7/go.mod h1:ovoTxGguSuoUGKMk5Nn3R7L7BgMQkylsO+bblBuI22A= github.com/jaypipes/ghw v0.17.0 h1:EVLJeNcy5z6GK/Lqby0EhBpynZo+ayl8iJWY0kbEUJA= github.com/jaypipes/ghw v0.17.0/go.mod h1:In8SsaDqlb1oTyrbmTC14uy+fbBMvp+xdqX51MidlD8= github.com/jaypipes/pcidb v1.0.1 h1:WB2zh27T3nwg8AE8ei81sNRb9yWBii3JGNJtT7K9Oic= github.com/jaypipes/pcidb v1.0.1/go.mod h1:6xYUz/yYEyOkIkUt2t2J2folIuZ4Yg6uByCGFXMCeE4= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= +github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= -github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY= +github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ= github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU= github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= +github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-zglob v0.0.6 h1:mP8RnmCgho4oaUYDIDn6GNxYk+qJGUs8fJLn+twYj2A= github.com/mattn/go-zglob v0.0.6/go.mod h1:MxxjyoXXnMxfIpxTK2GAkw1w8glPsQILx3N5wrKakiY= github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= @@ -116,79 +168,169 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= +github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= +github.com/muesli/mango v0.1.0/go.mod h1:5XFpbC8jY5UUv89YQciiXNlbi+iJgt29VDC5xbzrLL4= +github.com/muesli/mango-cobra v1.2.0/go.mod h1:vMJL54QytZAJhCT13LPVDfkvCUJ5/4jNUKF/8NC2UjA= +github.com/muesli/mango-pflag v0.1.0/go.mod h1:YEQomTxaCUp8PrbhFh10UfbhbQrM/xJ4i2PB8VTLLW0= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= +github.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= +github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= +github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= +github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU= +github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= +github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= +github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s= github.com/pterm/pterm v0.12.80 h1:mM55B+GnKUnLMUSqhdINe4s6tOuVQIetQ3my8JGyAIg= github.com/pterm/pterm v0.12.80/go.mod h1:c6DeF9bSnOSeFPZlfs4ZRAFcf5SCoTwvwQ5xaKGQlHo= github.com/radovskyb/watcher v1.0.7 h1:AYePLih6dpmS32vlHfhCeli8127LzkIgwJGcwwe8tUE= github.com/radovskyb/watcher v1.0.7/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rjeczalik/notify v0.9.3 h1:6rJAzHTGKXGj76sbRgDiDcYj/HniypXmSJo1SWakZeY= github.com/rjeczalik/notify v0.9.3/go.mod h1:gF3zSOrafR9DQEWSE8TjfI9NkooDxbyT4UgRGKZA0lc= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= github.com/sajari/fuzzy v1.0.0 h1:+FmwVvJErsd0d0hAPlj4CxqxUtQY/fOoY0DwX4ykpRY= github.com/sajari/fuzzy v1.0.0/go.mod h1:OjYR6KxoWOe9+dOlXeiCJd4dIbED4Oo8wpS89o0pwOo= +github.com/sassoftware/go-rpmutils v0.4.0/go.mod h1:3goNWi7PGAT3/dlql2lv3+MSN5jNYPjT5mVcQcIsYzI= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= +github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= +github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tc-hib/winres v0.3.1 h1:CwRjEGrKdbi5CvZ4ID+iyVhgyfatxFoizjPhzez9Io4= github.com/tc-hib/winres v0.3.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk= github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/wailsapp/task/v3 v3.40.1-patched3 h1:i6O1WNdSur9CGaiMDIYGjsmj/qS4465zqv+WEs6sPRs= github.com/wailsapp/task/v3 v3.40.1-patched3/go.mod h1:jIP48r8ftoSQNlxFP4+aEnkvGQqQXqCnRi/B7ROaecE= +github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= +github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic= github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark-emoji v1.0.5 h1:EMVWyCGPlXJfUXBXpuMu+ii3TIaxbVBnEX9uaDC4cIk= github.com/yuin/goldmark-emoji v1.0.5/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U= +github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= gitlab.com/digitalxero/go-conventional-commit v1.0.7 h1:8/dO6WWG+98PMhlZowt/YjuiKhqhGlOCwlIV8SqqGh8= gitlab.com/digitalxero/go-conventional-commit v1.0.7/go.mod h1:05Xc2BFsSyC5tKhK0y+P3bs0AwUtNuTp+mTpbCU/DZ0= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +golang.org/x/crypto v0.11.1-0.20230711161743-2e82bdd1719d/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac h1:TSSpLIG4v+p0rPv1pNOQtl1I8knsO4S9trOxNMOLVP4= golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ= golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8= golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM= howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y= +modernc.org/cc/v4 v4.24.4/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= +modernc.org/ccgo/v3 v3.17.0/go.mod h1:Sg3fwVpmLvCUTaqEUjiBDAvshIaKDB0RXaf+zgqFu8I= +modernc.org/ccgo/v4 v4.23.16/go.mod h1:nNma8goMTY7aQZQNTyN9AIoJfxav4nvTnvKThAeMDdo= +modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= +modernc.org/gc/v2 v2.6.3/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= modernc.org/libc v1.61.13 h1:3LRd6ZO1ezsFiX1y+bHd1ipyEHIJKvuprv0sLTBwLW8= modernc.org/libc v1.61.13/go.mod h1:8F/uJWL/3nNil0Lgt1Dpz+GgkApWh04N3el3hxJcA6E= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= modernc.org/memory v1.8.2 h1:cL9L4bcoAObu4NkxOlKWBWtNHIsnnACGF/TbqQ6sbcI= modernc.org/memory v1.8.2/go.mod h1:ZbjSvMO5NQ1A2i3bWeDiVMxIorXwdClKE/0SZ+BMotU= +modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= +modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= modernc.org/sqlite v1.36.0 h1:EQXNRn4nIS+gfsKeUTymHIz1waxuv5BzU7558dHSfH8= modernc.org/sqlite v1.36.0/go.mod h1:7MPwH7Z6bREicF9ZVUR78P1IKuxfZ8mRIDHD0iD+8TU= +modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= mvdan.cc/editorconfig v0.3.0 h1:D1D2wLYEYGpawWT5SpM5pRivgEgXjtEXwC9MWhEY0gQ= mvdan.cc/editorconfig v0.3.0/go.mod h1:NcJHuDtNOTEJ6251indKiWuzK6+VcrMuLzGMLKBFupQ= mvdan.cc/sh/v3 v3.10.0 h1:v9z7N1DLZ7owyLM/SXZQkBSXcwr2IGMm2LY2pmhVXj4= diff --git a/help/help.go b/help/help.go deleted file mode 100644 index 371f47b..0000000 --- a/help/help.go +++ /dev/null @@ -1,27 +0,0 @@ -// package help provides the public API for the help service. -package help - -import ( - // Import the internal implementation with an alias. - impl "github.com/Snider/Core/pkg/help" - - // Import the core contracts to re-export the interface. - "github.com/Snider/Core/pkg/core" -) - -// Options is the public type for the Options service. It is a type alias -// to the underlying implementation, making it transparent to the user. -type Options = impl.Options - -// Service is the public type for the Service service. It is a type alias -// to the underlying implementation, making it transparent to the user. -type Service = impl.Service - -// New is a public function that points to the real function in the implementation package. -var New = impl.New - -// Register is a public function that points to the real function in the implementation package. -var Register = impl.Register - -// Help is the public interface for the help service. -type Help = core.Help diff --git a/help/help_test.go b/help/help_test.go deleted file mode 100644 index 50eb07b..0000000 --- a/help/help_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package help_test - -import ( - "testing" - - "github.com/Snider/Core/help" - "github.com/Snider/Core/pkg/core" -) - -// TestNew ensures that the public constructor New is available. -func TestNew(t *testing.T) { - if help.New == nil { - t.Fatal("help.New constructor is nil") - } - // Note: This is a basic check. Some services may require a core instance - // or other arguments. This test can be expanded as needed. -} - -// TestRegister ensures that the public factory Register is available. -func TestRegister(t *testing.T) { - if help.Register == nil { - t.Fatal("help.Register factory is nil") - } -} - -// TestInterfaceCompliance ensures that the public Service type correctly -// implements the public Help interface. This is a compile-time check. -func TestInterfaceCompliance(t *testing.T) { - // This is a compile-time check. If it compiles, the test passes. - var _ core.Help = (*help.Service)(nil) -} diff --git a/i18n/i18n.go b/i18n/i18n.go deleted file mode 100644 index bfea9b7..0000000 --- a/i18n/i18n.go +++ /dev/null @@ -1,27 +0,0 @@ -// package i18n provides the public API for the i18n service. -package i18n - -import ( - // Import the internal implementation with an alias. - impl "github.com/Snider/Core/pkg/i18n" - - // Import the core contracts to re-export the interface. - "github.com/Snider/Core/pkg/core" -) - -// New is a public function that points to the real function in the implementation package. -var New = impl.New - -// Register is a public function that points to the real function in the implementation package. -var Register = impl.Register - -// Options is the public type for the Options service. It is a type alias -// to the underlying implementation, making it transparent to the user. -type Options = impl.Options - -// Service is the public type for the Service service. It is a type alias -// to the underlying implementation, making it transparent to the user. -type Service = impl.Service - -// I18n is the public interface for the i18n service. -type I18n = core.I18n diff --git a/i18n/i18n_test.go b/i18n/i18n_test.go deleted file mode 100644 index 20752cf..0000000 --- a/i18n/i18n_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package i18n_test - -import ( - "testing" - - "github.com/Snider/Core/i18n" - "github.com/Snider/Core/pkg/core" -) - -// TestNew ensures that the public constructor New is available. -func TestNew(t *testing.T) { - if i18n.New == nil { - t.Fatal("i18n.New constructor is nil") - } - // Note: This is a basic check. Some services may require a core instance - // or other arguments. This test can be expanded as needed. -} - -// TestRegister ensures that the public factory Register is available. -func TestRegister(t *testing.T) { - if i18n.Register == nil { - t.Fatal("i18n.Register factory is nil") - } -} - -// TestInterfaceCompliance ensures that the public Service type correctly -// implements the public I18n interface. This is a compile-time check. -func TestInterfaceCompliance(t *testing.T) { - // This is a compile-time check. If it compiles, the test passes. - var _ core.I18n = (*i18n.Service)(nil) -} diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..5902fdd --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,39 @@ +site_name: Core Library Documentation +site_description: 'Developer documentation for the Core library, a framework for building Go desktop apps with Wails.' +site_author: 'The Core Team' +repo_url: 'https://github.com/Snider/Core' +repo_name: 'Snider/Core' + +theme: + name: material + palette: + # Palette toggle for light vs dark mode + - scheme: default + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - scheme: slate + toggle: + icon: material/brightness-4 + name: Switch to light mode + features: + - navigation.tabs + - navigation.sections + - toc.integrate + - navigation.top + - search.suggest + - search.highlight + - content.tabs.link + +nav: + - 'Overview': 'index.md' + - 'Services': + - 'Runtime': 'services/runtime.md' + - 'Config': 'services/config.md' + - 'Crypt': 'services/crypt.md' + - 'Display': 'services/display.md' + - 'Error Handling': 'services/e.md' + - 'Help': 'services/help.md' + - 'I18n': 'services/i18n.md' + - 'IO': 'services/io.md' + - 'Workspace': 'services/workspace.md' diff --git a/pkg/config/config.go b/pkg/config/config.go index eba202e..ee27ed1 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -1,188 +1,22 @@ package config import ( - "encoding/json" - "errors" - "fmt" - "os" - "path/filepath" - "reflect" - "strings" - + "github.com/Snider/Core/pkg/config/internal" "github.com/Snider/Core/pkg/core" - "github.com/adrg/xdg" ) -const appName = "lethean" -const configFileName = "config.json" - // Options holds configuration for the config service. -type Options struct{} +type Options = internal.Options // Service provides access to the application's configuration. -// It handles loading, saving, and providing access to configuration values. -type Service struct { - *core.Runtime[Options] `json:"-"` - - // Persistent fields, saved to config.json. - ConfigPath string `json:"configPath,omitempty"` - UserHomeDir string `json:"userHomeDir,omitempty"` - RootDir string `json:"rootDir,omitempty"` - CacheDir string `json:"cacheDir,omitempty"` - ConfigDir string `json:"configDir,omitempty"` - DataDir string `json:"dataDir,omitempty"` - WorkspaceDir string `json:"workspaceDir,omitempty"` - DefaultRoute string `json:"default_route"` - Features []string `json:"features"` - Language string `json:"language"` -} - -// createServiceInstance contains the common logic for initializing a Service struct. -func createServiceInstance() (*Service, error) { - // --- Path and Directory Setup --- - homeDir, err := os.UserHomeDir() - if err != nil { - return nil, fmt.Errorf("could not resolve user home directory: %w", err) - } - userHomeDir := filepath.Join(homeDir, appName) - - rootDir, err := xdg.DataFile(appName) - if err != nil { - return nil, fmt.Errorf("could not resolve data directory: %w", err) - } - - cacheDir, err := xdg.CacheFile(appName) - if err != nil { - return nil, fmt.Errorf("could not resolve cache directory: %w", err) - } - - s := &Service{ - UserHomeDir: userHomeDir, - RootDir: rootDir, - CacheDir: cacheDir, - ConfigDir: filepath.Join(userHomeDir, "config"), - DataDir: filepath.Join(userHomeDir, "data"), - WorkspaceDir: filepath.Join(userHomeDir, "workspace"), - DefaultRoute: "/", - Features: []string{}, - Language: "en", - } - s.ConfigPath = filepath.Join(s.ConfigDir, configFileName) - - dirs := []string{s.RootDir, s.ConfigDir, s.DataDir, s.CacheDir, s.WorkspaceDir, s.UserHomeDir} - for _, dir := range dirs { - if err := os.MkdirAll(dir, os.ModePerm); err != nil { - return nil, fmt.Errorf("could not create directory %s: %w", dir, err) - } - } - - // --- Load or Create Configuration --- - if data, err := os.ReadFile(s.ConfigPath); err == nil { - // Config file exists, load it. - if err := json.Unmarshal(data, s); err != nil { - return nil, fmt.Errorf("failed to unmarshal config: %w", err) - } - } else if os.IsNotExist(err) { - // Config file does not exist, create it with default values. - if err := s.Save(); err != nil { - return nil, fmt.Errorf("failed to create default config file: %w", err) - } - } else { - // Another error occurred reading the file. - return nil, fmt.Errorf("failed to read config file: %w", err) - } - - return s, nil -} +type Service = internal.Service // New is the constructor for static dependency injection. -// It creates a Service instance without initializing the core.Runtime field. func New() (*Service, error) { - return createServiceInstance() + return internal.New() } -// Register is the constructor for dynamic dependency injection (used with core.WithService). -// It creates a Service instance and initializes its core.Runtime field. +// Register is the constructor for dynamic dependency injection. func Register(c *core.Core) (any, error) { - s, err := createServiceInstance() - if err != nil { - return nil, err - } - // Defensive check: createServiceInstance should not return nil service with nil error - if s == nil { - return nil, errors.New("config: createServiceInstance returned a nil service instance with no error") - } - s.Runtime = core.NewRuntime(c, Options{}) - return s, nil -} - -// Save writes the current configuration to config.json. -func (s *Service) Save() error { - data, err := json.MarshalIndent(s, "", " ") - if err != nil { - return fmt.Errorf("failed to marshal config: %w", err) - } - - if err := os.WriteFile(s.ConfigPath, data, 0644); err != nil { - return fmt.Errorf("failed to write config file: %w", err) - } - return nil -} - -// Get retrieves a configuration value by its key. -func (s *Service) Get(key string, out any) error { - val := reflect.ValueOf(s).Elem() - typ := val.Type() - - for i := 0; i < val.NumField(); i++ { - field := typ.Field(i) - jsonTag := field.Tag.Get("json") - if jsonTag != "" && jsonTag != "-" { - jsonName := strings.Split(jsonTag, ",")[0] - if strings.EqualFold(jsonName, key) { - outVal := reflect.ValueOf(out) - if outVal.Kind() != reflect.Ptr || outVal.IsNil() { - return errors.New("output argument must be a non-nil pointer") - } - targetVal := outVal.Elem() - srcVal := val.Field(i) - - if !srcVal.Type().AssignableTo(targetVal.Type()) { - return fmt.Errorf("cannot assign config value of type %s to output of type %s", srcVal.Type(), targetVal.Type()) - } - targetVal.Set(srcVal) - return nil - } - } - } - - return fmt.Errorf("key '%s' not found in config", key) -} - -// Set updates a configuration value and saves the config. -func (s *Service) Set(key string, v any) error { - val := reflect.ValueOf(s).Elem() - typ := val.Type() - - for i := 0; i < val.NumField(); i++ { - field := typ.Field(i) - jsonTag := field.Tag.Get("json") - if jsonTag != "" && jsonTag != "-" { - jsonName := strings.Split(jsonTag, ",")[0] - if strings.EqualFold(jsonName, key) { - fieldVal := val.Field(i) - if !fieldVal.CanSet() { - return fmt.Errorf("cannot set config field for key '%s'", key) - } - newVal := reflect.ValueOf(v) - if !newVal.Type().AssignableTo(fieldVal.Type()) { - return fmt.Errorf("type mismatch for key '%s': expected %s, got %s", key, fieldVal.Type(), newVal.Type()) - } - fieldVal.Set(newVal) - return s.Save() - } - } - } - - return fmt.Errorf("key '%s' not found in config", key) + return internal.Register(c) } diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go deleted file mode 100644 index 6ca52f2..0000000 --- a/pkg/config/config_test.go +++ /dev/null @@ -1,132 +0,0 @@ -package config - -import ( - "os" - "path/filepath" - "testing" - - "github.com/Snider/Core/pkg/core" -) - -// setupTestEnv creates a temporary home directory for testing and ensures a clean environment. -func setupTestEnv(t *testing.T) (string, func()) { - tempHomeDir, err := os.MkdirTemp("", "test_home_*") - if err != nil { - t.Fatalf("Failed to create temp home directory: %v", err) - } - - oldHome := os.Getenv("HOME") - os.Setenv("HOME", tempHomeDir) - - // Unset XDG vars to ensure HOME is used for path resolution, creating a hermetic test. - oldXdgData := os.Getenv("XDG_DATA_HOME") - oldXdgCache := os.Getenv("XDG_CACHE_HOME") - os.Unsetenv("XDG_DATA_HOME") - os.Unsetenv("XDG_CACHE_HOME") - - cleanup := func() { - os.Setenv("HOME", oldHome) - os.Setenv("XDG_DATA_HOME", oldXdgData) - os.Setenv("XDG_CACHE_HOME", oldXdgCache) - os.RemoveAll(tempHomeDir) - } - - return tempHomeDir, cleanup -} - -// newTestCore creates a new, empty core instance for testing. -func newTestCore(t *testing.T) *core.Core { - c, err := core.New() - if err != nil { - t.Fatalf("core.New() failed: %v", err) - } - if c == nil { - t.Fatalf("core.New() returned a nil instance") - } - return c -} - -func TestConfigService(t *testing.T) { - t.Run("New service creates default config", func(t *testing.T) { - _, cleanup := setupTestEnv(t) - defer cleanup() - - serviceInstance, err := New() - if err != nil { - t.Fatalf("New() failed: %v", err) - } - - // Check that the config file was created - if _, err := os.Stat(serviceInstance.ConfigPath); os.IsNotExist(err) { - t.Errorf("config.json was not created at %s", serviceInstance.ConfigPath) - } - - // Check default values - if serviceInstance.Language != "en" { - t.Errorf("Expected default language 'en', got '%s'", serviceInstance.Language) - } - }) - - t.Run("New service loads existing config", func(t *testing.T) { - tempHomeDir, cleanup := setupTestEnv(t) - defer cleanup() - - // Manually create a config file with non-default values - configDir := filepath.Join(tempHomeDir, appName, "config") - if err := os.MkdirAll(configDir, os.ModePerm); err != nil { - t.Fatalf("Failed to create test config dir: %v", err) - } - configPath := filepath.Join(configDir, configFileName) - - customConfig := `{"language": "fr", "features": ["beta-testing"]}` - if err := os.WriteFile(configPath, []byte(customConfig), 0644); err != nil { - t.Fatalf("Failed to write custom config file: %v", err) - } - - serviceInstance, err := New() - if err != nil { - t.Fatalf("New() failed while loading existing config: %v", err) - } - - if serviceInstance.Language != "fr" { - t.Errorf("Expected language 'fr', got '%s'", serviceInstance.Language) - } - // A check for IsFeatureEnabled would require a proper core instance and service registration. - // This is a simplified check for now. - found := false - for _, f := range serviceInstance.Features { - if f == "beta-testing" { - found = true - break - } - } - if !found { - t.Errorf("Expected 'beta-testing' feature to be enabled") - } - }) - - t.Run("Set and Get", func(t *testing.T) { - _, cleanup := setupTestEnv(t) - defer cleanup() - - s, err := New() - if err != nil { - t.Fatalf("New() failed: %v", err) - } - - key := "language" - expectedValue := "de" - if err := s.Set(key, expectedValue); err != nil { - t.Fatalf("Set() failed: %v", err) - } - - var actualValue string - if err := s.Get(key, &actualValue); err != nil { - t.Fatalf("Get() failed: %v", err) - } - - if actualValue != expectedValue { - t.Errorf("Expected value '%s', got '%s'", expectedValue, actualValue) - } - }) -} diff --git a/pkg/config/internal/config_test.go b/pkg/config/internal/config_test.go new file mode 100644 index 0000000..71e00d4 --- /dev/null +++ b/pkg/config/internal/config_test.go @@ -0,0 +1,184 @@ +package internal + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// setupTestEnv creates a temporary home directory for testing and ensures a clean environment. +func setupTestEnv(t *testing.T) (string, func()) { + tempHomeDir, err := os.MkdirTemp("", "test_home_*") + require.NoError(t, err, "Failed to create temp home directory") + + oldHome := os.Getenv("HOME") + os.Setenv("HOME", tempHomeDir) + + // Unset XDG vars to ensure HOME is used for path resolution, creating a hermetic test. + oldXdgData, hadXdgData := os.LookupEnv("XDG_DATA_HOME") + oldXdgCache, hadXdgCache := os.LookupEnv("XDG_CACHE_HOME") + require.NoError(t, os.Unsetenv("XDG_DATA_HOME")) + require.NoError(t, os.Unsetenv("XDG_CACHE_HOME")) + + cleanup := func() { + os.Setenv("HOME", oldHome) + if hadXdgData { + os.Setenv("XDG_DATA_HOME", oldXdgData) + } else { + os.Unsetenv("XDG_DATA_HOME") + } + if hadXdgCache { + os.Setenv("XDG_CACHE_HOME", oldXdgCache) + } else { + os.Unsetenv("XDG_CACHE_HOME") + } + os.RemoveAll(tempHomeDir) + } + + return tempHomeDir, cleanup +} + +func TestConfigService(t *testing.T) { + t.Run("New service creates default config", func(t *testing.T) { + _, cleanup := setupTestEnv(t) + defer cleanup() + + serviceInstance, err := New() + require.NoError(t, err, "New() failed") + + // Check that the config file was created + assert.FileExists(t, serviceInstance.ConfigPath, "config.json was not created") + + // Check default values + assert.Equal(t, "en", serviceInstance.Language, "Expected default language 'en'") + }) + + t.Run("New service loads existing config", func(t *testing.T) { + tempHomeDir, cleanup := setupTestEnv(t) + defer cleanup() + + // Manually create a config file with non-default values + configDir := filepath.Join(tempHomeDir, appName, "config") + require.NoError(t, os.MkdirAll(configDir, os.ModePerm), "Failed to create test config dir") + configPath := filepath.Join(configDir, configFileName) + + customConfig := `{"language": "fr", "features": ["beta-testing"]}` + require.NoError(t, os.WriteFile(configPath, []byte(customConfig), 0644), "Failed to write custom config file") + + serviceInstance, err := New() + require.NoError(t, err, "New() failed while loading existing config") + + assert.Equal(t, "fr", serviceInstance.Language, "Expected language 'fr'") + assert.True(t, serviceInstance.IsFeatureEnabled("beta-testing"), "Expected 'beta-testing' feature to be enabled") + assert.False(t, serviceInstance.IsFeatureEnabled("alpha-testing"), "Did not expect 'alpha-testing' to be enabled") + }) + + t.Run("Set and Get", func(t *testing.T) { + _, cleanup := setupTestEnv(t) + defer cleanup() + + s, err := New() + require.NoError(t, err, "New() failed") + + key := "language" + expectedValue := "de" + require.NoError(t, s.Set(key, expectedValue), "Set() failed") + + var actualValue string + require.NoError(t, s.Get(key, &actualValue), "Get() failed") + assert.Equal(t, expectedValue, actualValue, "Get() returned unexpected value") + }) +} + +func TestIsFeatureEnabled(t *testing.T) { + _, cleanup := setupTestEnv(t) + defer cleanup() + + s, err := New() + require.NoError(t, err) + + // Test with no features enabled + assert.False(t, s.IsFeatureEnabled("beta-feature")) + + // Enable a feature + s.Features = []string{"beta-feature", "alpha-testing"} + + // Test for an enabled feature + assert.True(t, s.IsFeatureEnabled("beta-feature")) + + // Test for another enabled feature + assert.True(t, s.IsFeatureEnabled("alpha-testing")) + + // Test for a disabled feature + assert.False(t, s.IsFeatureEnabled("gamma-feature")) + + // Test with an empty string + assert.False(t, s.IsFeatureEnabled("")) + + // Test with a nil slice + s.Features = nil + assert.False(t, s.IsFeatureEnabled("beta-feature")) +} + +func TestSet_Good(t *testing.T) { + _, cleanup := setupTestEnv(t) + defer cleanup() + + s, err := New() + require.NoError(t, err, "New() failed") + + // Test setting a string value + err = s.Set("language", "de") + assert.NoError(t, err) + var lang string + err = s.Get("language", &lang) + assert.NoError(t, err) + assert.Equal(t, "de", lang) + + // Test setting a slice value + err = s.Set("features", []string{"new-feature"}) + assert.NoError(t, err) + var features []string + err = s.Get("features", &features) + assert.NoError(t, err) + assert.Equal(t, []string{"new-feature"}, features) +} + +func TestSet_Bad(t *testing.T) { + _, cleanup := setupTestEnv(t) + defer cleanup() + + s, err := New() + require.NoError(t, err, "New() failed") + + // Test setting a value with the wrong type + err = s.Set("language", 123) + assert.Error(t, err) + + // Test setting a non-existent key + err = s.Set("nonExistentKey", "value") + assert.Error(t, err) +} + +func TestSet_Ugly(t *testing.T) { + _, cleanup := setupTestEnv(t) + defer cleanup() + + s, err := New() + require.NoError(t, err, "New() failed") + + // This should not panic + assert.NotPanics(t, func() { + err = s.Set("features", nil) + }) + assert.NoError(t, err) + + // Verify the slice is now nil + var features []string + err = s.Get("features", &features) + assert.NoError(t, err) + assert.Nil(t, features) +} diff --git a/pkg/config/internal/service.go b/pkg/config/internal/service.go new file mode 100644 index 0000000..ed5964a --- /dev/null +++ b/pkg/config/internal/service.go @@ -0,0 +1,207 @@ +package internal + +import ( + "encoding/json" + "errors" + "fmt" + "os" + "path/filepath" + "reflect" + "strings" + + "github.com/Snider/Core/pkg/core" + "github.com/adrg/xdg" +) + +const appName = "lethean" +const configFileName = "config.json" + +// Options holds configuration for the config service. +type Options struct{} + +// Service provides access to the application's configuration. +// It handles loading, saving, and providing access to configuration values. +type Service struct { + *core.Runtime[Options] `json:"-"` + + // Persistent fields, saved to config.json. + ConfigPath string `json:"configPath,omitempty"` + UserHomeDir string `json:"userHomeDir,omitempty"` + RootDir string `json:"rootDir,omitempty"` + CacheDir string `json:"cacheDir,omitempty"` + ConfigDir string `json:"configDir,omitempty"` + DataDir string `json:"dataDir,omitempty"` + WorkspaceDir string `json:"workspaceDir,omitempty"` + DefaultRoute string `json:"default_route"` + Features []string `json:"features"` + Language string `json:"language"` +} + +// createServiceInstance contains the common logic for initializing a Service struct. +func createServiceInstance() (*Service, error) { + // --- Path and Directory Setup --- + homeDir, err := os.UserHomeDir() + if err != nil { + return nil, fmt.Errorf("could not resolve user home directory: %w", err) + } + userHomeDir := filepath.Join(homeDir, appName) + + rootDir, err := xdg.DataFile(appName) + if err != nil { + return nil, fmt.Errorf("could not resolve data directory: %w", err) + } + + cacheDir, err := xdg.CacheFile(appName) + if err != nil { + return nil, fmt.Errorf("could not resolve cache directory: %w", err) + } + + s := &Service{ + UserHomeDir: userHomeDir, + RootDir: rootDir, + CacheDir: cacheDir, + ConfigDir: filepath.Join(userHomeDir, "config"), + DataDir: filepath.Join(userHomeDir, "data"), + WorkspaceDir: filepath.Join(userHomeDir, "workspace"), + DefaultRoute: "/", + Features: []string{}, + Language: "en", + } + s.ConfigPath = filepath.Join(s.ConfigDir, configFileName) + + dirs := []string{s.RootDir, s.ConfigDir, s.DataDir, s.CacheDir, s.WorkspaceDir, s.UserHomeDir} + for _, dir := range dirs { + if err := os.MkdirAll(dir, os.ModePerm); err != nil { + return nil, fmt.Errorf("could not create directory %s: %w", dir, err) + } + } + + // --- Load or Create Configuration --- + if data, err := os.ReadFile(s.ConfigPath); err == nil { + // Config file exists, load it. + if err := json.Unmarshal(data, s); err != nil { + return nil, fmt.Errorf("failed to unmarshal config: %w", err) + } + } else if os.IsNotExist(err) { + // Config file does not exist, create it with default values. + if err := s.Save(); err != nil { + return nil, fmt.Errorf("failed to create default config file: %w", err) + } + } else { + // Another error occurred reading the file. + return nil, fmt.Errorf("failed to read config file: %w", err) + } + + return s, nil +} + +// New is the constructor for static dependency injection. +// It creates a Service instance without initializing the core.Runtime field. +func New() (*Service, error) { + return createServiceInstance() +} + +// Register is the constructor for dynamic dependency injection (used with core.WithService). +// It creates a Service instance and initializes its core.Runtime field. +func Register(c *core.Core) (any, error) { + s, err := createServiceInstance() + if err != nil { + return nil, err + } + // Defensive check: createServiceInstance should not return nil service with nil error + if s == nil { + return nil, errors.New("config: createServiceInstance returned a nil service instance with no error") + } + s.Runtime = core.NewRuntime(c, Options{}) + return s, nil +} + +// Save writes the current configuration to config.json. +func (s *Service) Save() error { + data, err := json.MarshalIndent(s, "", " ") + if err != nil { + return fmt.Errorf("failed to marshal config: %w", err) + } + + if err := os.WriteFile(s.ConfigPath, data, 0644); err != nil { + return fmt.Errorf("failed to write config file: %w", err) + } + return nil +} + +// Get retrieves a configuration value by its key. +func (s *Service) Get(key string, out any) error { + val := reflect.ValueOf(s).Elem() + typ := val.Type() + + for i := 0; i < val.NumField(); i++ { + field := typ.Field(i) + jsonTag := field.Tag.Get("json") + if jsonTag != "" && jsonTag != "-" { + jsonName := strings.Split(jsonTag, ",")[0] + if strings.EqualFold(jsonName, key) { + outVal := reflect.ValueOf(out) + if outVal.Kind() != reflect.Ptr || outVal.IsNil() { + return errors.New("output argument must be a non-nil pointer") + } + targetVal := outVal.Elem() + srcVal := val.Field(i) + + if !srcVal.Type().AssignableTo(targetVal.Type()) { + return fmt.Errorf("cannot assign config value of type %s to output of type %s", srcVal.Type(), targetVal.Type()) + } + targetVal.Set(srcVal) + return nil + } + } + } + + return fmt.Errorf("key '%s' not found in config", key) +} + +// IsFeatureEnabled checks if a specific feature is enabled in the config. +func (s *Service) IsFeatureEnabled(feature string) bool { + for _, f := range s.Features { + if f == feature { + return true + } + } + return false +} + +// Set updates a configuration value and saves the config. +func (s *Service) Set(key string, v any) error { + val := reflect.ValueOf(s).Elem() + typ := val.Type() + + for i := 0; i < val.NumField(); i++ { + field := typ.Field(i) + jsonTag := field.Tag.Get("json") + if jsonTag != "" && jsonTag != "-" { + jsonName := strings.Split(jsonTag, ",")[0] + if strings.EqualFold(jsonName, key) { + fieldVal := val.Field(i) + if !fieldVal.CanSet() { + return fmt.Errorf("cannot set config field for key '%s'", key) + } + if v == nil { + switch fieldVal.Kind() { + case reflect.Pointer, reflect.Interface, reflect.Map, reflect.Slice, reflect.Func: + fieldVal.Set(reflect.Zero(fieldVal.Type())) + return s.Save() + default: + return fmt.Errorf("type mismatch for key '%s': expected %s, got nil", key, fieldVal.Type()) + } + } + newVal := reflect.ValueOf(v) + if !newVal.Type().AssignableTo(fieldVal.Type()) { + return fmt.Errorf("type mismatch for key '%s': expected %s, got %s", key, fieldVal.Type(), newVal.Type()) + } + fieldVal.Set(newVal) + return s.Save() + } + } + } + + return fmt.Errorf("key '%s' not found in config", key) +} diff --git a/pkg/core/actions.go b/pkg/core/actions.go index 828df0f..f0fe28c 100644 --- a/pkg/core/actions.go +++ b/pkg/core/actions.go @@ -4,6 +4,8 @@ import "github.com/wailsapp/wails/v3/pkg/application" type ActionServiceStartup struct{} +type ActionServiceShutdown struct{} + // ActionDisplayOpenWindow is a structured message for requesting a new window. type ActionDisplayOpenWindow struct { Name string diff --git a/pkg/core/core.go b/pkg/core/core.go index dea862e..166cca2 100644 --- a/pkg/core/core.go +++ b/pkg/core/core.go @@ -67,6 +67,22 @@ func WithService(factory func(*Core) (any, error)) Option { } } +// WithName creates an option that registers a service with a specific name. +// This is useful when the service name cannot be inferred from the package path, +// such as when using anonymous functions as factories. +// Note: Unlike WithService, this does not automatically discover or register +// IPC handlers. If your service needs IPC handling, implement HandleIPCEvents +// and register it manually. +func WithName(name string, factory func(*Core) (any, error)) Option { + return func(c *Core) error { + serviceInstance, err := factory(c) + if err != nil { + return fmt.Errorf("core: failed to create service '%s': %w", name, err) + } + return c.RegisterService(name, serviceInstance) + } +} + func WithWails(app *application.App) Option { return func(c *Core) error { c.App = app @@ -90,10 +106,14 @@ func WithServiceLock() Option { // --- Core Methods --- -func (c *Core) ServiceStartup(context.Context, application.ServiceOptions) error { +func (c *Core) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { return c.ACTION(ActionServiceStartup{}) } +func (c *Core) ServiceShutdown(ctx context.Context) error { + return c.ACTION(ActionServiceShutdown{}) +} + func (c *Core) ACTION(msg Message) error { c.ipcMu.RLock() handlers := append([]func(*Core, Message) error(nil), c.ipcHandlers...) diff --git a/pkg/crypt/crypt.go b/pkg/crypt/crypt.go index 4484ea9..848be61 100644 --- a/pkg/crypt/crypt.go +++ b/pkg/crypt/crypt.go @@ -1,176 +1,33 @@ package crypt import ( - "bytes" - "crypto/md5" - "crypto/sha1" - "crypto/sha256" - "crypto/sha512" - "encoding/binary" - "encoding/hex" - "io" - "strconv" - "strings" - "github.com/Snider/Core/pkg/core" - "github.com/Snider/Core/pkg/crypt/lthn" - "github.com/Snider/Core/pkg/crypt/openpgp" + "github.com/Snider/Core/pkg/crypt/internal" ) // Options holds configuration for the crypt service. -type Options struct{} +type Options = internal.Options // Service provides cryptographic functions to the application. -type Service struct { - *core.Runtime[Options] -} +type Service = internal.Service // HashType defines the supported hashing algorithms. -type HashType string +type HashType = internal.HashType const ( - LTHN HashType = "lthn" - SHA512 HashType = "sha512" - SHA256 HashType = "sha256" - SHA1 HashType = "sha1" - MD5 HashType = "md5" + LTHN = internal.LTHN + SHA512 = internal.SHA512 + SHA256 = internal.SHA256 + SHA1 = internal.SHA1 + MD5 = internal.MD5 ) -// newCryptService contains the common logic for initializing a Service struct. -func newCryptService() (*Service, error) { - return &Service{}, nil -} - // New is the constructor for static dependency injection. -// It creates a Service instance without initializing the core.Runtime field. func New() (*Service, error) { - return newCryptService() + return internal.New() } -// Register is the constructor for dynamic dependency injection (used with core.WithService). -// It creates a Service instance and initializes its core.Runtime field. +// Register is the constructor for dynamic dependency injection. func Register(c *core.Core) (any, error) { - s, err := newCryptService() - if err != nil { - return nil, err - } - s.Runtime = core.NewRuntime(c, Options{}) - return s, nil -} - -// --- Hashing --- - -// Hash computes a hash of the payload using the specified algorithm. -func (s *Service) Hash(lib HashType, payload string) string { - switch lib { - case LTHN: - return lthn.Hash(payload) - case SHA512: - hash := sha512.Sum512([]byte(payload)) - return hex.EncodeToString(hash[:]) - case SHA1: - hash := sha1.Sum([]byte(payload)) - return hex.EncodeToString(hash[:]) - case MD5: - hash := md5.Sum([]byte(payload)) - return hex.EncodeToString(hash[:]) - case SHA256: - fallthrough - default: - hash := sha256.Sum256([]byte(payload)) - return hex.EncodeToString(hash[:]) - } -} - -// --- Checksums --- - -// Luhn validates a number using the Luhn algorithm. -func (s *Service) Luhn(payload string) bool { - payload = strings.ReplaceAll(payload, " ", "") - sum := 0 - isSecond := false - for i := len(payload) - 1; i >= 0; i-- { - digit, err := strconv.Atoi(string(payload[i])) - if err != nil { - return false // Contains non-digit - } - - if isSecond { - digit = digit * 2 - if digit > 9 { - digit = digit - 9 - } - } - - sum += digit - isSecond = !isSecond - } - return sum%10 == 0 -} - -// Fletcher16 computes the Fletcher-16 checksum. -func (s *Service) Fletcher16(payload string) uint16 { - data := []byte(payload) - var sum1, sum2 uint16 - for _, b := range data { - sum1 = (sum1 + uint16(b)) % 255 - sum2 = (sum2 + sum1) % 255 - } - return (sum2 << 8) | sum1 -} - -// Fletcher32 computes the Fletcher-32 checksum. -func (s *Service) Fletcher32(payload string) uint32 { - data := []byte(payload) - if len(data)%2 != 0 { - data = append(data, 0) - } - - var sum1, sum2 uint32 - for i := 0; i < len(data); i += 2 { - val := binary.LittleEndian.Uint16(data[i : i+2]) - sum1 = (sum1 + uint32(val)) % 65535 - sum2 = (sum2 + sum1) % 65535 - } - return (sum2 << 16) | sum1 -} - -// Fletcher64 computes the Fletcher-64 checksum. -func (s *Service) Fletcher64(payload string) uint64 { - data := []byte(payload) - if len(data)%4 != 0 { - padding := 4 - (len(data) % 4) - data = append(data, make([]byte, padding)...) - } - - var sum1, sum2 uint64 - for i := 0; i < len(data); i += 4 { - val := binary.LittleEndian.Uint32(data[i : i+4]) - sum1 = (sum1 + uint64(val)) % 4294967295 - sum2 = (sum2 + sum1) % 4294967295 - } - return (sum2 << 32) | sum1 -} - -// --- PGP --- - -// EncryptPGP encrypts data for a recipient, optionally signing it. -func (s *Service) EncryptPGP(writer io.Writer, recipientPath, data string, signerPath, signerPassphrase *string) (string, error) { - var buf bytes.Buffer - err := openpgp.EncryptPGP(&buf, recipientPath, data, signerPath, signerPassphrase) - if err != nil { - return "", err - } - - // Copy the encrypted data to the original writer. - if _, err := writer.Write(buf.Bytes()); err != nil { - return "", err - } - - return buf.String(), nil -} - -// DecryptPGP decrypts a PGP message, optionally verifying the signature. -func (s *Service) DecryptPGP(recipientPath, message, passphrase string, signerPath *string) (string, error) { - return openpgp.DecryptPGP(recipientPath, message, passphrase, signerPath) + return internal.Register(c) } diff --git a/pkg/crypt/crypt_test.go b/pkg/crypt/internal/crypt_test.go similarity index 94% rename from pkg/crypt/crypt_test.go rename to pkg/crypt/internal/crypt_test.go index 2cde507..56867aa 100644 --- a/pkg/crypt/crypt_test.go +++ b/pkg/crypt/internal/crypt_test.go @@ -1,4 +1,4 @@ -package crypt +package internal import ( "testing" diff --git a/pkg/crypt/internal/service.go b/pkg/crypt/internal/service.go new file mode 100644 index 0000000..66ed1b7 --- /dev/null +++ b/pkg/crypt/internal/service.go @@ -0,0 +1,181 @@ +package internal + +import ( + "bytes" + "crypto/md5" + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "encoding/binary" + "encoding/hex" + "io" + "strconv" + "strings" + + "github.com/Snider/Core/pkg/core" + "github.com/Snider/Core/pkg/crypt/lthn" + "github.com/Snider/Core/pkg/crypt/openpgp" + "github.com/Snider/Core/pkg/e" +) + +// Options holds configuration for the crypt service. +type Options struct{} + +// Service provides cryptographic functions to the application. +type Service struct { + *core.Runtime[Options] +} + +// HashType defines the supported hashing algorithms. +type HashType string + +const ( + LTHN HashType = "lthn" + SHA512 HashType = "sha512" + SHA256 HashType = "sha256" + SHA1 HashType = "sha1" + MD5 HashType = "md5" +) + +// newCryptService contains the common logic for initializing a Service struct. +func newCryptService() (*Service, error) { + return &Service{}, nil +} + +// New is the constructor for static dependency injection. +// It creates a Service instance without initializing the core.Runtime field. +func New() (*Service, error) { + return newCryptService() +} + +// Register is the constructor for dynamic dependency injection (used with core.WithService). +// It creates a Service instance and initializes its core.Runtime field. +func Register(c *core.Core) (any, error) { + s, err := newCryptService() + if err != nil { + return nil, e.E("crypt.Register", "failed to create new crypt service", err) + } + s.Runtime = core.NewRuntime(c, Options{}) + return s, nil +} + +// --- Hashing --- + +// Hash computes a hash of the payload using the specified algorithm. +func (s *Service) Hash(lib HashType, payload string) string { + switch lib { + case LTHN: + return lthn.Hash(payload) + case SHA512: + hash := sha512.Sum512([]byte(payload)) + return hex.EncodeToString(hash[:]) + case SHA1: + hash := sha1.Sum([]byte(payload)) + return hex.EncodeToString(hash[:]) + case MD5: + hash := md5.Sum([]byte(payload)) + return hex.EncodeToString(hash[:]) + case SHA256: + fallthrough + default: + hash := sha256.Sum256([]byte(payload)) + return hex.EncodeToString(hash[:]) + } +} + +// --- Checksums --- + +// Luhn validates a number using the Luhn algorithm. +func (s *Service) Luhn(payload string) bool { + payload = strings.ReplaceAll(payload, " ", "") + sum := 0 + isSecond := false + for i := len(payload) - 1; i >= 0; i-- { + digit, err := strconv.Atoi(string(payload[i])) + if err != nil { + return false // Contains non-digit + } + + if isSecond { + digit = digit * 2 + if digit > 9 { + digit = digit - 9 + } + } + + sum += digit + isSecond = !isSecond + } + return sum%10 == 0 +} + +// Fletcher16 computes the Fletcher-16 checksum. +func (s *Service) Fletcher16(payload string) uint16 { + data := []byte(payload) + var sum1, sum2 uint16 + for _, b := range data { + sum1 = (sum1 + uint16(b)) % 255 + sum2 = (sum2 + sum1) % 255 + } + return (sum2 << 8) | sum1 +} + +// Fletcher32 computes the Fletcher-32 checksum. +func (s *Service) Fletcher32(payload string) uint32 { + data := []byte(payload) + if len(data)%2 != 0 { + data = append(data, 0) + } + + var sum1, sum2 uint32 + for i := 0; i < len(data); i += 2 { + val := binary.LittleEndian.Uint16(data[i : i+2]) + sum1 = (sum1 + uint32(val)) % 65535 + sum2 = (sum2 + sum1) % 65535 + } + return (sum2 << 16) | sum1 +} + +// Fletcher64 computes the Fletcher-64 checksum. +func (s *Service) Fletcher64(payload string) uint64 { + data := []byte(payload) + if len(data)%4 != 0 { + padding := 4 - (len(data) % 4) + data = append(data, make([]byte, padding)...) + } + + var sum1, sum2 uint64 + for i := 0; i < len(data); i += 4 { + val := binary.LittleEndian.Uint32(data[i : i+4]) + sum1 = (sum1 + uint64(val)) % 4294967295 + sum2 = (sum2 + sum1) % 4294967295 + } + return (sum2 << 32) | sum1 +} + +// --- PGP --- + +// EncryptPGP encrypts data for a recipient, optionally signing it. +func (s *Service) EncryptPGP(writer io.Writer, recipientPath, data string, signerPath, signerPassphrase *string) (string, error) { + var buf bytes.Buffer + err := openpgp.EncryptPGP(&buf, recipientPath, data, signerPath, signerPassphrase) + if err != nil { + return "", e.E("crypt.EncryptPGP", "failed to encrypt PGP message", err) + } + + // Copy the encrypted data to the original writer. + if _, err := writer.Write(buf.Bytes()); err != nil { + return "", e.E("crypt.EncryptPGP", "failed to write encrypted PGP message to writer", err) + } + + return buf.String(), nil +} + +// DecryptPGP decrypts a PGP message, optionally verifying the signature. +func (s *Service) DecryptPGP(recipientPath, message, passphrase string, signerPath *string) (string, error) { + decrypted, err := openpgp.DecryptPGP(recipientPath, message, passphrase, signerPath) + if err != nil { + return "", e.E("crypt.DecryptPGP", "failed to decrypt PGP message", err) + } + return decrypted, nil +} diff --git a/pkg/e/e.go b/pkg/e/e.go new file mode 100644 index 0000000..bfe9a08 --- /dev/null +++ b/pkg/e/e.go @@ -0,0 +1,59 @@ +// Package e provides a standardized error handling mechanism for the Core library. +// It allows for wrapping errors with contextual information, making it easier to +// trace the origin of an error and provide meaningful feedback. +// +// The design of this package is influenced by the need for a simple, yet powerful +// way to handle errors that can occur in different layers of the application, +// from low-level file operations to high-level service interactions. +// +// The key features of this package are: +// - Error wrapping: The Op and an optional Msg field provide context about +// where and why an error occurred. +// - Stack traces: By wrapping errors, we can build a logical stack trace +// that is more informative than a raw stack trace. +// - Consistent error handling: Encourages a uniform approach to error +// handling across the entire codebase. +package e + +import ( + "fmt" +) + +// Error represents a standardized error with operational context. +type Error struct { + // Op is the operation being performed, e.g., "config.Load". + Op string + // Msg is a human-readable message explaining the error. + Msg string + // Err is the underlying error that was wrapped. + Err error +} + +// E is a helper function to create a new Error. +// This is the primary way to create errors that will be consumed by the system. +// For example: +// +// return e.E("config.Load", "failed to load config file", err) +// +// The 'op' parameter should be in the format of 'package.function' or 'service.method'. +// The 'msg' parameter should be a human-readable message that can be displayed to the user. +// The 'err' parameter is the underlying error that is being wrapped. +func E(op, msg string, err error) error { + if err == nil { + return &Error{Op: op, Msg: msg} + } + return &Error{Op: op, Msg: msg, Err: err} +} + +// Error returns the string representation of the error. +func (e *Error) Error() string { + if e.Err != nil { + return fmt.Sprintf("%s: %s: %v", e.Op, e.Msg, e.Err) + } + return fmt.Sprintf("%s: %s", e.Op, e.Msg) +} + +// Unwrap provides compatibility for Go's errors.Is and errors.As functions. +func (e *Error) Unwrap() error { + return e.Err +} \ No newline at end of file diff --git a/pkg/help/src/core/config.md b/pkg/help/src/core/config.md deleted file mode 100644 index d475c3e..0000000 --- a/pkg/help/src/core/config.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Core.Config ---- - -# Core.Config - -Short: App config and UI state persistence. - -## Overview -Stores and retrieves configuration, including window positions/sizes and user prefs. - -## Setup -```go -import ( - core "github.com/Snider/Core" - config "github.com/Snider/Core/config" -) - -app := core.New( - core.WithService(config.Register), - core.WithServiceLock(), -) - -``` - -## Use -- Persist UI state automatically when using `Core.Display`. -- Read/write your own settings via the config API. - -## API -- `Register(c *core.Core) error` -- `Get(path string, out any) error` -- `Set(path string, v any) error` diff --git a/pkg/help/src/core/crypt.md b/pkg/help/src/core/crypt.md deleted file mode 100644 index 47960eb..0000000 --- a/pkg/help/src/core/crypt.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Core.Crypt ---- - -# Core.Crypt - -Short: Keys, encrypt/decrypt, sign/verify. - -## Overview -Simple wrappers around OpenPGP for common crypto tasks. - -## Setup -```go -import ( - core "github.com/Snider/Core" - crypt "github.com/Snider/Core/pkg/crypt" -) - -// In your application's startup -cryptService, err := crypt.New() -if err != nil { - // handle error -} -app := core.New( - core.WithService(cryptService), - core.WithServiceLock(), -) -``` - -## Use -- Generate keys -- Encrypt/decrypt data -- Sign/verify messages - -## API -- `New() (*Service, error)` -- `Register(c *core.Core) (any, error)` -- `(s *Service) Hash(lib HashType, payload string) string` -- `(s *Service) Luhn(payload string) bool` -- `(s *Service) Fletcher16(payload string) uint16` -- `(s *Service) Fletcher32(payload string) uint32` -- `(s *Service) Fletcher64(payload string) uint64` -- `(s *Service) EncryptPGP(writer io.Writer, recipientPath, data string, signerPath, signerPassphrase *string) (string, error)` -- `(s *Service) DecryptPGP(recipientPath, message, passphrase string, signerPath *string) (string, error)` - -## Notes -- Uses [Proton Mail](https://pr.tn/ref/VZFX8H2VDCFG) OpenPGP fork. diff --git a/pkg/help/src/core/display.md b/pkg/help/src/core/display.md deleted file mode 100644 index 162d041..0000000 --- a/pkg/help/src/core/display.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Core.Display ---- - -# Core.Display - -Short: Windows, tray, and window state. - -## Overview -Manages Wails windows, remembers positions/sizes, exposes JS bindings, and integrates with `Core.Config` for persistence. - -## Setup -```go -import ( - core "github.com/Snider/Core" - display "github.com/Snider/Core/display" -) - -app := core.New( - core.WithService(display.Register), - core.WithServiceLock(), -) -``` - -## Use -- Open a window: `OpenWindow(OptName("main"), ...)` -- Get a window: `Window("main")` -- Save/restore state automatically when `Core.Config` is present - -## API -- `Register(c *core.Core) error` -- `OpenWindow(opts ...Option) *Window` -- `Window(name string) *Window` -- Options: `OptName`, `OptWidth`, `OptHeight`, `OptURL`, `OptTitle` - -## Example -```go -func (d *API) ServiceStartup(ctx context.Context, _ application.ServiceOptions) error { - d.OpenWindow( - OptName("main"), OptWidth(1280), OptHeight(900), OptURL("/"), OptTitle("Core"), - ) - return nil -} -``` - - diff --git a/pkg/help/src/core/help.md b/pkg/help/src/core/help.md deleted file mode 100644 index 0628615..0000000 --- a/pkg/help/src/core/help.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: Core.Help ---- - -# Core.Help - -Short: In‑app help and deep‑links. - -## Overview -Renders MkDocs content inside your app. Opens specific sections in new windows for contextual help. - -## Setup -```go -package demo -import ( - "github.com/Snider/Core" - "github.com/Snider/Core/docs" -) - -core.New( - core.WithService(docs.Register), - core.WithServiceLock(), -) -``` - -## Use -- Open Help home in a window: `help.Open()` -- Open a section: `help.OpenAt("core/display#setup")` -- Use short, descriptive headings to create stable anchors. - -## API -- `Register(c *core.Core) error` -- `Open()` — show help home -- `OpenAt(anchor string)` — open specific section - -## Notes -- Help is built with MkDocs Material and included in the demo app assets. -- When viewed in the app, this documentation is served from Core.Help and is bundled into the app binary by default. diff --git a/pkg/help/src/core/index.md b/pkg/help/src/core/index.md deleted file mode 100644 index c5d8339..0000000 --- a/pkg/help/src/core/index.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Core ---- - -# Core - -Short: Framework bootstrap and service container. - -## What it is -Core wires modules together, provides lifecycle hooks, and locks the service graph for clarity and safety. - -## Setup -```go -import "github.com/Snider/Core" - -app := core.New( - core.WithServiceLock(), -) -``` - -## Use -- Register a module: `core.RegisterModule(name, module)` -- Access a module: `core.Mod[T](c, name)` -- Lock services: `core.WithServiceLock()` - -## API -- `New(opts ...) *core.Core` -- `RegisterModule(name string, m any) error` -- `Mod[T any](c *core.Core, name ...string) *T` - diff --git a/pkg/help/src/core/io.md b/pkg/help/src/core/io.md deleted file mode 100644 index e62087d..0000000 --- a/pkg/help/src/core/io.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: Core.IO ---- - -# Core.IO - -Short: Local/remote filesystem helpers. - -## Overview -Abstracts filesystems (local, SFTP, WebDAV) behind a unified API for reading/writing and listing. - -## Setup -```go -import ( - core "github.com/Snider/Core" - ioapi "github.com/Snider/Core/filesystem" -) - -app := core.New( - core.WithService(ioapi.Register), - core.WithServiceLock(), -) -``` - -## Use -- Open a filesystem: `fs := ioapi.Local()` or `ioapi.SFTP(cfg)` -- Read/write files: `fs.Read(path)`, `fs.Write(path, data)` -- List directories: `fs.List(path)` - -## API -- `Register(c *core.Core) error` -- `Local() FS` -- `SFTP(cfg Config) (FS, error)` -- `WebDAV(cfg Config) (FS, error)` - -## Notes -- See package `pkg/v1/core/filesystem/*` for drivers. - diff --git a/pkg/help/src/core/workspace.md b/pkg/help/src/core/workspace.md deleted file mode 100644 index 71ac8c3..0000000 --- a/pkg/help/src/core/workspace.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: Core.Workspace ---- - -# Core.Workspace - -Short: Projects and paths. - -## Overview -Provides a consistent way to resolve app/project directories, temp/cache locations, and user data paths across platforms. - -## Setup -```go -import ( - core "github.com/Snider/Core" - workspace "github.com/Snider/Core/workspace" -) - -app := core.New( - core.WithService(workspace.Register), - core.WithServiceLock(), -) -``` - -## Use -- Get app data dir: `ws.DataDir()` -- Get cache dir: `ws.CacheDir()` -- Resolve project path: `ws.Project("my-app")` - -## API -- `Register(c *core.Core) error` -- `DataDir() string` -- `CacheDir() string` -- `Project(name string) string` - -## Notes -- Follows OS directory standards (AppData, ~/Library, XDG, etc.). - - diff --git a/pkg/runtime/runtime.go b/pkg/runtime/runtime.go index 85cab14..c5efeec 100644 --- a/pkg/runtime/runtime.go +++ b/pkg/runtime/runtime.go @@ -1,22 +1,23 @@ package runtime import ( + "context" "fmt" - // Import the CONCRETE implementations from the internal packages. "github.com/Snider/Core/pkg/config" + "github.com/Snider/Core/pkg/core" "github.com/Snider/Core/pkg/crypt" "github.com/Snider/Core/pkg/display" "github.com/Snider/Core/pkg/help" "github.com/Snider/Core/pkg/i18n" "github.com/Snider/Core/pkg/workspace" - // Import the ABSTRACT contracts (interfaces). - "github.com/Snider/Core/pkg/core" + "github.com/wailsapp/wails/v3/pkg/application" ) -// App is the runtime container that holds all instantiated services. +// Runtime is the container that holds all instantiated services. // Its fields are the concrete types, allowing Wails to bind them directly. type Runtime struct { + app *application.App Core *core.Core Config *config.Service Display *display.Service @@ -30,9 +31,11 @@ type Runtime struct { type ServiceFactory func() (any, error) // newWithFactories creates a new Runtime instance using the provided service factories. -func newWithFactories(factories map[string]ServiceFactory) (*Runtime, error) { +func newWithFactories(app *application.App, factories map[string]ServiceFactory) (*Runtime, error) { services := make(map[string]any) - coreOpts := []core.Option{} + coreOpts := []core.Option{ + core.WithWails(app), + } for _, name := range []string{"config", "display", "help", "crypt", "i18n", "workspace"} { factory, ok := factories[name] @@ -45,7 +48,7 @@ func newWithFactories(factories map[string]ServiceFactory) (*Runtime, error) { } services[name] = svc svcCopy := svc - coreOpts = append(coreOpts, core.WithService(func(c *core.Core) (any, error) { return svcCopy, nil })) + coreOpts = append(coreOpts, core.WithName(name, func(c *core.Core) (any, error) { return svcCopy, nil })) } coreInstance, err := core.New(coreOpts...) @@ -53,6 +56,7 @@ func newWithFactories(factories map[string]ServiceFactory) (*Runtime, error) { return nil, err } + // --- Type Assertions --- configSvc, ok := services["config"].(*config.Service) if !ok { return nil, fmt.Errorf("config service has unexpected type") @@ -78,7 +82,8 @@ func newWithFactories(factories map[string]ServiceFactory) (*Runtime, error) { return nil, fmt.Errorf("workspace service has unexpected type") } - app := &Runtime{ + rt := &Runtime{ + app: app, Core: coreInstance, Config: configSvc, Display: displaySvc, @@ -88,12 +93,12 @@ func newWithFactories(factories map[string]ServiceFactory) (*Runtime, error) { Workspace: workspaceSvc, } - return app, nil + return rt, nil } -// New creates and wires together all application services using static dependency injection. -func New() (*Runtime, error) { - return newWithFactories(map[string]ServiceFactory{ +// New creates and wires together all application services. +func New(app *application.App) (*Runtime, error) { + return newWithFactories(app, map[string]ServiceFactory{ "config": func() (any, error) { return config.New() }, "display": func() (any, error) { return display.New() }, "help": func() (any, error) { return help.New() }, @@ -102,3 +107,20 @@ func New() (*Runtime, error) { "workspace": func() (any, error) { return workspace.New() }, }) } + +// ServiceName returns the name of the service. This is used by Wails to identify the service. +func (r *Runtime) ServiceName() string { + return "Core" +} + +// ServiceStartup is called by Wails at application startup. +func (r *Runtime) ServiceStartup(ctx context.Context, options application.ServiceOptions) { + r.Core.ServiceStartup(ctx, options) +} + +// ServiceShutdown is called by Wails at application shutdown. +func (r *Runtime) ServiceShutdown(ctx context.Context) { + if r.Core != nil { + r.Core.ServiceShutdown(ctx) + } +} diff --git a/pkg/runtime/runtime_test.go b/pkg/runtime/runtime_test.go index 8829051..f340282 100644 --- a/pkg/runtime/runtime_test.go +++ b/pkg/runtime/runtime_test.go @@ -4,18 +4,18 @@ import ( "errors" "testing" - "github.com/stretchr/testify/assert" - "github.com/Snider/Core/pkg/config" "github.com/Snider/Core/pkg/crypt" "github.com/Snider/Core/pkg/display" "github.com/Snider/Core/pkg/help" "github.com/Snider/Core/pkg/workspace" + "github.com/stretchr/testify/assert" ) // TestNew ensures that New correctly initializes a Runtime instance. func TestNew(t *testing.T) { - runtime, err := New() + // Pass nil for the application, as it is not required for this test. + runtime, err := New(nil) assert.NoError(t, err) assert.NotNil(t, runtime) @@ -65,11 +65,10 @@ func TestNewServiceInitializationError(t *testing.T) { "workspace": func() (any, error) { return workspace.New() }, } - runtime, err := newWithFactories(factories) + // Pass nil for the application, as it is not required for this test. + runtime, err := newWithFactories(nil, factories) assert.Error(t, err) assert.Nil(t, runtime) assert.Contains(t, err.Error(), "failed to create service i18n: i18n service failed to initialize") } - -// Removed TestRuntimeOptions and TestRuntimeCore as these methods no longer exist on the Runtime struct. diff --git a/pkg/workspace/workspace.go b/pkg/workspace/workspace.go index 8de7b46..230db81 100644 --- a/pkg/workspace/workspace.go +++ b/pkg/workspace/workspace.go @@ -9,6 +9,7 @@ import ( "github.com/Snider/Core/pkg/core" "github.com/Snider/Core/pkg/crypt/lthn" "github.com/Snider/Core/pkg/crypt/openpgp" + "github.com/Snider/Core/pkg/e" "github.com/Snider/Core/pkg/io" "github.com/wailsapp/wails/v3/pkg/application" ) @@ -50,13 +51,13 @@ func newWorkspaceService() (*Service, error) { func New() (*Service, error) { s, err := newWorkspaceService() if err != nil { - return nil, err + return nil, e.E("workspace.New", "failed to create new workspace service", err) } //s.medium = medium // Initialize the service after creation. // Note: ServiceStartup will now get config from s.Runtime.Config() //if err := s.ServiceStartup(context.Background(), application.ServiceOptions{}); err != nil { - // return nil, fmt.Errorf("workspace service startup failed: %w", err) + // return nil, e.E("workspace.New", "workspace service startup failed", err) //} return s, nil } @@ -67,7 +68,7 @@ func New() (*Service, error) { func Register(c *core.Core) (any, error) { s, err := newWorkspaceService() if err != nil { - return nil, err + return nil, e.E("workspace.Register", "failed to create new workspace service", err) } s.Runtime = core.NewRuntime(c, Options{}) return s, nil @@ -92,7 +93,7 @@ func (s *Service) HandleIPCEvents(c *core.Core, msg core.Message) error { func (s *Service) getWorkspaceDir() (string, error) { var workspaceDir string if err := s.Config().Get("workspaceDir", &workspaceDir); err != nil { - return "", fmt.Errorf("failed to get WorkspaceDir from config: %w", err) + return "", e.E("workspace.getWorkspaceDir", "failed to get WorkspaceDir from config", err) } return workspaceDir, nil } @@ -111,7 +112,7 @@ func (s *Service) ServiceStartup(context.Context, application.ServiceOptions) er //if s.medium.IsFile(listPath) { // content, err := s.medium.FileGet(listPath) // if err != nil { - // return fmt.Errorf("failed to read workspace list: %w", err) + // return e.E("workspace.ServiceStartup", "failed to read workspace list", err) // } // if err := json.Unmarshal([]byte(content), &s.workspaceList); err != nil { // fmt.Printf("Warning: could not parse workspace list: %v\n", err) @@ -134,19 +135,19 @@ func (s *Service) CreateWorkspace(identifier, password string) (string, error) { workspacePath := filepath.Join(workspaceDir, workspaceID) if _, exists := s.workspaceList[workspaceID]; exists { - return "", fmt.Errorf("workspace for this identifier already exists") + return "", e.E("workspace.CreateWorkspace", "workspace for this identifier already exists", nil) } dirsToCreate := []string{"config", "log", "data", "files", "keys"} for _, dir := range dirsToCreate { if err := s.medium.EnsureDir(filepath.Join(workspacePath, dir)); err != nil { - return "", fmt.Errorf("failed to create workspace directory '%s': %w", dir, err) + return "", e.E("workspace.CreateWorkspace", fmt.Sprintf("failed to create workspace directory '%s'", dir), err) } } keyPair, err := openpgp.CreateKeyPair(workspaceID, password) if err != nil { - return "", fmt.Errorf("failed to create workspace key pair: %w", err) + return "", e.E("workspace.CreateWorkspace", "failed to create workspace key pair", err) } keyFiles := map[string]string{ @@ -155,19 +156,19 @@ func (s *Service) CreateWorkspace(identifier, password string) (string, error) { } for path, content := range keyFiles { if err := s.medium.FileSet(path, content); err != nil { - return "", fmt.Errorf("failed to write key file %s: %w", path, err) + return "", e.E("workspace.CreateWorkspace", fmt.Sprintf("failed to write key file %s", path), err) } } s.workspaceList[workspaceID] = keyPair.PublicKey listData, err := json.MarshalIndent(s.workspaceList, "", " ") if err != nil { - return "", fmt.Errorf("failed to marshal workspace list: %w", err) + return "", e.E("workspace.CreateWorkspace", "failed to marshal workspace list", err) } listPath := filepath.Join(workspaceDir, listFile) if err := s.medium.FileSet(listPath, string(listData)); err != nil { - return "", fmt.Errorf("failed to write workspace list file: %w", err) + return "", e.E("workspace.CreateWorkspace", "failed to write workspace list file", err) } return workspaceID, nil @@ -182,13 +183,13 @@ func (s *Service) SwitchWorkspace(name string) error { if name != defaultWorkspace { if _, exists := s.workspaceList[name]; !exists { - return fmt.Errorf("workspace '%s' does not exist", name) + return e.E("workspace.SwitchWorkspace", fmt.Sprintf("workspace '%s' does not exist", name), nil) } } path := filepath.Join(workspaceDir, name) //if err := s.medium.EnsureDir(path); err != nil { - // return fmt.Errorf("failed to ensure workspace directory exists: %w", err) + // return e.E("workspace.SwitchWorkspace", "failed to ensure workspace directory exists", err) //} s.activeWorkspace = &Workspace{ @@ -202,17 +203,25 @@ func (s *Service) SwitchWorkspace(name string) error { // WorkspaceFileGet retrieves a file from the active workspace. func (s *Service) WorkspaceFileGet(filename string) (string, error) { if s.activeWorkspace == nil { - return "", fmt.Errorf("no active workspace") + return "", e.E("workspace.WorkspaceFileGet", "no active workspace", nil) } path := filepath.Join(s.activeWorkspace.Path, filename) - return s.medium.FileGet(path) + content, err := s.medium.FileGet(path) + if err != nil { + return "", e.E("workspace.WorkspaceFileGet", "failed to get file", err) + } + return content, nil } // WorkspaceFileSet writes a file to the active workspace. func (s *Service) WorkspaceFileSet(filename, content string) error { if s.activeWorkspace == nil { - return fmt.Errorf("no active workspace") + return e.E("workspace.WorkspaceFileSet", "no active workspace", nil) } path := filepath.Join(s.activeWorkspace.Path, filename) - return s.medium.FileSet(path, content) + err := s.medium.FileSet(path, content) + if err != nil { + return e.E("workspace.WorkspaceFileSet", "failed to set file", err) + } + return nil } diff --git a/workspace/workspace.go b/workspace/workspace.go deleted file mode 100644 index ebed1f9..0000000 --- a/workspace/workspace.go +++ /dev/null @@ -1,27 +0,0 @@ -// package workspace provides the public API for the workspace service. -package workspace - -import ( - // Import the internal implementation with an alias. - impl "github.com/Snider/Core/pkg/workspace" - - // Import the core contracts to re-export the interface. - "github.com/Snider/Core/pkg/core" -) - -// Options is the public type for the Options service. It is a type alias -// to the underlying implementation, making it transparent to the user. -type Options = impl.Options - -// Service is the public type for the Service service. It is a type alias -// to the underlying implementation, making it transparent to the user. -type Service = impl.Service - -// New is a public function that points to the real function in the implementation package. -var New = impl.New - -// Register is a public function that points to the real function in the implementation package. -var Register = impl.Register - -// Workspace is the public interface for the workspace service. -type Workspace = core.Workspace diff --git a/workspace/workspace_test.go b/workspace/workspace_test.go deleted file mode 100644 index 5816328..0000000 --- a/workspace/workspace_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package workspace_test - -import ( - "testing" - - "github.com/Snider/Core/pkg/core" - "github.com/Snider/Core/workspace" -) - -// TestNew ensures that the public constructor New is available. -func TestNew(t *testing.T) { - if workspace.New == nil { - t.Fatal("workspace.New constructor is nil") - } - // Note: This is a basic check. Some services may require a core instance - // or other arguments. This test can be expanded as needed. -} - -// TestRegister ensures that the public factory Register is available. -func TestRegister(t *testing.T) { - if workspace.Register == nil { - t.Fatal("workspace.Register factory is nil") - } -} - -// TestInterfaceCompliance ensures that the public Service type correctly -// implements the public Workspace interface. This is a compile-time check. -func TestInterfaceCompliance(t *testing.T) { - // This is a compile-time check. If it compiles, the test passes. - var _ core.Workspace = (*workspace.Service)(nil) -}