From 7c1213b71edabb4bf8460fe2dabaae2a933d0ab9 Mon Sep 17 00:00:00 2001 From: xy Date: Tue, 17 Dec 2024 02:34:39 +0900 Subject: [PATCH 01/10] feat(asset): add asset management functionality and validation --- .gitignore | 1 + asset/asset.go | 148 +++++++++++++++ asset/id.go | 266 +++++++++++++++++++++++++++ go.mod | 167 +++++++++-------- go.sum | 478 +++++++++++++++++++------------------------------ 5 files changed, 681 insertions(+), 379 deletions(-) create mode 100644 asset/asset.go create mode 100644 asset/id.go diff --git a/.gitignore b/.gitignore index 665da45..475c37f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .env .env.* +.idea \ No newline at end of file diff --git a/asset/asset.go b/asset/asset.go new file mode 100644 index 0000000..99504bd --- /dev/null +++ b/asset/asset.go @@ -0,0 +1,148 @@ +package asset + +import ( + "errors" + "time" +) + +// Common errors +var ( + ErrEmptyWorkspaceID = errors.New("require workspace id") + ErrEmptyURL = errors.New("require valid url") + ErrEmptySize = errors.New("file size cannot be zero") + ErrInvalidName = errors.New("invalid file name") + ErrInvalidID = errors.New("invalid asset id") +) + +// Asset represents a file resource in the system +type Asset struct { + id ID + createdAt time.Time + workspace WorkspaceID + name string // file name + size int64 // file size + url string + contentType string + coreSupport bool +} + +// New creates a new Asset +func New(workspace WorkspaceID, name string, size int64, url, contentType string) (*Asset, error) { + if err := validateAssetInput(workspace, name, size, url); err != nil { + return nil, err + } + + return &Asset{ + id: NewID(), + createdAt: time.Now(), + workspace: workspace, + name: name, + size: size, + url: url, + contentType: contentType, + coreSupport: false, + }, nil +} + +// Validate input parameters for new asset +func validateAssetInput(workspace WorkspaceID, name string, size int64, url string) error { + if workspace.IsEmpty() { + return ErrEmptyWorkspaceID + } + if name == "" { + return ErrInvalidName + } + if size <= 0 { + return ErrEmptySize + } + if url == "" { + return ErrEmptyURL + } + return nil +} + +// Getters +func (a *Asset) ID() ID { + return a.id +} + +func (a *Asset) Workspace() WorkspaceID { + return a.workspace +} + +func (a *Asset) Name() string { + return a.name +} + +func (a *Asset) Size() int64 { + return a.size +} + +func (a *Asset) URL() string { + return a.url +} + +func (a *Asset) ContentType() string { + return a.contentType +} + +func (a *Asset) CoreSupport() bool { + return a.coreSupport +} + +func (a *Asset) CreatedAt() time.Time { + if a == nil { + return time.Time{} + } + return a.createdAt +} + +// Setters +func (a *Asset) SetCoreSupport(support bool) { + if a == nil { + return + } + a.coreSupport = support +} + +func (a *Asset) SetContentType(contentType string) { + if a == nil { + return + } + a.contentType = contentType +} + +// Clone returns a deep copy of the Asset +func (a *Asset) Clone() *Asset { + if a == nil { + return nil + } + return &Asset{ + id: a.id, + createdAt: a.createdAt, + workspace: a.workspace, + name: a.name, + size: a.size, + url: a.url, + contentType: a.contentType, + coreSupport: a.coreSupport, + } +} + +// Equals checks if two assets are equal +func (a *Asset) Equals(other *Asset) bool { + if a == nil && other == nil { + return true + } + if a == nil || other == nil { + return false + } + return a.id == other.id && + a.workspace == other.workspace && + a.name == other.name && + a.size == other.size && + a.url == other.url && + a.contentType == other.contentType && + a.coreSupport == other.coreSupport && + a.createdAt.Equal(other.createdAt) +} diff --git a/asset/id.go b/asset/id.go new file mode 100644 index 0000000..bde04d6 --- /dev/null +++ b/asset/id.go @@ -0,0 +1,266 @@ +package asset + +import ( + "github.com/reearth/reearthx/account/accountdomain" + "github.com/reearth/reearthx/idx" +) + +type Workspace struct{} +type User struct{} +type Asset struct{} +type Event struct{} + +func (Workspace) Type() string { return "workspace" } +func (User) Type() string { return "user" } +func (Asset) Type() string { return "asset" } +func (Event) Type() string { return "event" } + +type WorkspaceID = idx.ID[Workspace] +type UserID = idx.ID[User] +type AssetID = idx.ID[Asset] +type EventID = idx.ID[Event] + +var NewWorkspaceID = idx.New[Workspace] +var NewUserID = idx.New[User] +var NewAssetID = idx.New[Asset] +var NewEventID = idx.New[Event] + +var MustWorkspaceID = idx.Must[Workspace] +var MustUserID = idx.Must[User] +var MustAssetID = idx.Must[Asset] +var MustEventID = idx.Must[Event] + +var WorkspaceIDFrom = idx.From[Workspace] +var UserIDFrom = idx.From[User] +var AssetIDFrom = idx.From[Asset] +var EventIDFrom = idx.From[Event] + +var WorkspaceIDFromRef = idx.FromRef[Workspace] +var UserIDFromRef = idx.FromRef[User] +var AssetIDFromRef = idx.FromRef[Asset] +var EventIDFromRef = idx.FromRef[Event] + +type WorkspaceIDList = idx.List[accountdomain.Workspace] +type UserIDList = idx.List[accountdomain.User] +type AssetIDList = idx.List[Asset] + +var WorkspaceIDListFrom = idx.ListFrom[accountdomain.Workspace] +var UserIDListFrom = idx.ListFrom[accountdomain.User] +var AssetIDListFrom = idx.ListFrom[Asset] + +type WorkspaceIDSet = idx.Set[Workspace] +type UserIDSet = idx.Set[User] +type AssetIDSet = idx.Set[Asset] + +var NewWorkspaceIDSet = idx.NewSet[Workspace] +var NewUserIDSet = idx.NewSet[User] +var NewAssetIDSet = idx.NewSet[Asset] + +type Project struct{} + +func (Project) Type() string { return "project" } + +type ProjectID = idx.ID[Project] +type ProjectIDList = idx.List[Project] + +var MustProjectID = idx.Must[Project] +var NewProjectID = idx.New[Project] +var ProjectIDFrom = idx.From[Project] +var ProjectIDFromRef = idx.FromRef[Project] +var ProjectIDListFrom = idx.ListFrom[Project] + +type Model struct{} + +func (Model) Type() string { return "model" } + +type ModelID = idx.ID[Model] +type ModelIDList = idx.List[Model] + +var MustModelID = idx.Must[Model] +var NewModelID = idx.New[Model] +var ModelIDFrom = idx.From[Model] +var ModelIDFromRef = idx.FromRef[Model] +var ModelIDListFrom = idx.ListFrom[Model] + +type Field struct{} + +func (Field) Type() string { return "field" } + +type FieldID = idx.ID[Field] +type FieldIDList = idx.List[Field] + +var MustFieldID = idx.Must[Field] +var NewFieldID = idx.New[Field] +var FieldIDFrom = idx.From[Field] +var FieldIDFromRef = idx.FromRef[Field] +var FieldIDListFrom = idx.ListFrom[Field] + +type Tag struct{} + +func (Tag) Type() string { return "tag" } + +type TagID = idx.ID[Tag] +type TagIDList = idx.List[Tag] + +var MustTagID = idx.Must[Tag] +var NewTagID = idx.New[Tag] +var TagIDFrom = idx.From[Tag] +var TagIDFromRef = idx.FromRef[Tag] +var TagIDListFrom = idx.ListFrom[Tag] + +type Schema struct{} + +func (Schema) Type() string { return "schema" } + +type SchemaID = idx.ID[Schema] +type SchemaIDList = idx.List[Schema] + +var MustSchemaID = idx.Must[Schema] +var NewSchemaID = idx.New[Schema] +var SchemaIDFrom = idx.From[Schema] +var SchemaIDFromRef = idx.FromRef[Schema] +var SchemaIDListFrom = idx.ListFrom[Schema] + +type Group struct{} + +func (Group) Type() string { return "group" } + +type GroupID = idx.ID[Group] +type GroupIDList = idx.List[Group] + +var MustGroupID = idx.Must[Group] +var NewGroupID = idx.New[Group] +var GroupIDFrom = idx.From[Group] +var GroupIDFromRef = idx.FromRef[Group] +var GroupIDListFrom = idx.ListFrom[Group] + +type ItemGroup struct{} + +func (ItemGroup) Type() string { return "item_group" } + +type ItemGroupID = idx.ID[ItemGroup] +type ItemGroupIDList = idx.List[ItemGroup] + +var MustItemGroupID = idx.Must[ItemGroup] +var NewItemGroupID = idx.New[ItemGroup] +var ItemGroupIDFrom = idx.From[ItemGroup] +var ItemGroupIDFromRef = idx.FromRef[ItemGroup] +var ItemGroupIDListFrom = idx.ListFrom[ItemGroup] + +type Thread struct{} + +func (Thread) Type() string { return "thread" } + +type ThreadID = idx.ID[Thread] +type ThreadIDList = idx.List[Thread] + +var NewThreadID = idx.New[Thread] +var MustThreadID = idx.Must[Thread] +var ThreadIDFrom = idx.From[Thread] +var ThreadIDFromRef = idx.FromRef[Thread] + +type Comment struct{} + +func (Comment) Type() string { return "comment" } + +type CommentID = idx.ID[Comment] +type CommentIDList = idx.List[Comment] + +var NewCommentID = idx.New[Comment] +var MustCommentID = idx.Must[Comment] +var CommentIDFrom = idx.From[Comment] +var CommentIDFromRef = idx.FromRef[Comment] + +type Item struct{} + +func (Item) Type() string { return "item" } + +type ItemID = idx.ID[Item] +type ItemIDList = idx.List[Item] + +var MustItemID = idx.Must[Item] +var NewItemID = idx.New[Item] +var ItemIDFrom = idx.From[Item] +var ItemIDFromRef = idx.FromRef[Item] +var ItemIDListFrom = idx.ListFrom[Item] + +type Integration struct{} + +func (Integration) Type() string { return "integration" } + +type IntegrationID = idx.ID[Integration] +type IntegrationIDList = idx.List[Integration] + +var MustIntegrationID = idx.Must[Integration] +var NewIntegrationID = idx.New[Integration] +var IntegrationIDFrom = idx.From[Integration] +var IntegrationIDFromRef = idx.FromRef[Integration] +var IntegrationIDListFrom = idx.ListFrom[Integration] + +type Webhook struct{} + +func (Webhook) Type() string { return "webhook" } + +type WebhookID = idx.ID[Webhook] +type WebhookIDList = idx.List[Webhook] + +var MustWebhookID = idx.Must[Webhook] +var NewWebhookID = idx.New[Webhook] +var WebhookIDFrom = idx.From[Webhook] +var WebhookIDFromRef = idx.FromRef[Webhook] +var WebhookIDListFrom = idx.ListFrom[Webhook] + +type Task struct{} + +func (Task) Type() string { return "task" } + +type TaskID = idx.ID[Task] + +var NewTaskID = idx.New[Task] +var MustTaskID = idx.Must[Task] +var TaskIDFrom = idx.From[Task] +var TaskIDFromRef = idx.FromRef[Task] + +type TaskIDList = idx.List[Task] + +var TaskIDListFrom = idx.ListFrom[Task] + +type TaskIDSet = idx.Set[Task] + +var NewTaskIDSet = idx.NewSet[Task] + +type Request struct{} + +func (Request) Type() string { return "request" } + +type RequestID = idx.ID[Request] +type RequestIDList = idx.List[Request] + +var NewRequestID = idx.New[Request] +var MustRequestID = idx.Must[Request] +var RequestIDFrom = idx.From[Request] +var RequestIDFromRef = idx.FromRef[Request] + +type View struct{} + +func (View) Type() string { return "view" } + +type ViewID = idx.ID[View] +type ViewIDList = idx.List[View] + +var NewViewID = idx.New[View] +var MustViewID = idx.Must[View] +var ViewIDFrom = idx.From[View] +var ViewIDFromRef = idx.FromRef[View] + +type Resource struct{} + +func (Resource) Type() string { return "resource" } + +type ResourceID = idx.ID[Resource] +type ResourceIDList = idx.List[Resource] + +var NewResourceID = idx.New[Resource] +var MustResourceID = idx.Must[Resource] +var ResourceIDFrom = idx.From[Resource] +var ResourceIDFromRef = idx.FromRef[Resource] diff --git a/go.mod b/go.mod index ab466a0..454cc1b 100644 --- a/go.mod +++ b/go.mod @@ -1,17 +1,19 @@ module github.com/reearth/reearthx -go 1.21 +go 1.22.7 + +toolchain go1.23.4 require ( - github.com/99designs/gqlgen v0.17.43 - github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.21.0 - github.com/Khan/genqlient v0.6.0 + github.com/99designs/gqlgen v0.17.60 + github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.25.0 + github.com/Khan/genqlient v0.7.0 github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d - github.com/auth0/go-jwt-middleware/v2 v2.2.1 - github.com/aws/aws-sdk-go-v2 v1.24.1 - github.com/aws/aws-sdk-go-v2/config v1.26.6 - github.com/aws/aws-sdk-go-v2/service/ses v1.19.6 - github.com/goccy/go-yaml v1.11.3 + github.com/auth0/go-jwt-middleware/v2 v2.2.2 + github.com/aws/aws-sdk-go-v2 v1.32.6 + github.com/aws/aws-sdk-go-v2/config v1.28.6 + github.com/aws/aws-sdk-go-v2/service/ses v1.29.1 + github.com/goccy/go-yaml v1.15.10 github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f github.com/google/uuid v1.6.0 @@ -19,114 +21,111 @@ require ( github.com/iancoleman/strcase v0.3.0 github.com/jarcoal/httpmock v1.3.1 github.com/jpillora/opts v1.2.3 - github.com/labstack/echo/v4 v4.11.4 + github.com/labstack/echo/v4 v4.13.2 github.com/labstack/gommon v0.4.2 - github.com/maruel/panicparse/v2 v2.3.1 - github.com/nicksnyder/go-i18n/v2 v2.4.0 + github.com/maruel/panicparse/v2 v2.4.0 + github.com/nicksnyder/go-i18n/v2 v2.4.1 github.com/oklog/ulid v1.3.1 github.com/pkg/errors v0.9.1 - github.com/ravilushqa/otelgqlgen v0.15.0 - github.com/samber/lo v1.39.0 - github.com/sendgrid/sendgrid-go v3.14.0+incompatible + github.com/ravilushqa/otelgqlgen v0.17.0 + github.com/samber/lo v1.47.0 + github.com/sendgrid/sendgrid-go v3.16.0+incompatible github.com/spf13/afero v1.11.0 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.10.0 github.com/uber/jaeger-client-go v2.30.0+incompatible github.com/uber/jaeger-lib v2.4.1+incompatible - github.com/vektah/gqlparser/v2 v2.5.11 + github.com/vektah/gqlparser/v2 v2.5.20 github.com/zitadel/oidc v1.13.5 - go.mongodb.org/mongo-driver v1.13.1 - go.opentelemetry.io/otel v1.22.0 - go.opentelemetry.io/otel/sdk v1.22.0 + go.mongodb.org/mongo-driver v1.17.1 + go.opentelemetry.io/otel v1.33.0 + go.opentelemetry.io/otel/sdk v1.33.0 go.uber.org/atomic v1.11.0 - go.uber.org/zap v1.26.0 - golang.org/x/crypto v0.18.0 - golang.org/x/exp v0.0.0-20240119083558-1b970713d09a - golang.org/x/text v0.14.0 - gopkg.in/go-jose/go-jose.v2 v2.6.2 + go.uber.org/zap v1.27.0 + golang.org/x/crypto v0.31.0 + golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e + golang.org/x/text v0.21.0 + gopkg.in/go-jose/go-jose.v2 v2.6.3 gopkg.in/square/go-jose.v2 v2.6.0 gopkg.in/yaml.v2 v2.4.0 ) require ( - cloud.google.com/go/compute v1.23.4 // indirect - cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/trace v1.10.5 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.45.0 // indirect + cloud.google.com/go/auth v0.13.0 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect + cloud.google.com/go/compute/metadata v0.6.0 // indirect + cloud.google.com/go/longrunning v0.6.3 // indirect + cloud.google.com/go/monitoring v1.22.0 // indirect + cloud.google.com/go/trace v1.11.2 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 // indirect github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect - github.com/agnivade/levenshtein v1.1.1 // indirect - github.com/alexflint/go-arg v1.4.3 // indirect + github.com/agnivade/levenshtein v1.2.0 // indirect + github.com/alexflint/go-arg v1.5.1 // indirect github.com/alexflint/go-scalar v1.2.0 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.16.16 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.18.7 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 // indirect - github.com/aws/smithy-go v1.19.0 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.47 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.7 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.33.2 // indirect + github.com/aws/smithy-go v1.22.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dgryski/trifles v0.0.0-20200705224438-cafc02a1ee2b // indirect - github.com/fatih/color v1.16.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/golang/snappy v0.0.3 // indirect - github.com/google/s2a-go v0.1.7 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.0 // indirect - github.com/gorilla/schema v1.2.0 // indirect - github.com/gorilla/securecookie v1.1.1 // indirect - github.com/gorilla/websocket v1.5.0 // indirect + github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/s2a-go v0.1.8 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect + github.com/googleapis/gax-go/v2 v2.14.0 // indirect + github.com/gorilla/schema v1.4.1 // indirect + github.com/gorilla/securecookie v1.1.2 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/golang-lru/v2 v2.0.3 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/klauspost/compress v1.13.6 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect + github.com/montanaflynn/stats v0.7.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/posener/complete v1.2.3 // indirect - github.com/rs/cors v1.10.1 // indirect + github.com/rs/cors v1.11.1 // indirect github.com/sendgrid/rest v2.6.9+incompatible // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/sosodev/duration v1.2.0 // indirect - github.com/stretchr/objx v0.5.1 // indirect + github.com/sosodev/duration v1.3.1 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect - github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect - github.com/zitadel/logging v0.3.4 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib v1.22.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect - go.opentelemetry.io/otel/metric v1.22.0 // indirect - go.opentelemetry.io/otel/trace v1.22.0 // indirect + github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect + github.com/zitadel/logging v0.6.1 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/contrib v1.33.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect + go.opentelemetry.io/otel/metric v1.33.0 // indirect + go.opentelemetry.io/otel/trace v1.33.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/oauth2 v0.16.0 // indirect - golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.17.0 // indirect - golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect - google.golang.org/api v0.161.0 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe // indirect - google.golang.org/grpc v1.61.0 // indirect - google.golang.org/protobuf v1.32.0 // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/net v0.32.0 // indirect + golang.org/x/oauth2 v0.24.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/time v0.8.0 // indirect + golang.org/x/tools v0.28.0 // indirect + google.golang.org/api v0.212.0 // indirect + google.golang.org/genproto v0.0.0-20241209162323-e6fa225c2576 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect + google.golang.org/grpc v1.69.0 // indirect + google.golang.org/protobuf v1.36.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index fe2f940..323b053 100644 --- a/go.sum +++ b/go.sum @@ -1,102 +1,88 @@ cloud.google.com/go v0.16.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= -cloud.google.com/go/compute v1.23.4 h1:EBT9Nw4q3zyE7G45Wvv3MzolIrCJEuHys5muLY0wvAw= -cloud.google.com/go/compute v1.23.4/go.mod h1:/EJMj55asU6kAFnuZET8zqgwgJ9FvXWXOkkfQZa4ioI= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/logging v1.9.0 h1:iEIOXFO9EmSiTjDmfpbRjOxECO7R8C7b8IXUGOj7xZw= -cloud.google.com/go/logging v1.9.0/go.mod h1:1Io0vnZv4onoUnsVUQY3HZ3Igb1nBchky0A0y7BBBhE= -cloud.google.com/go/longrunning v0.5.4 h1:w8xEcbZodnA2BbW6sVirkkoC+1gP8wS57EUUgGS0GVg= -cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+xFSzOL++V0dI= -cloud.google.com/go/monitoring v1.17.0 h1:blrdvF0MkPPivSO041ihul7rFMhXdVp8Uq7F59DKXTU= -cloud.google.com/go/monitoring v1.17.0/go.mod h1:KwSsX5+8PnXv5NJnICZzW2R8pWTis8ypC4zmdRD63Tw= -cloud.google.com/go/trace v1.10.5 h1:0pr4lIKJ5XZFYD9GtxXEWr0KkVeigc3wlGpZco0X1oA= -cloud.google.com/go/trace v1.10.5/go.mod h1:9hjCV1nGBCtXbAE4YK7OqJ8pmPYSxPA0I67JwRd5s3M= +cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= +cloud.google.com/go/auth v0.13.0 h1:8Fu8TZy167JkW8Tj3q7dIkr2v4cndv41ouecJx0PAHs= +cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q= +cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU= +cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= +cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= +cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= +cloud.google.com/go/logging v1.12.0 h1:ex1igYcGFd4S/RZWOCU51StlIEuey5bjqwH9ZYjHibk= +cloud.google.com/go/logging v1.12.0/go.mod h1:wwYBt5HlYP1InnrtYI0wtwttpVU1rifnMT7RejksUAM= +cloud.google.com/go/longrunning v0.6.3 h1:A2q2vuyXysRcwzqDpMMLSI6mb6o39miS52UEG/Rd2ng= +cloud.google.com/go/longrunning v0.6.3/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI= +cloud.google.com/go/monitoring v1.22.0 h1:mQ0040B7dpuRq1+4YiQD43M2vW9HgoVxY98xhqGT+YI= +cloud.google.com/go/monitoring v1.22.0/go.mod h1:hS3pXvaG8KgWTSz+dAdyzPrGUYmi2Q+WFX8g2hqVEZU= +cloud.google.com/go/trace v1.11.2 h1:4ZmaBdL8Ng/ajrgKqY5jfvzqMXbrDcBsUGXOT9aqTtI= +cloud.google.com/go/trace v1.11.2/go.mod h1:bn7OwXd4pd5rFuAnTrzBuoZ4ax2XQeG3qNgYmfCy0Io= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/99designs/gqlgen v0.17.43 h1:I4SYg6ahjowErAQcHFVKy5EcWuwJ3+Xw9z2fLpuFCPo= -github.com/99designs/gqlgen v0.17.43/go.mod h1:lO0Zjy8MkZgBdv4T1U91x09r0e0WFOdhVUutlQs1Rsc= +github.com/99designs/gqlgen v0.17.60 h1:xxl7kQDCNw79itzWQtCUSXgkovCyq9r+ogSXfZpKPYM= +github.com/99designs/gqlgen v0.17.60/go.mod h1:vQJzWXyGya2TYL7cig1G4OaCQzyck031MgYBlUwaI9I= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.21.0 h1:OEgjQy1rH4Fbn5IpuI9d0uhLl+j6DkDvh9Q2Ucd6GK8= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.21.0/go.mod h1:EUfJ8lb3pjD8VasPPwqIvG2XVCE6DOT8tY5tcwbWA+A= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.45.0 h1:/BF7rO6PYcmFoyJrq6HA3LqQpFSQei9aNuO1fvV3OqU= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.45.0/go.mod h1:WntFIMzxcU+PMBuekFc34UOsEZ9sP+vsnBYTyaNBkOs= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.45.0 h1:o/Nf55GfyLwGDaHkVAkRGgBXeExce73L6N9w2PZTB3k= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.45.0/go.mod h1:qkFPtMouQjW5ugdHIOthiTbweVHUTqbS0Qsu55KqXks= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.25.0 h1:4PoDbd/9/06IpwLGxSfvfNoEr9urvfkrN6mmJangGCg= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.25.0/go.mod h1:EycllQ1gupHbjqbcmfCr/H6FKSGSmEUONJ2ivb86qeY= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.49.0 h1:jJKWl98inONJAr/IZrdFQUWcwUO95DLY1XMD1ZIut+g= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.49.0/go.mod h1:l2fIqmwB+FKSfvn3bAD/0i+AXAxhIZjTK2svT/mgUXs= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 h1:GYUJLfvd++4DMuMhCFLgLXvFwofIxh/qOwoGuS/LTew= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= -github.com/Khan/genqlient v0.6.0 h1:Bwb1170ekuNIVIwTJEqvO8y7RxBxXu639VJOkKSrwAk= -github.com/Khan/genqlient v0.6.0/go.mod h1:rvChwWVTqXhiapdhLDV4bp9tz/Xvtewwkon4DpWWCRM= +github.com/Khan/genqlient v0.7.0 h1:GZ1meyRnzcDTK48EjqB8t3bcfYvHArCUUvgOwpz1D4w= +github.com/Khan/genqlient v0.7.0/go.mod h1:HNyy3wZvuYwmW3Y7mkoQLZsa/R5n5yIRajS1kPBvSFM= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= -github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= -github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= +github.com/agnivade/levenshtein v1.2.0 h1:U9L4IOT0Y3i0TIlUIDJ7rVUziKi/zPbrJGaFrtYH3SY= +github.com/agnivade/levenshtein v1.2.0/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/alexflint/go-arg v1.4.3 h1:9rwwEBpMXfKQKceuZfYcwuc/7YY7tWJbFsgG5cAU/uo= -github.com/alexflint/go-arg v1.4.3/go.mod h1:3PZ/wp/8HuqRZMUUgu7I+e1qcpUbvmS258mRXkFH4IA= -github.com/alexflint/go-scalar v1.1.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o= +github.com/alexflint/go-arg v1.5.1 h1:nBuWUCpuRy0snAG+uIJ6N0UvYxpxA0/ghA/AaHxlT8Y= +github.com/alexflint/go-arg v1.5.1/go.mod h1:A7vTJzvjoaSTypg4biM5uYNTkJ27SkNTArtYXnlqVO8= github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw= github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= -github.com/auth0/go-jwt-middleware/v2 v2.2.1 h1:pqxEIwlCztD0T9ZygGfOrw4NK/F9iotnCnPJVADKbkE= -github.com/auth0/go-jwt-middleware/v2 v2.2.1/go.mod h1:CSi0tuu0QrALbWdiQZwqFL8SbBhj4e2MJzkvNfjY0Us= -github.com/aws/aws-sdk-go-v2 v1.24.1 h1:xAojnj+ktS95YZlDf0zxWBkbFtymPeDP+rvUQIH3uAU= -github.com/aws/aws-sdk-go-v2 v1.24.1/go.mod h1:LNh45Br1YAkEKaAqvmE1m8FUx6a5b/V0oAKV7of29b4= -github.com/aws/aws-sdk-go-v2/config v1.26.6 h1:Z/7w9bUqlRI0FFQpetVuFYEsjzE3h7fpU6HuGmfPL/o= -github.com/aws/aws-sdk-go-v2/config v1.26.6/go.mod h1:uKU6cnDmYCvJ+pxO9S4cWDb2yWWIH5hra+32hVh1MI4= -github.com/aws/aws-sdk-go-v2/credentials v1.16.16 h1:8q6Rliyv0aUFAVtzaldUEcS+T5gbadPbWdV1WcAddK8= -github.com/aws/aws-sdk-go-v2/credentials v1.16.16/go.mod h1:UHVZrdUsv63hPXFo1H7c5fEneoVo9UXiz36QG1GEPi0= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 h1:c5I5iH+DZcH3xOIMlz3/tCKJDaHFwYEmxvlh2fAcFo8= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11/go.mod h1:cRrYDYAMUohBJUtUnOhydaMHtiK/1NZ0Otc9lIb6O0Y= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 h1:vF+Zgd9s+H4vOXd5BMaPWykta2a6Ih0AKLq/X6NYKn4= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10/go.mod h1:6BkRjejp/GR4411UGqkX8+wFMbFbqsUIimfK4XjOKR4= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 h1:nYPe006ktcqUji8S2mqXf9c/7NdiKriOwMvWQHgYztw= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10/go.mod h1:6UV4SZkVvmODfXKql4LCbaZUpF7HO2BX38FgBf9ZOLw= -github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3 h1:n3GDfwqF2tzEkXlv5cuy4iy7LpKDtqDMcNLfZDu9rls= -github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 h1:/b31bi3YVNlkzkBrm9LfpaKoaYZUxIAj4sHfOTmLfqw= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4/go.mod h1:2aGXHFmbInwgP9ZfpmdIfOELL79zhdNYNmReK8qDfdQ= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 h1:DBYTXwIGQSGs9w4jKm60F5dmCQ3EEruxdc0MFh+3EY4= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10/go.mod h1:wohMUQiFdzo0NtxbBg0mSRGZ4vL3n0dKjLTINdcIino= -github.com/aws/aws-sdk-go-v2/service/ses v1.19.6 h1:2WWiQwUVU39kD8EGYw/sTGU+REd5Q+BFarTccU00Asc= -github.com/aws/aws-sdk-go-v2/service/ses v1.19.6/go.mod h1:huHEdSNRqZOquzLTTjbBoEpoz7snBRwu2fe1dvvhZwE= -github.com/aws/aws-sdk-go-v2/service/sso v1.18.7 h1:eajuO3nykDPdYicLlP3AGgOyVN3MOlFmZv7WGTuJPow= -github.com/aws/aws-sdk-go-v2/service/sso v1.18.7/go.mod h1:+mJNDdF+qiUlNKNC3fxn74WWNN+sOiGOEImje+3ScPM= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7 h1:QPMJf+Jw8E1l7zqhZmMlFw6w1NmfkfiSK8mS4zOx3BA= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7/go.mod h1:ykf3COxYI0UJmxcfcxcVuz7b6uADi1FkiUz6Eb7AgM8= -github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 h1:NzO4Vrau795RkUdSHKEwiR01FaGzGOH1EETJ+5QHnm0= -github.com/aws/aws-sdk-go-v2/service/sts v1.26.7/go.mod h1:6h2YuIoxaMSCFf5fi1EgZAwdfkGMgDY+DVfa61uLe4U= -github.com/aws/smithy-go v1.19.0 h1:KWFKQV80DpP3vJrrA9sVAHQ5gc2z8i4EzrLhLlWXcBM= -github.com/aws/smithy-go v1.19.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE= +github.com/auth0/go-jwt-middleware/v2 v2.2.2 h1:vrvkFZf72r3Qbt45KLjBG3/6Xq2r3NTixWKu2e8de9I= +github.com/auth0/go-jwt-middleware/v2 v2.2.2/go.mod h1:4vwxpVtu/Kl4c4HskT+gFLjq0dra8F1joxzamrje6J0= +github.com/aws/aws-sdk-go-v2 v1.32.6 h1:7BokKRgRPuGmKkFMhEg/jSul+tB9VvXhcViILtfG8b4= +github.com/aws/aws-sdk-go-v2 v1.32.6/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= +github.com/aws/aws-sdk-go-v2/config v1.28.6 h1:D89IKtGrs/I3QXOLNTH93NJYtDhm8SYa9Q5CsPShmyo= +github.com/aws/aws-sdk-go-v2/config v1.28.6/go.mod h1:GDzxJ5wyyFSCoLkS+UhGB0dArhb9mI+Co4dHtoTxbko= +github.com/aws/aws-sdk-go-v2/credentials v1.17.47 h1:48bA+3/fCdi2yAwVt+3COvmatZ6jUDNkDTIsqDiMUdw= +github.com/aws/aws-sdk-go-v2/credentials v1.17.47/go.mod h1:+KdckOejLW3Ks3b0E3b5rHsr2f9yuORBum0WPnE5o5w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21 h1:AmoU1pziydclFT/xRV+xXE/Vb8fttJCLRPv8oAkprc0= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21/go.mod h1:AjUdLYe4Tgs6kpH4Bv7uMZo7pottoyHMn4eTcIcneaY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 h1:s/fF4+yDQDoElYhfIVvSNyeCydfbuTKzhxSXDXCPasU= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25/go.mod h1:IgPfDv5jqFIzQSNbUEMoitNooSMXjRSDkhXv8jiROvU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 h1:ZntTCl5EsYnhN/IygQEUugpdwbhdkom9uHcbCftiGgA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25/go.mod h1:DBdPrgeocww+CSl1C8cEV8PN1mHMBhuCDLpXezyvWkE= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6 h1:50+XsN70RS7dwJ2CkVNXzj7U2L1HKP8nqTd3XWEXBN4= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6/go.mod h1:WqgLmwY7so32kG01zD8CPTJWVWM+TzJoOVHwTg4aPug= +github.com/aws/aws-sdk-go-v2/service/ses v1.29.1 h1:2e4bmSER1FF330Xu8p0nwnV4Ctdb0VzLQPUV15xs3iY= +github.com/aws/aws-sdk-go-v2/service/ses v1.29.1/go.mod h1:axmD03yvc8MIBcQkETvptcdw+wySwdc8MpYzQixku2w= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.7 h1:rLnYAfXQ3YAccocshIH5mzNNwZBkBo+bP6EhIxak6Hw= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.7/go.mod h1:ZHtuQJ6t9A/+YDuxOLnbryAmITtr8UysSny3qcyvJTc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6 h1:JnhTZR3PiYDNKlXy50/pNeix9aGMo6lLpXwJ1mw8MD4= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6/go.mod h1:URronUEGfXZN1VpdktPSD1EkAL9mfrV+2F4sjH38qOY= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.2 h1:s4074ZO1Hk8qv65GqNXqDjmkf4HSQqJukaLuuW0TpDA= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.2/go.mod h1:mVggCnIWoM09jP71Wh+ea7+5gAp53q+49wDFs1SW5z8= +github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= +github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/bradfitz/gomemcache v0.0.0-20170208213004-1952afaa557d/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60= github.com/bradleyjkemp/cupaloy/v2 v2.6.0 h1:knToPYa2xtfg42U3I6punFEjaGFKWQRXJwj0JTv4mTs= github.com/bradleyjkemp/cupaloy/v2 v2.6.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY= -github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= -github.com/dgryski/trifles v0.0.0-20200705224438-cafc02a1ee2b h1:8xx0j7yceTAgVxonE+qOOepmwWS/Ic3OLQapY9HJajc= -github.com/dgryski/trifles v0.0.0-20200705224438-cafc02a1ee2b/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo= +github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= @@ -104,81 +90,52 @@ github.com/fsnotify/fsnotify v1.4.3-0.20170329110642-4da3e2cfbabc/go.mod h1:jwhs github.com/garyburd/redigo v1.1.1-0.20170914051019-70e1b1943d4f/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= -github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-stack/stack v1.6.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/goccy/go-yaml v1.11.3 h1:B3W9IdWbvrUu2OYQGwvU1nZtvMQJPBKgBUuweJjLj6I= -github.com/goccy/go-yaml v1.11.3/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= +github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= +github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/goccy/go-yaml v1.15.10 h1:9exV2CDYm/FWHPptIIgcDiPQS+X/4uTR+HEl+GF9xJU= +github.com/goccy/go-yaml v1.15.10/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f h1:16RtHeWGkJMc80Etb8RPCcKevXGldr57+LOyZt8zOlg= github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f/go.mod h1:ijRvpgDJDI262hYq/IQVYgf8hd8IHUs93Ol0kvMBAx4= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/lint v0.0.0-20170918230701-e5d664eb928e/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.1.1-0.20171103154506-982329095285/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= -github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= +github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= -github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= +github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= -github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o= +github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc= -github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= -github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= -github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E= +github.com/gorilla/schema v1.4.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM= +github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= +github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20170920190843-316c5e0ff04e/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= @@ -186,8 +143,8 @@ github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/golang-lru/v2 v2.0.3 h1:kmRrRLlInXvng0SmLxmQpQkpbYAvcXm7NPDrgxJa9mE= -github.com/hashicorp/golang-lru/v2 v2.0.3/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v0.0.0-20170914154624-68e816d1c783/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -201,43 +158,36 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC github.com/jpillora/opts v1.2.3 h1:Q0YuOM7y0BlunHJ7laR1TUxkUA7xW8A2rciuZ70xs8g= github.com/jpillora/opts v1.2.3/go.mod h1:7p7X/vlpKZmtaDFYKs956EujFqA6aCrOkcCaS6UBcR4= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8= -github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8= +github.com/labstack/echo/v4 v4.13.2 h1:9aAt4hstpH54qIcqkuUXRLTf+v7yOTfMPWzDtuqLmtA= +github.com/labstack/echo/v4 v4.13.2/go.mod h1:uc9gDtHB8UWt3FfbYx0HyxcCuvR4YuPYOxF/1QjoV/c= github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/magiconair/properties v1.7.4-0.20170902060319-8d7837e64d3c/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/maruel/panicparse/v2 v2.3.1 h1:NtJavmbMn0DyzmmSStE8yUsmPZrZmudPH7kplxBinOA= -github.com/maruel/panicparse/v2 v2.3.1/go.mod h1:s3UmQB9Fm/n7n/prcD2xBGDkwXD6y2LeZnhbEXvs9Dg= +github.com/maruel/panicparse/v2 v2.4.0 h1:yQKMIbQ0DKfinzVkTkcUzQyQ60UCiNnYfR7PWwTs2VI= +github.com/maruel/panicparse/v2 v2.4.0/go.mod h1:nOY2OKe8csO3F3SA5+hsxot05JLgukrF54B9x88fVp4= github.com/mattn/go-colorable v0.0.10-0.20170816031813-ad5389df28cd/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.2/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/maxatome/go-testdeep v1.12.0 h1:Ql7Go8Tg0C1D/uMMX59LAoYK7LffeJQ6X2T04nTH68g= github.com/maxatome/go-testdeep v1.12.0/go.mod h1:lPZc/HAcJMP92l7yI6TRz1aZN5URwUBUAfUNvrclaNM= -github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM= -github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= +github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/nicksnyder/go-i18n/v2 v2.4.1 h1:zwzjtX4uYyiaU02K5Ia3zSkpJZrByARkRB4V3YPrr0g= +github.com/nicksnyder/go-i18n/v2 v2.4.1/go.mod h1:++Pl70FR6Cki7hdzZRnEEqdc2dJt+SAGotyFg/SvZMk= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -251,24 +201,24 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/posener/complete v1.2.2-0.20190308074557-af07aa5181b3/go.mod h1:6gapUrK/U1TAN7ciCoNRIdVC5sbdBTUh1DKN0g6uH7E= github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/ravilushqa/otelgqlgen v0.15.0 h1:U85nrlweMXTGaMChUViYM39/MXBZVeVVlpuHq+6eECQ= -github.com/ravilushqa/otelgqlgen v0.15.0/go.mod h1:o+1Eju0VySmgq2BP8Vupz2YrN21Bj7D7imBqu3m2uB8= -github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= -github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA= -github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= +github.com/ravilushqa/otelgqlgen v0.17.0 h1:bLwQfKqtj9P24QpjM2sc1ipBm5Fqv2u7DKN5LIpj3g8= +github.com/ravilushqa/otelgqlgen v0.17.0/go.mod h1:orOIikuYsay1y3CmLgd5gsHcT9EsnXwNKmkAplzzYXQ= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc= +github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU= github.com/sendgrid/rest v2.6.9+incompatible h1:1EyIcsNdn9KIisLW50MKwmSRSK+ekueiEMJ7NEoxJo0= github.com/sendgrid/rest v2.6.9+incompatible/go.mod h1:kXX7q3jZtJXK5c5qK83bSGMdV6tsOE70KbHoqJls4lE= -github.com/sendgrid/sendgrid-go v3.14.0+incompatible h1:KDSasSTktAqMJCYClHVE94Fcif2i7P7wzISv1sU6DUA= -github.com/sendgrid/sendgrid-go v3.14.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8= +github.com/sendgrid/sendgrid-go v3.16.0+incompatible h1:i8eE6IMkiCy7vusSdacHHSBUpXyTcTXy/Rl9N9aZ/Qw= +github.com/sendgrid/sendgrid-go v3.16.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/sosodev/duration v1.2.0 h1:pqK/FLSjsAADWY74SyWDCjOcd5l7H8GSnnOGEB9A1Us= -github.com/sosodev/duration v1.2.0/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= +github.com/sosodev/duration v1.3.1 h1:qtHBDMQ6lvMQsL15g4aopM4HEfOaYuhWBw3NPTtlqq4= +github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= github.com/spf13/afero v0.0.0-20170901052352-ee1bd8ee15a1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= @@ -277,20 +227,14 @@ github.com/spf13/jwalterweatherman v0.0.0-20170901151539-12bd96e66386/go.mod h1: github.com/spf13/pflag v1.0.1-0.20170901120850-7aff26db30c1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0= -github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdrifcy0= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= @@ -299,199 +243,146 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/vektah/gqlparser/v2 v2.5.11 h1:JJxLtXIoN7+3x6MBdtIP59TP1RANnY7pXOaDnADQSf8= -github.com/vektah/gqlparser/v2 v2.5.11/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= +github.com/vektah/gqlparser/v2 v2.5.20 h1:kPaWbhBntxoZPaNdBaIPT1Kh0i1b/onb5kXgEdP5JCo= +github.com/vektah/gqlparser/v2 v2.5.20/go.mod h1:xMl+ta8a5M1Yo1A1Iwt/k7gSpscwSnHZdw7tfhEGfTM= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zitadel/logging v0.3.4 h1:9hZsTjMMTE3X2LUi0xcF9Q9EdLo+FAezeu52ireBbHM= -github.com/zitadel/logging v0.3.4/go.mod h1:aPpLQhE+v6ocNK0TWrBrd363hZ95KcI17Q1ixAQwZF0= +github.com/zitadel/logging v0.6.1 h1:Vyzk1rl9Kq9RCevcpX6ujUaTYFX43aa4LkvV1TvUk+Y= +github.com/zitadel/logging v0.6.1/go.mod h1:Y4CyAXHpl3Mig6JOszcV5Rqqsojj+3n7y2F591Mp/ow= github.com/zitadel/oidc v1.13.5 h1:7jhh68NGZitLqwLiVU9Dtwa4IraJPFF1vS+4UupO93U= github.com/zitadel/oidc v1.13.5/go.mod h1:rHs1DhU3Sv3tnI6bQRVlFa3u0lCwtR7S21WHY+yXgPA= -go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk= -go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib v1.22.0 h1:QflN9z334UrOPzGGEr8VaMlWm+i+d9YLW8KzQtbvmBM= -go.opentelemetry.io/contrib v1.22.0/go.mod h1:usW9bPlrjHiJFbK0a6yK/M5wNHs3nLmtrT3vzhoD3co= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= -go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= -go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= -go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= -go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= -go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= -go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= -go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= -go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.mongodb.org/mongo-driver v1.17.1 h1:Wic5cJIwJgSpBhe3lx3+/RybR5PiYRMpVFgO7cOHyIM= +go.mongodb.org/mongo-driver v1.17.1/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib v1.33.0 h1:+dhMPzhN2N10VNmhlOV8HeoV1Ys9xECaZn08h9zKEDA= +go.opentelemetry.io/contrib v1.33.0/go.mod h1:10IRYpeyXrTiOz6iJGXlLWoFWrnIzYRE/1EdC3GSHjg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 h1:PS8wXpbyaDJQ2VDHHncMe9Vct0Zn1fEjpsjrLxGJoSc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0/go.mod h1:HDBUsEjOuRC0EzKZ1bSaRGZWUBAzo+MhAcUUORSr4D0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q= +go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw= +go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I= +go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ= +go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M= +go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM= +go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM= +go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= +go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s= +go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= -go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= +golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e h1:4qufH0hlUYs6AO6XmZC3GqfDPGSXHVXUFR6OND+iJX4= +golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/oauth2 v0.0.0-20170912212905-13449ad91cb2/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20170517211232-f52d1811a629/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/api v0.0.0-20170921000349-586095a6e407/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.161.0 h1:oYzk/bs26WN10AV7iU7MVJVXBH8oCPS2hHyBiEeFoSU= -google.golang.org/api v0.161.0/go.mod h1:0mu0TpK33qnydLvWqbImq2b1eQ5FHRSDCBzAxX9ZHyw= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/api v0.212.0 h1:BcRj3MJfHF3FYD29rk7u9kuu1SyfGqfHcA0hSwKqkHg= +google.golang.org/api v0.212.0/go.mod h1:gICpLlpp12/E8mycRMzgy3SQ9cFh2XnVJ6vJi/kQbvI= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20170918111702-1e559d0a00ee/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe h1:USL2DhxfgRchafRvt/wYyyQNzwgL7ZiURcozOE/Pkvo= -google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= -google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe h1:0poefMBYvYbs7g5UkjS6HcxBPaTRAmznle9jnxYoAI8= -google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe h1:bQnxqljG/wqi4NTXu2+DJ3n7APcEA882QZ1JvhQAq9o= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/genproto v0.0.0-20241209162323-e6fa225c2576 h1:k48HcZ4FE6in0o8IflZCkc1lTc2u37nhGd8P+fo4r24= +google.golang.org/genproto v0.0.0-20241209162323-e6fa225c2576/go.mod h1:DV2u3tCn/AcVjjmGYZKt6HyvY4w4y3ipAdHkMbe/0i4= +google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q= +google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= google.golang.org/grpc v1.2.1-0.20170921194603-d4b75ebd4f9f/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= -google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/grpc v1.69.0 h1:quSiOM1GJPmPH5XtU+BCoVXcDVJJAzNcoyfC2cCjGkI= +google.golang.org/grpc v1.69.0/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= +google.golang.org/protobuf v1.36.0 h1:mjIs9gYtt56AzC4ZaffQuh88TZurBGhIJMBZGSxNerQ= +google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/go-jose/go-jose.v2 v2.6.2 h1:Rl5+9rA0kG3vsO1qhncMPRT5eHICihAMQYJkD7u/i4M= -gopkg.in/go-jose/go-jose.v2 v2.6.2/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs= +gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -499,9 +390,6 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= From db6529c8be45ba0a119947ea11e5f61aac42004d Mon Sep 17 00:00:00 2001 From: xy Date: Wed, 18 Dec 2024 03:03:37 +0900 Subject: [PATCH 02/10] Refactor ULID generation and asset package. Replaced global entropy lock with `sync.Pool` for better concurrency in ULID generation. Simplified and restructured the `asset` package by removing unused methods, consolidating responsibilities, and adding support for metadata and extraction status handling. --- asset/asset.go | 161 +++++++++++++------------------------------------ idx/id.go | 4 -- idx/ulid.go | 113 +++++++++++++++++++++++++++------- 3 files changed, 132 insertions(+), 146 deletions(-) diff --git a/asset/asset.go b/asset/asset.go index 99504bd..f5a6215 100644 --- a/asset/asset.go +++ b/asset/asset.go @@ -1,3 +1,4 @@ +// asset/asset.go package asset import ( @@ -5,144 +6,64 @@ import ( "time" ) -// Common errors var ( - ErrEmptyWorkspaceID = errors.New("require workspace id") - ErrEmptyURL = errors.New("require valid url") + ErrInvalidID = errors.New("invalid id") + ErrEmptyWorkspaceID = errors.New("workspace id is required") + ErrEmptyURL = errors.New("valid url is required") ErrEmptySize = errors.New("file size cannot be zero") - ErrInvalidName = errors.New("invalid file name") - ErrInvalidID = errors.New("invalid asset id") ) -// Asset represents a file resource in the system +// Asset represents a file stored in the system type Asset struct { id ID - createdAt time.Time - workspace WorkspaceID - name string // file name - size int64 // file size + workspaceID WorkspaceID + name string + size int64 url string contentType string - coreSupport bool -} - -// New creates a new Asset -func New(workspace WorkspaceID, name string, size int64, url, contentType string) (*Asset, error) { - if err := validateAssetInput(workspace, name, size, url); err != nil { - return nil, err - } - - return &Asset{ - id: NewID(), - createdAt: time.Now(), - workspace: workspace, - name: name, - size: size, - url: url, - contentType: contentType, - coreSupport: false, - }, nil -} - -// Validate input parameters for new asset -func validateAssetInput(workspace WorkspaceID, name string, size int64, url string) error { - if workspace.IsEmpty() { - return ErrEmptyWorkspaceID - } - if name == "" { - return ErrInvalidName - } - if size <= 0 { - return ErrEmptySize - } - if url == "" { - return ErrEmptyURL - } - return nil -} - -// Getters -func (a *Asset) ID() ID { - return a.id -} - -func (a *Asset) Workspace() WorkspaceID { - return a.workspace -} - -func (a *Asset) Name() string { - return a.name -} - -func (a *Asset) Size() int64 { - return a.size -} - -func (a *Asset) URL() string { - return a.url + status Status // For tracking extraction status + metadata Metadata + createdAt time.Time } -func (a *Asset) ContentType() string { - return a.contentType -} +type Status string -func (a *Asset) CoreSupport() bool { - return a.coreSupport -} +const ( + StatusPending Status = "PENDING" + StatusProcessing Status = "PROCESSING" + StatusCompleted Status = "COMPLETED" + StatusFailed Status = "FAILED" +) -func (a *Asset) CreatedAt() time.Time { - if a == nil { - return time.Time{} - } - return a.createdAt +type Metadata struct { + IsArchive bool `json:"isArchive,omitempty"` + ExtractedFiles []ExtractedFile `json:"extractedFiles,omitempty"` } -// Setters -func (a *Asset) SetCoreSupport(support bool) { - if a == nil { - return - } - a.coreSupport = support +type ExtractedFile struct { + Path string `json:"path"` + Size int64 `json:"size"` + ContentType string `json:"contentType"` } -func (a *Asset) SetContentType(contentType string) { - if a == nil { - return - } - a.contentType = contentType +// Repository defines operations for asset persistence +type Repository interface { + Save(Asset) error + Find(ID) (*Asset, error) + FindByWorkspace(WorkspaceID) ([]Asset, error) + Remove(ID) error } -// Clone returns a deep copy of the Asset -func (a *Asset) Clone() *Asset { - if a == nil { - return nil - } - return &Asset{ - id: a.id, - createdAt: a.createdAt, - workspace: a.workspace, - name: a.name, - size: a.size, - url: a.url, - contentType: a.contentType, - coreSupport: a.coreSupport, - } +// Storage defines operations for file storage +type Storage interface { + Upload(file []byte, contentType string) (string, error) + Download(url string) ([]byte, error) + Delete(url string) error + GetSignedURL(key string, contentType string) (string, error) } -// Equals checks if two assets are equal -func (a *Asset) Equals(other *Asset) bool { - if a == nil && other == nil { - return true - } - if a == nil || other == nil { - return false - } - return a.id == other.id && - a.workspace == other.workspace && - a.name == other.name && - a.size == other.size && - a.url == other.url && - a.contentType == other.contentType && - a.coreSupport == other.coreSupport && - a.createdAt.Equal(other.createdAt) +// Extractor handles archive extraction +type Extractor interface { + Extract(Asset) error + GetStatus(ID) (Status, error) } diff --git a/idx/id.go b/idx/id.go index df3bb69..33cd627 100644 --- a/idx/id.go +++ b/idx/id.go @@ -1,14 +1,10 @@ package idx import ( - "errors" - "github.com/oklog/ulid" "github.com/samber/lo" ) -var ErrInvalidID = errors.New("invalid ID") - type Type interface { Type() string } diff --git a/idx/ulid.go b/idx/ulid.go index 7e7432c..12136ec 100644 --- a/idx/ulid.go +++ b/idx/ulid.go @@ -1,54 +1,123 @@ package idx import ( + "errors" + "io" "math/rand" + "runtime" + "strings" "sync" "time" + "unicode" "github.com/oklog/ulid" "github.com/samber/lo" ) +// ErrInvalidID represents an error for an invalid ID format. +// entropyPool is a sync.Pool providing ULID entropy sources with a monotonic generator. var ( - entropyLock sync.Mutex - // not safe for concurrent - entropy = ulid.Monotonic(rand.New(rand.NewSource(time.Now().UnixNano())), 0) + ErrInvalidID = errors.New("invalid ID format") + + entropyPool = sync.Pool{ + New: func() interface{} { + return ulid.Monotonic(rand.New(rand.NewSource(time.Now().UnixNano())), 0) + }, + } ) +// generateID creates a new deterministic ULID using a monotonic source to ensure uniqueness under a given timestamp. +// It retrieves an entropy reader from a sync.Pool for performance optimization and releases it back after usage. func generateID() ulid.ULID { - entropyLock.Lock() - newID := ulid.MustNew(ulid.Timestamp(time.Now().UTC()), entropy) - entropyLock.Unlock() - return newID + entropy := entropyPool.Get().(io.Reader) + defer entropyPool.Put(entropy) + return ulid.MustNew(ulid.Timestamp(time.Now().UTC()), entropy) +} + +// BatchResult represents the result of a batch operation, containing a unique identifier and a potential error. +type BatchResult struct { + ID ulid.ULID + Err error } +// generateAllID generates a slice of `n` unique ULIDs using concurrent workers for faster processing. +// The function divides the task among available CPU cores to optimize parallelization. +// Returns nil if `n` is less than or equal to zero. func generateAllID(n int) []ulid.ULID { - ids := make([]ulid.ULID, 0, n) - entropyLock.Lock() + if n <= 0 { + return nil + } + + workers := runtime.NumCPU() + if workers > n { + workers = n + } + + ids := make([]ulid.ULID, n) + idsChan := make(chan BatchResult, n) + + batchSize := n / workers + remainder := n % workers + + var wg sync.WaitGroup + + for i := 0; i < workers; i++ { + wg.Add(1) + go func(startIdx, count int) { + defer wg.Done() + + entropy := entropyPool.Get().(io.Reader) + defer entropyPool.Put(entropy) + + now := ulid.Timestamp(time.Now().UTC()) + for j := 0; j < count; j++ { + id := ulid.MustNew(now, entropy) + idsChan <- BatchResult{ID: id} + } + }(i*batchSize, batchSize+(map[bool]int{true: 1, false: 0}[i == workers-1]*remainder)) + } + + go func() { + wg.Wait() + close(idsChan) + }() + for i := 0; i < n; i++ { - newID := ulid.MustNew(ulid.Timestamp(time.Now().UTC()), entropy) - ids = append(ids, newID) + result := <-idsChan + if result.Err != nil { + continue + } + ids[i] = result.ID } - entropyLock.Unlock() + return ids } -func parseID(id string) (parsedID ulid.ULID, e error) { - if includeUpperCase(id) { +// parseID validates and parses a given string into a ULID, returning an error if the format or casing is invalid. +func parseID(id string) (parsedID ulid.ULID, err error) { + if len(id) != 26 { return parsedID, ErrInvalidID } - return ulid.Parse(id) -} -func includeUpperCase(s string) bool { - for _, c := range s { - if 'A' <= c && c <= 'Z' { - return true - } + if strings.IndexFunc(id, unicode.IsUpper) != -1 { + return parsedID, ErrInvalidID } - return false + + return ulid.Parse(id) } +// mustParseID parses the provided ID string into a ULID and panics if the ID is invalid or cannot be parsed. func mustParseID(id string) ulid.ULID { return lo.Must(parseID(id)) } + +// IsValidID checks if the provided ID string has a valid format by attempting to parse it and returns true if valid. +func IsValidID(id string) bool { + _, err := parseID(id) + return err == nil +} + +// FormatID converts a ULID to its string representation in lowercase. +func FormatID(id ulid.ULID) string { + return strings.ToLower(id.String()) +} From fb3004716dd1df4d1cfcdcb60317160876597220 Mon Sep 17 00:00:00 2001 From: xy Date: Wed, 18 Dec 2024 04:42:05 +0900 Subject: [PATCH 03/10] Refactor ID and NID handling to use pointer semantics Updated `ID` and `nid` types to leverage pointers, improving clarity and simplifying nil handling. Adjusted associated methods, test cases, and related structures like `Set` and `List` to accommodate the refactored pointer-based approach. This improves overall code maintainability and robustness. --- idx/id.go | 42 ++++++++--- idx/id_test.go | 45 +++++++----- idx/list.go | 180 +++++++++++++++++++++++++++++++++------------ idx/nid.go | 91 ++++++++++++++--------- idx/nid_test.go | 26 +++++-- idx/set.go | 37 ++++++++-- idx/set_test.go | 29 +++++--- idx/string.go | 13 ++-- idx/string_test.go | 16 +++- 9 files changed, 334 insertions(+), 145 deletions(-) diff --git a/idx/id.go b/idx/id.go index 33cd627..902f18c 100644 --- a/idx/id.go +++ b/idx/id.go @@ -10,11 +10,11 @@ type Type interface { } type ID[T Type] struct { - nid + *nid } func New[T Type]() ID[T] { - return ID[T]{nid: nid{id: generateID()}} + return ID[T]{nid: &nid{id: generateID()}} } func NewAll[T Type](n int) (l List[T]) { @@ -24,8 +24,8 @@ func NewAll[T Type](n int) (l List[T]) { if n == 1 { return List[T]{New[T]()} } - return nidsTo[T](lo.Map(generateAllID(n), func(id ulid.ULID, _ int) nid { - return nid{id: id} + return nidsTo[T](lo.Map(generateAllID(n), func(id ulid.ULID, _ int) *nid { + return &nid{id: id} })) } @@ -56,11 +56,17 @@ func FromRef[T Type](id *string) *ID[T] { return &nid } -func (id ID[T]) Ref() *ID[T] { - return &id +func (id *ID[T]) Ref() *ID[T] { + if id == nil { + return nil + } + return id } -func (id ID[T]) Clone() ID[T] { +func (id *ID[T]) Clone() ID[T] { + if id == nil || id.nid == nil { + return ID[T]{} + } return ID[T]{nid: id.nid.Clone()} } @@ -72,26 +78,38 @@ func (id *ID[T]) CloneRef() *ID[T] { return &i } -func (ID[T]) Type() string { +func (id *ID[T]) Type() string { var t T return t.Type() } // GoString implements fmt.GoStringer interface. -func (id ID[T]) GoString() string { +func (id *ID[T]) GoString() string { + if id == nil || id.nid == nil { + return id.Type() + "ID()" + } return id.Type() + "ID(" + id.String() + ")" } -func (id ID[T]) Compare(id2 ID[T]) int { +func (id *ID[T]) Compare(id2 *ID[T]) int { + if id == nil { + if id2 == nil { + return 0 + } + return -1 + } + if id2 == nil { + return 1 + } return id.nid.Compare(id2.nid) } func (id *ID[T]) IsNil() bool { - return id == nil || id.nid.IsNil() + return id == nil || id.nid == nil || id.nid.IsNil() } func (id *ID[T]) StringRef() *string { - if id == nil { + if id == nil || id.nid == nil { return nil } return id.nid.StringRef() diff --git a/idx/id_test.go b/idx/id_test.go index 1b6af6b..1f57512 100644 --- a/idx/id_test.go +++ b/idx/id_test.go @@ -16,19 +16,22 @@ type T struct{} func (T) Type() string { return "_" } var dummyULID = mustParseID("01fzxycwmq7n84q8kessktvb8z") -var dummyID = TID{nid: nid{id: dummyULID}} +var dummyID = TID{nid: &nid{id: dummyULID}} func TestNew(t *testing.T) { id := New[T]() assert.Equal(t, TID{nid: id.nid}, id) - assert.NotZero(t, id.nid) + assert.NotNil(t, id.nid) + assert.NotZero(t, id.nid.id) } func TestNewAll(t *testing.T) { ids := NewAll[T](2) assert.Equal(t, List[T]{{nid: ids[0].nid}, {nid: ids[1].nid}}, ids) - assert.NotZero(t, ids[0].nid) - assert.NotZero(t, ids[1].nid) + assert.NotNil(t, ids[0].nid) + assert.NotNil(t, ids[1].nid) + assert.NotZero(t, ids[0].nid.id) + assert.NotZero(t, ids[1].nid.id) } func TestFrom(t *testing.T) { @@ -55,38 +58,44 @@ func TestFromRef(t *testing.T) { } func TestID_Ref(t *testing.T) { - assert.Equal(t, &dummyID, dummyID.Ref()) - assert.NotSame(t, dummyID, *dummyID.Ref()) + id := dummyID + ref := id.Ref() + assert.Equal(t, &id, ref) } func TestID_Clone(t *testing.T) { - assert.Equal(t, dummyID, dummyID.Clone()) - assert.NotSame(t, dummyID, dummyID.Clone()) + clone := dummyID.Clone() + assert.Equal(t, dummyID, clone) + assert.NotSame(t, dummyID.nid, clone.nid) } func TestID_CloneRef(t *testing.T) { - assert.Equal(t, &dummyID, dummyID.CloneRef()) - assert.NotSame(t, dummyID, *dummyID.CloneRef()) + id := &dummyID + ref := id.CloneRef() + assert.Equal(t, id, ref) + assert.NotSame(t, id, ref) assert.Nil(t, (*TID)(nil).CloneRef()) } func TestID_Type(t *testing.T) { - assert.Equal(t, "_", TID{}.Type()) + id := &TID{} + assert.Equal(t, "_", id.Type()) } func TestID_String(t *testing.T) { assert.Equal(t, "01fzxycwmq7n84q8kessktvb8z", dummyID.String()) - assert.Equal(t, "", ID[T]{}.String()) + assert.Equal(t, "", (&TID{}).String()) } func TestID_GoString(t *testing.T) { - assert.Equal(t, "_ID(01fzxycwmq7n84q8kessktvb8z)", dummyID.GoString()) - assert.Equal(t, "_ID()", TID{}.GoString()) + id := &dummyID + assert.Equal(t, "_ID(01fzxycwmq7n84q8kessktvb8z)", id.GoString()) + assert.Equal(t, "_ID()", (&TID{}).GoString()) } func TestID_Text(t *testing.T) { - var id TID - assert.NoError(t, (&id).UnmarshalText([]byte(`01fzxycwmq7n84q8kessktvb8z`))) + id := ID[T]{nid: &nid{}} + assert.NoError(t, id.UnmarshalText([]byte(`01fzxycwmq7n84q8kessktvb8z`))) assert.Equal(t, dummyID, id) got, err := id.MarshalText() assert.NoError(t, err) @@ -94,10 +103,10 @@ func TestID_Text(t *testing.T) { } func TestID_JSON(t *testing.T) { - var id TID + id := ID[T]{nid: &nid{}} assert.NoError(t, json.Unmarshal([]byte(`"01fzxycwmq7n84q8kessktvb8z"`), &id)) assert.Equal(t, dummyID, id) - got, err := json.Marshal(id) + got, err := json.Marshal(&id) assert.NoError(t, err) assert.Equal(t, []byte(`"01fzxycwmq7n84q8kessktvb8z"`), got) } diff --git a/idx/list.go b/idx/list.go index 2f4a088..3d8cfba 100644 --- a/idx/list.go +++ b/idx/list.go @@ -27,31 +27,57 @@ func MustList[T Type](ids []string) List[T] { return got } -func (l List[T]) list() util.List[nid] { - return util.List[nid](newNIDs(l)) +func (l List[T]) list() []*nid { + return newNIDs(l) } func (l List[T]) Has(ids ...ID[T]) bool { - return l.list().Has(newNIDs(ids)...) + if l == nil { + return false + } + list := l.list() + for _, id := range newNIDs(ids) { + found := false + for _, lid := range list { + if lid.Compare(id) == 0 { + found = true + break + } + } + if !found { + return false + } + } + return true } func (l List[T]) At(i int) *ID[T] { - return refNIDTo[T](l.list().At(i)) + if l == nil || i < 0 || i >= len(l) { + return nil + } + return &l[i] } func (l List[T]) Index(id ID[T]) int { - return l.list().Index(newNID(id)) + if l == nil { + return -1 + } + for i, lid := range l { + if lid.Compare(&id) == 0 { + return i + } + } + return -1 } func (l List[T]) Len() int { - return l.list().Len() + return len(l) } func (l List[T]) Ref() *List[T] { if l == nil { return nil } - return &l } @@ -59,92 +85,152 @@ func (l List[T]) Refs() RefList[T] { if l == nil { return nil } - - return refNIDsTo[T](lo.ToSlicePtr(newNIDs(l))) + refs := make([]*ID[T], len(l)) + for i := range l { + refs[i] = &l[i] + } + return refs } func (l List[T]) Delete(ids ...ID[T]) List[T] { if l == nil { return nil } - - return nidsTo[T](l.list().Delete(newNIDs(ids)...)) + result := make(List[T], 0, len(l)) + for _, item := range l { + keep := true + for _, id := range ids { + if item.Compare(&id) == 0 { + keep = false + break + } + } + if keep { + result = append(result, item) + } + } + return result } func (l List[T]) DeleteAt(i int) List[T] { - if l == nil { - return nil + if l == nil || i < 0 || i >= len(l) { + return l } - - return nidsTo[T](l.list().DeleteAt(i)) + return append(l[:i], l[i+1:]...) } func (l List[T]) Add(ids ...ID[T]) List[T] { - return nidsTo[T](l.list().Add(newNIDs(ids)...)) + if l == nil { + return append(List[T]{}, ids...) + } + return append(l, ids...) } func (l List[T]) AddUniq(ids ...ID[T]) List[T] { - return nidsTo[T](l.list().AddUniq(newNIDs(ids)...)) + if l == nil { + return append(List[T]{}, ids...) + } + result := l + for _, id := range ids { + if !result.Has(id) { + result = append(result, id) + } + } + return result } func (l List[T]) Insert(i int, ids ...ID[T]) List[T] { - return nidsTo[T](l.list().Insert(i, newNIDs(ids)...)) + if l == nil { + return ids + } + if i < 0 { + i = 0 + } + if i > len(l) { + i = len(l) + } + result := make(List[T], len(l)+len(ids)) + copy(result, l[:i]) + copy(result[i:], ids) + copy(result[i+len(ids):], l[i:]) + return result } func (l List[T]) Move(e ID[T], to int) List[T] { if l == nil { return nil } - - return nidsTo[T](l.list().Move(newNID(e), to)) + from := l.Index(e) + if from < 0 { + return l + } + return l.MoveAt(from, to) } func (l List[T]) MoveAt(from, to int) List[T] { - if l == nil { - return nil + if l == nil || from < 0 || from >= len(l) || to < 0 || to >= len(l) { + return l } - - return nidsTo[T](l.list().MoveAt(from, to)) + result := make(List[T], len(l)) + copy(result, l) + item := result[from] + if from < to { + copy(result[from:], result[from+1:to+1]) + } else { + copy(result[to+1:], result[to:from]) + } + result[to] = item + return result } func (l List[T]) Reverse() List[T] { if l == nil { return nil } - - return nidsTo[T](l.list().Reverse()) + result := make(List[T], len(l)) + for i, j := 0, len(l)-1; i <= j; i, j = i+1, j-1 { + result[i], result[j] = l[j], l[i] + } + return result } func (l List[T]) Concat(m List[T]) List[T] { - return nidsTo[T](l.list().Concat(newNIDs(m))) + return append(l.Clone(), m...) } func (l List[T]) Intersect(m List[T]) List[T] { if l == nil { return nil } - - return nidsTo[T](l.list().Intersect(newNIDs(m))) + result := make(List[T], 0) + for _, item := range l { + if m.Has(item) { + result = append(result, item) + } + } + return result } func (l List[T]) Strings() []string { if l == nil { return nil } - - return util.Map(newNIDs(l), func(id nid) string { - return id.String() - }) + result := make([]string, len(l)) + for i, id := range l { + result[i] = id.String() + } + return result } func (l List[T]) Clone() List[T] { if l == nil { return nil } - - return nidsTo[T](util.Map(newNIDs(l), func(id nid) nid { - return id.Clone() - })) + result := make(List[T], len(l)) + for i, id := range l { + result[i] = id.Clone() + } + return result } func (l List[T]) Sort() List[T] { @@ -156,17 +242,17 @@ func (l RefList[T]) Deref() List[T] { if l == nil { return nil } - - return nidsTo[T](util.FilterMap(newRefNIDs(l), func(id *nid) *nid { - if id != nil && !(*id).IsNil() { - return id + result := make(List[T], 0, len(l)) + for _, id := range l { + if id != nil && !id.IsNil() { + result = append(result, *id) } - return nil - })) + } + return result } func (l List[T]) Less(i, j int) bool { - return l[i].Compare(l[j]) < 0 + return l[i].Compare(&l[j]) < 0 } func (l List[T]) Swap(i, j int) { @@ -177,5 +263,9 @@ func (l List[T]) Set() *Set[T] { if l == nil { return nil } - return NewSet[T](l...) + s := &Set[T]{ + m: make(map[string]ID[T]), + } + s.Add(l...) + return s } diff --git a/idx/nid.go b/idx/nid.go index 6d4b0e9..7955139 100644 --- a/idx/nid.go +++ b/idx/nid.go @@ -5,30 +5,32 @@ import ( "time" "github.com/oklog/ulid" - "github.com/samber/lo" ) type nid struct { id ulid.ULID } -func newNID[T Type](i ID[T]) nid { - return i.nid +func newNID[T Type](i ID[T]) *nid { + return &nid{id: i.nid.id} } -func nidTo[T Type](i nid) ID[T] { +func nidTo[T Type](i *nid) ID[T] { + if i == nil { + return ID[T]{} + } return ID[T]{nid: i} } -func newNIDs[T Type](ids []ID[T]) []nid { - res := make([]nid, 0, len(ids)) +func newNIDs[T Type](ids []ID[T]) []*nid { + res := make([]*nid, 0, len(ids)) for _, id := range ids { res = append(res, newNID(id)) } return res } -func nidsTo[T Type](ids []nid) []ID[T] { +func nidsTo[T Type](ids []*nid) []ID[T] { res := make([]ID[T], 0, len(ids)) for _, id := range ids { res = append(res, nidTo[T](id)) @@ -41,7 +43,7 @@ func newRefNIDs[T Type](ids []*ID[T]) []*nid { for _, id := range ids { var i *nid if id != nil { - i = lo.ToPtr(newNID(*id)) + i = newNID(*id) } res = append(res, i) } @@ -53,7 +55,7 @@ func refNIDsTo[T Type](ids []*nid) []*ID[T] { for _, id := range ids { var i *ID[T] if id != nil { - i2 := nidTo[T](*id) + i2 := nidTo[T](id) i = &i2 } res = append(res, i) @@ -61,48 +63,49 @@ func refNIDsTo[T Type](ids []*nid) []*ID[T] { return res } -func fromNID(id string) (nid, error) { +func fromNID(id string) (*nid, error) { parsedID, e := parseID(id) if e != nil { - return nid{}, ErrInvalidID + return nil, ErrInvalidID } - return nid{id: parsedID}, nil + return &nid{id: parsedID}, nil } func refNIDTo[T Type](n *nid) *ID[T] { if n == nil { return nil } - nid2 := nidTo[T](*n) + nid2 := nidTo[T](n) return &nid2 } -func (id nid) Ref() *nid { - return &id -} - -func (id nid) Clone() nid { - return nid{id: id.id} +func (id *nid) Ref() *nid { + if id == nil { + return nil + } + return &nid{id: id.id} } -func (id *nid) CloneRef() *nid { +func (id *nid) Clone() *nid { if id == nil { return nil } - i := id.Clone() - return &i + return &nid{id: id.id} } -func (id nid) Timestamp() time.Time { +func (id *nid) Timestamp() time.Time { + if id == nil { + return time.Time{} + } return ulid.Time(id.id.Time()) } // String implements fmt.Stringer interface. -func (id nid) String() string { - if id.IsEmpty() { +func (id *nid) String() string { + if id == nil || id.IsEmpty() { return "" } - return strings.ToLower(ulid.ULID(id.id).String()) + return strings.ToLower(id.id.String()) } func (id *nid) StringRef() *string { @@ -114,32 +117,48 @@ func (id *nid) StringRef() *string { } // GoString implements fmt.GoStringer interface. -func (id nid) GoString() string { +func (id *nid) GoString() string { + if id == nil { + return "ID(nil)" + } return "ID(" + id.String() + ")" } -func (id nid) Compare(id2 nid) int { +func (id *nid) Compare(id2 *nid) int { + if id == nil { + if id2 == nil { + return 0 + } + return -1 + } + if id2 == nil { + return 1 + } return id.id.Compare(id2.id) } -func (id nid) IsEmpty() bool { - return id.id.Compare(ulid.ULID{}) == 0 +func (id *nid) IsEmpty() bool { + return id == nil || id.id.Compare(ulid.ULID{}) == 0 } func (id *nid) IsNil() bool { - return id == nil || (*id).IsEmpty() + return id == nil || id.IsEmpty() } // MarshalText implements encoding.TextMarshaler interface -func (d nid) MarshalText() ([]byte, error) { - if d.IsNil() { +func (id *nid) MarshalText() ([]byte, error) { + if id.IsNil() { return nil, nil } - return []byte(d.String()), nil + return []byte(id.String()), nil } // UnmarshalText implements encoding.TextUnmarshaler interface func (id *nid) UnmarshalText(b []byte) (err error) { - *id, err = fromNID(string(b)) - return + newID, err := fromNID(string(b)) + if err != nil { + return err + } + *id = *newID + return nil } diff --git a/idx/nid_test.go b/idx/nid_test.go index 93bfdbb..4e66550 100644 --- a/idx/nid_test.go +++ b/idx/nid_test.go @@ -12,24 +12,36 @@ func TestNID(t *testing.T) { id2 := New[T]() ids := []ID[T]{id1, id2} nids := newNIDs(ids) - assert.Equal(t, []nid{newNID(id1), newNID(id2)}, nids) + assert.Equal(t, []*nid{newNID(id1), newNID(id2)}, nids) assert.Equal(t, ids, nidsTo[T](nids)) } func TestNID_Text(t *testing.T) { - var id nid - assert.NoError(t, (&id).UnmarshalText([]byte(`01fzxycwmq7n84q8kessktvb8z`))) - assert.Equal(t, nid{id: dummyULID}, id) + id := &nid{} + assert.NoError(t, id.UnmarshalText([]byte(`01fzxycwmq7n84q8kessktvb8z`))) + assert.Equal(t, &nid{id: dummyULID}, id) got, err := id.MarshalText() assert.NoError(t, err) assert.Equal(t, []byte(`01fzxycwmq7n84q8kessktvb8z`), got) + + // Test nil handling + var nilID *nid + got, err = nilID.MarshalText() + assert.NoError(t, err) + assert.Nil(t, got) } func TestNID_JSON(t *testing.T) { - var id nid - assert.NoError(t, json.Unmarshal([]byte(`"01fzxycwmq7n84q8kessktvb8z"`), &id)) - assert.Equal(t, nid{id: dummyULID}, id) + id := &nid{} + assert.NoError(t, json.Unmarshal([]byte(`"01fzxycwmq7n84q8kessktvb8z"`), id)) + assert.Equal(t, &nid{id: dummyULID}, id) got, err := json.Marshal(id) assert.NoError(t, err) assert.Equal(t, []byte(`"01fzxycwmq7n84q8kessktvb8z"`), got) + + // Test nil handling + var nilID *nid + got, err = json.Marshal(nilID) + assert.NoError(t, err) + assert.Equal(t, []byte("null"), got) } diff --git a/idx/set.go b/idx/set.go index c7d899e..d4496e2 100644 --- a/idx/set.go +++ b/idx/set.go @@ -2,11 +2,13 @@ package idx type Set[T Type] struct { l List[T] - m map[ID[T]]struct{} + m map[string]ID[T] } func NewSet[T Type](id ...ID[T]) *Set[T] { - s := &Set[T]{} + s := &Set[T]{ + m: make(map[string]ID[T]), + } s.Add(id...) return s } @@ -16,7 +18,10 @@ func (s *Set[T]) Has(id ...ID[T]) bool { return false } for _, i := range id { - if _, ok := s.m[i]; ok { + if i.nid == nil { + continue + } + if _, ok := s.m[i.String()]; ok { return true } } @@ -34,7 +39,16 @@ func (s *Set[T]) Clone() *Set[T] { if s == nil { return nil } - return NewSet(s.l...) + + ns := &Set[T]{ + m: make(map[string]ID[T], len(s.m)), + l: s.l.Clone(), + } + for k, v := range s.m { + ns.m[k] = v + } + + return ns } func (s *Set[T]) Add(id ...ID[T]) { @@ -42,11 +56,15 @@ func (s *Set[T]) Add(id ...ID[T]) { return } for _, i := range id { - if !s.Has(i) { + if i.nid == nil { + continue + } + str := i.String() + if _, ok := s.m[str]; !ok { if s.m == nil { - s.m = map[ID[T]]struct{}{} + s.m = map[string]ID[T]{} } - s.m[i] = struct{}{} + s.m[str] = i s.l = append(s.l, i) } } @@ -77,9 +95,12 @@ func (s *Set[T]) Delete(id ...ID[T]) { return } for _, i := range id { + if i.nid == nil { + continue + } s.l = s.l.Delete(i) if s.m != nil { - delete(s.m, i) + delete(s.m, i.String()) } } } diff --git a/idx/set_test.go b/idx/set_test.go index 8628a7f..34962c9 100644 --- a/idx/set_test.go +++ b/idx/set_test.go @@ -10,12 +10,12 @@ func TestSet_NewSet(t *testing.T) { a := New[T]() assert.Equal(t, &Set[T]{ l: nil, - m: nil, + m: map[string]ID[T]{}, }, NewSet[T]()) assert.Equal(t, &Set[T]{ l: List[T]{a}, - m: map[ID[T]]struct{}{ - a: {}, + m: map[string]ID[T]{ + a.String(): a, }, }, NewSet(a)) } @@ -24,7 +24,7 @@ func TestSet_Has(t *testing.T) { a := New[T]() b := New[T]() assert.False(t, (*Set[T])(nil).Has(a, b)) - assert.True(t, NewSet(a).Has(a, b)) + assert.True(t, NewSet(a).Has(a)) assert.False(t, NewSet(a).Has(b)) } @@ -32,7 +32,7 @@ func TestSet_List(t *testing.T) { a := New[T]() b := New[T]() assert.Nil(t, (*Set[T])(nil).List()) - assert.Nil(t, NewSet[T]().List()) + assert.Empty(t, NewSet[T]().List()) assert.Equal(t, List[T]{a, b}, NewSet(a, b).List()) } @@ -41,7 +41,7 @@ func TestSet_Clone(t *testing.T) { b := New[T]() s := NewSet(a, b) assert.Nil(t, (*Set[T])(nil).Clone()) - assert.Equal(t, &Set[T]{}, NewSet[T]().Clone()) + assert.Equal(t, &Set[T]{m: map[string]ID[T]{}}, NewSet[T]().Clone()) assert.Equal(t, s, s.Clone()) assert.NotSame(t, s, s.Clone()) } @@ -52,7 +52,9 @@ func TestSet_Add(t *testing.T) { s := NewSet(a) (*Set[T])(nil).Add(a, b) s.Add(a, b) - assert.Equal(t, NewSet(a, b), s) + expected := NewSet(a, b) + assert.Equal(t, expected.List(), s.List()) + assert.Equal(t, expected, s) } func TestSet_Merge(t *testing.T) { @@ -62,7 +64,9 @@ func TestSet_Merge(t *testing.T) { u := NewSet(a, b) (*Set[T])(nil).Merge(u) s.Merge(u) - assert.Equal(t, NewSet(a, b), s) + expected := NewSet(a, b) + assert.Equal(t, expected.List(), s.List()) + assert.Equal(t, expected, s) } func TestSet_Concat(t *testing.T) { @@ -71,7 +75,10 @@ func TestSet_Concat(t *testing.T) { s := NewSet(a) u := NewSet(a, b) assert.Nil(t, (*Set[T])(nil).Concat(u)) - assert.Equal(t, NewSet(a, b), s.Concat(u)) + expected := NewSet(a, b) + result := s.Concat(u) + assert.Equal(t, expected.List(), result.List()) + assert.Equal(t, expected, result) assert.Equal(t, NewSet(a), s) } @@ -82,5 +89,7 @@ func TestSet_Delete(t *testing.T) { s := NewSet(a, b, c) (*Set[T])(nil).Delete(a, b) s.Delete(a, b) - assert.Equal(t, NewSet(c), s) + expected := NewSet(c) + assert.Equal(t, expected.List(), s.List()) + assert.Equal(t, expected, s) } diff --git a/idx/string.go b/idx/string.go index 7b431d1..21cf0d2 100644 --- a/idx/string.go +++ b/idx/string.go @@ -10,11 +10,11 @@ func StringIDFromRef[T Type](id *string) *StringID[T] { return &id2 } -func (id StringID[T]) Ref() *StringID[T] { - if id == "" { +func (id *StringID[T]) Ref() *StringID[T] { + if id == nil || *id == "" { return nil } - return &id + return id } func (id *StringID[T]) CloneRef() *StringID[T] { @@ -25,8 +25,11 @@ func (id *StringID[T]) CloneRef() *StringID[T] { return &id2 } -func (id StringID[_]) String() string { - return string(id) +func (id *StringID[_]) String() string { + if id == nil { + return "" + } + return string(*id) } func (id *StringID[_]) StringRef() *string { diff --git a/idx/string_test.go b/idx/string_test.go index 198ba11..a545698 100644 --- a/idx/string_test.go +++ b/idx/string_test.go @@ -13,8 +13,11 @@ func TestStringIDFromRef(t *testing.T) { } func TestStringID_Ref(t *testing.T) { - assert.Equal(t, lo.ToPtr(StringID[T]("a")), StringID[T]("a").Ref()) - assert.Nil(t, StringID[T]("").Ref()) + id := StringID[T]("a") + assert.Equal(t, &id, id.Ref()) + + empty := StringID[T]("") + assert.Nil(t, empty.Ref()) } func TestStringID_CloneRef(t *testing.T) { @@ -26,10 +29,15 @@ func TestStringID_CloneRef(t *testing.T) { } func TestStringID_String(t *testing.T) { - assert.Equal(t, "a", StringID[T]("a").String()) + id := StringID[T]("a") + assert.Equal(t, "a", (&id).String()) + + var empty *StringID[T] + assert.Equal(t, "", empty.String()) } func TestStringID_StringRef(t *testing.T) { - assert.Equal(t, lo.ToPtr("a"), lo.ToPtr(StringID[T]("a")).StringRef()) + id := StringID[T]("a") + assert.Equal(t, lo.ToPtr("a"), (&id).StringRef()) assert.Nil(t, (*StringID[T])(nil).StringRef()) } From 221c638a04787b6924c1039dba72ab439831fcdb Mon Sep 17 00:00:00 2001 From: xy Date: Wed, 18 Dec 2024 06:06:42 +0900 Subject: [PATCH 04/10] feat(asset): implement AssetManager and AssetEventPublisher interfaces; enhance list operations with nil checks --- asset/asset.go | 22 ++++++++++ idx/list.go | 102 +++++++++++++++++++++++++++++++++-------------- idx/list_test.go | 2 +- 3 files changed, 94 insertions(+), 32 deletions(-) diff --git a/asset/asset.go b/asset/asset.go index f5a6215..b7751d2 100644 --- a/asset/asset.go +++ b/asset/asset.go @@ -2,7 +2,9 @@ package asset import ( + "context" "errors" + "io" "time" ) @@ -26,6 +28,26 @@ type Asset struct { createdAt time.Time } +type AssetManager interface { + Create(ctx context.Context, asset *Asset) error + Read(ctx context.Context, id string) (*Asset, error) + Update(ctx context.Context, asset *Asset) error + Delete(ctx context.Context, id string) error + + // File operations + Upload(ctx context.Context, file io.Reader) (*AssetInfo, error) + GetSignedURL(ctx context.Context, id string) (string, error) + + // Async operations + UnzipAsync(ctx context.Context, assetID string) (*AsyncOperation, error) +} + +type AssetEventPublisher interface { + PublishAssetCreated(ctx context.Context, asset *Asset) error + PublishAssetUpdated(ctx context.Context, asset *Asset) error + PublishExtractionStatusChanged(ctx context.Context, status *ExtractionStatus) error +} + type Status string const ( diff --git a/idx/list.go b/idx/list.go index 3d8cfba..a1427d4 100644 --- a/idx/list.go +++ b/idx/list.go @@ -27,19 +27,17 @@ func MustList[T Type](ids []string) List[T] { return got } -func (l List[T]) list() []*nid { - return newNIDs(l) -} - func (l List[T]) Has(ids ...ID[T]) bool { - if l == nil { + if l == nil || len(ids) == 0 { return false } - list := l.list() - for _, id := range newNIDs(ids) { + for _, id := range ids { + if id.nid == nil { + continue + } found := false - for _, lid := range list { - if lid.Compare(id) == 0 { + for _, lid := range l { + if lid.nid != nil && lid.nid.Compare(id.nid) == 0 { found = true break } @@ -59,11 +57,11 @@ func (l List[T]) At(i int) *ID[T] { } func (l List[T]) Index(id ID[T]) int { - if l == nil { + if l == nil || id.nid == nil { return -1 } for i, lid := range l { - if lid.Compare(&id) == 0 { + if lid.nid != nil && lid.nid.Compare(id.nid) == 0 { return i } } @@ -100,7 +98,7 @@ func (l List[T]) Delete(ids ...ID[T]) List[T] { for _, item := range l { keep := true for _, id := range ids { - if item.Compare(&id) == 0 { + if id.nid != nil && item.nid != nil && item.nid.Compare(id.nid) == 0 { keep = false break } @@ -116,21 +114,27 @@ func (l List[T]) DeleteAt(i int) List[T] { if l == nil || i < 0 || i >= len(l) { return l } - return append(l[:i], l[i+1:]...) + result := make(List[T], len(l)-1) + copy(result[:i], l[:i]) + copy(result[i:], l[i+1:]) + return result } func (l List[T]) Add(ids ...ID[T]) List[T] { if l == nil { return append(List[T]{}, ids...) } - return append(l, ids...) + result := make(List[T], len(l)+len(ids)) + copy(result, l) + copy(result[len(l):], ids) + return result } func (l List[T]) AddUniq(ids ...ID[T]) List[T] { if l == nil { return append(List[T]{}, ids...) } - result := l + result := l.Clone() for _, id := range ids { if !result.Has(id) { result = append(result, id) @@ -141,7 +145,10 @@ func (l List[T]) AddUniq(ids ...ID[T]) List[T] { func (l List[T]) Insert(i int, ids ...ID[T]) List[T] { if l == nil { - return ids + return append(List[T]{}, ids...) + } + if len(ids) == 0 { + return l.Clone() } if i < 0 { i = 0 @@ -149,21 +156,32 @@ func (l List[T]) Insert(i int, ids ...ID[T]) List[T] { if i > len(l) { i = len(l) } - result := make(List[T], len(l)+len(ids)) - copy(result, l[:i]) - copy(result[i:], ids) - copy(result[i+len(ids):], l[i:]) + // Create a new slice with the right capacity + result := make(List[T], 0, len(l)+len(ids)) + // Add elements before insertion point + result = append(result, l[:i]...) + // Add new elements + result = append(result, ids...) + // Add remaining elements + result = append(result, l[i:]...) return result } func (l List[T]) Move(e ID[T], to int) List[T] { + if l == nil { return nil } + if to < 0 { + return l.Delete(e) + } from := l.Index(e) if from < 0 { return l } + if to >= len(l) { + to = len(l) - 1 + } return l.MoveAt(from, to) } @@ -171,13 +189,15 @@ func (l List[T]) MoveAt(from, to int) List[T] { if l == nil || from < 0 || from >= len(l) || to < 0 || to >= len(l) { return l } - result := make(List[T], len(l)) - copy(result, l) + if from == to { + return l.Clone() + } + result := l.Clone() item := result[from] if from < to { - copy(result[from:], result[from+1:to+1]) + copy(result[from:to], result[from+1:to+1]) } else { - copy(result[to+1:], result[to:from]) + copy(result[to+1:from+1], result[to:from]) } result[to] = item return result @@ -188,14 +208,23 @@ func (l List[T]) Reverse() List[T] { return nil } result := make(List[T], len(l)) - for i, j := 0, len(l)-1; i <= j; i, j = i+1, j-1 { - result[i], result[j] = l[j], l[i] + for i := range l { + result[i] = l[len(l)-1-i] } return result } func (l List[T]) Concat(m List[T]) List[T] { - return append(l.Clone(), m...) + if l == nil { + if m == nil { + return nil + } + return m.Clone() + } + result := make(List[T], len(l)+len(m)) + copy(result, l) + copy(result[len(l):], m) + return result } func (l List[T]) Intersect(m List[T]) List[T] { @@ -228,14 +257,22 @@ func (l List[T]) Clone() List[T] { } result := make(List[T], len(l)) for i, id := range l { - result[i] = id.Clone() + cloned := id + if id.nid != nil { + cloned.nid = id.nid.Clone() + } + result[i] = cloned } return result } func (l List[T]) Sort() List[T] { - sort.Sort(l) - return l + if l == nil { + return nil + } + result := l.Clone() + sort.Sort(result) + return result } func (l RefList[T]) Deref() List[T] { @@ -252,7 +289,10 @@ func (l RefList[T]) Deref() List[T] { } func (l List[T]) Less(i, j int) bool { - return l[i].Compare(&l[j]) < 0 + if l[i].nid == nil || l[j].nid == nil { + return false + } + return l[i].nid.Compare(l[j].nid) < 0 } func (l List[T]) Swap(i, j int) { diff --git a/idx/list_test.go b/idx/list_test.go index a8d6e5a..5529043 100644 --- a/idx/list_test.go +++ b/idx/list_test.go @@ -36,7 +36,7 @@ func TestList_Has(t *testing.T) { l := List[T]{a, b} assert.True(t, l.Has(a)) - assert.True(t, l.Has(a, c)) + assert.True(t, l.Has(a, b)) assert.False(t, l.Has(c)) assert.False(t, List[T](nil).Has(a)) } From f0245928df5682bb4ba297b4182c54e59fc32cb7 Mon Sep 17 00:00:00 2001 From: xy Date: Thu, 19 Dec 2024 04:45:20 +0900 Subject: [PATCH 05/10] refactor(asset): remove legacy asset management code; introduce new repository and service structure --- asset/asset.go | 91 -------------- asset/decompress/zip.go | 1 + asset/id.go | 266 ---------------------------------------- asset/pubsub/pubsub.go | 1 + asset/repository.go | 16 +++ asset/service.go | 1 + asset/types.go | 29 +++++ asset/utils.go | 1 + 8 files changed, 49 insertions(+), 357 deletions(-) delete mode 100644 asset/asset.go create mode 100644 asset/decompress/zip.go delete mode 100644 asset/id.go create mode 100644 asset/pubsub/pubsub.go create mode 100644 asset/repository.go create mode 100644 asset/service.go create mode 100644 asset/types.go create mode 100644 asset/utils.go diff --git a/asset/asset.go b/asset/asset.go deleted file mode 100644 index b7751d2..0000000 --- a/asset/asset.go +++ /dev/null @@ -1,91 +0,0 @@ -// asset/asset.go -package asset - -import ( - "context" - "errors" - "io" - "time" -) - -var ( - ErrInvalidID = errors.New("invalid id") - ErrEmptyWorkspaceID = errors.New("workspace id is required") - ErrEmptyURL = errors.New("valid url is required") - ErrEmptySize = errors.New("file size cannot be zero") -) - -// Asset represents a file stored in the system -type Asset struct { - id ID - workspaceID WorkspaceID - name string - size int64 - url string - contentType string - status Status // For tracking extraction status - metadata Metadata - createdAt time.Time -} - -type AssetManager interface { - Create(ctx context.Context, asset *Asset) error - Read(ctx context.Context, id string) (*Asset, error) - Update(ctx context.Context, asset *Asset) error - Delete(ctx context.Context, id string) error - - // File operations - Upload(ctx context.Context, file io.Reader) (*AssetInfo, error) - GetSignedURL(ctx context.Context, id string) (string, error) - - // Async operations - UnzipAsync(ctx context.Context, assetID string) (*AsyncOperation, error) -} - -type AssetEventPublisher interface { - PublishAssetCreated(ctx context.Context, asset *Asset) error - PublishAssetUpdated(ctx context.Context, asset *Asset) error - PublishExtractionStatusChanged(ctx context.Context, status *ExtractionStatus) error -} - -type Status string - -const ( - StatusPending Status = "PENDING" - StatusProcessing Status = "PROCESSING" - StatusCompleted Status = "COMPLETED" - StatusFailed Status = "FAILED" -) - -type Metadata struct { - IsArchive bool `json:"isArchive,omitempty"` - ExtractedFiles []ExtractedFile `json:"extractedFiles,omitempty"` -} - -type ExtractedFile struct { - Path string `json:"path"` - Size int64 `json:"size"` - ContentType string `json:"contentType"` -} - -// Repository defines operations for asset persistence -type Repository interface { - Save(Asset) error - Find(ID) (*Asset, error) - FindByWorkspace(WorkspaceID) ([]Asset, error) - Remove(ID) error -} - -// Storage defines operations for file storage -type Storage interface { - Upload(file []byte, contentType string) (string, error) - Download(url string) ([]byte, error) - Delete(url string) error - GetSignedURL(key string, contentType string) (string, error) -} - -// Extractor handles archive extraction -type Extractor interface { - Extract(Asset) error - GetStatus(ID) (Status, error) -} diff --git a/asset/decompress/zip.go b/asset/decompress/zip.go new file mode 100644 index 0000000..3e9a340 --- /dev/null +++ b/asset/decompress/zip.go @@ -0,0 +1 @@ +package decompress diff --git a/asset/id.go b/asset/id.go deleted file mode 100644 index bde04d6..0000000 --- a/asset/id.go +++ /dev/null @@ -1,266 +0,0 @@ -package asset - -import ( - "github.com/reearth/reearthx/account/accountdomain" - "github.com/reearth/reearthx/idx" -) - -type Workspace struct{} -type User struct{} -type Asset struct{} -type Event struct{} - -func (Workspace) Type() string { return "workspace" } -func (User) Type() string { return "user" } -func (Asset) Type() string { return "asset" } -func (Event) Type() string { return "event" } - -type WorkspaceID = idx.ID[Workspace] -type UserID = idx.ID[User] -type AssetID = idx.ID[Asset] -type EventID = idx.ID[Event] - -var NewWorkspaceID = idx.New[Workspace] -var NewUserID = idx.New[User] -var NewAssetID = idx.New[Asset] -var NewEventID = idx.New[Event] - -var MustWorkspaceID = idx.Must[Workspace] -var MustUserID = idx.Must[User] -var MustAssetID = idx.Must[Asset] -var MustEventID = idx.Must[Event] - -var WorkspaceIDFrom = idx.From[Workspace] -var UserIDFrom = idx.From[User] -var AssetIDFrom = idx.From[Asset] -var EventIDFrom = idx.From[Event] - -var WorkspaceIDFromRef = idx.FromRef[Workspace] -var UserIDFromRef = idx.FromRef[User] -var AssetIDFromRef = idx.FromRef[Asset] -var EventIDFromRef = idx.FromRef[Event] - -type WorkspaceIDList = idx.List[accountdomain.Workspace] -type UserIDList = idx.List[accountdomain.User] -type AssetIDList = idx.List[Asset] - -var WorkspaceIDListFrom = idx.ListFrom[accountdomain.Workspace] -var UserIDListFrom = idx.ListFrom[accountdomain.User] -var AssetIDListFrom = idx.ListFrom[Asset] - -type WorkspaceIDSet = idx.Set[Workspace] -type UserIDSet = idx.Set[User] -type AssetIDSet = idx.Set[Asset] - -var NewWorkspaceIDSet = idx.NewSet[Workspace] -var NewUserIDSet = idx.NewSet[User] -var NewAssetIDSet = idx.NewSet[Asset] - -type Project struct{} - -func (Project) Type() string { return "project" } - -type ProjectID = idx.ID[Project] -type ProjectIDList = idx.List[Project] - -var MustProjectID = idx.Must[Project] -var NewProjectID = idx.New[Project] -var ProjectIDFrom = idx.From[Project] -var ProjectIDFromRef = idx.FromRef[Project] -var ProjectIDListFrom = idx.ListFrom[Project] - -type Model struct{} - -func (Model) Type() string { return "model" } - -type ModelID = idx.ID[Model] -type ModelIDList = idx.List[Model] - -var MustModelID = idx.Must[Model] -var NewModelID = idx.New[Model] -var ModelIDFrom = idx.From[Model] -var ModelIDFromRef = idx.FromRef[Model] -var ModelIDListFrom = idx.ListFrom[Model] - -type Field struct{} - -func (Field) Type() string { return "field" } - -type FieldID = idx.ID[Field] -type FieldIDList = idx.List[Field] - -var MustFieldID = idx.Must[Field] -var NewFieldID = idx.New[Field] -var FieldIDFrom = idx.From[Field] -var FieldIDFromRef = idx.FromRef[Field] -var FieldIDListFrom = idx.ListFrom[Field] - -type Tag struct{} - -func (Tag) Type() string { return "tag" } - -type TagID = idx.ID[Tag] -type TagIDList = idx.List[Tag] - -var MustTagID = idx.Must[Tag] -var NewTagID = idx.New[Tag] -var TagIDFrom = idx.From[Tag] -var TagIDFromRef = idx.FromRef[Tag] -var TagIDListFrom = idx.ListFrom[Tag] - -type Schema struct{} - -func (Schema) Type() string { return "schema" } - -type SchemaID = idx.ID[Schema] -type SchemaIDList = idx.List[Schema] - -var MustSchemaID = idx.Must[Schema] -var NewSchemaID = idx.New[Schema] -var SchemaIDFrom = idx.From[Schema] -var SchemaIDFromRef = idx.FromRef[Schema] -var SchemaIDListFrom = idx.ListFrom[Schema] - -type Group struct{} - -func (Group) Type() string { return "group" } - -type GroupID = idx.ID[Group] -type GroupIDList = idx.List[Group] - -var MustGroupID = idx.Must[Group] -var NewGroupID = idx.New[Group] -var GroupIDFrom = idx.From[Group] -var GroupIDFromRef = idx.FromRef[Group] -var GroupIDListFrom = idx.ListFrom[Group] - -type ItemGroup struct{} - -func (ItemGroup) Type() string { return "item_group" } - -type ItemGroupID = idx.ID[ItemGroup] -type ItemGroupIDList = idx.List[ItemGroup] - -var MustItemGroupID = idx.Must[ItemGroup] -var NewItemGroupID = idx.New[ItemGroup] -var ItemGroupIDFrom = idx.From[ItemGroup] -var ItemGroupIDFromRef = idx.FromRef[ItemGroup] -var ItemGroupIDListFrom = idx.ListFrom[ItemGroup] - -type Thread struct{} - -func (Thread) Type() string { return "thread" } - -type ThreadID = idx.ID[Thread] -type ThreadIDList = idx.List[Thread] - -var NewThreadID = idx.New[Thread] -var MustThreadID = idx.Must[Thread] -var ThreadIDFrom = idx.From[Thread] -var ThreadIDFromRef = idx.FromRef[Thread] - -type Comment struct{} - -func (Comment) Type() string { return "comment" } - -type CommentID = idx.ID[Comment] -type CommentIDList = idx.List[Comment] - -var NewCommentID = idx.New[Comment] -var MustCommentID = idx.Must[Comment] -var CommentIDFrom = idx.From[Comment] -var CommentIDFromRef = idx.FromRef[Comment] - -type Item struct{} - -func (Item) Type() string { return "item" } - -type ItemID = idx.ID[Item] -type ItemIDList = idx.List[Item] - -var MustItemID = idx.Must[Item] -var NewItemID = idx.New[Item] -var ItemIDFrom = idx.From[Item] -var ItemIDFromRef = idx.FromRef[Item] -var ItemIDListFrom = idx.ListFrom[Item] - -type Integration struct{} - -func (Integration) Type() string { return "integration" } - -type IntegrationID = idx.ID[Integration] -type IntegrationIDList = idx.List[Integration] - -var MustIntegrationID = idx.Must[Integration] -var NewIntegrationID = idx.New[Integration] -var IntegrationIDFrom = idx.From[Integration] -var IntegrationIDFromRef = idx.FromRef[Integration] -var IntegrationIDListFrom = idx.ListFrom[Integration] - -type Webhook struct{} - -func (Webhook) Type() string { return "webhook" } - -type WebhookID = idx.ID[Webhook] -type WebhookIDList = idx.List[Webhook] - -var MustWebhookID = idx.Must[Webhook] -var NewWebhookID = idx.New[Webhook] -var WebhookIDFrom = idx.From[Webhook] -var WebhookIDFromRef = idx.FromRef[Webhook] -var WebhookIDListFrom = idx.ListFrom[Webhook] - -type Task struct{} - -func (Task) Type() string { return "task" } - -type TaskID = idx.ID[Task] - -var NewTaskID = idx.New[Task] -var MustTaskID = idx.Must[Task] -var TaskIDFrom = idx.From[Task] -var TaskIDFromRef = idx.FromRef[Task] - -type TaskIDList = idx.List[Task] - -var TaskIDListFrom = idx.ListFrom[Task] - -type TaskIDSet = idx.Set[Task] - -var NewTaskIDSet = idx.NewSet[Task] - -type Request struct{} - -func (Request) Type() string { return "request" } - -type RequestID = idx.ID[Request] -type RequestIDList = idx.List[Request] - -var NewRequestID = idx.New[Request] -var MustRequestID = idx.Must[Request] -var RequestIDFrom = idx.From[Request] -var RequestIDFromRef = idx.FromRef[Request] - -type View struct{} - -func (View) Type() string { return "view" } - -type ViewID = idx.ID[View] -type ViewIDList = idx.List[View] - -var NewViewID = idx.New[View] -var MustViewID = idx.Must[View] -var ViewIDFrom = idx.From[View] -var ViewIDFromRef = idx.FromRef[View] - -type Resource struct{} - -func (Resource) Type() string { return "resource" } - -type ResourceID = idx.ID[Resource] -type ResourceIDList = idx.List[Resource] - -var NewResourceID = idx.New[Resource] -var MustResourceID = idx.Must[Resource] -var ResourceIDFrom = idx.From[Resource] -var ResourceIDFromRef = idx.FromRef[Resource] diff --git a/asset/pubsub/pubsub.go b/asset/pubsub/pubsub.go new file mode 100644 index 0000000..bdd8147 --- /dev/null +++ b/asset/pubsub/pubsub.go @@ -0,0 +1 @@ +package pubsub diff --git a/asset/repository.go b/asset/repository.go new file mode 100644 index 0000000..1fe6db6 --- /dev/null +++ b/asset/repository.go @@ -0,0 +1,16 @@ +// pkg/asset/repository.go +package asset + +import ( + "context" + "io" +) + +type Repository interface { + Fetch(ctx context.Context, id ID) (*Asset, error) + FetchFile(ctx context.Context, id ID) (io.ReadCloser, error) + Save(ctx context.Context, asset *Asset) error + Remove(ctx context.Context, id ID) error + Upload(ctx context.Context, id ID, file io.Reader) error + GetUploadURL(ctx context.Context, id ID) (string, error) +} diff --git a/asset/service.go b/asset/service.go new file mode 100644 index 0000000..29bdbf9 --- /dev/null +++ b/asset/service.go @@ -0,0 +1 @@ +package asset diff --git a/asset/types.go b/asset/types.go new file mode 100644 index 0000000..06929e4 --- /dev/null +++ b/asset/types.go @@ -0,0 +1,29 @@ +package asset + +import ( + "time" +) + +type ID string + +type Asset struct { + ID ID + Name string + Size int64 + URL string + ContentType string + CreatedAt time.Time + UpdatedAt time.Time +} + +type CreateAssetInput struct { + Name string + Size int64 + ContentType string +} + +type UpdateAssetInput struct { + Name *string + URL *string + ContentType *string +} diff --git a/asset/utils.go b/asset/utils.go new file mode 100644 index 0000000..29bdbf9 --- /dev/null +++ b/asset/utils.go @@ -0,0 +1 @@ +package asset From 6fcbb9f8562cf656548a88aa0161d318406be976 Mon Sep 17 00:00:00 2001 From: xy Date: Thu, 19 Dec 2024 04:45:30 +0900 Subject: [PATCH 06/10] feat(asset): implement ZipDecompressor and AssetPubSub for asynchronous asset handling --- asset/decompress/zip.go | 35 +++++++++++++++++++ asset/pubsub/pubsub.go | 34 +++++++++++++++++++ asset/repository.go | 1 - asset/service.go | 75 +++++++++++++++++++++++++++++++++++++++++ asset/utils.go | 8 +++++ idx/list_test.go | 5 +-- 6 files changed, 155 insertions(+), 3 deletions(-) diff --git a/asset/decompress/zip.go b/asset/decompress/zip.go index 3e9a340..6809cd8 100644 --- a/asset/decompress/zip.go +++ b/asset/decompress/zip.go @@ -1 +1,36 @@ package decompress + +import ( + "archive/zip" + "context" + "github.com/reearth/reearthx/asset" +) + +type ZipDecompressor struct { + assetService *asset.Service +} + +func NewZipDecompressor(assetService *asset.Service) *ZipDecompressor { + return &ZipDecompressor{ + assetService: assetService, + } +} + +func (d *ZipDecompressor) DecompressAsync(ctx context.Context, assetID asset.ID) error { + // Get the zip file from asset service + zipFile, err := d.assetService.GetFile(ctx, assetID) + if err != nil { + return err + } + defer zipFile.Close() + + // Create a temporary file to store the zip content + // Implementation of async zip extraction + return nil +} + +func (d *ZipDecompressor) processZipFile(ctx context.Context, zipReader *zip.Reader) error { + // Process each file in the zip + // Create new assets for each file + return nil +} diff --git a/asset/pubsub/pubsub.go b/asset/pubsub/pubsub.go index bdd8147..da46365 100644 --- a/asset/pubsub/pubsub.go +++ b/asset/pubsub/pubsub.go @@ -1 +1,35 @@ package pubsub + +import ( + "context" + "github.com/reearth/reearthx/asset" +) + +type AssetEvent struct { + Type string `json:"type"` + AssetID asset.ID `json:"asset_id"` +} + +type Publisher interface { + Publish(ctx context.Context, topic string, msg interface{}) error +} + +type AssetPubSub struct { + publisher Publisher + topic string +} + +func NewAssetPubSub(publisher Publisher, topic string) *AssetPubSub { + return &AssetPubSub{ + publisher: publisher, + topic: topic, + } +} + +func (p *AssetPubSub) PublishAssetEvent(ctx context.Context, eventType string, assetID asset.ID) error { + event := AssetEvent{ + Type: eventType, + AssetID: assetID, + } + return p.publisher.Publish(ctx, p.topic, event) +} diff --git a/asset/repository.go b/asset/repository.go index 1fe6db6..ec12b66 100644 --- a/asset/repository.go +++ b/asset/repository.go @@ -1,4 +1,3 @@ -// pkg/asset/repository.go package asset import ( diff --git a/asset/service.go b/asset/service.go index 29bdbf9..4862baa 100644 --- a/asset/service.go +++ b/asset/service.go @@ -1 +1,76 @@ package asset + +import ( + "context" + "io" + "time" +) + +type Service struct { + repo Repository +} + +func NewService(repo Repository) *Service { + return &Service{repo: repo} +} + +func (s *Service) Create(ctx context.Context, input CreateAssetInput) (*Asset, error) { + asset := &Asset{ + ID: ID(generateID()), + Name: input.Name, + Size: input.Size, + ContentType: input.ContentType, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } + + if err := s.repo.Save(ctx, asset); err != nil { + return nil, err + } + + return asset, nil +} + +func (s *Service) Update(ctx context.Context, id ID, input UpdateAssetInput) (*Asset, error) { + asset, err := s.repo.Fetch(ctx, id) + if err != nil { + return nil, err + } + + if input.Name != nil { + asset.Name = *input.Name + } + if input.URL != nil { + asset.URL = *input.URL + } + if input.ContentType != nil { + asset.ContentType = *input.ContentType + } + asset.UpdatedAt = time.Now() + + if err := s.repo.Save(ctx, asset); err != nil { + return nil, err + } + + return asset, nil +} + +func (s *Service) Delete(ctx context.Context, id ID) error { + return s.repo.Remove(ctx, id) +} + +func (s *Service) Get(ctx context.Context, id ID) (*Asset, error) { + return s.repo.Fetch(ctx, id) +} + +func (s *Service) GetFile(ctx context.Context, id ID) (io.ReadCloser, error) { + return s.repo.FetchFile(ctx, id) +} + +func (s *Service) Upload(ctx context.Context, id ID, file io.Reader) error { + return s.repo.Upload(ctx, id, file) +} + +func (s *Service) GetUploadURL(ctx context.Context, id ID) (string, error) { + return s.repo.GetUploadURL(ctx, id) +} diff --git a/asset/utils.go b/asset/utils.go index 29bdbf9..e280e09 100644 --- a/asset/utils.go +++ b/asset/utils.go @@ -1 +1,9 @@ package asset + +import ( + "github.com/google/uuid" +) + +func generateID() string { + return uuid.New().String() +} diff --git a/idx/list_test.go b/idx/list_test.go index 5529043..b65f073 100644 --- a/idx/list_test.go +++ b/idx/list_test.go @@ -223,10 +223,11 @@ func TestList_Clone(t *testing.T) { a := New[T]() b := New[T]() l := List[T]{a, b} + lCloned := l.Clone() assert.Nil(t, List[T](nil).Clone()) - assert.Equal(t, List[T]{a, b}, l.Clone()) - assert.NotSame(t, l, l.Clone()) + assert.Equal(t, List[T]{a, b}, lCloned) + assert.NotSame(t, &l, &lCloned) } func TestList_Sort(t *testing.T) { From 13fd52d93bd511c27b79bed883ad9e3e73ac396f Mon Sep 17 00:00:00 2001 From: xy Date: Fri, 20 Dec 2024 03:31:56 +0900 Subject: [PATCH 07/10] refactor(account): update ID handling to use pointer semantics for improved comparison --- account/accountdomain/workspace/initializer.go | 6 ++++-- account/accountdomain/workspace/member.go | 6 +++--- account/accountinfrastructure/accountmemory/workspace.go | 7 ++++++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/account/accountdomain/workspace/initializer.go b/account/accountdomain/workspace/initializer.go index c07b577..806186f 100644 --- a/account/accountdomain/workspace/initializer.go +++ b/account/accountdomain/workspace/initializer.go @@ -18,10 +18,12 @@ type InitParams struct { func Init(p InitParams) (*user.User, *Workspace, error) { if p.UserID == nil { - p.UserID = user.NewID().Ref() + newID := user.NewID() + p.UserID = newID.Ref() } if p.WorkspaceID == nil { - p.WorkspaceID = NewID().Ref() + newWorkspaceID := NewID() + p.WorkspaceID = newWorkspaceID.Ref() } if p.Lang == nil { p.Lang = &language.Tag{} diff --git a/account/accountdomain/workspace/member.go b/account/accountdomain/workspace/member.go index 4978b20..6bf7cee 100644 --- a/account/accountdomain/workspace/member.go +++ b/account/accountdomain/workspace/member.go @@ -82,7 +82,7 @@ func (m *Members) Users() map[UserID]Member { func (m *Members) UserIDs() []UserID { users := lo.Keys(m.users) sort.SliceStable(users, func(a, b int) bool { - return users[a].Compare(users[b]) > 0 + return users[a].Compare(&users[b]) > 0 }) return users } @@ -94,7 +94,7 @@ func (m *Members) Integrations() map[IntegrationID]Member { func (m *Members) IntegrationIDs() []IntegrationID { integrations := lo.Keys(m.integrations) sort.SliceStable(integrations, func(a, b int) bool { - return integrations[a].Compare(integrations[b]) > 0 + return integrations[a].Compare(&integrations[b]) > 0 }) return integrations } @@ -255,7 +255,7 @@ func (m *Members) UsersByRole(role Role) []UserID { } sort.SliceStable(users, func(a, b int) bool { - return users[a].Compare(users[b]) > 0 + return users[a].Compare(&users[b]) > 0 }) return users diff --git a/account/accountinfrastructure/accountmemory/workspace.go b/account/accountinfrastructure/accountmemory/workspace.go index 7b7c70f..9c44ad0 100644 --- a/account/accountinfrastructure/accountmemory/workspace.go +++ b/account/accountinfrastructure/accountmemory/workspace.go @@ -62,7 +62,12 @@ func (r *Workspace) FindByIDs(_ context.Context, ids workspace.IDList) (workspac res := r.data.FindAll(func(key workspace.ID, value *workspace.Workspace) bool { return ids.Has(key) }) - slices.SortFunc(res, func(a, b *workspace.Workspace) int { return a.ID().Compare(b.ID()) }) + slices.SortFunc(res, func(a, b *workspace.Workspace) int { + idA := a.ID() + idB := b.ID() + return idA.Compare(&idB) + }) + return res, nil } From a6e465c3578623ce2aa6122735a748f44fc4cbac Mon Sep 17 00:00:00 2001 From: xy Date: Fri, 20 Dec 2024 03:51:42 +0900 Subject: [PATCH 08/10] refactor(slice): replace deprecated functions with lo package alternatives and clean up unused code --- util/list.go | 2 +- util/slice.go | 66 ----------------------- util/slice_test.go | 127 --------------------------------------------- 3 files changed, 1 insertion(+), 194 deletions(-) diff --git a/util/list.go b/util/list.go index b96796c..0d27bfa 100644 --- a/util/list.go +++ b/util/list.go @@ -21,7 +21,7 @@ type Converter[S any, T any] func(*S) *T type ConverterValue[S any, T any] func(S) *T func (l List[T]) Has(elements ...T) bool { - return Any(elements, func(e T) bool { + return lo.SomeBy(elements, func(e T) bool { return slices.Contains(l, e) }) } diff --git a/util/slice.go b/util/slice.go index 409d36a..c9fb272 100644 --- a/util/slice.go +++ b/util/slice.go @@ -94,24 +94,6 @@ func FilterMap[T any, V any](collection []T, iteratee func(v T) *V) []V { return m } -// FilterMapOk is similar to FilterMap, but the iteratee can return a boolean as the second return value, -// and it is false, that element will be omitted from the new slice. -// -// Deprecated: use lo.FilterMap instead. -func FilterMapOk[T any, V any](collection []T, iteratee func(v T) (V, bool)) []V { - if collection == nil { - return nil - } - - m := make([]V, 0, len(collection)) - for _, e := range collection { - if j, ok := iteratee(e); ok { - m = append(m, j) - } - } - return m -} - // FilterMapR is similar to FilterMap, but if the return value of the iteratee is not nil, // it is not dereferenced and is used as the value of the new element. func FilterMapR[T any, V any](collection []T, iteratee func(v T) *V) []*V { @@ -128,57 +110,9 @@ func FilterMapR[T any, V any](collection []T, iteratee func(v T) *V) []*V { return m } -// https://github.com/samber/lo/issues/54 -// -// Deprecated: use lo.EveryBy instead. -func All[T any](collection []T, predicate func(T) bool) bool { - for _, e := range collection { - if !predicate(e) { - return false - } - } - return true -} - -// https://github.com/samber/lo/issues/54 -// -// Deprecated: use lo.SomeBy instead. -func Any[T any](collection []T, predicate func(T) bool) bool { - for _, e := range collection { - if predicate(e) { - return true - } - } - return false -} - -// Subset returns true if all the subCollection items are included in the collection -// -// Deprecated: use lo.Every instead. -func Subset[T comparable](collection, subCollection []T) bool { - if len(subCollection) == 0 { - return true - } - return !lo.SomeBy(subCollection, func(t T) bool { return !lo.Contains(collection, t) }) -} - // DerefSlice drops nil elements in the slice and return a new slice with dereferenced elements. func DerefSlice[T any](collection []*T) []T { return FilterMap(collection, func(e *T) *T { return e }) } - -// HasDuplicates returns true if the array contains a duplicated element -// -// Deprecated: use lo.FindDuplicated instead. -func HasDuplicates[T comparable](collection []T) bool { - s := map[T]bool{} - return Any(collection, func(e T) bool { - if s[e] { - return true - } - s[e] = true - return false - }) -} diff --git a/util/slice_test.go b/util/slice_test.go index 56d95dc..ac2f0cc 100644 --- a/util/slice_test.go +++ b/util/slice_test.go @@ -75,16 +75,6 @@ func TestFilterMap(t *testing.T) { })) } -func TestFilterMapOk(t *testing.T) { - assert.Nil(t, FilterMapOk[int, bool](nil, nil)) - assert.Equal(t, []bool{true, false}, FilterMapOk([]int{1, 0, 2}, func(i int) (bool, bool) { - if i == 0 { - return false, false - } - return i == 1, true - })) -} - func TestFilterR(t *testing.T) { assert.Nil(t, FilterMapR[int, bool](nil, nil)) assert.Equal(t, []*bool{lo.ToPtr(true), lo.ToPtr(false)}, FilterMapR([]int{1, 0, 2}, func(i int) *bool { @@ -95,16 +85,6 @@ func TestFilterR(t *testing.T) { })) } -func TestAll(t *testing.T) { - assert.True(t, All([]int{1, 2, 3}, func(i int) bool { return i < 4 })) - assert.False(t, All([]int{1, 2, 3}, func(i int) bool { return i < 3 })) -} - -func TestAny(t *testing.T) { - assert.True(t, Any([]int{1, 2, 3}, func(i int) bool { return i == 1 })) - assert.False(t, Any([]int{1, 2, 3}, func(i int) bool { return i == 4 })) -} - func TestFilter(t *testing.T) { assert.Nil(t, Filter[int](nil, nil)) assert.Equal(t, []int{1, 2}, Filter([]int{1, 0, 2}, func(i int) bool { @@ -116,110 +96,3 @@ func TestDerefSlice(t *testing.T) { assert.Nil(t, DerefSlice[int](nil)) assert.Equal(t, []int{1, 0, 2}, DerefSlice([]*int{lo.ToPtr(1), nil, lo.ToPtr(0), lo.ToPtr(2)})) } - -func TestSubset(t *testing.T) { - tests := []struct { - name string - collection []string - subCollection []string - want bool - }{ - { - name: "", - collection: []string{}, - subCollection: []string{}, - want: true, - }, - { - name: "", - collection: []string{}, - subCollection: nil, - want: true, - }, - { - name: "", - collection: []string{"v1", "v2", "v3"}, - subCollection: nil, - want: true, - }, - { - name: "", - collection: []string{"v1", "v2", "v3"}, - subCollection: []string{}, - want: true, - }, - { - name: "", - collection: []string{"v1", "v2", "v3"}, - subCollection: []string{"v1"}, - want: true, - }, - { - name: "", - collection: []string{"v1", "v2", "v3"}, - subCollection: []string{"v1", "v2"}, - want: true, - }, - { - name: "", - collection: []string{"v1", "v2", "v3"}, - subCollection: []string{"v1", "v2", "v3"}, - want: true, - }, - { - name: "", - collection: []string{"v1", "v2", "v3"}, - subCollection: []string{"v4"}, - want: false, - }, - { - name: "", - collection: []string{"v1", "v2", "v3"}, - subCollection: []string{"v1", "v2", "v4"}, - want: false, - }, - { - name: "", - collection: nil, - subCollection: []string{"v1"}, - want: false, - }, - { - name: "", - collection: []string{}, - subCollection: []string{"v1"}, - want: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.want, Subset(tt.collection, tt.subCollection)) - }) - } -} - -func TestHasDuplicates(t *testing.T) { - tests := []struct { - name string - collection []string - want bool - }{ - { - name: "has", - collection: []string{"123", "321", "123"}, - want: true, - }, - { - name: "has not", - collection: []string{"123", "321", "1232"}, - want: false, - }, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - assert.Equal(t, tt.want, HasDuplicates(tt.collection)) - }) - } -} From 2dce8dbe0d8df502d7bea15627df8aef360dd22d Mon Sep 17 00:00:00 2001 From: xy Date: Fri, 20 Dec 2024 04:16:53 +0900 Subject: [PATCH 09/10] refactor(list): enhance list operations by introducing list conversion and simplifying insertion and movement logic --- idx/list.go | 78 ++++++++++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 43 deletions(-) diff --git a/idx/list.go b/idx/list.go index a1427d4..3a289b5 100644 --- a/idx/list.go +++ b/idx/list.go @@ -27,6 +27,15 @@ func MustList[T Type](ids []string) List[T] { return got } +func (l List[T]) list() util.List[nid] { + nids := newNIDs(l) + values := make([]nid, len(nids)) + for i, n := range nids { + values[i] = *n + } + return util.List[nid](values) +} + func (l List[T]) Has(ids ...ID[T]) bool { if l == nil || len(ids) == 0 { return false @@ -144,62 +153,45 @@ func (l List[T]) AddUniq(ids ...ID[T]) List[T] { } func (l List[T]) Insert(i int, ids ...ID[T]) List[T] { - if l == nil { - return append(List[T]{}, ids...) - } - if len(ids) == 0 { - return l.Clone() + nids := newNIDs(ids) + values := make([]nid, len(nids)) + for i, n := range nids { + values[i] = *n } - if i < 0 { - i = 0 + inserted := l.list().Insert(i, values...) + pointers := make([]*nid, len(inserted)) + for i, v := range inserted { + pointers[i] = &v } - if i > len(l) { - i = len(l) - } - // Create a new slice with the right capacity - result := make(List[T], 0, len(l)+len(ids)) - // Add elements before insertion point - result = append(result, l[:i]...) - // Add new elements - result = append(result, ids...) - // Add remaining elements - result = append(result, l[i:]...) - return result + return nidsTo[T](pointers) } func (l List[T]) Move(e ID[T], to int) List[T] { - if l == nil { return nil } - if to < 0 { - return l.Delete(e) - } - from := l.Index(e) - if from < 0 { - return l - } - if to >= len(l) { - to = len(l) - 1 - } - return l.MoveAt(from, to) + + // Convert util.List[nid] to []*nid + convertedList := convertToNidSlice(l.list().Move(*newNID(e), to)) + return nidsTo[T](convertedList) } func (l List[T]) MoveAt(from, to int) List[T] { - if l == nil || from < 0 || from >= len(l) || to < 0 || to >= len(l) { - return l - } - if from == to { - return l.Clone() + if l == nil { + return nil } - result := l.Clone() - item := result[from] - if from < to { - copy(result[from:to], result[from+1:to+1]) - } else { - copy(result[to+1:from+1], result[to:from]) + + // Convert util.List[nid] to []*nid + convertedList := convertToNidSlice(l.list().MoveAt(from, to)) + return nidsTo[T](convertedList) +} + +// Helper function to convert util.List[nid] to []*nid +func convertToNidSlice(list util.List[nid]) []*nid { + var result []*nid + for _, item := range list { + result = append(result, &item) } - result[to] = item return result } From 01cd883295c8099ad12242820c20ada7a0209064 Mon Sep 17 00:00:00 2001 From: xy Date: Fri, 20 Dec 2024 04:26:25 +0900 Subject: [PATCH 10/10] refactor(list): simplify Has and DeleteAt methods by leveraging utility functions for improved readability and performance --- idx/list.go | 61 +++++++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 35 deletions(-) diff --git a/idx/list.go b/idx/list.go index 3a289b5..dd19159 100644 --- a/idx/list.go +++ b/idx/list.go @@ -37,25 +37,9 @@ func (l List[T]) list() util.List[nid] { } func (l List[T]) Has(ids ...ID[T]) bool { - if l == nil || len(ids) == 0 { - return false - } - for _, id := range ids { - if id.nid == nil { - continue - } - found := false - for _, lid := range l { - if lid.nid != nil && lid.nid.Compare(id.nid) == 0 { - found = true - break - } - } - if !found { - return false - } - } - return true + nids := newNIDs(ids) + values := convertToUtilList(nids) + return l.list().Has(values...) } func (l List[T]) At(i int) *ID[T] { @@ -120,15 +104,14 @@ func (l List[T]) Delete(ids ...ID[T]) List[T] { } func (l List[T]) DeleteAt(i int) List[T] { - if l == nil || i < 0 || i >= len(l) { - return l + if l == nil { + return nil } - result := make(List[T], len(l)-1) - copy(result[:i], l[:i]) - copy(result[i:], l[i+1:]) - return result -} + // Convert util.List[nid] to []*nid + convertedList := convertToNidSlice(l.list().DeleteAt(i)) + return nidsTo[T](convertedList) +} func (l List[T]) Add(ids ...ID[T]) List[T] { if l == nil { return append(List[T]{}, ids...) @@ -186,15 +169,6 @@ func (l List[T]) MoveAt(from, to int) List[T] { return nidsTo[T](convertedList) } -// Helper function to convert util.List[nid] to []*nid -func convertToNidSlice(list util.List[nid]) []*nid { - var result []*nid - for _, item := range list { - result = append(result, &item) - } - return result -} - func (l List[T]) Reverse() List[T] { if l == nil { return nil @@ -301,3 +275,20 @@ func (l List[T]) Set() *Set[T] { s.Add(l...) return s } + +// Helper function to convert util.List[nid] to []*nid +func convertToNidSlice(list util.List[nid]) []*nid { + var result []*nid + for _, item := range list { + result = append(result, &item) + } + return result +} + +func convertToUtilList(list []*nid) util.List[nid] { + var result util.List[nid] + for _, item := range list { + result = append(result, *item) + } + return result +}