Skip to content

Commit

Permalink
Initial project
Browse files Browse the repository at this point in the history
  • Loading branch information
htquangg committed Jul 27, 2024
0 parents commit e9ec188
Show file tree
Hide file tree
Showing 17 changed files with 1,148 additions and 0 deletions.
21 changes: 21 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# http://editorconfig.org
root = true

[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
tab_width = 2
insert_final_newline = true
trim_trailing_whitespace = true
max_line_length = 100

[*.go]
indent_style = tab

[*.{yml, yaml}]
indent_style = tab

[Makefile]
indent_style = tab
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Test binary, build with `go test -c`
*.test

# Coverage
coverage.txt
profile.cov

*.out

#Debug
__debug_bin*
debug

# IDE
.idea
.vscode
.DS_STORE
105 changes: 105 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
run:
concurrency: 4
timeout: 10m
go: '1.22'

linters-settings:
gocyclo:
min-complexity: 25
dupl:
threshold: 100
goconst:
min-len: 2
min-occurrences: 3
misspell:
locale: US
goimports:
local-prefixes: github.com/htquangg/avault
gocritic:
enabled-tags:
- diagnostic
- experimental
- opinionated
- performance
- style
disabled-checks:
- wrapperFunc
- ifElseChain
funlen:
lines: 350
statements: 200
revive:
# default rules derived from upstream revive repo
# https://github.com/walles/revive/blob/f417cbd57c6d90b43bdb7f113c222e5aeef117e5/defaults.toml
rules:
- name: blank-imports
- name: context-as-argument
- name: context-keys-type
- name: dot-imports
- name: error-return
- name: error-strings
- name: error-naming
- name: exported
# - name: if-return
- name: increment-decrement
- name: var-naming
- name: var-declaration
- name: package-comments
- name: range
- name: receiver-naming
- name: time-naming
- name: unexported-return
- name: indent-error-flow
- name: errorf
- name: empty-block
- name: superfluous-else
# - name: unused-parameter
- name: unreachable-code
- name: redefines-builtin-id

linters:
disable-all: true
enable:
- bodyclose
# - deadcode
# - depguard
- dogsled
# - dupl
# - errcheck
- funlen
- gocritic
- gocyclo
# - gofmt
- goimports
- revive
# - gosec
- gosimple
- govet
- ineffassign
- misspell
- nakedret
- exportloopref
- staticcheck
# - structcheck
- stylecheck
- typecheck
- unconvert
- unused
# - varcheck
- whitespace
- goconst
- unused
# - gochecknoinits

issues:
exclude-dirs:
- .artifacts
- .codecov
- .github
- build
- deploy
- proto
- tools
exclude:
- consider giving a name to these results
- include an explanation for nolint directive
22 changes: 22 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.PHONY: generate-proto
generate-proto: ## generate proto
buf generate

.PHONY: lint
lint: ## lint
@echo "Linting"
golangci-lint run \
--timeout 10m \
--config ./.golangci.yaml \
--out-format=github-actions \
--concurrency=$$(getconf _NPROCESSORS_ONLN)

.PHONY: test
test: ## run the go tests
go test -coverprofile cover.out ./...

.PHONY: help
help: ## print help
@awk 'BEGIN {FS = ":.*##"; printf "Usage:\n make \033[36m\033[0m\n"} /^[$$()% 0-9a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

.DEFAULT_GOAL := help
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# AErrors

Builds on Go 1.22 errors by adding HTTP statuses and GRPC codes to them.

## Installation

go get -u github.com/htquangg/aerrors

## Prerequisites

Go 1.22
148 changes: 148 additions & 0 deletions aerrors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package aerrors

import (
"bytes"
"errors"
"fmt"
"reflect"
)

type TypeCoder interface {
TypeCode() string
}

type ErrorCode string

func (err ErrorCode) TypeCode() string {
if err == ErrOK {
return ""
}
return string(err)
}

func (err ErrorCode) Error() string {
if err == ErrOK {
return ""
}

return string(err)
}

type AError struct {
code ErrorCode
parent error
reason string
message string
stack string
}

func New(code ErrorCode, reason string) *AError {
return &AError{code: code, reason: reason}
}

func (err *AError) Code() ErrorCode {
return err.code
}

func (err *AError) Parent() error {
return err.parent
}

func (err *AError) Reason() string {
return err.reason
}

func (err *AError) Message() string {
return err.message
}

func (err *AError) Stack() string {
return err.stack
}

func (err *AError) WithCode(code ErrorCode) *AError {
if err == nil {
return nil
}
err.code = code
return err
}

func (err *AError) WithParent(parent error) *AError {
if err == nil {
return nil
}
err.parent = parent
return err
}

func (err *AError) WithReason(reason string) *AError {
if err == nil {
return nil
}
err.reason = reason
return err
}

func (err *AError) WithMessage(message string) *AError {
if err == nil {
return nil
}
err.message = message
return err
}

func (err *AError) WithStack() *AError {
if err == nil {
return nil
}
err.message = LogStack(2, 0)
return err
}

// nolint:gocritic
func (err AError) Error() string {
str := bytes.NewBuffer([]byte{})
fmt.Fprintf(str, "code: %s, ", err.code.Error())
str.WriteString("reason: ")
str.WriteString(err.reason + ", ")
str.WriteString("message: ")
str.WriteString(err.message)
if err.parent != nil {
str.WriteString(", error: ")
str.WriteString(err.parent.Error())
}
if err.stack != "" {
str.WriteString("\n")
str.WriteString(err.stack)
}

return str.String()
}

func (err *AError) Is(target error) bool {
t, ok := target.(*AError)
if !ok {
return false
}
if t.code != ErrOK && t.code != err.code {
return false
}
if t.message != "" && t.message != err.message {
return false
}
if t.parent != nil && !errors.Is(err.parent, t.parent) {
return false
}

return true
}

func (err *AError) As(target interface{}) bool {
_, ok := target.(**AError)
if !ok {
return false
}
reflect.Indirect(reflect.ValueOf(target)).Set(reflect.ValueOf(err))
return true
}
26 changes: 26 additions & 0 deletions aerrors_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package aerrors

import (
"fmt"
"testing"
)

func TestNew(t *testing.T) {
e := A()
fmt.Printf("%s\n\n", e)
fmt.Printf("%v\n\n", e)
}

func A() error {
return B()
}

func B() error {
return C()
}

func C() error {
return Internal("internal server error").
WithParent(fmt.Errorf("db connection error")).
WithStack()
}
12 changes: 12 additions & 0 deletions buf.gen.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: v1
managed:
enabled: true
go_package_prefix:
default: github.com/htquang/aerrors;aerrors
except:
- buf.build/googleapis/googleapis
plugins:
- name: go
out: .
opt:
- paths=source_relative
9 changes: 9 additions & 0 deletions buf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: v1
lint:
enum_zero_value_suffix: _UNKNOWN
except:
- PACKAGE_VERSION_SUFFIX
- PACKAGE_DIRECTORY_MATCH
breaking:
use:
- FILE
Loading

0 comments on commit e9ec188

Please sign in to comment.