@rivascva/dt-idl 1.1.68 → 1.1.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,7 @@ import (
6
6
  "github.com/golang-jwt/jwt/v5"
7
7
  )
8
8
 
9
- // Validates the given JWT token using the provided secret.
9
+ // ValidateToken validates the given JWT token using the provided secret.
10
10
  func ValidateToken(token string, secret string) (*jwt.Token, error) {
11
11
  // create a JWT parser with the HS256 signing method
12
12
  parser := jwt.NewParser(jwt.WithValidMethods([]string{jwt.SigningMethodHS256.Alg()}))
@@ -14,7 +14,7 @@ func ValidateToken(token string, secret string) (*jwt.Token, error) {
14
14
  // validate the JWT token
15
15
  parsedToken, err := parser.Parse(token, func(t *jwt.Token) (any, error) { return []byte(secret), nil })
16
16
  if err != nil {
17
- return nil, fmt.Errorf("ValidateToken: unable to validate the JWT token: %w", err)
17
+ return nil, fmt.Errorf("unable to validate the JWT token: %w", err)
18
18
  }
19
19
 
20
20
  return parsedToken, nil
package/go/log/log.go ADDED
@@ -0,0 +1,88 @@
1
+ package log
2
+
3
+ import (
4
+ "fmt"
5
+ "log"
6
+ "maps"
7
+ "os"
8
+ )
9
+
10
+ type Logger interface {
11
+ // Info prints an info log message.
12
+ Info(m any)
13
+ // Warn prints a warning log message.
14
+ Warn(m any)
15
+ // Error prints an error log message.
16
+ Error(m any)
17
+ // Fatal prints an error log message and exits the program.
18
+ Fatal(m any)
19
+ // With returns a new log with the given key-value pairs.
20
+ With(kvs ...any) Logger
21
+ }
22
+
23
+ type Log struct {
24
+ kvs map[string]any
25
+ prefix string
26
+ info *log.Logger
27
+ warn *log.Logger
28
+ error *log.Logger
29
+ }
30
+
31
+ // NewLog creates a new log.
32
+ func NewLog() *Log {
33
+ return NewLogWithPrefix("")
34
+ }
35
+
36
+ // NewLogWithPrefix creates a new log with a custom prefix.
37
+ func NewLogWithPrefix(prefix string) *Log {
38
+ return &Log{
39
+ kvs: make(map[string]any, 10),
40
+ prefix: prefix,
41
+ info: log.New(os.Stdout, "[INFO] ", log.LstdFlags),
42
+ warn: log.New(os.Stdout, "[WARN] ", log.LstdFlags),
43
+ error: log.New(os.Stdout, "[ERROR] ", log.LstdFlags),
44
+ }
45
+ }
46
+
47
+ func (l *Log) Info(m any) {
48
+ l.info.Println(l.prefix, toJson(m, l.kvs))
49
+ }
50
+
51
+ func (l *Log) Warn(m any) {
52
+ l.warn.Println(l.prefix, toJson(m, l.kvs))
53
+ }
54
+
55
+ func (l *Log) Error(m any) {
56
+ l.error.Println(l.prefix, toJson(m, l.kvs))
57
+ }
58
+
59
+ func (l *Log) Fatal(m any) {
60
+ l.error.Fatal(l.prefix, toJson(m, l.kvs))
61
+ }
62
+
63
+ func (l *Log) With(kvs ...any) Logger {
64
+ // copy the existing key-value pairs into a new map
65
+ newkvs := make(map[string]any, len(l.kvs)+len(kvs))
66
+ maps.Copy(newkvs, l.kvs)
67
+
68
+ // add the new key-value pairs into the new map
69
+ for i := 0; i < len(kvs); i += 2 {
70
+ k := fmt.Sprintf("%v", kvs[i])
71
+ v := ""
72
+ if i+1 < len(kvs) {
73
+ v = fmt.Sprintf("%v", kvs[i+1])
74
+ }
75
+ newkvs[k] = v
76
+ }
77
+
78
+ return &Log{
79
+ kvs: newkvs,
80
+ prefix: l.prefix,
81
+ info: l.info,
82
+ warn: l.warn,
83
+ error: l.error,
84
+ }
85
+ }
86
+
87
+ //exhaustruct:ignore - check for interface implementation
88
+ var _ Logger = &Log{}
@@ -0,0 +1,22 @@
1
+ package log
2
+
3
+ import (
4
+ "encoding/json"
5
+ "maps"
6
+ )
7
+
8
+ // toJson converts the message and key-value pairs to a JSON string.
9
+ func toJson(m any, kvs map[string]any) string {
10
+ // copy the key-value pairs into a new map and add the message
11
+ out := make(map[string]any, len(kvs)+1)
12
+ maps.Copy(out, kvs)
13
+ out["msg"] = m
14
+
15
+ // marshal the map to a JSON byte array
16
+ data, err := json.Marshal(out)
17
+ if err != nil {
18
+ return err.Error()
19
+ }
20
+
21
+ return string(data)
22
+ }
@@ -6,16 +6,18 @@ import (
6
6
  "slices"
7
7
  "strings"
8
8
 
9
+ "github.com/RivasCVA/dt-idl/go/jwt"
10
+ "github.com/RivasCVA/dt-idl/go/log"
9
11
  "github.com/RivasCVA/dt-idl/go/models"
10
- "github.com/RivasCVA/dt-idl/go/utils/jwt"
11
- "github.com/RivasCVA/dt-idl/go/utils/logger"
12
- "github.com/RivasCVA/dt-idl/go/utils/responder"
12
+ "github.com/RivasCVA/dt-idl/go/write"
13
13
  )
14
14
 
15
- // Returns a middleware function that authenticates all requests except for the login endpoints.
15
+ // GetAuthMiddleware returns a middleware function that authenticates all requests, except for the login endpoints.
16
16
  // It attaches the token to the request context.
17
17
  func GetAuthMiddleware(secret string) func(http.Handler) http.Handler {
18
- responder := responder.NewStandardResponder(logger.NewConsoleLoggerWithPrefix("GetAuthMiddleware:"), "ERROR")
18
+ log := log.NewLog().With("method", "GetAuthMiddleware")
19
+ write := write.NewWrite("ERROR", log)
20
+
19
21
  return func(next http.Handler) http.Handler {
20
22
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
21
23
  // check if the request is a login endpoint
@@ -28,14 +30,14 @@ func GetAuthMiddleware(secret string) func(http.Handler) http.Handler {
28
30
  authorizationHeader := r.Header.Get("Authorization")
29
31
  arr := strings.Split(authorizationHeader, " ")
30
32
  if len(arr) != 2 || arr[0] != "Bearer" {
31
- responder.WriteError(w, http.StatusUnauthorized, "invalid authorization header")
33
+ write.ResponseWithError(w, http.StatusUnauthorized, "invalid authorization header")
32
34
  return
33
35
  }
34
36
 
35
37
  // validate the token
36
38
  token, err := jwt.ValidateToken(arr[1], secret)
37
39
  if err != nil {
38
- responder.WriteError(w, http.StatusUnauthorized, "invalid token")
40
+ write.ResponseWithError(w, http.StatusUnauthorized, "invalid token")
39
41
  return
40
42
  }
41
43
 
@@ -48,7 +50,7 @@ func GetAuthMiddleware(secret string) func(http.Handler) http.Handler {
48
50
  }
49
51
  }
50
52
 
51
- // Adds shared headers to all responses.
53
+ // CommonHeaders adds shared headers to all responses.
52
54
  func CommonHeaders(next http.Handler) http.Handler {
53
55
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
54
56
  w.Header().Add("content-type", "application/json")
@@ -1,7 +1,9 @@
1
1
  package models
2
2
 
3
- // ContextKey is the type used to define keys for the request context.
3
+ // ContextKey is a type used to define keys for a request context.
4
4
  type ContextKey string
5
5
 
6
- // TokenKey is the key used to store the JWT token in the request context.
7
- const TokenKey = ContextKey("token")
6
+ const (
7
+ // TokenKey is the key used to set/get the JWT token in the request context.
8
+ TokenKey = ContextKey("token")
9
+ )
@@ -1,4 +1,4 @@
1
- package fetch
1
+ package request
2
2
 
3
3
  import (
4
4
  "encoding/json"
@@ -6,9 +6,12 @@ import (
6
6
  "net/http"
7
7
  )
8
8
 
9
- // Makes a GET request to the given url.
10
- //
11
- // Parses the JSON-encoded response and stores the result into v.
9
+ type Response struct {
10
+ StatusCode int
11
+ }
12
+
13
+ // Get makes a GET request to the given url.
14
+ // It parses the JSON-encoded response and stores the result into v.
12
15
  func Get(url string, v any) (*Response, error) {
13
16
  // make the GET request
14
17
  resp, err := http.Get(url)
@@ -0,0 +1,17 @@
1
+ package utils
2
+
3
+ import (
4
+ "context"
5
+
6
+ "github.com/RivasCVA/dt-idl/go/models"
7
+ "github.com/golang-jwt/jwt/v5"
8
+ )
9
+
10
+ // GetTokenFromContext retrieves the JWT token from the given context.
11
+ func GetTokenFromContext(ctx context.Context) *jwt.Token {
12
+ token, ok := ctx.Value(models.TokenKey).(*jwt.Token)
13
+ if !ok {
14
+ return nil
15
+ }
16
+ return token
17
+ }
@@ -0,0 +1,10 @@
1
+ package utils
2
+
3
+ // MapKeys returns the keys of the given map as a slice.
4
+ func MapKeys[K ~string, V any](m map[K]V) []K {
5
+ keys := make([]K, 0, len(m))
6
+ for k := range m {
7
+ keys = append(keys, k)
8
+ }
9
+ return keys
10
+ }
@@ -1,14 +1,13 @@
1
- package url
1
+ package utils
2
2
 
3
3
  import (
4
4
  "fmt"
5
5
  "net/url"
6
6
  )
7
7
 
8
- // Builds a url string from the given base and path.
9
- //
10
- // Encodes any given query parameters into the url.
11
- func Build(base string, path string, params map[string]any) (string, error) {
8
+ // BuildUrl builds a url string from the given base and path.
9
+ // It encodes any given query parameters into the url.
10
+ func BuildUrl(base string, path string, params map[string]any) (string, error) {
12
11
  // parse the combined base and path
13
12
  url, err := url.Parse(base + path)
14
13
  if err != nil {
@@ -1,8 +1,7 @@
1
- package responder
1
+ package write
2
2
 
3
- // Base error struct.
4
- //
5
- // The struct should match the base "Error" schema in all services.
3
+ // Error is a shared error schema.
4
+ // The struct should match the base Error schema in all services.
6
5
  type Error[T ~string] struct {
7
6
  Status int64 `json:"status"`
8
7
  Code T `json:"code"`
@@ -0,0 +1,75 @@
1
+ package write
2
+
3
+ import (
4
+ "encoding/json"
5
+ "net/http"
6
+
7
+ "github.com/RivasCVA/dt-idl/go/log"
8
+ )
9
+
10
+ type Writer[T ~string] interface {
11
+ // Response writes a JSON response to the given response writer.
12
+ // The given data is converted to JSON. An error response is written if the marshal fails.
13
+ Response(w http.ResponseWriter, status int, data any)
14
+ // ResponseWithError writes a JSON error response to the given response writer.
15
+ // The response is based on the shared Error schema.
16
+ ResponseWithError(w http.ResponseWriter, status int, message string)
17
+ // ResponseWithErrorCode writes a JSON error response with a specific code to the given response writer.
18
+ // The response is based on the shared Error schema.
19
+ ResponseWithErrorCode(w http.ResponseWriter, status int, code T, message string)
20
+ }
21
+
22
+ type Write[T ~string] struct {
23
+ baseError T
24
+ log log.Logger
25
+ }
26
+
27
+ func NewWrite[T ~string](baseError T, log log.Logger) *Write[T] {
28
+ return &Write[T]{
29
+ baseError: baseError,
30
+ log: log,
31
+ }
32
+ }
33
+
34
+ func (r *Write[T]) Response(w http.ResponseWriter, status int, data any) {
35
+ // encode the given data object
36
+ out, err := json.Marshal(data)
37
+ if err != nil {
38
+ r.log.With("err", err).Error("failed to marshal the data")
39
+ r.ResponseWithError(w, http.StatusInternalServerError, "error encoding the data")
40
+ return
41
+ }
42
+
43
+ // write the data to the given writer
44
+ w.WriteHeader(status)
45
+ _, err = w.Write(out)
46
+ if err != nil {
47
+ r.log.With("err", err).Fatal("failed to write the response")
48
+ }
49
+ }
50
+
51
+ func (r *Write[T]) ResponseWithError(w http.ResponseWriter, status int, message string) {
52
+ r.ResponseWithErrorCode(w, status, r.baseError, message)
53
+ }
54
+
55
+ func (r *Write[T]) ResponseWithErrorCode(w http.ResponseWriter, status int, code T, message string) {
56
+ // encode an error object with the given message
57
+ out, err := json.Marshal(Error[T]{
58
+ Status: int64(status),
59
+ Code: code,
60
+ Message: message,
61
+ })
62
+ if err != nil {
63
+ r.log.With("err", err).Fatal("failed to marshal the error")
64
+ }
65
+
66
+ // write the data to the given writer
67
+ w.WriteHeader(status)
68
+ _, err = w.Write(out)
69
+ if err != nil {
70
+ r.log.With("err", err).Fatal("failed to write the response")
71
+ }
72
+ }
73
+
74
+ //exhaustruct:ignore - check for interface implementation
75
+ var _ Writer[string] = &Write[string]{}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rivascva/dt-idl",
3
- "version": "1.1.68",
3
+ "version": "1.1.70",
4
4
  "description": "Dream Trade - Interface Definition Language",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",
@@ -1,6 +0,0 @@
1
- package fetch
2
-
3
- // Base fetch response struct.
4
- type Response struct {
5
- StatusCode int
6
- }
@@ -1,56 +0,0 @@
1
- package logger
2
-
3
- import (
4
- "fmt"
5
- "log"
6
- "os"
7
- )
8
-
9
- type Logger interface {
10
- // Prints an info log message.
11
- Info(v ...any)
12
- // Prints a warning log message.
13
- Warn(v ...any)
14
- // Prints an error log message.
15
- Error(v ...any)
16
- // Prints an error log message and exits the program.
17
- Fatal(v ...any)
18
- }
19
-
20
- type ConsoleLogger struct {
21
- prefix string
22
- info *log.Logger
23
- warn *log.Logger
24
- error *log.Logger
25
- }
26
-
27
- // Creates a new console logger.
28
- func NewConsoleLogger() *ConsoleLogger {
29
- return NewConsoleLoggerWithPrefix("")
30
- }
31
-
32
- // Creates a new logger with a custom prefix.
33
- func NewConsoleLoggerWithPrefix(prefix string) *ConsoleLogger {
34
- return &ConsoleLogger{
35
- prefix: prefix,
36
- info: log.New(os.Stdout, "[INFO] ", log.LstdFlags),
37
- warn: log.New(os.Stdout, "[WARN] ", log.LstdFlags),
38
- error: log.New(os.Stdout, "[ERROR] ", log.LstdFlags),
39
- }
40
- }
41
-
42
- func (l *ConsoleLogger) Info(v ...any) {
43
- l.info.Println(l.prefix, fmt.Sprint(v...))
44
- }
45
-
46
- func (l *ConsoleLogger) Warn(v ...any) {
47
- l.warn.Println(l.prefix, fmt.Sprint(v...))
48
- }
49
-
50
- func (l *ConsoleLogger) Error(v ...any) {
51
- l.error.Println(l.prefix, fmt.Sprint(v...))
52
- }
53
-
54
- func (l *ConsoleLogger) Fatal(v ...any) {
55
- l.error.Fatal(l.prefix, fmt.Sprint(v...))
56
- }
@@ -1,10 +0,0 @@
1
- package maps
2
-
3
- // Returns the keys of the given map as a slice.
4
- func Keys[K ~string, V any](m map[K]V) []K {
5
- keys := make([]K, 0, len(m))
6
- for k := range m {
7
- keys = append(keys, k)
8
- }
9
- return keys
10
- }
@@ -1,76 +0,0 @@
1
- package responder
2
-
3
- import (
4
- "encoding/json"
5
- "fmt"
6
- "net/http"
7
-
8
- "github.com/RivasCVA/dt-idl/go/utils/logger"
9
- )
10
-
11
- type Responder[T ~string] interface {
12
- // Writes a JSON response to the given response writer.
13
- //
14
- // The given data is converted to JSON. An error response is written if the marshal fails.
15
- Write(w http.ResponseWriter, status int, data any)
16
- // Writes a JSON error response to the given response writer.
17
- //
18
- // The response is based on the shared "Error" schema.
19
- WriteError(w http.ResponseWriter, status int, message string)
20
- // Writes a JSON error response with a specific code to the given response writer.
21
- //
22
- // The response is based on the shared "Error" schema.
23
- WriteErrorWithCode(w http.ResponseWriter, status int, code T, message string)
24
- }
25
-
26
- type StandardResponder[T ~string] struct {
27
- logger logger.Logger
28
- defaultCode T
29
- }
30
-
31
- func NewStandardResponder[T ~string](logger logger.Logger, defaultCode T) *StandardResponder[T] {
32
- return &StandardResponder[T]{
33
- logger: logger,
34
- defaultCode: defaultCode,
35
- }
36
- }
37
-
38
- func (r *StandardResponder[T]) Write(w http.ResponseWriter, status int, data any) {
39
- // encode the given data object
40
- out, err := json.Marshal(data)
41
- if err != nil {
42
- r.logger.Error(fmt.Errorf("Write: failed to marshal the data: %w", err))
43
- r.WriteError(w, http.StatusInternalServerError, "error encoding the data")
44
- return
45
- }
46
-
47
- // write the data to the given writer
48
- w.WriteHeader(status)
49
- _, err = w.Write(out)
50
- if err != nil {
51
- r.logger.Fatal(fmt.Errorf("Write: failed to write a response: %w", err))
52
- }
53
- }
54
-
55
- func (r *StandardResponder[T]) WriteError(w http.ResponseWriter, status int, message string) {
56
- r.WriteErrorWithCode(w, status, r.defaultCode, message)
57
- }
58
-
59
- func (r *StandardResponder[T]) WriteErrorWithCode(w http.ResponseWriter, status int, code T, message string) {
60
- // encode an error object with the given message
61
- out, err := json.Marshal(Error[T]{
62
- Status: int64(status),
63
- Code: code,
64
- Message: message,
65
- })
66
- if err != nil {
67
- r.logger.Fatal(fmt.Errorf("WriteErrorWithCode: failed to marshal the error: %w", err))
68
- }
69
-
70
- // write the data to the given writer
71
- w.WriteHeader(status)
72
- _, err = w.Write(out)
73
- if err != nil {
74
- r.logger.Fatal(fmt.Errorf("WriteErrorWithCode: failed to write a response: %w", err))
75
- }
76
- }