diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d68e06..1e44c44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.11.0] - 2026-07-23 + ### Added +- `accounts`: Added account details, active plan, and usage report clients. - `datasets`: Added source JSON pointers, queryable metadata, JSON Schema references, semantic roles, and well-known protobuf message and enum fields to dataset creation and updates, including generated STAC types. -- `datasets`: Added fluent Boolean and numeric expressions for filtering datapoints by custom queryable fields. +- `datasets`: Added fluent Boolean, string, and numeric expressions for filtering datapoints by custom queryable fields. ### Changed @@ -157,7 +160,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added support for Tilebox Observability, including logging and tracing helpers. - Added examples for using the library. -[Unreleased]: https://github.com/tilebox/tilebox-go/compare/v0.10.0...HEAD +[Unreleased]: https://github.com/tilebox/tilebox-go/compare/v0.11.0...HEAD +[0.11.0]: https://github.com/tilebox/tilebox-go/compare/v0.10.0...v0.11.0 [0.10.0]: https://github.com/tilebox/tilebox-go/compare/v0.9.0...v0.10.0 [0.9.0]: https://github.com/tilebox/tilebox-go/compare/v0.8.0...v0.9.0 [0.8.0]: https://github.com/tilebox/tilebox-go/compare/v0.7.1...v0.8.0 diff --git a/README.md b/README.md index 5dc3471..39b062f 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ For examples on how to use the library, see the [examples](examples) directory. ### Filtering Dataset Queries -Fields marked queryable in a dataset schema can be filtered with fluent Boolean and numeric expressions. Multiple +Fields marked queryable in a dataset schema can be filtered with fluent Boolean, string, and numeric expressions. Multiple expressions passed to `WithFilters` are combined with each other and with temporal and spatial filters using logical AND. @@ -77,6 +77,7 @@ func main() { datasets.WithTemporalExtent(query.NewTimeInterval(start, end)), datasets.WithFilters( query.Field("eo_cloud_cover").LessThan(20.0), + query.Field("granule_name").Equal("S2A_GRANULE"), query.Or( query.Field("quality").GreaterThanOrEqual(80), query.Field("quality").IsNull(), diff --git a/accounts/v1/accounts.go b/accounts/v1/accounts.go new file mode 100644 index 0000000..b80a7ab --- /dev/null +++ b/accounts/v1/accounts.go @@ -0,0 +1,38 @@ +package accounts // import "github.com/tilebox/tilebox-go/accounts/v1" + +import ( + "context" + "fmt" + + "connectrpc.com/connect" + "github.com/tilebox/tilebox-go/observability" + accountsv1alpha1 "github.com/tilebox/tilebox-go/protogen/accounts/v1alpha1" + "github.com/tilebox/tilebox-go/protogen/accounts/v1alpha1/accountsv1alpha1connect" + "go.opentelemetry.io/otel/trace" +) + +// AccountClient provides access to account details for the authenticated credential. +type AccountClient interface { + // GetAccountDetails returns details about the account associated with the authenticated credential. + GetAccountDetails(ctx context.Context) (*accountsv1alpha1.AccountDetails, error) +} + +var _ AccountClient = &accountClient{} + +type accountClient struct { + connectClient accountsv1alpha1connect.AccountServiceClient + tracer trace.Tracer +} + +func (c *accountClient) GetAccountDetails(ctx context.Context) (*accountsv1alpha1.AccountDetails, error) { + return observability.WithSpanResult(ctx, c.tracer, "accounts/details/get", func(ctx context.Context) (*accountsv1alpha1.AccountDetails, error) { + response, err := c.connectClient.GetAccountDetails(ctx, connect.NewRequest( + accountsv1alpha1.GetAccountDetailsRequest_builder{}.Build(), + )) + if err != nil { + return nil, fmt.Errorf("failed to get account details: %w", err) + } + + return response.Msg, nil + }) +} diff --git a/accounts/v1/billing.go b/accounts/v1/billing.go new file mode 100644 index 0000000..a477c69 --- /dev/null +++ b/accounts/v1/billing.go @@ -0,0 +1,83 @@ +package accounts // import "github.com/tilebox/tilebox-go/accounts/v1" + +import ( + "context" + "fmt" + + "connectrpc.com/connect" + "github.com/tilebox/tilebox-go/observability" + accountsv1alpha1 "github.com/tilebox/tilebox-go/protogen/accounts/v1alpha1" + "github.com/tilebox/tilebox-go/protogen/accounts/v1alpha1/accountsv1alpha1connect" + "go.opentelemetry.io/otel/trace" +) + +// BillingClient provides access to account billing information. +type BillingClient interface { + // GetActivePlan returns the active subscription plan for the authenticated account. + GetActivePlan(ctx context.Context) (*accountsv1alpha1.Plan, error) + + // GetUsageReport returns the current usage report for the authenticated account. + // + // Options: + // - WithHistoryDays: includes historical values for the requested number of days. + GetUsageReport(ctx context.Context, options ...UsageReportOption) (*accountsv1alpha1.UsageReport, error) +} + +var _ BillingClient = &billingClient{} + +type billingClient struct { + connectClient accountsv1alpha1connect.BillingServiceClient + tracer trace.Tracer +} + +func (c *billingClient) GetActivePlan(ctx context.Context) (*accountsv1alpha1.Plan, error) { + return observability.WithSpanResult(ctx, c.tracer, "accounts/billing/active_plan/get", func(ctx context.Context) (*accountsv1alpha1.Plan, error) { + response, err := c.connectClient.GetActivePlan(ctx, connect.NewRequest( + accountsv1alpha1.GetActivePlanRequest_builder{}.Build(), + )) + if err != nil { + return nil, fmt.Errorf("failed to get active plan: %w", err) + } + + return response.Msg, nil + }) +} + +func (c *billingClient) GetUsageReport(ctx context.Context, options ...UsageReportOption) (*accountsv1alpha1.UsageReport, error) { + usageReportOptions := newUsageReportOptions(options) + return observability.WithSpanResult(ctx, c.tracer, "accounts/billing/usage_report/get", func(ctx context.Context) (*accountsv1alpha1.UsageReport, error) { + response, err := c.connectClient.GetUsageReport(ctx, connect.NewRequest( + accountsv1alpha1.GetUsageReportRequest_builder{ + HistoryDays: usageReportOptions.historyDays, + }.Build(), + )) + if err != nil { + return nil, fmt.Errorf("failed to get usage report: %w", err) + } + + return response.Msg, nil + }) +} + +type usageReportOptions struct { + historyDays uint64 +} + +// UsageReportOption configures a usage report request. +type UsageReportOption func(*usageReportOptions) + +// WithHistoryDays includes historical usage values for the requested number of days. +// The API supports up to 365 days. +func WithHistoryDays(historyDays uint64) UsageReportOption { + return func(options *usageReportOptions) { + options.historyDays = historyDays + } +} + +func newUsageReportOptions(options []UsageReportOption) usageReportOptions { + var result usageReportOptions + for _, option := range options { + option(&result) + } + return result +} diff --git a/accounts/v1/client.go b/accounts/v1/client.go new file mode 100644 index 0000000..805d141 --- /dev/null +++ b/accounts/v1/client.go @@ -0,0 +1,150 @@ +// Package accounts provides a client for interacting with Tilebox Accounts. +package accounts // import "github.com/tilebox/tilebox-go/accounts/v1" + +import ( + "context" + "net" + "net/http" + "os" + "strings" + + "connectrpc.com/connect" + "github.com/tilebox/tilebox-go/internal/grpc" + "github.com/tilebox/tilebox-go/protogen/accounts/v1alpha1/accountsv1alpha1connect" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/trace" + "go.opentelemetry.io/otel/trace/noop" +) + +const otelTracerName = "tilebox.com/observability" + +// Client is a Tilebox Accounts client. +type Client struct { + Account AccountClient + Billing BillingClient +} + +// NewClient creates a new Tilebox Accounts client. +// +// By default, the returned Client is configured with: +// - "https://api.tilebox.com" as the URL +// - environment variable TILEBOX_API_KEY as the API key +// - a grpc.RetryHTTPClient HTTP client +// - the global tracer provider +// +// The passed options are used to override these default values and configure the returned Client appropriately. +func NewClient(options ...ClientOption) *Client { + cfg := newClientConfig(options) + accountConnectClient := newConnectClient(accountsv1alpha1connect.NewAccountServiceClient, cfg) + billingConnectClient := newConnectClient(accountsv1alpha1connect.NewBillingServiceClient, cfg) + tracer := cfg.tracerProvider.Tracer(otelTracerName) + + return &Client{ + Account: &accountClient{ + connectClient: accountConnectClient, + tracer: tracer, + }, + Billing: &billingClient{ + connectClient: billingConnectClient, + tracer: tracer, + }, + } +} + +// clientConfig contains the configuration for a Tilebox Accounts client. +type clientConfig struct { + httpClient connect.HTTPClient + url string + apiKey string + connectOptions []connect.ClientOption + + tracerProvider trace.TracerProvider +} + +// ClientOption configures a client. +type ClientOption func(*clientConfig) + +// WithHTTPClient sets the connect.HTTPClient to use for the client. +// +// Defaults to grpc.RetryHTTPClient. +func WithHTTPClient(httpClient connect.HTTPClient) ClientOption { + return func(cfg *clientConfig) { + cfg.httpClient = httpClient + } +} + +// WithURL sets the URL of the Tilebox Accounts service. +// +// Defaults to "https://api.tilebox.com". +func WithURL(url string) ClientOption { + return func(cfg *clientConfig) { + cfg.url = url + } +} + +// WithAPIKey sets the API key to use for the client. +// +// Defaults to the TILEBOX_API_KEY environment variable. +func WithAPIKey(apiKey string) ClientOption { + return func(cfg *clientConfig) { + cfg.apiKey = apiKey + } +} + +// WithConnectClientOptions sets additional options for the connect.HTTPClient. +func WithConnectClientOptions(options ...connect.ClientOption) ClientOption { + return func(cfg *clientConfig) { + cfg.connectOptions = append(cfg.connectOptions, options...) + } +} + +// WithDisableTracing disables OpenTelemetry tracing for the client. +func WithDisableTracing() ClientOption { + return func(cfg *clientConfig) { + cfg.tracerProvider = noop.NewTracerProvider() + } +} + +func newClientConfig(options []ClientOption) *clientConfig { + cfg := &clientConfig{ + url: "https://api.tilebox.com", + apiKey: os.Getenv("TILEBOX_API_KEY"), + tracerProvider: otel.GetTracerProvider(), + } + for _, option := range options { + option(cfg) + } + + if cfg.httpClient == nil { + if strings.HasPrefix(cfg.url, "https://") || strings.HasPrefix(cfg.url, "http://") { + cfg.httpClient = grpc.RetryHTTPClient() + } else { + address := cfg.url + dial := func(ctx context.Context, _ string, _ string) (net.Conn, error) { + var dialer net.Dialer + return dialer.DialContext(ctx, "unix", address) + } + transport := &http.Transport{DialContext: dial} + cfg.httpClient = &http.Client{Transport: transport} + cfg.url = "http://localhost" + } + } + + return cfg +} + +func newConnectClient[T any](newClientFunc func(httpClient connect.HTTPClient, baseURL string, options ...connect.ClientOption) T, cfg *clientConfig) T { + interceptors := make([]connect.Interceptor, 0) + if cfg.apiKey != "" { + interceptors = append(interceptors, grpc.NewAddAuthTokenInterceptor(func() string { + return cfg.apiKey + })) + } + + return newClientFunc( + cfg.httpClient, + cfg.url, + connect.WithClientOptions(cfg.connectOptions...), + connect.WithInterceptors(interceptors...), + ) +} diff --git a/accounts/v1/client_test.go b/accounts/v1/client_test.go new file mode 100644 index 0000000..af2645e --- /dev/null +++ b/accounts/v1/client_test.go @@ -0,0 +1,119 @@ +package accounts + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + + "connectrpc.com/connect" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + accountsv1alpha1 "github.com/tilebox/tilebox-go/protogen/accounts/v1alpha1" + "github.com/tilebox/tilebox-go/protogen/accounts/v1alpha1/accountsv1alpha1connect" +) + +func TestClient_GetAccountDetails(t *testing.T) { + service := &fakeAccountsService{} + client := newTestClient(t, service) + + details, err := client.Account.GetAccountDetails(context.Background()) + require.NoError(t, err) + + assert.Equal(t, "Test User", details.GetUserName()) + assert.Equal(t, "test-organization", details.GetOrganizationSlug()) + assert.Equal(t, "Bearer test-api-key", service.authorization) +} + +func TestClient_GetActivePlan(t *testing.T) { + service := &fakeAccountsService{} + client := newTestClient(t, service) + + plan, err := client.Billing.GetActivePlan(context.Background()) + require.NoError(t, err) + + assert.Equal(t, accountsv1alpha1.SubscriptionTier_SUBSCRIPTION_TIER_PAID, plan.GetTier()) + assert.Equal(t, "Bearer test-api-key", service.authorization) +} + +func TestClient_GetUsageReport(t *testing.T) { + tests := []struct { + name string + options []UsageReportOption + expectedHistoryDays uint64 + }{ + { + name: "current usage", + }, + { + name: "usage with history", + options: []UsageReportOption{WithHistoryDays(30)}, + expectedHistoryDays: 30, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + service := &fakeAccountsService{} + client := newTestClient(t, service) + + report, err := client.Billing.GetUsageReport(context.Background(), tt.options...) + require.NoError(t, err) + + require.Len(t, report.GetMetrics(), 1) + assert.Equal(t, "storage_bytes", report.GetMetrics()[0].GetKey()) + assert.Equal(t, tt.expectedHistoryDays, service.historyDays) + assert.Equal(t, "Bearer test-api-key", service.authorization) + }) + } +} + +func newTestClient(t *testing.T, service *fakeAccountsService) *Client { + t.Helper() + + mux := http.NewServeMux() + accountPath, accountHandler := accountsv1alpha1connect.NewAccountServiceHandler(service) + billingPath, billingHandler := accountsv1alpha1connect.NewBillingServiceHandler(service) + mux.Handle(accountPath, accountHandler) + mux.Handle(billingPath, billingHandler) + + server := httptest.NewServer(mux) + t.Cleanup(server.Close) + + return NewClient( + WithURL(server.URL), + WithHTTPClient(server.Client()), + WithAPIKey("test-api-key"), + WithDisableTracing(), + ) +} + +type fakeAccountsService struct { + authorization string + historyDays uint64 +} + +func (s *fakeAccountsService) GetAccountDetails(_ context.Context, request *connect.Request[accountsv1alpha1.GetAccountDetailsRequest]) (*connect.Response[accountsv1alpha1.AccountDetails], error) { + s.authorization = request.Header().Get("Authorization") + return connect.NewResponse(accountsv1alpha1.AccountDetails_builder{ + UserName: "Test User", + OrganizationSlug: "test-organization", + }.Build()), nil +} + +func (s *fakeAccountsService) GetActivePlan(_ context.Context, request *connect.Request[accountsv1alpha1.GetActivePlanRequest]) (*connect.Response[accountsv1alpha1.Plan], error) { + s.authorization = request.Header().Get("Authorization") + return connect.NewResponse(accountsv1alpha1.Plan_builder{ + Tier: accountsv1alpha1.SubscriptionTier_SUBSCRIPTION_TIER_PAID, + }.Build()), nil +} + +func (s *fakeAccountsService) GetUsageReport(_ context.Context, request *connect.Request[accountsv1alpha1.GetUsageReportRequest]) (*connect.Response[accountsv1alpha1.UsageReport], error) { + s.authorization = request.Header().Get("Authorization") + s.historyDays = request.Msg.GetHistoryDays() + return connect.NewResponse(accountsv1alpha1.UsageReport_builder{ + Metrics: []*accountsv1alpha1.UsageMetric{ + accountsv1alpha1.UsageMetric_builder{Key: "storage_bytes"}.Build(), + }, + }.Build()), nil +} diff --git a/datasets/v1/datapoints_test.go b/datasets/v1/datapoints_test.go index d31f026..170489b 100644 --- a/datasets/v1/datapoints_test.go +++ b/datasets/v1/datapoints_test.go @@ -368,19 +368,21 @@ func Test_datapointClient_QueryPage_WithFilters(t *testing.T) { WithFilters( query.Field("cloud_cover").LessThan(20.0), query.Field("valid").Equal(true), + query.Field("granule_name").Equal("S2A_GRANULE"), ), ) require.NoError(t, err) - require.Len(t, service.filters.GetExpressions(), 2) + require.Len(t, service.filters.GetExpressions(), 3) assert.Equal(t, "cloud_cover", service.filters.GetExpressions()[0].GetComparison().GetFieldName()) assert.Equal(t, "valid", service.filters.GetExpressions()[1].GetComparison().GetFieldName()) + assert.Equal(t, "S2A_GRANULE", service.filters.GetExpressions()[2].GetComparison().GetValue().GetStringValue()) service.called = false _, err = client.QueryPage( context.Background(), uuid.New(), WithTemporalExtent(timeInterval), - WithFilters(query.Field("cloud_cover").Equal("unsupported")), + WithFilters(query.Field("cloud_cover").Equal([]byte("unsupported"))), ) require.ErrorContains(t, err, "invalid query expression 0") assert.False(t, service.called) diff --git a/datasets/v1/field/field.go b/datasets/v1/field/field.go index b31f7aa..ee1c5ea 100644 --- a/datasets/v1/field/field.go +++ b/datasets/v1/field/field.go @@ -201,7 +201,7 @@ func (d *Descriptor) SourceJSONPointer(sourceJSONPointer string) *Descriptor { } // Queryable marks the field for projection into query storage and server-side filtering. -// Only optional fields created with Bool, Int32, Int64, Uint64, or Float64 can be queryable. +// Only optional fields created with String, Bool, Int32, Int64, Uint64, or Float64 can be queryable. // Repeated fields and fields of all other types are not supported. func (d *Descriptor) Queryable() *Descriptor { d.queryable = true diff --git a/examples/datasets/create/main.go b/examples/datasets/create/main.go index cde605d..16dc656 100644 --- a/examples/datasets/create/main.go +++ b/examples/datasets/create/main.go @@ -21,6 +21,7 @@ func main() { Description("The source granule name used as the primary title of the STAC item."). ExampleValue("S2A_MSIL2A_20260521T104031_N0511_R008_T32TQM_20260521T132145"). SourceJSONPointer("/properties/granule_name"). + Queryable(). Roles(field.RolePrimaryTitle), field.Message("assets", &stacv1.Assets{}). Description("The STAC assets associated with the item."). diff --git a/protogen/accounts/v1alpha1/account.pb.go b/protogen/accounts/v1alpha1/account.pb.go new file mode 100644 index 0000000..7a9767f --- /dev/null +++ b/protogen/accounts/v1alpha1/account.pb.go @@ -0,0 +1,563 @@ +// Public API for resolving account details associated with an authenticated request. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: accounts/v1alpha1/account.proto + +package accountsv1alpha1 + +import ( + _ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Type identifies the kind of credential used to authenticate the request. +type AuthenticationMethod_Type int32 + +const ( + AuthenticationMethod_TYPE_UNSPECIFIED AuthenticationMethod_Type = 0 + AuthenticationMethod_TYPE_API_KEY AuthenticationMethod_Type = 1 + AuthenticationMethod_TYPE_JWT AuthenticationMethod_Type = 2 +) + +// Enum value maps for AuthenticationMethod_Type. +var ( + AuthenticationMethod_Type_name = map[int32]string{ + 0: "TYPE_UNSPECIFIED", + 1: "TYPE_API_KEY", + 2: "TYPE_JWT", + } + AuthenticationMethod_Type_value = map[string]int32{ + "TYPE_UNSPECIFIED": 0, + "TYPE_API_KEY": 1, + "TYPE_JWT": 2, + } +) + +func (x AuthenticationMethod_Type) Enum() *AuthenticationMethod_Type { + p := new(AuthenticationMethod_Type) + *p = x + return p +} + +func (x AuthenticationMethod_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (AuthenticationMethod_Type) Descriptor() protoreflect.EnumDescriptor { + return file_accounts_v1alpha1_account_proto_enumTypes[0].Descriptor() +} + +func (AuthenticationMethod_Type) Type() protoreflect.EnumType { + return &file_accounts_v1alpha1_account_proto_enumTypes[0] +} + +func (x AuthenticationMethod_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// GetAccountDetailsRequest requests details about the account associated with the calling credential. +type GetAccountDetailsRequest struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetAccountDetailsRequest) Reset() { + *x = GetAccountDetailsRequest{} + mi := &file_accounts_v1alpha1_account_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetAccountDetailsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetAccountDetailsRequest) ProtoMessage() {} + +func (x *GetAccountDetailsRequest) ProtoReflect() protoreflect.Message { + mi := &file_accounts_v1alpha1_account_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +type GetAccountDetailsRequest_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + +} + +func (b0 GetAccountDetailsRequest_builder) Build() *GetAccountDetailsRequest { + m0 := &GetAccountDetailsRequest{} + b, x := &b0, m0 + _, _ = b, x + return m0 +} + +// AccountDetails is a minimal view of the account associated with an authenticated request. +type AccountDetails struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_UserName string `protobuf:"bytes,1,opt,name=user_name,json=userName"` + xxx_hidden_Email string `protobuf:"bytes,2,opt,name=email"` + xxx_hidden_OrganizationName string `protobuf:"bytes,3,opt,name=organization_name,json=organizationName"` + xxx_hidden_OrganizationSlug string `protobuf:"bytes,4,opt,name=organization_slug,json=organizationSlug"` + xxx_hidden_ActiveAuthenticationMethod *AuthenticationMethod `protobuf:"bytes,5,opt,name=active_authentication_method,json=activeAuthenticationMethod"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AccountDetails) Reset() { + *x = AccountDetails{} + mi := &file_accounts_v1alpha1_account_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AccountDetails) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AccountDetails) ProtoMessage() {} + +func (x *AccountDetails) ProtoReflect() protoreflect.Message { + mi := &file_accounts_v1alpha1_account_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *AccountDetails) GetUserName() string { + if x != nil { + return x.xxx_hidden_UserName + } + return "" +} + +func (x *AccountDetails) GetEmail() string { + if x != nil { + return x.xxx_hidden_Email + } + return "" +} + +func (x *AccountDetails) GetOrganizationName() string { + if x != nil { + return x.xxx_hidden_OrganizationName + } + return "" +} + +func (x *AccountDetails) GetOrganizationSlug() string { + if x != nil { + return x.xxx_hidden_OrganizationSlug + } + return "" +} + +func (x *AccountDetails) GetActiveAuthenticationMethod() *AuthenticationMethod { + if x != nil { + return x.xxx_hidden_ActiveAuthenticationMethod + } + return nil +} + +func (x *AccountDetails) SetUserName(v string) { + x.xxx_hidden_UserName = v +} + +func (x *AccountDetails) SetEmail(v string) { + x.xxx_hidden_Email = v +} + +func (x *AccountDetails) SetOrganizationName(v string) { + x.xxx_hidden_OrganizationName = v +} + +func (x *AccountDetails) SetOrganizationSlug(v string) { + x.xxx_hidden_OrganizationSlug = v +} + +func (x *AccountDetails) SetActiveAuthenticationMethod(v *AuthenticationMethod) { + x.xxx_hidden_ActiveAuthenticationMethod = v +} + +func (x *AccountDetails) HasActiveAuthenticationMethod() bool { + if x == nil { + return false + } + return x.xxx_hidden_ActiveAuthenticationMethod != nil +} + +func (x *AccountDetails) ClearActiveAuthenticationMethod() { + x.xxx_hidden_ActiveAuthenticationMethod = nil +} + +type AccountDetails_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + UserName string + Email string + OrganizationName string + OrganizationSlug string + // The authentication method used to authenticate the request. + ActiveAuthenticationMethod *AuthenticationMethod +} + +func (b0 AccountDetails_builder) Build() *AccountDetails { + m0 := &AccountDetails{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_UserName = b.UserName + x.xxx_hidden_Email = b.Email + x.xxx_hidden_OrganizationName = b.OrganizationName + x.xxx_hidden_OrganizationSlug = b.OrganizationSlug + x.xxx_hidden_ActiveAuthenticationMethod = b.ActiveAuthenticationMethod + return m0 +} + +// AuthenticationMethod describes the credential used to authenticate the request. +type AuthenticationMethod struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Type AuthenticationMethod_Type `protobuf:"varint,1,opt,name=type,enum=accounts.v1alpha1.AuthenticationMethod_Type"` + xxx_hidden_ApiKey *APIKeyDetails `protobuf:"bytes,2,opt,name=api_key,json=apiKey"` + xxx_hidden_Jwt *JWTDetails `protobuf:"bytes,3,opt,name=jwt"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AuthenticationMethod) Reset() { + *x = AuthenticationMethod{} + mi := &file_accounts_v1alpha1_account_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AuthenticationMethod) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AuthenticationMethod) ProtoMessage() {} + +func (x *AuthenticationMethod) ProtoReflect() protoreflect.Message { + mi := &file_accounts_v1alpha1_account_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *AuthenticationMethod) GetType() AuthenticationMethod_Type { + if x != nil { + return x.xxx_hidden_Type + } + return AuthenticationMethod_TYPE_UNSPECIFIED +} + +func (x *AuthenticationMethod) GetApiKey() *APIKeyDetails { + if x != nil { + return x.xxx_hidden_ApiKey + } + return nil +} + +func (x *AuthenticationMethod) GetJwt() *JWTDetails { + if x != nil { + return x.xxx_hidden_Jwt + } + return nil +} + +func (x *AuthenticationMethod) SetType(v AuthenticationMethod_Type) { + x.xxx_hidden_Type = v +} + +func (x *AuthenticationMethod) SetApiKey(v *APIKeyDetails) { + x.xxx_hidden_ApiKey = v +} + +func (x *AuthenticationMethod) SetJwt(v *JWTDetails) { + x.xxx_hidden_Jwt = v +} + +func (x *AuthenticationMethod) HasApiKey() bool { + if x == nil { + return false + } + return x.xxx_hidden_ApiKey != nil +} + +func (x *AuthenticationMethod) HasJwt() bool { + if x == nil { + return false + } + return x.xxx_hidden_Jwt != nil +} + +func (x *AuthenticationMethod) ClearApiKey() { + x.xxx_hidden_ApiKey = nil +} + +func (x *AuthenticationMethod) ClearJwt() { + x.xxx_hidden_Jwt = nil +} + +type AuthenticationMethod_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Type AuthenticationMethod_Type + ApiKey *APIKeyDetails + Jwt *JWTDetails +} + +func (b0 AuthenticationMethod_builder) Build() *AuthenticationMethod { + m0 := &AuthenticationMethod{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Type = b.Type + x.xxx_hidden_ApiKey = b.ApiKey + x.xxx_hidden_Jwt = b.Jwt + return m0 +} + +// APIKeyDetails describes the API key used for the request without exposing its secret or internal identifier. +type APIKeyDetails struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Description string `protobuf:"bytes,1,opt,name=description"` + xxx_hidden_PublicIdentifier string `protobuf:"bytes,2,opt,name=public_identifier,json=publicIdentifier"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *APIKeyDetails) Reset() { + *x = APIKeyDetails{} + mi := &file_accounts_v1alpha1_account_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *APIKeyDetails) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*APIKeyDetails) ProtoMessage() {} + +func (x *APIKeyDetails) ProtoReflect() protoreflect.Message { + mi := &file_accounts_v1alpha1_account_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *APIKeyDetails) GetDescription() string { + if x != nil { + return x.xxx_hidden_Description + } + return "" +} + +func (x *APIKeyDetails) GetPublicIdentifier() string { + if x != nil { + return x.xxx_hidden_PublicIdentifier + } + return "" +} + +func (x *APIKeyDetails) SetDescription(v string) { + x.xxx_hidden_Description = v +} + +func (x *APIKeyDetails) SetPublicIdentifier(v string) { + x.xxx_hidden_PublicIdentifier = v +} + +type APIKeyDetails_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Description string + // The non-secret identifier embedded in the API key. + PublicIdentifier string +} + +func (b0 APIKeyDetails_builder) Build() *APIKeyDetails { + m0 := &APIKeyDetails{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Description = b.Description + x.xxx_hidden_PublicIdentifier = b.PublicIdentifier + return m0 +} + +// JWTDetails describes the verified JWT without exposing the token or subject and session identifiers. +type JWTDetails struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Issuer string `protobuf:"bytes,1,opt,name=issuer"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *JWTDetails) Reset() { + *x = JWTDetails{} + mi := &file_accounts_v1alpha1_account_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *JWTDetails) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JWTDetails) ProtoMessage() {} + +func (x *JWTDetails) ProtoReflect() protoreflect.Message { + mi := &file_accounts_v1alpha1_account_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *JWTDetails) GetIssuer() string { + if x != nil { + return x.xxx_hidden_Issuer + } + return "" +} + +func (x *JWTDetails) SetIssuer(v string) { + x.xxx_hidden_Issuer = v +} + +type JWTDetails_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // The verified issuer. For Clerk-authenticated requests, this is the Clerk issuer URL. + Issuer string +} + +func (b0 JWTDetails_builder) Build() *JWTDetails { + m0 := &JWTDetails{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Issuer = b.Issuer + return m0 +} + +var File_accounts_v1alpha1_account_proto protoreflect.FileDescriptor + +const file_accounts_v1alpha1_account_proto_rawDesc = "" + + "\n" + + "\x1faccounts/v1alpha1/account.proto\x12\x11accounts.v1alpha1\x1a\x1bbuf/validate/validate.proto\"\x1a\n" + + "\x18GetAccountDetailsRequest\"\x88\x02\n" + + "\x0eAccountDetails\x12\x1b\n" + + "\tuser_name\x18\x01 \x01(\tR\buserName\x12\x14\n" + + "\x05email\x18\x02 \x01(\tR\x05email\x12+\n" + + "\x11organization_name\x18\x03 \x01(\tR\x10organizationName\x12+\n" + + "\x11organization_slug\x18\x04 \x01(\tR\x10organizationSlug\x12i\n" + + "\x1cactive_authentication_method\x18\x05 \x01(\v2'.accounts.v1alpha1.AuthenticationMethodR\x1aactiveAuthenticationMethod\"\xd5\x03\n" + + "\x14AuthenticationMethod\x12L\n" + + "\x04type\x18\x01 \x01(\x0e2,.accounts.v1alpha1.AuthenticationMethod.TypeB\n" + + "\xbaH\a\x82\x01\x04\x10\x01 \x00R\x04type\x129\n" + + "\aapi_key\x18\x02 \x01(\v2 .accounts.v1alpha1.APIKeyDetailsR\x06apiKey\x12/\n" + + "\x03jwt\x18\x03 \x01(\v2\x1d.accounts.v1alpha1.JWTDetailsR\x03jwt\"<\n" + + "\x04Type\x12\x14\n" + + "\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n" + + "\fTYPE_API_KEY\x10\x01\x12\f\n" + + "\bTYPE_JWT\x10\x02:\xc4\x01\xbaH\xc0\x01\x1a\xab\x01\n" + + "*authentication_method.type_matches_details\x121authentication method type must match its details\x1aJ(this.type == 1 && has(this.api_key)) || (this.type == 2 && has(this.jwt))\"\x10\n" + + "\aapi_key\n" + + "\x03jwt\x10\x01\"^\n" + + "\rAPIKeyDetails\x12 \n" + + "\vdescription\x18\x01 \x01(\tR\vdescription\x12+\n" + + "\x11public_identifier\x18\x02 \x01(\tR\x10publicIdentifier\"0\n" + + "\n" + + "JWTDetails\x12\"\n" + + "\x06issuer\x18\x01 \x01(\tB\n" + + "\xbaH\ar\x05\x10\x01\x88\x01\x01R\x06issuer2w\n" + + "\x0eAccountService\x12e\n" + + "\x11GetAccountDetails\x12+.accounts.v1alpha1.GetAccountDetailsRequest\x1a!.accounts.v1alpha1.AccountDetails\"\x00B\xda\x01\n" + + "\x15com.accounts.v1alpha1B\fAccountProtoP\x01ZIgithub.com/tilebox/tilebox-go/protogen/accounts/v1alpha1;accountsv1alpha1\xa2\x02\x03AXX\xaa\x02\x11Accounts.V1alpha1\xca\x02\x11Accounts\\V1alpha1\xe2\x02\x1dAccounts\\V1alpha1\\GPBMetadata\xea\x02\x12Accounts::V1alpha1\x92\x03\x02\b\x02b\beditionsp\xe8\a" + +var file_accounts_v1alpha1_account_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_accounts_v1alpha1_account_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_accounts_v1alpha1_account_proto_goTypes = []any{ + (AuthenticationMethod_Type)(0), // 0: accounts.v1alpha1.AuthenticationMethod.Type + (*GetAccountDetailsRequest)(nil), // 1: accounts.v1alpha1.GetAccountDetailsRequest + (*AccountDetails)(nil), // 2: accounts.v1alpha1.AccountDetails + (*AuthenticationMethod)(nil), // 3: accounts.v1alpha1.AuthenticationMethod + (*APIKeyDetails)(nil), // 4: accounts.v1alpha1.APIKeyDetails + (*JWTDetails)(nil), // 5: accounts.v1alpha1.JWTDetails +} +var file_accounts_v1alpha1_account_proto_depIdxs = []int32{ + 3, // 0: accounts.v1alpha1.AccountDetails.active_authentication_method:type_name -> accounts.v1alpha1.AuthenticationMethod + 0, // 1: accounts.v1alpha1.AuthenticationMethod.type:type_name -> accounts.v1alpha1.AuthenticationMethod.Type + 4, // 2: accounts.v1alpha1.AuthenticationMethod.api_key:type_name -> accounts.v1alpha1.APIKeyDetails + 5, // 3: accounts.v1alpha1.AuthenticationMethod.jwt:type_name -> accounts.v1alpha1.JWTDetails + 1, // 4: accounts.v1alpha1.AccountService.GetAccountDetails:input_type -> accounts.v1alpha1.GetAccountDetailsRequest + 2, // 5: accounts.v1alpha1.AccountService.GetAccountDetails:output_type -> accounts.v1alpha1.AccountDetails + 5, // [5:6] is the sub-list for method output_type + 4, // [4:5] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name +} + +func init() { file_accounts_v1alpha1_account_proto_init() } +func file_accounts_v1alpha1_account_proto_init() { + if File_accounts_v1alpha1_account_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_accounts_v1alpha1_account_proto_rawDesc), len(file_accounts_v1alpha1_account_proto_rawDesc)), + NumEnums: 1, + NumMessages: 5, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_accounts_v1alpha1_account_proto_goTypes, + DependencyIndexes: file_accounts_v1alpha1_account_proto_depIdxs, + EnumInfos: file_accounts_v1alpha1_account_proto_enumTypes, + MessageInfos: file_accounts_v1alpha1_account_proto_msgTypes, + }.Build() + File_accounts_v1alpha1_account_proto = out.File + file_accounts_v1alpha1_account_proto_goTypes = nil + file_accounts_v1alpha1_account_proto_depIdxs = nil +} diff --git a/protogen/accounts/v1alpha1/account_grpc.pb.go b/protogen/accounts/v1alpha1/account_grpc.pb.go new file mode 100644 index 0000000..d017724 --- /dev/null +++ b/protogen/accounts/v1alpha1/account_grpc.pb.go @@ -0,0 +1,131 @@ +// Public API for resolving account details associated with an authenticated request. + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.2 +// - protoc (unknown) +// source: accounts/v1alpha1/account.proto + +package accountsv1alpha1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + AccountService_GetAccountDetails_FullMethodName = "/accounts.v1alpha1.AccountService/GetAccountDetails" +) + +// AccountServiceClient is the client API for AccountService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// AccountService exposes information about the account associated with an authenticated request. +type AccountServiceClient interface { + // GetAccountDetails resolves the calling credential to its effective account details. + // Requests without valid authentication fail with UNAUTHENTICATED. + GetAccountDetails(ctx context.Context, in *GetAccountDetailsRequest, opts ...grpc.CallOption) (*AccountDetails, error) +} + +type accountServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewAccountServiceClient(cc grpc.ClientConnInterface) AccountServiceClient { + return &accountServiceClient{cc} +} + +func (c *accountServiceClient) GetAccountDetails(ctx context.Context, in *GetAccountDetailsRequest, opts ...grpc.CallOption) (*AccountDetails, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(AccountDetails) + err := c.cc.Invoke(ctx, AccountService_GetAccountDetails_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// AccountServiceServer is the server API for AccountService service. +// All implementations must embed UnimplementedAccountServiceServer +// for forward compatibility. +// +// AccountService exposes information about the account associated with an authenticated request. +type AccountServiceServer interface { + // GetAccountDetails resolves the calling credential to its effective account details. + // Requests without valid authentication fail with UNAUTHENTICATED. + GetAccountDetails(context.Context, *GetAccountDetailsRequest) (*AccountDetails, error) + mustEmbedUnimplementedAccountServiceServer() +} + +// UnimplementedAccountServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedAccountServiceServer struct{} + +func (UnimplementedAccountServiceServer) GetAccountDetails(context.Context, *GetAccountDetailsRequest) (*AccountDetails, error) { + return nil, status.Error(codes.Unimplemented, "method GetAccountDetails not implemented") +} +func (UnimplementedAccountServiceServer) mustEmbedUnimplementedAccountServiceServer() {} +func (UnimplementedAccountServiceServer) testEmbeddedByValue() {} + +// UnsafeAccountServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AccountServiceServer will +// result in compilation errors. +type UnsafeAccountServiceServer interface { + mustEmbedUnimplementedAccountServiceServer() +} + +func RegisterAccountServiceServer(s grpc.ServiceRegistrar, srv AccountServiceServer) { + // If the following call panics, it indicates UnimplementedAccountServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&AccountService_ServiceDesc, srv) +} + +func _AccountService_GetAccountDetails_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetAccountDetailsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AccountServiceServer).GetAccountDetails(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AccountService_GetAccountDetails_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AccountServiceServer).GetAccountDetails(ctx, req.(*GetAccountDetailsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// AccountService_ServiceDesc is the grpc.ServiceDesc for AccountService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var AccountService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "accounts.v1alpha1.AccountService", + HandlerType: (*AccountServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetAccountDetails", + Handler: _AccountService_GetAccountDetails_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "accounts/v1alpha1/account.proto", +} diff --git a/protogen/accounts/v1alpha1/accountsv1alpha1connect/account.connect.go b/protogen/accounts/v1alpha1/accountsv1alpha1connect/account.connect.go new file mode 100644 index 0000000..705c8e3 --- /dev/null +++ b/protogen/accounts/v1alpha1/accountsv1alpha1connect/account.connect.go @@ -0,0 +1,115 @@ +// Public API for resolving account details associated with an authenticated request. + +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: accounts/v1alpha1/account.proto + +package accountsv1alpha1connect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + v1alpha1 "github.com/tilebox/tilebox-go/protogen/accounts/v1alpha1" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion1_13_0 + +const ( + // AccountServiceName is the fully-qualified name of the AccountService service. + AccountServiceName = "accounts.v1alpha1.AccountService" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // AccountServiceGetAccountDetailsProcedure is the fully-qualified name of the AccountService's + // GetAccountDetails RPC. + AccountServiceGetAccountDetailsProcedure = "/accounts.v1alpha1.AccountService/GetAccountDetails" +) + +// AccountServiceClient is a client for the accounts.v1alpha1.AccountService service. +type AccountServiceClient interface { + // GetAccountDetails resolves the calling credential to its effective account details. + // Requests without valid authentication fail with UNAUTHENTICATED. + GetAccountDetails(context.Context, *connect.Request[v1alpha1.GetAccountDetailsRequest]) (*connect.Response[v1alpha1.AccountDetails], error) +} + +// NewAccountServiceClient constructs a client for the accounts.v1alpha1.AccountService service. By +// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, +// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the +// connect.WithGRPC() or connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewAccountServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) AccountServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + accountServiceMethods := v1alpha1.File_accounts_v1alpha1_account_proto.Services().ByName("AccountService").Methods() + return &accountServiceClient{ + getAccountDetails: connect.NewClient[v1alpha1.GetAccountDetailsRequest, v1alpha1.AccountDetails]( + httpClient, + baseURL+AccountServiceGetAccountDetailsProcedure, + connect.WithSchema(accountServiceMethods.ByName("GetAccountDetails")), + connect.WithClientOptions(opts...), + ), + } +} + +// accountServiceClient implements AccountServiceClient. +type accountServiceClient struct { + getAccountDetails *connect.Client[v1alpha1.GetAccountDetailsRequest, v1alpha1.AccountDetails] +} + +// GetAccountDetails calls accounts.v1alpha1.AccountService.GetAccountDetails. +func (c *accountServiceClient) GetAccountDetails(ctx context.Context, req *connect.Request[v1alpha1.GetAccountDetailsRequest]) (*connect.Response[v1alpha1.AccountDetails], error) { + return c.getAccountDetails.CallUnary(ctx, req) +} + +// AccountServiceHandler is an implementation of the accounts.v1alpha1.AccountService service. +type AccountServiceHandler interface { + // GetAccountDetails resolves the calling credential to its effective account details. + // Requests without valid authentication fail with UNAUTHENTICATED. + GetAccountDetails(context.Context, *connect.Request[v1alpha1.GetAccountDetailsRequest]) (*connect.Response[v1alpha1.AccountDetails], error) +} + +// NewAccountServiceHandler builds an HTTP handler from the service implementation. It returns the +// path on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewAccountServiceHandler(svc AccountServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + accountServiceMethods := v1alpha1.File_accounts_v1alpha1_account_proto.Services().ByName("AccountService").Methods() + accountServiceGetAccountDetailsHandler := connect.NewUnaryHandler( + AccountServiceGetAccountDetailsProcedure, + svc.GetAccountDetails, + connect.WithSchema(accountServiceMethods.ByName("GetAccountDetails")), + connect.WithHandlerOptions(opts...), + ) + return "/accounts.v1alpha1.AccountService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case AccountServiceGetAccountDetailsProcedure: + accountServiceGetAccountDetailsHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedAccountServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedAccountServiceHandler struct{} + +func (UnimplementedAccountServiceHandler) GetAccountDetails(context.Context, *connect.Request[v1alpha1.GetAccountDetailsRequest]) (*connect.Response[v1alpha1.AccountDetails], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("accounts.v1alpha1.AccountService.GetAccountDetails is not implemented")) +} diff --git a/protogen/accounts/v1alpha1/accountsv1alpha1connect/billing.connect.go b/protogen/accounts/v1alpha1/accountsv1alpha1connect/billing.connect.go new file mode 100644 index 0000000..15e3266 --- /dev/null +++ b/protogen/accounts/v1alpha1/accountsv1alpha1connect/billing.connect.go @@ -0,0 +1,140 @@ +// Public API for reading subscription plan and usage information. + +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: accounts/v1alpha1/billing.proto + +package accountsv1alpha1connect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + v1alpha1 "github.com/tilebox/tilebox-go/protogen/accounts/v1alpha1" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion1_13_0 + +const ( + // BillingServiceName is the fully-qualified name of the BillingService service. + BillingServiceName = "accounts.v1alpha1.BillingService" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // BillingServiceGetActivePlanProcedure is the fully-qualified name of the BillingService's + // GetActivePlan RPC. + BillingServiceGetActivePlanProcedure = "/accounts.v1alpha1.BillingService/GetActivePlan" + // BillingServiceGetUsageReportProcedure is the fully-qualified name of the BillingService's + // GetUsageReport RPC. + BillingServiceGetUsageReportProcedure = "/accounts.v1alpha1.BillingService/GetUsageReport" +) + +// BillingServiceClient is a client for the accounts.v1alpha1.BillingService service. +type BillingServiceClient interface { + GetActivePlan(context.Context, *connect.Request[v1alpha1.GetActivePlanRequest]) (*connect.Response[v1alpha1.Plan], error) + GetUsageReport(context.Context, *connect.Request[v1alpha1.GetUsageReportRequest]) (*connect.Response[v1alpha1.UsageReport], error) +} + +// NewBillingServiceClient constructs a client for the accounts.v1alpha1.BillingService service. By +// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, +// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the +// connect.WithGRPC() or connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewBillingServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) BillingServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + billingServiceMethods := v1alpha1.File_accounts_v1alpha1_billing_proto.Services().ByName("BillingService").Methods() + return &billingServiceClient{ + getActivePlan: connect.NewClient[v1alpha1.GetActivePlanRequest, v1alpha1.Plan]( + httpClient, + baseURL+BillingServiceGetActivePlanProcedure, + connect.WithSchema(billingServiceMethods.ByName("GetActivePlan")), + connect.WithClientOptions(opts...), + ), + getUsageReport: connect.NewClient[v1alpha1.GetUsageReportRequest, v1alpha1.UsageReport]( + httpClient, + baseURL+BillingServiceGetUsageReportProcedure, + connect.WithSchema(billingServiceMethods.ByName("GetUsageReport")), + connect.WithClientOptions(opts...), + ), + } +} + +// billingServiceClient implements BillingServiceClient. +type billingServiceClient struct { + getActivePlan *connect.Client[v1alpha1.GetActivePlanRequest, v1alpha1.Plan] + getUsageReport *connect.Client[v1alpha1.GetUsageReportRequest, v1alpha1.UsageReport] +} + +// GetActivePlan calls accounts.v1alpha1.BillingService.GetActivePlan. +func (c *billingServiceClient) GetActivePlan(ctx context.Context, req *connect.Request[v1alpha1.GetActivePlanRequest]) (*connect.Response[v1alpha1.Plan], error) { + return c.getActivePlan.CallUnary(ctx, req) +} + +// GetUsageReport calls accounts.v1alpha1.BillingService.GetUsageReport. +func (c *billingServiceClient) GetUsageReport(ctx context.Context, req *connect.Request[v1alpha1.GetUsageReportRequest]) (*connect.Response[v1alpha1.UsageReport], error) { + return c.getUsageReport.CallUnary(ctx, req) +} + +// BillingServiceHandler is an implementation of the accounts.v1alpha1.BillingService service. +type BillingServiceHandler interface { + GetActivePlan(context.Context, *connect.Request[v1alpha1.GetActivePlanRequest]) (*connect.Response[v1alpha1.Plan], error) + GetUsageReport(context.Context, *connect.Request[v1alpha1.GetUsageReportRequest]) (*connect.Response[v1alpha1.UsageReport], error) +} + +// NewBillingServiceHandler builds an HTTP handler from the service implementation. It returns the +// path on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewBillingServiceHandler(svc BillingServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + billingServiceMethods := v1alpha1.File_accounts_v1alpha1_billing_proto.Services().ByName("BillingService").Methods() + billingServiceGetActivePlanHandler := connect.NewUnaryHandler( + BillingServiceGetActivePlanProcedure, + svc.GetActivePlan, + connect.WithSchema(billingServiceMethods.ByName("GetActivePlan")), + connect.WithHandlerOptions(opts...), + ) + billingServiceGetUsageReportHandler := connect.NewUnaryHandler( + BillingServiceGetUsageReportProcedure, + svc.GetUsageReport, + connect.WithSchema(billingServiceMethods.ByName("GetUsageReport")), + connect.WithHandlerOptions(opts...), + ) + return "/accounts.v1alpha1.BillingService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case BillingServiceGetActivePlanProcedure: + billingServiceGetActivePlanHandler.ServeHTTP(w, r) + case BillingServiceGetUsageReportProcedure: + billingServiceGetUsageReportHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedBillingServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedBillingServiceHandler struct{} + +func (UnimplementedBillingServiceHandler) GetActivePlan(context.Context, *connect.Request[v1alpha1.GetActivePlanRequest]) (*connect.Response[v1alpha1.Plan], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("accounts.v1alpha1.BillingService.GetActivePlan is not implemented")) +} + +func (UnimplementedBillingServiceHandler) GetUsageReport(context.Context, *connect.Request[v1alpha1.GetUsageReportRequest]) (*connect.Response[v1alpha1.UsageReport], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("accounts.v1alpha1.BillingService.GetUsageReport is not implemented")) +} diff --git a/protogen/accounts/v1alpha1/billing.pb.go b/protogen/accounts/v1alpha1/billing.pb.go new file mode 100644 index 0000000..e642d57 --- /dev/null +++ b/protogen/accounts/v1alpha1/billing.pb.go @@ -0,0 +1,1142 @@ +// Public API for reading subscription plan and usage information. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: accounts/v1alpha1/billing.proto + +package accountsv1alpha1 + +import ( + _ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// SubscriptionTier identifies the type of subscription an organization has. +type SubscriptionTier int32 + +const ( + SubscriptionTier_SUBSCRIPTION_TIER_UNSPECIFIED SubscriptionTier = 0 + SubscriptionTier_SUBSCRIPTION_TIER_FREE SubscriptionTier = 1 + SubscriptionTier_SUBSCRIPTION_TIER_PAID SubscriptionTier = 2 + SubscriptionTier_SUBSCRIPTION_TIER_CUSTOM SubscriptionTier = 3 +) + +// Enum value maps for SubscriptionTier. +var ( + SubscriptionTier_name = map[int32]string{ + 0: "SUBSCRIPTION_TIER_UNSPECIFIED", + 1: "SUBSCRIPTION_TIER_FREE", + 2: "SUBSCRIPTION_TIER_PAID", + 3: "SUBSCRIPTION_TIER_CUSTOM", + } + SubscriptionTier_value = map[string]int32{ + "SUBSCRIPTION_TIER_UNSPECIFIED": 0, + "SUBSCRIPTION_TIER_FREE": 1, + "SUBSCRIPTION_TIER_PAID": 2, + "SUBSCRIPTION_TIER_CUSTOM": 3, + } +) + +func (x SubscriptionTier) Enum() *SubscriptionTier { + p := new(SubscriptionTier) + *p = x + return p +} + +func (x SubscriptionTier) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SubscriptionTier) Descriptor() protoreflect.EnumDescriptor { + return file_accounts_v1alpha1_billing_proto_enumTypes[0].Descriptor() +} + +func (SubscriptionTier) Type() protoreflect.EnumType { + return &file_accounts_v1alpha1_billing_proto_enumTypes[0] +} + +func (x SubscriptionTier) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// BillingCadence is the period in which the base subscription and add-ons are billed. +type BillingCadence int32 + +const ( + BillingCadence_BILLING_CADENCE_UNSPECIFIED BillingCadence = 0 + BillingCadence_BILLING_CADENCE_MONTHLY BillingCadence = 1 + BillingCadence_BILLING_CADENCE_YEARLY BillingCadence = 2 +) + +// Enum value maps for BillingCadence. +var ( + BillingCadence_name = map[int32]string{ + 0: "BILLING_CADENCE_UNSPECIFIED", + 1: "BILLING_CADENCE_MONTHLY", + 2: "BILLING_CADENCE_YEARLY", + } + BillingCadence_value = map[string]int32{ + "BILLING_CADENCE_UNSPECIFIED": 0, + "BILLING_CADENCE_MONTHLY": 1, + "BILLING_CADENCE_YEARLY": 2, + } +) + +func (x BillingCadence) Enum() *BillingCadence { + p := new(BillingCadence) + *p = x + return p +} + +func (x BillingCadence) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (BillingCadence) Descriptor() protoreflect.EnumDescriptor { + return file_accounts_v1alpha1_billing_proto_enumTypes[1].Descriptor() +} + +func (BillingCadence) Type() protoreflect.EnumType { + return &file_accounts_v1alpha1_billing_proto_enumTypes[1] +} + +func (x BillingCadence) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Unit identifies the unit in which a usage metric is measured. +type Unit int32 + +const ( + Unit_UNIT_UNSPECIFIED Unit = 0 + Unit_UNIT_NO_UNIT Unit = 1 + Unit_UNIT_BYTES Unit = 2 + Unit_UNIT_SECONDS Unit = 3 +) + +// Enum value maps for Unit. +var ( + Unit_name = map[int32]string{ + 0: "UNIT_UNSPECIFIED", + 1: "UNIT_NO_UNIT", + 2: "UNIT_BYTES", + 3: "UNIT_SECONDS", + } + Unit_value = map[string]int32{ + "UNIT_UNSPECIFIED": 0, + "UNIT_NO_UNIT": 1, + "UNIT_BYTES": 2, + "UNIT_SECONDS": 3, + } +) + +func (x Unit) Enum() *Unit { + p := new(Unit) + *p = x + return p +} + +func (x Unit) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Unit) Descriptor() protoreflect.EnumDescriptor { + return file_accounts_v1alpha1_billing_proto_enumTypes[2].Descriptor() +} + +func (Unit) Type() protoreflect.EnumType { + return &file_accounts_v1alpha1_billing_proto_enumTypes[2] +} + +func (x Unit) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// MetricAggregation describes how the current value of a metric was aggregated. +type MetricAggregation int32 + +const ( + MetricAggregation_METRIC_AGGREGATION_UNSPECIFIED MetricAggregation = 0 + MetricAggregation_METRIC_AGGREGATION_TOTAL MetricAggregation = 1 + MetricAggregation_METRIC_AGGREGATION_USAGE_PERIOD MetricAggregation = 2 +) + +// Enum value maps for MetricAggregation. +var ( + MetricAggregation_name = map[int32]string{ + 0: "METRIC_AGGREGATION_UNSPECIFIED", + 1: "METRIC_AGGREGATION_TOTAL", + 2: "METRIC_AGGREGATION_USAGE_PERIOD", + } + MetricAggregation_value = map[string]int32{ + "METRIC_AGGREGATION_UNSPECIFIED": 0, + "METRIC_AGGREGATION_TOTAL": 1, + "METRIC_AGGREGATION_USAGE_PERIOD": 2, + } +) + +func (x MetricAggregation) Enum() *MetricAggregation { + p := new(MetricAggregation) + *p = x + return p +} + +func (x MetricAggregation) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MetricAggregation) Descriptor() protoreflect.EnumDescriptor { + return file_accounts_v1alpha1_billing_proto_enumTypes[3].Descriptor() +} + +func (MetricAggregation) Type() protoreflect.EnumType { + return &file_accounts_v1alpha1_billing_proto_enumTypes[3] +} + +func (x MetricAggregation) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// BillingPeriod describes the time range and anchor of a billing period. +type BillingPeriod struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Start *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=start"` + xxx_hidden_End *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=end"` + xxx_hidden_Anchor *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=anchor"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BillingPeriod) Reset() { + *x = BillingPeriod{} + mi := &file_accounts_v1alpha1_billing_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BillingPeriod) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BillingPeriod) ProtoMessage() {} + +func (x *BillingPeriod) ProtoReflect() protoreflect.Message { + mi := &file_accounts_v1alpha1_billing_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *BillingPeriod) GetStart() *timestamppb.Timestamp { + if x != nil { + return x.xxx_hidden_Start + } + return nil +} + +func (x *BillingPeriod) GetEnd() *timestamppb.Timestamp { + if x != nil { + return x.xxx_hidden_End + } + return nil +} + +func (x *BillingPeriod) GetAnchor() *timestamppb.Timestamp { + if x != nil { + return x.xxx_hidden_Anchor + } + return nil +} + +func (x *BillingPeriod) SetStart(v *timestamppb.Timestamp) { + x.xxx_hidden_Start = v +} + +func (x *BillingPeriod) SetEnd(v *timestamppb.Timestamp) { + x.xxx_hidden_End = v +} + +func (x *BillingPeriod) SetAnchor(v *timestamppb.Timestamp) { + x.xxx_hidden_Anchor = v +} + +func (x *BillingPeriod) HasStart() bool { + if x == nil { + return false + } + return x.xxx_hidden_Start != nil +} + +func (x *BillingPeriod) HasEnd() bool { + if x == nil { + return false + } + return x.xxx_hidden_End != nil +} + +func (x *BillingPeriod) HasAnchor() bool { + if x == nil { + return false + } + return x.xxx_hidden_Anchor != nil +} + +func (x *BillingPeriod) ClearStart() { + x.xxx_hidden_Start = nil +} + +func (x *BillingPeriod) ClearEnd() { + x.xxx_hidden_End = nil +} + +func (x *BillingPeriod) ClearAnchor() { + x.xxx_hidden_Anchor = nil +} + +type BillingPeriod_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Start *timestamppb.Timestamp + End *timestamppb.Timestamp + Anchor *timestamppb.Timestamp +} + +func (b0 BillingPeriod_builder) Build() *BillingPeriod { + m0 := &BillingPeriod{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Start = b.Start + x.xxx_hidden_End = b.End + x.xxx_hidden_Anchor = b.Anchor + return m0 +} + +// Plan describes the active subscription plan of an organization. +type Plan struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Tier SubscriptionTier `protobuf:"varint,1,opt,name=tier,enum=accounts.v1alpha1.SubscriptionTier"` + xxx_hidden_AddOns []string `protobuf:"bytes,2,rep,name=add_ons,json=addOns"` + xxx_hidden_BillingCadence BillingCadence `protobuf:"varint,3,opt,name=billing_cadence,json=billingCadence,enum=accounts.v1alpha1.BillingCadence"` + xxx_hidden_SubscriptionBillingPeriod *BillingPeriod `protobuf:"bytes,4,opt,name=subscription_billing_period,json=subscriptionBillingPeriod"` + xxx_hidden_UsageBillingPeriod *BillingPeriod `protobuf:"bytes,5,opt,name=usage_billing_period,json=usageBillingPeriod"` + xxx_hidden_ValidUntil *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=valid_until,json=validUntil"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Plan) Reset() { + *x = Plan{} + mi := &file_accounts_v1alpha1_billing_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Plan) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Plan) ProtoMessage() {} + +func (x *Plan) ProtoReflect() protoreflect.Message { + mi := &file_accounts_v1alpha1_billing_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Plan) GetTier() SubscriptionTier { + if x != nil { + return x.xxx_hidden_Tier + } + return SubscriptionTier_SUBSCRIPTION_TIER_UNSPECIFIED +} + +func (x *Plan) GetAddOns() []string { + if x != nil { + return x.xxx_hidden_AddOns + } + return nil +} + +func (x *Plan) GetBillingCadence() BillingCadence { + if x != nil { + return x.xxx_hidden_BillingCadence + } + return BillingCadence_BILLING_CADENCE_UNSPECIFIED +} + +func (x *Plan) GetSubscriptionBillingPeriod() *BillingPeriod { + if x != nil { + return x.xxx_hidden_SubscriptionBillingPeriod + } + return nil +} + +func (x *Plan) GetUsageBillingPeriod() *BillingPeriod { + if x != nil { + return x.xxx_hidden_UsageBillingPeriod + } + return nil +} + +func (x *Plan) GetValidUntil() *timestamppb.Timestamp { + if x != nil { + return x.xxx_hidden_ValidUntil + } + return nil +} + +func (x *Plan) SetTier(v SubscriptionTier) { + x.xxx_hidden_Tier = v +} + +func (x *Plan) SetAddOns(v []string) { + x.xxx_hidden_AddOns = v +} + +func (x *Plan) SetBillingCadence(v BillingCadence) { + x.xxx_hidden_BillingCadence = v +} + +func (x *Plan) SetSubscriptionBillingPeriod(v *BillingPeriod) { + x.xxx_hidden_SubscriptionBillingPeriod = v +} + +func (x *Plan) SetUsageBillingPeriod(v *BillingPeriod) { + x.xxx_hidden_UsageBillingPeriod = v +} + +func (x *Plan) SetValidUntil(v *timestamppb.Timestamp) { + x.xxx_hidden_ValidUntil = v +} + +func (x *Plan) HasSubscriptionBillingPeriod() bool { + if x == nil { + return false + } + return x.xxx_hidden_SubscriptionBillingPeriod != nil +} + +func (x *Plan) HasUsageBillingPeriod() bool { + if x == nil { + return false + } + return x.xxx_hidden_UsageBillingPeriod != nil +} + +func (x *Plan) HasValidUntil() bool { + if x == nil { + return false + } + return x.xxx_hidden_ValidUntil != nil +} + +func (x *Plan) ClearSubscriptionBillingPeriod() { + x.xxx_hidden_SubscriptionBillingPeriod = nil +} + +func (x *Plan) ClearUsageBillingPeriod() { + x.xxx_hidden_UsageBillingPeriod = nil +} + +func (x *Plan) ClearValidUntil() { + x.xxx_hidden_ValidUntil = nil +} + +type Plan_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Tier SubscriptionTier + AddOns []string + BillingCadence BillingCadence + SubscriptionBillingPeriod *BillingPeriod + UsageBillingPeriod *BillingPeriod + // Set when a canceled subscription remains valid until the given time. + ValidUntil *timestamppb.Timestamp +} + +func (b0 Plan_builder) Build() *Plan { + m0 := &Plan{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Tier = b.Tier + x.xxx_hidden_AddOns = b.AddOns + x.xxx_hidden_BillingCadence = b.BillingCadence + x.xxx_hidden_SubscriptionBillingPeriod = b.SubscriptionBillingPeriod + x.xxx_hidden_UsageBillingPeriod = b.UsageBillingPeriod + x.xxx_hidden_ValidUntil = b.ValidUntil + return m0 +} + +// UsageRecord is the value of a metric at a specific time. +type UsageRecord struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Timestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=timestamp"` + xxx_hidden_Value int64 `protobuf:"varint,2,opt,name=value"` + xxx_hidden_CumulativeValue int64 `protobuf:"varint,3,opt,name=cumulative_value,json=cumulativeValue"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UsageRecord) Reset() { + *x = UsageRecord{} + mi := &file_accounts_v1alpha1_billing_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UsageRecord) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UsageRecord) ProtoMessage() {} + +func (x *UsageRecord) ProtoReflect() protoreflect.Message { + mi := &file_accounts_v1alpha1_billing_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *UsageRecord) GetTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.xxx_hidden_Timestamp + } + return nil +} + +func (x *UsageRecord) GetValue() int64 { + if x != nil { + return x.xxx_hidden_Value + } + return 0 +} + +func (x *UsageRecord) GetCumulativeValue() int64 { + if x != nil { + return x.xxx_hidden_CumulativeValue + } + return 0 +} + +func (x *UsageRecord) SetTimestamp(v *timestamppb.Timestamp) { + x.xxx_hidden_Timestamp = v +} + +func (x *UsageRecord) SetValue(v int64) { + x.xxx_hidden_Value = v +} + +func (x *UsageRecord) SetCumulativeValue(v int64) { + x.xxx_hidden_CumulativeValue = v +} + +func (x *UsageRecord) HasTimestamp() bool { + if x == nil { + return false + } + return x.xxx_hidden_Timestamp != nil +} + +func (x *UsageRecord) ClearTimestamp() { + x.xxx_hidden_Timestamp = nil +} + +type UsageRecord_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Timestamp *timestamppb.Timestamp + Value int64 + CumulativeValue int64 +} + +func (b0 UsageRecord_builder) Build() *UsageRecord { + m0 := &UsageRecord{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Timestamp = b.Timestamp + x.xxx_hidden_Value = b.Value + x.xxx_hidden_CumulativeValue = b.CumulativeValue + return m0 +} + +// UsageHistory contains the historical values and billing periods of a metric. +type UsageHistory struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_UsagePeriods *[]*BillingPeriod `protobuf:"bytes,1,rep,name=usage_periods,json=usagePeriods"` + xxx_hidden_Records *[]*UsageRecord `protobuf:"bytes,2,rep,name=records"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UsageHistory) Reset() { + *x = UsageHistory{} + mi := &file_accounts_v1alpha1_billing_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UsageHistory) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UsageHistory) ProtoMessage() {} + +func (x *UsageHistory) ProtoReflect() protoreflect.Message { + mi := &file_accounts_v1alpha1_billing_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *UsageHistory) GetUsagePeriods() []*BillingPeriod { + if x != nil { + if x.xxx_hidden_UsagePeriods != nil { + return *x.xxx_hidden_UsagePeriods + } + } + return nil +} + +func (x *UsageHistory) GetRecords() []*UsageRecord { + if x != nil { + if x.xxx_hidden_Records != nil { + return *x.xxx_hidden_Records + } + } + return nil +} + +func (x *UsageHistory) SetUsagePeriods(v []*BillingPeriod) { + x.xxx_hidden_UsagePeriods = &v +} + +func (x *UsageHistory) SetRecords(v []*UsageRecord) { + x.xxx_hidden_Records = &v +} + +type UsageHistory_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + UsagePeriods []*BillingPeriod + Records []*UsageRecord +} + +func (b0 UsageHistory_builder) Build() *UsageHistory { + m0 := &UsageHistory{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_UsagePeriods = &b.UsagePeriods + x.xxx_hidden_Records = &b.Records + return m0 +} + +// UsageMetric describes the current and historical consumption of an organization metric. +type UsageMetric struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Key string `protobuf:"bytes,1,opt,name=key"` + xxx_hidden_Unit Unit `protobuf:"varint,2,opt,name=unit,enum=accounts.v1alpha1.Unit"` + xxx_hidden_Limit int64 `protobuf:"varint,3,opt,name=limit"` + xxx_hidden_Value int64 `protobuf:"varint,4,opt,name=value"` + xxx_hidden_Aggregation MetricAggregation `protobuf:"varint,5,opt,name=aggregation,enum=accounts.v1alpha1.MetricAggregation"` + xxx_hidden_History *UsageHistory `protobuf:"bytes,6,opt,name=history"` + XXX_raceDetectHookData protoimpl.RaceDetectHookData + XXX_presence [1]uint32 + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UsageMetric) Reset() { + *x = UsageMetric{} + mi := &file_accounts_v1alpha1_billing_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UsageMetric) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UsageMetric) ProtoMessage() {} + +func (x *UsageMetric) ProtoReflect() protoreflect.Message { + mi := &file_accounts_v1alpha1_billing_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *UsageMetric) GetKey() string { + if x != nil { + return x.xxx_hidden_Key + } + return "" +} + +func (x *UsageMetric) GetUnit() Unit { + if x != nil { + return x.xxx_hidden_Unit + } + return Unit_UNIT_UNSPECIFIED +} + +func (x *UsageMetric) GetLimit() int64 { + if x != nil { + return x.xxx_hidden_Limit + } + return 0 +} + +func (x *UsageMetric) GetValue() int64 { + if x != nil { + return x.xxx_hidden_Value + } + return 0 +} + +func (x *UsageMetric) GetAggregation() MetricAggregation { + if x != nil { + return x.xxx_hidden_Aggregation + } + return MetricAggregation_METRIC_AGGREGATION_UNSPECIFIED +} + +func (x *UsageMetric) GetHistory() *UsageHistory { + if x != nil { + return x.xxx_hidden_History + } + return nil +} + +func (x *UsageMetric) SetKey(v string) { + x.xxx_hidden_Key = v +} + +func (x *UsageMetric) SetUnit(v Unit) { + x.xxx_hidden_Unit = v +} + +func (x *UsageMetric) SetLimit(v int64) { + x.xxx_hidden_Limit = v + protoimpl.X.SetPresent(&(x.XXX_presence[0]), 2, 6) +} + +func (x *UsageMetric) SetValue(v int64) { + x.xxx_hidden_Value = v +} + +func (x *UsageMetric) SetAggregation(v MetricAggregation) { + x.xxx_hidden_Aggregation = v +} + +func (x *UsageMetric) SetHistory(v *UsageHistory) { + x.xxx_hidden_History = v +} + +func (x *UsageMetric) HasLimit() bool { + if x == nil { + return false + } + return protoimpl.X.Present(&(x.XXX_presence[0]), 2) +} + +func (x *UsageMetric) HasHistory() bool { + if x == nil { + return false + } + return x.xxx_hidden_History != nil +} + +func (x *UsageMetric) ClearLimit() { + protoimpl.X.ClearPresent(&(x.XXX_presence[0]), 2) + x.xxx_hidden_Limit = 0 +} + +func (x *UsageMetric) ClearHistory() { + x.xxx_hidden_History = nil +} + +type UsageMetric_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Key string + Unit Unit + // Unset when the metric is unlimited. + Limit *int64 + Value int64 + Aggregation MetricAggregation + History *UsageHistory +} + +func (b0 UsageMetric_builder) Build() *UsageMetric { + m0 := &UsageMetric{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Key = b.Key + x.xxx_hidden_Unit = b.Unit + if b.Limit != nil { + protoimpl.X.SetPresentNonAtomic(&(x.XXX_presence[0]), 2, 6) + x.xxx_hidden_Limit = *b.Limit + } + x.xxx_hidden_Value = b.Value + x.xxx_hidden_Aggregation = b.Aggregation + x.xxx_hidden_History = b.History + return m0 +} + +// GetActivePlanRequest requests the active plan of the calling organization. +type GetActivePlanRequest struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetActivePlanRequest) Reset() { + *x = GetActivePlanRequest{} + mi := &file_accounts_v1alpha1_billing_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetActivePlanRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetActivePlanRequest) ProtoMessage() {} + +func (x *GetActivePlanRequest) ProtoReflect() protoreflect.Message { + mi := &file_accounts_v1alpha1_billing_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +type GetActivePlanRequest_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + +} + +func (b0 GetActivePlanRequest_builder) Build() *GetActivePlanRequest { + m0 := &GetActivePlanRequest{} + b, x := &b0, m0 + _, _ = b, x + return m0 +} + +// GetUsageReportRequest requests current usage and, optionally, historical values. +type GetUsageReportRequest struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_HistoryDays uint64 `protobuf:"varint,1,opt,name=history_days,json=historyDays"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetUsageReportRequest) Reset() { + *x = GetUsageReportRequest{} + mi := &file_accounts_v1alpha1_billing_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetUsageReportRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetUsageReportRequest) ProtoMessage() {} + +func (x *GetUsageReportRequest) ProtoReflect() protoreflect.Message { + mi := &file_accounts_v1alpha1_billing_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *GetUsageReportRequest) GetHistoryDays() uint64 { + if x != nil { + return x.xxx_hidden_HistoryDays + } + return 0 +} + +func (x *GetUsageReportRequest) SetHistoryDays(v uint64) { + x.xxx_hidden_HistoryDays = v +} + +type GetUsageReportRequest_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // The number of history days to return. Zero omits history. + HistoryDays uint64 +} + +func (b0 GetUsageReportRequest_builder) Build() *GetUsageReportRequest { + m0 := &GetUsageReportRequest{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_HistoryDays = b.HistoryDays + return m0 +} + +// UsageReport contains the usage metrics tracked for an organization. +type UsageReport struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Metrics *[]*UsageMetric `protobuf:"bytes,1,rep,name=metrics"` + xxx_hidden_UsagePeriod *BillingPeriod `protobuf:"bytes,2,opt,name=usage_period,json=usagePeriod"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UsageReport) Reset() { + *x = UsageReport{} + mi := &file_accounts_v1alpha1_billing_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UsageReport) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UsageReport) ProtoMessage() {} + +func (x *UsageReport) ProtoReflect() protoreflect.Message { + mi := &file_accounts_v1alpha1_billing_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *UsageReport) GetMetrics() []*UsageMetric { + if x != nil { + if x.xxx_hidden_Metrics != nil { + return *x.xxx_hidden_Metrics + } + } + return nil +} + +func (x *UsageReport) GetUsagePeriod() *BillingPeriod { + if x != nil { + return x.xxx_hidden_UsagePeriod + } + return nil +} + +func (x *UsageReport) SetMetrics(v []*UsageMetric) { + x.xxx_hidden_Metrics = &v +} + +func (x *UsageReport) SetUsagePeriod(v *BillingPeriod) { + x.xxx_hidden_UsagePeriod = v +} + +func (x *UsageReport) HasUsagePeriod() bool { + if x == nil { + return false + } + return x.xxx_hidden_UsagePeriod != nil +} + +func (x *UsageReport) ClearUsagePeriod() { + x.xxx_hidden_UsagePeriod = nil +} + +type UsageReport_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Metrics []*UsageMetric + UsagePeriod *BillingPeriod +} + +func (b0 UsageReport_builder) Build() *UsageReport { + m0 := &UsageReport{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Metrics = &b.Metrics + x.xxx_hidden_UsagePeriod = b.UsagePeriod + return m0 +} + +var File_accounts_v1alpha1_billing_proto protoreflect.FileDescriptor + +const file_accounts_v1alpha1_billing_proto_rawDesc = "" + + "\n" + + "\x1faccounts/v1alpha1/billing.proto\x12\x11accounts.v1alpha1\x1a\x1bbuf/validate/validate.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xa3\x01\n" + + "\rBillingPeriod\x120\n" + + "\x05start\x18\x01 \x01(\v2\x1a.google.protobuf.TimestampR\x05start\x12,\n" + + "\x03end\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\x03end\x122\n" + + "\x06anchor\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\x06anchor\"\x97\x03\n" + + "\x04Plan\x127\n" + + "\x04tier\x18\x01 \x01(\x0e2#.accounts.v1alpha1.SubscriptionTierR\x04tier\x12\x17\n" + + "\aadd_ons\x18\x02 \x03(\tR\x06addOns\x12J\n" + + "\x0fbilling_cadence\x18\x03 \x01(\x0e2!.accounts.v1alpha1.BillingCadenceR\x0ebillingCadence\x12`\n" + + "\x1bsubscription_billing_period\x18\x04 \x01(\v2 .accounts.v1alpha1.BillingPeriodR\x19subscriptionBillingPeriod\x12R\n" + + "\x14usage_billing_period\x18\x05 \x01(\v2 .accounts.v1alpha1.BillingPeriodR\x12usageBillingPeriod\x12;\n" + + "\vvalid_until\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\n" + + "validUntil\"\x88\x01\n" + + "\vUsageRecord\x128\n" + + "\ttimestamp\x18\x01 \x01(\v2\x1a.google.protobuf.TimestampR\ttimestamp\x12\x14\n" + + "\x05value\x18\x02 \x01(\x03R\x05value\x12)\n" + + "\x10cumulative_value\x18\x03 \x01(\x03R\x0fcumulativeValue\"\x8f\x01\n" + + "\fUsageHistory\x12E\n" + + "\rusage_periods\x18\x01 \x03(\v2 .accounts.v1alpha1.BillingPeriodR\fusagePeriods\x128\n" + + "\arecords\x18\x02 \x03(\v2\x1e.accounts.v1alpha1.UsageRecordR\arecords\"\x82\x02\n" + + "\vUsageMetric\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12+\n" + + "\x04unit\x18\x02 \x01(\x0e2\x17.accounts.v1alpha1.UnitR\x04unit\x12\x1b\n" + + "\x05limit\x18\x03 \x01(\x03B\x05\xaa\x01\x02\b\x01R\x05limit\x12\x14\n" + + "\x05value\x18\x04 \x01(\x03R\x05value\x12F\n" + + "\vaggregation\x18\x05 \x01(\x0e2$.accounts.v1alpha1.MetricAggregationR\vaggregation\x129\n" + + "\ahistory\x18\x06 \x01(\v2\x1f.accounts.v1alpha1.UsageHistoryR\ahistory\"\x16\n" + + "\x14GetActivePlanRequest\"D\n" + + "\x15GetUsageReportRequest\x12+\n" + + "\fhistory_days\x18\x01 \x01(\x04B\b\xbaH\x052\x03\x18\xed\x02R\vhistoryDays\"\x8c\x01\n" + + "\vUsageReport\x128\n" + + "\ametrics\x18\x01 \x03(\v2\x1e.accounts.v1alpha1.UsageMetricR\ametrics\x12C\n" + + "\fusage_period\x18\x02 \x01(\v2 .accounts.v1alpha1.BillingPeriodR\vusagePeriod*\x8b\x01\n" + + "\x10SubscriptionTier\x12!\n" + + "\x1dSUBSCRIPTION_TIER_UNSPECIFIED\x10\x00\x12\x1a\n" + + "\x16SUBSCRIPTION_TIER_FREE\x10\x01\x12\x1a\n" + + "\x16SUBSCRIPTION_TIER_PAID\x10\x02\x12\x1c\n" + + "\x18SUBSCRIPTION_TIER_CUSTOM\x10\x03*j\n" + + "\x0eBillingCadence\x12\x1f\n" + + "\x1bBILLING_CADENCE_UNSPECIFIED\x10\x00\x12\x1b\n" + + "\x17BILLING_CADENCE_MONTHLY\x10\x01\x12\x1a\n" + + "\x16BILLING_CADENCE_YEARLY\x10\x02*P\n" + + "\x04Unit\x12\x14\n" + + "\x10UNIT_UNSPECIFIED\x10\x00\x12\x10\n" + + "\fUNIT_NO_UNIT\x10\x01\x12\x0e\n" + + "\n" + + "UNIT_BYTES\x10\x02\x12\x10\n" + + "\fUNIT_SECONDS\x10\x03*z\n" + + "\x11MetricAggregation\x12\"\n" + + "\x1eMETRIC_AGGREGATION_UNSPECIFIED\x10\x00\x12\x1c\n" + + "\x18METRIC_AGGREGATION_TOTAL\x10\x01\x12#\n" + + "\x1fMETRIC_AGGREGATION_USAGE_PERIOD\x10\x022\xc3\x01\n" + + "\x0eBillingService\x12S\n" + + "\rGetActivePlan\x12'.accounts.v1alpha1.GetActivePlanRequest\x1a\x17.accounts.v1alpha1.Plan\"\x00\x12\\\n" + + "\x0eGetUsageReport\x12(.accounts.v1alpha1.GetUsageReportRequest\x1a\x1e.accounts.v1alpha1.UsageReport\"\x00B\xda\x01\n" + + "\x15com.accounts.v1alpha1B\fBillingProtoP\x01ZIgithub.com/tilebox/tilebox-go/protogen/accounts/v1alpha1;accountsv1alpha1\xa2\x02\x03AXX\xaa\x02\x11Accounts.V1alpha1\xca\x02\x11Accounts\\V1alpha1\xe2\x02\x1dAccounts\\V1alpha1\\GPBMetadata\xea\x02\x12Accounts::V1alpha1\x92\x03\x02\b\x02b\beditionsp\xe8\a" + +var file_accounts_v1alpha1_billing_proto_enumTypes = make([]protoimpl.EnumInfo, 4) +var file_accounts_v1alpha1_billing_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_accounts_v1alpha1_billing_proto_goTypes = []any{ + (SubscriptionTier)(0), // 0: accounts.v1alpha1.SubscriptionTier + (BillingCadence)(0), // 1: accounts.v1alpha1.BillingCadence + (Unit)(0), // 2: accounts.v1alpha1.Unit + (MetricAggregation)(0), // 3: accounts.v1alpha1.MetricAggregation + (*BillingPeriod)(nil), // 4: accounts.v1alpha1.BillingPeriod + (*Plan)(nil), // 5: accounts.v1alpha1.Plan + (*UsageRecord)(nil), // 6: accounts.v1alpha1.UsageRecord + (*UsageHistory)(nil), // 7: accounts.v1alpha1.UsageHistory + (*UsageMetric)(nil), // 8: accounts.v1alpha1.UsageMetric + (*GetActivePlanRequest)(nil), // 9: accounts.v1alpha1.GetActivePlanRequest + (*GetUsageReportRequest)(nil), // 10: accounts.v1alpha1.GetUsageReportRequest + (*UsageReport)(nil), // 11: accounts.v1alpha1.UsageReport + (*timestamppb.Timestamp)(nil), // 12: google.protobuf.Timestamp +} +var file_accounts_v1alpha1_billing_proto_depIdxs = []int32{ + 12, // 0: accounts.v1alpha1.BillingPeriod.start:type_name -> google.protobuf.Timestamp + 12, // 1: accounts.v1alpha1.BillingPeriod.end:type_name -> google.protobuf.Timestamp + 12, // 2: accounts.v1alpha1.BillingPeriod.anchor:type_name -> google.protobuf.Timestamp + 0, // 3: accounts.v1alpha1.Plan.tier:type_name -> accounts.v1alpha1.SubscriptionTier + 1, // 4: accounts.v1alpha1.Plan.billing_cadence:type_name -> accounts.v1alpha1.BillingCadence + 4, // 5: accounts.v1alpha1.Plan.subscription_billing_period:type_name -> accounts.v1alpha1.BillingPeriod + 4, // 6: accounts.v1alpha1.Plan.usage_billing_period:type_name -> accounts.v1alpha1.BillingPeriod + 12, // 7: accounts.v1alpha1.Plan.valid_until:type_name -> google.protobuf.Timestamp + 12, // 8: accounts.v1alpha1.UsageRecord.timestamp:type_name -> google.protobuf.Timestamp + 4, // 9: accounts.v1alpha1.UsageHistory.usage_periods:type_name -> accounts.v1alpha1.BillingPeriod + 6, // 10: accounts.v1alpha1.UsageHistory.records:type_name -> accounts.v1alpha1.UsageRecord + 2, // 11: accounts.v1alpha1.UsageMetric.unit:type_name -> accounts.v1alpha1.Unit + 3, // 12: accounts.v1alpha1.UsageMetric.aggregation:type_name -> accounts.v1alpha1.MetricAggregation + 7, // 13: accounts.v1alpha1.UsageMetric.history:type_name -> accounts.v1alpha1.UsageHistory + 8, // 14: accounts.v1alpha1.UsageReport.metrics:type_name -> accounts.v1alpha1.UsageMetric + 4, // 15: accounts.v1alpha1.UsageReport.usage_period:type_name -> accounts.v1alpha1.BillingPeriod + 9, // 16: accounts.v1alpha1.BillingService.GetActivePlan:input_type -> accounts.v1alpha1.GetActivePlanRequest + 10, // 17: accounts.v1alpha1.BillingService.GetUsageReport:input_type -> accounts.v1alpha1.GetUsageReportRequest + 5, // 18: accounts.v1alpha1.BillingService.GetActivePlan:output_type -> accounts.v1alpha1.Plan + 11, // 19: accounts.v1alpha1.BillingService.GetUsageReport:output_type -> accounts.v1alpha1.UsageReport + 18, // [18:20] is the sub-list for method output_type + 16, // [16:18] is the sub-list for method input_type + 16, // [16:16] is the sub-list for extension type_name + 16, // [16:16] is the sub-list for extension extendee + 0, // [0:16] is the sub-list for field type_name +} + +func init() { file_accounts_v1alpha1_billing_proto_init() } +func file_accounts_v1alpha1_billing_proto_init() { + if File_accounts_v1alpha1_billing_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_accounts_v1alpha1_billing_proto_rawDesc), len(file_accounts_v1alpha1_billing_proto_rawDesc)), + NumEnums: 4, + NumMessages: 8, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_accounts_v1alpha1_billing_proto_goTypes, + DependencyIndexes: file_accounts_v1alpha1_billing_proto_depIdxs, + EnumInfos: file_accounts_v1alpha1_billing_proto_enumTypes, + MessageInfos: file_accounts_v1alpha1_billing_proto_msgTypes, + }.Build() + File_accounts_v1alpha1_billing_proto = out.File + file_accounts_v1alpha1_billing_proto_goTypes = nil + file_accounts_v1alpha1_billing_proto_depIdxs = nil +} diff --git a/protogen/accounts/v1alpha1/billing_grpc.pb.go b/protogen/accounts/v1alpha1/billing_grpc.pb.go new file mode 100644 index 0000000..fe9b65e --- /dev/null +++ b/protogen/accounts/v1alpha1/billing_grpc.pb.go @@ -0,0 +1,165 @@ +// Public API for reading subscription plan and usage information. + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.2 +// - protoc (unknown) +// source: accounts/v1alpha1/billing.proto + +package accountsv1alpha1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + BillingService_GetActivePlan_FullMethodName = "/accounts.v1alpha1.BillingService/GetActivePlan" + BillingService_GetUsageReport_FullMethodName = "/accounts.v1alpha1.BillingService/GetUsageReport" +) + +// BillingServiceClient is the client API for BillingService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// BillingService exposes subscription plan and usage information. +type BillingServiceClient interface { + GetActivePlan(ctx context.Context, in *GetActivePlanRequest, opts ...grpc.CallOption) (*Plan, error) + GetUsageReport(ctx context.Context, in *GetUsageReportRequest, opts ...grpc.CallOption) (*UsageReport, error) +} + +type billingServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewBillingServiceClient(cc grpc.ClientConnInterface) BillingServiceClient { + return &billingServiceClient{cc} +} + +func (c *billingServiceClient) GetActivePlan(ctx context.Context, in *GetActivePlanRequest, opts ...grpc.CallOption) (*Plan, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Plan) + err := c.cc.Invoke(ctx, BillingService_GetActivePlan_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *billingServiceClient) GetUsageReport(ctx context.Context, in *GetUsageReportRequest, opts ...grpc.CallOption) (*UsageReport, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(UsageReport) + err := c.cc.Invoke(ctx, BillingService_GetUsageReport_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// BillingServiceServer is the server API for BillingService service. +// All implementations must embed UnimplementedBillingServiceServer +// for forward compatibility. +// +// BillingService exposes subscription plan and usage information. +type BillingServiceServer interface { + GetActivePlan(context.Context, *GetActivePlanRequest) (*Plan, error) + GetUsageReport(context.Context, *GetUsageReportRequest) (*UsageReport, error) + mustEmbedUnimplementedBillingServiceServer() +} + +// UnimplementedBillingServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedBillingServiceServer struct{} + +func (UnimplementedBillingServiceServer) GetActivePlan(context.Context, *GetActivePlanRequest) (*Plan, error) { + return nil, status.Error(codes.Unimplemented, "method GetActivePlan not implemented") +} +func (UnimplementedBillingServiceServer) GetUsageReport(context.Context, *GetUsageReportRequest) (*UsageReport, error) { + return nil, status.Error(codes.Unimplemented, "method GetUsageReport not implemented") +} +func (UnimplementedBillingServiceServer) mustEmbedUnimplementedBillingServiceServer() {} +func (UnimplementedBillingServiceServer) testEmbeddedByValue() {} + +// UnsafeBillingServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to BillingServiceServer will +// result in compilation errors. +type UnsafeBillingServiceServer interface { + mustEmbedUnimplementedBillingServiceServer() +} + +func RegisterBillingServiceServer(s grpc.ServiceRegistrar, srv BillingServiceServer) { + // If the following call panics, it indicates UnimplementedBillingServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&BillingService_ServiceDesc, srv) +} + +func _BillingService_GetActivePlan_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetActivePlanRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BillingServiceServer).GetActivePlan(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: BillingService_GetActivePlan_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BillingServiceServer).GetActivePlan(ctx, req.(*GetActivePlanRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _BillingService_GetUsageReport_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetUsageReportRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BillingServiceServer).GetUsageReport(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: BillingService_GetUsageReport_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BillingServiceServer).GetUsageReport(ctx, req.(*GetUsageReportRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// BillingService_ServiceDesc is the grpc.ServiceDesc for BillingService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var BillingService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "accounts.v1alpha1.BillingService", + HandlerType: (*BillingServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetActivePlan", + Handler: _BillingService_GetActivePlan_Handler, + }, + { + MethodName: "GetUsageReport", + Handler: _BillingService_GetUsageReport_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "accounts/v1alpha1/billing.proto", +} diff --git a/query/expression.go b/query/expression.go index f17f5b7..c1f45c8 100644 --- a/query/expression.go +++ b/query/expression.go @@ -160,6 +160,9 @@ func queryValueToProto(value any) (*datasetsv1.FieldQueryValue, reflect.Kind, er case reflect.Bool: converted := reflected.Bool() return datasetsv1.FieldQueryValue_builder{BoolValue: &converted}.Build(), reflect.Bool, nil + case reflect.String: + converted := reflected.String() + return datasetsv1.FieldQueryValue_builder{StringValue: &converted}.Build(), reflect.String, nil case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: converted := reflected.Int() return datasetsv1.FieldQueryValue_builder{Int64Value: &converted}.Build(), reflect.Int64, nil @@ -173,6 +176,6 @@ func queryValueToProto(value any) (*datasetsv1.FieldQueryValue, reflect.Kind, er } return datasetsv1.FieldQueryValue_builder{DoubleValue: &converted}.Build(), reflect.Float64, nil default: - return nil, reflect.Invalid, fmt.Errorf("unsupported comparison value type %T; expected a boolean or numeric value", value) + return nil, reflect.Invalid, fmt.Errorf("unsupported comparison value type %T; expected a boolean, string, or numeric value", value) } } diff --git a/query/expression_test.go b/query/expression_test.go index 62cb097..2c39d91 100644 --- a/query/expression_test.go +++ b/query/expression_test.go @@ -12,6 +12,7 @@ import ( func TestComparisonExpressionValues(t *testing.T) { type signedCount int32 + type granuleName string tests := []struct { name string @@ -19,6 +20,8 @@ func TestComparisonExpressionValues(t *testing.T) { want *datasetsv1.FieldQueryValue }{ {name: "bool", value: false, want: datasetsv1.FieldQueryValue_builder{BoolValue: new(false)}.Build()}, + {name: "string", value: "S2A_GRANULE", want: datasetsv1.FieldQueryValue_builder{StringValue: new("S2A_GRANULE")}.Build()}, + {name: "named string", value: granuleName("S2B_GRANULE"), want: datasetsv1.FieldQueryValue_builder{StringValue: new("S2B_GRANULE")}.Build()}, {name: "int", value: 0, want: datasetsv1.FieldQueryValue_builder{Int64Value: new(int64(0))}.Build()}, {name: "named int32", value: signedCount(12), want: datasetsv1.FieldQueryValue_builder{Int64Value: new(int64(12))}.Build()}, {name: "uint64", value: uint64(42), want: datasetsv1.FieldQueryValue_builder{Uint64Value: new(uint64(42))}.Build()}, @@ -64,7 +67,7 @@ func TestInvalidExpression(t *testing.T) { wantErr string }{ {name: "nil value", expression: Field("value").Equal(nil), wantErr: "comparison value cannot be nil"}, - {name: "unsupported value", expression: Field("value").Equal("text"), wantErr: "unsupported comparison value type string"}, + {name: "unsupported value", expression: Field("value").Equal([]byte("text")), wantErr: "unsupported comparison value type []uint8"}, {name: "NaN", expression: Field("value").Equal(math.NaN()), wantErr: "comparison value must be finite"}, {name: "infinity", expression: Field("value").Equal(math.Inf(1)), wantErr: "comparison value must be finite"}, {name: "protobuf enum", expression: Field("value").Equal(datasetsv1.ProcessingLevel_PROCESSING_LEVEL_L1), wantErr: "protobuf enums are not queryable"},