syntax = "proto3";

package wix.devcenter.apps.components.v1;
option java_package = "com.wixpress.devcenter.apps.components.v1";

import "google/protobuf/wrappers.proto";
import "google/protobuf/field_mask.proto";
import "google/api/annotations.proto";
import "wix/api/annotations.proto";
import "wix/common/paging.proto";
import "wix/api/validations.proto";
import "google/protobuf/empty.proto";
import "wix/common/query.proto";
import "wix/api/entity.proto";
import "wix/api/permissions.proto";
import "wix/api/subscription.proto";
import "wix/api/callback.proto";
import "wix/http/field_mask.proto";
import "wix/devcenter/apps/components/v1/component.proto";
import "wix/devcenter/apps/components/enricher/upstream/wix/common/bulk.proto";

/**
  Manages Components
 */
service ComponentsService {
  option (.wix.api.service_maturity) = BETA;
  option (.wix.api.service_exposure) = PUBLIC;
  option (wix.api.service_entity).message = "wix.devcenter.apps.components.v1.Component";

  /**
    Creates a new Component
   */
  rpc CreateComponent (CreateComponentRequest) returns (CreateComponentResponse) {
    option (google.api.http).post = "/v1/components";
    option (.wix.api.required) = "CreateComponentRequest.component";
    option (.wix.api.writable) = "CreateComponentRequest.component.id";
    option (.wix.api.required) = "CreateComponentRequest.component.app_id";
    option (.wix.api.callback) = {
      event_type: CREATED
    };
    option (.wix.api.permission) = {
      name: "DEVCENTER.WRITE_COMPONENTS"
      type: MANUAL
    };
    option (.wix.api.additional_permission) = {
      name: "DEV_CENTER.CREATE_COMPONENT"
      type: MANUAL
    };
    option (.wix.api.crud) = {
      method: CREATE
      create_options: {
        item_field: "component"
      }
    };
  }

  /**
  Creates a new Component from struct
 */
  rpc CreateComponentFromStruct (CreateComponentFromStructRequest) returns (CreateComponentFromStructResponse) {
    option (.wix.api.required) = "CreateComponentFromStructRequest.component";
    option (.wix.api.required) = "CreateComponentFromStructRequest.component.app_id";
    option (.wix.api.callback) = {
      event_type: CREATED
    };
    option (.wix.api.permission) = {
      name: "DEVCENTER.WRITE_COMPONENTS"
      type: MANUAL
    };
    option (.wix.api.additional_permission) = {
      name: "DEV_CENTER.CREATE_COMPONENT"
      type: MANUAL
    };
  }

  /**
    Get a Component by id
   */
  rpc GetComponent (GetComponentRequest) returns (GetComponentResponse) {
    option (google.api.http).get = "/v1/components/{id}";
    //    option (.wix.api.required) = "GetComponentRequest.component_id";
    option (.wix.api.required) = "GetComponentRequest.app_id";
    option (.wix.api.permission) = {
      name: "DEVCENTER.READ_COMPONENTS"
      type: MANUAL
    };
    option (.wix.api.crud) = {
      method: GET_ITEM
      get_options: {
        id_field: "id"
      }
    };
    option (.wix.api.additional_permission) = {
      name: "DEV_CENTER.READ_COMPONENT"
      type: MANUAL
    };
  }

  /**
    Update a Component, supports partial update
    Pass the latest `revision` for a successful update
   */
  rpc UpdateComponent (UpdateComponentRequest) returns (UpdateComponentResponse) {
    option (google.api.http).patch = "/v1/components/{component.id}";
    option (.wix.api.required) = "UpdateComponentRequest.component";
    option (.wix.api.required) = "UpdateComponentRequest.component.id";
    option (.wix.api.required) = "UpdateComponentRequest.component.app_id";
    option (.wix.api.required) = "UpdateComponentRequest.component.revision";
    option (.wix.api.callback) = {
      event_type: UPDATED
    };
    option (wix.http.infer_fieldmask) = {
      from: "component"
      fieldmask: "mask"
    };
    option (.wix.api.permission) = {
      name: "DEVCENTER.WRITE_COMPONENTS"
      type: MANUAL
    };
    option (.wix.api.additional_permission) = {
      name: "DEV_CENTER.WRITE_COMPONENT"
      type: MANUAL
    };
    option (.wix.api.crud) = {
      method: UPDATE
      update_options: {
        item_field: "component"
      }
    };
  }

  /**
    Update a Component, supports partial update
    Pass the latest `revision` for a successful update
   */
  rpc UpdateComponentFromStruct (UpdateComponentFromStructRequest) returns (UpdateComponentFromStructResponse) {
    option (.wix.api.required) = "UpdateComponentFromStructRequest.component";
    option (.wix.api.required) = "UpdateComponentFromStructRequest.component.id";
    option (.wix.api.required) = "UpdateComponentFromStructRequest.component.app_id";
    option (.wix.api.required) = "UpdateComponentFromStructRequest.component.revision";
    option (.wix.api.callback) = {
      event_type: UPDATED
    };
    option (.wix.api.permission) = {
      name: "DEVCENTER.WRITE_COMPONENTS"
      type: MANUAL
    };
    option (.wix.api.additional_permission) = {
      name: "DEV_CENTER.WRITE_COMPONENT"
      type: MANUAL
    };
  }

  /**
    Delete the draft version of a Component
   */
  // flynt-disable missing-cud-event
  rpc DeleteComponent (DeleteComponentRequest) returns (DeleteComponentResponse) {
    option (google.api.http).delete = "/v1/components/{id}";
    //    option (.wix.api.required) = "DeleteComponentRequest.component_id";
    option (.wix.api.required) = "DeleteComponentRequest.app_id";
    option (.wix.api.callback) = {
      event_type: ACTION
      payload: "wix.devcenter.apps.components.v1.ComponentActionDomainEventEntity"
    };
    option (.wix.api.callback) = {
      event_type: DELETED
    };
    option (.wix.api.permission) = {
      name: "DEVCENTER.WRITE_COMPONENTS"
      type: MANUAL
    };
    option (.wix.api.additional_permission) = {
      name: "DEV_CENTER.WRITE_COMPONENT"
      type: MANUAL
    };
    option (wix.api.crud) = {
      method: DELETE
      delete_options: {
        id_field: "id"
      }
    };
  }

  /**
  Get the draft components of an app
 */
  rpc GetDraftAppComponents (GetDraftAppComponentsRequest) returns (GetDraftAppComponentsResponse) {
    option (google.api.http).get = "/v1/components/app/{app_id}";
    option (.wix.api.required) = "GetDraftAppComponentsRequest.app_id";
    option (.wix.api.permission) = {
      name: "DEVCENTER.READ_COMPONENTS"
      type: MANUAL
    };
    option (.wix.api.additional_permission) = {
      name: "DEV_CENTER.READ_COMPONENT"
      type: MANUAL
    };
  }

  /**
  Get the draft components for multiple apps
 */
  rpc ListDraftAppsComponents (ListDraftAppsComponentsRequest) returns (ListDraftAppsComponentsResponse) {
    option (google.api.http).get = "/v1/components/app/list-draft-components-by-app-ids";
    option (.wix.api.permission) = {
      name: "DEVCENTER.READ_COMPONENTS"
      type: MANUAL
    };
    option (.wix.api.additional_permission) = {
      name: "DEV_CENTER.READ_COMPONENT"
      type: MANUAL
    };
  }

  /**
Get the draft components of an app by external id
*/
  rpc GetComponentsByExternalId (GetComponentsByExternalIdRequest) returns (GetComponentsByExternalIdResponse) {
    option (google.api.http).get = "/v1/components/app/{app_id}/external-id/{external_id}";
    option (.wix.api.required) = "GetComponentsByExternalIdRequest.app_id";
    option (.wix.api.required) = "GetComponentsByExternalIdRequest.external_id";
    option (.wix.api.permission) = {
      name: "DEVCENTER.READ_COMPONENTS"
      type: MANUAL
    };
    option (.wix.api.additional_permission) = {
      name: "DEV_CENTER.READ_COMPONENT"
      type: MANUAL
    };
  }

  /**
    Query Components using [WQL - Wix Query Language](https://dev.wix.com/api/rest/getting-started/api-query-language)
   */
  rpc QueryComponent (QueryComponentRequest) returns (QueryComponentResponse) {
    option (google.api.http).post = "/v1/components/query";
    option (.wix.api.required) = "QueryComponentRequest.query";
    option (.wix.api.permission).name =  "DEVCENTER.READ_COMPONENTS";
    option (.wix.api.crud) = {
      method: QUERY
      query_options: {
        paging {
          type: CURSOR
          paging_metadata_field: "paging_metadata" // in response object
        };
        query_field: "query"
        items_field: "components"
        wql: {
          pattern: {
            operator: ALL_APPLICABLE_OPERATORS // will be smart - allow by type
            field: "id"
            field: "app_id"
            field: "version"
            field: "external_id"
            sort: NONE // NONE|ASC|DESC|BOTH. NONE is the default.
            required_fields: {
              required_field: {
                path: "app_id"
              }
            }
          }
        }
      };
    };
  }

  /**
      Returns the maximal version of each component of a given app
     */
  rpc GetMaxVersionOfAppComponents (GetMaxVersionOfAppComponentsRequest) returns (GetMaxVersionOfAppComponentsResponse) {
    option (google.api.http).get = "/v1/components/get-max/{app_id}";
    option (.wix.api.required) = "GetMaxVersionOfAppComponentsRequest.app_id";
    option (.wix.api.permission) = {
      name: "DEVCENTER.READ_COMPONENTS"
      type: MANUAL
    };
    option (.wix.api.additional_permission) = {
      name: "DEV_CENTER.READ_COMPONENT"
      type: MANUAL
    };
  }

  /**
  Fix revision for component
   */
  rpc FixComponentRevision (FixComponentRevisionRequest) returns (FixComponentRevisionResponse) {
    option (wix.api.exposure) = PRIVATE;
    option (.wix.api.permission) = {
      name: "DEVCENTER.WRITE_COMPONENTS"
      type: MANUAL
    };
  }

  /**
  Restore component
   */
  rpc RestoreDeletedComponent (RestoreDeletedComponentRequest) returns (RestoreDeletedComponentResponse) {
    option (wix.api.exposure) = PRIVATE;
    option (.wix.api.permission) = {
      name: "DEVCENTER.WRITE_COMPONENTS"
      type: MANUAL
    };
  }

  /**
  Upsert components for a single app id.
  If the component id exists, the action will be UPDATE. otherwise, the actu
 */
  // flynt-disable required-annotation-breaking-change
  rpc UpsertComponents (UpsertComponentsRequest) returns (UpsertComponentsResponse) {
    option (google.api.http).patch = "/v1/components";
    option (.wix.api.required) = "UpsertComponentsRequest.components";
    option (.wix.api.writable) = "UpsertComponentsRequest.components.id";
    option (.wix.api.required) = "UpsertComponentsRequest.components.app_id";
    option (.wix.api.callback) = {
      event_type: UPDATED
    };
    option (.wix.api.permission) = {
      name: "DEVCENTER.WRITE_COMPONENTS"
      type: MANUAL
    };
    option (.wix.api.additional_permission) = {
      name: "DEV_CENTER.WRITE_COMPONENT"
      type: MANUAL
    };
  }

  /**
  Validate components for a single app id.
  */
  rpc ValidateComponents (ValidateComponentsRequest) returns (ValidateComponentsResponse) {
    option (google.api.http).patch = "/v1/components/validate";
    option (wix.api.permission) = {
      name: "DEVCENTER.READ_COMPONENTS";
      type: MANUAL
    };
    option (.wix.api.additional_permission) = {
      name: "DEV_CENTER.READ_COMPONENT";
      type: MANUAL
    };
  }

  /**
  Enrich components for a single app id.
  */
  rpc EnrichComponents (EnrichComponentsRequest) returns (EnrichComponentsResponse) {
    option (google.api.http).patch = "/v1/components/enrich";
    option (wix.api.permission) = {
      name: "DEVCENTER.WRITE_COMPONENTS";
      type: MANUAL
    };
    option (.wix.api.additional_permission) = {
      name: "DEV_CENTER.WRITE_COMPONENT";
      type: MANUAL
    };
  }


  /**
Creates new Component versions directly from data. Not from Draft. Used internally in Dev Center.
*/
  rpc CreateComponentVersionFromData (CreateComponentVersionFromDataRequest) returns (CreateComponentVersionFromDataResponse) {
    option (google.api.http).patch = "/v1/components/create-from-data";
    option (wix.api.exposure) = PRIVATE;
    option (.wix.api.permission) = {
      name: "DEVCENTER.WRITE_COMPONENTS";
      type: MANUAL
    };
    option (.wix.api.additional_permission) = {
      name: "DEV_CENTER.WRITE_COMPONENT"
      type: MANUAL
    };
  }

  /*
  Syncs components from app-service-webapp
   */
  rpc ConsumeOldComponentChanged (OldComponentChangedEvent) returns (google.protobuf.Empty) {
    option (wix.api.exposure) = PRIVATE;
    option (wix.api.subscription) = {
      topic: "app-component-changed-in-old-service"
      segment: USERS
    };
  }
}

message CreateComponentRequest {
  Component component = 1; // Component to be created
}

message CreateComponentResponse {
  Component component = 1; // The created Component
}

message CreateComponentFromStructRequest {
  UntypedComponent component = 1; // Component to be created
}

message CreateComponentFromStructResponse {
  Component component = 1; // The created Component
}

message GetDraftAppComponentsRequest {
  string app_id = 1 [(.wix.api.format) = GUID]; // The app with the requested components
  bool consistent = 2; // Should return a consistent result for read-after-write operations
}

message GetDraftAppComponentsResponse {
  repeated Component components = 1; // The requested components
}

message ListDraftAppsComponentsRequest {
  repeated string app_ids = 1 [(.wix.api.format) = GUID, (wix.api.minSize) = 1, (wix.api.maxSize) = 50]; // The app ids you wish to get the components for
}

message ListDraftAppsComponentsResponse {
  map<string, Components> app_to_components = 1; // app to its component map
}

message Components {
  repeated Component components = 1 [(wix.api.maxSize) = 300]; // The requested components
}

message GetComponentRequest {
  string id = 1 [deprecated = true]; // Please use component id instead
  string app_id = 2 [(.wix.api.format) = GUID]; // Id of the app the component belongs to
  google.protobuf.Int64Value version = 3; //The version of the component. 0 draft.
  string component_id = 4 /* TODO after deprecation[(.wix.api.format) = GUID] */; // Id of the Component to retrieve
}

message GetComponentResponse {
  Component component = 1; // The retrieved Component
}

message GetComponentsByExternalIdRequest {
  string app_id = 1 [(.wix.api.format) = GUID]; // Id of the app the components belongs to
  string external_id = 2 [(wix.api.maxLength) = 64]; // The external id of the components
}

message GetComponentsByExternalIdResponse {
  repeated Component components = 1; // The retrieved components
}

message UpdateComponentRequest {
  Component component = 1; // Component to be updated, may be partial
  google.protobuf.FieldMask mask = 2; // Explicit list of fields to update
}

message UpdateComponentResponse {
  Component component = 1; // The updated Component
}

message UpdateComponentFromStructRequest {
  UntypedComponent component = 1; // Component to be updated, may be partial
  google.protobuf.FieldMask mask = 2; // Explicit list of fields to update
}

message UpdateComponentFromStructResponse {
  Component component = 1; // The updated Component
}

message DeleteComponentRequest {
  string id = 1 [deprecated = true]; // Please use component id instead
  string app_id = 2 [(.wix.api.format) = GUID]; // Id of the app of the component
  int64 revision = 3; // The revision of the Component
  string component_id = 4 /* TODO after deprecation[(.wix.api.format) = GUID] */; // Id of the Component to delete
}

message DeleteComponentResponse {
}

message QueryComponentRequest {
  .wix.common.QueryV2 query = 1; // WQL expression
  bool consistent = 2; // Should return a consistent result for read-after-write operations
}

message QueryComponentResponse {
  repeated Component components = 1; // The retrieved Components
  .wix.common.PagingMetadataV2 paging_metadata = 2; // paging data
}

message CreateComponentVersionFromDataRequest {
  repeated Component components = 1 [(wix.api.maxSize) = 100]; // Components to be created
}

message CreateComponentVersionFromDataResponse {
  map<string, google.protobuf.Int64Value> component_versions = 1 ; // Created Components
}

message ComponentActionDomainEventEntity {
  Component component = 1; // The component that had an event
  ActionType action_type = 2; // The action which happened
}

enum ActionType {
  COMPONENT_DELETED = 0;
}

message UpsertComponentsRequest {
  // TODO: change minSize to 1 after fixing app-service-autorelease
  repeated Component components = 1 [(wix.api.minSize) = 0, (wix.api.maxSize) = 100]; // The components to upsert
}

message UpsertComponentsResponse {
  repeated UpsertComponentStatus results = 1; // Upsert components results
}

message UpsertComponentStatus {
  Component component = 1; // The upserted component
  bool success = 2; // If the operation was successful
  google.protobuf.StringValue error = 3 [(.wix.api.maxLength) = 512]; // The error that the operation threw
  google.protobuf.StringValue error_code = 4 [(.wix.api.maxLength) = 50]; // The error code that the operation threw
}

message GetMaxVersionOfAppComponentsRequest {
  string app_id = 1 [(.wix.api.format) = GUID]; // Id of the app the components belongs to
  bool consistent = 2; // Fetch consistent data
}

message GetMaxVersionOfAppComponentsResponse {
  string app_id = 1 [(.wix.api.format) = GUID]; // Id of the app the components belongs to
  repeated ComponentVersion components_versions = 2; // The requested component versions
}

message ComponentVersion {
  string id = 1 [(.wix.api.format) = GUID]; // Id of the Component
  int64 version = 3; //The version of the component
}

message ValidateComponentsRequest {
  repeated ValidateComponentsOperation components = 1; // Components for validation, separated by operation (upsert/deleted)
  google.protobuf.StringValue components_override_id = 2 [(wix.api.maxLength) = 50]; // ID of the relevant ComponentsOverride
}

message ValidateComponentsResponse {
  repeated ComponentValidationResult results = 1; // Components validation results
}

message EnrichComponentsRequest {
  repeated Component components = 1 [(.wix.api.maxSize) = 100]; // Components to potentially enrich
  google.protobuf.StringValue components_override_id = 2 [(wix.api.maxLength) = 50]; // ID of the relevant ComponentsOverride
}

message EnrichComponentsResponse {
  // The results
  repeated ComponentEnrichResult results = 1;
  // Bulk request metadata
  wix.devcenter.apps.components.enricher.upstream.wix.common.BulkActionMetadata bulk_action_metadata = 2;
}

message ComponentEnrichResult {
  // the enriched component
  Component enriched_component = 1;
  // result metadata
  wix.devcenter.apps.components.enricher.upstream.wix.common.ItemMetadata item_metadata = 2;
}

message ComponentValidationResult {
  string component_id = 1 [(.wix.api.format) = GUID]; // component ID
  bool valid = 2; // validation result
  google.protobuf.StringValue error = 3 [(.wix.api.maxLength) = 512]; // The error that the operation threw
}

message ValidateComponentsOperation {
  oneof component {
    UpsertComponentValidation upsert_component = 1; // Upsert components for validation
    DeletedComponentValidation deleted_component = 2; // Deleted components for validation
  }
}

message UpsertComponentValidation {
  Component component = 1; // Full upsert component
}

message DeletedComponentValidation {
  string component_id = 1 [(.wix.api.format) = GUID]; // Component id
  string app_id = 2 [(.wix.api.format) = GUID]; // App id
}

message FixComponentRevisionRequest {
  string component_id = 1 [(.wix.api.format) = GUID]; // Component id
  string app_id = 2 [(.wix.api.format) = GUID]; // App id
}

message FixComponentRevisionResponse {
}

message RestoreDeletedComponentRequest {
  string app_id = 1 [(.wix.api.format) = GUID]; // App id
  string component_id = 2 [(.wix.api.format) = GUID]; // Component id
}

message RestoreDeletedComponentResponse {}