├── .air.toml
├── .gitignore
├── LICENSE.md
├── Makefile
├── README.md
├── app
├── README.md
├── components
│ └── button.templ
├── css
│ └── app.css
├── handlers
│ └── profile.go
├── main.go
└── views
│ └── profile.templ
├── auth
├── README.md
├── login.go
├── login.templ
├── register.go
└── register.templ
├── go.mod
├── go.sum
├── lib
├── README.md
├── auth.go
├── base.templ
├── htmx.go
└── render.go
├── main.go
├── middleware
├── README.md
└── auth.go
├── model
├── README.md
└── crud.go
├── package-lock.json
├── package.json
├── public
├── README.md
├── assets
│ └── bytesize_banner.svg
├── index.js
└── styles.css
└── tailwind.config.js
/.air.toml:
--------------------------------------------------------------------------------
1 | root = "."
2 | testdata_dir = "testdata"
3 | tmp_dir = "tmp"
4 |
5 | [build]
6 | args_bin = ["serve"]
7 | bin = "./tmp/main"
8 | cmd = "go build -o ./tmp/main ."
9 | delay = 1000
10 | exclude_dir = ["assets", "tmp", "vendor", "testdata"]
11 | exclude_file = []
12 | exclude_regex = ["_test.go"]
13 | exclude_unchanged = false
14 | follow_symlink = false
15 | full_bin = ""
16 | include_dir = []
17 | include_ext = ["go", "tpl", "tmpl", "html"]
18 | include_file = []
19 | kill_delay = "0s"
20 | log = "build-errors.log"
21 | poll = false
22 | poll_interval = 0
23 | post_cmd = []
24 | pre_cmd = []
25 | rerun = false
26 | rerun_delay = 500
27 | send_interrupt = false
28 | stop_on_error = false
29 |
30 | [color]
31 | app = ""
32 | build = "yellow"
33 | main = "magenta"
34 | runner = "green"
35 | watcher = "cyan"
36 |
37 | [log]
38 | main_only = false
39 | time = false
40 |
41 | [misc]
42 | clean_on_exit = false
43 |
44 | [proxy]
45 | app_port = 0
46 | enabled = false
47 | proxy_port = 0
48 |
49 | [screen]
50 | clear_on_rebuild = false
51 | keep_scroll = true
52 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Environment variables
2 | .env
3 |
4 | # Node modules
5 | node_modules/
6 |
7 | # Build directories
8 | bin
9 |
10 | # Temporary files
11 | tmp/
12 |
13 | # Compiled Go files
14 | *_templ.go
15 |
16 | # Pocketbase data
17 | pb_data/
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 cmcd97
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Load environment variables from .env file
2 | ifneq (,$(wildcard ./.env))
3 | include .env
4 | export
5 | endif
6 |
7 | run: build
8 | @./bin/app serve
9 |
10 | build:
11 | @go build -o bin/app .
12 |
13 | dev:
14 | @make air & make css & make templ
15 |
16 | air:
17 | @air
18 |
19 | css:
20 | @tailwindcss -i app/css/app.css -o public/styles.css --watch
21 |
22 | templ:
23 | @templ generate --watch --proxy="http://localhost$(LISTEN_ADDR)" --open-browser=true
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bytesize is a web application template designed to help you kickstart your web development projects with ease. The core philosophy of Bytesize is simplicity and lightweight performance.
6 |
7 | ## Features
8 |
9 | - **Preconfigured Pocketbase Backend**: Easily manage your backend with Pocketbase.
10 | - **Modern Frontend Stack**: Utilizes Templ, HTMX, Tailwind CSS, and DaisyUI for a seamless and responsive user interface.
11 | - **Hot Reloading**: Air is preconfigured to enable hot reloading in the browser, enhancing your development workflow.
12 |
13 | ## Prerequisites
14 |
15 | Before you begin, ensure you have the following installed:
16 |
17 | 1. **Go**: [Download Go](https://go.dev/dl/)
18 | 2. **Node and NPM**: [Download Node.js and NPM](https://nodejs.org/en)
19 | 3. **Air**: Install Air with the following command:
20 | ```sh
21 | curl -sSfL https://raw.githubusercontent.com/air-verse/air/master/install.sh | sh -s -- -b $(go env GOPATH)/bin
22 | ```
23 | Then, alias Air (if Air is not found):
24 | ```sh
25 | alias air='$(go env GOPATH)/bin/air'
26 | ```
27 | 4. **Templ**: Install Templ with the following command:
28 |
29 | Note: You may need to run the `templ generate --watch --proxy="http://localhost:3000" --open-browser=true` command manually the first time before using the makefile command.
30 |
31 | ```sh
32 | go install github.com/a-h/templ/cmd/templ@latest
33 | ```
34 |
35 | Add the Go path to your shell configuration file (`~/.bashrc` or `~/.zshrc`):
36 |
37 | ```sh
38 | export PATH=$PATH:$(go env GOPATH)/bin
39 | ```
40 |
41 | Source the file:
42 |
43 | ```sh
44 | source ~/.bashrc
45 | # or
46 | source ~/.zshrc
47 | ```
48 |
49 | Check the Templ version:
50 |
51 | ```sh
52 | templ --version
53 | ```
54 |
55 | 5. **TailwindCSS**: Install TailwindCSS with NPM:
56 | ```sh
57 | npm install -D tailwindcss
58 | ```
59 | Initialize TailwindCSS:
60 | ```sh
61 | npx tailwindcss init
62 | ```
63 |
64 | ## Getting Started
65 |
66 | To get started with Bytesize, follow these steps:
67 |
68 | 1. **Clone the Repository**:
69 |
70 | ```sh
71 | git clone https://github.com/cmcd97/bytesize.git
72 | cd bytesize
73 | ```
74 |
75 | 2. **Install Dependencies**:
76 |
77 | ```sh
78 | go mod tidy
79 | npm install
80 | ```
81 |
82 | you make also need to run `templ generate` to generate the go files otherwise you will get an error stating that your local packages are not found
83 |
84 | 3. **Run the Application in Development Mode**:
85 |
86 | ```sh
87 | make dev
88 | ```
89 |
90 | 4. **Build the Binary**:
91 |
92 | If you just want to build the binary you will find an `app` binary in the `./bin` directory after running this command. Ensure that you are building for the desired OS.
93 |
94 | ```sh
95 | make build
96 | ```
97 |
98 | ## Documentation
99 |
100 | Every directory contains a `README.md` file which explains the purpose of the directory and how you can make use of it. Feel free to delete these if you want, they are only there to help provide context to the repo structure.
101 |
102 | #### Disclaimer
103 |
104 | A large amount of the documentation is generated by ChatGPT, I will update it as I use this template in my future projects, otherwise feel free submit improvements
105 |
106 | ## Real world examples:
107 |
108 | Submit a PR or create an issue to add your projects here
109 |
110 | - [OffsideFPL](https://offsidefpl.com/): A fresh take on Fantasy Premier League (FPL), designed to raise the stakes in your mini leagues! Each week, managers compete to climb the leaderboard while avoiding suspension.
111 | - [Repository Link](https://github.com/Connorrmcd6/offsidefpl)
112 |
113 | ## Inspiration
114 |
115 | I started learning Go by building webapps with HTMX and Templ. I learned a lot from the [Anthony GG]('https://www.youtube.com/@anthonygg_") YouTube channel and based my first template off of this [video](https://www.youtube.com/live/FU1kYukjwJM?si=51mLdiNyjPCKHnd6) and the [Superkit](https://github.com/anthdm/superkit) repo. After building a few apps with this template I wanted to try an integrate [Pocketbase](https://github.com/pocketbase/pocketbase). I came across [pocketbase-htmx](https://github.com/gobeli/pocketbase-htmx) from a reddit thread. I really liked the project structure of this repo but it didn't include any hot reloading (Air) or any sort of styling. Bytesize is my attempt of taking the hot reloading and UI styling from [Superkit](https://github.com/anthdm/superkit) and combining it with the project structure of [pocketbase-htmx](https://github.com/gobeli/pocketbase-htmx).
116 |
--------------------------------------------------------------------------------
/app/README.md:
--------------------------------------------------------------------------------
1 | # App Package
2 |
3 | This directory contains most of the application logic and is organized into four main subdirectories:
4 |
5 | - **`components`**: Standalone Templ components that can be reused across multiple places, such as custom buttons, tables, and navbars.
6 | - **`css`**: The output directory where Tailwind writes its custom CSS classes.
7 | - **`handlers`**: Custom HTTP handlers.
8 | - **`views`**: Similar to the `components` directory, but contains Templ components that represent entire pages. These pages are typically used in a single location within the app and often utilize components from the `components` directory.
9 |
--------------------------------------------------------------------------------
/app/components/button.templ:
--------------------------------------------------------------------------------
1 | package components
2 |
3 | templ Button() {
4 | Primary
5 | }
6 |
--------------------------------------------------------------------------------
/app/css/app.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
--------------------------------------------------------------------------------
/app/handlers/profile.go:
--------------------------------------------------------------------------------
1 | package handlers
2 |
3 | import (
4 | "github.com/cmcd97/bytesize/app/views"
5 | "github.com/cmcd97/bytesize/lib"
6 | "github.com/labstack/echo/v5"
7 | "github.com/pocketbase/pocketbase/apis"
8 | "github.com/pocketbase/pocketbase/models"
9 | )
10 |
11 | func ProfileGet(c echo.Context) error {
12 | var record *models.Record = c.Get(apis.ContextAuthRecordKey).(*models.Record)
13 | return lib.Render(c, 200, views.Profile(record))
14 | }
15 |
--------------------------------------------------------------------------------
/app/main.go:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | import (
4 | "github.com/cmcd97/bytesize/app/handlers"
5 | "github.com/cmcd97/bytesize/middleware"
6 | "github.com/labstack/echo/v5"
7 | "github.com/pocketbase/pocketbase"
8 | "github.com/pocketbase/pocketbase/core"
9 | )
10 |
11 | func InitAppRoutes(e *core.ServeEvent, pb *pocketbase.PocketBase) {
12 | appGroup := e.Router.Group("/app", middleware.LoadAuthContextFromCookie(pb), middleware.AuthGuard)
13 |
14 | appGroup.GET("", func(c echo.Context) error {
15 | return c.Redirect(303, "profile")
16 | })
17 | appGroup.GET("/profile", handlers.ProfileGet)
18 |
19 | e.Router.GET("/", func(c echo.Context) error {
20 | return c.Redirect(303, "/app")
21 | })
22 | }
23 |
--------------------------------------------------------------------------------
/app/views/profile.templ:
--------------------------------------------------------------------------------
1 | package views
2 |
3 | import (
4 | "github.com/cmcd97/bytesize/lib"
5 | "github.com/pocketbase/pocketbase/models"
6 | )
7 |
8 | templ Profile(user *models.Record) {
9 | @lib.BaseLayout() {
10 |
11 |
12 |
13 | Bytesize
14 |
15 |
16 |
19 |
20 |
21 |
22 |
28 |
29 |
git clone https://github.com/cmcd97/bytesize.git
30 |
cd bytesize
31 |
go mod tidy
32 |
npm install
33 |
installing...
34 |
Done!
35 |
36 |
37 |
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/auth/README.md:
--------------------------------------------------------------------------------
1 | # Authentication Package
2 |
3 | The `auth` directory contains all code related to user authentication. This module is intentionally kept separate from the rest of the application logic, as it is generally the only section that can be accessed without prior authentication.
4 |
5 | The directory includes the following files:
6 |
7 | - **`login.go`**: Manages user authentication routes. It defines the `LoginFormValue` struct for capturing login form data and includes validation logic. The `RegisterLoginRoutes` function sets up the `/login` and `/logout` routes:
8 |
9 | - **`/login` GET**: Renders the login page.
10 | - **`/login` POST**: Processes login form submissions, validates credentials, and handles authentication. If authentication fails, it re-renders the login form with error messages.
11 | - **`/logout` POST**: Clears the authentication cookie and redirects the user to the login page.
12 |
13 | This file integrates with Echo for routing, Pocketbase for user management, and Templ for rendering components.
14 |
15 | - **`login.templ`**: Contains the HTML/HTMX code for the login page.
16 |
17 | - **`register.go`**: Manages user registration routes. It defines the `RegisterFormValue` struct for capturing registration form data and includes validation logic. The `RegisterRegisterRoutes` function sets up the `/register` route:
18 |
19 | - **`/register` GET**: Renders the registration page.
20 | - **`/register` POST**: Processes registration form submissions, validates the input, and creates a new user. If validation or registration fails, it re-renders the form with error messages.
21 |
22 | This file integrates with Echo for routing, Pocketbase for user management, and Templ for rendering components.
23 |
24 | - **`register.templ`**: Contains the HTML/HTMX code for the registration page.
25 |
--------------------------------------------------------------------------------
/auth/login.go:
--------------------------------------------------------------------------------
1 | package auth
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/a-h/templ"
7 | "github.com/cmcd97/bytesize/lib"
8 | "github.com/cmcd97/bytesize/middleware"
9 | validation "github.com/go-ozzo/ozzo-validation/v4"
10 |
11 | "github.com/labstack/echo/v5"
12 | "github.com/pocketbase/pocketbase/apis"
13 | "github.com/pocketbase/pocketbase/core"
14 | )
15 |
16 | type LoginFormValue struct {
17 | username string
18 | password string
19 | }
20 |
21 | func (lfv LoginFormValue) Validate() error {
22 | return validation.ValidateStruct(&lfv,
23 | validation.Field(&lfv.username, validation.Required, validation.Length(3, 50)),
24 | validation.Field(&lfv.password, validation.Required),
25 | )
26 | }
27 |
28 | func getLoginFormValue(c echo.Context) LoginFormValue {
29 | return LoginFormValue{
30 | username: c.FormValue("username"),
31 | password: c.FormValue("password"),
32 | }
33 | }
34 |
35 | func RegisterLoginRoutes(e *core.ServeEvent, group echo.Group) {
36 | group.GET("/login", func(c echo.Context) error {
37 | if c.Get(apis.ContextAuthRecordKey) != nil {
38 | return c.Redirect(302, "/app/profile")
39 | }
40 |
41 | return lib.Render(c, 200, Login(LoginFormValue{}, nil))
42 | })
43 |
44 | group.POST("/login", func(c echo.Context) error {
45 | form := getLoginFormValue(c)
46 | err := form.Validate()
47 |
48 | if err == nil {
49 | err = lib.Login(e, c, form.username, form.password)
50 | }
51 |
52 | if err != nil {
53 | component := lib.HtmxRender(
54 | c,
55 | func() templ.Component { return LoginForm(form, err) },
56 | func() templ.Component { return Login(form, err) },
57 | )
58 | return lib.Render(c, 200, component)
59 | }
60 |
61 | return lib.HtmxRedirect(c, "/app/profile")
62 | })
63 |
64 | group.POST("/logout", func(c echo.Context) error {
65 | c.SetCookie(&http.Cookie{
66 | Name: middleware.AuthCookieName,
67 | Value: "",
68 | Path: "/",
69 | Secure: true,
70 | HttpOnly: true,
71 | MaxAge: -1,
72 | })
73 |
74 | return lib.HtmxRedirect(c, "/auth/login")
75 | })
76 | }
77 |
--------------------------------------------------------------------------------
/auth/login.templ:
--------------------------------------------------------------------------------
1 | package auth
2 |
3 | import "github.com/cmcd97/bytesize/lib"
4 |
5 | templ Login(form LoginFormValue, err error) {
6 | @lib.BaseLayout() {
7 | @LoginForm(form, err)
8 | }
9 | }
10 |
11 | templ LoginForm(form LoginFormValue, err error) {
12 |
65 | }
66 |
--------------------------------------------------------------------------------
/auth/register.go:
--------------------------------------------------------------------------------
1 | package auth
2 |
3 | import (
4 | "github.com/a-h/templ"
5 | "github.com/cmcd97/bytesize/lib"
6 | validation "github.com/go-ozzo/ozzo-validation/v4"
7 |
8 | "github.com/labstack/echo/v5"
9 | "github.com/pocketbase/pocketbase/apis"
10 | "github.com/pocketbase/pocketbase/core"
11 | )
12 |
13 | type RegisterFormValue struct {
14 | username string
15 | password string
16 | passwordRepeat string
17 | }
18 |
19 | func (rfv RegisterFormValue) Validate() error {
20 | return validation.ValidateStruct(&rfv,
21 | validation.Field(&rfv.username, validation.Required, validation.Length(3, 50)),
22 | validation.Field(&rfv.password, validation.Required),
23 | )
24 | }
25 |
26 | func getRegisterFormValue(c echo.Context) RegisterFormValue {
27 | return RegisterFormValue{
28 | username: c.FormValue("username"),
29 | password: c.FormValue("password"),
30 | passwordRepeat: c.FormValue("passwordRepeat"),
31 | }
32 | }
33 |
34 | func RegisterRegisterRoutes(e *core.ServeEvent, group echo.Group) {
35 | group.GET("/register", func(c echo.Context) error {
36 | if c.Get(apis.ContextAuthRecordKey) != nil {
37 | return c.Redirect(302, "/app/profile")
38 | }
39 |
40 | return lib.Render(c, 200, Register(RegisterFormValue{}, nil))
41 | })
42 |
43 | group.POST("/register", func(c echo.Context) error {
44 | form := getRegisterFormValue(c)
45 | err := form.Validate()
46 |
47 | if err == nil {
48 | err = lib.Register(e, c, form.username, form.password, form.passwordRepeat)
49 | }
50 |
51 | if err != nil {
52 | component := lib.HtmxRender(
53 | c,
54 | func() templ.Component { return RegisterForm(form, err) },
55 | func() templ.Component { return Register(form, err) },
56 | )
57 | return lib.Render(c, 200, component)
58 | }
59 |
60 | return lib.HtmxRedirect(c, "/app/profile")
61 | })
62 | }
63 |
--------------------------------------------------------------------------------
/auth/register.templ:
--------------------------------------------------------------------------------
1 | package auth
2 |
3 | import "github.com/cmcd97/bytesize/lib"
4 |
5 | templ Register(form RegisterFormValue, err error) {
6 | @lib.BaseLayout() {
7 | @RegisterForm(form, err)
8 | }
9 | }
10 |
11 | templ RegisterForm(form RegisterFormValue, err error) {
12 |
69 | }
70 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/cmcd97/bytesize
2 |
3 | go 1.22.5
4 |
5 | require (
6 | github.com/a-h/templ v0.2.778
7 | github.com/go-ozzo/ozzo-validation/v4 v4.3.0
8 | github.com/joho/godotenv v1.5.1
9 | github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61
10 | github.com/pocketbase/dbx v1.10.1
11 | github.com/pocketbase/pocketbase v0.22.20
12 | )
13 |
14 | require (
15 | github.com/AlecAivazis/survey/v2 v2.3.7 // indirect
16 | github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
17 | github.com/aws/aws-sdk-go-v2 v1.30.4 // indirect
18 | github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.4 // indirect
19 | github.com/aws/aws-sdk-go-v2/config v1.27.31 // indirect
20 | github.com/aws/aws-sdk-go-v2/credentials v1.17.30 // indirect
21 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 // indirect
22 | github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.15 // indirect
23 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 // indirect
24 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 // indirect
25 | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
26 | github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.16 // indirect
27 | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect
28 | github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.18 // indirect
29 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 // indirect
30 | github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.16 // indirect
31 | github.com/aws/aws-sdk-go-v2/service/s3 v1.60.1 // indirect
32 | github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 // indirect
33 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 // indirect
34 | github.com/aws/aws-sdk-go-v2/service/sts v1.30.5 // indirect
35 | github.com/aws/smithy-go v1.20.4 // indirect
36 | github.com/disintegration/imaging v1.6.2 // indirect
37 | github.com/domodwyer/mailyak/v3 v3.6.2 // indirect
38 | github.com/dustin/go-humanize v1.0.1 // indirect
39 | github.com/fatih/color v1.17.0 // indirect
40 | github.com/gabriel-vasile/mimetype v1.4.5 // indirect
41 | github.com/ganigeorgiev/fexpr v0.4.1 // indirect
42 | github.com/goccy/go-json v0.10.3 // indirect
43 | github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
44 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
45 | github.com/google/uuid v1.6.0 // indirect
46 | github.com/googleapis/gax-go/v2 v2.13.0 // indirect
47 | github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
48 | github.com/inconshreveable/mousetrap v1.1.0 // indirect
49 | github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
50 | github.com/mattn/go-colorable v0.1.13 // indirect
51 | github.com/mattn/go-isatty v0.0.20 // indirect
52 | github.com/mattn/go-sqlite3 v1.14.22 // indirect
53 | github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
54 | github.com/ncruces/go-strftime v0.1.9 // indirect
55 | github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
56 | github.com/spf13/cast v1.7.0 // indirect
57 | github.com/spf13/cobra v1.8.1 // indirect
58 | github.com/spf13/pflag v1.0.5 // indirect
59 | github.com/valyala/bytebufferpool v1.0.0 // indirect
60 | github.com/valyala/fasttemplate v1.2.2 // indirect
61 | go.opencensus.io v0.24.0 // indirect
62 | gocloud.dev v0.39.0 // indirect
63 | golang.org/x/crypto v0.26.0 // indirect
64 | golang.org/x/image v0.19.0 // indirect
65 | golang.org/x/net v0.28.0 // indirect
66 | golang.org/x/oauth2 v0.22.0 // indirect
67 | golang.org/x/sync v0.8.0 // indirect
68 | golang.org/x/sys v0.24.0 // indirect
69 | golang.org/x/term v0.23.0 // indirect
70 | golang.org/x/text v0.17.0 // indirect
71 | golang.org/x/time v0.6.0 // indirect
72 | golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 // indirect
73 | google.golang.org/api v0.194.0 // indirect
74 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed // indirect
75 | google.golang.org/grpc v1.65.0 // indirect
76 | google.golang.org/protobuf v1.34.2 // indirect
77 | modernc.org/gc/v3 v3.0.0-20240801135723-a856999a2e4a // indirect
78 | modernc.org/libc v1.55.3 // indirect
79 | modernc.org/mathutil v1.6.0 // indirect
80 | modernc.org/memory v1.8.0 // indirect
81 | modernc.org/sqlite v1.32.0 // indirect
82 | modernc.org/strutil v1.2.0 // indirect
83 | modernc.org/token v1.1.0 // indirect
84 | )
85 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
2 | cloud.google.com/go v0.115.1 h1:Jo0SM9cQnSkYfp44+v+NQXHpcHqlnRJk2qxh6yvxxxQ=
3 | cloud.google.com/go v0.115.1/go.mod h1:DuujITeaufu3gL68/lOFIirVNJwQeyf5UXyi+Wbgknc=
4 | cloud.google.com/go/auth v0.9.1 h1:+pMtLEV2k0AXKvs/tGZojuj6QaioxfUjOpMsG5Gtx+w=
5 | cloud.google.com/go/auth v0.9.1/go.mod h1:Sw8ocT5mhhXxFklyhT12Eiy0ed6tTrPMCJjSI8KhYLk=
6 | cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY=
7 | cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc=
8 | cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
9 | cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY=
10 | cloud.google.com/go/iam v1.1.13 h1:7zWBXG9ERbMLrzQBRhFliAV+kjcRToDTgQT3CTwYyv4=
11 | cloud.google.com/go/iam v1.1.13/go.mod h1:K8mY0uSXwEXS30KrnVb+j54LB/ntfZu1dr+4zFMNbus=
12 | cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs=
13 | cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0=
14 | filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
15 | filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
16 | github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
17 | github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
18 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
19 | github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
20 | github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
21 | github.com/a-h/templ v0.2.778 h1:VzhOuvWECrwOec4790lcLlZpP4Iptt5Q4K9aFxQmtaM=
22 | github.com/a-h/templ v0.2.778/go.mod h1:lq48JXoUvuQrU0VThrK31yFwdRjTCnIE5bcPCM9IP1w=
23 | github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
24 | github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
25 | github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
26 | github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU=
27 | github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
28 | github.com/aws/aws-sdk-go-v2 v1.30.4 h1:frhcagrVNrzmT95RJImMHgabt99vkXGslubDaDagTk8=
29 | github.com/aws/aws-sdk-go-v2 v1.30.4/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0=
30 | github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.4 h1:70PVAiL15/aBMh5LThwgXdSQorVr91L127ttckI9QQU=
31 | github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.4/go.mod h1:/MQxMqci8tlqDH+pjmoLu1i0tbWCUP1hhyMRuFxpQCw=
32 | github.com/aws/aws-sdk-go-v2/config v1.27.31 h1:kxBoRsjhT3pq0cKthgj6RU6bXTm/2SgdoUMyrVw0rAI=
33 | github.com/aws/aws-sdk-go-v2/config v1.27.31/go.mod h1:z04nZdSWFPaDwK3DdJOG2r+scLQzMYuJeW0CujEm9FM=
34 | github.com/aws/aws-sdk-go-v2/credentials v1.17.30 h1:aau/oYFtibVovr2rDt8FHlU17BTicFEMAi29V1U+L5Q=
35 | github.com/aws/aws-sdk-go-v2/credentials v1.17.30/go.mod h1:BPJ/yXV92ZVq6G8uYvbU0gSl8q94UB63nMT5ctNO38g=
36 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 h1:yjwoSyDZF8Jth+mUk5lSPJCkMC0lMy6FaCD51jm6ayE=
37 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12/go.mod h1:fuR57fAgMk7ot3WcNQfb6rSEn+SUffl7ri+aa8uKysI=
38 | github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.15 h1:ijB7hr56MngOiELJe0C5aQRaBQ11LveNgWFyG02AUto=
39 | github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.15/go.mod h1:0QEmQSSWMVfiAk93l1/ayR9DQ9+jwni7gHS2NARZXB0=
40 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 h1:TNyt/+X43KJ9IJJMjKfa3bNTiZbUP7DeCxfbTROESwY=
41 | github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16/go.mod h1:2DwJF39FlNAUiX5pAc0UNeiz16lK2t7IaFcm0LFHEgc=
42 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 h1:jYfy8UPmd+6kJW5YhY0L1/KftReOGxI/4NtVSTh9O/I=
43 | github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16/go.mod h1:7ZfEPZxkW42Afq4uQB8H2E2e6ebh6mXTueEpYzjCzcs=
44 | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ=
45 | github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc=
46 | github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.16 h1:mimdLQkIX1zr8GIPY1ZtALdBQGxcASiBd2MOp8m/dMc=
47 | github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.16/go.mod h1:YHk6owoSwrIsok+cAH9PENCOGoH5PU2EllX4vLtSrsY=
48 | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 h1:KypMCbLPPHEmf9DgMGw51jMj77VfGPAN2Kv4cfhlfgI=
49 | github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4/go.mod h1:Vz1JQXliGcQktFTN/LN6uGppAIRoLBR2bMvIMP0gOjc=
50 | github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.18 h1:GckUnpm4EJOAio1c8o25a+b3lVfwVzC9gnSBqiiNmZM=
51 | github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.18/go.mod h1:Br6+bxfG33Dk3ynmkhsW2Z/t9D4+lRqdLDNCKi85w0U=
52 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 h1:tJ5RnkHCiSH0jyd6gROjlJtNwov0eGYNz8s8nFcR0jQ=
53 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18/go.mod h1:++NHzT+nAF7ZPrHPsA+ENvsXkOO8wEu+C6RXltAG4/c=
54 | github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.16 h1:jg16PhLPUiHIj8zYIW6bqzeQSuHVEiWnGA0Brz5Xv2I=
55 | github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.16/go.mod h1:Uyk1zE1VVdsHSU7096h/rwnXDzOzYQVl+FNPhPw7ShY=
56 | github.com/aws/aws-sdk-go-v2/service/s3 v1.60.1 h1:mx2ucgtv+MWzJesJY9Ig/8AFHgoE5FwLXwUVgW/FGdI=
57 | github.com/aws/aws-sdk-go-v2/service/s3 v1.60.1/go.mod h1:BSPI0EfnYUuNHPS0uqIo5VrRwzie+Fp+YhQOUs16sKI=
58 | github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 h1:zCsFCKvbj25i7p1u94imVoO447I/sFv8qq+lGJhRN0c=
59 | github.com/aws/aws-sdk-go-v2/service/sso v1.22.5/go.mod h1:ZeDX1SnKsVlejeuz41GiajjZpRSWR7/42q/EyA/QEiM=
60 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 h1:SKvPgvdvmiTWoi0GAJ7AsJfOz3ngVkD/ERbs5pUnHNI=
61 | github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5/go.mod h1:20sz31hv/WsPa3HhU3hfrIet2kxM4Pe0r20eBZ20Tac=
62 | github.com/aws/aws-sdk-go-v2/service/sts v1.30.5 h1:OMsEmCyz2i89XwRwPouAJvhj81wINh+4UK+k/0Yo/q8=
63 | github.com/aws/aws-sdk-go-v2/service/sts v1.30.5/go.mod h1:vmSqFK+BVIwVpDAGZB3CoCXHzurt4qBE8lf+I/kRTh0=
64 | github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4=
65 | github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
66 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
67 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
68 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
69 | github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
70 | github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
71 | github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
72 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
73 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
74 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
75 | github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
76 | github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
77 | github.com/domodwyer/mailyak/v3 v3.6.2 h1:x3tGMsyFhTCaxp6ycgR0FE/bu5QiNp+hetUuCOBXMn8=
78 | github.com/domodwyer/mailyak/v3 v3.6.2/go.mod h1:lOm/u9CyCVWHeaAmHIdF4RiKVxKUT/H5XX10lIKAL6c=
79 | github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
80 | github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
81 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
82 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
83 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
84 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
85 | github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
86 | github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
87 | github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
88 | github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
89 | github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
90 | github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
91 | github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
92 | github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
93 | github.com/ganigeorgiev/fexpr v0.4.1 h1:hpUgbUEEWIZhSDBtf4M9aUNfQQ0BZkGRaMePy7Gcx5k=
94 | github.com/ganigeorgiev/fexpr v0.4.1/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO2WtJkF5drE=
95 | github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
96 | github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
97 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
98 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
99 | github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es=
100 | github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew=
101 | github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
102 | github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
103 | github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
104 | github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
105 | github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
106 | github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
107 | github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
108 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
109 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
110 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
111 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
112 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
113 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
114 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
115 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
116 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
117 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
118 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
119 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
120 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
121 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
122 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
123 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
124 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
125 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
126 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
127 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
128 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
129 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
130 | github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
131 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
132 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
133 | github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA=
134 | github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
135 | github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM=
136 | github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA=
137 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
138 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
139 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
140 | github.com/google/wire v0.6.0 h1:HBkoIh4BdSxoyo9PveV8giw7ZsaBOvzWKfcg/6MrVwI=
141 | github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk6NA=
142 | github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
143 | github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
144 | github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s=
145 | github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A=
146 | github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
147 | github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
148 | github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
149 | github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
150 | github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
151 | github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
152 | github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
153 | github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
154 | github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
155 | github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
156 | github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
157 | github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
158 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
159 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
160 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
161 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
162 | github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61 h1:FwuzbVh87iLiUQj1+uQUsuw9x5t9m5n5g7rG7o4svW4=
163 | github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61/go.mod h1:paQfF1YtHe+GrGg5fOgjsjoCX/UKDr9bc1DoWpZfns8=
164 | github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
165 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
166 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
167 | github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
168 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
169 | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
170 | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
171 | github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
172 | github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
173 | github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
174 | github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
175 | github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
176 | github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
177 | github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
178 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
179 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
180 | github.com/pocketbase/dbx v1.10.1 h1:cw+vsyfCJD8YObOVeqb93YErnlxwYMkNZ4rwN0G0AaA=
181 | github.com/pocketbase/dbx v1.10.1/go.mod h1:xXRCIAKTHMgUCyCKZm55pUOdvFziJjQfXaWKhu2vhMs=
182 | github.com/pocketbase/pocketbase v0.22.20 h1:yUkhO5bTPWlzD4ZK6EQlS4R3AcHKDlBD+DxxU2BR83I=
183 | github.com/pocketbase/pocketbase v0.22.20/go.mod h1:Cw5E4uoGhKItBIE2lJL3NfmiUr9Syk2xaNJ2G7Dssow=
184 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
185 | github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
186 | github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
187 | github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
188 | github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
189 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
190 | github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
191 | github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
192 | github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
193 | github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
194 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
195 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
196 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
197 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
198 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
199 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
200 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
201 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
202 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
203 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
204 | github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
205 | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
206 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
207 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
208 | github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
209 | github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
210 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
211 | go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
212 | go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
213 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g=
214 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74=
215 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
216 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
217 | go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
218 | go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
219 | go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
220 | go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
221 | go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
222 | go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
223 | gocloud.dev v0.39.0 h1:EYABYGhAalPUaMrbSKOr5lejxoxvXj99nE8XFtsDgds=
224 | gocloud.dev v0.39.0/go.mod h1:drz+VyYNBvrMTW0KZiBAYEdl8lbNZx+OQ7oQvdrFmSQ=
225 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
226 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
227 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
228 | golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
229 | golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
230 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
231 | golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
232 | golang.org/x/image v0.19.0 h1:D9FX4QWkLfkeqaC62SonffIIuYdOk/UE2XKUBgRIBIQ=
233 | golang.org/x/image v0.19.0/go.mod h1:y0zrRqlQRWQ5PXaYCOMLTW2fpsxZ8Qh9I/ohnInJEys=
234 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
235 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
236 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
237 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
238 | golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
239 | golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
240 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
241 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
242 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
243 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
244 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
245 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
246 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
247 | golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
248 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
249 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
250 | golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
251 | golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
252 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
253 | golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA=
254 | golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
255 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
256 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
257 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
258 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
259 | golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
260 | golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
261 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
262 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
263 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
264 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
265 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
266 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
267 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
268 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
269 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
270 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
271 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
272 | golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
273 | golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
274 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
275 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
276 | golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
277 | golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
278 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
279 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
280 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
281 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
282 | golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
283 | golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
284 | golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
285 | golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
286 | golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
287 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
288 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
289 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
290 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
291 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
292 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
293 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
294 | golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
295 | golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
296 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
297 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
298 | golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 h1:LLhsEBxRTBLuKlQxFBYUOU8xyFgXv6cOTp2HASDlsDk=
299 | golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
300 | google.golang.org/api v0.194.0 h1:dztZKG9HgtIpbI35FhfuSNR/zmaMVdxNlntHj1sIS4s=
301 | google.golang.org/api v0.194.0/go.mod h1:AgvUFdojGANh3vI+P7EVnxj3AISHllxGCJSFmggmnd0=
302 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
303 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
304 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
305 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
306 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
307 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
308 | google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 h1:oLiyxGgE+rt22duwci1+TG7bg2/L1LQsXwfjPlmuJA0=
309 | google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142/go.mod h1:G11eXq53iI5Q+kyNOmCvnzBaxEA2Q/Ik5Tj7nqBE8j4=
310 | google.golang.org/genproto/googleapis/api v0.0.0-20240812133136-8ffd90a71988 h1:+/tmTy5zAieooKIXfzDm9KiA3Bv6JBwriRN9LY+yayk=
311 | google.golang.org/genproto/googleapis/api v0.0.0-20240812133136-8ffd90a71988/go.mod h1:4+X6GvPs+25wZKbQq9qyAXrwIRExv7w0Ea6MgZLZiDM=
312 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed h1:J6izYgfBXAI3xTKLgxzTmUltdYaLsuBxFCgDHWJ/eXg=
313 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
314 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
315 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
316 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
317 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
318 | google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
319 | google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
320 | google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
321 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
322 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
323 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
324 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
325 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
326 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
327 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
328 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
329 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
330 | google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
331 | google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
332 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
333 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
334 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
335 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
336 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
337 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
338 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
339 | modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ=
340 | modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
341 | modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y=
342 | modernc.org/ccgo/v4 v4.19.2/go.mod h1:ysS3mxiMV38XGRTTcgo0DQTeTmAO4oCmJl1nX9VFI3s=
343 | modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
344 | modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
345 | modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
346 | modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
347 | modernc.org/gc/v3 v3.0.0-20240801135723-a856999a2e4a h1:CfbpOLEo2IwNzJdMvE8aiRbPMxoTpgAJeyePh0SmO8M=
348 | modernc.org/gc/v3 v3.0.0-20240801135723-a856999a2e4a/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
349 | modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U=
350 | modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w=
351 | modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
352 | modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
353 | modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
354 | modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
355 | modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
356 | modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
357 | modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
358 | modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
359 | modernc.org/sqlite v1.32.0 h1:6BM4uGza7bWypsw4fdLRsLxut6bHe4c58VeqjRgST8s=
360 | modernc.org/sqlite v1.32.0/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA=
361 | modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
362 | modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
363 | modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
364 | modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
365 |
--------------------------------------------------------------------------------
/lib/README.md:
--------------------------------------------------------------------------------
1 | # Lib Package
2 |
3 | The `lib` directory contains reusable code essential for the application.
4 |
5 | - **`auth.go`**: Manages user authentication, including:
6 |
7 | - `Login`: Validates user credentials.
8 | - `Register`: Ensures unique usernames and matching passwords before creating a new user.
9 | - `setAuthToken`: Generates and sets an authentication token as an HTTP cookie.
10 |
11 | - **`base.templ`**: Defines the base HTML layout, including:
12 |
13 | - Essential metadata, stylesheets, and scripts.
14 | - Uses Tailwind CSS, DaisyUI, and HTMX.
15 | - `{ children... }` placeholder for dynamic content.
16 |
17 | - **`htmx.go`**: Provides utilities for handling HTMX requests, including:
18 |
19 | - Checking if a request is an HTMX request.
20 | - Rendering templates based on request type.
21 | - Handling HTMX-specific redirects.
22 |
23 | - **`render.go`**: Renders Templ components in an Echo context, including:
24 | - Setting the HTTP status code.
25 | - Rendering the Templ component to the response writer.
26 | - Returning a 500 Internal Server Error if rendering fails.
27 |
--------------------------------------------------------------------------------
/lib/auth.go:
--------------------------------------------------------------------------------
1 | package lib
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 |
7 | "github.com/cmcd97/bytesize/middleware"
8 | "github.com/labstack/echo/v5"
9 | "github.com/pocketbase/pocketbase/core"
10 | "github.com/pocketbase/pocketbase/models"
11 | "github.com/pocketbase/pocketbase/tokens"
12 | )
13 |
14 | type Users struct {
15 | models.Record
16 | }
17 |
18 | func (*Users) TableName() string {
19 | return "users"
20 | }
21 |
22 | func Login(e *core.ServeEvent, c echo.Context, username string, password string) error {
23 | user, err := e.App.Dao().FindAuthRecordByUsername("users", username)
24 | if err != nil {
25 | return fmt.Errorf("Login failed")
26 | }
27 |
28 | valid := user.ValidatePassword(password)
29 | if !valid {
30 | return fmt.Errorf("Login failed")
31 | }
32 |
33 | return setAuthToken(e.App, c, user)
34 | }
35 |
36 | func Register(e *core.ServeEvent, c echo.Context, username string, password string, passwordRepeat string) error {
37 | user, _ := e.App.Dao().FindAuthRecordByUsername("users", username)
38 | if user != nil {
39 | return fmt.Errorf("username already taken")
40 | }
41 |
42 | if password != passwordRepeat {
43 | return fmt.Errorf("passwords don't match")
44 | }
45 |
46 | collection, err := e.App.Dao().FindCollectionByNameOrId("users")
47 | if err != nil {
48 | return err
49 | }
50 |
51 | newUser := models.NewRecord(collection)
52 | newUser.SetPassword(password)
53 | newUser.SetUsername(username)
54 |
55 | if err = e.App.Dao().SaveRecord(newUser); err != nil {
56 | return err
57 | }
58 |
59 | return setAuthToken(e.App, c, newUser)
60 | }
61 |
62 | func setAuthToken(app core.App, c echo.Context, user *models.Record) error {
63 | s, tokenErr := tokens.NewRecordAuthToken(app, user)
64 | if tokenErr != nil {
65 | return fmt.Errorf("Login failed")
66 | }
67 |
68 | c.SetCookie(&http.Cookie{
69 | Name: middleware.AuthCookieName,
70 | Value: s,
71 | Path: "/",
72 | Secure: true,
73 | HttpOnly: true,
74 | })
75 |
76 | return nil
77 | }
78 |
--------------------------------------------------------------------------------
/lib/base.templ:
--------------------------------------------------------------------------------
1 | package lib
2 |
3 | templ BaseLayout() {
4 |
5 |
6 | Bytesize
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | { children... }
18 |
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/lib/htmx.go:
--------------------------------------------------------------------------------
1 | package lib
2 |
3 | import (
4 | "github.com/a-h/templ"
5 | "github.com/labstack/echo/v5"
6 | )
7 |
8 | func IsHtmxRequest(c echo.Context) bool {
9 | return c.Request().Header.Get("HX-Request") == "true"
10 | }
11 |
12 | type TemplRenderFunc func() templ.Component
13 |
14 | func HtmxRender(c echo.Context, htmxTemplate TemplRenderFunc, nonHtmxTemplate TemplRenderFunc) templ.Component {
15 | if IsHtmxRequest(c) {
16 | return htmxTemplate()
17 | } else {
18 | return nonHtmxTemplate()
19 | }
20 | }
21 |
22 | func HtmxRedirect(c echo.Context, path string) error {
23 | if IsHtmxRequest(c) {
24 | c.Response().Header().Set("HX-Location", path)
25 | return c.NoContent(204)
26 | }
27 |
28 | return c.Redirect(302, path)
29 | }
30 |
--------------------------------------------------------------------------------
/lib/render.go:
--------------------------------------------------------------------------------
1 | package lib
2 |
3 | import (
4 | "context"
5 | "net/http"
6 |
7 | "github.com/a-h/templ"
8 | "github.com/labstack/echo/v5"
9 | )
10 |
11 | func Render(ctx echo.Context, status int, t templ.Component) error {
12 | ctx.Response().Writer.WriteHeader(status)
13 |
14 | err := t.Render(context.Background(), ctx.Response().Writer)
15 | if err != nil {
16 | return ctx.String(http.StatusInternalServerError, "failed to render response template")
17 | }
18 |
19 | return nil
20 | }
21 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 |
6 | "github.com/cmcd97/bytesize/app"
7 | "github.com/cmcd97/bytesize/auth"
8 | "github.com/cmcd97/bytesize/middleware"
9 |
10 | "github.com/joho/godotenv"
11 | "github.com/pocketbase/pocketbase"
12 | "github.com/pocketbase/pocketbase/core"
13 | )
14 |
15 | func main() {
16 | if err := godotenv.Load(); err != nil {
17 | println("Error loading .env file. Please create one or check the spelling of the file name")
18 | log.Fatal(err)
19 | }
20 |
21 | pb := pocketbase.New()
22 |
23 | // serves static files from the provided public dir (if exists)
24 | pb.OnBeforeServe().Add(func(e *core.ServeEvent) error {
25 | e.Router.Static("/public", "public")
26 |
27 | authGroup := e.Router.Group("/auth", middleware.LoadAuthContextFromCookie(pb))
28 | auth.RegisterLoginRoutes(e, *authGroup)
29 | auth.RegisterRegisterRoutes(e, *authGroup)
30 |
31 | app.InitAppRoutes(e, pb)
32 | return nil
33 | })
34 |
35 | if err := pb.Start(); err != nil {
36 | log.Fatal(err)
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/middleware/README.md:
--------------------------------------------------------------------------------
1 | # Middleware Package
2 |
3 | The `middleware` directory contains middleware functions that are used to handle various aspects of request processing in the application. Middleware functions are essential for tasks such as authentication, logging, error handling, and more. They act as a bridge between the incoming request and the final route handler, allowing you to execute code before the request reaches the route handler.
4 |
5 | ## Purpose
6 |
7 | The primary purpose of the middleware functions in this directory is to enhance the functionality and security of the application by performing common tasks that need to be executed for multiple routes.
8 |
9 | ## Auth Middleware
10 |
11 | One of the key middleware functions in this directory is the `AuthGuard` function, located in the `middleware/auth.go` file. This middleware is responsible for ensuring that only authenticated users can access certain routes.
12 |
13 | ### `AuthGuard` Middleware
14 |
15 | The `AuthGuard` middleware checks if a user is authenticated before allowing them to proceed to the requested route. If the user is not authenticated, they are redirected to the login page.
16 |
17 | #### Example Usage
18 |
19 | Here is an example of how the `AuthGuard` middleware is used:
20 |
21 | ```go
22 | package middleware
23 |
24 | import (
25 | "github.com/labstack/echo/v5"
26 | "github.com/cmcd97/bytesize/apis"
27 | )
28 |
29 | // AuthGuard ensures that the user is authenticated before proceeding to the next handler.
30 | func AuthGuard(next echo.HandlerFunc) echo.HandlerFunc {
31 | return func(c echo.Context) error {
32 | record := c.Get(apis.ContextAuthRecordKey)
33 |
34 | if record == nil {
35 | return c.Redirect(302, "/auth/login")
36 | }
37 |
38 | return next(c)
39 | }
40 | }
41 |
42 | ```
43 |
--------------------------------------------------------------------------------
/middleware/auth.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "github.com/labstack/echo/v5"
5 | "github.com/pocketbase/pocketbase/apis"
6 | "github.com/pocketbase/pocketbase/core"
7 | )
8 |
9 | const AuthCookieName = "Auth"
10 |
11 | func LoadAuthContextFromCookie(app core.App) echo.MiddlewareFunc {
12 | return func(next echo.HandlerFunc) echo.HandlerFunc {
13 | return func(c echo.Context) error {
14 | tokenCookie, err := c.Request().Cookie(AuthCookieName)
15 | if err != nil {
16 | return next(c)
17 | }
18 |
19 | token := tokenCookie.Value
20 | record, err := app.Dao().FindAuthRecordByToken(
21 | token,
22 | app.Settings().RecordAuthToken.Secret,
23 | )
24 |
25 | if err != nil {
26 | return next(c)
27 | }
28 |
29 | c.Set(apis.ContextAuthRecordKey, record)
30 | return next(c)
31 | }
32 | }
33 | }
34 |
35 | func AuthGuard(next echo.HandlerFunc) echo.HandlerFunc {
36 | return func(c echo.Context) error {
37 | record := c.Get(apis.ContextAuthRecordKey)
38 |
39 | if record == nil {
40 | return c.Redirect(302, "/auth/login")
41 | }
42 |
43 | return next(c)
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/model/README.md:
--------------------------------------------------------------------------------
1 | # Model Package
2 |
3 | This package provides CRUD operations for models in a PocketBase application.
4 |
5 | ## Overview
6 |
7 | The `model` package defines a `Crud` interface and provides functions to perform common database operations such as finding all records, finding a record by ID, and saving a record.
8 |
9 | ## Interface
10 |
11 | ```go
12 | type Crud interface {
13 | models.Model
14 | GetUser() string
15 | Validate() error
16 | }
17 | ```
18 |
19 | ## Functions
20 |
21 | ### FindAll
22 |
23 | ```go
24 | func FindAll[C Crud](model Crud, dao *daos.Dao, authRecord *models.Record) ([]C, error)
25 | ```
26 |
27 | Finds all records of a given model that belong to the authenticated user.
28 |
29 | ### FindById
30 |
31 | ```go
32 | func FindById(model Crud, dao *daos.Dao, authRecord *models.Record, id string) error
33 | ```
34 |
35 | Finds a record by its ID and ensures it belongs to the authenticated user.
36 |
37 | ### Save
38 |
39 | ```go
40 | func Save(model Crud, dao *daos.Dao) error
41 | ```
42 |
43 | Validates and saves a model to the database.
44 |
45 | ## Dependencies
46 |
47 | - [PocketBase](https://github.com/pocketbase/pocketbase)
48 | - [dbx](https://github.com/pocketbase/dbx)
49 |
50 | ## Usage
51 |
52 | Import the package and use the provided functions to interact with your models.
53 |
54 | ```go
55 | import (
56 | "github.com/yourusername/yourrepo/model"
57 | "github.com/pocketbase/pocketbase/daos"
58 | "github.com/pocketbase/pocketbase/models"
59 | )
60 | ```
61 |
--------------------------------------------------------------------------------
/model/crud.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/pocketbase/dbx"
7 | "github.com/pocketbase/pocketbase/daos"
8 | "github.com/pocketbase/pocketbase/models"
9 | )
10 |
11 | type Crud interface {
12 | models.Model
13 | GetUser() string
14 | Validate() error
15 | }
16 |
17 | func FindAll[C Crud](model Crud, dao *daos.Dao, authRecord *models.Record) ([]C, error) {
18 | items := []C{}
19 | error := dao.ModelQuery(model).Where(dbx.NewExp("user = {:id}", dbx.Params{"id": authRecord.Id})).All(&items)
20 |
21 | return items, error
22 | }
23 |
24 | func FindById(model Crud, dao *daos.Dao, authRecord *models.Record, id string) error {
25 | err := dao.FindById(model, id)
26 |
27 | if err != nil || model.GetUser() != authRecord.Id {
28 | return fmt.Errorf("record not found")
29 | }
30 |
31 | return nil
32 | }
33 |
34 | func Save(model Crud, dao *daos.Dao) error {
35 | err := model.Validate()
36 | if err == nil {
37 | return dao.Save(model)
38 | }
39 |
40 | return err
41 | }
42 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bytesize",
3 | "lockfileVersion": 3,
4 | "requires": true,
5 | "packages": {
6 | "": {
7 | "devDependencies": {
8 | "tailwindcss": "^3.4.11"
9 | }
10 | },
11 | "node_modules/@alloc/quick-lru": {
12 | "version": "5.2.0",
13 | "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
14 | "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
15 | "dev": true,
16 | "license": "MIT",
17 | "engines": {
18 | "node": ">=10"
19 | },
20 | "funding": {
21 | "url": "https://github.com/sponsors/sindresorhus"
22 | }
23 | },
24 | "node_modules/@isaacs/cliui": {
25 | "version": "8.0.2",
26 | "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
27 | "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
28 | "dev": true,
29 | "license": "ISC",
30 | "dependencies": {
31 | "string-width": "^5.1.2",
32 | "string-width-cjs": "npm:string-width@^4.2.0",
33 | "strip-ansi": "^7.0.1",
34 | "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
35 | "wrap-ansi": "^8.1.0",
36 | "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
37 | },
38 | "engines": {
39 | "node": ">=12"
40 | }
41 | },
42 | "node_modules/@jridgewell/gen-mapping": {
43 | "version": "0.3.5",
44 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
45 | "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
46 | "dev": true,
47 | "license": "MIT",
48 | "dependencies": {
49 | "@jridgewell/set-array": "^1.2.1",
50 | "@jridgewell/sourcemap-codec": "^1.4.10",
51 | "@jridgewell/trace-mapping": "^0.3.24"
52 | },
53 | "engines": {
54 | "node": ">=6.0.0"
55 | }
56 | },
57 | "node_modules/@jridgewell/resolve-uri": {
58 | "version": "3.1.2",
59 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
60 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
61 | "dev": true,
62 | "license": "MIT",
63 | "engines": {
64 | "node": ">=6.0.0"
65 | }
66 | },
67 | "node_modules/@jridgewell/set-array": {
68 | "version": "1.2.1",
69 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
70 | "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
71 | "dev": true,
72 | "license": "MIT",
73 | "engines": {
74 | "node": ">=6.0.0"
75 | }
76 | },
77 | "node_modules/@jridgewell/sourcemap-codec": {
78 | "version": "1.5.0",
79 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
80 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
81 | "dev": true,
82 | "license": "MIT"
83 | },
84 | "node_modules/@jridgewell/trace-mapping": {
85 | "version": "0.3.25",
86 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
87 | "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
88 | "dev": true,
89 | "license": "MIT",
90 | "dependencies": {
91 | "@jridgewell/resolve-uri": "^3.1.0",
92 | "@jridgewell/sourcemap-codec": "^1.4.14"
93 | }
94 | },
95 | "node_modules/@nodelib/fs.scandir": {
96 | "version": "2.1.5",
97 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
98 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
99 | "dev": true,
100 | "license": "MIT",
101 | "dependencies": {
102 | "@nodelib/fs.stat": "2.0.5",
103 | "run-parallel": "^1.1.9"
104 | },
105 | "engines": {
106 | "node": ">= 8"
107 | }
108 | },
109 | "node_modules/@nodelib/fs.stat": {
110 | "version": "2.0.5",
111 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
112 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
113 | "dev": true,
114 | "license": "MIT",
115 | "engines": {
116 | "node": ">= 8"
117 | }
118 | },
119 | "node_modules/@nodelib/fs.walk": {
120 | "version": "1.2.8",
121 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
122 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
123 | "dev": true,
124 | "license": "MIT",
125 | "dependencies": {
126 | "@nodelib/fs.scandir": "2.1.5",
127 | "fastq": "^1.6.0"
128 | },
129 | "engines": {
130 | "node": ">= 8"
131 | }
132 | },
133 | "node_modules/@pkgjs/parseargs": {
134 | "version": "0.11.0",
135 | "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
136 | "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
137 | "dev": true,
138 | "license": "MIT",
139 | "optional": true,
140 | "engines": {
141 | "node": ">=14"
142 | }
143 | },
144 | "node_modules/ansi-regex": {
145 | "version": "6.1.0",
146 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
147 | "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
148 | "dev": true,
149 | "license": "MIT",
150 | "engines": {
151 | "node": ">=12"
152 | },
153 | "funding": {
154 | "url": "https://github.com/chalk/ansi-regex?sponsor=1"
155 | }
156 | },
157 | "node_modules/ansi-styles": {
158 | "version": "6.2.1",
159 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
160 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
161 | "dev": true,
162 | "license": "MIT",
163 | "engines": {
164 | "node": ">=12"
165 | },
166 | "funding": {
167 | "url": "https://github.com/chalk/ansi-styles?sponsor=1"
168 | }
169 | },
170 | "node_modules/any-promise": {
171 | "version": "1.3.0",
172 | "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
173 | "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
174 | "dev": true,
175 | "license": "MIT"
176 | },
177 | "node_modules/anymatch": {
178 | "version": "3.1.3",
179 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
180 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
181 | "dev": true,
182 | "license": "ISC",
183 | "dependencies": {
184 | "normalize-path": "^3.0.0",
185 | "picomatch": "^2.0.4"
186 | },
187 | "engines": {
188 | "node": ">= 8"
189 | }
190 | },
191 | "node_modules/arg": {
192 | "version": "5.0.2",
193 | "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
194 | "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
195 | "dev": true,
196 | "license": "MIT"
197 | },
198 | "node_modules/balanced-match": {
199 | "version": "1.0.2",
200 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
201 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
202 | "dev": true,
203 | "license": "MIT"
204 | },
205 | "node_modules/binary-extensions": {
206 | "version": "2.3.0",
207 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
208 | "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
209 | "dev": true,
210 | "license": "MIT",
211 | "engines": {
212 | "node": ">=8"
213 | },
214 | "funding": {
215 | "url": "https://github.com/sponsors/sindresorhus"
216 | }
217 | },
218 | "node_modules/brace-expansion": {
219 | "version": "2.0.1",
220 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
221 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
222 | "dev": true,
223 | "license": "MIT",
224 | "dependencies": {
225 | "balanced-match": "^1.0.0"
226 | }
227 | },
228 | "node_modules/braces": {
229 | "version": "3.0.3",
230 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
231 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
232 | "dev": true,
233 | "license": "MIT",
234 | "dependencies": {
235 | "fill-range": "^7.1.1"
236 | },
237 | "engines": {
238 | "node": ">=8"
239 | }
240 | },
241 | "node_modules/camelcase-css": {
242 | "version": "2.0.1",
243 | "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
244 | "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
245 | "dev": true,
246 | "license": "MIT",
247 | "engines": {
248 | "node": ">= 6"
249 | }
250 | },
251 | "node_modules/chokidar": {
252 | "version": "3.6.0",
253 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
254 | "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
255 | "dev": true,
256 | "license": "MIT",
257 | "dependencies": {
258 | "anymatch": "~3.1.2",
259 | "braces": "~3.0.2",
260 | "glob-parent": "~5.1.2",
261 | "is-binary-path": "~2.1.0",
262 | "is-glob": "~4.0.1",
263 | "normalize-path": "~3.0.0",
264 | "readdirp": "~3.6.0"
265 | },
266 | "engines": {
267 | "node": ">= 8.10.0"
268 | },
269 | "funding": {
270 | "url": "https://paulmillr.com/funding/"
271 | },
272 | "optionalDependencies": {
273 | "fsevents": "~2.3.2"
274 | }
275 | },
276 | "node_modules/chokidar/node_modules/glob-parent": {
277 | "version": "5.1.2",
278 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
279 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
280 | "dev": true,
281 | "license": "ISC",
282 | "dependencies": {
283 | "is-glob": "^4.0.1"
284 | },
285 | "engines": {
286 | "node": ">= 6"
287 | }
288 | },
289 | "node_modules/color-convert": {
290 | "version": "2.0.1",
291 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
292 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
293 | "dev": true,
294 | "license": "MIT",
295 | "dependencies": {
296 | "color-name": "~1.1.4"
297 | },
298 | "engines": {
299 | "node": ">=7.0.0"
300 | }
301 | },
302 | "node_modules/color-name": {
303 | "version": "1.1.4",
304 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
305 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
306 | "dev": true,
307 | "license": "MIT"
308 | },
309 | "node_modules/commander": {
310 | "version": "4.1.1",
311 | "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
312 | "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
313 | "dev": true,
314 | "license": "MIT",
315 | "engines": {
316 | "node": ">= 6"
317 | }
318 | },
319 | "node_modules/cross-spawn": {
320 | "version": "7.0.3",
321 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
322 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
323 | "dev": true,
324 | "license": "MIT",
325 | "dependencies": {
326 | "path-key": "^3.1.0",
327 | "shebang-command": "^2.0.0",
328 | "which": "^2.0.1"
329 | },
330 | "engines": {
331 | "node": ">= 8"
332 | }
333 | },
334 | "node_modules/cssesc": {
335 | "version": "3.0.0",
336 | "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
337 | "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
338 | "dev": true,
339 | "license": "MIT",
340 | "bin": {
341 | "cssesc": "bin/cssesc"
342 | },
343 | "engines": {
344 | "node": ">=4"
345 | }
346 | },
347 | "node_modules/didyoumean": {
348 | "version": "1.2.2",
349 | "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
350 | "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
351 | "dev": true,
352 | "license": "Apache-2.0"
353 | },
354 | "node_modules/dlv": {
355 | "version": "1.1.3",
356 | "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
357 | "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
358 | "dev": true,
359 | "license": "MIT"
360 | },
361 | "node_modules/eastasianwidth": {
362 | "version": "0.2.0",
363 | "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
364 | "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
365 | "dev": true,
366 | "license": "MIT"
367 | },
368 | "node_modules/emoji-regex": {
369 | "version": "9.2.2",
370 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
371 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
372 | "dev": true,
373 | "license": "MIT"
374 | },
375 | "node_modules/fast-glob": {
376 | "version": "3.3.2",
377 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
378 | "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
379 | "dev": true,
380 | "license": "MIT",
381 | "dependencies": {
382 | "@nodelib/fs.stat": "^2.0.2",
383 | "@nodelib/fs.walk": "^1.2.3",
384 | "glob-parent": "^5.1.2",
385 | "merge2": "^1.3.0",
386 | "micromatch": "^4.0.4"
387 | },
388 | "engines": {
389 | "node": ">=8.6.0"
390 | }
391 | },
392 | "node_modules/fast-glob/node_modules/glob-parent": {
393 | "version": "5.1.2",
394 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
395 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
396 | "dev": true,
397 | "license": "ISC",
398 | "dependencies": {
399 | "is-glob": "^4.0.1"
400 | },
401 | "engines": {
402 | "node": ">= 6"
403 | }
404 | },
405 | "node_modules/fastq": {
406 | "version": "1.17.1",
407 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
408 | "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
409 | "dev": true,
410 | "license": "ISC",
411 | "dependencies": {
412 | "reusify": "^1.0.4"
413 | }
414 | },
415 | "node_modules/fill-range": {
416 | "version": "7.1.1",
417 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
418 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
419 | "dev": true,
420 | "license": "MIT",
421 | "dependencies": {
422 | "to-regex-range": "^5.0.1"
423 | },
424 | "engines": {
425 | "node": ">=8"
426 | }
427 | },
428 | "node_modules/foreground-child": {
429 | "version": "3.3.0",
430 | "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
431 | "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
432 | "dev": true,
433 | "license": "ISC",
434 | "dependencies": {
435 | "cross-spawn": "^7.0.0",
436 | "signal-exit": "^4.0.1"
437 | },
438 | "engines": {
439 | "node": ">=14"
440 | },
441 | "funding": {
442 | "url": "https://github.com/sponsors/isaacs"
443 | }
444 | },
445 | "node_modules/fsevents": {
446 | "version": "2.3.3",
447 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
448 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
449 | "dev": true,
450 | "hasInstallScript": true,
451 | "license": "MIT",
452 | "optional": true,
453 | "os": [
454 | "darwin"
455 | ],
456 | "engines": {
457 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
458 | }
459 | },
460 | "node_modules/function-bind": {
461 | "version": "1.1.2",
462 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
463 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
464 | "dev": true,
465 | "license": "MIT",
466 | "funding": {
467 | "url": "https://github.com/sponsors/ljharb"
468 | }
469 | },
470 | "node_modules/glob": {
471 | "version": "10.4.5",
472 | "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
473 | "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
474 | "dev": true,
475 | "license": "ISC",
476 | "dependencies": {
477 | "foreground-child": "^3.1.0",
478 | "jackspeak": "^3.1.2",
479 | "minimatch": "^9.0.4",
480 | "minipass": "^7.1.2",
481 | "package-json-from-dist": "^1.0.0",
482 | "path-scurry": "^1.11.1"
483 | },
484 | "bin": {
485 | "glob": "dist/esm/bin.mjs"
486 | },
487 | "funding": {
488 | "url": "https://github.com/sponsors/isaacs"
489 | }
490 | },
491 | "node_modules/glob-parent": {
492 | "version": "6.0.2",
493 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
494 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
495 | "dev": true,
496 | "license": "ISC",
497 | "dependencies": {
498 | "is-glob": "^4.0.3"
499 | },
500 | "engines": {
501 | "node": ">=10.13.0"
502 | }
503 | },
504 | "node_modules/hasown": {
505 | "version": "2.0.2",
506 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
507 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
508 | "dev": true,
509 | "license": "MIT",
510 | "dependencies": {
511 | "function-bind": "^1.1.2"
512 | },
513 | "engines": {
514 | "node": ">= 0.4"
515 | }
516 | },
517 | "node_modules/is-binary-path": {
518 | "version": "2.1.0",
519 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
520 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
521 | "dev": true,
522 | "license": "MIT",
523 | "dependencies": {
524 | "binary-extensions": "^2.0.0"
525 | },
526 | "engines": {
527 | "node": ">=8"
528 | }
529 | },
530 | "node_modules/is-core-module": {
531 | "version": "2.15.1",
532 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
533 | "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
534 | "dev": true,
535 | "license": "MIT",
536 | "dependencies": {
537 | "hasown": "^2.0.2"
538 | },
539 | "engines": {
540 | "node": ">= 0.4"
541 | },
542 | "funding": {
543 | "url": "https://github.com/sponsors/ljharb"
544 | }
545 | },
546 | "node_modules/is-extglob": {
547 | "version": "2.1.1",
548 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
549 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
550 | "dev": true,
551 | "license": "MIT",
552 | "engines": {
553 | "node": ">=0.10.0"
554 | }
555 | },
556 | "node_modules/is-fullwidth-code-point": {
557 | "version": "3.0.0",
558 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
559 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
560 | "dev": true,
561 | "license": "MIT",
562 | "engines": {
563 | "node": ">=8"
564 | }
565 | },
566 | "node_modules/is-glob": {
567 | "version": "4.0.3",
568 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
569 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
570 | "dev": true,
571 | "license": "MIT",
572 | "dependencies": {
573 | "is-extglob": "^2.1.1"
574 | },
575 | "engines": {
576 | "node": ">=0.10.0"
577 | }
578 | },
579 | "node_modules/is-number": {
580 | "version": "7.0.0",
581 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
582 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
583 | "dev": true,
584 | "license": "MIT",
585 | "engines": {
586 | "node": ">=0.12.0"
587 | }
588 | },
589 | "node_modules/isexe": {
590 | "version": "2.0.0",
591 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
592 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
593 | "dev": true,
594 | "license": "ISC"
595 | },
596 | "node_modules/jackspeak": {
597 | "version": "3.4.3",
598 | "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
599 | "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
600 | "dev": true,
601 | "license": "BlueOak-1.0.0",
602 | "dependencies": {
603 | "@isaacs/cliui": "^8.0.2"
604 | },
605 | "funding": {
606 | "url": "https://github.com/sponsors/isaacs"
607 | },
608 | "optionalDependencies": {
609 | "@pkgjs/parseargs": "^0.11.0"
610 | }
611 | },
612 | "node_modules/jiti": {
613 | "version": "1.21.6",
614 | "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
615 | "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
616 | "dev": true,
617 | "license": "MIT",
618 | "bin": {
619 | "jiti": "bin/jiti.js"
620 | }
621 | },
622 | "node_modules/lilconfig": {
623 | "version": "2.1.0",
624 | "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
625 | "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
626 | "dev": true,
627 | "license": "MIT",
628 | "engines": {
629 | "node": ">=10"
630 | }
631 | },
632 | "node_modules/lines-and-columns": {
633 | "version": "1.2.4",
634 | "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
635 | "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
636 | "dev": true,
637 | "license": "MIT"
638 | },
639 | "node_modules/lru-cache": {
640 | "version": "10.4.3",
641 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
642 | "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
643 | "dev": true,
644 | "license": "ISC"
645 | },
646 | "node_modules/merge2": {
647 | "version": "1.4.1",
648 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
649 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
650 | "dev": true,
651 | "license": "MIT",
652 | "engines": {
653 | "node": ">= 8"
654 | }
655 | },
656 | "node_modules/micromatch": {
657 | "version": "4.0.8",
658 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
659 | "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
660 | "dev": true,
661 | "license": "MIT",
662 | "dependencies": {
663 | "braces": "^3.0.3",
664 | "picomatch": "^2.3.1"
665 | },
666 | "engines": {
667 | "node": ">=8.6"
668 | }
669 | },
670 | "node_modules/minimatch": {
671 | "version": "9.0.5",
672 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
673 | "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
674 | "dev": true,
675 | "license": "ISC",
676 | "dependencies": {
677 | "brace-expansion": "^2.0.1"
678 | },
679 | "engines": {
680 | "node": ">=16 || 14 >=14.17"
681 | },
682 | "funding": {
683 | "url": "https://github.com/sponsors/isaacs"
684 | }
685 | },
686 | "node_modules/minipass": {
687 | "version": "7.1.2",
688 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
689 | "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
690 | "dev": true,
691 | "license": "ISC",
692 | "engines": {
693 | "node": ">=16 || 14 >=14.17"
694 | }
695 | },
696 | "node_modules/mz": {
697 | "version": "2.7.0",
698 | "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
699 | "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
700 | "dev": true,
701 | "license": "MIT",
702 | "dependencies": {
703 | "any-promise": "^1.0.0",
704 | "object-assign": "^4.0.1",
705 | "thenify-all": "^1.0.0"
706 | }
707 | },
708 | "node_modules/nanoid": {
709 | "version": "3.3.7",
710 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
711 | "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
712 | "dev": true,
713 | "funding": [
714 | {
715 | "type": "github",
716 | "url": "https://github.com/sponsors/ai"
717 | }
718 | ],
719 | "license": "MIT",
720 | "bin": {
721 | "nanoid": "bin/nanoid.cjs"
722 | },
723 | "engines": {
724 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
725 | }
726 | },
727 | "node_modules/normalize-path": {
728 | "version": "3.0.0",
729 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
730 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
731 | "dev": true,
732 | "license": "MIT",
733 | "engines": {
734 | "node": ">=0.10.0"
735 | }
736 | },
737 | "node_modules/object-assign": {
738 | "version": "4.1.1",
739 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
740 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
741 | "dev": true,
742 | "license": "MIT",
743 | "engines": {
744 | "node": ">=0.10.0"
745 | }
746 | },
747 | "node_modules/object-hash": {
748 | "version": "3.0.0",
749 | "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
750 | "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
751 | "dev": true,
752 | "license": "MIT",
753 | "engines": {
754 | "node": ">= 6"
755 | }
756 | },
757 | "node_modules/package-json-from-dist": {
758 | "version": "1.0.0",
759 | "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
760 | "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==",
761 | "dev": true,
762 | "license": "BlueOak-1.0.0"
763 | },
764 | "node_modules/path-key": {
765 | "version": "3.1.1",
766 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
767 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
768 | "dev": true,
769 | "license": "MIT",
770 | "engines": {
771 | "node": ">=8"
772 | }
773 | },
774 | "node_modules/path-parse": {
775 | "version": "1.0.7",
776 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
777 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
778 | "dev": true,
779 | "license": "MIT"
780 | },
781 | "node_modules/path-scurry": {
782 | "version": "1.11.1",
783 | "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
784 | "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
785 | "dev": true,
786 | "license": "BlueOak-1.0.0",
787 | "dependencies": {
788 | "lru-cache": "^10.2.0",
789 | "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
790 | },
791 | "engines": {
792 | "node": ">=16 || 14 >=14.18"
793 | },
794 | "funding": {
795 | "url": "https://github.com/sponsors/isaacs"
796 | }
797 | },
798 | "node_modules/picocolors": {
799 | "version": "1.1.0",
800 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz",
801 | "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==",
802 | "dev": true,
803 | "license": "ISC"
804 | },
805 | "node_modules/picomatch": {
806 | "version": "2.3.1",
807 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
808 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
809 | "dev": true,
810 | "license": "MIT",
811 | "engines": {
812 | "node": ">=8.6"
813 | },
814 | "funding": {
815 | "url": "https://github.com/sponsors/jonschlinkert"
816 | }
817 | },
818 | "node_modules/pify": {
819 | "version": "2.3.0",
820 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
821 | "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
822 | "dev": true,
823 | "license": "MIT",
824 | "engines": {
825 | "node": ">=0.10.0"
826 | }
827 | },
828 | "node_modules/pirates": {
829 | "version": "4.0.6",
830 | "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
831 | "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
832 | "dev": true,
833 | "license": "MIT",
834 | "engines": {
835 | "node": ">= 6"
836 | }
837 | },
838 | "node_modules/postcss": {
839 | "version": "8.4.47",
840 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
841 | "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
842 | "dev": true,
843 | "funding": [
844 | {
845 | "type": "opencollective",
846 | "url": "https://opencollective.com/postcss/"
847 | },
848 | {
849 | "type": "tidelift",
850 | "url": "https://tidelift.com/funding/github/npm/postcss"
851 | },
852 | {
853 | "type": "github",
854 | "url": "https://github.com/sponsors/ai"
855 | }
856 | ],
857 | "license": "MIT",
858 | "dependencies": {
859 | "nanoid": "^3.3.7",
860 | "picocolors": "^1.1.0",
861 | "source-map-js": "^1.2.1"
862 | },
863 | "engines": {
864 | "node": "^10 || ^12 || >=14"
865 | }
866 | },
867 | "node_modules/postcss-import": {
868 | "version": "15.1.0",
869 | "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
870 | "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
871 | "dev": true,
872 | "license": "MIT",
873 | "dependencies": {
874 | "postcss-value-parser": "^4.0.0",
875 | "read-cache": "^1.0.0",
876 | "resolve": "^1.1.7"
877 | },
878 | "engines": {
879 | "node": ">=14.0.0"
880 | },
881 | "peerDependencies": {
882 | "postcss": "^8.0.0"
883 | }
884 | },
885 | "node_modules/postcss-js": {
886 | "version": "4.0.1",
887 | "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
888 | "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
889 | "dev": true,
890 | "license": "MIT",
891 | "dependencies": {
892 | "camelcase-css": "^2.0.1"
893 | },
894 | "engines": {
895 | "node": "^12 || ^14 || >= 16"
896 | },
897 | "funding": {
898 | "type": "opencollective",
899 | "url": "https://opencollective.com/postcss/"
900 | },
901 | "peerDependencies": {
902 | "postcss": "^8.4.21"
903 | }
904 | },
905 | "node_modules/postcss-load-config": {
906 | "version": "4.0.2",
907 | "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
908 | "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
909 | "dev": true,
910 | "funding": [
911 | {
912 | "type": "opencollective",
913 | "url": "https://opencollective.com/postcss/"
914 | },
915 | {
916 | "type": "github",
917 | "url": "https://github.com/sponsors/ai"
918 | }
919 | ],
920 | "license": "MIT",
921 | "dependencies": {
922 | "lilconfig": "^3.0.0",
923 | "yaml": "^2.3.4"
924 | },
925 | "engines": {
926 | "node": ">= 14"
927 | },
928 | "peerDependencies": {
929 | "postcss": ">=8.0.9",
930 | "ts-node": ">=9.0.0"
931 | },
932 | "peerDependenciesMeta": {
933 | "postcss": {
934 | "optional": true
935 | },
936 | "ts-node": {
937 | "optional": true
938 | }
939 | }
940 | },
941 | "node_modules/postcss-load-config/node_modules/lilconfig": {
942 | "version": "3.1.2",
943 | "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
944 | "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
945 | "dev": true,
946 | "license": "MIT",
947 | "engines": {
948 | "node": ">=14"
949 | },
950 | "funding": {
951 | "url": "https://github.com/sponsors/antonk52"
952 | }
953 | },
954 | "node_modules/postcss-nested": {
955 | "version": "6.2.0",
956 | "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
957 | "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
958 | "dev": true,
959 | "funding": [
960 | {
961 | "type": "opencollective",
962 | "url": "https://opencollective.com/postcss/"
963 | },
964 | {
965 | "type": "github",
966 | "url": "https://github.com/sponsors/ai"
967 | }
968 | ],
969 | "license": "MIT",
970 | "dependencies": {
971 | "postcss-selector-parser": "^6.1.1"
972 | },
973 | "engines": {
974 | "node": ">=12.0"
975 | },
976 | "peerDependencies": {
977 | "postcss": "^8.2.14"
978 | }
979 | },
980 | "node_modules/postcss-selector-parser": {
981 | "version": "6.1.2",
982 | "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
983 | "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
984 | "dev": true,
985 | "license": "MIT",
986 | "dependencies": {
987 | "cssesc": "^3.0.0",
988 | "util-deprecate": "^1.0.2"
989 | },
990 | "engines": {
991 | "node": ">=4"
992 | }
993 | },
994 | "node_modules/postcss-value-parser": {
995 | "version": "4.2.0",
996 | "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
997 | "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
998 | "dev": true,
999 | "license": "MIT"
1000 | },
1001 | "node_modules/queue-microtask": {
1002 | "version": "1.2.3",
1003 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
1004 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
1005 | "dev": true,
1006 | "funding": [
1007 | {
1008 | "type": "github",
1009 | "url": "https://github.com/sponsors/feross"
1010 | },
1011 | {
1012 | "type": "patreon",
1013 | "url": "https://www.patreon.com/feross"
1014 | },
1015 | {
1016 | "type": "consulting",
1017 | "url": "https://feross.org/support"
1018 | }
1019 | ],
1020 | "license": "MIT"
1021 | },
1022 | "node_modules/read-cache": {
1023 | "version": "1.0.0",
1024 | "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
1025 | "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
1026 | "dev": true,
1027 | "license": "MIT",
1028 | "dependencies": {
1029 | "pify": "^2.3.0"
1030 | }
1031 | },
1032 | "node_modules/readdirp": {
1033 | "version": "3.6.0",
1034 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
1035 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
1036 | "dev": true,
1037 | "license": "MIT",
1038 | "dependencies": {
1039 | "picomatch": "^2.2.1"
1040 | },
1041 | "engines": {
1042 | "node": ">=8.10.0"
1043 | }
1044 | },
1045 | "node_modules/resolve": {
1046 | "version": "1.22.8",
1047 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
1048 | "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
1049 | "dev": true,
1050 | "license": "MIT",
1051 | "dependencies": {
1052 | "is-core-module": "^2.13.0",
1053 | "path-parse": "^1.0.7",
1054 | "supports-preserve-symlinks-flag": "^1.0.0"
1055 | },
1056 | "bin": {
1057 | "resolve": "bin/resolve"
1058 | },
1059 | "funding": {
1060 | "url": "https://github.com/sponsors/ljharb"
1061 | }
1062 | },
1063 | "node_modules/reusify": {
1064 | "version": "1.0.4",
1065 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
1066 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
1067 | "dev": true,
1068 | "license": "MIT",
1069 | "engines": {
1070 | "iojs": ">=1.0.0",
1071 | "node": ">=0.10.0"
1072 | }
1073 | },
1074 | "node_modules/run-parallel": {
1075 | "version": "1.2.0",
1076 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
1077 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
1078 | "dev": true,
1079 | "funding": [
1080 | {
1081 | "type": "github",
1082 | "url": "https://github.com/sponsors/feross"
1083 | },
1084 | {
1085 | "type": "patreon",
1086 | "url": "https://www.patreon.com/feross"
1087 | },
1088 | {
1089 | "type": "consulting",
1090 | "url": "https://feross.org/support"
1091 | }
1092 | ],
1093 | "license": "MIT",
1094 | "dependencies": {
1095 | "queue-microtask": "^1.2.2"
1096 | }
1097 | },
1098 | "node_modules/shebang-command": {
1099 | "version": "2.0.0",
1100 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
1101 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
1102 | "dev": true,
1103 | "license": "MIT",
1104 | "dependencies": {
1105 | "shebang-regex": "^3.0.0"
1106 | },
1107 | "engines": {
1108 | "node": ">=8"
1109 | }
1110 | },
1111 | "node_modules/shebang-regex": {
1112 | "version": "3.0.0",
1113 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
1114 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
1115 | "dev": true,
1116 | "license": "MIT",
1117 | "engines": {
1118 | "node": ">=8"
1119 | }
1120 | },
1121 | "node_modules/signal-exit": {
1122 | "version": "4.1.0",
1123 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
1124 | "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
1125 | "dev": true,
1126 | "license": "ISC",
1127 | "engines": {
1128 | "node": ">=14"
1129 | },
1130 | "funding": {
1131 | "url": "https://github.com/sponsors/isaacs"
1132 | }
1133 | },
1134 | "node_modules/source-map-js": {
1135 | "version": "1.2.1",
1136 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
1137 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
1138 | "dev": true,
1139 | "license": "BSD-3-Clause",
1140 | "engines": {
1141 | "node": ">=0.10.0"
1142 | }
1143 | },
1144 | "node_modules/string-width": {
1145 | "version": "5.1.2",
1146 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
1147 | "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
1148 | "dev": true,
1149 | "license": "MIT",
1150 | "dependencies": {
1151 | "eastasianwidth": "^0.2.0",
1152 | "emoji-regex": "^9.2.2",
1153 | "strip-ansi": "^7.0.1"
1154 | },
1155 | "engines": {
1156 | "node": ">=12"
1157 | },
1158 | "funding": {
1159 | "url": "https://github.com/sponsors/sindresorhus"
1160 | }
1161 | },
1162 | "node_modules/string-width-cjs": {
1163 | "name": "string-width",
1164 | "version": "4.2.3",
1165 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
1166 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
1167 | "dev": true,
1168 | "license": "MIT",
1169 | "dependencies": {
1170 | "emoji-regex": "^8.0.0",
1171 | "is-fullwidth-code-point": "^3.0.0",
1172 | "strip-ansi": "^6.0.1"
1173 | },
1174 | "engines": {
1175 | "node": ">=8"
1176 | }
1177 | },
1178 | "node_modules/string-width-cjs/node_modules/ansi-regex": {
1179 | "version": "5.0.1",
1180 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
1181 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
1182 | "dev": true,
1183 | "license": "MIT",
1184 | "engines": {
1185 | "node": ">=8"
1186 | }
1187 | },
1188 | "node_modules/string-width-cjs/node_modules/emoji-regex": {
1189 | "version": "8.0.0",
1190 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
1191 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
1192 | "dev": true,
1193 | "license": "MIT"
1194 | },
1195 | "node_modules/string-width-cjs/node_modules/strip-ansi": {
1196 | "version": "6.0.1",
1197 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1198 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1199 | "dev": true,
1200 | "license": "MIT",
1201 | "dependencies": {
1202 | "ansi-regex": "^5.0.1"
1203 | },
1204 | "engines": {
1205 | "node": ">=8"
1206 | }
1207 | },
1208 | "node_modules/strip-ansi": {
1209 | "version": "7.1.0",
1210 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
1211 | "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
1212 | "dev": true,
1213 | "license": "MIT",
1214 | "dependencies": {
1215 | "ansi-regex": "^6.0.1"
1216 | },
1217 | "engines": {
1218 | "node": ">=12"
1219 | },
1220 | "funding": {
1221 | "url": "https://github.com/chalk/strip-ansi?sponsor=1"
1222 | }
1223 | },
1224 | "node_modules/strip-ansi-cjs": {
1225 | "name": "strip-ansi",
1226 | "version": "6.0.1",
1227 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1228 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1229 | "dev": true,
1230 | "license": "MIT",
1231 | "dependencies": {
1232 | "ansi-regex": "^5.0.1"
1233 | },
1234 | "engines": {
1235 | "node": ">=8"
1236 | }
1237 | },
1238 | "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
1239 | "version": "5.0.1",
1240 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
1241 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
1242 | "dev": true,
1243 | "license": "MIT",
1244 | "engines": {
1245 | "node": ">=8"
1246 | }
1247 | },
1248 | "node_modules/sucrase": {
1249 | "version": "3.35.0",
1250 | "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
1251 | "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
1252 | "dev": true,
1253 | "license": "MIT",
1254 | "dependencies": {
1255 | "@jridgewell/gen-mapping": "^0.3.2",
1256 | "commander": "^4.0.0",
1257 | "glob": "^10.3.10",
1258 | "lines-and-columns": "^1.1.6",
1259 | "mz": "^2.7.0",
1260 | "pirates": "^4.0.1",
1261 | "ts-interface-checker": "^0.1.9"
1262 | },
1263 | "bin": {
1264 | "sucrase": "bin/sucrase",
1265 | "sucrase-node": "bin/sucrase-node"
1266 | },
1267 | "engines": {
1268 | "node": ">=16 || 14 >=14.17"
1269 | }
1270 | },
1271 | "node_modules/supports-preserve-symlinks-flag": {
1272 | "version": "1.0.0",
1273 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
1274 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
1275 | "dev": true,
1276 | "license": "MIT",
1277 | "engines": {
1278 | "node": ">= 0.4"
1279 | },
1280 | "funding": {
1281 | "url": "https://github.com/sponsors/ljharb"
1282 | }
1283 | },
1284 | "node_modules/tailwindcss": {
1285 | "version": "3.4.11",
1286 | "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.11.tgz",
1287 | "integrity": "sha512-qhEuBcLemjSJk5ajccN9xJFtM/h0AVCPaA6C92jNP+M2J8kX+eMJHI7R2HFKUvvAsMpcfLILMCFYSeDwpMmlUg==",
1288 | "dev": true,
1289 | "license": "MIT",
1290 | "dependencies": {
1291 | "@alloc/quick-lru": "^5.2.0",
1292 | "arg": "^5.0.2",
1293 | "chokidar": "^3.5.3",
1294 | "didyoumean": "^1.2.2",
1295 | "dlv": "^1.1.3",
1296 | "fast-glob": "^3.3.0",
1297 | "glob-parent": "^6.0.2",
1298 | "is-glob": "^4.0.3",
1299 | "jiti": "^1.21.0",
1300 | "lilconfig": "^2.1.0",
1301 | "micromatch": "^4.0.5",
1302 | "normalize-path": "^3.0.0",
1303 | "object-hash": "^3.0.0",
1304 | "picocolors": "^1.0.0",
1305 | "postcss": "^8.4.23",
1306 | "postcss-import": "^15.1.0",
1307 | "postcss-js": "^4.0.1",
1308 | "postcss-load-config": "^4.0.1",
1309 | "postcss-nested": "^6.0.1",
1310 | "postcss-selector-parser": "^6.0.11",
1311 | "resolve": "^1.22.2",
1312 | "sucrase": "^3.32.0"
1313 | },
1314 | "bin": {
1315 | "tailwind": "lib/cli.js",
1316 | "tailwindcss": "lib/cli.js"
1317 | },
1318 | "engines": {
1319 | "node": ">=14.0.0"
1320 | }
1321 | },
1322 | "node_modules/thenify": {
1323 | "version": "3.3.1",
1324 | "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
1325 | "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
1326 | "dev": true,
1327 | "license": "MIT",
1328 | "dependencies": {
1329 | "any-promise": "^1.0.0"
1330 | }
1331 | },
1332 | "node_modules/thenify-all": {
1333 | "version": "1.6.0",
1334 | "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
1335 | "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
1336 | "dev": true,
1337 | "license": "MIT",
1338 | "dependencies": {
1339 | "thenify": ">= 3.1.0 < 4"
1340 | },
1341 | "engines": {
1342 | "node": ">=0.8"
1343 | }
1344 | },
1345 | "node_modules/to-regex-range": {
1346 | "version": "5.0.1",
1347 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
1348 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
1349 | "dev": true,
1350 | "license": "MIT",
1351 | "dependencies": {
1352 | "is-number": "^7.0.0"
1353 | },
1354 | "engines": {
1355 | "node": ">=8.0"
1356 | }
1357 | },
1358 | "node_modules/ts-interface-checker": {
1359 | "version": "0.1.13",
1360 | "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
1361 | "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
1362 | "dev": true,
1363 | "license": "Apache-2.0"
1364 | },
1365 | "node_modules/util-deprecate": {
1366 | "version": "1.0.2",
1367 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
1368 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
1369 | "dev": true,
1370 | "license": "MIT"
1371 | },
1372 | "node_modules/which": {
1373 | "version": "2.0.2",
1374 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
1375 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
1376 | "dev": true,
1377 | "license": "ISC",
1378 | "dependencies": {
1379 | "isexe": "^2.0.0"
1380 | },
1381 | "bin": {
1382 | "node-which": "bin/node-which"
1383 | },
1384 | "engines": {
1385 | "node": ">= 8"
1386 | }
1387 | },
1388 | "node_modules/wrap-ansi": {
1389 | "version": "8.1.0",
1390 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
1391 | "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
1392 | "dev": true,
1393 | "license": "MIT",
1394 | "dependencies": {
1395 | "ansi-styles": "^6.1.0",
1396 | "string-width": "^5.0.1",
1397 | "strip-ansi": "^7.0.1"
1398 | },
1399 | "engines": {
1400 | "node": ">=12"
1401 | },
1402 | "funding": {
1403 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
1404 | }
1405 | },
1406 | "node_modules/wrap-ansi-cjs": {
1407 | "name": "wrap-ansi",
1408 | "version": "7.0.0",
1409 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
1410 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
1411 | "dev": true,
1412 | "license": "MIT",
1413 | "dependencies": {
1414 | "ansi-styles": "^4.0.0",
1415 | "string-width": "^4.1.0",
1416 | "strip-ansi": "^6.0.0"
1417 | },
1418 | "engines": {
1419 | "node": ">=10"
1420 | },
1421 | "funding": {
1422 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
1423 | }
1424 | },
1425 | "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
1426 | "version": "5.0.1",
1427 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
1428 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
1429 | "dev": true,
1430 | "license": "MIT",
1431 | "engines": {
1432 | "node": ">=8"
1433 | }
1434 | },
1435 | "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
1436 | "version": "4.3.0",
1437 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
1438 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
1439 | "dev": true,
1440 | "license": "MIT",
1441 | "dependencies": {
1442 | "color-convert": "^2.0.1"
1443 | },
1444 | "engines": {
1445 | "node": ">=8"
1446 | },
1447 | "funding": {
1448 | "url": "https://github.com/chalk/ansi-styles?sponsor=1"
1449 | }
1450 | },
1451 | "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
1452 | "version": "8.0.0",
1453 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
1454 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
1455 | "dev": true,
1456 | "license": "MIT"
1457 | },
1458 | "node_modules/wrap-ansi-cjs/node_modules/string-width": {
1459 | "version": "4.2.3",
1460 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
1461 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
1462 | "dev": true,
1463 | "license": "MIT",
1464 | "dependencies": {
1465 | "emoji-regex": "^8.0.0",
1466 | "is-fullwidth-code-point": "^3.0.0",
1467 | "strip-ansi": "^6.0.1"
1468 | },
1469 | "engines": {
1470 | "node": ">=8"
1471 | }
1472 | },
1473 | "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
1474 | "version": "6.0.1",
1475 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1476 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1477 | "dev": true,
1478 | "license": "MIT",
1479 | "dependencies": {
1480 | "ansi-regex": "^5.0.1"
1481 | },
1482 | "engines": {
1483 | "node": ">=8"
1484 | }
1485 | },
1486 | "node_modules/yaml": {
1487 | "version": "2.5.1",
1488 | "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz",
1489 | "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==",
1490 | "dev": true,
1491 | "license": "ISC",
1492 | "bin": {
1493 | "yaml": "bin.mjs"
1494 | },
1495 | "engines": {
1496 | "node": ">= 14"
1497 | }
1498 | }
1499 | }
1500 | }
1501 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "devDependencies": {
3 | "tailwindcss": "^3.4.11"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/public/README.md:
--------------------------------------------------------------------------------
1 | # Public Directory
2 |
3 | The `public` directory contains static assets for the project. These assets are publicly accessible and typically include files such as:
4 |
5 | - **HTML files**: The main entry points for the web application.
6 | - **CSS files**: Stylesheets for the application.
7 | - **JavaScript files**: Client-side scripts.
8 | - **Images**: Logos, icons, and other image assets.
9 | - **Fonts**: Custom fonts used in the application.
10 |
11 | These files are served directly to the client without any processing by the server, ensuring fast and efficient delivery of static content.
12 |
--------------------------------------------------------------------------------
/public/assets/bytesize_banner.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/public/index.js:
--------------------------------------------------------------------------------
1 | htmx.config.globalViewTransitions = true
2 | document.body.addEventListener('htmx:beforeTransition', (e) => {
3 | console.log(e);
4 | if (e.target !== document.body) {
5 | e.preventDefault();
6 | }
7 | });
--------------------------------------------------------------------------------
/public/styles.css:
--------------------------------------------------------------------------------
1 | /*
2 | ! tailwindcss v3.4.10 | MIT License | https://tailwindcss.com
3 | */
4 |
5 | /*
6 | 1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
7 | 2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
8 | */
9 |
10 | *,
11 | ::before,
12 | ::after {
13 | box-sizing: border-box;
14 | /* 1 */
15 | border-width: 0;
16 | /* 2 */
17 | border-style: solid;
18 | /* 2 */
19 | border-color: #e5e7eb;
20 | /* 2 */
21 | }
22 |
23 | ::before,
24 | ::after {
25 | --tw-content: '';
26 | }
27 |
28 | /*
29 | 1. Use a consistent sensible line-height in all browsers.
30 | 2. Prevent adjustments of font size after orientation changes in iOS.
31 | 3. Use a more readable tab size.
32 | 4. Use the user's configured `sans` font-family by default.
33 | 5. Use the user's configured `sans` font-feature-settings by default.
34 | 6. Use the user's configured `sans` font-variation-settings by default.
35 | 7. Disable tap highlights on iOS
36 | */
37 |
38 | html,
39 | :host {
40 | line-height: 1.5;
41 | /* 1 */
42 | -webkit-text-size-adjust: 100%;
43 | /* 2 */
44 | -moz-tab-size: 4;
45 | /* 3 */
46 | -o-tab-size: 4;
47 | tab-size: 4;
48 | /* 3 */
49 | font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
50 | /* 4 */
51 | font-feature-settings: normal;
52 | /* 5 */
53 | font-variation-settings: normal;
54 | /* 6 */
55 | -webkit-tap-highlight-color: transparent;
56 | /* 7 */
57 | }
58 |
59 | /*
60 | 1. Remove the margin in all browsers.
61 | 2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
62 | */
63 |
64 | body {
65 | margin: 0;
66 | /* 1 */
67 | line-height: inherit;
68 | /* 2 */
69 | }
70 |
71 | /*
72 | 1. Add the correct height in Firefox.
73 | 2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
74 | 3. Ensure horizontal rules are visible by default.
75 | */
76 |
77 | hr {
78 | height: 0;
79 | /* 1 */
80 | color: inherit;
81 | /* 2 */
82 | border-top-width: 1px;
83 | /* 3 */
84 | }
85 |
86 | /*
87 | Add the correct text decoration in Chrome, Edge, and Safari.
88 | */
89 |
90 | abbr:where([title]) {
91 | -webkit-text-decoration: underline dotted;
92 | text-decoration: underline dotted;
93 | }
94 |
95 | /*
96 | Remove the default font size and weight for headings.
97 | */
98 |
99 | h1,
100 | h2,
101 | h3,
102 | h4,
103 | h5,
104 | h6 {
105 | font-size: inherit;
106 | font-weight: inherit;
107 | }
108 |
109 | /*
110 | Reset links to optimize for opt-in styling instead of opt-out.
111 | */
112 |
113 | a {
114 | color: inherit;
115 | text-decoration: inherit;
116 | }
117 |
118 | /*
119 | Add the correct font weight in Edge and Safari.
120 | */
121 |
122 | b,
123 | strong {
124 | font-weight: bolder;
125 | }
126 |
127 | /*
128 | 1. Use the user's configured `mono` font-family by default.
129 | 2. Use the user's configured `mono` font-feature-settings by default.
130 | 3. Use the user's configured `mono` font-variation-settings by default.
131 | 4. Correct the odd `em` font sizing in all browsers.
132 | */
133 |
134 | code,
135 | kbd,
136 | samp,
137 | pre {
138 | font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
139 | /* 1 */
140 | font-feature-settings: normal;
141 | /* 2 */
142 | font-variation-settings: normal;
143 | /* 3 */
144 | font-size: 1em;
145 | /* 4 */
146 | }
147 |
148 | /*
149 | Add the correct font size in all browsers.
150 | */
151 |
152 | small {
153 | font-size: 80%;
154 | }
155 |
156 | /*
157 | Prevent `sub` and `sup` elements from affecting the line height in all browsers.
158 | */
159 |
160 | sub,
161 | sup {
162 | font-size: 75%;
163 | line-height: 0;
164 | position: relative;
165 | vertical-align: baseline;
166 | }
167 |
168 | sub {
169 | bottom: -0.25em;
170 | }
171 |
172 | sup {
173 | top: -0.5em;
174 | }
175 |
176 | /*
177 | 1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
178 | 2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
179 | 3. Remove gaps between table borders by default.
180 | */
181 |
182 | table {
183 | text-indent: 0;
184 | /* 1 */
185 | border-color: inherit;
186 | /* 2 */
187 | border-collapse: collapse;
188 | /* 3 */
189 | }
190 |
191 | /*
192 | 1. Change the font styles in all browsers.
193 | 2. Remove the margin in Firefox and Safari.
194 | 3. Remove default padding in all browsers.
195 | */
196 |
197 | button,
198 | input,
199 | optgroup,
200 | select,
201 | textarea {
202 | font-family: inherit;
203 | /* 1 */
204 | font-feature-settings: inherit;
205 | /* 1 */
206 | font-variation-settings: inherit;
207 | /* 1 */
208 | font-size: 100%;
209 | /* 1 */
210 | font-weight: inherit;
211 | /* 1 */
212 | line-height: inherit;
213 | /* 1 */
214 | letter-spacing: inherit;
215 | /* 1 */
216 | color: inherit;
217 | /* 1 */
218 | margin: 0;
219 | /* 2 */
220 | padding: 0;
221 | /* 3 */
222 | }
223 |
224 | /*
225 | Remove the inheritance of text transform in Edge and Firefox.
226 | */
227 |
228 | button,
229 | select {
230 | text-transform: none;
231 | }
232 |
233 | /*
234 | 1. Correct the inability to style clickable types in iOS and Safari.
235 | 2. Remove default button styles.
236 | */
237 |
238 | button,
239 | input:where([type='button']),
240 | input:where([type='reset']),
241 | input:where([type='submit']) {
242 | -webkit-appearance: button;
243 | /* 1 */
244 | background-color: transparent;
245 | /* 2 */
246 | background-image: none;
247 | /* 2 */
248 | }
249 |
250 | /*
251 | Use the modern Firefox focus style for all focusable elements.
252 | */
253 |
254 | :-moz-focusring {
255 | outline: auto;
256 | }
257 |
258 | /*
259 | Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
260 | */
261 |
262 | :-moz-ui-invalid {
263 | box-shadow: none;
264 | }
265 |
266 | /*
267 | Add the correct vertical alignment in Chrome and Firefox.
268 | */
269 |
270 | progress {
271 | vertical-align: baseline;
272 | }
273 |
274 | /*
275 | Correct the cursor style of increment and decrement buttons in Safari.
276 | */
277 |
278 | ::-webkit-inner-spin-button,
279 | ::-webkit-outer-spin-button {
280 | height: auto;
281 | }
282 |
283 | /*
284 | 1. Correct the odd appearance in Chrome and Safari.
285 | 2. Correct the outline style in Safari.
286 | */
287 |
288 | [type='search'] {
289 | -webkit-appearance: textfield;
290 | /* 1 */
291 | outline-offset: -2px;
292 | /* 2 */
293 | }
294 |
295 | /*
296 | Remove the inner padding in Chrome and Safari on macOS.
297 | */
298 |
299 | ::-webkit-search-decoration {
300 | -webkit-appearance: none;
301 | }
302 |
303 | /*
304 | 1. Correct the inability to style clickable types in iOS and Safari.
305 | 2. Change font properties to `inherit` in Safari.
306 | */
307 |
308 | ::-webkit-file-upload-button {
309 | -webkit-appearance: button;
310 | /* 1 */
311 | font: inherit;
312 | /* 2 */
313 | }
314 |
315 | /*
316 | Add the correct display in Chrome and Safari.
317 | */
318 |
319 | summary {
320 | display: list-item;
321 | }
322 |
323 | /*
324 | Removes the default spacing and border for appropriate elements.
325 | */
326 |
327 | blockquote,
328 | dl,
329 | dd,
330 | h1,
331 | h2,
332 | h3,
333 | h4,
334 | h5,
335 | h6,
336 | hr,
337 | figure,
338 | p,
339 | pre {
340 | margin: 0;
341 | }
342 |
343 | fieldset {
344 | margin: 0;
345 | padding: 0;
346 | }
347 |
348 | legend {
349 | padding: 0;
350 | }
351 |
352 | ol,
353 | ul,
354 | menu {
355 | list-style: none;
356 | margin: 0;
357 | padding: 0;
358 | }
359 |
360 | /*
361 | Reset default styling for dialogs.
362 | */
363 |
364 | dialog {
365 | padding: 0;
366 | }
367 |
368 | /*
369 | Prevent resizing textareas horizontally by default.
370 | */
371 |
372 | textarea {
373 | resize: vertical;
374 | }
375 |
376 | /*
377 | 1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
378 | 2. Set the default placeholder color to the user's configured gray 400 color.
379 | */
380 |
381 | input::-moz-placeholder, textarea::-moz-placeholder {
382 | opacity: 1;
383 | /* 1 */
384 | color: #9ca3af;
385 | /* 2 */
386 | }
387 |
388 | input::placeholder,
389 | textarea::placeholder {
390 | opacity: 1;
391 | /* 1 */
392 | color: #9ca3af;
393 | /* 2 */
394 | }
395 |
396 | /*
397 | Set the default cursor for buttons.
398 | */
399 |
400 | button,
401 | [role="button"] {
402 | cursor: pointer;
403 | }
404 |
405 | /*
406 | Make sure disabled buttons don't get the pointer cursor.
407 | */
408 |
409 | :disabled {
410 | cursor: default;
411 | }
412 |
413 | /*
414 | 1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
415 | 2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
416 | This can trigger a poorly considered lint error in some tools but is included by design.
417 | */
418 |
419 | img,
420 | svg,
421 | video,
422 | canvas,
423 | audio,
424 | iframe,
425 | embed,
426 | object {
427 | display: block;
428 | /* 1 */
429 | vertical-align: middle;
430 | /* 2 */
431 | }
432 |
433 | /*
434 | Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
435 | */
436 |
437 | img,
438 | video {
439 | max-width: 100%;
440 | height: auto;
441 | }
442 |
443 | /* Make elements with the HTML hidden attribute stay hidden by default */
444 |
445 | [hidden] {
446 | display: none;
447 | }
448 |
449 | *, ::before, ::after {
450 | --tw-border-spacing-x: 0;
451 | --tw-border-spacing-y: 0;
452 | --tw-translate-x: 0;
453 | --tw-translate-y: 0;
454 | --tw-rotate: 0;
455 | --tw-skew-x: 0;
456 | --tw-skew-y: 0;
457 | --tw-scale-x: 1;
458 | --tw-scale-y: 1;
459 | --tw-pan-x: ;
460 | --tw-pan-y: ;
461 | --tw-pinch-zoom: ;
462 | --tw-scroll-snap-strictness: proximity;
463 | --tw-gradient-from-position: ;
464 | --tw-gradient-via-position: ;
465 | --tw-gradient-to-position: ;
466 | --tw-ordinal: ;
467 | --tw-slashed-zero: ;
468 | --tw-numeric-figure: ;
469 | --tw-numeric-spacing: ;
470 | --tw-numeric-fraction: ;
471 | --tw-ring-inset: ;
472 | --tw-ring-offset-width: 0px;
473 | --tw-ring-offset-color: #fff;
474 | --tw-ring-color: rgb(59 130 246 / 0.5);
475 | --tw-ring-offset-shadow: 0 0 #0000;
476 | --tw-ring-shadow: 0 0 #0000;
477 | --tw-shadow: 0 0 #0000;
478 | --tw-shadow-colored: 0 0 #0000;
479 | --tw-blur: ;
480 | --tw-brightness: ;
481 | --tw-contrast: ;
482 | --tw-grayscale: ;
483 | --tw-hue-rotate: ;
484 | --tw-invert: ;
485 | --tw-saturate: ;
486 | --tw-sepia: ;
487 | --tw-drop-shadow: ;
488 | --tw-backdrop-blur: ;
489 | --tw-backdrop-brightness: ;
490 | --tw-backdrop-contrast: ;
491 | --tw-backdrop-grayscale: ;
492 | --tw-backdrop-hue-rotate: ;
493 | --tw-backdrop-invert: ;
494 | --tw-backdrop-opacity: ;
495 | --tw-backdrop-saturate: ;
496 | --tw-backdrop-sepia: ;
497 | --tw-contain-size: ;
498 | --tw-contain-layout: ;
499 | --tw-contain-paint: ;
500 | --tw-contain-style: ;
501 | }
502 |
503 | ::backdrop {
504 | --tw-border-spacing-x: 0;
505 | --tw-border-spacing-y: 0;
506 | --tw-translate-x: 0;
507 | --tw-translate-y: 0;
508 | --tw-rotate: 0;
509 | --tw-skew-x: 0;
510 | --tw-skew-y: 0;
511 | --tw-scale-x: 1;
512 | --tw-scale-y: 1;
513 | --tw-pan-x: ;
514 | --tw-pan-y: ;
515 | --tw-pinch-zoom: ;
516 | --tw-scroll-snap-strictness: proximity;
517 | --tw-gradient-from-position: ;
518 | --tw-gradient-via-position: ;
519 | --tw-gradient-to-position: ;
520 | --tw-ordinal: ;
521 | --tw-slashed-zero: ;
522 | --tw-numeric-figure: ;
523 | --tw-numeric-spacing: ;
524 | --tw-numeric-fraction: ;
525 | --tw-ring-inset: ;
526 | --tw-ring-offset-width: 0px;
527 | --tw-ring-offset-color: #fff;
528 | --tw-ring-color: rgb(59 130 246 / 0.5);
529 | --tw-ring-offset-shadow: 0 0 #0000;
530 | --tw-ring-shadow: 0 0 #0000;
531 | --tw-shadow: 0 0 #0000;
532 | --tw-shadow-colored: 0 0 #0000;
533 | --tw-blur: ;
534 | --tw-brightness: ;
535 | --tw-contrast: ;
536 | --tw-grayscale: ;
537 | --tw-hue-rotate: ;
538 | --tw-invert: ;
539 | --tw-saturate: ;
540 | --tw-sepia: ;
541 | --tw-drop-shadow: ;
542 | --tw-backdrop-blur: ;
543 | --tw-backdrop-brightness: ;
544 | --tw-backdrop-contrast: ;
545 | --tw-backdrop-grayscale: ;
546 | --tw-backdrop-hue-rotate: ;
547 | --tw-backdrop-invert: ;
548 | --tw-backdrop-opacity: ;
549 | --tw-backdrop-saturate: ;
550 | --tw-backdrop-sepia: ;
551 | --tw-contain-size: ;
552 | --tw-contain-layout: ;
553 | --tw-contain-paint: ;
554 | --tw-contain-style: ;
555 | }
556 |
557 | .container {
558 | width: 100%;
559 | }
560 |
561 | @media (min-width: 640px) {
562 | .container {
563 | max-width: 640px;
564 | }
565 | }
566 |
567 | @media (min-width: 768px) {
568 | .container {
569 | max-width: 768px;
570 | }
571 | }
572 |
573 | @media (min-width: 1024px) {
574 | .container {
575 | max-width: 1024px;
576 | }
577 | }
578 |
579 | @media (min-width: 1280px) {
580 | .container {
581 | max-width: 1280px;
582 | }
583 | }
584 |
585 | @media (min-width: 1536px) {
586 | .container {
587 | max-width: 1536px;
588 | }
589 | }
590 |
591 | .static {
592 | position: static;
593 | }
594 |
595 | .mx-auto {
596 | margin-left: auto;
597 | margin-right: auto;
598 | }
599 |
600 | .mb-10 {
601 | margin-bottom: 2.5rem;
602 | }
603 |
604 | .mb-4 {
605 | margin-bottom: 1rem;
606 | }
607 |
608 | .mt-10 {
609 | margin-top: 2.5rem;
610 | }
611 |
612 | .flex {
613 | display: flex;
614 | }
615 |
616 | .h-6 {
617 | height: 1.5rem;
618 | }
619 |
620 | .w-6 {
621 | width: 1.5rem;
622 | }
623 |
624 | .w-96 {
625 | width: 24rem;
626 | }
627 |
628 | .w-auto {
629 | width: auto;
630 | }
631 |
632 | .w-full {
633 | width: 100%;
634 | }
635 |
636 | .max-w-xs {
637 | max-width: 20rem;
638 | }
639 |
640 | .shrink-0 {
641 | flex-shrink: 0;
642 | }
643 |
644 | .flex-col {
645 | flex-direction: column;
646 | }
647 |
648 | .items-center {
649 | align-items: center;
650 | }
651 |
652 | .justify-end {
653 | justify-content: flex-end;
654 | }
655 |
656 | .justify-center {
657 | justify-content: center;
658 | }
659 |
660 | .overflow-auto {
661 | overflow: auto;
662 | }
663 |
664 | .stroke-current {
665 | stroke: currentColor;
666 | }
667 |
668 | .text-2xl {
669 | font-size: 1.5rem;
670 | line-height: 2rem;
671 | }
672 |
673 | .font-bold {
674 | font-weight: 700;
675 | }
676 |
677 | .text-blue-500 {
678 | --tw-text-opacity: 1;
679 | color: rgb(59 130 246 / var(--tw-text-opacity));
680 | }
681 |
682 | .underline {
683 | text-decoration-line: underline;
684 | }
685 |
686 | .antialiased {
687 | -webkit-font-smoothing: antialiased;
688 | -moz-osx-font-smoothing: grayscale;
689 | }
690 |
691 | .shadow-xl {
692 | --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
693 | --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);
694 | box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
695 | }
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: ["./**/*.html", "./**/*.templ", "./**/*.go", ],
4 | theme: {
5 | extend: {},
6 | },
7 |
8 | plugins: [],
9 | }
--------------------------------------------------------------------------------