Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Core

![CodeRabbit Pull Request Reviews](https://img.shields.io/coderabbit/prs/github/Snider/Core?utm_source=oss&utm_medium=github&utm_campaign=Snider%2FCore&labelColor=171717&color=FF570A&link=https%3A%2F%2Fcoderabbit.ai&label=CodeRabbit+Reviews)

Core is a Web3 Framework, written in Go using Wails.io to replace Electron and the bloat of browsers that, at their core, still live in their mum's basement.

More to come, follow us on Discord http://discord.dappco.re
Expand Down
10 changes: 0 additions & 10 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,3 @@ tasks:
cmds:
- task: cov
- go tool cover -html=coverage.txt

sync:
desc: "Updates the public API Go files to match the exported interface of the modules."
cmds:
- task: cli:sync

test-gen:
desc: "Generates tests for the public API."
cmds:
- task: cli:test-gen
53 changes: 53 additions & 0 deletions cmd/core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Core CLI

This directory contains the source code for the `core` command-line interface (CLI), a tool for managing and interacting with the Core framework.

## Purpose

The CLI provides a set of commands to streamline common development tasks, such as:

- Building and running applications.
- Generating tests for the public API.
- Synchronizing API definitions.
- Generating missing documentation.

## Key Packages

The CLI's user interface is built with the help of several key packages:

- **`github.com/charmbracelet/lipgloss`**: A library for styling terminal output. We use it to add color and formatting to make the CLI's output more readable and visually appealing.

- **`github.com/common-nighthawk/go-figure`**: Used to create ASCII art text banners, giving the CLI a distinct and recognizable startup message.

- **`github.com/leaanthony/clir`**: A simple and lightweight library for creating CLI applications, and our primary framework for specific, simpler command needs.

## Examples

```go
package main

import (
"fmt"

"github.com/leaanthony/clir"
)

func main() {
// Create new cli
cli := clir.NewCli("Flags", "A simple example", "v0.0.1")

// Name
name := "Anonymous"
cli.StringFlag("name", "Your name", &name)

// Define action for the command
cli.Action(func() error {
fmt.Printf("Hello %s!\n", name)
return nil
})

if err := cli.Run(); err != nil {
fmt.Printf("Error encountered: %v\n", err)
}
}
```
10 changes: 2 additions & 8 deletions cmd/core/Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ version: '3'

includes:
cmd: "./cmd/Taskfile.yml"
dev: "./cmd/dev/Taskfile.yml"

tasks:
build:
Expand All @@ -17,7 +18,7 @@ tasks:
run:
summary: Builds and runs the core executable
cmds:
- task: build
- task: cmd:build
- cmd: chmod +x {{.TASKFILE_DIR}}/bin/core
platforms: [linux, darwin]
- "{{.TASKFILE_DIR}}/bin/core {{.CLI_ARGS}}"
Expand All @@ -30,10 +31,3 @@ tasks:
platforms: [linux, darwin]
- "{{.TASKFILE_DIR}}/bin/core dev sync"

test-gen:
summary: Generates tests for the public API
deps: [build]
cmds:
- cmd: chmod +x {{.TASKFILE_DIR}}/bin/core
platforms: [linux, darwin]
- "{{.TASKFILE_DIR}}/bin/core dev test-gen"
1 change: 1 addition & 0 deletions cmd/core/cmd/Taskfile.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
version: '3'

tasks:

build:
summary: Builds the core executable
cmds:
Expand Down
26 changes: 26 additions & 0 deletions cmd/core/cmd/dev/Taskfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: '3'

tasks:
docgen:
summary: Generates missing docstrings for the public API
deps: [build]
cmds:
- cmd: chmod +x ../../bin/core
platforms: [linux, darwin]
- "../../bin/core dev doc"
Comment on lines +8 to +10
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix path inconsistency.

The docgen task uses relative paths (../../bin/core) whilst the other tasks use {{.TASKFILE_DIR}}/bin/core. This inconsistency could cause issues if the Taskfile location changes or when tasks are invoked from different contexts.

Apply this diff to use consistent path references:

     cmds:
-      - cmd: chmod +x ../../bin/core
+      - cmd: chmod +x {{.TASKFILE_DIR}}/../../bin/core
         platforms: [linux, darwin]
-      - "../../bin/core dev doc"
+      - "{{.TASKFILE_DIR}}/../../bin/core dev doc"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- cmd: chmod +x ../../bin/core
platforms: [linux, darwin]
- "../../bin/core dev doc"
- cmd: chmod +x {{.TASKFILE_DIR}}/../../bin/core
platforms: [linux, darwin]
- "{{.TASKFILE_DIR}}/../../bin/core dev doc"
🤖 Prompt for AI Agents
In cmd/core/cmd/dev/Taskfile.yml around lines 8 to 10, the docgen task uses a
relative path ../../bin/core which is inconsistent with other tasks using
{{.TASKFILE_DIR}}/bin/core; update both the chmod command and the task
invocation to use {{.TASKFILE_DIR}}/bin/core so the Taskfile uses a stable,
location-independent reference (keep the platforms list and other task fields
unchanged).


test-gen:
summary: Generates tests for the public API
deps: [ build ]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove extra spaces from array brackets.

YAML linting flags the inconsistent spacing in deps: [ build ] and platforms: [ linux, darwin ]. Arrays should not have spaces inside brackets.

Apply this diff to fix the formatting:

-    deps: [ build ]
+    deps: [build]
     cmds:
-      - cmd: chmod +x {{.TASKFILE_DIR}}/bin/core
-        platforms: [ linux, darwin ]
+      - cmd: chmod +x {{.TASKFILE_DIR}}/../../bin/core
+        platforms: [linux, darwin]
       - "{{.TASKFILE_DIR}}/bin/core dev test-gen"

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 14-14: too many spaces inside brackets

(brackets)


[error] 14-14: too many spaces inside brackets

(brackets)

🤖 Prompt for AI Agents
In cmd/core/cmd/dev/Taskfile.yml around line 14, the array spacing is
inconsistent: change "deps: [ build ]" to remove spaces inside the brackets (use
"deps: [build]"); also find the platforms array occurrence and change
"platforms: [ linux, darwin ]" to "platforms: [linux, darwin]" so there are no
spaces directly inside the square brackets to satisfy YAML linting.

cmds:
- cmd: chmod +x {{.TASKFILE_DIR}}/bin/core
platforms: [ linux, darwin ]
- "{{.TASKFILE_DIR}}/bin/core dev test-gen"

sync:
summary: Updates the public API Go files
deps: [ build ]
cmds:
- cmd: chmod +x {{.TASKFILE_DIR}}/bin/core
platforms: [ linux, darwin ]
Comment on lines +22 to +25
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove extra spaces from array brackets.

Same formatting issue as in the test-gen task.

Apply this diff:

-    deps: [ build ]
+    deps: [build]
     cmds:
-      - cmd: chmod +x {{.TASKFILE_DIR}}/bin/core
-        platforms: [ linux, darwin ]
+      - cmd: chmod +x {{.TASKFILE_DIR}}/../../bin/core
+        platforms: [linux, darwin]
       - "{{.TASKFILE_DIR}}/bin/core dev sync"

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 22-22: too many spaces inside brackets

(brackets)


[error] 22-22: too many spaces inside brackets

(brackets)


[error] 25-25: too many spaces inside brackets

(brackets)


[error] 25-25: too many spaces inside brackets

(brackets)

🤖 Prompt for AI Agents
In cmd/core/cmd/dev/Taskfile.yml around lines 22 to 25, remove the extra spaces
inside the array brackets so the deps and platforms arrays use bracketed lists
without leading/trailing spaces: change "deps: [ build ]" to "deps: [build]" and
change "platforms: [ linux, darwin ]" to "platforms: [linux, darwin]".

- "{{.TASKFILE_DIR}}/bin/core dev sync"
2 changes: 1 addition & 1 deletion cmd/core/cmd/api.go → cmd/core/cmd/dev/api.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package cmd
package dev

import (
"github.com/leaanthony/clir"
Expand Down
115 changes: 115 additions & 0 deletions cmd/core/cmd/dev/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package dev

import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"os"
"path/filepath"
"strings"

"github.com/leaanthony/clir"
)

// AddDocCommand adds the 'doc' command to the provided clir instance.
func AddDocCommand(parent *clir.Command) {
docCmd := parent.NewSubCommand("doc", "Generate missing docstrings for the public API.")
docCmd.LongDescription(`This command scans the public API of your project and generates placeholder docstrings for any exported functions, types, or methods that are missing them.

It will also report any values that cannot be determined through reflection, providing a list of file names and line numbers that require manual attention.

If a comment already exists, it will be preserved.`)

var basePath string
docCmd.StringFlag("path", "Base path to scan for Go files (defaults to current directory)", &basePath)

docCmd.Action(func() error {
if basePath == "" {
basePath = "."
}

reports := []string{}
fset := token.NewFileSet()

err := filepath.Walk(basePath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() && (info.Name() == "vendor" || strings.HasPrefix(info.Name(), ".")) {
return filepath.SkipDir
}
if !info.IsDir() && strings.HasSuffix(path, ".go") && !strings.HasSuffix(path, "_test.go") {
fileContent, readErr := os.ReadFile(path)
if readErr != nil {
return fmt.Errorf("failed to read file %s: %w", path, readErr)
}

node, parseErr := parser.ParseFile(fset, path, fileContent, parser.ParseComments)
if parseErr != nil {
return fmt.Errorf("failed to parse file %s: %w", path, parseErr)
}

for _, decl := range node.Decls {
switch d := decl.(type) {
case *ast.GenDecl:
if d.Doc == nil || len(d.Doc.List) == 0 {
for _, spec := range d.Specs {
switch s := spec.(type) {
case *ast.TypeSpec:
if ast.IsExported(s.Name.Name) {
reports = append(reports, fmt.Sprintf("%s:%d: Missing docstring for type %s. Suggested: // %s ...", path, fset.Position(s.Pos()).Line, s.Name.Name, s.Name.Name))
}
case *ast.ValueSpec: // For var and const
for _, name := range s.Names {
if ast.IsExported(name.Name) {
reports = append(reports, fmt.Sprintf("%s:%d: Missing docstring for %s %s. Suggested: // %s ...", path, fset.Position(name.Pos()).Line, d.Tok.String(), name.Name, name.Name))
}
}
}
}
}
Comment on lines +53 to +71
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Account for spec-level doc comments

When a type, const, or var is documented via spec.Doc inside a grouped declaration, d.Doc is nil, so this code wrongly reports a missing docstring even though one exists (common pattern for grouped declarations). Please check the spec’s own comment before flagging it to avoid constant false positives.

-					case *ast.GenDecl:
-						if d.Doc == nil || len(d.Doc.List) == 0 {
+					case *ast.GenDecl:
+						genDocMissing := d.Doc == nil || len(d.Doc.List) == 0
 						for _, spec := range d.Specs {
 							switch s := spec.(type) {
 							case *ast.TypeSpec:
-								if ast.IsExported(s.Name.Name) {
+								if ast.IsExported(s.Name.Name) && (genDocMissing && (s.Doc == nil || len(s.Doc.List) == 0)) {
 									reports = append(reports, fmt.Sprintf("%s:%d: Missing docstring for type %s. Suggested: // %s ...", path, fset.Position(s.Pos()).Line, s.Name.Name, s.Name.Name))
 								}
 							case *ast.ValueSpec: // For var and const
 								for _, name := range s.Names {
-									if ast.IsExported(name.Name) {
+									if ast.IsExported(name.Name) && (genDocMissing && (s.Doc == nil || len(s.Doc.List) == 0)) {
 										reports = append(reports, fmt.Sprintf("%s:%d: Missing docstring for %s %s. Suggested: // %s ...", path, fset.Position(name.Pos()).Line, d.Tok.String(), name.Name, name.Name))
 									}
 								}
 							}
-						}
+						}

case *ast.FuncDecl:
if d.Doc == nil || len(d.Doc.List) == 0 {
if d.Name != nil && ast.IsExported(d.Name.Name) {
funcName := d.Name.Name
if d.Recv != nil && len(d.Recv.List) > 0 {
// It's a method
recvType := ""
switch rt := d.Recv.List[0].Type.(type) {
case *ast.Ident:
recvType = rt.Name
case *ast.StarExpr:
if id, ok := rt.X.(*ast.Ident); ok {
recvType = "*" + id.Name
}
}
reports = append(reports, fmt.Sprintf("%s:%d: Missing docstring for method (%s) %s. Suggested: // (%s) %s ...", path, fset.Position(d.Pos()).Line, recvType, funcName, recvType, funcName))
} else {
// It's a function
reports = append(reports, fmt.Sprintf("%s:%d: Missing docstring for function %s. Suggested: // %s ...", path, fset.Position(d.Pos()).Line, funcName, funcName))
}
}
}
}
}
}
return nil
})

if err != nil {
fmt.Fprintf(os.Stderr, "Error walking through files: %v\n", err)
return err
}

if len(reports) == 0 {
fmt.Println("No missing docstrings found for exported declarations.")
} else {
fmt.Println("Missing docstrings found:")
for _, r := range reports {
fmt.Println(r)
}
}
return nil
})
}
60 changes: 30 additions & 30 deletions cmd/core/cmd/build.go → cmd/core/cmd/dev/pwa-build.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package cmd
package dev

import (
"embed"
Expand All @@ -22,8 +22,8 @@ import (
var guiTemplate embed.FS

// AddBuildCommand adds the new build command and its subcommands to the clir app.
func AddBuildCommand(app *clir.Cli) {
buildCmd := app.NewSubCommand("build", "Builds a web application into a standalone desktop app.")
func AddBuildCommand(parent *clir.Command) {
buildCmd := parent.NewSubCommand("build", "Builds a web application into a standalone desktop app.")

// --- `build from-path` command ---
fromPathCmd := buildCmd.NewSubCommand("from-path", "Build from a local directory.")
Expand Down Expand Up @@ -81,31 +81,31 @@ func downloadPWA(baseURL, destDir string) error {
}

// Find the manifest URL from the HTML
manifestURL, err := findManifestURL(string(body), baseURL)
if err != nil {
// If no manifest, it's not a PWA, but we can still try to package it as a simple site.
fmt.Println("Warning: no manifest file found. Proceeding with basic site download.")
if err := os.WriteFile(filepath.Join(destDir, "index.html"), body, 0644); err != nil {
return fmt.Errorf("failed to write index.html: %w", err)
}
return nil
}

fmt.Printf("Found manifest: %s\n", manifestURL)

// Fetch and parse the manifest
manifest, err := fetchManifest(manifestURL)
if err != nil {
return fmt.Errorf("failed to fetch or parse manifest: %w", err)
}
//manifestURL, err := findManifestURL(string(body), baseURL)
//if err != nil {
// // If no manifest, it's not a PWA, but we can still try to package it as a simple site.
// fmt.Println("Warning: no manifest file found. Proceeding with basic site download.")
// if err := os.WriteFile(filepath.Join(destDir, "index.html"), body, 0644); err != nil {
// return fmt.Errorf("failed to write index.html: %w", err)
// }
// return nil
//}
//
//fmt.Printf("Found manifest: %s\n", manifestURL)
//
//// Fetch and parse the manifest
//manifest, err := fetchManifest(baseURL, manifestURL)
//if err != nil {
// return fmt.Errorf("failed to fetch or parse manifest: %w", err)
//}

// Download all assets listed in the manifest
assets := collectAssets(manifest, manifestURL)
for _, assetURL := range assets {
if err := downloadAsset(assetURL, destDir); err != nil {
fmt.Printf("Warning: failed to download asset %s: %v\n", assetURL, err)
}
}
//assets := collectAssets(manifest, manifestURL)
//for _, assetURL := range assets {
// if err := downloadAsset(assetURL, destDir); err != nil {
// fmt.Printf("Warning: failed to download asset %s: %v\n", assetURL, err)
// }
//}

// Also save the root index.html
if err := os.WriteFile(filepath.Join(destDir, "index.html"), body, 0644); err != nil {
Expand Down Expand Up @@ -163,18 +163,18 @@ func findManifestURL(htmlContent, baseURL string) (string, error) {
return manifestURL.String(), nil
}

func fetchManifest(manifestURL string) (map[string]interface{}, error) {
func fetchManifest(manifest map[string]interface{}, manifestURL string) (map[string]interface{}, error) {
resp, err := http.Get(manifestURL)
if err != nil {
return nil, err
}
defer resp.Body.Close()

var manifest map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&manifest); err != nil {
var manifestData map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&manifestData); err != nil {
return nil, err
}
return manifest, nil
return manifestData, nil
}

func collectAssets(manifest map[string]interface{}, manifestURL string) []string {
Expand Down
2 changes: 1 addition & 1 deletion cmd/core/cmd/sync.go → cmd/core/cmd/dev/sync.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package cmd
package dev

import (
"bytes"
Expand Down
2 changes: 1 addition & 1 deletion cmd/core/cmd/test_gen.go → cmd/core/cmd/dev/test_gen.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package cmd
package dev

import (
"bytes"
Expand Down
Loading