Compare commits

..

4 Commits

Author SHA1 Message Date
627cfa36f5
Merge pull request 'Refactor and document StoneError with enhanced features' (#1) from feature/stone-error-implementation into develop
All checks were successful
Go CI/CD / go-ci (push) Successful in 10m12s
Go CI/CD / go-ci (pull_request) Successful in 10m7s
Reviewed-on: #1
Reviewed-by: Cloud Administrator <cloud-admin@noreply.gitstormr.dev>
2025-04-12 18:25:08 -06:00
bcb4a3008d
Add unwrap tests for normal and stone errors
All checks were successful
Go CI/CD / go-ci (push) Successful in 10m43s
Go CI/CD / go-ci (pull_request) Successful in 10m7s
Introduce tests to validate the behavior of the Unwrap function for both standard errors and StoneError instances. Ensure correct handling of wrapped errors and verify type identification with IsStoneError checks.
2025-04-12 17:53:48 -06:00
24ea252c96
Add unit tests for stoneerror package
All checks were successful
Go CI/CD / go-ci (pull_request) Successful in 10m37s
Go CI/CD / go-ci (push) Successful in 10m38s
Introduce comprehensive tests for core functionalities including error creation, metadata handling, wrapping, JSON conversion, and type validation. These tests ensure robustness and reliability of the stoneerror package.
2025-04-12 17:42:47 -06:00
b42137701b
Refactor and document StoneError with enhanced features
Some checks failed
Go CI/CD / go-ci (push) Failing after 5m34s
Go CI/CD / go-ci (pull_request) Failing after 5m29s
Updated module path and significantly extended the StoneError implementation with new functionality, including metadata handling, error wrapping, JSON serialization, and utilities like `IsStoneError`. Enhanced README with detailed examples, usage guidelines, and a thematic introduction.
2025-04-12 17:24:44 -06:00
4 changed files with 291 additions and 3 deletions

123
README.md
View File

@ -1,3 +1,122 @@
# stoneerror
# ๐Ÿ”ฅ StoneError - 10 Billion Times Error Handling!
Ultimate Go error toolkit! ๐Ÿ’Ž Standardized errors with custom codes, rich metadata & JSON superpowers. Perfect for APIs & microservices. Part of stone-utils ecosystem. Error handling, evolved! ๐Ÿš€
The most scientifically precise error library from the Kingdom of Science!
[![Kingdom of Science Approved](https://img.shields.io/badge/Approved%20By-Kingdom%20of%20Science-blueviolet)]()
[![SO BADASS](https://img.shields.io/badge/Science-SO_BADASS!-blueviolet)]()
[![10 BILLION](https://img.shields.io/badge/10_Billion%25-Reliable-blueviolet)]()
## ๐Ÿš€ Why StoneError?
- Dr.Stone-themed error handling that would make Senku proud
- Dramatic error traces worthy of a laboratory explosion
- Scientific metadata attached to every error case
- 10 billion percent more organized than standard errors
## ๐Ÿ’ฅ Installation
```bash
go get gitstormr.dev/stone-utils/stoneerror@latest
```
## โšก Basic Usage
```go
package main
import (
"errors"
"fmt"
"gitstormr.dev/stone-utils/stoneerror"
)
func main() {
// Create new scientific error
err := stoneerror.New(4001, "Invalid chemical formula").
WithMetadata("element", "H2O2").
WithMetadata("expected", "H2O")
// Wrap existing errors with scientific precision
dbErr := errors.New("connection timeout")
wrappedErr := stoneerror.Wrap(dbErr, 5001, "Database experiment failed").
WithMetadata("query", "SELECT * FROM chemical_elements")
}
```
## ๐Ÿ”ฌ Error Output Format
```text
StoneError [4001]
โ”œโ”€ Message: Invalid chemical formula
โ”œโ”€ Time: 2023-07-15T14:30:45Z
โ”œโ”€ Metadata:
โ”‚ โ”œโ”€ element: H2O2
โ”‚ โ”œโ”€ expected: H2O
โ””โ”€ Caused by:
StoneError [5001]
โ”œโ”€ Message: Database experiment failed
โ”œโ”€ Time: 2023-07-15T14:30:45Z
โ”œโ”€ Metadata:
โ”‚ โ”œโ”€ query: SELECT * FROM chemical_elements
โ””โ”€ Caused by:
connection timeout
```
## ๐Ÿงช Core Features
### Scientific Error Codes
```go
const (
LAB_FAILURE = 5000 // Critical experiment failure
BAD_CHEMISTRY = 4001 // Invalid formula or mixture
EQUIPMENT_FAIL = 5002 // Tools malfunction
)
```
### Advanced Error Wrapping
```go
// Wrap any error with scientific context
result := performExperiment()
if err != nil {
return stoneerror.Wrap(err, LAB_FAILURE, "Voltaic pile test failed")
.WithMetadata("voltage", "3.7V")
.WithMetadata("materials", []string{"zinc", "copper"})
}
```
### JSON Output
```go
jsonError := err.ToJSON()
// {
// "code": 4001,
// "message": "Invalid chemical formula",
// "time": "2023-07-15T14:30:45Z",
// "metadata": {
// "element": "H2O2",
// "expected": "H2O"
// }
// }
```
```go
stonelog.InitStoneLab(stonelog.STONE_DEBUG, true, false) // true = JSON, false = Keep suffixes
// Output: {"time":"2023-07-15T12:00:00Z","level":"OBSERVATION","message":"โœ… Experiment successful: System ready","caller":"main.go:15"}
```
## โš—๏ธ Scientific Best Practices
1. Always use specific error codes - Each experiment needs proper labeling!
2. Attach relevant metadata - A good scientist documents everything
3. Wrap underlying errors - Trace the full chain of causality
4. Combine related failures - Multiple data points lead to better conclusions
**Join the Scientific Revolution!**
> "With StoneError, we're 10 billion percent prepared for any failure!" - Senku Ishigami
Kingdom of Science Approved
(Now with 100% more Chrome screaming "SO BADASS!")

View File

@ -1,9 +1,19 @@
package stoneerror
import (
"encoding/json"
"errors"
"fmt"
"regexp"
"time"
)
// StoneError represents a structured error type with metadata and nested errors.
// Code indicates the error code for categorization.
// Message describes the error in a human-readable format.
// Time specifies when the error occurred.
// Metadata provides additional contextual data for the error.
// Err holds an underlying error causing the StoneError.
type StoneError struct {
Code int `json:"code"`
Message string `json:"message"`
@ -11,3 +21,83 @@ type StoneError struct {
Metadata map[string]interface{} `json:"metadata"`
Err error `json:"-"`
}
// Error returns the formatted string representation of the StoneError.
func (e *StoneError) Error() string {
var errorStr string
errorStr = fmt.Sprintf("[%d] %s", e.Code, e.Message)
if len(e.Metadata) > 0 {
errorStr += "\n Metadata:"
for k, v := range e.Metadata {
errorStr += fmt.Sprintf("\n %s: %v", k, v)
}
}
if e.Err != nil {
errorStr += fmt.Sprintf("\n Caused by: %v", e.Err)
var nestedStoneErr *StoneError
if errors.As(e.Err, &nestedStoneErr) {
errorStr += "\n" + indentString(nestedStoneErr.Error(), " ")
}
}
return errorStr
}
// New creates a new instance of StoneError with the provided code and message.
// It initializes the time to the current UTC time and sets Metadata as an empty map.
func New(code int, message string) *StoneError {
return &StoneError{
Code: code,
Message: message,
Time: time.Now().UTC(),
Metadata: make(map[string]interface{}),
}
}
// Wrap creates a new StoneError with a code, message, and wrapped error.
func Wrap(err error, code int, message string) *StoneError {
return &StoneError{
Code: code,
Message: message,
Time: time.Now().UTC(),
Err: err,
Metadata: make(map[string]interface{}),
}
}
// Unwrap returns the underlying error wrapped by the StoneError instance.
func (e *StoneError) Unwrap() error {
return e.Err
}
// WithMetadata adds a key-value pair to the error's metadata and returns the error.
func (e *StoneError) WithMetadata(key string, value interface{}) *StoneError {
if e.Metadata == nil {
e.Metadata = make(map[string]interface{})
}
e.Metadata[key] = value
return e
}
// ToJSON serializes the StoneError object into a JSON RawMessage.
func (e *StoneError) ToJSON() json.RawMessage {
jsonData, _ := json.Marshal(e)
return jsonData
}
// IsStoneError checks if the given error is of type *StoneError.
func IsStoneError(err error) bool {
var stoneError *StoneError
as := errors.As(err, &stoneError)
return as
}
// indentString prepends each line of string s with the given indent string.
func indentString(s string, indent string) string {
return indent + regexp.MustCompile("\n").ReplaceAllString(s, "\n"+indent)
}

79
error_test.go Normal file
View File

@ -0,0 +1,79 @@
package stoneerror
import (
"errors"
"testing"
)
func Test_StoneErrorWithoutMetadata(t *testing.T) {
stoneError := New(1, "test")
t.Log(stoneError)
}
func Test_StoneErrorWithMetadata(t *testing.T) {
stoneError := New(1, "test").
WithMetadata("key", "value").
WithMetadata("key2", "value2")
t.Log(stoneError)
}
func Test_NormalWrap(t *testing.T) {
normalError := errors.New("test")
stoneError := Wrap(normalError, 1, "test")
t.Log(stoneError)
}
func Test_StoneWrap(t *testing.T) {
originalError := New(1, "test").
WithMetadata("key", "value").
WithMetadata("key2", "value2")
stoneError := Wrap(originalError, 1, "test")
t.Log(stoneError)
}
func Test_NormalUnwrap(t *testing.T) {
normalError := errors.New("test")
stoneError := Wrap(normalError, 1, "test")
unwrap := stoneError.Unwrap()
if IsStoneError(unwrap) {
t.Fail()
} else {
t.Log(stoneError)
}
}
func Test_StoneUnwrap(t *testing.T) {
normalError := New(1, "test")
stoneError := Wrap(normalError, 1, "test")
unwrap := stoneError.Unwrap()
if !IsStoneError(unwrap) {
t.Fail()
} else {
t.Log(stoneError)
}
}
func Test_ToJSON(t *testing.T) {
stoneError := New(1, "test").
WithMetadata("key", "value").
WithMetadata("key2", "value2")
jsonData := stoneError.ToJSON()
t.Log(string(jsonData))
}
func Test_IsStoneError(t *testing.T) {
stoneError := New(1, "test").
WithMetadata("key", "value")
if IsStoneError(stoneError) {
t.Log("Is stone error")
} else {
t.Fail()
}
}

2
go.mod
View File

@ -1,3 +1,3 @@
module stoneerror
module gitstormr.dev/stone-utils/stoneerror
go 1.24