syntax = "proto2";

package wix.api;

import "google/protobuf/descriptor.proto";

option java_multiple_files = true;
option java_outer_classname = "AnnotationsProto";
option java_package = "com.wix.api";

extend google.protobuf.ServiceOptions {
    optional Maturity service_maturity = 50104;
    optional Exposure service_exposure = 50105;
    optional Deprecated service_deprecated = 50140; // mark a service as deprecated, optionally place replacing asset
    repeated ServiceAppendix appendix_files = 50150; // declare external configuration info
}

extend google.protobuf.MethodOptions {
    optional Exposure exposure = 50101;
    optional Maturity maturity = 50102;
    optional CacheSettings cacheable = 50103; // mark a method as cacheable, optionally pass max cache age
    optional Deprecated deprecated = 50141; // mark a method as deprecated, optionally place replacing asset
    optional Crud crud = 50146; // mark crud method type and describe related information about this method
    optional bool accepts_linguist = 50148; // marks that this method accepts `x-wix-linguist` header, MAY return translated/localized responses. without this option, requests that assign this header will get an error. CRUD annotated methods assumed to have this enabled for read ops and disabled for write ops.
}

extend google.protobuf.MessageOptions {
    optional string decomposite_of = 50120; // mark it a shard of a message to remove fields
    repeated FieldSet decomposition_minimum_fields = 50121; // constrain that sharding at the definition
    optional bool unwrap_array_value = 50122; // mark message as wrapper for arrays
    optional Deprecated message_deprecated = 50142; // mark a message as deprecated, optionally place replacing asset
    repeated Unique unique = 50145; // mark unique identifiers for this message
}

extend google.protobuf.FieldOptions {
    optional Exposure field_exposure = 50106;
    optional Maturity field_maturity = 50107;
    optional bool pii = 50110; // Mark specific field as PII so clients that store the data know it should be encrypted
    optional string referenced_entity = 50111; // FQDN of foreign keys. For example, an Order message that points to Product message can use it like this: `string product_id = 10 [(wix.api.referenced_entity) = "wix.stores.catalog.v1.product"];`
    optional ReferenceEntityField referenced_entity_field = 50112; // FQDN and path of a field that is referenced by `referenced_entity`. Should be located at same level or in a nested message with relation to `wix.api.referenced_entity`.
    optional Deprecated field_deprecated = 50143; // Mark a field as deprecated, optionally place replacing asset
    optional Translatable translatable = 50144; // Mark this field as translatable using MultiLingual services
    optional string sample_data = 50149; // Example of data that may be assigned as a value of this field
    optional Conditional conditional = 50151; // Configure the conditions required for this field to be returned
    optional bool nullable = 50152; // Mark specific field as nullable
}

extend google.protobuf.EnumValueOptions {
    optional Maturity enum_maturity = 50130;
    optional Exposure enum_exposure = 50131;
}

message ReferenceEntityField {
    required string path = 1; // field path from root of a message annotated with `wix.api.entity` annotation. For example 'item.name'.
}

message CacheSettings {
    optional int32 max_age_seconds = 1; // default is 604800 seconds = 1 week
    optional bool manual = 2; // default is false
}

message FieldSet {
    repeated string field = 1;
}

message Deprecated {
    optional string replaced_by = 1; // use relative proto FQN as absolute identifier. e.g. "wix.common.Query"
    optional string target_removal_date = 2; // a human readable sunset date of the deprecated resource YYYY-MM-DD
}

message Unique {
    repeated string field = 1;
}

message Crud {
    enum Method {
        UNKNOWN_METHOD = 0;
        CREATE = 1;
        GET_ITEM = 2;
        UPDATE = 3;
        DELETE = 4;
        UPSERT = 12;
        LIST = 5;
        QUERY = 6;
        SEARCH = 18;
        BULK_CREATE = 7;
        BULK_UPDATE = 8;
        BULK_UPDATE_BY_FILTER = 9;
        BULK_DELETE = 10;
        BULK_DELETE_BY_FILTER = 11;
        BULK_UPSERT = 13;
        LIST_DELETED = 14;
        GET_DELETED = 15;
        RESTORE_FROM_TRASHBIN = 16;
        REMOVE_FROM_TRASHBIN = 17;
        COUNT = 19;
        SEARCH_RELATED = 20;
        UPDATE_EXTENDED_FIELDS = 21;
        BULK_UPDATE_TAGS = 22;
        BULK_UPDATE_TAGS_BY_FILTER = 23;
        CUSTOM_ACTION = 24;
    }
    required Method method = 1; // method type
    oneof method_options {
        CreateMethodOptions create_options = 3;
        GetItemMethodOptions get_options = 4;
        UpdateMethodOptions update_options = 5;
        DeleteMethodOptions delete_options = 6;
        ListMethodOptions list_options = 7;
        QueryMethodOptions query_options = 8;
        SearchMethodOptions search_options = 20;
        BulkCreateMethodOptions bulk_create_options = 9;
        BulkUpdateMethodOptions bulk_update_options = 10;
        BulkUpdateByFilterMethodOptions bulk_update_by_filter_options = 11;
        BulkDeleteMethodOptions bulk_delete_options = 12;
        BulkDeleteByFilterMethodOptions bulk_delete_by_filter_options = 13;
        UpsertMethodOptions upsert_options = 14;
        BulkUpsertMethodOptions bulk_upsert_options = 15;
        ListDeletedMethodOptions list_deleted_options = 16;
        GetDeletedMethodOptions get_deleted_options = 17;
        RestoreFromTrashbinMethodOptions restore_from_trashbin_options = 18;
        RemoveFromTrashbinMethodOptions remove_from_trashbin_options = 19;
        CountOptions count_options = 21;
        SearchRelatedOptions search_related_options = 22;
        UpdateExtendedFieldsOptions update_extended_fields_options = 23;
        CustomActionOptions custom_action_options = 24; // marks that this method is a custom-action, that unfolds a read/write operation
        BulkUpdateTagsMethodOptions bulk_update_tags_options = 25;
        BulkUpdateTagsByFilterMethodOptions bulk_update_tags_by_filter_options = 26;
    }
}

message Paging {
    enum Type {
        UNKNOWN_TYPE = 0;
        OFFSET = 1;
        CURSOR = 2;
        BOTH = 3;
    }
    optional Type type = 1; // paging type
    optional string paging_metadata_field = 2 [deprecated=true]; // paging field name in response object. default is `metadata`, DEPRECATED in commons V2
    optional string cursor_paging_metadata_field = 3; // cursor paging field name in response object. default is `cursor_paging_metadata`
    optional string offset_paging_metadata_field = 4; // offset paging field name in response object. default is `offset_paging_metadata`
}

message CustomActionOptions {
    optional bool read_operation = 1; // the custom-action's operation will do nothing but read data.
    optional WqlOptions wql = 2; // if WQL validation is needed in this method, provide the data needed for the validator
}

message WqlOptions {
    optional string query_options_name = 1; // Name of WQL variant to use
    // The action may use either filter (struct), query (QueryV2) or search (Search) field. Point to the right one
    oneof field {
        string filter_field = 2; // provide path to filter field (struct) in your request message
        string query_field = 3; // provide path to query field (wix.common.QueryV2) in your request message
        string search_field = 4; // provide path to search field (wix.common.Search) in your request message
    }
}

message CreateMethodOptions {
    optional string item_field = 1; // item field name in request and response objects. default is `<entity-name>`
}

message GetItemMethodOptions {
    optional string item_field = 2; // item field name in response object only. default is `<entity-name>`
    optional string id_field = 1; // id field name in request object. default is `<entity-name>_id`
}

message UpdateMethodOptions {
    optional string item_field = 1; // item field name in request and response objects. default is `<entity-name>`
    optional string fieldmask_field = 2; // fieldmask field name in request object. default is `fieldmask`, only if it really exists in model
}

message UpsertMethodOptions {
    optional string item_field = 1; // item field name in request and response objects. default is `<entity-name>`
    optional string fieldmask_field = 2; // fieldmask field name in request object. default is `fieldmask`, only if it really exists in model
}

message DeleteMethodOptions {
    optional string id_field = 1; // id field name in request object. default is `<entity-name>_id`
}

message ListMethodOptions {
    optional string ids_field = 1; // ids field name in request object if such exists. recommended field-name: `<entity-name>_ids`
    required string items_field = 3; // items field name in response object.
    optional Paging paging = 2; // present paging mechanism info, default will be of type=`CURSOR`
    repeated string me_aliasable_field = 4; // collection of FQNs of fields that MAY be aliased with the const `"me"`
}

message QueryMethodOptions {
    optional string query_field = 1 [deprecated=true]; // query field name in request object. default is `query`, DEPRECATED in commons V2
    optional string cursor_query_field = 7; // cursor query field name in request object. default is `cursor_query`
    optional string offset_query_field = 8; // offset query field name in request object. default is `offset_query`
    required string items_field = 3; // items field name in response object.
    optional Paging paging = 2; // present paging mechanism info, default will be of type=`CURSOR`
    oneof wql_options {
        // mark fields that are available for filtering and sorting via WixQueryLanguage
        // Deprecated - use wql annotation on the entity level
        Wql wql = 4 [deprecated = true];
        string query_options_name = 6; // Name of WQL variant to use
    }
    repeated string me_aliasable_field = 5; // collection of FQNs of fields that MAY be aliased with the const `"me"`
}

message SearchMethodOptions {
    optional string search_field = 1 [deprecated=true]; // search field name in request object. default is `search`, DEPRECATED in commons V2
    optional string cursor_search_field = 8; // cursor search field name in request object. default is `cursor_search`
    optional string offset_search_field = 9; // offset search field name in request object. default is `offset_search`
    required string items_field = 3; // items field name in response object.
    optional Paging paging = 2; // present paging mechanism info, default will be of type=`CURSOR`
    oneof wql_options {
        Wql wql = 4; // mark fields that are available for filtering and sorting via WixQueryLanguage
        string query_options_name = 7; // Name of WQL variant to use
    }
    repeated string me_aliasable_field = 5; // collection of FQNs of fields that MAY be aliased with the const `"me"`
    repeated Search search = 6; // mark fields that are available for search
}

message BulkCreateMethodOptions {
    optional string item_field = 1; // item field name in request and response objects. default is `<entity-name>`
}

message BulkUpdateMethodOptions {
    optional string items_field = 1; // items field name in request and response objects. default is `<entity-name>` in plural. For the request, the field is expected to be a repeated message that includes entity and fieldmask.
    optional string item_field = 2; // item field name under the message used for the repeated field pointed by items_field. default is `<entity-name>`
    optional string fieldmask_field = 3; // fieldmask field name under the message used for the repeated field pointed by items_field. default is `fieldmask`, only if it really exists in model
}

message BulkUpdateByFilterMethodOptions {
    optional string item_field = 1; // item field name in request and response objects. default is `<entity-name>`
    optional string fieldmask_field = 2; // fieldmask field name in request object. default is `fieldmask`, only if it really exists in model
    optional string filter_field = 3; // filter field name in request object. default is `filter`
    optional string query_options_name = 4; // Name of WQL variant to use
}

message BulkUpdateTagsMethodOptions {
    optional string ids_field = 1; // ids field name in request object. default is `<entity-name>_ids`
}

message BulkUpdateTagsByFilterMethodOptions {
    optional string filter_field = 1; // filter field name in request object. default is `filter`
    optional string query_options_name = 2; // Name of WQL variant to use
}

message BulkUpsertMethodOptions {
    optional string item_field = 1; // item field name in request and response objects. default is `<entity-name>`
    optional string fieldmask_field = 2; // fieldmask field name in request object. default is `fieldmask`, only if it really exists in model
}

message BulkDeleteMethodOptions {
    optional string ids_field = 1; // ids field name in request object. default is `<entity-name>_ids`
}

message BulkDeleteByFilterMethodOptions {
    optional string filter_field = 1; // filter field name in request object. default is `filter`
    optional string query_options_name = 2; // Name of WQL variant to use
}

message ListDeletedMethodOptions {
    optional string ids_field = 1; // ids field name in request object if such exists. recommended field-name: `<entity-name>_ids`
    required string items_field = 3; // items field name in response object.
    optional Paging paging = 2; // present paging mechanism info, default will be of type=`CURSOR`
    repeated string me_aliasable_field = 4; // collection of FQNs of fields that MAY be aliased with the const `"me"`
}

message GetDeletedMethodOptions {
    optional string item_field = 2; // item field name in response object only. default is `<entity-name>`
    optional string id_field = 1; // id field name in request object. default is `<entity-name>_id`
}

message RestoreFromTrashbinMethodOptions {
    optional string item_field = 2; // item field name in response object only. default is `<entity-name>`
    optional string id_field = 1; // id field name in request object. default is `<entity-name>_id`
}

message RemoveFromTrashbinMethodOptions {
    optional string id_field = 1; // id field name in request object. default is `<entity-name>_id`
}

message CountOptions {
  oneof wql_options {
    // The name of the endpoint that the count "copy" the WQL settings from - e.g inherit_wql_from: 'QueryProducts'
    // Usually, that will be the query endpoint since you want the same filter capabilities for query and count
    string inherit_wql_from = 1 [deprecated = true];

    string query_options_name = 2; // Name of WQL variant to use
  }
  optional string filter_field = 3; // query field name in request object. default is `filter`
  optional string count_field = 4; // count field name in response object. default is `count`
}

message SearchRelatedOptions {
  oneof wql_options {
    // The name of the endpoint that the related-search "copy" the WQL settings from - e.g inherit_wql_from: 'SearchProducts'
    // Usually, that will be the search endpoint since you want the same filter capabilities for search and related search
    string inherit_wql_from = 1 [deprecated = true];

    string query_options_name = 2; // Name of WQL variant to use
  }
}

message UpdateExtendedFieldsOptions {
    optional string item_field = 2; // item field name in response object only. default is `<entity-name>`
}

message Wql {
    reserved 7;
    enum Operator {
        option allow_alias = true;
        ALL_APPLICABLE_OPERATORS = 0; // Applicable by type. i.e. if we allow LT/GT for **, it means for numeric fields only.
        EQ = 1; // [Comparison] Matches values that are equal to a specified value.
        GT = 2; // [Comparison] Matches values that are greater than a specified value.
        GTE = 3; // [Comparison] Matches values that are greater than or equal to a specified value.
        IN = 4; // [Comparison] Matches any of the values specified in an array.
        LT = 5; // [Comparison] Matches values that are less than a specified value.
        LTE = 6; // [Comparison] Matches values that are less than or equal to a specified value.
        NE = 7; // [Comparison] Matches all values that are not equal to a specified value.
        NIN = 8; // [Comparison] Matches none of the values specified in an array.
        BEGINS = 9; // [Comparison] Matches strings that begin with a specified value (NOT case sensitive).
        EXISTS = 10; // [Element] Matches documents that have the specified field.
        HAS_ALL = 11; // [Array] Matches arrays that contain all elements specified in the query.
        ALL = 11 [deprecated = true]; // [Array] Matches arrays that contain all elements specified in the query.
        HAS_SOME = 12; // [Array] Matches arrays that contain at least one element specified in the query.
        ANY = 12 [deprecated = true]; // [Array] Matches arrays that contain at least one element specified in the query.
        EMPTY = 13; // [Array] Matches arrays that contain no elements.
        MATCH_ALL = 14; // Matches all items. Intended for expressing intent in selecting everything for ex. destructive operations - bulk deletes, updates, etc.
        MATCH_ITEMS = 16; // [Array] match multiple fields within array with AND operator semantics.
        /* Enhances field, marked as LOCAL_DATE format, with additional subFields to sort and filter on.
            For local date, formatted as yyyy-mm-dd, available subfields are:
                '.dayOfMonth' - sorts/filters on the day of the month (dd), integer
                '.month' - sorts/filters on the month (mm), integer
                '.year' - sorts/filters on the year (yyyy), integer
            Example, there is a local date field named 'clientBirthday', you may use 'clientBirthday.dayOfMonth',
            'clientBirthday.month', 'clientBirthday.year' for filtering and sorting.
            You may also use the field without the enhanced subfields ('clientBirthday'). Then the usual date sorting/filtering is applied */
        ENHANCED_DATE = 17 [deprecated = true];
    }
    enum Sort {
        NONE = 0; // no sorting enabled
        ASC = 1; // ascending sort is supported
        DESC = 2; // descending sort is supported
        BOTH = 3; // sort is supported in both directions
    }
    message RequiredFields {
        // this field is deprecated because we need sort direction alongside to field path
        repeated string field = 1[(.wix.api.field_deprecated) = {
            replaced_by: "required_field"
            target_removal_date: "2023-03-31"
        }];
        message RequiredField {
            required string path = 1; // a field path that accepts this operator
            optional Sort sort = 2; // sort type enabled for this glob
        }
        repeated RequiredField required_field = 2; // all required field configurations to satisfy composite index
    }

    enum VirtualSubfields {
      NO_VIRTUAL_SUBFIELDS = 0;
      /* Can be set for a field, marked as LOCAL_DATE format, allows filtering by following subfields:
          - '.dayOfMonth' - sorts/filters on the day of the month (dd), integer
          - '.month' - sorts/filters on the month (mm), integer
          - '.year' - sorts/filters on the year (yyyy), integer
         For example, for a local date field named 'clientBirthday', you may use 'clientBirthday.dayOfMonth',
         'clientBirthday.month', 'clientBirthday.year' for filtering and sorting. */
      DATE = 1;
      /* Can be set for a field, marked as EMAIL format, allows filtering by following subfields:
          - '.domain' - sorts/filters on the domain of an email (example email: hello@wix.com --> domain: wix.com), string */
      EMAIL = 2;
    }

    message OperatorFieldSupport {
        repeated Operator operator = 1; // Operators supported for fields that match the glob
        // this field is deprecated because glob is hard to read. moved to a direct field config approach
        optional string glob = 2 [(.wix.api.field_deprecated) = {
            replaced_by: "field"
            target_removal_date: "2023-03-31"
        }, deprecated = true];
        repeated string field = 5; // a collection of field paths that accepts this operator
        optional Sort sort = 3; // sort type enabled for this glob
        repeated RequiredFields required_fields = 4; // fields that match this glob, can be used only if the query is also filtered by required_fields
        optional Maturity maturity = 6;
        optional VirtualSubfields virtual_subfields = 7; // kind of virtual subfields are supported for this field
    }
    // this field is deprecated due to a better and shorter naming
    repeated OperatorFieldSupport operator_field_support = 3 [(.wix.api.field_deprecated) = {
        replaced_by: "pattern"
        target_removal_date: "2023-03-31"
    }, deprecated = true];
    repeated OperatorFieldSupport pattern = 4; // supported operators for subject query method
    optional bool validate_query = 6; // false by default. all new services will have it set to true
}

message Search {
    repeated string field = 1; // a collection of field paths that supports Free Text Search
    optional Maturity maturity = 2;
}

message Translatable {
    enum Type {
        UNDEFINED_TYPE = 0 [(.wix.api.enum_maturity) = NOT_IMPLEMENTED];
        SHORT_TEXT = 1;
        LONG_TEXT = 2;
        RICH_TEXT = 3;
        RICH_CONTENT_EDITOR = 4;
        SELECTION = 5;
        MULTI_SELECTION = 6;
        DOCUMENT = 7;
        IMAGE = 8;
        VIDEO = 9;
        IMAGE_LINK = 10; // Image URI without metadata
    }
    optional string name = 1; // a human friendly field name
    optional bool hidden = 2; // is this translatable field hidden in Multilingual
    optional string grouping = 3; // fields in schema may be grouped under meaningful topic or category of the source entity
    required Type type = 4; // translation input component type e.g. "freetext", "dropdown", etc..
    optional bool display_only = 5; // is this field for preview and not translatable
}

message Conditional {
    optional string permission = 1; // field will not be returned by the server, unless the client has this permission. If `requested_field` is also set, and a client explicitly requests this field but does not have permission, server will return 403-Forbidden error
    optional string requested_field = 2; // field will not be returned by the server, unless the client explicitly requested it using `fields` parameter in the request, with the enum value specified by this annotation
}

message ServiceAppendix {
    enum Type {
        UNKNOWN_APPENDIX_TYPE = 0;
        NILE = 1; // Nile(tm) FW configuration
        MESSAGE_BUS = 2; // wix message bus / pub-sub configuration
    }
    required Type type = 1; // appendix type
    required string path = 2; // absolute from module root
}

// Defines the target audience of your API
// @see https://dev.wix.com/docs/rnd-general/articles/p13n-guidelines-aips/guidance-aips/api-lifecycle/2005-exposure
enum Exposure {
    // Exposed to the owning team only. No other devs inside or outside Wix can use these APIs.
    PRIVATE = 0;
    // Exposed to internal Wix devs only. APIs that can only accept gRPC traffic and/or HTTP traffic over VPN
    INTERNAL = 1;
    // Exposed (or intended to be) to external devs. APIs that are accessible from the Internet, for example to the dashboard or live-site.
    PUBLIC = 2;
}

enum Maturity {
    ALPHA = 0;
    BETA = 1;
    IA = 2 [deprecated=true];
    GA = 3;
    NOT_IMPLEMENTED = 4;
}
