diff --git a/cmd/cli/config/list.go b/cmd/cli/config/list.go index c3d970b132..905f443811 100644 --- a/cmd/cli/config/list.go +++ b/cmd/cli/config/list.go @@ -41,7 +41,7 @@ Each key shown can be used with: if err != nil { return err } - log.Info().Msgf("Config loaded from: %s, and with data-dir %s", cfg.Paths(), cfg.Get(types.DataDirKey)) + log.Debug().Msgf("Config loaded from: %s, and with data-dir %s", cfg.Paths(), cfg.Get(types.DataDirKey)) return list(cmd, cfg, o) }, } diff --git a/cmd/cli/devstack/devstack.go b/cmd/cli/devstack/devstack.go index 8eb9102566..80fb3ed4d2 100644 --- a/cmd/cli/devstack/devstack.go +++ b/cmd/cli/devstack/devstack.go @@ -6,6 +6,7 @@ import ( "path/filepath" "strconv" + "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/spf13/viper" "k8s.io/kubectl/pkg/util/i18n" @@ -103,9 +104,7 @@ func NewCmd() *cobra.Command { RunE: func(cmd *cobra.Command, _ []string) error { // TODO: a hack to force debug logging for devstack // until I figure out why flags and env vars are not working - if err := logger.ConfigureLogging(string(logger.LogModeDefault), "debug"); err != nil { - return fmt.Errorf("failed to configure logging: %w", err) - } + logger.ConfigureLogging(logger.LogModeDefault, zerolog.DebugLevel) return runDevstack(cmd, ODs) }, } diff --git a/cmd/cli/root.go b/cmd/cli/root.go index 9677911d71..8df28fa5ee 100644 --- a/cmd/cli/root.go +++ b/cmd/cli/root.go @@ -76,15 +76,11 @@ func NewRootCmd() *cobra.Command { // While we allow users to configure logging via the config file, they are applied // and will override this configuration at a later stage when the config is loaded. // This is needed to ensure any logs before the config is loaded are captured. - logMode := viper.GetString(types.LoggingModeKey) - if logMode == "" { - logMode = string(logger.LogModeDefault) - } logLevel := viper.GetString(types.LoggingLevelKey) if logLevel == "" { logLevel = "Info" } - if err := logger.ConfigureLogging(logMode, logLevel); err != nil { + if err := logger.ParseAndConfigureLogging(string(logger.LogModeCmd), logLevel); err != nil { return fmt.Errorf("failed to configure logging: %w", err) } diff --git a/cmd/cli/serve/serve.go b/cmd/cli/serve/serve.go index 2ca436e133..8886b58ae4 100644 --- a/cmd/cli/serve/serve.go +++ b/cmd/cli/serve/serve.go @@ -95,6 +95,10 @@ func NewCmd() *cobra.Command { return fmt.Errorf("failed to setup config: %w", err) } + if err = logger.ParseAndConfigureLogging(cfg.Logging.Mode, cfg.Logging.Level); err != nil { + return fmt.Errorf("failed to configure logging: %w", err) + } + log.Info().Msgf("Config loaded from: %s, and with data-dir %s", rawCfg.Paths(), rawCfg.Get(types.DataDirKey)) @@ -103,7 +107,6 @@ func NewCmd() *cobra.Command { if err != nil { return fmt.Errorf("failed to reconcile repo: %w", err) } - return serve(cmd, cfg, fsr) }, } diff --git a/cmd/util/repo.go b/cmd/util/repo.go index 042041a056..a295d53661 100644 --- a/cmd/util/repo.go +++ b/cmd/util/repo.go @@ -12,6 +12,7 @@ import ( "github.com/bacalhau-project/bacalhau/cmd/util/hook" "github.com/bacalhau-project/bacalhau/pkg/config" "github.com/bacalhau-project/bacalhau/pkg/config/types" + "github.com/bacalhau-project/bacalhau/pkg/logger" "github.com/bacalhau-project/bacalhau/pkg/repo" "github.com/bacalhau-project/bacalhau/pkg/setup" ) @@ -75,6 +76,12 @@ func SetupConfigType(cmd *cobra.Command) (*config.Config, error) { if err != nil { return nil, err } + + // We always apply the configured logging level. Logging mode on the other hand is only applied with serve cmd + if err = logger.ParseAndConfigureLoggingLevel(cfg.Get(types.LoggingLevelKey).(string)); err != nil { + return nil, fmt.Errorf("failed to configure logging: %w", err) + } + return cfg, nil } diff --git a/ops/terraform/dev.tfvars b/ops/terraform/dev.tfvars index d1dbfa7e0b..cf966dcb6a 100644 --- a/ops/terraform/dev.tfvars +++ b/ops/terraform/dev.tfvars @@ -1,8 +1,8 @@ -bacalhau_version = "v1.4.0" +bacalhau_version = "v1.5.0" bacalhau_branch = "" bacalhau_port = "1235" bacalhau_environment = "development" -ipfs_version = "v0.12.2" +ipfs_version = "v0.18.1" gcp_project = "bacalhau-dev" grafana_cloud_prometheus_user = "14299" grafana_cloud_prometheus_endpoint = "https://prometheus-us-central1.grafana.net/api/prom/push" diff --git a/ops/terraform/main.tf b/ops/terraform/main.tf index ec6c73d682..da5d9fa6d5 100644 --- a/ops/terraform/main.tf +++ b/ops/terraform/main.tf @@ -67,11 +67,10 @@ export GRAFANA_CLOUD_TEMPO_ENDPOINT="${var.grafana_cloud_tempo_endpoint}" export OTEL_COLLECTOR_VERSION="${var.otel_collector_version}" export OTEL_EXPORTER_OTLP_ENDPOINT="${var.otel_collector_endpoint}" export OTEL_RESOURCE_ATTRIBUTES="deployment.environment=${terraform.workspace}" -export BACALHAU_NODE_NETWORK_ORCHESTRATORS="${var.internal_ip_addresses[0]}:4222" -export BACALHAU_NODE_NETWORK_ADVERTISEDADDRESS="${var.public_ip_addresses[count.index]}:4222" -export BACALHAU_NODE_NETWORK_CLUSTER_PEERS="" +export BACALHAU_ORCHESTRATORS="${var.internal_ip_addresses[0]}:4222" +export BACALHAU_ORCHESTRATOR_ADVERTISE="${var.public_ip_addresses[count.index]}:4222" export BACALHAU_LOCAL_PUBLISHER_ADDRESS="${var.public_ip_addresses[count.index]}" - +export BACALHAU_WEBUI_BACKEND="http://${var.public_ip_addresses[0]}:1234" ### secrets are installed in the install-node.sh script export SECRETS_GRAFANA_CLOUD_PROMETHEUS_API_KEY="${var.grafana_cloud_prometheus_api_key}" diff --git a/ops/terraform/prod.tfvars b/ops/terraform/prod.tfvars index f123692123..c626227559 100644 --- a/ops/terraform/prod.tfvars +++ b/ops/terraform/prod.tfvars @@ -1,7 +1,7 @@ -bacalhau_version = "v1.4.0" +bacalhau_version = "v1.5.0" bacalhau_port = "1235" bacalhau_environment = "production" -ipfs_version = "v0.12.2" +ipfs_version = "v0.18.1" gcp_project = "bacalhau-prod" grafana_cloud_prometheus_user = "1008771" grafana_cloud_prometheus_endpoint = "https://prometheus-us-central1.grafana.net/api/prom/push" diff --git a/ops/terraform/remote_files/scripts/start-bacalhau.sh b/ops/terraform/remote_files/scripts/start-bacalhau.sh index 318faefd82..252fbb148c 100644 --- a/ops/terraform/remote_files/scripts/start-bacalhau.sh +++ b/ops/terraform/remote_files/scripts/start-bacalhau.sh @@ -36,12 +36,14 @@ bacalhau serve \ --job-execution-timeout-bypass-client-id="${TRUSTED_CLIENT_IDS}" \ --ipfs-connect /ip4/127.0.0.1/tcp/5001 \ --api-port 1234 \ - --web-ui="${BACALHAU_NODE_WEBUI}" \ - --web-ui-port 80 \ - --labels owner=bacalhau \ --requester-job-translation-enabled \ - --config Job.Defaults.Batch.Task.Publisher.Type=local \ - --config Job.Defaults.Ops.Task.Publisher.Type=local \ - --config Job.Defaults.Service.Task.Publisher.Type=local \ - --config Job.Defaults.Daemon.Task.Publisher.Type=local \ - --local-publisher-address "${BACALHAU_LOCAL_PUBLISHER_ADDRESS}" + --config DisableAnalytics \ + --config labels="owner=bacalhau,name=node-${TERRAFORM_NODE_INDEX}"\ + --config Compute.Orchestrators="${BACALHAU_ORCHESTRATORS}" \ + --config Orchestrator.Advertise="${BACALHAU_ORCHESTRATOR_ADVERTISE}" \ + --config WebUI.Enabled="${BACALHAU_NODE_WEBUI}" \ + --config WebUI.Listen=0.0.0.0:80 \ + --config WebUI.Backend="${BACALHAU_WEBUI_BACKEND}" \ + --config JobDefaults.Batch.Task.Publisher.Type=local \ + --config JobDefaults.Ops.Task.Publisher.Type=local \ + --config Publishers.Types.Local.Address="${BACALHAU_LOCAL_PUBLISHER_ADDRESS}" diff --git a/ops/terraform/stage.tfvars b/ops/terraform/stage.tfvars index 544b263869..628f78e0ee 100644 --- a/ops/terraform/stage.tfvars +++ b/ops/terraform/stage.tfvars @@ -1,8 +1,8 @@ -bacalhau_version = "v1.5.0-dev2" +bacalhau_version = "v1.5.0" bacalhau_branch = "" # deploy from a branch instead of the version above bacalhau_port = "1235" bacalhau_environment = "staging" -ipfs_version = "v0.12.2" +ipfs_version = "v0.18.1" gcp_project = "bacalhau-stage" grafana_cloud_prometheus_user = "1008771" grafana_cloud_prometheus_endpoint = "https://prometheus-us-central1.grafana.net/api/prom/push" diff --git a/pkg/logger/logger.go b/pkg/logger/logger.go index c053cd9b94..dc34a033c0 100644 --- a/pkg/logger/logger.go +++ b/pkg/logger/logger.go @@ -13,6 +13,7 @@ import ( "runtime/debug" "strconv" "strings" + "sync" "time" "github.com/rs/zerolog/pkgerrors" @@ -29,22 +30,31 @@ type LogMode string // Available logging modes const ( - LogModeDefault LogMode = "default" - LogModeStation LogMode = "station" - LogModeJSON LogMode = "json" - LogModeCombined LogMode = "combined" - LogModeEvent LogMode = "event" + LogModeDefault LogMode = "default" + LogModeJSON LogMode = "json" + LogModeCmd LogMode = "cmd" +) + +var ( + logMu sync.Mutex ) func ParseLogMode(s string) (LogMode, error) { - lm := []LogMode{LogModeDefault, LogModeStation, LogModeJSON, LogModeCombined, LogModeEvent} + lm := []LogMode{LogModeDefault, LogModeJSON, LogModeCmd} for _, logMode := range lm { if strings.ToLower(s) == strings.ToLower(string(logMode)) { return logMode, nil } } - return "Error", fmt.Errorf("%q is an invalid log-mode (valid modes: %q)", - s, lm) + return "", fmt.Errorf("%q is an invalid log-mode (valid modes: %q)", s, lm) +} + +func ParseLogLevel(s string) (zerolog.Level, error) { + l, err := zerolog.ParseLevel(s) + if err != nil { + return l, fmt.Errorf("%q is an invalid log-level", s) + } + return l, nil } var nodeIDFieldName = "NodeID" @@ -57,12 +67,14 @@ func init() { //nolint:gochecknoinits strings.HasSuffix(os.Args[0], ".test") || flag.Lookup("test.v") != nil || flag.Lookup("test.run") != nil { - configureLogging(zerolog.DebugLevel, defaultLogging()) + ConfigureLoggingLevel(zerolog.DebugLevel) + configureLogging(defaultLogging()) return } // the default log level when not running a test is ERROR - configureLogging(zerolog.ErrorLevel, bufferLogs()) + ConfigureLoggingLevel(zerolog.ErrorLevel) + configureLogging(bufferLogs()) } func ErrOrDebug(err error) zerolog.Level { @@ -82,46 +94,66 @@ type tTesting interface { func ConfigureTestLogging(t tTesting) { oldLogger := log.Logger oldContextLogger := zerolog.DefaultContextLogger - configureLogging(zerolog.DebugLevel, zerolog.NewConsoleWriter(zerolog.ConsoleTestWriter(t), defaultLogFormat)) + ConfigureLoggingLevel(zerolog.DebugLevel) + configureLogging(zerolog.NewConsoleWriter(zerolog.ConsoleTestWriter(t), defaultLogFormat)) t.Cleanup(func() { log.Logger = oldLogger zerolog.DefaultContextLogger = oldContextLogger }) } -func ConfigureLogging(modeStr, levelStr string) error { - logModeConfig := defaultLogging() - +func ParseAndConfigureLogging(modeStr, levelStr string) error { mode, err := ParseLogMode(modeStr) if err != nil { - return fmt.Errorf("invalid log mode: %w", err) + return err } - level, err := zerolog.ParseLevel(levelStr) + level, err := ParseLogLevel(levelStr) if err != nil { - return fmt.Errorf("invalid log level: %w", err) + return err } + ConfigureLogging(mode, level) + return nil +} + +func ConfigureLogging(mode LogMode, level zerolog.Level) { + var logWriter io.Writer switch mode { case LogModeDefault: - logModeConfig = defaultLogging() - case LogModeStation: - logModeConfig = defaultStationLogging() + logWriter = defaultLogging() case LogModeJSON: - logModeConfig = jsonLogging() - case LogModeEvent: - logModeConfig = eventLogging() - case LogModeCombined: - logModeConfig = combinedLogging() + logWriter = jsonLogging() + case LogModeCmd: + logWriter = clientLogging() + default: + logWriter = defaultLogging() } - configureLogging(level, logModeConfig) - LogBufferedLogs(logModeConfig) + ConfigureLoggingLevel(level) + configureLogging(logWriter) + LogBufferedLogs(logWriter) +} + +func ParseAndConfigureLoggingLevel(level string) error { + l, err := ParseLogLevel(level) + if err != nil { + return err + } + ConfigureLoggingLevel(l) return nil } -func configureLogging(level zerolog.Level, logWriter io.Writer) { - zerolog.TimeFieldFormat = time.RFC3339Nano +func ConfigureLoggingLevel(level zerolog.Level) { + logMu.Lock() + defer logMu.Unlock() zerolog.SetGlobalLevel(level) +} + +func configureLogging(logWriter io.Writer) { + logMu.Lock() + defer logMu.Unlock() + + zerolog.TimeFieldFormat = time.RFC3339Nano info, ok := debug.ReadBuildInfo() if ok && info.Main.Path != "" { @@ -148,21 +180,13 @@ func jsonLogging() io.Writer { return os.Stdout } -func eventLogging() io.Writer { - return io.Discard -} - -func combinedLogging() io.Writer { - return zerolog.MultiLevelWriter(defaultLogging(), os.Stdout) -} - func defaultLogging() io.Writer { return zerolog.NewConsoleWriter(defaultLogFormat) } func defaultLogFormat(w *zerolog.ConsoleWriter) { isTerminal := isatty.IsTerminal(os.Stdout.Fd()) - w.Out = os.Stderr + w.Out = os.Stdout w.NoColor = !isTerminal w.TimeFormat = "15:04:05.999 |" w.PartsOrder = []string{ @@ -187,25 +211,10 @@ func defaultLogFormat(w *zerolog.ConsoleWriter) { } } -func defaultStationLogging() io.Writer { +func clientLogging() io.Writer { return zerolog.NewConsoleWriter(func(w *zerolog.ConsoleWriter) { - isTerminal := isatty.IsTerminal(os.Stdout.Fd()) - w.Out = os.Stdout - w.NoColor = !isTerminal - w.PartsOrder = []string{ - zerolog.LevelFieldName, - zerolog.MessageFieldName, - } - - w.FormatLevel = func(i interface{}) string { - return strings.ToUpper(i.(string)) + ":" - } - w.FormatErrFieldName = func(i interface{}) string { - return "- " - } - w.FormatErrFieldValue = func(i interface{}) string { - return strings.Trim(i.(string), "\"") - } + defaultLogFormat(w) + w.PartsOrder = []string{zerolog.MessageFieldName} }) } diff --git a/pkg/logger/logger_test.go b/pkg/logger/logger_test.go index ac25c6536d..7786c4b979 100644 --- a/pkg/logger/logger_test.go +++ b/pkg/logger/logger_test.go @@ -23,7 +23,8 @@ func TestConfigureLogging(t *testing.T) { }) var logging strings.Builder - configureLogging(zerolog.InfoLevel, zerolog.NewConsoleWriter(func(w *zerolog.ConsoleWriter) { + ConfigureLoggingLevel(zerolog.InfoLevel) + configureLogging(zerolog.NewConsoleWriter(func(w *zerolog.ConsoleWriter) { defaultLogFormat(w) w.Out = &logging w.NoColor = true @@ -40,3 +41,66 @@ func TestConfigureLogging(t *testing.T) { assert.Contains(t, actual, "pkg/logger/testpackage/subpackage/subsubpackage/testutil.go", "Log statement doesn't contain the full package path") assert.Contains(t, actual, `stack:[{"func":"TestLog","line":`, "Log statement didn't automatically include the error's stacktrace") } + +func TestParseAndConfigureLogging(t *testing.T) { + err := ParseAndConfigureLogging("default", "debug") + assert.NoError(t, err) + assert.Equal(t, zerolog.DebugLevel, zerolog.GlobalLevel()) + + err = ParseAndConfigureLogging("json", "info") + assert.NoError(t, err) + assert.Equal(t, zerolog.InfoLevel, zerolog.GlobalLevel()) + + err = ParseAndConfigureLogging("invalid", "error") + assert.Error(t, err) + + err = ParseAndConfigureLogging("default", "invalid") + assert.Error(t, err) +} + +func TestParseLogMode(t *testing.T) { + tests := []struct { + input string + expected LogMode + hasError bool + }{ + {"default", LogModeDefault, false}, + {"json", LogModeJSON, false}, + {"cmd", LogModeCmd, false}, + {"invalid", "", true}, + } + + for _, test := range tests { + result, err := ParseLogMode(test.input) + if test.hasError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, test.expected, result) + } + } +} + +func TestParseLogLevel(t *testing.T) { + tests := []struct { + input string + expected zerolog.Level + hasError bool + }{ + {"debug", zerolog.DebugLevel, false}, + {"info", zerolog.InfoLevel, false}, + {"warn", zerolog.WarnLevel, false}, + {"error", zerolog.ErrorLevel, false}, + {"invalid", zerolog.NoLevel, true}, + } + + for _, test := range tests { + result, err := ParseLogLevel(test.input) + if test.hasError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, test.expected, result) + } + } +} diff --git a/pkg/publicapi/apimodels/error.go b/pkg/publicapi/apimodels/error.go index 6d2bc98bfd..842fe5734e 100644 --- a/pkg/publicapi/apimodels/error.go +++ b/pkg/publicapi/apimodels/error.go @@ -2,7 +2,6 @@ package apimodels import ( "encoding/json" - "errors" "fmt" "io" "net/http" @@ -67,23 +66,29 @@ func (e *APIError) Error() string { } // Parse HTTP Resposne to APIError -func FromHttpResponse(resp *http.Response) (*APIError, error) { - +func GenerateAPIErrorFromHTTPResponse(resp *http.Response) *APIError { if resp == nil { - return nil, errors.New("response is nil, cannot be unmarsheld to APIError") + return NewAPIError(0, "API call error, invalid response") } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { - return nil, fmt.Errorf("error reading response body: %w", err) + return NewAPIError( + resp.StatusCode, + fmt.Sprintf("Unable to read API call response body. Error: %q", err.Error())) } var apiErr APIError err = json.Unmarshal(body, &apiErr) if err != nil { - return nil, fmt.Errorf("error parsing response body: %w", err) + return NewAPIError( + resp.StatusCode, + fmt.Sprintf("Unable to parse API call response body. Error: %q. Body received: %q", + err.Error(), + string(body), + )) } // If the JSON didn't include a status code, use the HTTP Status @@ -91,7 +96,7 @@ func FromHttpResponse(resp *http.Response) (*APIError, error) { apiErr.HTTPStatusCode = resp.StatusCode } - return &apiErr, nil + return &apiErr } // FromBacError converts a bacerror.Error to an APIError diff --git a/pkg/publicapi/client/v2/client.go b/pkg/publicapi/client/v2/client.go index 18f687ed34..95979028be 100644 --- a/pkg/publicapi/client/v2/client.go +++ b/pkg/publicapi/client/v2/client.go @@ -74,18 +74,12 @@ func (c *httpClient) Get(ctx context.Context, endpoint string, in apimodels.GetR return apimodels.NewUnauthorizedError("invalid token") } - var apiError *apimodels.APIError if resp.StatusCode != http.StatusOK { - apiError, err = apimodels.FromHttpResponse(resp) - if err != nil { - return err + if apiError := apimodels.GenerateAPIErrorFromHTTPResponse(resp); apiError != nil { + return apiError } } - if apiError != nil { - return apiError - } - defer resp.Body.Close() if out != nil { @@ -116,18 +110,12 @@ func (c *httpClient) write(ctx context.Context, verb, endpoint string, in apimod return apimodels.ErrInvalidToken } - var apiError *apimodels.APIError if resp.StatusCode != http.StatusOK { - apiError, err = apimodels.FromHttpResponse(resp) - if err != nil { - return err + if apiError := apimodels.GenerateAPIErrorFromHTTPResponse(resp); apiError != nil { + return apiError } } - if apiError != nil { - return apiError - } - if out != nil { if err := decodeBody(resp, &out); err != nil { return err @@ -362,12 +350,13 @@ func (c *httpClient) interceptError(ctx context.Context, err error, resp *http.R WithCode(bacerrors.UnauthorizedError) } - apiError, apiErr := apimodels.FromHttpResponse(resp) - if apiErr == nil { + apiError := apimodels.GenerateAPIErrorFromHTTPResponse(resp) + if apiError != nil { return apiError.ToBacError() } - return bacerrors.Wrap(apiErr, "server error"). + return bacerrors.New("server error"). + WithHTTPStatusCode(http.StatusInternalServerError). WithCode(bacerrors.InternalError) } diff --git a/pkg/setup/setup.go b/pkg/setup/setup.go index 345268831e..d270600bec 100644 --- a/pkg/setup/setup.go +++ b/pkg/setup/setup.go @@ -9,7 +9,6 @@ import ( "github.com/bacalhau-project/bacalhau/pkg/config" "github.com/bacalhau-project/bacalhau/pkg/config/types" - "github.com/bacalhau-project/bacalhau/pkg/logger" "github.com/bacalhau-project/bacalhau/pkg/repo/migrations" "github.com/bacalhau-project/bacalhau/pkg/repo" @@ -25,9 +24,6 @@ func SetupMigrationManager() (*repo.MigrationManager, error) { // SetupBacalhauRepo ensures that a bacalhau repo and config exist and are initialized. func SetupBacalhauRepo(cfg types.Bacalhau) (*repo.FsRepo, error) { - if err := logger.ConfigureLogging(cfg.Logging.Mode, cfg.Logging.Level); err != nil { - return nil, fmt.Errorf("failed to configure logging: %w", err) - } migrationManger, err := SetupMigrationManager() if err != nil { return nil, fmt.Errorf("failed to create migration manager: %w", err) diff --git a/webui/package.json b/webui/package.json index 6f4ad63331..114b626a3a 100644 --- a/webui/package.json +++ b/webui/package.json @@ -27,7 +27,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "lucide-react": "^0.438.0", - "next": "14.2.7", + "next": "14.2.10", "next-themes": "^0.3.0", "react": "^18", "react-dom": "^18", diff --git a/webui/yarn.lock b/webui/yarn.lock index f645055fda..bbbe05d0bc 100644 --- a/webui/yarn.lock +++ b/webui/yarn.lock @@ -223,10 +223,10 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:14.2.7": - version: 14.2.7 - resolution: "@next/env@npm:14.2.7" - checksum: 10c0/1cda023007acda4d47036a25fba0e039d9b2df9c3770651dc289207e0537506675546c02b5b574fe92bb1adc1c887d948d5cb630673aa572754278b82d150b7e +"@next/env@npm:14.2.10": + version: 14.2.10 + resolution: "@next/env@npm:14.2.10" + checksum: 10c0/e13ad3bb18f576a62a011f08393bd20cf025c3e3aa378d9df5c10f53b63a6eacd43b47aee00ffc8b2eb7988e4af58a1e1504a8e115aad753b35f3ee1cdbbc37a languageName: node linkType: hard @@ -239,65 +239,65 @@ __metadata: languageName: node linkType: hard -"@next/swc-darwin-arm64@npm:14.2.7": - version: 14.2.7 - resolution: "@next/swc-darwin-arm64@npm:14.2.7" +"@next/swc-darwin-arm64@npm:14.2.10": + version: 14.2.10 + resolution: "@next/swc-darwin-arm64@npm:14.2.10" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@next/swc-darwin-x64@npm:14.2.7": - version: 14.2.7 - resolution: "@next/swc-darwin-x64@npm:14.2.7" +"@next/swc-darwin-x64@npm:14.2.10": + version: 14.2.10 + resolution: "@next/swc-darwin-x64@npm:14.2.10" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@next/swc-linux-arm64-gnu@npm:14.2.7": - version: 14.2.7 - resolution: "@next/swc-linux-arm64-gnu@npm:14.2.7" +"@next/swc-linux-arm64-gnu@npm:14.2.10": + version: 14.2.10 + resolution: "@next/swc-linux-arm64-gnu@npm:14.2.10" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:14.2.7": - version: 14.2.7 - resolution: "@next/swc-linux-arm64-musl@npm:14.2.7" +"@next/swc-linux-arm64-musl@npm:14.2.10": + version: 14.2.10 + resolution: "@next/swc-linux-arm64-musl@npm:14.2.10" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:14.2.7": - version: 14.2.7 - resolution: "@next/swc-linux-x64-gnu@npm:14.2.7" +"@next/swc-linux-x64-gnu@npm:14.2.10": + version: 14.2.10 + resolution: "@next/swc-linux-x64-gnu@npm:14.2.10" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:14.2.7": - version: 14.2.7 - resolution: "@next/swc-linux-x64-musl@npm:14.2.7" +"@next/swc-linux-x64-musl@npm:14.2.10": + version: 14.2.10 + resolution: "@next/swc-linux-x64-musl@npm:14.2.10" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:14.2.7": - version: 14.2.7 - resolution: "@next/swc-win32-arm64-msvc@npm:14.2.7" +"@next/swc-win32-arm64-msvc@npm:14.2.10": + version: 14.2.10 + resolution: "@next/swc-win32-arm64-msvc@npm:14.2.10" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@next/swc-win32-ia32-msvc@npm:14.2.7": - version: 14.2.7 - resolution: "@next/swc-win32-ia32-msvc@npm:14.2.7" +"@next/swc-win32-ia32-msvc@npm:14.2.10": + version: 14.2.10 + resolution: "@next/swc-win32-ia32-msvc@npm:14.2.10" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@next/swc-win32-x64-msvc@npm:14.2.7": - version: 14.2.7 - resolution: "@next/swc-win32-x64-msvc@npm:14.2.7" +"@next/swc-win32-x64-msvc@npm:14.2.10": + version: 14.2.10 + resolution: "@next/swc-win32-x64-msvc@npm:14.2.10" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -4071,20 +4071,20 @@ __metadata: languageName: node linkType: hard -"next@npm:14.2.7": - version: 14.2.7 - resolution: "next@npm:14.2.7" - dependencies: - "@next/env": "npm:14.2.7" - "@next/swc-darwin-arm64": "npm:14.2.7" - "@next/swc-darwin-x64": "npm:14.2.7" - "@next/swc-linux-arm64-gnu": "npm:14.2.7" - "@next/swc-linux-arm64-musl": "npm:14.2.7" - "@next/swc-linux-x64-gnu": "npm:14.2.7" - "@next/swc-linux-x64-musl": "npm:14.2.7" - "@next/swc-win32-arm64-msvc": "npm:14.2.7" - "@next/swc-win32-ia32-msvc": "npm:14.2.7" - "@next/swc-win32-x64-msvc": "npm:14.2.7" +"next@npm:14.2.10": + version: 14.2.10 + resolution: "next@npm:14.2.10" + dependencies: + "@next/env": "npm:14.2.10" + "@next/swc-darwin-arm64": "npm:14.2.10" + "@next/swc-darwin-x64": "npm:14.2.10" + "@next/swc-linux-arm64-gnu": "npm:14.2.10" + "@next/swc-linux-arm64-musl": "npm:14.2.10" + "@next/swc-linux-x64-gnu": "npm:14.2.10" + "@next/swc-linux-x64-musl": "npm:14.2.10" + "@next/swc-win32-arm64-msvc": "npm:14.2.10" + "@next/swc-win32-ia32-msvc": "npm:14.2.10" + "@next/swc-win32-x64-msvc": "npm:14.2.10" "@swc/helpers": "npm:0.5.5" busboy: "npm:1.6.0" caniuse-lite: "npm:^1.0.30001579" @@ -4125,7 +4125,7 @@ __metadata: optional: true bin: next: dist/bin/next - checksum: 10c0/661ff5196f671d68ece76f3003d049848163cb21a946fe71673225e56f82726f647a1869085f010869a778e56dd601b9065221031823562aeb92026677f8a5fd + checksum: 10c0/a64991d44db2b6dcb3e7b780f14fe138fa97052767cf96a7733d1de4a857834e19a31fd5a742cca14201ad800bf03924d613e3d4e99932a1112bb9a03662f95a languageName: node linkType: hard @@ -5737,7 +5737,7 @@ __metadata: eslint-config-prettier: "npm:^9.1.0" eslint-plugin-prettier: "npm:^5.2.1" lucide-react: "npm:^0.438.0" - next: "npm:14.2.7" + next: "npm:14.2.10" next-themes: "npm:^0.3.0" openapi-typescript-codegen: "npm:^0.29.0" postcss: "npm:^8"