diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 0e27423..f860e69 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -10,30 +10,42 @@ on: branches: [ "develop" ] jobs: - - build: + run: + name: Build runs-on: ubuntu-latest + timeout-minutes: 5 + strategy: + fail-fast: true + matrix: + go: ['stable', 'oldstable'] + steps: - - uses: actions/checkout@v4 + - name: Check out code + uses: actions/checkout@v3 + + - name: Install Go + uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.go }} + check-latest: true + + - name: Go Format + run: gofmt -s -w . && git diff --exit-code + + - name: Go Vet + run: go vet ./... - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: '1.21.5' + - name: Go Tidy + run: go mod tidy && git diff --exit-code - - name: Cache Go modules - uses: actions/cache@v2 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- + - name: Go Mod + run: go mod download - - name: Install dependencies - run: go mod download + - name: Go Mod Verify + run: go mod verify - - name: Build - run: go build -v ./... + - name: Go Generate + run: go generate ./... && git diff --exit-code - - name: Test - run: go test -v ./... + - name: Go Build + run: go build -o /dev/null ./... diff --git a/README.md b/README.md index 69143d4..a378b24 100644 --- a/README.md +++ b/README.md @@ -14,17 +14,7 @@ Phase 2: Phase 3: * Interactable UI * Have a UI in which you can interact with the transactions - give them additional metadata such as tags, photos (receipts/invoices) - * Mutate the graphs - apply filters to change what the graphs output - - -## Notes - -* To generate the open-api interface run the following command: -``` -sudo docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate -i /local/openapi.json -g go -o /local/expense-manager/up-bank-interface -``` - - + * Mutate the graphs - apply filters to change what the graphs output ## Modules @@ -67,6 +57,10 @@ LICENSE ``` This will stop the generator from generating those files (which will mess up the Go compilation) +4. Generate the TEMPL components +`templ generate` + + * Note if you're finding it hard to run `templ`, it might be because `$GOPATH` is not on your `$PATH` so your computer can't find the executable. In that case either update your path or run `./$GOPATH/templ` 4. Format code `gofmt -s -w .` diff --git a/datafetcher/handlers/accounts.go b/datafetcher/handlers/accounts.go new file mode 100644 index 0000000..5facf25 --- /dev/null +++ b/datafetcher/handlers/accounts.go @@ -0,0 +1,42 @@ +package handlers + +import ( + "context" + "fmt" + "log" + "net/http" + + "github.com/esteanes/expense-manager/datafetcher/upclient" +) + +type AccountHandler struct { + *BaseHandler +} + +func NewAccountHandler(log *log.Logger, upclient *upclient.APIClient, auth context.Context) *AccountHandler { + handler := &AccountHandler{} + handler.BaseHandler = &BaseHandler{ + Uri: "/accounts", + Log: log, + UpClient: upclient, + UpAuth: auth, + Handler: handler, // Set the Handler interface to the specific handler + } + return handler +} + +func (h *AccountHandler) Post(w http.ResponseWriter, r *http.Request) {} +func (h *AccountHandler) Get(w http.ResponseWriter, r *http.Request) { + pageSize := int32(30) + filterAccountType := upclient.AccountTypeEnum("SAVER") + filterOwnershipType := upclient.OwnershipTypeEnum("INDIVIDUAL") + resp, r2, err := h.UpClient.AccountsAPI.AccountsGet(h.UpAuth).PageSize(pageSize).FilterAccountType(filterAccountType).FilterOwnershipType(filterOwnershipType).Execute() + + if err != nil { + fmt.Fprintf(w, "Error when calling `AccountsAPI.AccountsGet``: %v\n", err) + fmt.Fprintf(w, "Full HTTP response: %v\n", r2) + h.Log.Println("Unable to get account information") + } + + fmt.Fprintf(w, "Response from `AccountsAPI.AccountsGet`: %v\n", resp) +} diff --git a/datafetcher/handlers/basehandler.go b/datafetcher/handlers/basehandler.go new file mode 100644 index 0000000..70c2a52 --- /dev/null +++ b/datafetcher/handlers/basehandler.go @@ -0,0 +1,33 @@ +package handlers + +import ( + "context" + "log" + "net/http" + + "github.com/esteanes/expense-manager/datafetcher/upclient" +) + +type Handler interface { + Post(w http.ResponseWriter, r *http.Request) + Get(w http.ResponseWriter, r *http.Request) +} + +type BaseHandler struct { + Uri string + Log *log.Logger + UpClient *upclient.APIClient + UpAuth context.Context + Handler Handler // Embed the Handler interface +} + +func (h *BaseHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case http.MethodPost: + h.Handler.Post(w, r) + case http.MethodGet: + h.Handler.Get(w, r) + default: + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + } +} diff --git a/datafetcher/handlers/transactions.go b/datafetcher/handlers/transactions.go new file mode 100644 index 0000000..a48ae86 --- /dev/null +++ b/datafetcher/handlers/transactions.go @@ -0,0 +1,39 @@ +package handlers + +import ( + "context" + "fmt" + "log" + "net/http" + "os" + + "github.com/esteanes/expense-manager/datafetcher/upclient" +) + +type TransactionsHandler struct { + *BaseHandler +} + +func NewTransactionHandler(log *log.Logger, upclient *upclient.APIClient, auth context.Context) *AccountHandler { + handler := &AccountHandler{} + handler.BaseHandler = &BaseHandler{ + Uri: "/transactions", + Log: log, + UpClient: upclient, + UpAuth: auth, + Handler: handler, // Set the Handler interface to the specific handler + } + return handler +} + +func (h *TransactionsHandler) Post(w http.ResponseWriter, r *http.Request) {} +func (h *TransactionsHandler) Get(w http.ResponseWriter, r *http.Request) { + pageSize := int32(30) // int32 | The number of records to return in each page. (optional) + resp2, r2, err := h.UpClient.TransactionsAPI.TransactionsGet(h.UpAuth).PageSize(pageSize).Execute() + if err != nil { + fmt.Fprintf(os.Stderr, "Error when calling `TransactionsAPI.TransactionsGet``: %v\n", err) + fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r2.Body) + } + // response from `TransactionsGet`: ListTransactionsResponse + fmt.Fprintf(os.Stdout, "Response from `TransactionsAPI.TransactionsGet`: %v\n", resp2) +} diff --git a/datafetcher/server.go b/datafetcher/server.go index caba004..177fdcd 100644 --- a/datafetcher/server.go +++ b/datafetcher/server.go @@ -5,9 +5,14 @@ import ( "fmt" "log" "net/http" - "os" + "time" + "github.com/a-h/templ" + "github.com/esteanes/expense-manager/datafetcher/handlers" + templates "github.com/esteanes/expense-manager/datafetcher/templ" "github.com/esteanes/expense-manager/datafetcher/upclient" + + "github.com/alexedwards/scs/v2" ) // homePage function to handle requests to the root URL @@ -17,36 +22,84 @@ func homePage(w http.ResponseWriter, r *http.Request) { } func getInfo(w http.ResponseWriter, r *http.Request) { - pageSize := int32(30) // int32 | The number of records to return in each page. (optional) - filterAccountType := upclient.AccountTypeEnum("SAVER") // AccountTypeEnum | The type of account for which to return records. This can be used to filter Savers from spending accounts. (optional) - filterOwnershipType := upclient.OwnershipTypeEnum("INDIVIDUAL") // OwnershipTypeEnum | The account ownership structure for which to return records. This can be used to filter 2Up accounts from Up accounts. (optional) - auth := context.WithValue(context.Background(), upclient.ContextAccessToken, os.Getenv("up-bank-bearer-token")) - configuration := upclient.NewConfiguration() - apiClient := upclient.NewAPIClient(configuration) - resp, r2, err := apiClient.AccountsAPI.AccountsGet(auth).PageSize(pageSize).FilterAccountType(filterAccountType).FilterOwnershipType(filterOwnershipType).Execute() - if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `AccountsAPI.AccountsGet``: %v\n", err) - fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r2) - } - // response from `AccountsGet`: ListAccountsResponse - fmt.Fprintf(os.Stdout, "Response from `AccountsAPI.AccountsGet`: %v\n", resp) +} + +func NewNowHandler(now func() time.Time) NowHandler { + return NowHandler{Now: now} +} + +type NowHandler struct { + Now func() time.Time +} + +func (nh NowHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + templates.TimeComponent(nh.Now()).Render(r.Context(), w) +} + +type GlobalState struct { + Count int +} - resp2, r2, err := apiClient.TransactionsAPI.TransactionsGet(auth).PageSize(pageSize).Execute() - if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `TransactionsAPI.TransactionsGet``: %v\n", err) - fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r2.Body) +var global GlobalState +var sessionManager *scs.SessionManager + +func getHandler(w http.ResponseWriter, r *http.Request) { + userCount := sessionManager.GetInt(r.Context(), "count") + component := templates.Page(global.Count, userCount) + component.Render(r.Context(), w) +} + +func postHandler(w http.ResponseWriter, r *http.Request) { + // Update state. + r.ParseForm() + + // Check to see if the global button was pressed. + if r.Form.Has("global") { + global.Count++ } - // response from `TransactionsGet`: ListTransactionsResponse - fmt.Fprintf(os.Stdout, "Response from `TransactionsAPI.TransactionsGet`: %v\n", resp2) + //TODO: Update session. + if r.Form.Has("user") { + currentCount := sessionManager.GetInt(r.Context(), "count") + sessionManager.Put(r.Context(), "count", currentCount+1) + } + // Display the form. + getHandler(w, r) +} +func handleInfo(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodPost { + postHandler(w, r) + return + } + getHandler(w, r) } // HandleRequests function to define the routes and start the server -func HandleRequests() { - http.HandleFunc("/", homePage) // Set the root URL to call homePage function - http.HandleFunc("/info", getInfo) - log.Default().Println("Serving request at localhost:8080") - log.Fatal(http.ListenAndServe(":8080", nil)) // Start the server on port 8080 +func HandleRequests(upBankToken string, log *log.Logger) { + sessionManager = scs.New() + sessionManager.Lifetime = 24 * time.Hour + auth := context.WithValue(context.Background(), upclient.ContextAccessToken, upBankToken) + + configuration := upclient.NewConfiguration() + apiClient := upclient.NewAPIClient(configuration) + + accountHandler := handlers.NewAccountHandler(log, apiClient, auth) + transactionsHandler := handlers.NewTransactionHandler(log, apiClient, auth) + component := templates.Hello("its ya boi") + mux := http.NewServeMux() + mux.HandleFunc(accountHandler.Uri, accountHandler.ServeHTTP) + mux.HandleFunc(transactionsHandler.Uri, transactionsHandler.ServeHTTP) + + mux.HandleFunc("/", homePage) + mux.HandleFunc("/info", getInfo) + mux.Handle("/time", NewNowHandler(time.Now)) + mux.Handle("/hello", templ.Handler(component)) + mux.HandleFunc("/counter", handleInfo) + log.Println("Serving request at localhost:8080") + muxWithSessionMiddleware := sessionManager.LoadAndSave(mux) + if err := http.ListenAndServe("localhost:8080", muxWithSessionMiddleware); err != nil { + log.Printf("error listening: %v", err) + } } diff --git a/datafetcher/templ/components.templ b/datafetcher/templ/components.templ new file mode 100644 index 0000000..2bbda5a --- /dev/null +++ b/datafetcher/templ/components.templ @@ -0,0 +1,31 @@ +package templ + +import ( + "strconv" + "time" +) +templ TimeComponent(d time.Time) { +
{ d.String() }
+} + +templ NotFoundComponent() { +
404 - Not found
+} + + +templ counts(global, user int) { +
Global: { strconv.Itoa(global) }
+
User: { strconv.Itoa(user) }
+} + +templ form() { +
+
+
+
+} + +templ Page(global, user int) { + @counts(global, user) + @form() +} \ No newline at end of file diff --git a/datafetcher/templ/components_templ.go b/datafetcher/templ/components_templ.go new file mode 100644 index 0000000..3b37a7e --- /dev/null +++ b/datafetcher/templ/components_templ.go @@ -0,0 +1,187 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.747 +package templ + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import templruntime "github.com/a-h/templ/runtime" + +import ( + "strconv" + "time" +) + +func TimeComponent(d time.Time) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var1 := templ.GetChildren(ctx) + if templ_7745c5c3_Var1 == nil { + templ_7745c5c3_Var1 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var2 string + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(d.String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templ/components.templ`, Line: 8, Col: 18} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func NotFoundComponent() templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var3 := templ.GetChildren(ctx) + if templ_7745c5c3_Var3 == nil { + templ_7745c5c3_Var3 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
404 - Not found
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func counts(global, user int) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var4 := templ.GetChildren(ctx) + if templ_7745c5c3_Var4 == nil { + templ_7745c5c3_Var4 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Global: ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var5 string + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(global)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templ/components.templ`, Line: 17, Col: 36} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
User: ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var6 string + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(user)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templ/components.templ`, Line: 18, Col: 32} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func form() templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var7 := templ.GetChildren(ctx) + if templ_7745c5c3_Var7 == nil { + templ_7745c5c3_Var7 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func Page(global, user int) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var8 := templ.GetChildren(ctx) + if templ_7745c5c3_Var8 == nil { + templ_7745c5c3_Var8 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = counts(global, user).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = form().Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} diff --git a/datafetcher/templ/hello.templ b/datafetcher/templ/hello.templ new file mode 100644 index 0000000..6f6255e --- /dev/null +++ b/datafetcher/templ/hello.templ @@ -0,0 +1,5 @@ +package templ + +templ Hello(name string) { +
Hello, { name }
+} \ No newline at end of file diff --git a/datafetcher/templ/hello_templ.go b/datafetcher/templ/hello_templ.go new file mode 100644 index 0000000..ea0fb7d --- /dev/null +++ b/datafetcher/templ/hello_templ.go @@ -0,0 +1,48 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.747 +package templ + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import templruntime "github.com/a-h/templ/runtime" + +func Hello(name string) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var1 := templ.GetChildren(ctx) + if templ_7745c5c3_Var1 == nil { + templ_7745c5c3_Var1 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Hello, ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var2 string + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(name) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templ/hello.templ`, Line: 4, Col: 19} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} diff --git a/go.mod b/go.mod index 47020ba..b34b192 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,11 @@ module github.com/esteanes/expense-manager go 1.21.5 -require github.com/stretchr/testify v1.9.0 +require ( + github.com/a-h/templ v0.2.747 + github.com/alexedwards/scs/v2 v2.8.0 + github.com/stretchr/testify v1.9.0 +) require ( github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/go.sum b/go.sum index 60ce688..4fbc7cf 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,11 @@ +github.com/a-h/templ v0.2.747 h1:D0dQ2lxC3W7Dxl6fxQ/1zZHBQslSkTSvl5FxP/CfdKg= +github.com/a-h/templ v0.2.747/go.mod h1:69ObQIbrcuwPCU32ohNaWce3Cb7qM5GMiqN1K+2yop4= +github.com/alexedwards/scs/v2 v2.8.0 h1:h31yUYoycPuL0zt14c0gd+oqxfRwIj6SOjHdKRZxhEw= +github.com/alexedwards/scs/v2 v2.8.0/go.mod h1:ToaROZxyKukJKT/xLcVQAChi5k6+Pn1Gvmdl7h3RRj8= 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/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= diff --git a/main.go b/main.go index f8dc27b..a3e3a5d 100644 --- a/main.go +++ b/main.go @@ -2,10 +2,14 @@ package main import ( "fmt" + "log" + "os" + "github.com/esteanes/expense-manager/datafetcher" ) func main() { fmt.Println("Starting server on port 8080...") - datafetcher.HandleRequests() + logger := log.New(os.Stdout, "datafetcher:", log.Default().Flags()) + datafetcher.HandleRequests(os.Getenv("UP_BANK_TOKEN"), logger) }