detached 5dc0e41

Merge branch 'dev'

commit
5dc0e4156bcb6bdf58e4dda89014cc7e016ab18b
author
bamen · · 2024-10-16 08:57 UTC
merge of
b05cd54 + 2966ef2 · diff against the first parent
signature
unsigned
44 files · +213 -1679
M .vscode/launch.json +1 -1
@@ -9,7 +9,7 @@
99 "type": "go",
1010 "request": "launch",
1111 "mode": "debug",
12- "program": "./cmd/cli/main.go",
12+ "program": "./main.go",
1313 }
1414
1515
@@ -9,7 +9,7 @@
9 "type": "go",9 "type": "go",
10 "request": "launch",10 "request": "launch",
11 "mode": "debug",11 "mode": "debug",
12- "program": "./cmd/cli/main.go",12+ "program": "./main.go",
13 }13 }
14 14
15 15
M Makefile +56 -11
@@ -1,19 +1,64 @@
1+# This Makefile is used for dev purposes
12 # Variables
2-INSTALL_DIR = /usr/bin
3-BINARY_NAME = gordon
3+REPO := ghcr.io/bnema/gordon
4+TAG := dev
5+DIST_DIR := ./dist
6+ENGINE := podman
7+
8+# Architectures
9+ARCHS := amd64 arm64
10+
11+# Phony targets
12+.PHONY: all build build-push clean
13+
414 # Default target
515 all: build
616
7-# Build the Go binary
17+# Build binaries
818 build:
9- go build -o $(BINARY_NAME) cmd/cli/main.go
19+ @echo "Building Go binaries..."
20+ @mkdir -p $(DIST_DIR)
21+ @rm -f $(DIST_DIR)/*
22+ @CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $(DIST_DIR)/gordon-linux-amd64 ./main.go
23+ @CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $(DIST_DIR)/gordon-linux-arm64 ./main.go
24+ @echo "Go binaries built successfully"
1025
11-# Install the binary to /usr/local/bin
12-install:
13- mv $(BINARY_NAME) $(INSTALL_DIR)
26+# Build and push Docker images
27+build-push: build
28+ @echo "Cleaning up dangling images..."
29+ @$(ENGINE) image prune -f
1430
15-# Clean up the built binary
16-clean:
17- rm -f $(BINARY_NAME)
31+ @echo "Building and pushing Docker images..."
32+ @for arch in $(ARCHS); do \
33+ cp $(DIST_DIR)/gordon-linux-$$arch gordon; \
34+ $(ENGINE) build -t $(REPO):$(TAG)-$$arch .; \
35+ rm gordon; \
36+ $(ENGINE) push $(REPO):$(TAG)-$$arch; \
37+ done
38+
39+ @echo "Removing existing manifest..."
40+ @$(ENGINE) manifest rm $(REPO):$(TAG) || true
41+
42+ @echo "Creating multi-arch manifest..."
43+ @$(ENGINE) manifest create $(REPO):$(TAG) \
44+ $(REPO):$(TAG)-amd64 \
45+ $(REPO):$(TAG)-arm64
1846
19-.PHONY: all build install clean⏎̸
47+ @echo "Annotating arm64 image..."
48+ @$(ENGINE) manifest annotate $(REPO):$(TAG) \
49+ $(REPO):$(TAG)-arm64 --arch arm64 --variant v8
50+
51+ @echo "Inspecting manifest..."
52+ @$(ENGINE) manifest inspect $(REPO):$(TAG)
53+
54+ @echo "Pushing multi-arch manifest..."
55+ @$(ENGINE) manifest push --all $(REPO):$(TAG)
56+
57+ @echo "Script completed successfully."
58+
59+# Clean up
60+clean:
61+ @echo "Cleaning up..."
62+ @rm -rf $(DIST_DIR)
63+ @$(ENGINE) system prune -f
64+ @echo "Cleanup completed."⏎̸
@@ -1,19 +1,64 @@
1+# This Makefile is used for dev purposes
1 # Variables2 # Variables
2-INSTALL_DIR = /usr/bin3+REPO := ghcr.io/bnema/gordon
3-BINARY_NAME = gordon 4+TAG := dev
5+DIST_DIR := ./dist
6+ENGINE := podman
7+
8+# Architectures
9+ARCHS := amd64 arm64
10+
11+# Phony targets
12+.PHONY: all build build-push clean
13+
4 # Default target14 # Default target
5 all: build15 all: build
6 16
7-# Build the Go binary17+# Build binaries
8 build:18 build:
9- go build -o $(BINARY_NAME) cmd/cli/main.go19+ @echo "Building Go binaries..."
20+ @mkdir -p $(DIST_DIR)
21+ @rm -f $(DIST_DIR)/*
22+ @CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $(DIST_DIR)/gordon-linux-amd64 ./main.go
23+ @CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $(DIST_DIR)/gordon-linux-arm64 ./main.go
24+ @echo "Go binaries built successfully"
10 25
11-# Install the binary to /usr/local/bin26+# Build and push Docker images
12-install:27+build-push: build
13- mv $(BINARY_NAME) $(INSTALL_DIR)28+ @echo "Cleaning up dangling images..."
29+ @$(ENGINE) image prune -f
14 30
15-# Clean up the built binary31+ @echo "Building and pushing Docker images..."
16-clean:32+ @for arch in $(ARCHS); do \
17- rm -f $(BINARY_NAME)33+ cp $(DIST_DIR)/gordon-linux-$$arch gordon; \
34+ $(ENGINE) build -t $(REPO):$(TAG)-$$arch .; \
35+ rm gordon; \
36+ $(ENGINE) push $(REPO):$(TAG)-$$arch; \
37+ done
38+
39+ @echo "Removing existing manifest..."
40+ @$(ENGINE) manifest rm $(REPO):$(TAG) || true
41+
42+ @echo "Creating multi-arch manifest..."
43+ @$(ENGINE) manifest create $(REPO):$(TAG) \
44+ $(REPO):$(TAG)-amd64 \
45+ $(REPO):$(TAG)-arm64
18 46
19-.PHONY: all build install clean⏎̸47+ @echo "Annotating arm64 image..."
48+ @$(ENGINE) manifest annotate $(REPO):$(TAG) \
49+ $(REPO):$(TAG)-arm64 --arch arm64 --variant v8
50+
51+ @echo "Inspecting manifest..."
52+ @$(ENGINE) manifest inspect $(REPO):$(TAG)
53+
54+ @echo "Pushing multi-arch manifest..."
55+ @$(ENGINE) manifest push --all $(REPO):$(TAG)
56+
57+ @echo "Script completed successfully."
58+
59+# Clean up
60+clean:
61+ @echo "Cleaning up..."
62+ @rm -rf $(DIST_DIR)
63+ @$(ENGINE) system prune -f
64+ @echo "Cleanup completed."⏎̸
M assets/vhs/demo_deploy.tape +1 -1
@@ -60,7 +60,7 @@ Require curl
6060
6161 Set TypingSpeed 75ms
6262 Set Shell "bash"
63-Set FontSize 17
63+Set FontSize 16
6464 Set FontFamily "FiraCode Nerd Font"
6565 Set Width 1200
6666 Set Height 500
@@ -60,7 +60,7 @@ Require curl
60 60
61 Set TypingSpeed 75ms61 Set TypingSpeed 75ms
62 Set Shell "bash"62 Set Shell "bash"
63-Set FontSize 1763+Set FontSize 16
64 Set FontFamily "FiraCode Nerd Font"64 Set FontFamily "FiraCode Nerd Font"
65 Set Width 120065 Set Width 1200
66 Set Height 50066 Set Height 500
D build-dev.sh +0 -20
@@ -1,20 +0,0 @@
1-#!/bin/bash
2-
3-set -e
4-
5-REPO="ghcr.io/bnema/gordon"
6-TAG="dev"
7-DIST_DIR="./dist"
8-
9-# Ensure dist directory exists
10-mkdir -p $DIST_DIR
11-
12-# Clean up previous builds
13-rm -f $DIST_DIR/*
14-
15-# Build Go binaries for multiple platforms with CGO_ENABLED=0
16-echo "Building Go binaries..."
17-CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $DIST_DIR/gordon-linux-amd64 ./main.go
18-CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $DIST_DIR/gordon-linux-arm64 ./main.go
19-
20-echo "Successfully built Go binaries"
@@ -1,20 +0,0 @@
1-#!/bin/bash
2-
3-set -e
4-
5-REPO="ghcr.io/bnema/gordon"
6-TAG="dev"
7-DIST_DIR="./dist"
8-
9-# Ensure dist directory exists
10-mkdir -p $DIST_DIR
11-
12-# Clean up previous builds
13-rm -f $DIST_DIR/*
14-
15-# Build Go binaries for multiple platforms with CGO_ENABLED=0
16-echo "Building Go binaries..."
17-CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $DIST_DIR/gordon-linux-amd64 ./main.go
18-CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $DIST_DIR/gordon-linux-arm64 ./main.go
19-
20-echo "Successfully built Go binaries"
D buildpush-dev.sh +0 -71
@@ -1,71 +0,0 @@
1-#!/bin/bash
2-set -e
3-ENGINE="podman"
4-REPO="ghcr.io/bnema/gordon"
5-TAG="dev"
6-DIST_DIR="./dist"
7-
8-# Function to handle errors
9-handle_error() {
10- echo "Error occurred. Cleaning up..."
11- $ENGINE system prune -f
12- exit 1
13-}
14-
15-# Set up error handling
16-trap 'handle_error' ERR
17-
18-# Ensure dist directory exists
19-mkdir -p $DIST_DIR
20-
21-# Build Go binaries for multiple platforms with CGO_ENABLED=0
22-echo "Building Go binaries..."
23-CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $DIST_DIR/gordon-linux-amd64 ./main.go
24-CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $DIST_DIR/gordon-linux-arm64 ./main.go
25-
26-# Clean up any dangling images before building
27-echo "Cleaning up dangling images..."
28-$ENGINE image prune -f
29-
30-# Build Docker images for each architecture
31-echo "Building Docker images..."
32-for ARCH in amd64 arm64; do
33- # Copy the appropriate binary to the root directory and rename it to 'gordon'
34- cp $DIST_DIR/gordon-linux-$ARCH gordon
35-
36- # Build the Docker image
37- $ENGINE build -t $REPO:${TAG}-$ARCH .
38-
39- # Remove the temporary 'gordon' file
40- rm gordon
41-done
42-
43-# Push images
44-echo "Pushing Docker images..."
45-$ENGINE push $REPO:${TAG}-amd64
46-$ENGINE push $REPO:${TAG}-arm64
47-
48-# Remove existing manifest if it exists
49-echo "Removing existing manifest..."
50-$ENGINE manifest rm $REPO:$TAG || true
51-
52-# Create multi-arch manifest
53-echo "Creating multi-arch manifest..."
54-$ENGINE manifest create $REPO:$TAG \
55- $REPO:${TAG}-amd64 \
56- $REPO:${TAG}-arm64
57-
58-# Annotate the arm64 image with variant information
59-echo "Annotating arm64 image..."
60-$ENGINE manifest annotate $REPO:$TAG \
61- $REPO:${TAG}-arm64 --arch arm64 --variant v8
62-
63-# Debug: List manifests
64-echo "Listing manifests..."
65-$ENGINE manifest inspect $REPO:$TAG
66-
67-# Push multi-arch manifest
68-echo "Pushing multi-arch manifest..."
69-$ENGINE manifest push --all $REPO:$TAG
70-
71-echo "Script completed successfully."
@@ -1,71 +0,0 @@
1-#!/bin/bash
2-set -e
3-ENGINE="podman"
4-REPO="ghcr.io/bnema/gordon"
5-TAG="dev"
6-DIST_DIR="./dist"
7-
8-# Function to handle errors
9-handle_error() {
10- echo "Error occurred. Cleaning up..."
11- $ENGINE system prune -f
12- exit 1
13-}
14-
15-# Set up error handling
16-trap 'handle_error' ERR
17-
18-# Ensure dist directory exists
19-mkdir -p $DIST_DIR
20-
21-# Build Go binaries for multiple platforms with CGO_ENABLED=0
22-echo "Building Go binaries..."
23-CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $DIST_DIR/gordon-linux-amd64 ./main.go
24-CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o $DIST_DIR/gordon-linux-arm64 ./main.go
25-
26-# Clean up any dangling images before building
27-echo "Cleaning up dangling images..."
28-$ENGINE image prune -f
29-
30-# Build Docker images for each architecture
31-echo "Building Docker images..."
32-for ARCH in amd64 arm64; do
33- # Copy the appropriate binary to the root directory and rename it to 'gordon'
34- cp $DIST_DIR/gordon-linux-$ARCH gordon
35-
36- # Build the Docker image
37- $ENGINE build -t $REPO:${TAG}-$ARCH .
38-
39- # Remove the temporary 'gordon' file
40- rm gordon
41-done
42-
43-# Push images
44-echo "Pushing Docker images..."
45-$ENGINE push $REPO:${TAG}-amd64
46-$ENGINE push $REPO:${TAG}-arm64
47-
48-# Remove existing manifest if it exists
49-echo "Removing existing manifest..."
50-$ENGINE manifest rm $REPO:$TAG || true
51-
52-# Create multi-arch manifest
53-echo "Creating multi-arch manifest..."
54-$ENGINE manifest create $REPO:$TAG \
55- $REPO:${TAG}-amd64 \
56- $REPO:${TAG}-arm64
57-
58-# Annotate the arm64 image with variant information
59-echo "Annotating arm64 image..."
60-$ENGINE manifest annotate $REPO:$TAG \
61- $REPO:${TAG}-arm64 --arch arm64 --variant v8
62-
63-# Debug: List manifests
64-echo "Listing manifests..."
65-$ENGINE manifest inspect $REPO:$TAG
66-
67-# Push multi-arch manifest
68-echo "Pushing multi-arch manifest..."
69-$ENGINE manifest push --all $REPO:$TAG
70-
71-echo "Script completed successfully."
M internal/cli/cmd/deploy.go +4 -2
@@ -116,7 +116,7 @@ func exportDockerImage(imageName string) (io.ReadCloser, int64, error) {
116116
117117 func deployImage(a *cli.App, reader io.Reader, imageName, port, targetDomain string) error {
118118
119- log.Info("Attempting to deploy...", "image", imageName, "port", port, "target_domain", targetDomain)
119+ log.Info("Attempting to deploy...", "image", imageName, "port", port, "target", targetDomain)
120120
121121 reqPayload := common.RequestPayload{
122122 Type: "deploy",
@@ -172,6 +172,8 @@ func waitForDeployment(domain string, containerID string) error {
172172 client := &http.Client{Timeout: 10 * time.Second}
173173 maxRetries := 20
174174 retryInterval := time.Second
175+ // shorten the container id to 12 characters
176+ shortContainerID := containerID[:12]
175177
176178 log.Info("Waiting for deployment to be reachable")
177179 for i := 0; i < maxRetries; i++ {
@@ -181,7 +183,7 @@ func waitForDeployment(domain string, containerID string) error {
181183 if resp.StatusCode == http.StatusOK {
182184 log.Info("Deployment successful",
183185 "domain", domain,
184- "container_id", containerID)
186+ "container_id", shortContainerID)
185187 return nil
186188 }
187189 // Check for error messages in the response body
@@ -116,7 +116,7 @@ func exportDockerImage(imageName string) (io.ReadCloser, int64, error) {
116 116
117 func deployImage(a *cli.App, reader io.Reader, imageName, port, targetDomain string) error {117 func deployImage(a *cli.App, reader io.Reader, imageName, port, targetDomain string) error {
118 118
119- log.Info("Attempting to deploy...", "image", imageName, "port", port, "target_domain", targetDomain)119+ log.Info("Attempting to deploy...", "image", imageName, "port", port, "target", targetDomain)
120 120
121 reqPayload := common.RequestPayload{121 reqPayload := common.RequestPayload{
122 Type: "deploy",122 Type: "deploy",
@@ -172,6 +172,8 @@ func waitForDeployment(domain string, containerID string) error {
172 client := &http.Client{Timeout: 10 * time.Second}172 client := &http.Client{Timeout: 10 * time.Second}
173 maxRetries := 20173 maxRetries := 20
174 retryInterval := time.Second174 retryInterval := time.Second
175+ // shorten the container id to 12 characters
176+ shortContainerID := containerID[:12]
175 177
176 log.Info("Waiting for deployment to be reachable")178 log.Info("Waiting for deployment to be reachable")
177 for i := 0; i < maxRetries; i++ {179 for i := 0; i < maxRetries; i++ {
@@ -181,7 +183,7 @@ func waitForDeployment(domain string, containerID string) error {
181 if resp.StatusCode == http.StatusOK {183 if resp.StatusCode == http.StatusOK {
182 log.Info("Deployment successful",184 log.Info("Deployment successful",
183 "domain", domain,185 "domain", domain,
184- "container_id", containerID)186+ "container_id", shortContainerID)
185 return nil187 return nil
186 }188 }
187 // Check for error messages in the response body189 // Check for error messages in the response body
M internal/cli/cmd/push.go +12 -5
@@ -4,6 +4,7 @@ import (
44 "encoding/json"
55 "fmt"
66 "os"
7+ "strings"
78
89 "github.com/bnema/gordon/internal/cli"
910 "github.com/bnema/gordon/internal/cli/handler"
@@ -73,22 +74,28 @@ func pushImage(a *cli.App, imageName string) error {
7374
7475 resp, err := handler.SendHTTPRequest(a, &reqPayload, "POST", "/push")
7576 if err != nil {
76- return fmt.Errorf("error sending HTTP request: %w", err)
77+ log.Error("Error sending HTTP request", "error", err)
78+ return err
7779 }
7880
7981 var pushResponse common.PushResponse
8082 if err := json.Unmarshal(resp.Body, &pushResponse); err != nil {
81- return fmt.Errorf("error parsing response: %w", err)
83+ log.Error("Error parsing response", "error", err)
84+ return err
8285 }
8386
8487 if !pushResponse.Success {
85- return fmt.Errorf("push failed: %s", pushResponse.Message)
88+ log.Error("Push failed", "resp", pushResponse.Message)
89+ return fmt.Errorf(pushResponse.Message)
8690 }
8791
88- log.Info("Image pushed successfully", "image", imageName)
92+ //Remove the double quotes from the message
93+ message := strings.Trim(pushResponse.Message, "\"")
94+
95+ log.Info(message)
8996
9097 if pushResponse.CreateContainerURL != "" {
91- log.Info("Container creation URL:", "url", pushResponse.CreateContainerURL)
98+ log.Info("Container creation available", "url", pushResponse.CreateContainerURL)
9299 }
93100
94101 return nil
@@ -4,6 +4,7 @@ import (
4 "encoding/json"4 "encoding/json"
5 "fmt"5 "fmt"
6 "os"6 "os"
7+ "strings"
7 8
8 "github.com/bnema/gordon/internal/cli"9 "github.com/bnema/gordon/internal/cli"
9 "github.com/bnema/gordon/internal/cli/handler"10 "github.com/bnema/gordon/internal/cli/handler"
@@ -73,22 +74,28 @@ func pushImage(a *cli.App, imageName string) error {
73 74
74 resp, err := handler.SendHTTPRequest(a, &reqPayload, "POST", "/push")75 resp, err := handler.SendHTTPRequest(a, &reqPayload, "POST", "/push")
75 if err != nil {76 if err != nil {
76- return fmt.Errorf("error sending HTTP request: %w", err)77+ log.Error("Error sending HTTP request", "error", err)
78+ return err
77 }79 }
78 80
79 var pushResponse common.PushResponse81 var pushResponse common.PushResponse
80 if err := json.Unmarshal(resp.Body, &pushResponse); err != nil {82 if err := json.Unmarshal(resp.Body, &pushResponse); err != nil {
81- return fmt.Errorf("error parsing response: %w", err)83+ log.Error("Error parsing response", "error", err)
84+ return err
82 }85 }
83 86
84 if !pushResponse.Success {87 if !pushResponse.Success {
85- return fmt.Errorf("push failed: %s", pushResponse.Message)88+ log.Error("Push failed", "resp", pushResponse.Message)
89+ return fmt.Errorf(pushResponse.Message)
86 }90 }
87 91
88- log.Info("Image pushed successfully", "image", imageName)92+ //Remove the double quotes from the message
93+ message := strings.Trim(pushResponse.Message, "\"")
94+
95+ log.Info(message)
89 96
90 if pushResponse.CreateContainerURL != "" {97 if pushResponse.CreateContainerURL != "" {
91- log.Info("Container creation URL:", "url", pushResponse.CreateContainerURL)98+ log.Info("Container creation available", "url", pushResponse.CreateContainerURL)
92 }99 }
93 100
94 return nil101 return nil
R internal/cli/handler/fieldcheck.go → internal/cli/handler/field_check.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/cli/handler/pingrequest.go → internal/cli/handler/ping_request.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/cli/handler/regexcheck.go → internal/cli/handler/regex_check.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/cli/handler/startserver.go → internal/cli/handler/start_server.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/cli/newclient.go → internal/cli/new_client.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/common/initconfig.go → internal/common/init_config.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/common/initdockerclient.go → internal/common/init_dockerclient.go +0 -0 renamed, 100% similar

renamed, 100% similar

M internal/common/payload.go +63 -1
@@ -3,19 +3,21 @@ package common
33 import (
44 "encoding/json"
55 "fmt"
6-
76 "io"
87 )
98
9+// RequestPayload represents the structure of incoming requests
1010 type RequestPayload struct {
1111 Type string `json:"type"`
1212 Payload Payload `json:"payload"`
1313 }
1414
15+// Payload is an interface for different types of payloads
1516 type Payload interface {
1617 GetType() string
1718 }
1819
20+// DeployResponse represents the response structure for deployment requests
1921 type DeployResponse struct {
2022 Success bool `json:"success"`
2123 Message string `json:"message"`
@@ -23,22 +25,26 @@ type DeployResponse struct {
2325 ContainerID string `json:"container_id,omitempty"`
2426 }
2527
28+// PushResponse represents the response structure for push requests
2629 type PushResponse struct {
2730 Success bool `json:"success"`
2831 Message string `json:"message"`
2932 CreateContainerURL string `json:"create_container_url,omitempty"`
3033 }
3134
35+// DeploymentError represents an error that occurred during deployment
3236 type DeploymentError struct {
3337 StatusCode int `json:"status"`
3438 Message string `json:"message"`
3539 RawResponse string `json:"raw_response"`
3640 }
3741
42+// Error implements the error interface for DeploymentError
3843 func (e *DeploymentError) Error() string {
3944 return fmt.Sprintf("Deployment failed (status %d): %s", e.StatusCode, e.Message)
4045 }
4146
47+// DeployPayload represents the payload for deployment requests
4248 type DeployPayload struct {
4349 Port string `json:"port"`
4450 TargetDomain string `json:"targetdomain"`
@@ -47,12 +53,14 @@ type DeployPayload struct {
4753 Data io.ReadCloser
4854 }
4955
56+// PushPayload represents the payload for push requests
5057 type PushPayload struct {
5158 ImageName string `json:"imagename"`
5259 ImageID string `json:"imageid"`
5360 Data io.ReadCloser
5461 }
5562
63+// UnmarshalJSON custom unmarshaler for RequestPayload
5664 func (p *RequestPayload) UnmarshalJSON(data []byte) error {
5765 var raw map[string]json.RawMessage
5866 err := json.Unmarshal(data, &raw)
@@ -64,6 +72,7 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
6472 return err
6573 }
6674
75+ // Unmarshal the payload based on the type
6776 switch p.Type {
6877 case "ping":
6978 var payload PingPayload
@@ -83,6 +92,24 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
8392 return err
8493 }
8594 p.Payload = payload
95+ case "stop":
96+ var payload StopPayload
97+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
98+ return err
99+ }
100+ p.Payload = payload
101+ case "start":
102+ var payload StartPayload
103+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
104+ return err
105+ }
106+ p.Payload = payload
107+ case "remove":
108+ var payload RemovePayload
109+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
110+ return err
111+ }
112+ p.Payload = payload
86113 default:
87114 return fmt.Errorf("invalid type: %s", p.Type)
88115 }
@@ -90,22 +117,27 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
90117 return nil
91118 }
92119
120+// PingPayload represents the payload for ping requests
93121 type PingPayload struct {
94122 Message string `json:"message"`
95123 }
96124
125+// GetType returns the type of the PingPayload
97126 func (p PingPayload) GetType() string {
98127 return "ping"
99128 }
100129
130+// GetType returns the type of the DeployPayload
101131 func (p DeployPayload) GetType() string {
102132 return "deploy"
103133 }
104134
135+// GetType returns the type of the PushPayload
105136 func (p PushPayload) GetType() string {
106137 return "push"
107138 }
108139
140+// NewPingPayload creates a new PingPayload from a map of data
109141 func NewPingPayload(data map[string]interface{}) (PingPayload, error) {
110142 message, ok := data["message"].(string)
111143 if !ok {
@@ -113,3 +145,33 @@ func NewPingPayload(data map[string]interface{}) (PingPayload, error) {
113145 }
114146 return PingPayload{Message: message}, nil
115147 }
148+
149+// StopPayload represents the payload for stop requests
150+type StopPayload struct {
151+ ContainerID string `json:"container_id"`
152+}
153+
154+// GetType returns the type of the StopPayload
155+func (p StopPayload) GetType() string {
156+ return "stop"
157+}
158+
159+// StartPayload represents the payload for start requests
160+type StartPayload struct {
161+ ContainerID string `json:"container_id"`
162+}
163+
164+// GetType returns the type of the StartPayload
165+func (p StartPayload) GetType() string {
166+ return "start"
167+}
168+
169+// RemovePayload represents the payload for remove requests
170+type RemovePayload struct {
171+ ContainerID string `json:"container_id"`
172+}
173+
174+// GetType returns the type of the RemovePayload
175+func (p RemovePayload) GetType() string {
176+ return "remove"
177+}
@@ -3,19 +3,21 @@ package common
3 import (3 import (
4 "encoding/json"4 "encoding/json"
5 "fmt"5 "fmt"
6-
7 "io"6 "io"
8 )7 )
9 8
9+// RequestPayload represents the structure of incoming requests
10 type RequestPayload struct {10 type RequestPayload struct {
11 Type string `json:"type"`11 Type string `json:"type"`
12 Payload Payload `json:"payload"`12 Payload Payload `json:"payload"`
13 }13 }
14 14
15+// Payload is an interface for different types of payloads
15 type Payload interface {16 type Payload interface {
16 GetType() string17 GetType() string
17 }18 }
18 19
20+// DeployResponse represents the response structure for deployment requests
19 type DeployResponse struct {21 type DeployResponse struct {
20 Success bool `json:"success"`22 Success bool `json:"success"`
21 Message string `json:"message"`23 Message string `json:"message"`
@@ -23,22 +25,26 @@ type DeployResponse struct {
23 ContainerID string `json:"container_id,omitempty"`25 ContainerID string `json:"container_id,omitempty"`
24 }26 }
25 27
28+// PushResponse represents the response structure for push requests
26 type PushResponse struct {29 type PushResponse struct {
27 Success bool `json:"success"`30 Success bool `json:"success"`
28 Message string `json:"message"`31 Message string `json:"message"`
29 CreateContainerURL string `json:"create_container_url,omitempty"`32 CreateContainerURL string `json:"create_container_url,omitempty"`
30 }33 }
31 34
35+// DeploymentError represents an error that occurred during deployment
32 type DeploymentError struct {36 type DeploymentError struct {
33 StatusCode int `json:"status"`37 StatusCode int `json:"status"`
34 Message string `json:"message"`38 Message string `json:"message"`
35 RawResponse string `json:"raw_response"`39 RawResponse string `json:"raw_response"`
36 }40 }
37 41
42+// Error implements the error interface for DeploymentError
38 func (e *DeploymentError) Error() string {43 func (e *DeploymentError) Error() string {
39 return fmt.Sprintf("Deployment failed (status %d): %s", e.StatusCode, e.Message)44 return fmt.Sprintf("Deployment failed (status %d): %s", e.StatusCode, e.Message)
40 }45 }
41 46
47+// DeployPayload represents the payload for deployment requests
42 type DeployPayload struct {48 type DeployPayload struct {
43 Port string `json:"port"`49 Port string `json:"port"`
44 TargetDomain string `json:"targetdomain"`50 TargetDomain string `json:"targetdomain"`
@@ -47,12 +53,14 @@ type DeployPayload struct {
47 Data io.ReadCloser53 Data io.ReadCloser
48 }54 }
49 55
56+// PushPayload represents the payload for push requests
50 type PushPayload struct {57 type PushPayload struct {
51 ImageName string `json:"imagename"`58 ImageName string `json:"imagename"`
52 ImageID string `json:"imageid"`59 ImageID string `json:"imageid"`
53 Data io.ReadCloser60 Data io.ReadCloser
54 }61 }
55 62
63+// UnmarshalJSON custom unmarshaler for RequestPayload
56 func (p *RequestPayload) UnmarshalJSON(data []byte) error {64 func (p *RequestPayload) UnmarshalJSON(data []byte) error {
57 var raw map[string]json.RawMessage65 var raw map[string]json.RawMessage
58 err := json.Unmarshal(data, &raw)66 err := json.Unmarshal(data, &raw)
@@ -64,6 +72,7 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
64 return err72 return err
65 }73 }
66 74
75+ // Unmarshal the payload based on the type
67 switch p.Type {76 switch p.Type {
68 case "ping":77 case "ping":
69 var payload PingPayload78 var payload PingPayload
@@ -83,6 +92,24 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
83 return err92 return err
84 }93 }
85 p.Payload = payload94 p.Payload = payload
95+ case "stop":
96+ var payload StopPayload
97+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
98+ return err
99+ }
100+ p.Payload = payload
101+ case "start":
102+ var payload StartPayload
103+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
104+ return err
105+ }
106+ p.Payload = payload
107+ case "remove":
108+ var payload RemovePayload
109+ if err := json.Unmarshal(raw["payload"], &payload); err != nil {
110+ return err
111+ }
112+ p.Payload = payload
86 default:113 default:
87 return fmt.Errorf("invalid type: %s", p.Type)114 return fmt.Errorf("invalid type: %s", p.Type)
88 }115 }
@@ -90,22 +117,27 @@ func (p *RequestPayload) UnmarshalJSON(data []byte) error {
90 return nil117 return nil
91 }118 }
92 119
120+// PingPayload represents the payload for ping requests
93 type PingPayload struct {121 type PingPayload struct {
94 Message string `json:"message"`122 Message string `json:"message"`
95 }123 }
96 124
125+// GetType returns the type of the PingPayload
97 func (p PingPayload) GetType() string {126 func (p PingPayload) GetType() string {
98 return "ping"127 return "ping"
99 }128 }
100 129
130+// GetType returns the type of the DeployPayload
101 func (p DeployPayload) GetType() string {131 func (p DeployPayload) GetType() string {
102 return "deploy"132 return "deploy"
103 }133 }
104 134
135+// GetType returns the type of the PushPayload
105 func (p PushPayload) GetType() string {136 func (p PushPayload) GetType() string {
106 return "push"137 return "push"
107 }138 }
108 139
140+// NewPingPayload creates a new PingPayload from a map of data
109 func NewPingPayload(data map[string]interface{}) (PingPayload, error) {141 func NewPingPayload(data map[string]interface{}) (PingPayload, error) {
110 message, ok := data["message"].(string)142 message, ok := data["message"].(string)
111 if !ok {143 if !ok {
@@ -113,3 +145,33 @@ func NewPingPayload(data map[string]interface{}) (PingPayload, error) {
113 }145 }
114 return PingPayload{Message: message}, nil146 return PingPayload{Message: message}, nil
115 }147 }
148+
149+// StopPayload represents the payload for stop requests
150+type StopPayload struct {
151+ ContainerID string `json:"container_id"`
152+}
153+
154+// GetType returns the type of the StopPayload
155+func (p StopPayload) GetType() string {
156+ return "stop"
157+}
158+
159+// StartPayload represents the payload for start requests
160+type StartPayload struct {
161+ ContainerID string `json:"container_id"`
162+}
163+
164+// GetType returns the type of the StartPayload
165+func (p StartPayload) GetType() string {
166+ return "start"
167+}
168+
169+// RemovePayload represents the payload for remove requests
170+type RemovePayload struct {
171+ ContainerID string `json:"container_id"`
172+}
173+
174+// GetType returns the type of the RemovePayload
175+func (p RemovePayload) GetType() string {
176+ return "remove"
177+}
R internal/db/dbstruct.go → internal/db/db_struct.go +0 -0 renamed, 100% similar

renamed, 100% similar

D internal/httpserve/handler/htmx.go +0 -1
@@ -1,1 +0,0 @@
1-package handler
@@ -1,1 +0,0 @@
1-package handler
R internal/httpserve/handler/admin-view.go → internal/httpserve/handlers/admin_view.go +1 -1 renamed, 99% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
R internal/httpserve/handler/cli-endpoints.go → internal/httpserve/handlers/cli_endpoints.go +16 -16 renamed, 91% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "encoding/json"
@@ -89,7 +89,7 @@ func PostPush(c echo.Context, a *server.App) error {
8989
9090 return sendJSONResponse(c, http.StatusOK, common.PushResponse{
9191 Success: true,
92- Message: "Image pushed successfully",
92+ Message: "Image pushed and imported successfully",
9393 CreateContainerURL: createContainerURL,
9494 })
9595 }
@@ -101,7 +101,7 @@ func validateAndPreparePayload(c echo.Context) (*common.PushPayload, error) {
101101 }
102102
103103 if payload.ImageName == "" {
104- return nil, errors.New("Invalid image name")
104+ return nil, errors.New("invalid image name")
105105 }
106106
107107 return payload, nil
@@ -116,22 +116,22 @@ func saveAndImportImage(c echo.Context, a *server.App, payload *common.PushPaylo
116116
117117 imagePath, err := store.SaveImageToStorage(&a.Config, imageFileName, imageReader)
118118 if err != nil {
119- return "", fmt.Errorf("Failed to save image: %v", err)
119+ return "", fmt.Errorf("failed to save image: %v", err)
120120 }
121121
122122 imageID, err := docker.ImportImageToEngine(imagePath)
123123 if err != nil {
124124 store.RemoveFromStorage(imagePath)
125- return "", fmt.Errorf("Failed to import image: %v", err)
125+ return "", fmt.Errorf("failed to import image: %v", err)
126126 }
127127
128128 if imageID == "" {
129- return "", errors.New("Imported image ID is empty")
129+ return "", errors.New("imported image ID is empty")
130130 }
131131
132132 err = store.RemoveFromStorage(imagePath)
133133 if err != nil {
134- return "", fmt.Errorf("Failed to remove temporary image file: %v", err)
134+ return "", fmt.Errorf("failed to remove temporary image file: %v", err)
135135 }
136136
137137 payload.ImageID = imageID
@@ -207,7 +207,7 @@ func PostDeploy(c echo.Context, a *server.App) error {
207207
208208 return sendJSONResponse(c, http.StatusConflict, DeployResponse{
209209 Success: false,
210- Message: fmt.Sprintf("A container for this deploy already exists."),
210+ Message: "A container for this deploy already exists.",
211211 ContainerID: extractedID,
212212 })
213213 }
@@ -253,7 +253,7 @@ func validateAndPrepareDeployPayload(c echo.Context) (*common.DeployPayload, err
253253 }
254254
255255 if payload.ImageName == "" {
256- return nil, errors.New("Invalid image name")
256+ return nil, errors.New("invalid image name")
257257 }
258258
259259 payload.Port = normalizePort(payload.Port)
@@ -287,22 +287,22 @@ func saveAndImportDeployImage(c echo.Context, a *server.App, payload *common.Dep
287287
288288 imagePath, err := store.SaveImageToStorage(&a.Config, imageFileName, imageReader)
289289 if err != nil {
290- return "", fmt.Errorf("Failed to save image: %v", err)
290+ return "", fmt.Errorf("failed to save image: %v", err)
291291 }
292292
293293 imageID, err := docker.ImportImageToEngine(imagePath)
294294 if err != nil {
295295 store.RemoveFromStorage(imagePath)
296- return "", fmt.Errorf("Failed to import image: %v", err)
296+ return "", fmt.Errorf("failed to import image: %v", err)
297297 }
298298
299299 if imageID == "" {
300- return "", errors.New("Imported image ID is empty")
300+ return "", errors.New("imported image ID is empty")
301301 }
302302
303303 err = store.RemoveFromStorage(imagePath)
304304 if err != nil {
305- return "", fmt.Errorf("Failed to remove temporary image file: %v", err)
305+ return "", fmt.Errorf("failed to remove temporary image file: %v", err)
306306 }
307307
308308 payload.ImageID = imageID
@@ -313,18 +313,18 @@ func saveAndImportDeployImage(c echo.Context, a *server.App, payload *common.Dep
313313 func createAndStartContainer(a *server.App, payload *common.DeployPayload) (string, error) {
314314 params, err := cmdparams.FromPayloadStructToCmdParams(payload, a, payload.ImageID)
315315 if err != nil {
316- return "", fmt.Errorf("Failed to create command parameters: %v", err)
316+ return "", fmt.Errorf("failed to create command parameters: %v", err)
317317 }
318318
319319 containerID, err := docker.CreateContainer(params)
320320 if err != nil {
321- return "", fmt.Errorf("Failed to create container: %v", err)
321+ return "", fmt.Errorf("failed to create container: %v", err)
322322 }
323323
324324 err = docker.StartContainer(containerID)
325325 if err != nil {
326326 docker.RemoveContainer(containerID)
327- return "", fmt.Errorf("Failed to start container: %v", err)
327+ return "", fmt.Errorf("failed to start container: %v", err)
328328 }
329329
330330 return containerID, nil
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "encoding/json"4 "encoding/json"
@@ -89,7 +89,7 @@ func PostPush(c echo.Context, a *server.App) error {
89 89
90 return sendJSONResponse(c, http.StatusOK, common.PushResponse{90 return sendJSONResponse(c, http.StatusOK, common.PushResponse{
91 Success: true,91 Success: true,
92- Message: "Image pushed successfully",92+ Message: "Image pushed and imported successfully",
93 CreateContainerURL: createContainerURL,93 CreateContainerURL: createContainerURL,
94 })94 })
95 }95 }
@@ -101,7 +101,7 @@ func validateAndPreparePayload(c echo.Context) (*common.PushPayload, error) {
101 }101 }
102 102
103 if payload.ImageName == "" {103 if payload.ImageName == "" {
104- return nil, errors.New("Invalid image name")104+ return nil, errors.New("invalid image name")
105 }105 }
106 106
107 return payload, nil107 return payload, nil
@@ -116,22 +116,22 @@ func saveAndImportImage(c echo.Context, a *server.App, payload *common.PushPaylo
116 116
117 imagePath, err := store.SaveImageToStorage(&a.Config, imageFileName, imageReader)117 imagePath, err := store.SaveImageToStorage(&a.Config, imageFileName, imageReader)
118 if err != nil {118 if err != nil {
119- return "", fmt.Errorf("Failed to save image: %v", err)119+ return "", fmt.Errorf("failed to save image: %v", err)
120 }120 }
121 121
122 imageID, err := docker.ImportImageToEngine(imagePath)122 imageID, err := docker.ImportImageToEngine(imagePath)
123 if err != nil {123 if err != nil {
124 store.RemoveFromStorage(imagePath)124 store.RemoveFromStorage(imagePath)
125- return "", fmt.Errorf("Failed to import image: %v", err)125+ return "", fmt.Errorf("failed to import image: %v", err)
126 }126 }
127 127
128 if imageID == "" {128 if imageID == "" {
129- return "", errors.New("Imported image ID is empty")129+ return "", errors.New("imported image ID is empty")
130 }130 }
131 131
132 err = store.RemoveFromStorage(imagePath)132 err = store.RemoveFromStorage(imagePath)
133 if err != nil {133 if err != nil {
134- return "", fmt.Errorf("Failed to remove temporary image file: %v", err)134+ return "", fmt.Errorf("failed to remove temporary image file: %v", err)
135 }135 }
136 136
137 payload.ImageID = imageID137 payload.ImageID = imageID
@@ -207,7 +207,7 @@ func PostDeploy(c echo.Context, a *server.App) error {
207 207
208 return sendJSONResponse(c, http.StatusConflict, DeployResponse{208 return sendJSONResponse(c, http.StatusConflict, DeployResponse{
209 Success: false,209 Success: false,
210- Message: fmt.Sprintf("A container for this deploy already exists."),210+ Message: "A container for this deploy already exists.",
211 ContainerID: extractedID,211 ContainerID: extractedID,
212 })212 })
213 }213 }
@@ -253,7 +253,7 @@ func validateAndPrepareDeployPayload(c echo.Context) (*common.DeployPayload, err
253 }253 }
254 254
255 if payload.ImageName == "" {255 if payload.ImageName == "" {
256- return nil, errors.New("Invalid image name")256+ return nil, errors.New("invalid image name")
257 }257 }
258 258
259 payload.Port = normalizePort(payload.Port)259 payload.Port = normalizePort(payload.Port)
@@ -287,22 +287,22 @@ func saveAndImportDeployImage(c echo.Context, a *server.App, payload *common.Dep
287 287
288 imagePath, err := store.SaveImageToStorage(&a.Config, imageFileName, imageReader)288 imagePath, err := store.SaveImageToStorage(&a.Config, imageFileName, imageReader)
289 if err != nil {289 if err != nil {
290- return "", fmt.Errorf("Failed to save image: %v", err)290+ return "", fmt.Errorf("failed to save image: %v", err)
291 }291 }
292 292
293 imageID, err := docker.ImportImageToEngine(imagePath)293 imageID, err := docker.ImportImageToEngine(imagePath)
294 if err != nil {294 if err != nil {
295 store.RemoveFromStorage(imagePath)295 store.RemoveFromStorage(imagePath)
296- return "", fmt.Errorf("Failed to import image: %v", err)296+ return "", fmt.Errorf("failed to import image: %v", err)
297 }297 }
298 298
299 if imageID == "" {299 if imageID == "" {
300- return "", errors.New("Imported image ID is empty")300+ return "", errors.New("imported image ID is empty")
301 }301 }
302 302
303 err = store.RemoveFromStorage(imagePath)303 err = store.RemoveFromStorage(imagePath)
304 if err != nil {304 if err != nil {
305- return "", fmt.Errorf("Failed to remove temporary image file: %v", err)305+ return "", fmt.Errorf("failed to remove temporary image file: %v", err)
306 }306 }
307 307
308 payload.ImageID = imageID308 payload.ImageID = imageID
@@ -313,18 +313,18 @@ func saveAndImportDeployImage(c echo.Context, a *server.App, payload *common.Dep
313 func createAndStartContainer(a *server.App, payload *common.DeployPayload) (string, error) {313 func createAndStartContainer(a *server.App, payload *common.DeployPayload) (string, error) {
314 params, err := cmdparams.FromPayloadStructToCmdParams(payload, a, payload.ImageID)314 params, err := cmdparams.FromPayloadStructToCmdParams(payload, a, payload.ImageID)
315 if err != nil {315 if err != nil {
316- return "", fmt.Errorf("Failed to create command parameters: %v", err)316+ return "", fmt.Errorf("failed to create command parameters: %v", err)
317 }317 }
318 318
319 containerID, err := docker.CreateContainer(params)319 containerID, err := docker.CreateContainer(params)
320 if err != nil {320 if err != nil {
321- return "", fmt.Errorf("Failed to create container: %v", err)321+ return "", fmt.Errorf("failed to create container: %v", err)
322 }322 }
323 323
324 err = docker.StartContainer(containerID)324 err = docker.StartContainer(containerID)
325 if err != nil {325 if err != nil {
326 docker.RemoveContainer(containerID)326 docker.RemoveContainer(containerID)
327- return "", fmt.Errorf("Failed to start container: %v", err)327+ return "", fmt.Errorf("failed to start container: %v", err)
328 }328 }
329 329
330 return containerID, nil330 return containerID, nil
R internal/httpserve/handler/createcontainer.go → internal/httpserve/handlers/container_crud.go +2 -1 renamed, 98% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -57,6 +57,7 @@ func CreateContainerGET(c echo.Context, a *server.App) error {
5757 "ImageName": imageName,
5858 }
5959
60+ // Render the create container page
6061 rendererData, err := render.GetHTMLRenderer("html/fragments", "createcontainer.gohtml", a.TemplateFS, a)
6162
6263 if err != nil {
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
@@ -57,6 +57,7 @@ func CreateContainerGET(c echo.Context, a *server.App) error {
57 "ImageName": imageName,57 "ImageName": imageName,
58 }58 }
59 59
60+ // Render the create container page
60 rendererData, err := render.GetHTMLRenderer("html/fragments", "createcontainer.gohtml", a.TemplateFS, a)61 rendererData, err := render.GetHTMLRenderer("html/fragments", "createcontainer.gohtml", a.TemplateFS, a)
61 62
62 if err != nil {63 if err != nil {
R internal/httpserve/handler/containers.go → internal/httpserve/handlers/container_management.go +1 -1 renamed, 99% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
R internal/httpserve/handler/editcontainer.go → internal/httpserve/handlers/container_transactions.go +1 -1 renamed, 99% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
R internal/httpserve/handler/oauth.go → internal/httpserve/handlers/login.go +16 -14 renamed, 92% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "encoding/base64"
@@ -13,6 +13,7 @@ import (
1313 "github.com/bnema/gordon/internal/db/queries"
1414 "github.com/bnema/gordon/internal/server"
1515 "github.com/bnema/gordon/internal/templating/render"
16+ "github.com/charmbracelet/log"
1617 "github.com/gorilla/sessions"
1718 _ "github.com/joho/godotenv/autoload"
1819 "github.com/labstack/echo-contrib/session"
@@ -59,58 +60,59 @@ func RenderLoginPage(c echo.Context, a *server.App) error {
5960 }
6061
6162 // StartOAuthGithub starts the Github OAuth flow.
63+
6264 func StartOAuthGithub(c echo.Context, a *server.App) error {
63- fmt.Println("Attempting to get an existing session.")
65+ log.Info("Attempting to get an existing session.")
6466 sess, err := getSession(c)
6567 if err != nil || sess == nil || sess.Values == nil {
66- fmt.Println("Session retrieval failed, initiating new GitHub OAuth flow.")
68+ log.Info("Session retrieval failed, initiating new GitHub OAuth flow.")
6769 return initiateGithubOAuthFlow(c, a)
6870 }
6971
70- fmt.Println("Attempting to assert session values.")
72+ log.Info("Attempting to assert session values.")
7173 sessionID, ok1 := sess.Values["sessionID"].(string)
7274 accountID, ok2 := sess.Values["accountID"].(string)
7375 authenticated, ok3 := sess.Values["authenticated"].(bool)
7476
7577 if !ok1 || !ok2 || !ok3 || !authenticated {
76- fmt.Println("Session assertion failed, or user not authenticated. Initiating new OAuth flow.")
78+ log.Info("Session assertion failed, or user not authenticated. Initiating new OAuth flow.")
7779 return initiateGithubOAuthFlow(c, a)
7880 }
7981
80- fmt.Println("Checking if session exists in DB.")
82+ log.Info("Checking if session exists in DB.")
8183 sessionExists, err := queries.CheckDBSessionExists(a, sessionID)
8284 if err != nil {
83- fmt.Printf("Error checking if session exists: %v\n", err)
85+ log.Info("Error checking if session exists", "error", err)
8486 return fmt.Errorf("could not check if session exists: %w", err)
8587 }
8688
8789 if !sessionExists {
88- fmt.Println("Session does not exist in DB, initiating new OAuth flow.")
90+ log.Info("Session does not exist in DB, initiating new OAuth flow.")
8991 return initiateGithubOAuthFlow(c, a)
9092 }
9193
92- fmt.Println("Getting the expiration time of the session.")
94+ log.Info("Getting the expiration time of the session.")
9395 currentTime := time.Now()
9496 sessionExpiration, err := queries.GetSessionExpiration(a, accountID, sessionID, currentTime)
9597 if err != nil {
96- fmt.Printf("Error getting session expiration: %v\n", err)
98+ log.Info("Error getting session expiration", "error", err)
9799 return fmt.Errorf("could not get session expiration: %w", err)
98100 }
99101
100102 if currentTime.After(sessionExpiration) {
101- fmt.Println("Current time is after session expiration, initiating new OAuth flow.")
103+ log.Info("Current time is after session expiration, initiating new OAuth flow.")
102104 return initiateGithubOAuthFlow(c, a)
103105 }
104106
105- fmt.Println("Extending session expiration time by 30 minutes.")
107+ log.Info("Extending session expiration time by 30 minutes.")
106108 newExpirationTime := currentTime.Add(30 * time.Minute)
107109 err = queries.ExtendSessionExpiration(a, accountID, sessionID, newExpirationTime)
108110 if err != nil {
109- fmt.Printf("Error extending session expiration: %v\n", err)
111+ log.Info("Error extending session expiration", "error", err)
110112 return fmt.Errorf("could not extend session expiration: %w", err)
111113 }
112114
113- fmt.Println("Session is valid and extended. Redirecting to admin panel.")
115+ log.Info("Session is valid and extended. Redirecting to admin panel.")
114116 return c.Redirect(http.StatusFound, a.Config.Admin.Path)
115117 }
116118
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "encoding/base64"4 "encoding/base64"
@@ -13,6 +13,7 @@ import (
13 "github.com/bnema/gordon/internal/db/queries"13 "github.com/bnema/gordon/internal/db/queries"
14 "github.com/bnema/gordon/internal/server"14 "github.com/bnema/gordon/internal/server"
15 "github.com/bnema/gordon/internal/templating/render"15 "github.com/bnema/gordon/internal/templating/render"
16+ "github.com/charmbracelet/log"
16 "github.com/gorilla/sessions"17 "github.com/gorilla/sessions"
17 _ "github.com/joho/godotenv/autoload"18 _ "github.com/joho/godotenv/autoload"
18 "github.com/labstack/echo-contrib/session"19 "github.com/labstack/echo-contrib/session"
@@ -59,58 +60,59 @@ func RenderLoginPage(c echo.Context, a *server.App) error {
59 }60 }
60 61
61 // StartOAuthGithub starts the Github OAuth flow.62 // StartOAuthGithub starts the Github OAuth flow.
63+
62 func StartOAuthGithub(c echo.Context, a *server.App) error {64 func StartOAuthGithub(c echo.Context, a *server.App) error {
63- fmt.Println("Attempting to get an existing session.")65+ log.Info("Attempting to get an existing session.")
64 sess, err := getSession(c)66 sess, err := getSession(c)
65 if err != nil || sess == nil || sess.Values == nil {67 if err != nil || sess == nil || sess.Values == nil {
66- fmt.Println("Session retrieval failed, initiating new GitHub OAuth flow.")68+ log.Info("Session retrieval failed, initiating new GitHub OAuth flow.")
67 return initiateGithubOAuthFlow(c, a)69 return initiateGithubOAuthFlow(c, a)
68 }70 }
69 71
70- fmt.Println("Attempting to assert session values.")72+ log.Info("Attempting to assert session values.")
71 sessionID, ok1 := sess.Values["sessionID"].(string)73 sessionID, ok1 := sess.Values["sessionID"].(string)
72 accountID, ok2 := sess.Values["accountID"].(string)74 accountID, ok2 := sess.Values["accountID"].(string)
73 authenticated, ok3 := sess.Values["authenticated"].(bool)75 authenticated, ok3 := sess.Values["authenticated"].(bool)
74 76
75 if !ok1 || !ok2 || !ok3 || !authenticated {77 if !ok1 || !ok2 || !ok3 || !authenticated {
76- fmt.Println("Session assertion failed, or user not authenticated. Initiating new OAuth flow.")78+ log.Info("Session assertion failed, or user not authenticated. Initiating new OAuth flow.")
77 return initiateGithubOAuthFlow(c, a)79 return initiateGithubOAuthFlow(c, a)
78 }80 }
79 81
80- fmt.Println("Checking if session exists in DB.")82+ log.Info("Checking if session exists in DB.")
81 sessionExists, err := queries.CheckDBSessionExists(a, sessionID)83 sessionExists, err := queries.CheckDBSessionExists(a, sessionID)
82 if err != nil {84 if err != nil {
83- fmt.Printf("Error checking if session exists: %v\n", err)85+ log.Info("Error checking if session exists", "error", err)
84 return fmt.Errorf("could not check if session exists: %w", err)86 return fmt.Errorf("could not check if session exists: %w", err)
85 }87 }
86 88
87 if !sessionExists {89 if !sessionExists {
88- fmt.Println("Session does not exist in DB, initiating new OAuth flow.")90+ log.Info("Session does not exist in DB, initiating new OAuth flow.")
89 return initiateGithubOAuthFlow(c, a)91 return initiateGithubOAuthFlow(c, a)
90 }92 }
91 93
92- fmt.Println("Getting the expiration time of the session.")94+ log.Info("Getting the expiration time of the session.")
93 currentTime := time.Now()95 currentTime := time.Now()
94 sessionExpiration, err := queries.GetSessionExpiration(a, accountID, sessionID, currentTime)96 sessionExpiration, err := queries.GetSessionExpiration(a, accountID, sessionID, currentTime)
95 if err != nil {97 if err != nil {
96- fmt.Printf("Error getting session expiration: %v\n", err)98+ log.Info("Error getting session expiration", "error", err)
97 return fmt.Errorf("could not get session expiration: %w", err)99 return fmt.Errorf("could not get session expiration: %w", err)
98 }100 }
99 101
100 if currentTime.After(sessionExpiration) {102 if currentTime.After(sessionExpiration) {
101- fmt.Println("Current time is after session expiration, initiating new OAuth flow.")103+ log.Info("Current time is after session expiration, initiating new OAuth flow.")
102 return initiateGithubOAuthFlow(c, a)104 return initiateGithubOAuthFlow(c, a)
103 }105 }
104 106
105- fmt.Println("Extending session expiration time by 30 minutes.")107+ log.Info("Extending session expiration time by 30 minutes.")
106 newExpirationTime := currentTime.Add(30 * time.Minute)108 newExpirationTime := currentTime.Add(30 * time.Minute)
107 err = queries.ExtendSessionExpiration(a, accountID, sessionID, newExpirationTime)109 err = queries.ExtendSessionExpiration(a, accountID, sessionID, newExpirationTime)
108 if err != nil {110 if err != nil {
109- fmt.Printf("Error extending session expiration: %v\n", err)111+ log.Info("Error extending session expiration", "error", err)
110 return fmt.Errorf("could not extend session expiration: %w", err)112 return fmt.Errorf("could not extend session expiration: %w", err)
111 }113 }
112 114
113- fmt.Println("Session is valid and extended. Redirecting to admin panel.")115+ log.Info("Session is valid and extended. Redirecting to admin panel.")
114 return c.Redirect(http.StatusFound, a.Config.Admin.Path)116 return c.Redirect(http.StatusFound, a.Config.Admin.Path)
115 }117 }
116 118
R internal/httpserve/handler/logout.go → internal/httpserve/handlers/logout.go +4 -3 renamed, 89% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -21,8 +21,9 @@ func Logout(c echo.Context, a *server.App) error {
2121 }
2222
2323 // Invalidate the session in the database
24- if sess != nil {
25- err := queries.InvalidateDBSession(a, sess.Values["sessionID"].(string))
24+ sessionID, ok := sess.Values["sessionID"].(string)
25+ if ok {
26+ err := queries.InvalidateDBSession(a, sessionID)
2627 if err != nil {
2728 return fmt.Errorf("failed to invalidate session: %w", err)
2829 }
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
@@ -21,8 +21,9 @@ func Logout(c echo.Context, a *server.App) error {
21 }21 }
22 22
23 // Invalidate the session in the database23 // Invalidate the session in the database
24- if sess != nil {24+ sessionID, ok := sess.Values["sessionID"].(string)
25- err := queries.InvalidateDBSession(a, sess.Values["sessionID"].(string))25+ if ok {
26+ err := queries.InvalidateDBSession(a, sessionID)
26 if err != nil {27 if err != nil {
27 return fmt.Errorf("failed to invalidate session: %w", err)28 return fmt.Errorf("failed to invalidate session: %w", err)
28 }29 }
R internal/httpserve/handler/senderror.go → internal/httpserve/handlers/send_error.go +1 -1 renamed, 96% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "net/http"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "net/http"4 "net/http"
R internal/httpserve/handler/sessiondb.go → internal/httpserve/handlers/session_db.go +1 -1 renamed, 99% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
R internal/httpserve/handler/static.go → internal/httpserve/handlers/static.go +1 -1 renamed, 98% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "io/fs"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "io/fs"4 "io/fs"
R internal/httpserve/handler/upload-image.go → internal/httpserve/handlers/upload_image.go +1 -1 renamed, 99% similar
@@ -1,4 +1,4 @@
1-package handler
1+package handlers
22
33 import (
44 "fmt"
@@ -1,4 +1,4 @@
1-package handler1+package handlers
2 2
3 import (3 import (
4 "fmt"4 "fmt"
M internal/httpserve/middleware/requirelogin.go +2 -2
@@ -4,7 +4,7 @@ import (
44 "net/http"
55 "time"
66
7- "github.com/bnema/gordon/internal/httpserve/handler"
7+ "github.com/bnema/gordon/internal/httpserve/handlers"
88 "github.com/bnema/gordon/internal/server"
99
1010 "github.com/labstack/echo/v4"
@@ -20,7 +20,7 @@ func RequireLogin(a *server.App) echo.MiddlewareFunc {
2020 const maxRetries = 3
2121 var err error
2222 for i := 0; i < maxRetries; i++ {
23- err = handler.ValidateSessionAndUser(c, a)
23+ err = handlers.ValidateSessionAndUser(c, a)
2424 if err == nil {
2525 return next(c)
2626 }
@@ -4,7 +4,7 @@ import (
4 "net/http"4 "net/http"
5 "time"5 "time"
6 6
7- "github.com/bnema/gordon/internal/httpserve/handler"7+ "github.com/bnema/gordon/internal/httpserve/handlers"
8 "github.com/bnema/gordon/internal/server"8 "github.com/bnema/gordon/internal/server"
9 9
10 "github.com/labstack/echo/v4"10 "github.com/labstack/echo/v4"
@@ -20,7 +20,7 @@ func RequireLogin(a *server.App) echo.MiddlewareFunc {
20 const maxRetries = 320 const maxRetries = 3
21 var err error21 var err error
22 for i := 0; i < maxRetries; i++ {22 for i := 0; i < maxRetries; i++ {
23- err = handler.ValidateSessionAndUser(c, a)23+ err = handlers.ValidateSessionAndUser(c, a)
24 if err == nil {24 if err == nil {
25 return next(c)25 return next(c)
26 }26 }
M internal/httpserve/router.go +25 -25
@@ -1,7 +1,7 @@
11 package httpserve
22
33 import (
4- "github.com/bnema/gordon/internal/httpserve/handler"
4+ "github.com/bnema/gordon/internal/httpserve/handlers"
55 "github.com/bnema/gordon/internal/httpserve/middleware"
66 "github.com/bnema/gordon/internal/server"
77 _ "github.com/joho/godotenv/autoload"
@@ -53,45 +53,45 @@ func bindAPIEndpoints(e *echo.Echo, a *server.App) {
5353
5454 // Device flow endpoints (without RequireToken middleware)
5555 apiGroup.POST("/device/code", func(c echo.Context) error {
56- return handler.DeviceCodeRequest(c, a)
56+ return handlers.DeviceCodeRequest(c, a)
5757 })
5858 apiGroup.POST("/device/token", func(c echo.Context) error {
59- return handler.DeviceTokenRequest(c, a)
59+ return handlers.DeviceTokenRequest(c, a)
6060 })
6161
6262 // Other API endpoints that require a token
6363 protectedApiGroup := apiGroup.Group("", middleware.RequireToken(a))
6464 protectedApiGroup.GET("/ping", func(c echo.Context) error {
65- return handler.GetInfos(c, a)
65+ return handlers.GetInfos(c, a)
6666 })
6767 protectedApiGroup.POST("/deploy", func(c echo.Context) error {
68- return handler.PostDeploy(c, a)
68+ return handlers.PostDeploy(c, a)
6969 })
7070 protectedApiGroup.POST("/push", func(c echo.Context) error {
71- return handler.PostPush(c, a)
71+ return handlers.PostPush(c, a)
7272 })
7373 }
7474
7575 // bindStaticRoute bind static path
7676 func bindStaticRoute(e *echo.Echo, a *server.App, path string) {
7777 e.GET(path, func(c echo.Context) error {
78- return handler.StaticRoute(c, a)
78+ return handlers.StaticRoute(c, a)
7979 }, echomid.Gzip())
8080 }
8181
8282 // bindLoginRoute binds all login routes
8383 func bindLoginRoute(e *echo.Echo, a *server.App, adminPath string) {
8484 e.GET(adminPath+"/login", func(c echo.Context) error {
85- return handler.RenderLoginPage(c, a)
85+ return handlers.RenderLoginPage(c, a)
8686 })
8787 e.GET(adminPath+"/login/oauth/github", func(c echo.Context) error {
88- return handler.StartOAuthGithub(c, a)
88+ return handlers.StartOAuthGithub(c, a)
8989 })
9090 e.GET(adminPath+"/login/oauth/callback", func(c echo.Context) error {
91- return handler.OAuthCallback(c, a)
91+ return handlers.OAuthCallback(c, a)
9292 })
9393 e.GET(adminPath+"/logout", func(c echo.Context) error {
94- return handler.Logout(c, a)
94+ return handlers.Logout(c, a)
9595 })
9696 }
9797
@@ -104,10 +104,10 @@ func bindAdminRoute(e *echo.Echo, a *server.App, adminPath string) {
104104 }, middleware.RequireLogin(a))
105105
106106 adminGroup.GET("/manager", func(c echo.Context) error {
107- return handler.AdminManagerRoute(c, a)
107+ return handlers.AdminManagerRoute(c, a)
108108 }, middleware.RequireLogin(a))
109109 adminGroup.GET("/cc/:ID", func(c echo.Context) error {
110- return handler.CreateContainerFullGET(c, a)
110+ return handlers.CreateContainerFullGET(c, a)
111111 }, middleware.RequireLogin(a))
112112 }
113113
@@ -121,52 +121,52 @@ func bindHTMXEndpoints(e *echo.Echo, a *server.App) {
121121
122122 // List all images component
123123 htmxGroup.GET("/image-manager", func(c echo.Context) error {
124- return handler.ImageManagerComponent(c, a)
124+ return handlers.ImageManagerComponent(c, a)
125125 })
126126 // Delete an image
127127 htmxGroup.DELETE("/image-manager/delete/:ID", func(c echo.Context) error {
128- return handler.ImageManagerDelete(c, a)
128+ return handlers.ImageManagerDelete(c, a)
129129 })
130130
131131 // List all containers
132132 htmxGroup.GET("/container-manager", func(c echo.Context) error {
133- return handler.ContainerManagerComponent(c, a)
133+ return handlers.ContainerManagerComponent(c, a)
134134 })
135135 // Stop a container
136136 htmxGroup.POST("/container-manager/stop/:ID", func(c echo.Context) error {
137- return handler.ContainerManagerStop(c, a)
137+ return handlers.ContainerManagerStop(c, a)
138138 })
139139 // Delete a container
140140 htmxGroup.DELETE("/container-manager/delete/:ID", func(c echo.Context) error {
141- return handler.ContainerManagerDelete(c, a)
141+ return handlers.ContainerManagerDelete(c, a)
142142 })
143143 // Start a container
144144 htmxGroup.POST("/container-manager/start/:ID", func(c echo.Context) error {
145- return handler.ContainerManagerStart(c, a)
145+ return handlers.ContainerManagerStart(c, a)
146146 })
147147 // Edit a container view
148148 htmxGroup.GET("/container-manager/edit/:ID", func(c echo.Context) error {
149- return handler.ContainerManagerEditGET(c, a)
149+ return handlers.ContainerManagerEditGET(c, a)
150150 })
151151 // Edit a container action
152152 htmxGroup.POST("/container-manager/edit/:ID", func(c echo.Context) error {
153- return handler.ContainerManagerEditPOST(c, a)
153+ return handlers.ContainerManagerEditPOST(c, a)
154154 })
155155
156156 // Display upload-image component
157157 htmxGroup.GET("/upload-image", func(c echo.Context) error {
158- return handler.UploadImageGETHandler(c, a)
158+ return handlers.UploadImageGETHandler(c, a)
159159 })
160160 // Upload image
161161 htmxGroup.POST("/upload-image", func(c echo.Context) error {
162- return handler.UploadImagePOSTHandler(c, a)
162+ return handlers.UploadImagePOSTHandler(c, a)
163163 })
164164 // Display create-container component
165165 htmxGroup.GET("/create-container/:ID", func(c echo.Context) error {
166- return handler.CreateContainerGET(c, a)
166+ return handlers.CreateContainerGET(c, a)
167167 })
168168 // Create container
169169 htmxGroup.POST("/create-container/:ID", func(c echo.Context) error {
170- return handler.CreateContainerPOST(c, a)
170+ return handlers.CreateContainerPOST(c, a)
171171 })
172172 }
@@ -1,7 +1,7 @@
1 package httpserve1 package httpserve
2 2
3 import (3 import (
4- "github.com/bnema/gordon/internal/httpserve/handler"4+ "github.com/bnema/gordon/internal/httpserve/handlers"
5 "github.com/bnema/gordon/internal/httpserve/middleware"5 "github.com/bnema/gordon/internal/httpserve/middleware"
6 "github.com/bnema/gordon/internal/server"6 "github.com/bnema/gordon/internal/server"
7 _ "github.com/joho/godotenv/autoload"7 _ "github.com/joho/godotenv/autoload"
@@ -53,45 +53,45 @@ func bindAPIEndpoints(e *echo.Echo, a *server.App) {
53 53
54 // Device flow endpoints (without RequireToken middleware)54 // Device flow endpoints (without RequireToken middleware)
55 apiGroup.POST("/device/code", func(c echo.Context) error {55 apiGroup.POST("/device/code", func(c echo.Context) error {
56- return handler.DeviceCodeRequest(c, a)56+ return handlers.DeviceCodeRequest(c, a)
57 })57 })
58 apiGroup.POST("/device/token", func(c echo.Context) error {58 apiGroup.POST("/device/token", func(c echo.Context) error {
59- return handler.DeviceTokenRequest(c, a)59+ return handlers.DeviceTokenRequest(c, a)
60 })60 })
61 61
62 // Other API endpoints that require a token62 // Other API endpoints that require a token
63 protectedApiGroup := apiGroup.Group("", middleware.RequireToken(a))63 protectedApiGroup := apiGroup.Group("", middleware.RequireToken(a))
64 protectedApiGroup.GET("/ping", func(c echo.Context) error {64 protectedApiGroup.GET("/ping", func(c echo.Context) error {
65- return handler.GetInfos(c, a)65+ return handlers.GetInfos(c, a)
66 })66 })
67 protectedApiGroup.POST("/deploy", func(c echo.Context) error {67 protectedApiGroup.POST("/deploy", func(c echo.Context) error {
68- return handler.PostDeploy(c, a)68+ return handlers.PostDeploy(c, a)
69 })69 })
70 protectedApiGroup.POST("/push", func(c echo.Context) error {70 protectedApiGroup.POST("/push", func(c echo.Context) error {
71- return handler.PostPush(c, a)71+ return handlers.PostPush(c, a)
72 })72 })
73 }73 }
74 74
75 // bindStaticRoute bind static path75 // bindStaticRoute bind static path
76 func bindStaticRoute(e *echo.Echo, a *server.App, path string) {76 func bindStaticRoute(e *echo.Echo, a *server.App, path string) {
77 e.GET(path, func(c echo.Context) error {77 e.GET(path, func(c echo.Context) error {
78- return handler.StaticRoute(c, a)78+ return handlers.StaticRoute(c, a)
79 }, echomid.Gzip())79 }, echomid.Gzip())
80 }80 }
81 81
82 // bindLoginRoute binds all login routes82 // bindLoginRoute binds all login routes
83 func bindLoginRoute(e *echo.Echo, a *server.App, adminPath string) {83 func bindLoginRoute(e *echo.Echo, a *server.App, adminPath string) {
84 e.GET(adminPath+"/login", func(c echo.Context) error {84 e.GET(adminPath+"/login", func(c echo.Context) error {
85- return handler.RenderLoginPage(c, a)85+ return handlers.RenderLoginPage(c, a)
86 })86 })
87 e.GET(adminPath+"/login/oauth/github", func(c echo.Context) error {87 e.GET(adminPath+"/login/oauth/github", func(c echo.Context) error {
88- return handler.StartOAuthGithub(c, a)88+ return handlers.StartOAuthGithub(c, a)
89 })89 })
90 e.GET(adminPath+"/login/oauth/callback", func(c echo.Context) error {90 e.GET(adminPath+"/login/oauth/callback", func(c echo.Context) error {
91- return handler.OAuthCallback(c, a)91+ return handlers.OAuthCallback(c, a)
92 })92 })
93 e.GET(adminPath+"/logout", func(c echo.Context) error {93 e.GET(adminPath+"/logout", func(c echo.Context) error {
94- return handler.Logout(c, a)94+ return handlers.Logout(c, a)
95 })95 })
96 }96 }
97 97
@@ -104,10 +104,10 @@ func bindAdminRoute(e *echo.Echo, a *server.App, adminPath string) {
104 }, middleware.RequireLogin(a))104 }, middleware.RequireLogin(a))
105 105
106 adminGroup.GET("/manager", func(c echo.Context) error {106 adminGroup.GET("/manager", func(c echo.Context) error {
107- return handler.AdminManagerRoute(c, a)107+ return handlers.AdminManagerRoute(c, a)
108 }, middleware.RequireLogin(a))108 }, middleware.RequireLogin(a))
109 adminGroup.GET("/cc/:ID", func(c echo.Context) error {109 adminGroup.GET("/cc/:ID", func(c echo.Context) error {
110- return handler.CreateContainerFullGET(c, a)110+ return handlers.CreateContainerFullGET(c, a)
111 }, middleware.RequireLogin(a))111 }, middleware.RequireLogin(a))
112 }112 }
113 113
@@ -121,52 +121,52 @@ func bindHTMXEndpoints(e *echo.Echo, a *server.App) {
121 121
122 // List all images component122 // List all images component
123 htmxGroup.GET("/image-manager", func(c echo.Context) error {123 htmxGroup.GET("/image-manager", func(c echo.Context) error {
124- return handler.ImageManagerComponent(c, a)124+ return handlers.ImageManagerComponent(c, a)
125 })125 })
126 // Delete an image126 // Delete an image
127 htmxGroup.DELETE("/image-manager/delete/:ID", func(c echo.Context) error {127 htmxGroup.DELETE("/image-manager/delete/:ID", func(c echo.Context) error {
128- return handler.ImageManagerDelete(c, a)128+ return handlers.ImageManagerDelete(c, a)
129 })129 })
130 130
131 // List all containers131 // List all containers
132 htmxGroup.GET("/container-manager", func(c echo.Context) error {132 htmxGroup.GET("/container-manager", func(c echo.Context) error {
133- return handler.ContainerManagerComponent(c, a)133+ return handlers.ContainerManagerComponent(c, a)
134 })134 })
135 // Stop a container135 // Stop a container
136 htmxGroup.POST("/container-manager/stop/:ID", func(c echo.Context) error {136 htmxGroup.POST("/container-manager/stop/:ID", func(c echo.Context) error {
137- return handler.ContainerManagerStop(c, a)137+ return handlers.ContainerManagerStop(c, a)
138 })138 })
139 // Delete a container139 // Delete a container
140 htmxGroup.DELETE("/container-manager/delete/:ID", func(c echo.Context) error {140 htmxGroup.DELETE("/container-manager/delete/:ID", func(c echo.Context) error {
141- return handler.ContainerManagerDelete(c, a)141+ return handlers.ContainerManagerDelete(c, a)
142 })142 })
143 // Start a container143 // Start a container
144 htmxGroup.POST("/container-manager/start/:ID", func(c echo.Context) error {144 htmxGroup.POST("/container-manager/start/:ID", func(c echo.Context) error {
145- return handler.ContainerManagerStart(c, a)145+ return handlers.ContainerManagerStart(c, a)
146 })146 })
147 // Edit a container view147 // Edit a container view
148 htmxGroup.GET("/container-manager/edit/:ID", func(c echo.Context) error {148 htmxGroup.GET("/container-manager/edit/:ID", func(c echo.Context) error {
149- return handler.ContainerManagerEditGET(c, a)149+ return handlers.ContainerManagerEditGET(c, a)
150 })150 })
151 // Edit a container action151 // Edit a container action
152 htmxGroup.POST("/container-manager/edit/:ID", func(c echo.Context) error {152 htmxGroup.POST("/container-manager/edit/:ID", func(c echo.Context) error {
153- return handler.ContainerManagerEditPOST(c, a)153+ return handlers.ContainerManagerEditPOST(c, a)
154 })154 })
155 155
156 // Display upload-image component156 // Display upload-image component
157 htmxGroup.GET("/upload-image", func(c echo.Context) error {157 htmxGroup.GET("/upload-image", func(c echo.Context) error {
158- return handler.UploadImageGETHandler(c, a)158+ return handlers.UploadImageGETHandler(c, a)
159 })159 })
160 // Upload image160 // Upload image
161 htmxGroup.POST("/upload-image", func(c echo.Context) error {161 htmxGroup.POST("/upload-image", func(c echo.Context) error {
162- return handler.UploadImagePOSTHandler(c, a)162+ return handlers.UploadImagePOSTHandler(c, a)
163 })163 })
164 // Display create-container component164 // Display create-container component
165 htmxGroup.GET("/create-container/:ID", func(c echo.Context) error {165 htmxGroup.GET("/create-container/:ID", func(c echo.Context) error {
166- return handler.CreateContainerGET(c, a)166+ return handlers.CreateContainerGET(c, a)
167 })167 })
168 // Create container168 // Create container
169 htmxGroup.POST("/create-container/:ID", func(c echo.Context) error {169 htmxGroup.POST("/create-container/:ID", func(c echo.Context) error {
170- return handler.CreateContainerPOST(c, a)170+ return handlers.CreateContainerPOST(c, a)
171 })171 })
172 }172 }
R internal/server/appserver.go → internal/server/app_server.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/server/newserver.go → internal/server/new_server.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/server/sqliteclose.go → internal/server/sqlite_close.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/server/sqliteinit.go → internal/server/sqlite_init.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/server/tokeninit.go → internal/server/token_init.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/templating/cmdparams/fromcli.go → internal/templating/cmdparams/from_cli.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/templating/cmdparams/frominputs.go → internal/templating/cmdparams/from_inputs.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/templating/cmdparams/fromyaml.go → internal/templating/cmdparams/from_yaml.go +0 -0 renamed, 100% similar

renamed, 100% similar

R internal/templating/load/loadfragment.go → internal/templating/load/fragment.go +0 -0 renamed, 100% similar

renamed, 100% similar

D package-lock.json +0 -1494
@@ -1,1494 +0,0 @@
1-{
2- "name": "gordon",
3- "lockfileVersion": 3,
4- "requires": true,
5- "packages": {
6- "": {
7- "dependencies": {
8- "dotenv": "^16.4.5"
9- },
10- "devDependencies": {
11- "@catppuccin/tailwindcss": "^0.1.6",
12- "prettier": "^3.0.3",
13- "prettier-plugin-tailwindcss": "^0.5.5",
14- "tailwindcss": "^3.3.3"
15- }
16- },
17- "node_modules/@alloc/quick-lru": {
18- "version": "5.2.0",
19- "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
20- "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
21- "dev": true,
22- "engines": {
23- "node": ">=10"
24- },
25- "funding": {
26- "url": "https://github.com/sponsors/sindresorhus"
27- }
28- },
29- "node_modules/@catppuccin/tailwindcss": {
30- "version": "0.1.6",
31- "resolved": "https://registry.npmjs.org/@catppuccin/tailwindcss/-/tailwindcss-0.1.6.tgz",
32- "integrity": "sha512-V+Y0AwZ5SSyvOVAcDl7Ng30xy+m82OKnEJ+9+kcZZ7lRyXuZrAb2GScdq9XR3v+ggt8qiZ/G4TvaC9cJ88AAXA==",
33- "dev": true,
34- "peerDependencies": {
35- "tailwindcss": ">=3.0.0"
36- }
37- },
38- "node_modules/@isaacs/cliui": {
39- "version": "8.0.2",
40- "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
41- "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
42- "dev": true,
43- "dependencies": {
44- "string-width": "^5.1.2",
45- "string-width-cjs": "npm:string-width@^4.2.0",
46- "strip-ansi": "^7.0.1",
47- "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
48- "wrap-ansi": "^8.1.0",
49- "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
50- },
51- "engines": {
52- "node": ">=12"
53- }
54- },
55- "node_modules/@jridgewell/gen-mapping": {
56- "version": "0.3.5",
57- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
58- "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
59- "dev": true,
60- "dependencies": {
61- "@jridgewell/set-array": "^1.2.1",
62- "@jridgewell/sourcemap-codec": "^1.4.10",
63- "@jridgewell/trace-mapping": "^0.3.24"
64- },
65- "engines": {
66- "node": ">=6.0.0"
67- }
68- },
69- "node_modules/@jridgewell/resolve-uri": {
70- "version": "3.1.2",
71- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
72- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
73- "dev": true,
74- "engines": {
75- "node": ">=6.0.0"
76- }
77- },
78- "node_modules/@jridgewell/set-array": {
79- "version": "1.2.1",
80- "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
81- "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
82- "dev": true,
83- "engines": {
84- "node": ">=6.0.0"
85- }
86- },
87- "node_modules/@jridgewell/sourcemap-codec": {
88- "version": "1.4.15",
89- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
90- "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
91- "dev": true
92- },
93- "node_modules/@jridgewell/trace-mapping": {
94- "version": "0.3.25",
95- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
96- "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
97- "dev": true,
98- "dependencies": {
99- "@jridgewell/resolve-uri": "^3.1.0",
100- "@jridgewell/sourcemap-codec": "^1.4.14"
101- }
102- },
103- "node_modules/@nodelib/fs.scandir": {
104- "version": "2.1.5",
105- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
106- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
107- "dev": true,
108- "dependencies": {
109- "@nodelib/fs.stat": "2.0.5",
110- "run-parallel": "^1.1.9"
111- },
112- "engines": {
113- "node": ">= 8"
114- }
115- },
116- "node_modules/@nodelib/fs.stat": {
117- "version": "2.0.5",
118- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
119- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
120- "dev": true,
121- "engines": {
122- "node": ">= 8"
123- }
124- },
125- "node_modules/@nodelib/fs.walk": {
126- "version": "1.2.8",
127- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
128- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
129- "dev": true,
130- "dependencies": {
131- "@nodelib/fs.scandir": "2.1.5",
132- "fastq": "^1.6.0"
133- },
134- "engines": {
135- "node": ">= 8"
136- }
137- },
138- "node_modules/@pkgjs/parseargs": {
139- "version": "0.11.0",
140- "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
141- "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
142- "dev": true,
143- "optional": true,
144- "engines": {
145- "node": ">=14"
146- }
147- },
148- "node_modules/ansi-regex": {
149- "version": "6.0.1",
150- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
151- "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
152- "dev": true,
153- "engines": {
154- "node": ">=12"
155- },
156- "funding": {
157- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
158- }
159- },
160- "node_modules/ansi-styles": {
161- "version": "6.2.1",
162- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
163- "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
164- "dev": true,
165- "engines": {
166- "node": ">=12"
167- },
168- "funding": {
169- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
170- }
171- },
172- "node_modules/any-promise": {
173- "version": "1.3.0",
174- "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
175- "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
176- "dev": true
177- },
178- "node_modules/anymatch": {
179- "version": "3.1.3",
180- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
181- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
182- "dev": true,
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- },
197- "node_modules/balanced-match": {
198- "version": "1.0.2",
199- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
200- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
201- "dev": true
202- },
203- "node_modules/binary-extensions": {
204- "version": "2.3.0",
205- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
206- "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
207- "dev": true,
208- "engines": {
209- "node": ">=8"
210- },
211- "funding": {
212- "url": "https://github.com/sponsors/sindresorhus"
213- }
214- },
215- "node_modules/brace-expansion": {
216- "version": "2.0.1",
217- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
218- "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
219- "dev": true,
220- "dependencies": {
221- "balanced-match": "^1.0.0"
222- }
223- },
224- "node_modules/braces": {
225- "version": "3.0.2",
226- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
227- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
228- "dev": true,
229- "dependencies": {
230- "fill-range": "^7.0.1"
231- },
232- "engines": {
233- "node": ">=8"
234- }
235- },
236- "node_modules/camelcase-css": {
237- "version": "2.0.1",
238- "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
239- "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
240- "dev": true,
241- "engines": {
242- "node": ">= 6"
243- }
244- },
245- "node_modules/chokidar": {
246- "version": "3.6.0",
247- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
248- "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
249- "dev": true,
250- "dependencies": {
251- "anymatch": "~3.1.2",
252- "braces": "~3.0.2",
253- "glob-parent": "~5.1.2",
254- "is-binary-path": "~2.1.0",
255- "is-glob": "~4.0.1",
256- "normalize-path": "~3.0.0",
257- "readdirp": "~3.6.0"
258- },
259- "engines": {
260- "node": ">= 8.10.0"
261- },
262- "funding": {
263- "url": "https://paulmillr.com/funding/"
264- },
265- "optionalDependencies": {
266- "fsevents": "~2.3.2"
267- }
268- },
269- "node_modules/chokidar/node_modules/glob-parent": {
270- "version": "5.1.2",
271- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
272- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
273- "dev": true,
274- "dependencies": {
275- "is-glob": "^4.0.1"
276- },
277- "engines": {
278- "node": ">= 6"
279- }
280- },
281- "node_modules/color-convert": {
282- "version": "2.0.1",
283- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
284- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
285- "dev": true,
286- "dependencies": {
287- "color-name": "~1.1.4"
288- },
289- "engines": {
290- "node": ">=7.0.0"
291- }
292- },
293- "node_modules/color-name": {
294- "version": "1.1.4",
295- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
296- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
297- "dev": true
298- },
299- "node_modules/commander": {
300- "version": "4.1.1",
301- "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
302- "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
303- "dev": true,
304- "engines": {
305- "node": ">= 6"
306- }
307- },
308- "node_modules/cross-spawn": {
309- "version": "7.0.3",
310- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
311- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
312- "dev": true,
313- "dependencies": {
314- "path-key": "^3.1.0",
315- "shebang-command": "^2.0.0",
316- "which": "^2.0.1"
317- },
318- "engines": {
319- "node": ">= 8"
320- }
321- },
322- "node_modules/cssesc": {
323- "version": "3.0.0",
324- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
325- "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
326- "dev": true,
327- "bin": {
328- "cssesc": "bin/cssesc"
329- },
330- "engines": {
331- "node": ">=4"
332- }
333- },
334- "node_modules/didyoumean": {
335- "version": "1.2.2",
336- "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
337- "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
338- "dev": true
339- },
340- "node_modules/dlv": {
341- "version": "1.1.3",
342- "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
343- "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
344- "dev": true
345- },
346- "node_modules/dotenv": {
347- "version": "16.4.5",
348- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
349- "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
350- "engines": {
351- "node": ">=12"
352- },
353- "funding": {
354- "url": "https://dotenvx.com"
355- }
356- },
357- "node_modules/eastasianwidth": {
358- "version": "0.2.0",
359- "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
360- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
361- "dev": true
362- },
363- "node_modules/emoji-regex": {
364- "version": "9.2.2",
365- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
366- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
367- "dev": true
368- },
369- "node_modules/fast-glob": {
370- "version": "3.3.2",
371- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
372- "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
373- "dev": true,
374- "dependencies": {
375- "@nodelib/fs.stat": "^2.0.2",
376- "@nodelib/fs.walk": "^1.2.3",
377- "glob-parent": "^5.1.2",
378- "merge2": "^1.3.0",
379- "micromatch": "^4.0.4"
380- },
381- "engines": {
382- "node": ">=8.6.0"
383- }
384- },
385- "node_modules/fast-glob/node_modules/glob-parent": {
386- "version": "5.1.2",
387- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
388- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
389- "dev": true,
390- "dependencies": {
391- "is-glob": "^4.0.1"
392- },
393- "engines": {
394- "node": ">= 6"
395- }
396- },
397- "node_modules/fastq": {
398- "version": "1.17.1",
399- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
400- "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
401- "dev": true,
402- "dependencies": {
403- "reusify": "^1.0.4"
404- }
405- },
406- "node_modules/fill-range": {
407- "version": "7.0.1",
408- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
409- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
410- "dev": true,
411- "dependencies": {
412- "to-regex-range": "^5.0.1"
413- },
414- "engines": {
415- "node": ">=8"
416- }
417- },
418- "node_modules/foreground-child": {
419- "version": "3.1.1",
420- "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
421- "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
422- "dev": true,
423- "dependencies": {
424- "cross-spawn": "^7.0.0",
425- "signal-exit": "^4.0.1"
426- },
427- "engines": {
428- "node": ">=14"
429- },
430- "funding": {
431- "url": "https://github.com/sponsors/isaacs"
432- }
433- },
434- "node_modules/fsevents": {
435- "version": "2.3.3",
436- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
437- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
438- "dev": true,
439- "hasInstallScript": true,
440- "optional": true,
441- "os": [
442- "darwin"
443- ],
444- "engines": {
445- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
446- }
447- },
448- "node_modules/function-bind": {
449- "version": "1.1.2",
450- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
451- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
452- "dev": true,
453- "funding": {
454- "url": "https://github.com/sponsors/ljharb"
455- }
456- },
457- "node_modules/glob": {
458- "version": "10.3.12",
459- "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz",
460- "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==",
461- "dev": true,
462- "dependencies": {
463- "foreground-child": "^3.1.0",
464- "jackspeak": "^2.3.6",
465- "minimatch": "^9.0.1",
466- "minipass": "^7.0.4",
467- "path-scurry": "^1.10.2"
468- },
469- "bin": {
470- "glob": "dist/esm/bin.mjs"
471- },
472- "engines": {
473- "node": ">=16 || 14 >=14.17"
474- },
475- "funding": {
476- "url": "https://github.com/sponsors/isaacs"
477- }
478- },
479- "node_modules/glob-parent": {
480- "version": "6.0.2",
481- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
482- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
483- "dev": true,
484- "dependencies": {
485- "is-glob": "^4.0.3"
486- },
487- "engines": {
488- "node": ">=10.13.0"
489- }
490- },
491- "node_modules/hasown": {
492- "version": "2.0.2",
493- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
494- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
495- "dev": true,
496- "dependencies": {
497- "function-bind": "^1.1.2"
498- },
499- "engines": {
500- "node": ">= 0.4"
501- }
502- },
503- "node_modules/is-binary-path": {
504- "version": "2.1.0",
505- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
506- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
507- "dev": true,
508- "dependencies": {
509- "binary-extensions": "^2.0.0"
510- },
511- "engines": {
512- "node": ">=8"
513- }
514- },
515- "node_modules/is-core-module": {
516- "version": "2.13.1",
517- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
518- "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
519- "dev": true,
520- "dependencies": {
521- "hasown": "^2.0.0"
522- },
523- "funding": {
524- "url": "https://github.com/sponsors/ljharb"
525- }
526- },
527- "node_modules/is-extglob": {
528- "version": "2.1.1",
529- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
530- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
531- "dev": true,
532- "engines": {
533- "node": ">=0.10.0"
534- }
535- },
536- "node_modules/is-fullwidth-code-point": {
537- "version": "3.0.0",
538- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
539- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
540- "dev": true,
541- "engines": {
542- "node": ">=8"
543- }
544- },
545- "node_modules/is-glob": {
546- "version": "4.0.3",
547- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
548- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
549- "dev": true,
550- "dependencies": {
551- "is-extglob": "^2.1.1"
552- },
553- "engines": {
554- "node": ">=0.10.0"
555- }
556- },
557- "node_modules/is-number": {
558- "version": "7.0.0",
559- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
560- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
561- "dev": true,
562- "engines": {
563- "node": ">=0.12.0"
564- }
565- },
566- "node_modules/isexe": {
567- "version": "2.0.0",
568- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
569- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
570- "dev": true
571- },
572- "node_modules/jackspeak": {
573- "version": "2.3.6",
574- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
575- "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
576- "dev": true,
577- "dependencies": {
578- "@isaacs/cliui": "^8.0.2"
579- },
580- "engines": {
581- "node": ">=14"
582- },
583- "funding": {
584- "url": "https://github.com/sponsors/isaacs"
585- },
586- "optionalDependencies": {
587- "@pkgjs/parseargs": "^0.11.0"
588- }
589- },
590- "node_modules/jiti": {
591- "version": "1.21.0",
592- "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
593- "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==",
594- "dev": true,
595- "bin": {
596- "jiti": "bin/jiti.js"
597- }
598- },
599- "node_modules/lilconfig": {
600- "version": "2.1.0",
601- "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
602- "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
603- "dev": true,
604- "engines": {
605- "node": ">=10"
606- }
607- },
608- "node_modules/lines-and-columns": {
609- "version": "1.2.4",
610- "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
611- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
612- "dev": true
613- },
614- "node_modules/lru-cache": {
615- "version": "10.2.0",
616- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
617- "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
618- "dev": true,
619- "engines": {
620- "node": "14 || >=16.14"
621- }
622- },
623- "node_modules/merge2": {
624- "version": "1.4.1",
625- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
626- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
627- "dev": true,
628- "engines": {
629- "node": ">= 8"
630- }
631- },
632- "node_modules/micromatch": {
633- "version": "4.0.5",
634- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
635- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
636- "dev": true,
637- "dependencies": {
638- "braces": "^3.0.2",
639- "picomatch": "^2.3.1"
640- },
641- "engines": {
642- "node": ">=8.6"
643- }
644- },
645- "node_modules/minimatch": {
646- "version": "9.0.4",
647- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
648- "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
649- "dev": true,
650- "dependencies": {
651- "brace-expansion": "^2.0.1"
652- },
653- "engines": {
654- "node": ">=16 || 14 >=14.17"
655- },
656- "funding": {
657- "url": "https://github.com/sponsors/isaacs"
658- }
659- },
660- "node_modules/minipass": {
661- "version": "7.0.4",
662- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
663- "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
664- "dev": true,
665- "engines": {
666- "node": ">=16 || 14 >=14.17"
667- }
668- },
669- "node_modules/mz": {
670- "version": "2.7.0",
671- "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
672- "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
673- "dev": true,
674- "dependencies": {
675- "any-promise": "^1.0.0",
676- "object-assign": "^4.0.1",
677- "thenify-all": "^1.0.0"
678- }
679- },
680- "node_modules/nanoid": {
681- "version": "3.3.7",
682- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
683- "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
684- "dev": true,
685- "funding": [
686- {
687- "type": "github",
688- "url": "https://github.com/sponsors/ai"
689- }
690- ],
691- "bin": {
692- "nanoid": "bin/nanoid.cjs"
693- },
694- "engines": {
695- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
696- }
697- },
698- "node_modules/normalize-path": {
699- "version": "3.0.0",
700- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
701- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
702- "dev": true,
703- "engines": {
704- "node": ">=0.10.0"
705- }
706- },
707- "node_modules/object-assign": {
708- "version": "4.1.1",
709- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
710- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
711- "dev": true,
712- "engines": {
713- "node": ">=0.10.0"
714- }
715- },
716- "node_modules/object-hash": {
717- "version": "3.0.0",
718- "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
719- "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
720- "dev": true,
721- "engines": {
722- "node": ">= 6"
723- }
724- },
725- "node_modules/path-key": {
726- "version": "3.1.1",
727- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
728- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
729- "dev": true,
730- "engines": {
731- "node": ">=8"
732- }
733- },
734- "node_modules/path-parse": {
735- "version": "1.0.7",
736- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
737- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
738- "dev": true
739- },
740- "node_modules/path-scurry": {
741- "version": "1.10.2",
742- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz",
743- "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==",
744- "dev": true,
745- "dependencies": {
746- "lru-cache": "^10.2.0",
747- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
748- },
749- "engines": {
750- "node": ">=16 || 14 >=14.17"
751- },
752- "funding": {
753- "url": "https://github.com/sponsors/isaacs"
754- }
755- },
756- "node_modules/picocolors": {
757- "version": "1.0.0",
758- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
759- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
760- "dev": true
761- },
762- "node_modules/picomatch": {
763- "version": "2.3.1",
764- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
765- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
766- "dev": true,
767- "engines": {
768- "node": ">=8.6"
769- },
770- "funding": {
771- "url": "https://github.com/sponsors/jonschlinkert"
772- }
773- },
774- "node_modules/pify": {
775- "version": "2.3.0",
776- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
777- "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
778- "dev": true,
779- "engines": {
780- "node": ">=0.10.0"
781- }
782- },
783- "node_modules/pirates": {
784- "version": "4.0.6",
785- "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
786- "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
787- "dev": true,
788- "engines": {
789- "node": ">= 6"
790- }
791- },
792- "node_modules/postcss": {
793- "version": "8.4.38",
794- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
795- "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
796- "dev": true,
797- "funding": [
798- {
799- "type": "opencollective",
800- "url": "https://opencollective.com/postcss/"
801- },
802- {
803- "type": "tidelift",
804- "url": "https://tidelift.com/funding/github/npm/postcss"
805- },
806- {
807- "type": "github",
808- "url": "https://github.com/sponsors/ai"
809- }
810- ],
811- "dependencies": {
812- "nanoid": "^3.3.7",
813- "picocolors": "^1.0.0",
814- "source-map-js": "^1.2.0"
815- },
816- "engines": {
817- "node": "^10 || ^12 || >=14"
818- }
819- },
820- "node_modules/postcss-import": {
821- "version": "15.1.0",
822- "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
823- "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
824- "dev": true,
825- "dependencies": {
826- "postcss-value-parser": "^4.0.0",
827- "read-cache": "^1.0.0",
828- "resolve": "^1.1.7"
829- },
830- "engines": {
831- "node": ">=14.0.0"
832- },
833- "peerDependencies": {
834- "postcss": "^8.0.0"
835- }
836- },
837- "node_modules/postcss-js": {
838- "version": "4.0.1",
839- "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
840- "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
841- "dev": true,
842- "dependencies": {
843- "camelcase-css": "^2.0.1"
844- },
845- "engines": {
846- "node": "^12 || ^14 || >= 16"
847- },
848- "funding": {
849- "type": "opencollective",
850- "url": "https://opencollective.com/postcss/"
851- },
852- "peerDependencies": {
853- "postcss": "^8.4.21"
854- }
855- },
856- "node_modules/postcss-load-config": {
857- "version": "4.0.2",
858- "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
859- "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
860- "dev": true,
861- "funding": [
862- {
863- "type": "opencollective",
864- "url": "https://opencollective.com/postcss/"
865- },
866- {
867- "type": "github",
868- "url": "https://github.com/sponsors/ai"
869- }
870- ],
871- "dependencies": {
872- "lilconfig": "^3.0.0",
873- "yaml": "^2.3.4"
874- },
875- "engines": {
876- "node": ">= 14"
877- },
878- "peerDependencies": {
879- "postcss": ">=8.0.9",
880- "ts-node": ">=9.0.0"
881- },
882- "peerDependenciesMeta": {
883- "postcss": {
884- "optional": true
885- },
886- "ts-node": {
887- "optional": true
888- }
889- }
890- },
891- "node_modules/postcss-load-config/node_modules/lilconfig": {
892- "version": "3.1.1",
893- "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz",
894- "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==",
895- "dev": true,
896- "engines": {
897- "node": ">=14"
898- },
899- "funding": {
900- "url": "https://github.com/sponsors/antonk52"
901- }
902- },
903- "node_modules/postcss-nested": {
904- "version": "6.0.1",
905- "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
906- "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
907- "dev": true,
908- "dependencies": {
909- "postcss-selector-parser": "^6.0.11"
910- },
911- "engines": {
912- "node": ">=12.0"
913- },
914- "funding": {
915- "type": "opencollective",
916- "url": "https://opencollective.com/postcss/"
917- },
918- "peerDependencies": {
919- "postcss": "^8.2.14"
920- }
921- },
922- "node_modules/postcss-selector-parser": {
923- "version": "6.0.16",
924- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz",
925- "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==",
926- "dev": true,
927- "dependencies": {
928- "cssesc": "^3.0.0",
929- "util-deprecate": "^1.0.2"
930- },
931- "engines": {
932- "node": ">=4"
933- }
934- },
935- "node_modules/postcss-value-parser": {
936- "version": "4.2.0",
937- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
938- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
939- "dev": true
940- },
941- "node_modules/prettier": {
942- "version": "3.2.5",
943- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
944- "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==",
945- "dev": true,
946- "bin": {
947- "prettier": "bin/prettier.cjs"
948- },
949- "engines": {
950- "node": ">=14"
951- },
952- "funding": {
953- "url": "https://github.com/prettier/prettier?sponsor=1"
954- }
955- },
956- "node_modules/prettier-plugin-tailwindcss": {
957- "version": "0.5.14",
958- "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.14.tgz",
959- "integrity": "sha512-Puaz+wPUAhFp8Lo9HuciYKM2Y2XExESjeT+9NQoVFXZsPPnc9VYss2SpxdQ6vbatmt8/4+SN0oe0I1cPDABg9Q==",
960- "dev": true,
961- "engines": {
962- "node": ">=14.21.3"
963- },
964- "peerDependencies": {
965- "@ianvs/prettier-plugin-sort-imports": "*",
966- "@prettier/plugin-pug": "*",
967- "@shopify/prettier-plugin-liquid": "*",
968- "@trivago/prettier-plugin-sort-imports": "*",
969- "@zackad/prettier-plugin-twig-melody": "*",
970- "prettier": "^3.0",
971- "prettier-plugin-astro": "*",
972- "prettier-plugin-css-order": "*",
973- "prettier-plugin-import-sort": "*",
974- "prettier-plugin-jsdoc": "*",
975- "prettier-plugin-marko": "*",
976- "prettier-plugin-organize-attributes": "*",
977- "prettier-plugin-organize-imports": "*",
978- "prettier-plugin-sort-imports": "*",
979- "prettier-plugin-style-order": "*",
980- "prettier-plugin-svelte": "*"
981- },
982- "peerDependenciesMeta": {
983- "@ianvs/prettier-plugin-sort-imports": {
984- "optional": true
985- },
986- "@prettier/plugin-pug": {
987- "optional": true
988- },
989- "@shopify/prettier-plugin-liquid": {
990- "optional": true
991- },
992- "@trivago/prettier-plugin-sort-imports": {
993- "optional": true
994- },
995- "@zackad/prettier-plugin-twig-melody": {
996- "optional": true
997- },
998- "prettier-plugin-astro": {
999- "optional": true
1000- },
1001- "prettier-plugin-css-order": {
1002- "optional": true
1003- },
1004- "prettier-plugin-import-sort": {
1005- "optional": true
1006- },
1007- "prettier-plugin-jsdoc": {
1008- "optional": true
1009- },
1010- "prettier-plugin-marko": {
1011- "optional": true
1012- },
1013- "prettier-plugin-organize-attributes": {
1014- "optional": true
1015- },
1016- "prettier-plugin-organize-imports": {
1017- "optional": true
1018- },
1019- "prettier-plugin-sort-imports": {
1020- "optional": true
1021- },
1022- "prettier-plugin-style-order": {
1023- "optional": true
1024- },
1025- "prettier-plugin-svelte": {
1026- "optional": true
1027- }
1028- }
1029- },
1030- "node_modules/queue-microtask": {
1031- "version": "1.2.3",
1032- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
1033- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
1034- "dev": true,
1035- "funding": [
1036- {
1037- "type": "github",
1038- "url": "https://github.com/sponsors/feross"
1039- },
1040- {
1041- "type": "patreon",
1042- "url": "https://www.patreon.com/feross"
1043- },
1044- {
1045- "type": "consulting",
1046- "url": "https://feross.org/support"
1047- }
1048- ]
1049- },
1050- "node_modules/read-cache": {
1051- "version": "1.0.0",
1052- "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
1053- "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
1054- "dev": true,
1055- "dependencies": {
1056- "pify": "^2.3.0"
1057- }
1058- },
1059- "node_modules/readdirp": {
1060- "version": "3.6.0",
1061- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
1062- "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
1063- "dev": true,
1064- "dependencies": {
1065- "picomatch": "^2.2.1"
1066- },
1067- "engines": {
1068- "node": ">=8.10.0"
1069- }
1070- },
1071- "node_modules/resolve": {
1072- "version": "1.22.8",
1073- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
1074- "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
1075- "dev": true,
1076- "dependencies": {
1077- "is-core-module": "^2.13.0",
1078- "path-parse": "^1.0.7",
1079- "supports-preserve-symlinks-flag": "^1.0.0"
1080- },
1081- "bin": {
1082- "resolve": "bin/resolve"
1083- },
1084- "funding": {
1085- "url": "https://github.com/sponsors/ljharb"
1086- }
1087- },
1088- "node_modules/reusify": {
1089- "version": "1.0.4",
1090- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
1091- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
1092- "dev": true,
1093- "engines": {
1094- "iojs": ">=1.0.0",
1095- "node": ">=0.10.0"
1096- }
1097- },
1098- "node_modules/run-parallel": {
1099- "version": "1.2.0",
1100- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
1101- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
1102- "dev": true,
1103- "funding": [
1104- {
1105- "type": "github",
1106- "url": "https://github.com/sponsors/feross"
1107- },
1108- {
1109- "type": "patreon",
1110- "url": "https://www.patreon.com/feross"
1111- },
1112- {
1113- "type": "consulting",
1114- "url": "https://feross.org/support"
1115- }
1116- ],
1117- "dependencies": {
1118- "queue-microtask": "^1.2.2"
1119- }
1120- },
1121- "node_modules/shebang-command": {
1122- "version": "2.0.0",
1123- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
1124- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
1125- "dev": true,
1126- "dependencies": {
1127- "shebang-regex": "^3.0.0"
1128- },
1129- "engines": {
1130- "node": ">=8"
1131- }
1132- },
1133- "node_modules/shebang-regex": {
1134- "version": "3.0.0",
1135- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
1136- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
1137- "dev": true,
1138- "engines": {
1139- "node": ">=8"
1140- }
1141- },
1142- "node_modules/signal-exit": {
1143- "version": "4.1.0",
1144- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
1145- "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
1146- "dev": true,
1147- "engines": {
1148- "node": ">=14"
1149- },
1150- "funding": {
1151- "url": "https://github.com/sponsors/isaacs"
1152- }
1153- },
1154- "node_modules/source-map-js": {
1155- "version": "1.2.0",
1156- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
1157- "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
1158- "dev": true,
1159- "engines": {
1160- "node": ">=0.10.0"
1161- }
1162- },
1163- "node_modules/string-width": {
1164- "version": "5.1.2",
1165- "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
1166- "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
1167- "dev": true,
1168- "dependencies": {
1169- "eastasianwidth": "^0.2.0",
1170- "emoji-regex": "^9.2.2",
1171- "strip-ansi": "^7.0.1"
1172- },
1173- "engines": {
1174- "node": ">=12"
1175- },
1176- "funding": {
1177- "url": "https://github.com/sponsors/sindresorhus"
1178- }
1179- },
1180- "node_modules/string-width-cjs": {
1181- "name": "string-width",
1182- "version": "4.2.3",
1183- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
1184- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
1185- "dev": true,
1186- "dependencies": {
1187- "emoji-regex": "^8.0.0",
1188- "is-fullwidth-code-point": "^3.0.0",
1189- "strip-ansi": "^6.0.1"
1190- },
1191- "engines": {
1192- "node": ">=8"
1193- }
1194- },
1195- "node_modules/string-width-cjs/node_modules/ansi-regex": {
1196- "version": "5.0.1",
1197- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
1198- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
1199- "dev": true,
1200- "engines": {
1201- "node": ">=8"
1202- }
1203- },
1204- "node_modules/string-width-cjs/node_modules/emoji-regex": {
1205- "version": "8.0.0",
1206- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
1207- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
1208- "dev": true
1209- },
1210- "node_modules/string-width-cjs/node_modules/strip-ansi": {
1211- "version": "6.0.1",
1212- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1213- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1214- "dev": true,
1215- "dependencies": {
1216- "ansi-regex": "^5.0.1"
1217- },
1218- "engines": {
1219- "node": ">=8"
1220- }
1221- },
1222- "node_modules/strip-ansi": {
1223- "version": "7.1.0",
1224- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
1225- "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
1226- "dev": true,
1227- "dependencies": {
1228- "ansi-regex": "^6.0.1"
1229- },
1230- "engines": {
1231- "node": ">=12"
1232- },
1233- "funding": {
1234- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
1235- }
1236- },
1237- "node_modules/strip-ansi-cjs": {
1238- "name": "strip-ansi",
1239- "version": "6.0.1",
1240- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1241- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1242- "dev": true,
1243- "dependencies": {
1244- "ansi-regex": "^5.0.1"
1245- },
1246- "engines": {
1247- "node": ">=8"
1248- }
1249- },
1250- "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
1251- "version": "5.0.1",
1252- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
1253- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
1254- "dev": true,
1255- "engines": {
1256- "node": ">=8"
1257- }
1258- },
1259- "node_modules/sucrase": {
1260- "version": "3.35.0",
1261- "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
1262- "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
1263- "dev": true,
1264- "dependencies": {
1265- "@jridgewell/gen-mapping": "^0.3.2",
1266- "commander": "^4.0.0",
1267- "glob": "^10.3.10",
1268- "lines-and-columns": "^1.1.6",
1269- "mz": "^2.7.0",
1270- "pirates": "^4.0.1",
1271- "ts-interface-checker": "^0.1.9"
1272- },
1273- "bin": {
1274- "sucrase": "bin/sucrase",
1275- "sucrase-node": "bin/sucrase-node"
1276- },
1277- "engines": {
1278- "node": ">=16 || 14 >=14.17"
1279- }
1280- },
1281- "node_modules/supports-preserve-symlinks-flag": {
1282- "version": "1.0.0",
1283- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
1284- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
1285- "dev": true,
1286- "engines": {
1287- "node": ">= 0.4"
1288- },
1289- "funding": {
1290- "url": "https://github.com/sponsors/ljharb"
1291- }
1292- },
1293- "node_modules/tailwindcss": {
1294- "version": "3.4.3",
1295- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz",
1296- "integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==",
1297- "dev": true,
1298- "dependencies": {
1299- "@alloc/quick-lru": "^5.2.0",
1300- "arg": "^5.0.2",
1301- "chokidar": "^3.5.3",
1302- "didyoumean": "^1.2.2",
1303- "dlv": "^1.1.3",
1304- "fast-glob": "^3.3.0",
1305- "glob-parent": "^6.0.2",
1306- "is-glob": "^4.0.3",
1307- "jiti": "^1.21.0",
1308- "lilconfig": "^2.1.0",
1309- "micromatch": "^4.0.5",
1310- "normalize-path": "^3.0.0",
1311- "object-hash": "^3.0.0",
1312- "picocolors": "^1.0.0",
1313- "postcss": "^8.4.23",
1314- "postcss-import": "^15.1.0",
1315- "postcss-js": "^4.0.1",
1316- "postcss-load-config": "^4.0.1",
1317- "postcss-nested": "^6.0.1",
1318- "postcss-selector-parser": "^6.0.11",
1319- "resolve": "^1.22.2",
1320- "sucrase": "^3.32.0"
1321- },
1322- "bin": {
1323- "tailwind": "lib/cli.js",
1324- "tailwindcss": "lib/cli.js"
1325- },
1326- "engines": {
1327- "node": ">=14.0.0"
1328- }
1329- },
1330- "node_modules/thenify": {
1331- "version": "3.3.1",
1332- "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
1333- "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
1334- "dev": true,
1335- "dependencies": {
1336- "any-promise": "^1.0.0"
1337- }
1338- },
1339- "node_modules/thenify-all": {
1340- "version": "1.6.0",
1341- "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
1342- "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
1343- "dev": true,
1344- "dependencies": {
1345- "thenify": ">= 3.1.0 < 4"
1346- },
1347- "engines": {
1348- "node": ">=0.8"
1349- }
1350- },
1351- "node_modules/to-regex-range": {
1352- "version": "5.0.1",
1353- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
1354- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
1355- "dev": true,
1356- "dependencies": {
1357- "is-number": "^7.0.0"
1358- },
1359- "engines": {
1360- "node": ">=8.0"
1361- }
1362- },
1363- "node_modules/ts-interface-checker": {
1364- "version": "0.1.13",
1365- "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
1366- "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
1367- "dev": true
1368- },
1369- "node_modules/util-deprecate": {
1370- "version": "1.0.2",
1371- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
1372- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
1373- "dev": true
1374- },
1375- "node_modules/which": {
1376- "version": "2.0.2",
1377- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
1378- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
1379- "dev": true,
1380- "dependencies": {
1381- "isexe": "^2.0.0"
1382- },
1383- "bin": {
1384- "node-which": "bin/node-which"
1385- },
1386- "engines": {
1387- "node": ">= 8"
1388- }
1389- },
1390- "node_modules/wrap-ansi": {
1391- "version": "8.1.0",
1392- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
1393- "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
1394- "dev": true,
1395- "dependencies": {
1396- "ansi-styles": "^6.1.0",
1397- "string-width": "^5.0.1",
1398- "strip-ansi": "^7.0.1"
1399- },
1400- "engines": {
1401- "node": ">=12"
1402- },
1403- "funding": {
1404- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
1405- }
1406- },
1407- "node_modules/wrap-ansi-cjs": {
1408- "name": "wrap-ansi",
1409- "version": "7.0.0",
1410- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
1411- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
1412- "dev": true,
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- "engines": {
1431- "node": ">=8"
1432- }
1433- },
1434- "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
1435- "version": "4.3.0",
1436- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
1437- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
1438- "dev": true,
1439- "dependencies": {
1440- "color-convert": "^2.0.1"
1441- },
1442- "engines": {
1443- "node": ">=8"
1444- },
1445- "funding": {
1446- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
1447- }
1448- },
1449- "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
1450- "version": "8.0.0",
1451- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
1452- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
1453- "dev": true
1454- },
1455- "node_modules/wrap-ansi-cjs/node_modules/string-width": {
1456- "version": "4.2.3",
1457- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
1458- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
1459- "dev": true,
1460- "dependencies": {
1461- "emoji-regex": "^8.0.0",
1462- "is-fullwidth-code-point": "^3.0.0",
1463- "strip-ansi": "^6.0.1"
1464- },
1465- "engines": {
1466- "node": ">=8"
1467- }
1468- },
1469- "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
1470- "version": "6.0.1",
1471- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1472- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1473- "dev": true,
1474- "dependencies": {
1475- "ansi-regex": "^5.0.1"
1476- },
1477- "engines": {
1478- "node": ">=8"
1479- }
1480- },
1481- "node_modules/yaml": {
1482- "version": "2.4.1",
1483- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz",
1484- "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==",
1485- "dev": true,
1486- "bin": {
1487- "yaml": "bin.mjs"
1488- },
1489- "engines": {
1490- "node": ">= 14"
1491- }
1492- }
1493- }
1494-}
@@ -1,1494 +0,0 @@
1-{
2- "name": "gordon",
3- "lockfileVersion": 3,
4- "requires": true,
5- "packages": {
6- "": {
7- "dependencies": {
8- "dotenv": "^16.4.5"
9- },
10- "devDependencies": {
11- "@catppuccin/tailwindcss": "^0.1.6",
12- "prettier": "^3.0.3",
13- "prettier-plugin-tailwindcss": "^0.5.5",
14- "tailwindcss": "^3.3.3"
15- }
16- },
17- "node_modules/@alloc/quick-lru": {
18- "version": "5.2.0",
19- "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
20- "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
21- "dev": true,
22- "engines": {
23- "node": ">=10"
24- },
25- "funding": {
26- "url": "https://github.com/sponsors/sindresorhus"
27- }
28- },
29- "node_modules/@catppuccin/tailwindcss": {
30- "version": "0.1.6",
31- "resolved": "https://registry.npmjs.org/@catppuccin/tailwindcss/-/tailwindcss-0.1.6.tgz",
32- "integrity": "sha512-V+Y0AwZ5SSyvOVAcDl7Ng30xy+m82OKnEJ+9+kcZZ7lRyXuZrAb2GScdq9XR3v+ggt8qiZ/G4TvaC9cJ88AAXA==",
33- "dev": true,
34- "peerDependencies": {
35- "tailwindcss": ">=3.0.0"
36- }
37- },
38- "node_modules/@isaacs/cliui": {
39- "version": "8.0.2",
40- "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
41- "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
42- "dev": true,
43- "dependencies": {
44- "string-width": "^5.1.2",
45- "string-width-cjs": "npm:string-width@^4.2.0",
46- "strip-ansi": "^7.0.1",
47- "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
48- "wrap-ansi": "^8.1.0",
49- "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
50- },
51- "engines": {
52- "node": ">=12"
53- }
54- },
55- "node_modules/@jridgewell/gen-mapping": {
56- "version": "0.3.5",
57- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
58- "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
59- "dev": true,
60- "dependencies": {
61- "@jridgewell/set-array": "^1.2.1",
62- "@jridgewell/sourcemap-codec": "^1.4.10",
63- "@jridgewell/trace-mapping": "^0.3.24"
64- },
65- "engines": {
66- "node": ">=6.0.0"
67- }
68- },
69- "node_modules/@jridgewell/resolve-uri": {
70- "version": "3.1.2",
71- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
72- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
73- "dev": true,
74- "engines": {
75- "node": ">=6.0.0"
76- }
77- },
78- "node_modules/@jridgewell/set-array": {
79- "version": "1.2.1",
80- "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
81- "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
82- "dev": true,
83- "engines": {
84- "node": ">=6.0.0"
85- }
86- },
87- "node_modules/@jridgewell/sourcemap-codec": {
88- "version": "1.4.15",
89- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
90- "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
91- "dev": true
92- },
93- "node_modules/@jridgewell/trace-mapping": {
94- "version": "0.3.25",
95- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
96- "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
97- "dev": true,
98- "dependencies": {
99- "@jridgewell/resolve-uri": "^3.1.0",
100- "@jridgewell/sourcemap-codec": "^1.4.14"
101- }
102- },
103- "node_modules/@nodelib/fs.scandir": {
104- "version": "2.1.5",
105- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
106- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
107- "dev": true,
108- "dependencies": {
109- "@nodelib/fs.stat": "2.0.5",
110- "run-parallel": "^1.1.9"
111- },
112- "engines": {
113- "node": ">= 8"
114- }
115- },
116- "node_modules/@nodelib/fs.stat": {
117- "version": "2.0.5",
118- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
119- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
120- "dev": true,
121- "engines": {
122- "node": ">= 8"
123- }
124- },
125- "node_modules/@nodelib/fs.walk": {
126- "version": "1.2.8",
127- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
128- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
129- "dev": true,
130- "dependencies": {
131- "@nodelib/fs.scandir": "2.1.5",
132- "fastq": "^1.6.0"
133- },
134- "engines": {
135- "node": ">= 8"
136- }
137- },
138- "node_modules/@pkgjs/parseargs": {
139- "version": "0.11.0",
140- "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
141- "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
142- "dev": true,
143- "optional": true,
144- "engines": {
145- "node": ">=14"
146- }
147- },
148- "node_modules/ansi-regex": {
149- "version": "6.0.1",
150- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
151- "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
152- "dev": true,
153- "engines": {
154- "node": ">=12"
155- },
156- "funding": {
157- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
158- }
159- },
160- "node_modules/ansi-styles": {
161- "version": "6.2.1",
162- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
163- "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
164- "dev": true,
165- "engines": {
166- "node": ">=12"
167- },
168- "funding": {
169- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
170- }
171- },
172- "node_modules/any-promise": {
173- "version": "1.3.0",
174- "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
175- "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
176- "dev": true
177- },
178- "node_modules/anymatch": {
179- "version": "3.1.3",
180- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
181- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
182- "dev": true,
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- },
197- "node_modules/balanced-match": {
198- "version": "1.0.2",
199- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
200- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
201- "dev": true
202- },
203- "node_modules/binary-extensions": {
204- "version": "2.3.0",
205- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
206- "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
207- "dev": true,
208- "engines": {
209- "node": ">=8"
210- },
211- "funding": {
212- "url": "https://github.com/sponsors/sindresorhus"
213- }
214- },
215- "node_modules/brace-expansion": {
216- "version": "2.0.1",
217- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
218- "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
219- "dev": true,
220- "dependencies": {
221- "balanced-match": "^1.0.0"
222- }
223- },
224- "node_modules/braces": {
225- "version": "3.0.2",
226- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
227- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
228- "dev": true,
229- "dependencies": {
230- "fill-range": "^7.0.1"
231- },
232- "engines": {
233- "node": ">=8"
234- }
235- },
236- "node_modules/camelcase-css": {
237- "version": "2.0.1",
238- "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
239- "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
240- "dev": true,
241- "engines": {
242- "node": ">= 6"
243- }
244- },
245- "node_modules/chokidar": {
246- "version": "3.6.0",
247- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
248- "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
249- "dev": true,
250- "dependencies": {
251- "anymatch": "~3.1.2",
252- "braces": "~3.0.2",
253- "glob-parent": "~5.1.2",
254- "is-binary-path": "~2.1.0",
255- "is-glob": "~4.0.1",
256- "normalize-path": "~3.0.0",
257- "readdirp": "~3.6.0"
258- },
259- "engines": {
260- "node": ">= 8.10.0"
261- },
262- "funding": {
263- "url": "https://paulmillr.com/funding/"
264- },
265- "optionalDependencies": {
266- "fsevents": "~2.3.2"
267- }
268- },
269- "node_modules/chokidar/node_modules/glob-parent": {
270- "version": "5.1.2",
271- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
272- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
273- "dev": true,
274- "dependencies": {
275- "is-glob": "^4.0.1"
276- },
277- "engines": {
278- "node": ">= 6"
279- }
280- },
281- "node_modules/color-convert": {
282- "version": "2.0.1",
283- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
284- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
285- "dev": true,
286- "dependencies": {
287- "color-name": "~1.1.4"
288- },
289- "engines": {
290- "node": ">=7.0.0"
291- }
292- },
293- "node_modules/color-name": {
294- "version": "1.1.4",
295- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
296- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
297- "dev": true
298- },
299- "node_modules/commander": {
300- "version": "4.1.1",
301- "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
302- "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
303- "dev": true,
304- "engines": {
305- "node": ">= 6"
306- }
307- },
308- "node_modules/cross-spawn": {
309- "version": "7.0.3",
310- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
311- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
312- "dev": true,
313- "dependencies": {
314- "path-key": "^3.1.0",
315- "shebang-command": "^2.0.0",
316- "which": "^2.0.1"
317- },
318- "engines": {
319- "node": ">= 8"
320- }
321- },
322- "node_modules/cssesc": {
323- "version": "3.0.0",
324- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
325- "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
326- "dev": true,
327- "bin": {
328- "cssesc": "bin/cssesc"
329- },
330- "engines": {
331- "node": ">=4"
332- }
333- },
334- "node_modules/didyoumean": {
335- "version": "1.2.2",
336- "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
337- "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
338- "dev": true
339- },
340- "node_modules/dlv": {
341- "version": "1.1.3",
342- "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
343- "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
344- "dev": true
345- },
346- "node_modules/dotenv": {
347- "version": "16.4.5",
348- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
349- "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
350- "engines": {
351- "node": ">=12"
352- },
353- "funding": {
354- "url": "https://dotenvx.com"
355- }
356- },
357- "node_modules/eastasianwidth": {
358- "version": "0.2.0",
359- "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
360- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
361- "dev": true
362- },
363- "node_modules/emoji-regex": {
364- "version": "9.2.2",
365- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
366- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
367- "dev": true
368- },
369- "node_modules/fast-glob": {
370- "version": "3.3.2",
371- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
372- "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
373- "dev": true,
374- "dependencies": {
375- "@nodelib/fs.stat": "^2.0.2",
376- "@nodelib/fs.walk": "^1.2.3",
377- "glob-parent": "^5.1.2",
378- "merge2": "^1.3.0",
379- "micromatch": "^4.0.4"
380- },
381- "engines": {
382- "node": ">=8.6.0"
383- }
384- },
385- "node_modules/fast-glob/node_modules/glob-parent": {
386- "version": "5.1.2",
387- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
388- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
389- "dev": true,
390- "dependencies": {
391- "is-glob": "^4.0.1"
392- },
393- "engines": {
394- "node": ">= 6"
395- }
396- },
397- "node_modules/fastq": {
398- "version": "1.17.1",
399- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
400- "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
401- "dev": true,
402- "dependencies": {
403- "reusify": "^1.0.4"
404- }
405- },
406- "node_modules/fill-range": {
407- "version": "7.0.1",
408- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
409- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
410- "dev": true,
411- "dependencies": {
412- "to-regex-range": "^5.0.1"
413- },
414- "engines": {
415- "node": ">=8"
416- }
417- },
418- "node_modules/foreground-child": {
419- "version": "3.1.1",
420- "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
421- "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
422- "dev": true,
423- "dependencies": {
424- "cross-spawn": "^7.0.0",
425- "signal-exit": "^4.0.1"
426- },
427- "engines": {
428- "node": ">=14"
429- },
430- "funding": {
431- "url": "https://github.com/sponsors/isaacs"
432- }
433- },
434- "node_modules/fsevents": {
435- "version": "2.3.3",
436- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
437- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
438- "dev": true,
439- "hasInstallScript": true,
440- "optional": true,
441- "os": [
442- "darwin"
443- ],
444- "engines": {
445- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
446- }
447- },
448- "node_modules/function-bind": {
449- "version": "1.1.2",
450- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
451- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
452- "dev": true,
453- "funding": {
454- "url": "https://github.com/sponsors/ljharb"
455- }
456- },
457- "node_modules/glob": {
458- "version": "10.3.12",
459- "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz",
460- "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==",
461- "dev": true,
462- "dependencies": {
463- "foreground-child": "^3.1.0",
464- "jackspeak": "^2.3.6",
465- "minimatch": "^9.0.1",
466- "minipass": "^7.0.4",
467- "path-scurry": "^1.10.2"
468- },
469- "bin": {
470- "glob": "dist/esm/bin.mjs"
471- },
472- "engines": {
473- "node": ">=16 || 14 >=14.17"
474- },
475- "funding": {
476- "url": "https://github.com/sponsors/isaacs"
477- }
478- },
479- "node_modules/glob-parent": {
480- "version": "6.0.2",
481- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
482- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
483- "dev": true,
484- "dependencies": {
485- "is-glob": "^4.0.3"
486- },
487- "engines": {
488- "node": ">=10.13.0"
489- }
490- },
491- "node_modules/hasown": {
492- "version": "2.0.2",
493- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
494- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
495- "dev": true,
496- "dependencies": {
497- "function-bind": "^1.1.2"
498- },
499- "engines": {
500- "node": ">= 0.4"
501- }
502- },
503- "node_modules/is-binary-path": {
504- "version": "2.1.0",
505- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
506- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
507- "dev": true,
508- "dependencies": {
509- "binary-extensions": "^2.0.0"
510- },
511- "engines": {
512- "node": ">=8"
513- }
514- },
515- "node_modules/is-core-module": {
516- "version": "2.13.1",
517- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
518- "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
519- "dev": true,
520- "dependencies": {
521- "hasown": "^2.0.0"
522- },
523- "funding": {
524- "url": "https://github.com/sponsors/ljharb"
525- }
526- },
527- "node_modules/is-extglob": {
528- "version": "2.1.1",
529- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
530- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
531- "dev": true,
532- "engines": {
533- "node": ">=0.10.0"
534- }
535- },
536- "node_modules/is-fullwidth-code-point": {
537- "version": "3.0.0",
538- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
539- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
540- "dev": true,
541- "engines": {
542- "node": ">=8"
543- }
544- },
545- "node_modules/is-glob": {
546- "version": "4.0.3",
547- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
548- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
549- "dev": true,
550- "dependencies": {
551- "is-extglob": "^2.1.1"
552- },
553- "engines": {
554- "node": ">=0.10.0"
555- }
556- },
557- "node_modules/is-number": {
558- "version": "7.0.0",
559- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
560- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
561- "dev": true,
562- "engines": {
563- "node": ">=0.12.0"
564- }
565- },
566- "node_modules/isexe": {
567- "version": "2.0.0",
568- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
569- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
570- "dev": true
571- },
572- "node_modules/jackspeak": {
573- "version": "2.3.6",
574- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
575- "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
576- "dev": true,
577- "dependencies": {
578- "@isaacs/cliui": "^8.0.2"
579- },
580- "engines": {
581- "node": ">=14"
582- },
583- "funding": {
584- "url": "https://github.com/sponsors/isaacs"
585- },
586- "optionalDependencies": {
587- "@pkgjs/parseargs": "^0.11.0"
588- }
589- },
590- "node_modules/jiti": {
591- "version": "1.21.0",
592- "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
593- "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==",
594- "dev": true,
595- "bin": {
596- "jiti": "bin/jiti.js"
597- }
598- },
599- "node_modules/lilconfig": {
600- "version": "2.1.0",
601- "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
602- "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
603- "dev": true,
604- "engines": {
605- "node": ">=10"
606- }
607- },
608- "node_modules/lines-and-columns": {
609- "version": "1.2.4",
610- "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
611- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
612- "dev": true
613- },
614- "node_modules/lru-cache": {
615- "version": "10.2.0",
616- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
617- "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
618- "dev": true,
619- "engines": {
620- "node": "14 || >=16.14"
621- }
622- },
623- "node_modules/merge2": {
624- "version": "1.4.1",
625- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
626- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
627- "dev": true,
628- "engines": {
629- "node": ">= 8"
630- }
631- },
632- "node_modules/micromatch": {
633- "version": "4.0.5",
634- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
635- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
636- "dev": true,
637- "dependencies": {
638- "braces": "^3.0.2",
639- "picomatch": "^2.3.1"
640- },
641- "engines": {
642- "node": ">=8.6"
643- }
644- },
645- "node_modules/minimatch": {
646- "version": "9.0.4",
647- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
648- "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
649- "dev": true,
650- "dependencies": {
651- "brace-expansion": "^2.0.1"
652- },
653- "engines": {
654- "node": ">=16 || 14 >=14.17"
655- },
656- "funding": {
657- "url": "https://github.com/sponsors/isaacs"
658- }
659- },
660- "node_modules/minipass": {
661- "version": "7.0.4",
662- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
663- "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
664- "dev": true,
665- "engines": {
666- "node": ">=16 || 14 >=14.17"
667- }
668- },
669- "node_modules/mz": {
670- "version": "2.7.0",
671- "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
672- "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
673- "dev": true,
674- "dependencies": {
675- "any-promise": "^1.0.0",
676- "object-assign": "^4.0.1",
677- "thenify-all": "^1.0.0"
678- }
679- },
680- "node_modules/nanoid": {
681- "version": "3.3.7",
682- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
683- "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
684- "dev": true,
685- "funding": [
686- {
687- "type": "github",
688- "url": "https://github.com/sponsors/ai"
689- }
690- ],
691- "bin": {
692- "nanoid": "bin/nanoid.cjs"
693- },
694- "engines": {
695- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
696- }
697- },
698- "node_modules/normalize-path": {
699- "version": "3.0.0",
700- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
701- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
702- "dev": true,
703- "engines": {
704- "node": ">=0.10.0"
705- }
706- },
707- "node_modules/object-assign": {
708- "version": "4.1.1",
709- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
710- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
711- "dev": true,
712- "engines": {
713- "node": ">=0.10.0"
714- }
715- },
716- "node_modules/object-hash": {
717- "version": "3.0.0",
718- "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
719- "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
720- "dev": true,
721- "engines": {
722- "node": ">= 6"
723- }
724- },
725- "node_modules/path-key": {
726- "version": "3.1.1",
727- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
728- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
729- "dev": true,
730- "engines": {
731- "node": ">=8"
732- }
733- },
734- "node_modules/path-parse": {
735- "version": "1.0.7",
736- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
737- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
738- "dev": true
739- },
740- "node_modules/path-scurry": {
741- "version": "1.10.2",
742- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz",
743- "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==",
744- "dev": true,
745- "dependencies": {
746- "lru-cache": "^10.2.0",
747- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
748- },
749- "engines": {
750- "node": ">=16 || 14 >=14.17"
751- },
752- "funding": {
753- "url": "https://github.com/sponsors/isaacs"
754- }
755- },
756- "node_modules/picocolors": {
757- "version": "1.0.0",
758- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
759- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
760- "dev": true
761- },
762- "node_modules/picomatch": {
763- "version": "2.3.1",
764- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
765- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
766- "dev": true,
767- "engines": {
768- "node": ">=8.6"
769- },
770- "funding": {
771- "url": "https://github.com/sponsors/jonschlinkert"
772- }
773- },
774- "node_modules/pify": {
775- "version": "2.3.0",
776- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
777- "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
778- "dev": true,
779- "engines": {
780- "node": ">=0.10.0"
781- }
782- },
783- "node_modules/pirates": {
784- "version": "4.0.6",
785- "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
786- "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
787- "dev": true,
788- "engines": {
789- "node": ">= 6"
790- }
791- },
792- "node_modules/postcss": {
793- "version": "8.4.38",
794- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
795- "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
796- "dev": true,
797- "funding": [
798- {
799- "type": "opencollective",
800- "url": "https://opencollective.com/postcss/"
801- },
802- {
803- "type": "tidelift",
804- "url": "https://tidelift.com/funding/github/npm/postcss"
805- },
806- {
807- "type": "github",
808- "url": "https://github.com/sponsors/ai"
809- }
810- ],
811- "dependencies": {
812- "nanoid": "^3.3.7",
813- "picocolors": "^1.0.0",
814- "source-map-js": "^1.2.0"
815- },
816- "engines": {
817- "node": "^10 || ^12 || >=14"
818- }
819- },
820- "node_modules/postcss-import": {
821- "version": "15.1.0",
822- "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
823- "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
824- "dev": true,
825- "dependencies": {
826- "postcss-value-parser": "^4.0.0",
827- "read-cache": "^1.0.0",
828- "resolve": "^1.1.7"
829- },
830- "engines": {
831- "node": ">=14.0.0"
832- },
833- "peerDependencies": {
834- "postcss": "^8.0.0"
835- }
836- },
837- "node_modules/postcss-js": {
838- "version": "4.0.1",
839- "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
840- "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
841- "dev": true,
842- "dependencies": {
843- "camelcase-css": "^2.0.1"
844- },
845- "engines": {
846- "node": "^12 || ^14 || >= 16"
847- },
848- "funding": {
849- "type": "opencollective",
850- "url": "https://opencollective.com/postcss/"
851- },
852- "peerDependencies": {
853- "postcss": "^8.4.21"
854- }
855- },
856- "node_modules/postcss-load-config": {
857- "version": "4.0.2",
858- "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
859- "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
860- "dev": true,
861- "funding": [
862- {
863- "type": "opencollective",
864- "url": "https://opencollective.com/postcss/"
865- },
866- {
867- "type": "github",
868- "url": "https://github.com/sponsors/ai"
869- }
870- ],
871- "dependencies": {
872- "lilconfig": "^3.0.0",
873- "yaml": "^2.3.4"
874- },
875- "engines": {
876- "node": ">= 14"
877- },
878- "peerDependencies": {
879- "postcss": ">=8.0.9",
880- "ts-node": ">=9.0.0"
881- },
882- "peerDependenciesMeta": {
883- "postcss": {
884- "optional": true
885- },
886- "ts-node": {
887- "optional": true
888- }
889- }
890- },
891- "node_modules/postcss-load-config/node_modules/lilconfig": {
892- "version": "3.1.1",
893- "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz",
894- "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==",
895- "dev": true,
896- "engines": {
897- "node": ">=14"
898- },
899- "funding": {
900- "url": "https://github.com/sponsors/antonk52"
901- }
902- },
903- "node_modules/postcss-nested": {
904- "version": "6.0.1",
905- "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
906- "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
907- "dev": true,
908- "dependencies": {
909- "postcss-selector-parser": "^6.0.11"
910- },
911- "engines": {
912- "node": ">=12.0"
913- },
914- "funding": {
915- "type": "opencollective",
916- "url": "https://opencollective.com/postcss/"
917- },
918- "peerDependencies": {
919- "postcss": "^8.2.14"
920- }
921- },
922- "node_modules/postcss-selector-parser": {
923- "version": "6.0.16",
924- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz",
925- "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==",
926- "dev": true,
927- "dependencies": {
928- "cssesc": "^3.0.0",
929- "util-deprecate": "^1.0.2"
930- },
931- "engines": {
932- "node": ">=4"
933- }
934- },
935- "node_modules/postcss-value-parser": {
936- "version": "4.2.0",
937- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
938- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
939- "dev": true
940- },
941- "node_modules/prettier": {
942- "version": "3.2.5",
943- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
944- "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==",
945- "dev": true,
946- "bin": {
947- "prettier": "bin/prettier.cjs"
948- },
949- "engines": {
950- "node": ">=14"
951- },
952- "funding": {
953- "url": "https://github.com/prettier/prettier?sponsor=1"
954- }
955- },
956- "node_modules/prettier-plugin-tailwindcss": {
957- "version": "0.5.14",
958- "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.14.tgz",
959- "integrity": "sha512-Puaz+wPUAhFp8Lo9HuciYKM2Y2XExESjeT+9NQoVFXZsPPnc9VYss2SpxdQ6vbatmt8/4+SN0oe0I1cPDABg9Q==",
960- "dev": true,
961- "engines": {
962- "node": ">=14.21.3"
963- },
964- "peerDependencies": {
965- "@ianvs/prettier-plugin-sort-imports": "*",
966- "@prettier/plugin-pug": "*",
967- "@shopify/prettier-plugin-liquid": "*",
968- "@trivago/prettier-plugin-sort-imports": "*",
969- "@zackad/prettier-plugin-twig-melody": "*",
970- "prettier": "^3.0",
971- "prettier-plugin-astro": "*",
972- "prettier-plugin-css-order": "*",
973- "prettier-plugin-import-sort": "*",
974- "prettier-plugin-jsdoc": "*",
975- "prettier-plugin-marko": "*",
976- "prettier-plugin-organize-attributes": "*",
977- "prettier-plugin-organize-imports": "*",
978- "prettier-plugin-sort-imports": "*",
979- "prettier-plugin-style-order": "*",
980- "prettier-plugin-svelte": "*"
981- },
982- "peerDependenciesMeta": {
983- "@ianvs/prettier-plugin-sort-imports": {
984- "optional": true
985- },
986- "@prettier/plugin-pug": {
987- "optional": true
988- },
989- "@shopify/prettier-plugin-liquid": {
990- "optional": true
991- },
992- "@trivago/prettier-plugin-sort-imports": {
993- "optional": true
994- },
995- "@zackad/prettier-plugin-twig-melody": {
996- "optional": true
997- },
998- "prettier-plugin-astro": {
999- "optional": true
1000- },
1001- "prettier-plugin-css-order": {
1002- "optional": true
1003- },
1004- "prettier-plugin-import-sort": {
1005- "optional": true
1006- },
1007- "prettier-plugin-jsdoc": {
1008- "optional": true
1009- },
1010- "prettier-plugin-marko": {
1011- "optional": true
1012- },
1013- "prettier-plugin-organize-attributes": {
1014- "optional": true
1015- },
1016- "prettier-plugin-organize-imports": {
1017- "optional": true
1018- },
1019- "prettier-plugin-sort-imports": {
1020- "optional": true
1021- },
1022- "prettier-plugin-style-order": {
1023- "optional": true
1024- },
1025- "prettier-plugin-svelte": {
1026- "optional": true
1027- }
1028- }
1029- },
1030- "node_modules/queue-microtask": {
1031- "version": "1.2.3",
1032- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
1033- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
1034- "dev": true,
1035- "funding": [
1036- {
1037- "type": "github",
1038- "url": "https://github.com/sponsors/feross"
1039- },
1040- {
1041- "type": "patreon",
1042- "url": "https://www.patreon.com/feross"
1043- },
1044- {
1045- "type": "consulting",
1046- "url": "https://feross.org/support"
1047- }
1048- ]
1049- },
1050- "node_modules/read-cache": {
1051- "version": "1.0.0",
1052- "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
1053- "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
1054- "dev": true,
1055- "dependencies": {
1056- "pify": "^2.3.0"
1057- }
1058- },
1059- "node_modules/readdirp": {
1060- "version": "3.6.0",
1061- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
1062- "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
1063- "dev": true,
1064- "dependencies": {
1065- "picomatch": "^2.2.1"
1066- },
1067- "engines": {
1068- "node": ">=8.10.0"
1069- }
1070- },
1071- "node_modules/resolve": {
1072- "version": "1.22.8",
1073- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
1074- "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
1075- "dev": true,
1076- "dependencies": {
1077- "is-core-module": "^2.13.0",
1078- "path-parse": "^1.0.7",
1079- "supports-preserve-symlinks-flag": "^1.0.0"
1080- },
1081- "bin": {
1082- "resolve": "bin/resolve"
1083- },
1084- "funding": {
1085- "url": "https://github.com/sponsors/ljharb"
1086- }
1087- },
1088- "node_modules/reusify": {
1089- "version": "1.0.4",
1090- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
1091- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
1092- "dev": true,
1093- "engines": {
1094- "iojs": ">=1.0.0",
1095- "node": ">=0.10.0"
1096- }
1097- },
1098- "node_modules/run-parallel": {
1099- "version": "1.2.0",
1100- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
1101- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
1102- "dev": true,
1103- "funding": [
1104- {
1105- "type": "github",
1106- "url": "https://github.com/sponsors/feross"
1107- },
1108- {
1109- "type": "patreon",
1110- "url": "https://www.patreon.com/feross"
1111- },
1112- {
1113- "type": "consulting",
1114- "url": "https://feross.org/support"
1115- }
1116- ],
1117- "dependencies": {
1118- "queue-microtask": "^1.2.2"
1119- }
1120- },
1121- "node_modules/shebang-command": {
1122- "version": "2.0.0",
1123- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
1124- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
1125- "dev": true,
1126- "dependencies": {
1127- "shebang-regex": "^3.0.0"
1128- },
1129- "engines": {
1130- "node": ">=8"
1131- }
1132- },
1133- "node_modules/shebang-regex": {
1134- "version": "3.0.0",
1135- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
1136- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
1137- "dev": true,
1138- "engines": {
1139- "node": ">=8"
1140- }
1141- },
1142- "node_modules/signal-exit": {
1143- "version": "4.1.0",
1144- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
1145- "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
1146- "dev": true,
1147- "engines": {
1148- "node": ">=14"
1149- },
1150- "funding": {
1151- "url": "https://github.com/sponsors/isaacs"
1152- }
1153- },
1154- "node_modules/source-map-js": {
1155- "version": "1.2.0",
1156- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
1157- "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
1158- "dev": true,
1159- "engines": {
1160- "node": ">=0.10.0"
1161- }
1162- },
1163- "node_modules/string-width": {
1164- "version": "5.1.2",
1165- "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
1166- "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
1167- "dev": true,
1168- "dependencies": {
1169- "eastasianwidth": "^0.2.0",
1170- "emoji-regex": "^9.2.2",
1171- "strip-ansi": "^7.0.1"
1172- },
1173- "engines": {
1174- "node": ">=12"
1175- },
1176- "funding": {
1177- "url": "https://github.com/sponsors/sindresorhus"
1178- }
1179- },
1180- "node_modules/string-width-cjs": {
1181- "name": "string-width",
1182- "version": "4.2.3",
1183- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
1184- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
1185- "dev": true,
1186- "dependencies": {
1187- "emoji-regex": "^8.0.0",
1188- "is-fullwidth-code-point": "^3.0.0",
1189- "strip-ansi": "^6.0.1"
1190- },
1191- "engines": {
1192- "node": ">=8"
1193- }
1194- },
1195- "node_modules/string-width-cjs/node_modules/ansi-regex": {
1196- "version": "5.0.1",
1197- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
1198- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
1199- "dev": true,
1200- "engines": {
1201- "node": ">=8"
1202- }
1203- },
1204- "node_modules/string-width-cjs/node_modules/emoji-regex": {
1205- "version": "8.0.0",
1206- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
1207- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
1208- "dev": true
1209- },
1210- "node_modules/string-width-cjs/node_modules/strip-ansi": {
1211- "version": "6.0.1",
1212- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1213- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1214- "dev": true,
1215- "dependencies": {
1216- "ansi-regex": "^5.0.1"
1217- },
1218- "engines": {
1219- "node": ">=8"
1220- }
1221- },
1222- "node_modules/strip-ansi": {
1223- "version": "7.1.0",
1224- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
1225- "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
1226- "dev": true,
1227- "dependencies": {
1228- "ansi-regex": "^6.0.1"
1229- },
1230- "engines": {
1231- "node": ">=12"
1232- },
1233- "funding": {
1234- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
1235- }
1236- },
1237- "node_modules/strip-ansi-cjs": {
1238- "name": "strip-ansi",
1239- "version": "6.0.1",
1240- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1241- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1242- "dev": true,
1243- "dependencies": {
1244- "ansi-regex": "^5.0.1"
1245- },
1246- "engines": {
1247- "node": ">=8"
1248- }
1249- },
1250- "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
1251- "version": "5.0.1",
1252- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
1253- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
1254- "dev": true,
1255- "engines": {
1256- "node": ">=8"
1257- }
1258- },
1259- "node_modules/sucrase": {
1260- "version": "3.35.0",
1261- "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
1262- "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
1263- "dev": true,
1264- "dependencies": {
1265- "@jridgewell/gen-mapping": "^0.3.2",
1266- "commander": "^4.0.0",
1267- "glob": "^10.3.10",
1268- "lines-and-columns": "^1.1.6",
1269- "mz": "^2.7.0",
1270- "pirates": "^4.0.1",
1271- "ts-interface-checker": "^0.1.9"
1272- },
1273- "bin": {
1274- "sucrase": "bin/sucrase",
1275- "sucrase-node": "bin/sucrase-node"
1276- },
1277- "engines": {
1278- "node": ">=16 || 14 >=14.17"
1279- }
1280- },
1281- "node_modules/supports-preserve-symlinks-flag": {
1282- "version": "1.0.0",
1283- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
1284- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
1285- "dev": true,
1286- "engines": {
1287- "node": ">= 0.4"
1288- },
1289- "funding": {
1290- "url": "https://github.com/sponsors/ljharb"
1291- }
1292- },
1293- "node_modules/tailwindcss": {
1294- "version": "3.4.3",
1295- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz",
1296- "integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==",
1297- "dev": true,
1298- "dependencies": {
1299- "@alloc/quick-lru": "^5.2.0",
1300- "arg": "^5.0.2",
1301- "chokidar": "^3.5.3",
1302- "didyoumean": "^1.2.2",
1303- "dlv": "^1.1.3",
1304- "fast-glob": "^3.3.0",
1305- "glob-parent": "^6.0.2",
1306- "is-glob": "^4.0.3",
1307- "jiti": "^1.21.0",
1308- "lilconfig": "^2.1.0",
1309- "micromatch": "^4.0.5",
1310- "normalize-path": "^3.0.0",
1311- "object-hash": "^3.0.0",
1312- "picocolors": "^1.0.0",
1313- "postcss": "^8.4.23",
1314- "postcss-import": "^15.1.0",
1315- "postcss-js": "^4.0.1",
1316- "postcss-load-config": "^4.0.1",
1317- "postcss-nested": "^6.0.1",
1318- "postcss-selector-parser": "^6.0.11",
1319- "resolve": "^1.22.2",
1320- "sucrase": "^3.32.0"
1321- },
1322- "bin": {
1323- "tailwind": "lib/cli.js",
1324- "tailwindcss": "lib/cli.js"
1325- },
1326- "engines": {
1327- "node": ">=14.0.0"
1328- }
1329- },
1330- "node_modules/thenify": {
1331- "version": "3.3.1",
1332- "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
1333- "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
1334- "dev": true,
1335- "dependencies": {
1336- "any-promise": "^1.0.0"
1337- }
1338- },
1339- "node_modules/thenify-all": {
1340- "version": "1.6.0",
1341- "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
1342- "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
1343- "dev": true,
1344- "dependencies": {
1345- "thenify": ">= 3.1.0 < 4"
1346- },
1347- "engines": {
1348- "node": ">=0.8"
1349- }
1350- },
1351- "node_modules/to-regex-range": {
1352- "version": "5.0.1",
1353- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
1354- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
1355- "dev": true,
1356- "dependencies": {
1357- "is-number": "^7.0.0"
1358- },
1359- "engines": {
1360- "node": ">=8.0"
1361- }
1362- },
1363- "node_modules/ts-interface-checker": {
1364- "version": "0.1.13",
1365- "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
1366- "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
1367- "dev": true
1368- },
1369- "node_modules/util-deprecate": {
1370- "version": "1.0.2",
1371- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
1372- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
1373- "dev": true
1374- },
1375- "node_modules/which": {
1376- "version": "2.0.2",
1377- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
1378- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
1379- "dev": true,
1380- "dependencies": {
1381- "isexe": "^2.0.0"
1382- },
1383- "bin": {
1384- "node-which": "bin/node-which"
1385- },
1386- "engines": {
1387- "node": ">= 8"
1388- }
1389- },
1390- "node_modules/wrap-ansi": {
1391- "version": "8.1.0",
1392- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
1393- "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
1394- "dev": true,
1395- "dependencies": {
1396- "ansi-styles": "^6.1.0",
1397- "string-width": "^5.0.1",
1398- "strip-ansi": "^7.0.1"
1399- },
1400- "engines": {
1401- "node": ">=12"
1402- },
1403- "funding": {
1404- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
1405- }
1406- },
1407- "node_modules/wrap-ansi-cjs": {
1408- "name": "wrap-ansi",
1409- "version": "7.0.0",
1410- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
1411- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
1412- "dev": true,
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- "engines": {
1431- "node": ">=8"
1432- }
1433- },
1434- "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
1435- "version": "4.3.0",
1436- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
1437- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
1438- "dev": true,
1439- "dependencies": {
1440- "color-convert": "^2.0.1"
1441- },
1442- "engines": {
1443- "node": ">=8"
1444- },
1445- "funding": {
1446- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
1447- }
1448- },
1449- "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
1450- "version": "8.0.0",
1451- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
1452- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
1453- "dev": true
1454- },
1455- "node_modules/wrap-ansi-cjs/node_modules/string-width": {
1456- "version": "4.2.3",
1457- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
1458- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
1459- "dev": true,
1460- "dependencies": {
1461- "emoji-regex": "^8.0.0",
1462- "is-fullwidth-code-point": "^3.0.0",
1463- "strip-ansi": "^6.0.1"
1464- },
1465- "engines": {
1466- "node": ">=8"
1467- }
1468- },
1469- "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
1470- "version": "6.0.1",
1471- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1472- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1473- "dev": true,
1474- "dependencies": {
1475- "ansi-regex": "^5.0.1"
1476- },
1477- "engines": {
1478- "node": ">=8"
1479- }
1480- },
1481- "node_modules/yaml": {
1482- "version": "2.4.1",
1483- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz",
1484- "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==",
1485- "dev": true,
1486- "bin": {
1487- "yaml": "bin.mjs"
1488- },
1489- "engines": {
1490- "node": ">= 14"
1491- }
1492- }
1493- }
1494-}
M package.json +4 -4
@@ -1,16 +1,16 @@
11 {
22 "devDependencies": {
33 "@catppuccin/tailwindcss": "^0.1.6",
4- "prettier": "^3.0.3",
5- "prettier-plugin-tailwindcss": "^0.5.5",
6- "tailwindcss": "^3.3.3"
4+ "prettier": "^3.3.3",
5+ "prettier-plugin-tailwindcss": "^0.5.14",
6+ "tailwindcss": "^3.4.14"
77 },
88 "scripts": {
99 "build:css": "tailwindcss build src/styles.css -o dist/styles.css",
1010 "dev:css": "tailwindcss -i internal/webui/public/assets/css/custom.css -o internal/webui/public/assets/css/tailwind.css --watch"
1111 },
1212 "dependencies": {
13- "caniuse-lite": "^1.0.30001653",
13+ "caniuse-lite": "^1.0.30001669",
1414 "dotenv": "^16.4.5"
1515 }
1616 }
@@ -1,16 +1,16 @@
1 {1 {
2 "devDependencies": {2 "devDependencies": {
3 "@catppuccin/tailwindcss": "^0.1.6",3 "@catppuccin/tailwindcss": "^0.1.6",
4- "prettier": "^3.0.3",4+ "prettier": "^3.3.3",
5- "prettier-plugin-tailwindcss": "^0.5.5",5+ "prettier-plugin-tailwindcss": "^0.5.14",
6- "tailwindcss": "^3.3.3"6+ "tailwindcss": "^3.4.14"
7 },7 },
8 "scripts": {8 "scripts": {
9 "build:css": "tailwindcss build src/styles.css -o dist/styles.css",9 "build:css": "tailwindcss build src/styles.css -o dist/styles.css",
10 "dev:css": "tailwindcss -i internal/webui/public/assets/css/custom.css -o internal/webui/public/assets/css/tailwind.css --watch"10 "dev:css": "tailwindcss -i internal/webui/public/assets/css/custom.css -o internal/webui/public/assets/css/tailwind.css --watch"
11 },11 },
12 "dependencies": {12 "dependencies": {
13- "caniuse-lite": "^1.0.30001653",13+ "caniuse-lite": "^1.0.30001669",
14 "dotenv": "^16.4.5"14 "dotenv": "^16.4.5"
15 }15 }
16 }16 }
R pkg/sanitize/htmlsanitizer.go → pkg/sanitize/html_sanitizer.go +0 -0 renamed, 100% similar

renamed, 100% similar

R pkg/sqlite/createdb.go → pkg/sqlite/db_create.go +0 -0 renamed, 100% similar

renamed, 100% similar

R pkg/store/storeimages.go → pkg/store/store_images.go +0 -0 renamed, 100% similar

renamed, 100% similar

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close