From 95e9fa4de5ab5c08dea4b394ddaa9f2437507d9a Mon Sep 17 00:00:00 2001 From: Stephen Sawchuk Date: Mon, 28 Sep 2015 10:03:12 -0400 Subject: [PATCH] datastore: update to v1beta3 --- lib/datastore/dataset.js | 5 +- lib/datastore/datastore_v1.proto | 594 -------------- lib/datastore/entity.js | 353 ++++---- lib/datastore/request.js | 162 ++-- package.json | 3 +- proto/google/api/annotations.proto | 29 + proto/google/api/http.proto | 245 ++++++ .../google/datastore/v1beta3/datastore.proto | 281 +++++++ proto/google/datastore/v1beta3/entity.proto | 189 +++++ proto/google/datastore/v1beta3/query.proto | 281 +++++++ proto/google/longrunning/README.md | 4 + proto/google/longrunning/operations.proto | 144 ++++ proto/google/protobuf/any.proto | 98 +++ proto/google/protobuf/any_test.proto | 41 + proto/google/protobuf/api.proto | 201 +++++ proto/google/protobuf/arena_nc_test.py | 61 ++ proto/google/protobuf/descriptor.proto | 774 ++++++++++++++++++ proto/google/protobuf/duration.proto | 95 +++ proto/google/protobuf/empty.proto | 50 ++ proto/google/protobuf/field_mask.proto | 167 ++++ proto/google/protobuf/source_context.proto | 47 ++ proto/google/protobuf/struct.proto | 94 +++ proto/google/protobuf/timestamp.proto | 107 +++ proto/google/protobuf/type.proto | 176 ++++ proto/google/protobuf/unknown_enum_test.proto | 62 ++ proto/google/protobuf/wrappers.proto | 117 +++ proto/google/rpc/code.proto | 190 +++++ proto/google/rpc/error_details.proto | 157 ++++ proto/google/rpc/status.proto | 90 ++ proto/google/type/color.proto | 163 ++++ proto/google/type/date.proto | 43 + proto/google/type/dayofweek.proto | 50 ++ proto/google/type/latlng.proto | 36 + proto/google/type/money.proto | 40 + proto/google/type/timeofday.proto | 42 + proto/index.js | 30 + system-test/datastore.js | 319 ++++---- test/datastore/request.js | 2 +- 38 files changed, 4560 insertions(+), 982 deletions(-) delete mode 100644 lib/datastore/datastore_v1.proto create mode 100644 proto/google/api/annotations.proto create mode 100644 proto/google/api/http.proto create mode 100644 proto/google/datastore/v1beta3/datastore.proto create mode 100644 proto/google/datastore/v1beta3/entity.proto create mode 100644 proto/google/datastore/v1beta3/query.proto create mode 100644 proto/google/longrunning/README.md create mode 100644 proto/google/longrunning/operations.proto create mode 100644 proto/google/protobuf/any.proto create mode 100644 proto/google/protobuf/any_test.proto create mode 100644 proto/google/protobuf/api.proto create mode 100644 proto/google/protobuf/arena_nc_test.py create mode 100644 proto/google/protobuf/descriptor.proto create mode 100644 proto/google/protobuf/duration.proto create mode 100644 proto/google/protobuf/empty.proto create mode 100644 proto/google/protobuf/field_mask.proto create mode 100644 proto/google/protobuf/source_context.proto create mode 100644 proto/google/protobuf/struct.proto create mode 100644 proto/google/protobuf/timestamp.proto create mode 100644 proto/google/protobuf/type.proto create mode 100644 proto/google/protobuf/unknown_enum_test.proto create mode 100644 proto/google/protobuf/wrappers.proto create mode 100644 proto/google/rpc/code.proto create mode 100644 proto/google/rpc/error_details.proto create mode 100644 proto/google/rpc/status.proto create mode 100644 proto/google/type/color.proto create mode 100644 proto/google/type/date.proto create mode 100644 proto/google/type/dayofweek.proto create mode 100644 proto/google/type/latlng.proto create mode 100644 proto/google/type/money.proto create mode 100644 proto/google/type/timeofday.proto create mode 100644 proto/index.js diff --git a/lib/datastore/dataset.js b/lib/datastore/dataset.js index f149f7405281..74b144eaacf2 100644 --- a/lib/datastore/dataset.js +++ b/lib/datastore/dataset.js @@ -60,8 +60,7 @@ var DatastoreRequest = require('./request.js'); * @private */ var SCOPES = [ - 'https://www.googleapis.com/auth/datastore', - 'https://www.googleapis.com/auth/userinfo.email' + 'https://www.googleapis.com/auth/datastore' ]; /** @@ -136,7 +135,7 @@ nodeutil.inherits(Dataset, DatastoreRequest); * @param {string=} options.apiEndpoint - Custom API endpoint. */ Dataset.determineApiEndpoint_ = function(options) { - var apiEndpoint = 'https://www.googleapis.com'; + var apiEndpoint = 'https://datastore.googleapis.com'; var trailingSlashes = new RegExp('/*$'); if (options.apiEndpoint) { diff --git a/lib/datastore/datastore_v1.proto b/lib/datastore/datastore_v1.proto deleted file mode 100644 index bb4c199b116c..000000000000 --- a/lib/datastore/datastore_v1.proto +++ /dev/null @@ -1,594 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// The datastore v1 service proto definitions - -syntax = "proto2"; - -package pb; -option java_package = "com.google.api.services.datastore"; - - -// An identifier for a particular subset of entities. -// -// Entities are partitioned into various subsets, each used by different -// datasets and different namespaces within a dataset and so forth. -// -// All input partition IDs are normalized before use. -// A partition ID is normalized as follows: -// If the partition ID is unset or is set to an empty partition ID, replace it -// with the context partition ID. -// Otherwise, if the partition ID has no dataset ID, assign it the context -// partition ID's dataset ID. -// Unless otherwise documented, the context partition ID has the dataset ID set -// to the context dataset ID and no other partition dimension set. -// -// A partition ID is empty if all of its fields are unset. -// -// Partition dimension: -// A dimension may be unset. -// A dimension's value must never be "". -// A dimension's value must match [A-Za-z\d\.\-_]{1,100} -// If the value of any dimension matches regex "__.*__", -// the partition is reserved/read-only. -// A reserved/read-only partition ID is forbidden in certain documented contexts. -// -// Dataset ID: -// A dataset id's value must never be "". -// A dataset id's value must match -// ([a-z\d\-]{1,100}~)?([a-z\d][a-z\d\-\.]{0,99}:)?([a-z\d][a-z\d\-]{0,99} -message PartitionId { - // The dataset ID. - optional string dataset_id = 3; - // The namespace. - optional string namespace = 4; -} - -// A unique identifier for an entity. -// If a key's partition id or any of its path kinds or names are -// reserved/read-only, the key is reserved/read-only. -// A reserved/read-only key is forbidden in certain documented contexts. -message Key { - // Entities are partitioned into subsets, currently identified by a dataset - // (usually implicitly specified by the project) and namespace ID. - // Queries are scoped to a single partition. - optional PartitionId partition_id = 1; - - // A (kind, ID/name) pair used to construct a key path. - // - // At most one of name or ID may be set. - // If either is set, the element is complete. - // If neither is set, the element is incomplete. - message PathElement { - // The kind of the entity. - // A kind matching regex "__.*__" is reserved/read-only. - // A kind must not contain more than 500 characters. - // Cannot be "". - required string kind = 1; - // The ID of the entity. - // Never equal to zero. Values less than zero are discouraged and will not - // be supported in the future. - optional int64 id = 2; - // The name of the entity. - // A name matching regex "__.*__" is reserved/read-only. - // A name must not be more than 500 characters. - // Cannot be "". - optional string name = 3; - } - - // The entity path. - // An entity path consists of one or more elements composed of a kind and a - // string or numerical identifier, which identify entities. The first - // element identifies a root entity, the second element identifies - // a child of the root entity, the third element a child of the - // second entity, and so forth. The entities identified by all prefixes of - // the path are called the element's ancestors. - // An entity path is always fully complete: ALL of the entity's ancestors - // are required to be in the path along with the entity identifier itself. - // The only exception is that in some documented cases, the identifier in the - // last path element (for the entity) itself may be omitted. A path can never - // be empty. - repeated PathElement path_element = 2; -} - -// A message that can hold any of the supported value types and associated -// metadata. -// -// At most one of the Value fields may be set. -// If none are set the value is "null". -// -message Value { - // A boolean value. - optional bool boolean_value = 1; - // An integer value. - optional int64 integer_value = 2; - // A double value. - optional double double_value = 3; - // A timestamp value. - optional int64 timestamp_microseconds_value = 4; - // A key value. - optional Key key_value = 5; - // A blob key value. - optional string blob_key_value = 16; - // A UTF-8 encoded string value. - optional string string_value = 17; - // A blob value. - optional bytes blob_value = 18; - // An entity value. - // May have no key. - // May have a key with an incomplete key path. - // May have a reserved/read-only key. - optional Entity entity_value = 6; - // A list value. - // Cannot contain another list value. - // Cannot also have a meaning and indexing set. - repeated Value list_value = 7; - - // The meaning field is reserved and should not be used. - optional int32 meaning = 14; - - // If the value should be indexed. - // - // The indexed property may be set for a - // null value. - // When indexed is true, stringValue - // is limited to 500 characters and the blob value is limited to 500 bytes. - // Exception: If meaning is set to 2, string_value is limited to 2038 - // characters regardless of indexed. - // When indexed is true, meaning 15 and 22 are not allowed, and meaning 16 - // will be ignored on input (and will never be set on output). - // Input values by default have indexed set to - // true; however, you can explicitly set indexed to - // true if you want. (An output value never has - // indexed explicitly set to true.) If a value is - // itself an entity, it cannot have indexed set to - // true. - // Exception: An entity value with meaning 9, 20 or 21 may be indexed. - optional bool indexed = 15 [default = true]; -} - -// An entity property. -message Property { - // The name of the property. - // A property name matching regex "__.*__" is reserved. - // A reserved property name is forbidden in certain documented contexts. - // The name must not contain more than 500 characters. - // Cannot be "". - required string name = 1; - - // The value(s) of the property. - // Each value can have only one value property populated. For example, - // you cannot have a values list of { value: { integerValue: 22, - // stringValue: "a" } }, but you can have { value: { listValue: - // [ { integerValue: 22 }, { stringValue: "a" } ] }. - required Value value = 4; -} - -// An entity. -// -// An entity is limited to 1 megabyte when stored. That roughly -// corresponds to a limit of 1 megabyte for the serialized form of this -// message. -message Entity { - // The entity's key. - // - // An entity must have a key, unless otherwise documented (for example, - // an entity in Value.entityValue may have no key). - // An entity's kind is its key's path's last element's kind, - // or null if it has no key. - optional Key key = 1; - // The entity's properties. - // Each property's name must be unique for its entity. - repeated Property property = 2; -} - -// The result of fetching an entity from the datastore. -message EntityResult { - // Specifies what data the 'entity' field contains. - // A ResultType is either implied (for example, in LookupResponse.found it - // is always FULL) or specified by context (for example, in message - // QueryResultBatch, field 'entity_result_type' specifies a ResultType - // for all the values in field 'entity_result'). - enum ResultType { - FULL = 1; // The entire entity. - PROJECTION = 2; // A projected subset of properties. - // The entity may have no key. - // A property value may have meaning 18. - KEY_ONLY = 3; // Only the key. - } - - // The resulting entity. - required Entity entity = 1; -} - -// A query. -message Query { - // The projection to return. If not set the entire entity is returned. - repeated PropertyExpression projection = 2; - - // The kinds to query (if empty, returns entities from all kinds). - repeated KindExpression kind = 3; - - // The filter to apply (optional). - optional Filter filter = 4; - - // The order to apply to the query results (if empty, order is unspecified). - repeated PropertyOrder order = 5; - - // The properties to group by (if empty, no grouping is applied to the - // result set). - repeated PropertyReference group_by = 6; - - // A starting point for the query results. Optional. Query cursors are - // returned in query result batches. - optional bytes /* serialized QueryCursor */ start_cursor = 7; - - // An ending point for the query results. Optional. Query cursors are - // returned in query result batches. - optional bytes /* serialized QueryCursor */ end_cursor = 8; - - // The number of results to skip. Applies before limit, but after all other - // constraints (optional, defaults to 0). - optional int32 offset = 10 [default=0]; - - // The maximum number of results to return. Applies after all other - // constraints. Optional. - optional int32 limit = 11; -} - -// A representation of a kind. -message KindExpression { - // The name of the kind. - required string name = 1; -} - -// A reference to a property relative to the kind expressions. -// exactly. -message PropertyReference { - // The name of the property. - required string name = 2; -} - -// A representation of a property in a projection. -message PropertyExpression { - enum AggregationFunction { - FIRST = 1; - } - // The property to project. - required PropertyReference property = 1; - // The aggregation function to apply to the property. Optional. - // Can only be used when grouping by at least one property. Must - // then be set on all properties in the projection that are not - // being grouped by. - optional AggregationFunction aggregation_function = 2; -} - -// The desired order for a specific property. -message PropertyOrder { - enum Direction { - ASCENDING = 1; - DESCENDING = 2; - } - // The property to order by. - required PropertyReference property = 1; - // The direction to order by. - optional Direction direction = 2 [default=ASCENDING]; -} - -// A holder for any type of filter. Exactly one field should be specified. -message Filter { - // A composite filter. - optional CompositeFilter composite_filter = 1; - // A filter on a property. - optional PropertyFilter property_filter = 2; -} - -// A filter that merges the multiple other filters using the given operation. -message CompositeFilter { - enum Operator { - AND = 1; - } - - // The operator for combining multiple filters. - required Operator operator = 1; - // The list of filters to combine. - // Must contain at least one filter. - repeated Filter filter = 2; -} - -// A filter on a specific property. -message PropertyFilter { - enum Operator { - LESS_THAN = 1; - LESS_THAN_OR_EQUAL = 2; - GREATER_THAN = 3; - GREATER_THAN_OR_EQUAL = 4; - EQUAL = 5; - - HAS_ANCESTOR = 11; - } - - // The property to filter by. - required PropertyReference property = 1; - // The operator to filter by. - required Operator operator = 2; - // The value to compare the property to. - required Value value = 3; -} - -// A GQL query. -message GqlQuery { - required string query_string = 1; - // When false, the query string must not contain a literal. - optional bool allow_literal = 2 [default = false]; - // A named argument must set field GqlQueryArg.name. - // No two named arguments may have the same name. - // For each non-reserved named binding site in the query string, - // there must be a named argument with that name, - // but not necessarily the inverse. - repeated GqlQueryArg name_arg = 3; - // Numbered binding site @1 references the first numbered argument, - // effectively using 1-based indexing, rather than the usual 0. - // A numbered argument must NOT set field GqlQueryArg.name. - // For each binding site numbered i in query_string, - // there must be an ith numbered argument. - // The inverse must also be true. - repeated GqlQueryArg number_arg = 4; -} - -// A binding argument for a GQL query. -// Exactly one of fields value and cursor must be set. -message GqlQueryArg { - // Must match regex "[A-Za-z_$][A-Za-z_$0-9]*". - // Must not match regex "__.*__". - // Must not be "". - optional string name = 1; - optional Value value = 2; - optional bytes cursor = 3; -} - -// A batch of results produced by a query. -message QueryResultBatch { - // The possible values for the 'more_results' field. - enum MoreResultsType { - NOT_FINISHED = 1; // There are additional batches to fetch from this query. - MORE_RESULTS_AFTER_LIMIT = 2; // The query is finished, but there are more - // results after the limit. - NO_MORE_RESULTS = 3; // The query has been exhausted. - } - - // The result type for every entity in entityResults. - required EntityResult.ResultType entity_result_type = 1; - // The results for this batch. - repeated EntityResult entity_result = 2; - - // A cursor that points to the position after the last result in the batch. - // May be absent. - optional bytes /* serialized QueryCursor */ end_cursor = 4; - - // The state of the query after the current batch. - required MoreResultsType more_results = 5; - - // The number of results skipped because of Query.offset. - optional int32 skipped_results = 6; -} - -// A set of changes to apply. -// -// No entity in this message may have a reserved property name, -// not even a property in an entity in a value. -// No value in this message may have meaning 18, -// not even a value in an entity in another value. -// -// If entities with duplicate keys are present, an arbitrary choice will -// be made as to which is written. -message Mutation { - // Entities to upsert. - // Each upserted entity's key must have a complete path and - // must not be reserved/read-only. - repeated Entity upsert = 1; - // Entities to update. - // Each updated entity's key must have a complete path and - // must not be reserved/read-only. - repeated Entity update = 2; - // Entities to insert. - // Each inserted entity's key must have a complete path and - // must not be reserved/read-only. - repeated Entity insert = 3; - // Insert entities with a newly allocated ID. - // Each inserted entity's key must omit the final identifier in its path and - // must not be reserved/read-only. - repeated Entity insert_auto_id = 4; - // Keys of entities to delete. - // Each key must have a complete key path and must not be reserved/read-only. - repeated Key delete = 5; - // Ignore a user specified read-only period. Optional. - optional bool force = 6; -} - -// The result of applying a mutation. -message MutationResult { - // Number of index writes. - required int32 index_updates = 1; - // Keys for insertAutoId entities. One per entity from the - // request, in the same order. - repeated Key insert_auto_id_key = 2; -} - -// Options shared by read requests. -message ReadOptions { - enum ReadConsistency { - DEFAULT = 0; - STRONG = 1; - EVENTUAL = 2; - } - - // The read consistency to use. - // Cannot be set when transaction is set. - // Lookup and ancestor queries default to STRONG, global queries default to - // EVENTUAL and cannot be set to STRONG. - optional ReadConsistency read_consistency = 1 [default=DEFAULT]; - - // The transaction to use. Optional. - optional bytes /* serialized Transaction */ transaction = 2; -} - -// The request for Lookup. -message LookupRequest { - - // Options for this lookup request. Optional. - optional ReadOptions read_options = 1; - // Keys of entities to look up from the datastore. - repeated Key key = 3; -} - -// The response for Lookup. -message LookupResponse { - - // The order of results in these fields is undefined and has no relation to - // the order of the keys in the input. - - // Entities found as ResultType.FULL entities. - repeated EntityResult found = 1; - - // Entities not found as ResultType.KEY_ONLY entities. - repeated EntityResult missing = 2; - - // A list of keys that were not looked up due to resource constraints. - repeated Key deferred = 3; -} - - -// The request for RunQuery. -message RunQueryRequest { - - // The options for this query. - optional ReadOptions read_options = 1; - - // Entities are partitioned into subsets, identified by a dataset (usually - // implicitly specified by the project) and namespace ID. Queries are scoped - // to a single partition. - // This partition ID is normalized with the standard default context - // partition ID, but all other partition IDs in RunQueryRequest are - // normalized with this partition ID as the context partition ID. - optional PartitionId partition_id = 2; - - // The query to run. - // Either this field or field gql_query must be set, but not both. - optional Query query = 3; - // The GQL query to run. - // Either this field or field query must be set, but not both. - optional GqlQuery gql_query = 7; -} - -// The response for RunQuery. -message RunQueryResponse { - - // A batch of query results (always present). - optional QueryResultBatch batch = 1; - -} - -// The request for BeginTransaction. -message BeginTransactionRequest { - - enum IsolationLevel { - SNAPSHOT = 0; // Read from a consistent snapshot. Concurrent transactions - // conflict if their mutations conflict. For example: - // Read(A),Write(B) may not conflict with Read(B),Write(A), - // but Read(B),Write(B) does conflict with Read(B),Write(B). - SERIALIZABLE = 1; // Read from a consistent snapshot. Concurrent - // transactions conflict if they cannot be serialized. - // For example Read(A),Write(B) does conflict with - // Read(B),Write(A) but Read(A) may not conflict with - // Write(A). - } - - // The transaction isolation level. - optional IsolationLevel isolation_level = 1 [default=SNAPSHOT]; -} - -// The response for BeginTransaction. -message BeginTransactionResponse { - - // The transaction identifier (always present). - optional bytes /* serialized Transaction */ transaction = 1; -} - -// The request for Rollback. -message RollbackRequest { - - // The transaction identifier, returned by a call to - // beginTransaction. - required bytes /* serialized Transaction */ transaction = 1; -} - -// The response for Rollback. -message RollbackResponse { -// Empty -} - -// The request for Commit. -message CommitRequest { - - enum Mode { - TRANSACTIONAL = 1; - NON_TRANSACTIONAL = 2; - } - - // The transaction identifier, returned by a call to - // beginTransaction. Must be set when mode is TRANSACTIONAL. - optional bytes /* serialized Transaction */ transaction = 1; - // The mutation to perform. Optional. - optional Mutation mutation = 2; - // The type of commit to perform. Either TRANSACTIONAL or NON_TRANSACTIONAL. - optional Mode mode = 5 [default=TRANSACTIONAL]; -} - -// The response for Commit. -message CommitResponse { - - // The result of performing the mutation (if any). - optional MutationResult mutation_result = 1; -} - -// The request for AllocateIds. -message AllocateIdsRequest { - - // A list of keys with incomplete key paths to allocate IDs for. - // No key may be reserved/read-only. - repeated Key key = 1; -} - -// The response for AllocateIds. -message AllocateIdsResponse { - - // The keys specified in the request (in the same order), each with - // its key path completed with a newly allocated ID. - repeated Key key = 1; -} - -// Each rpc normalizes the partition IDs of the keys in its input entities, -// and always returns entities with keys with normalized partition IDs. -// (Note that applies to all entities, including entities in values.) -service DatastoreService { - // Look up some entities by key. - rpc Lookup(LookupRequest) returns (LookupResponse) { - }; - // Query for entities. - rpc RunQuery(RunQueryRequest) returns (RunQueryResponse) { - }; - // Begin a new transaction. - rpc BeginTransaction(BeginTransactionRequest) returns (BeginTransactionResponse) { - }; - // Commit a transaction, optionally creating, deleting or modifying some - // entities. - rpc Commit(CommitRequest) returns (CommitResponse) { - }; - // Roll back a transaction. - rpc Rollback(RollbackRequest) returns (RollbackResponse) { - }; - // Allocate IDs for incomplete keys (useful for referencing an entity before - // it is inserted). - rpc AllocateIds(AllocateIdsRequest) returns (AllocateIdsResponse) { - }; -} diff --git a/lib/datastore/entity.js b/lib/datastore/entity.js index 0ce930954040..1748e8eaad27 100644 --- a/lib/datastore/entity.js +++ b/lib/datastore/entity.js @@ -142,12 +142,16 @@ module.exports.Double = Double; * // } */ function entityFromEntityProto(proto) { - var properties = proto.property || []; - return Object.keys(properties).reduce(function(acc, key) { - var property = properties[key]; - acc[property.name] = propertyToValue(property.value); - return acc; - }, {}); + var properties = proto.properties || []; + + var entity = {}; + + for (var property in properties.map) { + var value = properties.map[property].value; + entity[properties.map[property].key] = propertyToValue(value); + } + + return entity; } module.exports.entityFromEntityProto = entityFromEntityProto; @@ -177,16 +181,16 @@ function keyFromKeyProto(proto) { path: [] }; - if (proto.partition_id && proto.partition_id.namespace) { - keyOptions.namespace = proto.partition_id.namespace; + if (proto.partitionId && proto.partitionId.namespace) { + keyOptions.namespace = proto.partitionId.namespace; } - proto.path_element.forEach(function(path, index) { + proto.path.forEach(function(path, index) { var id = Number(path.id) || path.name; keyOptions.path.push(path.kind); if (id) { keyOptions.path.push(id); - } else if (index < proto.path_element.length - 1) { + } else if (index < proto.path.length - 1) { throw new Error('Invalid key. Ancestor keys require an id or name.'); } }); @@ -217,13 +221,20 @@ module.exports.keyFromKeyProto = keyFromKeyProto; */ function keyToKeyProto(key) { var keyPath = key.path; + if (keyPath.length === 0) { throw new Error('A key should contain at least a kind.'); } + var path = []; + for (var i = 0; i < keyPath.length; i += 2) { - var p = { kind: keyPath[i] }; + var p = { + kind: keyPath[i] + }; + var val = keyPath[i + 1]; + if (val) { if (is.number(val)) { p.id = val; @@ -233,16 +244,20 @@ function keyToKeyProto(key) { } else if (i < keyPath.length - 2) { // i is second last path item throw new Error('Invalid key. Ancestor keys require an id or name.'); } + path.push(p); } + var proto = { - path_element: path + path: path }; + if (key.namespace) { - proto.partition_id = { + proto.partitionId = { namespace: key.namespace }; } + return proto; } @@ -293,14 +308,17 @@ module.exports.formatArray = formatArray; */ module.exports.isKeyComplete = function(key) { var proto = keyToKeyProto(key); - for (var i = 0; i < proto.path_element.length; i++) { - if (!proto.path_element[i].kind) { + + for (var i = 0; i < proto.path.length; i++) { + if (!proto.path[i].kind) { return false; } - if (!proto.path_element[i].id && !proto.path_element[i].name) { + + if (!proto.path[i].id && !proto.path[i].name) { return false; } } + return true; }; @@ -314,53 +332,53 @@ module.exports.isKeyComplete = function(key) { * * @example * propertyToValue({ - * boolean_value: false + * booleanValue: false * }); * // false * * propertyToValue({ - * string_value: 'Hi' + * stringValue: 'Hi' * }); * // 'Hi' * * propertyToValue({ - * blob_value: new Buffer('68656c6c6f') + * blobValue: new Buffer('68656c6c6f') * }); * // */ function propertyToValue(property) { - if (exists(property.integer_value)) { - return parseInt(property.integer_value.toString(), 10); - } - if (exists(property.double_value)) { - return property.double_value; - } - if (exists(property.string_value)) { - return property.string_value; - } - if (exists(property.blob_value)) { - return property.blob_value.toBuffer(); - } - if (exists(property.timestamp_microseconds_value)) { - var microSecs = parseInt( - property.timestamp_microseconds_value.toString(), 10); - return new Date(microSecs / 1000); - } - if (exists(property.key_value)) { - return keyFromKeyProto(property.key_value); - } - if (exists(property.entity_value)) { - return entityFromEntityProto(property.entity_value); - } - if (exists(property.boolean_value)) { - return property.boolean_value; - } - if (exists(property.list_value)) { - var list = []; - for (var i = 0; i < property.list_value.length; i++) { - list.push(propertyToValue(property.list_value[i])); + var valueType = property.value_type; + var value = property[valueType]; + + switch (valueType) { + case 'arrayValue': { + return value.values.map(propertyToValue); + } + + case 'blobValue': { + return value.toBuffer(); + } + + case 'doubleValue': + case 'integerValue': { + return parseInt(value.toString(), 10); + } + + case 'entityValue': { + return entityFromEntityProto(value); + } + + case 'keyValue': { + return keyFromKeyProto(value); + } + + case 'timestampValue': { + return new Date(parseInt(value.seconds, 10) * 1000); + } + + default: { + return value; } - return list; } } @@ -369,7 +387,7 @@ module.exports.propertyToValue = propertyToValue; /** * Convert any native value to a property object. * - * @param {*} v - Original value. + * @param {*} value - Original value. * @return {object} * * @example @@ -378,63 +396,79 @@ module.exports.propertyToValue = propertyToValue; * // stringValue: 'Hi' * // } */ -function valueToProperty(v) { - var p = {}; - if (v instanceof Boolean || typeof v === 'boolean') { - p.boolean_value = v; - return p; - } - if (v instanceof Int) { - p.integer_value = v.get(); - return p; - } - if (v instanceof Double) { - p.double_value = v.get(); - return p; +function valueToProperty(value) { + var propertyObject = {}; + + if (is.boolean(value)) { + propertyObject.booleanValue = value; + return propertyObject; } - if (v instanceof Number || typeof v === 'number') { - if (v % 1 === 0) { - p.integer_value = v; + + if (is.number(value)) { + if (value % 1 === 0) { + value = new Int(value); } else { - p.double_value = v; + value = new Double(value); } - return p; } - if (v instanceof Date) { - p.timestamp_microseconds_value = v.getTime() * 1000; - return p; + + if (value instanceof Int) { + propertyObject.integerValue = value.get(); + return propertyObject; } - if (v instanceof String || typeof v === 'string') { - p.string_value = v; - return p; + + if (value instanceof Double) { + propertyObject.doubleValue = value.get(); + return propertyObject; } - if (v instanceof Buffer) { - p.blob_value = v; - return p; + + if (value instanceof Date) { + propertyObject.timestampValue = { + seconds: value.getTime() / 1000 + }; + return propertyObject; } - if (Array.isArray(v)) { - p.list_value = v.map(function(item) { - return valueToProperty(item); - }); - return p; + + if (is.string(value)) { + propertyObject.stringValue = value; + return propertyObject; + } + + if (value instanceof Buffer) { + propertyObject.blobValue = value; + return propertyObject; + } + + if (is.array(value)) { + propertyObject.arrayValue = { + values: value.map(valueToProperty) + }; + return propertyObject; } - if (v instanceof Key) { - p.key_value = keyToKeyProto(v); - return p; + + if (value instanceof Key) { + propertyObject.keyValue = keyToKeyProto(value); + return propertyObject; } - if (v instanceof Object && Object.keys(v).length > 0) { - var property = []; - Object.keys(v).forEach(function(k) { - property.push({ - name: k, - value: valueToProperty(v[k]) - }); + + if (is.object(value) && Object.keys(value).length > 0) { + var property = Object.keys(value).map(function(key) { + return { + name: key, + value: valueToProperty(value[key]) + }; }); - p.entity_value = { property: property }; - p.indexed = false; - return p; + + propertyObject.entityValue = { + property: property + }; + + propertyObject.excludeFromIndexes = true; + + return propertyObject; } - throw new Error('Unsupported field value, ' + v + ', is provided.'); + + throw new Error('Unsupported field value, ' + value + ', was provided.'); } module.exports.valueToProperty = valueToProperty; @@ -452,18 +486,12 @@ module.exports.valueToProperty = valueToProperty; * }); * // { * // key: null, - * // property: [ - * // { - * // name: 'name', - * // value: { - * // string_value: 'Burcu' - * // } + * // properties: { + * // name: { + * // stringValue: 'Burcu' * // }, - * // { - * // name: 'legit', - * // value: { - * // boolean_value: true - * // } + * // legit: { + * // booleanValue: true * // } * // } * // } @@ -471,12 +499,11 @@ module.exports.valueToProperty = valueToProperty; function entityToEntityProto(entity) { return { key: null, - property: Object.keys(entity).map(function(key) { - return { - name: key, - value: valueToProperty(entity[key]) - }; - }) + properties: Object.keys(entity).reduce(function(acc, key) { + var value = entity[key]; + acc[key] = valueToProperty(value); + return acc; + }, {}) }; } @@ -517,69 +544,85 @@ module.exports.entityToEntityProto = entityToEntityProto; * // } */ function queryToQueryProto(q) { - var query = {}; - query.projection = q.selectVal.map(function(v) { - return { property: { name: v } }; - }); - query.kind = q.kinds.map(function(k) { - return { name: k }; - }); - // filters + var query = { + distinctOn: q.groupByVal.map(function(g) { + return { + name: g + }; + }), + + kind: q.kinds.map(function(k) { + return { + name: k + }; + }), + + order: q.orders.map(function(o) { + return { + property: { + name: o.name + }, + direction: SIGN_TO_ORDER[o.sign] + }; + }), + + projection: q.selectVal.map(function(v) { + return { + property: { + name: v + } + }; + }) + }; + if (q.filters.length > 0) { var filters = q.filters.map(function(f) { var val = {}; + if (f.name === '__key__') { - val.key_value = keyToKeyProto(f.val); + val.keyValue = keyToKeyProto(f.val); } else { val = valueToProperty(f.val); } - var property = { - property: { name: f.name }, - operator: OP_TO_OPERATOR[f.op], - value: val + + return { + propertyFilter: { + property: { + name: f.name + }, + op: OP_TO_OPERATOR[f.op], + value: val + } }; - return { property_filter: property }; }); + query.filter = { - composite_filter: { filter: filters, operator: 'AND' } + compositeFilter: { + filters: filters, + op: 'AND' + } }; } - query.order = q.orders.map(function(o) { - return { - property: { name: o.name }, - direction: SIGN_TO_ORDER[o.sign] - }; - }); - query.group_by = q.groupByVal.map(function(g) { - return { name: g }; - }); - // pagination + if (q.startVal) { - query.start_cursor = new Buffer(q.startVal, 'base64'); + query.startCursor = new Buffer(q.startVal, 'base64'); } + if (q.endVal) { - query.end_cursor = new Buffer(q.endVal, 'base64'); + query.endCursor = new Buffer(q.endVal, 'base64'); } + if (q.offsetVal > 0) { query.offset = q.offsetVal; } + if (q.limitVal > 0) { - query.limit = q.limitVal; + query.limit = { + value: q.limitVal + }; } + return query; } module.exports.queryToQueryProto = queryToQueryProto; - -/** - * Does a value exist? - * - * @todo If protobufjs had hasFieldname support, we wouldn't need a utility. - * Later address it on Protobuf.js. - * - * @param {*} value - Value. - * @return {boolean} - */ -function exists(value) { - return (value !== null && value !== undefined); -} diff --git a/lib/datastore/request.js b/lib/datastore/request.js index eb73093e0f87..a67a4a53546f 100644 --- a/lib/datastore/request.js +++ b/lib/datastore/request.js @@ -22,6 +22,7 @@ var arrify = require('arrify'); var concat = require('concat-stream'); +var extend = require('extend'); var format = require('string-format-obj'); var is = require('is'); var propAssign = require('prop-assign'); @@ -32,7 +33,6 @@ var request = require('request').defaults({ }); var split = require('split-array-stream'); var through = require('through2'); -var extend = require('extend'); /** * @type {module:datastore/entity} @@ -41,10 +41,10 @@ var extend = require('extend'); var entity = require('./entity.js'); /** - * @type {module:datastore/pb} + * @type {module:proto} * @private */ -var pb = require('./pb.js'); +var datastoreProto = require('../../proto/index.js').datastore.v1beta3; /** * @type {module:datastore/query} @@ -195,7 +195,7 @@ DatastoreRequest.prototype.get = function(keys, callback) { }); } - this.makeReq_('lookup', { key: keys }, onApiResponse); + this.makeReq_('lookup', { keys: keys }, onApiResponse); return stream; }; @@ -232,7 +232,7 @@ DatastoreRequest.prototype.insert = function(entities, callback) { * @param {object|object[]} entities - Datastore key object(s). * @param {Key} entities.key - Datastore key object. * @param {string=} entities.method - Optional method to explicity use for save. - * The choices include 'insert', 'update', 'upsert' and 'insert_auto_id'. + * The choices include 'insert', 'update', and 'upsert'. * @param {object|object[]} entities.data - Data to save with the provided key. * If you provide an array of objects, you must use the explicit syntax: * `name` for the name of the property and `value` for its value. You may @@ -382,13 +382,12 @@ DatastoreRequest.prototype.insert = function(entities, callback) { DatastoreRequest.prototype.save = function(entities, callback) { entities = arrify(entities); - var insertIndexes = []; - - var mutation = { - insert: [], - update: [], - upsert: [], - insert_auto_id: [] + var insertIndexes = {}; + var mutations = []; + var methods = { + insert: true, + update: true, + upsert: true }; // Iterate over the entity objects, build a proto from all keys and values, @@ -396,24 +395,33 @@ DatastoreRequest.prototype.save = function(entities, callback) { entities.forEach(function(entityObject, index) { entityObject = extend(true, {}, entityObject); + var mutation = {}; var entityProto = {}; - var method = entityObject.method; + var method = 'upsert'; + + if (entityObject.method) { + if (methods[entityObject.method]) { + method = methods[entityObject.method]; + } else { + throw new Error('Method ' + method + ' not recognized.'); + } + } + + if (!entity.isKeyComplete(entityObject.key)) { + insertIndexes[index] = true; + } if (is.array(entityObject.data)) { - entityProto.property = entityObject.data.map(function(data) { + entityProto.properties = entityObject.data.map(function(data) { data.value = entity.valueToProperty(data.value); if (is.boolean(data.excludeFromIndexes)) { - var indexed = !data.excludeFromIndexes; + var excluded = data.excludeFromIndexes; + var values = data.value.arrayValue; - if (is.array(data.value.list_value)) { - data.value.list_value = - data.value.list_value.map(propAssign('indexed', indexed)); - } else { - data.value.indexed = indexed; + if (is.array(values)) { + values = values.map(propAssign('excludeFromIndexes', excluded)); } - - delete data.excludeFromIndexes; } return data; @@ -424,28 +432,12 @@ DatastoreRequest.prototype.save = function(entities, callback) { entityProto.key = entity.keyToKeyProto(entityObject.key); - if (method) { - if (mutation[method]) { - mutation[method].push(entityProto); - - if (method === 'insert_auto_id') { - insertIndexes.push(index); - } - } else { - throw new Error('Method ' + method + ' not recognized.'); - } - } else { - if (entity.isKeyComplete(entityObject.key)) { - mutation.upsert.push(entityProto); - } else { - insertIndexes.push(index); - mutation.insert_auto_id.push(entityProto); - } - } + mutation[method] = entityProto; + mutations.push(mutation); }); var req = { - mutation: mutation + mutations: mutations }; if (this.id) { @@ -462,10 +454,15 @@ DatastoreRequest.prototype.save = function(entities, callback) { return; } - var autoInserted = (resp.mutation_result.insert_auto_id_key || []); - autoInserted.forEach(function(key, index) { - var path = entity.keyFromKeyProto(key).path; - entities[insertIndexes[index]].key.path = path; + arrify(resp.mutationResults).forEach(function(result, index) { + if (!result.key) { + return; + } + + if (insertIndexes[index]) { + var path = entity.keyFromKeyProto(result.key).path; + entities[index].key.path = path; + } }); callback(null, resp); @@ -501,9 +498,11 @@ DatastoreRequest.prototype.delete = function(keys, callback) { callback = callback || util.noop; var req = { - mutation: { - delete: arrify(keys).map(entity.keyToKeyProto) - } + mutations: arrify(keys).map(function(key) { + return { + delete: entity.keyToKeyProto(key) + }; + }) }; if (this.id) { @@ -601,12 +600,12 @@ DatastoreRequest.prototype.delete = function(keys, callback) { */ DatastoreRequest.prototype.runQuery = function(query, callback) { var req = { - read_options: {}, + readOptions: {}, query: entity.queryToQueryProto(query) }; if (query.namespace) { - req.partition_id = { + req.partitionId = { namespace: query.namespace }; } @@ -617,11 +616,15 @@ DatastoreRequest.prototype.runQuery = function(query, callback) { return; } - var entities = entity.formatArray(resp.batch.entity_result); + var entities = []; var nextQuery = null; - if (resp.batch.end_cursor && entities.length > 0) { - var endCursor = resp.batch.end_cursor.toBase64(); + if (resp.batch.entityResults) { + entities = entity.formatArray(resp.batch.entityResults); + } + + if (resp.batch.endCursor && entities.length > 0) { + var endCursor = resp.batch.endCursor.toBase64(); nextQuery = extend(true, new Query(), query); nextQuery.start(endCursor).offset(0); @@ -677,7 +680,7 @@ DatastoreRequest.prototype.allocateIds = function(incompleteKey, n, callback) { } var req = { - key: incompleteKeys + keys: incompleteKeys }; this.makeReq_('allocateIds', req, function(err, resp) { @@ -686,7 +689,7 @@ DatastoreRequest.prototype.allocateIds = function(incompleteKey, n, callback) { return; } - var keys = (resp.key || []).map(entity.keyFromKeyProto); + var keys = (resp.keys || []).map(entity.keyFromKeyProto); callback(null, keys, resp); }); @@ -720,7 +723,7 @@ DatastoreRequest.prototype.upsert = function(entities, callback) { * * @example * var deleteRequest = { - * mutation: { + * mutations: { * delete: [] // datastore key objects. * } * }; @@ -732,7 +735,6 @@ DatastoreRequest.prototype.upsert = function(entities, callback) { * transaction.makeReq_('commit', deleteRequest, callback); */ DatastoreRequest.prototype.makeReq_ = function(method, body, callback) { - // TODO: Handle non-HTTP 200 cases. if (!callback) { callback = body; body = {}; @@ -755,22 +757,23 @@ DatastoreRequest.prototype.makeReq_ = function(method, body, callback) { } if (method === 'lookup' && this.id) { - body.read_options = body.read_options || {}; - body.read_options.transaction = this.id; + body.readOptions = body.readOptions || {}; + body.readOptions.transaction = this.id; } var pbKey = method[0].toUpperCase() + method.substr(1); - var pbRequest = new pb[pbKey + 'Request'](body).toBuffer(); - var pbResponse = pb[pbKey + 'Response']; + var pbRequest = datastoreProto[pbKey + 'Request'].encode(body).toBuffer(); + var pbResponse = datastoreProto[pbKey + 'Response']; var reqOpts = { method: 'POST', - uri: format('{apiEndpoint}/{path}/{projectId}/{method}', { + uri: format('{apiEndpoint}/v1beta3/projects/{projectId}:{method}', { apiEndpoint: this.apiEndpoint, - path: 'datastore/v1beta2/datasets', projectId: this.projectId, method: method }), + body: is.empty(body) ? '' : pbRequest, + encoding: null, headers: { 'Content-Type': 'application/x-protobuf' } @@ -779,34 +782,25 @@ DatastoreRequest.prototype.makeReq_ = function(method, body, callback) { this.makeAuthenticatedRequest_(reqOpts, { onAuthenticated: function(err, authenticatedReqOpts) { if (err) { - callback(err, null); // TODO(ryanseys): What goes as third parameter? + callback(err, null); return; } - authenticatedReqOpts.headers = authenticatedReqOpts.headers || {}; - authenticatedReqOpts.headers['Content-Length'] = pbRequest.length; - - var apiRequest = request(authenticatedReqOpts); + request(authenticatedReqOpts, function(err, resp, body) { + if (err) { + callback(err); + return; + } - apiRequest.on('error', callback); + util.handleResp(null, resp, body, function(err, result) { + if (err) { + callback(err, null, result); + return; + } - apiRequest.on('response', function(resp) { - var buffer = new Buffer(''); - resp.on('data', function(chunk) { - buffer = Buffer.concat([buffer, chunk]); - }); - resp.on('end', function() { - util.handleResp(null, resp, buffer.toString(), function(err, result) { - if (err) { - callback(err, null, result); - return; - } - callback(null, pbResponse.decode(buffer), result); - }); + callback(null, pbResponse.decode(body), result); }); }); - - apiRequest.end(pbRequest); } }); }; diff --git a/package.json b/package.json index 252f52ffb5a1..87960bcbc833 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "main": "./lib/index", "files": [ "lib/", + "proto/", "AUTHORS", "CONTRIBUTORS", "COPYING" @@ -99,7 +100,7 @@ "once": "^1.3.1", "prop-assign": "^1.0.0", "propprop": "^0.3.0", - "protobufjs": "^4.0.0", + "protobufjs": "^4.1.0", "pumpify": "^1.3.3", "request": "^2.53.0", "retry-request": "^1.2.1", diff --git a/proto/google/api/annotations.proto b/proto/google/api/annotations.proto new file mode 100644 index 000000000000..cbd18b847f39 --- /dev/null +++ b/proto/google/api/annotations.proto @@ -0,0 +1,29 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/api/http.proto"; +import "google/protobuf/descriptor.proto"; + +option java_multiple_files = true; +option java_outer_classname = "AnnotationsProto"; +option java_package = "com.google.api"; + +extend google.protobuf.MethodOptions { + // See `HttpRule`. + HttpRule http = 72295728; +} diff --git a/proto/google/api/http.proto b/proto/google/api/http.proto new file mode 100644 index 000000000000..4bbadbb76d0f --- /dev/null +++ b/proto/google/api/http.proto @@ -0,0 +1,245 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option java_multiple_files = true; +option java_outer_classname = "HttpProto"; +option java_package = "com.google.api"; + + +// `HttpRule` defines the mapping of an RPC method to one or more HTTP +// REST APIs. The mapping determines what portions of the request +// message are populated from the path, query parameters, or body of +// the HTTP request. The mapping is typically specified as an +// `google.api.http` annotation, see "google/api/annotations.proto" +// for details. +// +// The mapping consists of a field specifying the path template and +// method kind. The path template can refer to fields in the request +// message, as in the example below which describes a REST GET +// operation on a resource collection of messages: +// +// ```proto +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http).get = "/v1/messages/{message_id}"; +// } +// } +// message GetMessageRequest { +// string message_id = 1; // mapped to the URL +// } +// message Message { +// string text = 1; // content of the resource +// } +// ``` +// +// This definition enables an automatic, bidrectional mapping of HTTP +// JSON to RPC. Example: +// +// HTTP | RPC +// -----|----- +// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")` +// +// In general, not only fields but also field paths can be referenced +// from a path pattern. Fields mapped to the path pattern cannot be +// repeated and must have a primitive (non-message) type. +// +// Any fields in the request message which are not bound by the path +// pattern automatically become (optional) HTTP query +// parameters. Assume the following definition of the request message: +// +// ```proto +// message GetMessageRequest { +// string message_id = 1; // mapped to the URL +// int64 revision = 2; // becomes a parameter +// } +// ``` +// +// This enables a HTTP JSON to RPC mapping as below: +// +// HTTP | RPC +// -----|----- +// `GET /v1/messages/123456?revision=2` | `GetMessage(message_id: "123456" revision: 2)` +// +// Note that fields which are mapped to HTTP parameters must have a +// primitive type or a repeated primitive type. Message types are not +// allowed. In the case of a repeated type, the parameter can be +// repeated in the URL, as in `...?param=A¶m=B`. +// +// For HTTP method kinds which allow a request body, the `body` field +// specifies the mapping. Consider a REST update method on the +// message resource collection: +// +// ```proto +// service Messaging { +// rpc UpdateMessage(UpdateMessageRequest) returns (Message) { +// option (google.api.http) = { +// put: "/v1/messages/{message_id}" +// body: "message" +// } +// } +// message UpdateMessageRequest { +// string message_id = 1; // mapped to the URL +// Message message = 2; // mapped to the body +// } +// ``` +// +// The following HTTP JSON to RPC mapping is enabled, where the +// representation of the JSON in the request body is determined by +// protos JSON encoding: +// +// HTTP | RPC +// -----|----- +// `PUT /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: "123456" message { text: "Hi!" })` +// +// The special name `*` can be used in the body mapping to define that +// every field not bound by the path template should be mapped to the +// request body. This enables the following alternative definition of +// the update method: +// +// ```proto +// service Messaging { +// rpc UpdateMessage(Message) returns (Message) { +// option (google.api.http) = { +// put: "/v1/messages/{message_id}" +// body: "*" +// } +// } +// message Message { +// string message_id = 2; +// string text = 2; +// } +// ``` +// +// The following HTTP JSON to RPC mapping is enabled: +// +// HTTP | RPC +// -----|----- +// `PUT /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: "123456" text: "Hi!")` +// +// Note that when using `*` in the body mapping, it is not possible to +// have HTTP parameters, as all fields not bound by the path end in +// the body. This makes this option more rarely used in practice of +// defining REST APIs. The common usage of `*` is in custom methods +// which don't use the URL at all for transferring data. +// +// It is possible to define multiple HTTP methods for one RPC by using +// the `additional_bindings` option. Example: +// +// ```proto +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/messages/{message_id}" +// additional_bindings { +// get: "/v1/users/{user_id}/messages/{message_id}" +// } +// } +// } +// message GetMessageRequest { +// string message_id = 1; +// string user_id = 2; +// } +// ``` +// +// This enables the following two alternative HTTP JSON to RPC +// mappings: +// +// HTTP | RPC +// -----|----- +// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")` +// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: "123456")` +// +// # Rules for HTTP mapping +// The rules for mapping HTTP path, query parameters, and body fields +// to the request message are as follows: +// +// 1. The `body` field specifies either `*` or a field path, or is +// omitted. If omitted, it assumes there is no HTTP body. +// 2. Leaf fields (recursive expansion of nested messages in the +// request) can be classified into three types: +// (a) Matched in the URL template. +// (b) Covered by body (if body is `*`, everything except (a) fields; +// else everything under the body field) +// (c) All other fields. +// 3. URL query parameters found in the HTTP request are mapped to (c) fields. +// 4. Any body sent with an HTTP request can contain only (b) fields. +// +// The syntax of the path template is as follows: +// +// Template = "/" Segments [ Verb ] ; +// Segments = Segment { "/" Segment } ; +// Segment = "*" | "**" | LITERAL | Variable ; +// Variable = "{" FieldPath [ "=" Segments ] "}" ; +// FieldPath = IDENT { "." IDENT } ; +// Verb = ":" LITERAL ; +// +// `*` matches a single path component, `**` zero or more path components, and +// `LITERAL` a constant. A `Variable` can match an entire path as specified +// again by a template; this nested template must not contain further variables. +// If no template is given with a variable, it matches a single path component. +// The notation `{var}` is henceforth equivalent to `{var=*}`. NOTE: the field +// paths in variables and in the `body` must not refer to repeated fields. +// +// Use CustomHttpPattern to specify any HTTP method that is not included in the +// pattern field, such as HEAD, or "*" to leave the HTTP method unspecified for +// a given URL path rule. The wild-card rule is useful for services that provide +// content to Web (HTML) clients. +message HttpRule { + + // Determines the URL pattern is matched by this rules. This pattern can be + // used with any of the {get|put|post|delete|patch} methods. A custom method + // can be defined using the 'custom' field. + oneof pattern { + // Used for listing and getting information about resources. + string get = 2; + + // Used for updating a resource. + string put = 3; + + // Used for creating a resource. + string post = 4; + + // Used for deleting a resource. + string delete = 5; + + // Used for updating a resource. + string patch = 6; + + // Custom pattern is used for defining custom verbs. + CustomHttpPattern custom = 8; + } + + // The name of the request field whose value is mapped to the HTTP body, or + // `*` for mapping all fields not captured by the path pattern to the HTTP + // body. NOTE: the referred field must not be a repeated field. + string body = 7; + + // Additional HTTP bindings for the selector. Nested bindings must + // not contain an `additional_bindings` field themselves (that is, + // the nesting may only be one level deep). + repeated HttpRule additional_bindings = 11; +} + +// A custom pattern is used for defining custom HTTP verb. +message CustomHttpPattern { + // The name of this custom HTTP verb. + string kind = 1; + + // The path matched by this custom verb. + string path = 2; +} diff --git a/proto/google/datastore/v1beta3/datastore.proto b/proto/google/datastore/v1beta3/datastore.proto new file mode 100644 index 000000000000..beeb138826a5 --- /dev/null +++ b/proto/google/datastore/v1beta3/datastore.proto @@ -0,0 +1,281 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.datastore.v1beta3; + +import "google/api/annotations.proto"; +import "google/datastore/v1beta3/entity.proto"; +import "google/datastore/v1beta3/query.proto"; + +option java_multiple_files = true; +option java_outer_classname = "DatastoreProto"; +option java_package = "com.google.datastore.v1beta3"; + + +// Each RPC normalizes the partition IDs of the keys in its input entities, +// and always returns entities with keys with normalized partition IDs. +// This applies to all keys and entities, including those in values. +// +service Datastore { + // Look up entities by key. + rpc Lookup(LookupRequest) returns (LookupResponse) { + option (google.api.http) = { post: "/v1beta3/projects/{project_id}:lookup" body: "*" }; + } + + // Query for entities. + rpc RunQuery(RunQueryRequest) returns (RunQueryResponse) { + option (google.api.http) = { post: "/v1beta3/projects/{project_id}:runQuery" body: "*" }; + } + + // Begin a new transaction. + rpc BeginTransaction(BeginTransactionRequest) returns (BeginTransactionResponse) { + option (google.api.http) = { post: "/v1beta3/projects/{project_id}:beginTransaction" body: "*" }; + } + + // Commit a transaction, optionally creating, deleting or modifying some + // entities. + rpc Commit(CommitRequest) returns (CommitResponse) { + option (google.api.http) = { post: "/v1beta3/projects/{project_id}:commit" body: "*" }; + } + + // Roll back a transaction. + rpc Rollback(RollbackRequest) returns (RollbackResponse) { + option (google.api.http) = { post: "/v1beta3/projects/{project_id}:rollback" body: "*" }; + } + + // Allocate IDs for the given keys (useful for referencing an entity before + // it is inserted). + rpc AllocateIds(AllocateIdsRequest) returns (AllocateIdsResponse) { + option (google.api.http) = { post: "/v1beta3/projects/{project_id}:allocateIds" body: "*" }; + } +} + +// The request for [google.datastore.v1beta3.Datastore.Lookup][google.datastore.v1beta3.Datastore.Lookup]. +message LookupRequest { + // Project ID against which to make the request. Not required if the request + // is made over HTTP. + string project_id = 8; + + // Options for this lookup request. + ReadOptions read_options = 1; + + // Keys of entities to look up. + repeated Key keys = 3; +} + +// The response for [google.datastore.v1beta3.Datastore.Lookup][google.datastore.v1beta3.Datastore.Lookup]. +message LookupResponse { + // Entities found as `ResultType.FULL` entities. The order of results in this + // field is undefined and has no relation to the order of the keys in the + // input. + repeated EntityResult found = 1; + + // Entities not found as `ResultType.KEY_ONLY` entities. The order of results + // in this field is undefined and has no relation to the order of the keys + // in the input. + repeated EntityResult missing = 2; + + // A list of keys that were not looked up due to resource constraints. The + // order of results in this field is undefined and has no relation to the + // order of the keys in the input. + repeated Key deferred = 3; +} + +// The request for [google.datastore.v1beta3.Datastore.RunQuery][google.datastore.v1beta3.Datastore.RunQuery]. +message RunQueryRequest { + // Project ID against which to make the request. Not required if the request + // is made over HTTP. + string project_id = 8; + + // Entities are partitioned into subsets, identified by a partition ID. + // Queries are scoped to a single partition. + // This partition ID is normalized with the standard default context + // partition ID, but all other partition IDs in `RunQueryRequest` are + // normalized with this partition ID as the context partition ID. + PartitionId partition_id = 2; + + // The options for this query. + ReadOptions read_options = 1; + + // The type of query. + oneof query_type { + // The query to run. + Query query = 3; + + // The GQL query to run. + GqlQuery gql_query = 7; + } +} + +// The response for [google.datastore.v1beta3.Datastore.RunQuery][google.datastore.v1beta3.Datastore.RunQuery]. +message RunQueryResponse { + // A batch of query results (always present). + QueryResultBatch batch = 1; + + // The parsed form of the `GqlQuery` from the request, if it was set. + Query query = 2; +} + +// The request for [google.datastore.v1beta3.Datastore.BeginTransaction][google.datastore.v1beta3.Datastore.BeginTransaction]. +message BeginTransactionRequest { + // Project ID against which to make the request. Not required if the request + // is made over HTTP. + string project_id = 8; +} + +// The response for [google.datastore.v1beta3.Datastore.BeginTransaction][google.datastore.v1beta3.Datastore.BeginTransaction]. +message BeginTransactionResponse { + // The transaction identifier (always present). + bytes transaction = 1; +} + +// The request for [google.datastore.v1beta3.Datastore.Rollback][google.datastore.v1beta3.Datastore.Rollback]. +message RollbackRequest { + // Project ID against which to make the request. Not required if the request + // is made over HTTP. + string project_id = 8; + + // The transaction identifier, returned by a call to + // [google.datastore.v1beta3.Datastore.BeginTransaction][google.datastore.v1beta3.Datastore.BeginTransaction]. + bytes transaction = 1; +} + +// The response for [google.datastore.v1beta3.Datastore.Rollback][google.datastore.v1beta3.Datastore.Rollback] +// (an empty message). +message RollbackResponse { + +} + +// The request for [google.datastore.v1beta3.Datastore.Commit][google.datastore.v1beta3.Datastore.Commit]. +message CommitRequest { + // Commit modes. + enum Mode { + // Unspecified. + MODE_UNSPECIFIED = 0; + + // Transactional. + TRANSACTIONAL = 1; + + // Non-transactional. + NON_TRANSACTIONAL = 2; + } + + // Project ID against which to make the request. Not required if the request + // is made over HTTP. + string project_id = 8; + + // The type of commit to perform. Defaults to `TRANSACTIONAL`. + Mode mode = 5; + + // The transaction identifier, returned by a call to + // [google.datastore.v1beta3.Datastore.BeginTransaction][google.datastore.v1beta3.Datastore.BeginTransaction]. + // Must be set when mode is `TRANSACTIONAL`. + bytes transaction = 1; + + // The mutations to perform. + repeated Mutation mutations = 6; +} + +// The response for [google.datastore.v1beta3.Datastore.Commit][google.datastore.v1beta3.Datastore.Commit]. +message CommitResponse { + // The result of performing the mutations. + // The i-th mutation result corresponds to the i-th mutation in the request. + repeated MutationResult mutation_results = 3; + + // The number of index entries updated during the commit. + int32 index_updates = 4; +} + +// The request for [google.datastore.v1beta3.Datastore.AllocateIds][google.datastore.v1beta3.Datastore.AllocateIds]. +message AllocateIdsRequest { + // Project ID against which to make the request. Not required if the request + // is made over HTTP. + string project_id = 8; + + // A list of keys with incomplete key paths for which to allocate IDs. + // No key may be reserved/read-only. + repeated Key keys = 1; +} + +// The response for [google.datastore.v1beta3.Datastore.AllocateIds][google.datastore.v1beta3.Datastore.AllocateIds]. +message AllocateIdsResponse { + // The keys specified in the request (in the same order), each with + // its key path completed with a newly allocated ID. + repeated Key keys = 1; +} + +// A mutation to apply to an entity. +message Mutation { + // The mutation operation. + // + // For `insert`, `update`, and `upsert`: + // - The entity's key must not be reserved/read-only. + // - No property in the entity may have a reserved name, + // not even a property in an entity in a value. + // - No value in the entity may have meaning 18, + // not even a value in an entity in another value. + oneof operation { + // The entity to insert. The entity must not already exist. + // The entity's key's final path element may be incomplete. + Entity insert = 4; + + // The entity to update. The entity must already exist. + // Must have a complete key path. + Entity update = 5; + + // The entity to upsert. The entity may or may not already exist. + // The entity's key's final path element may be incomplete. + Entity upsert = 6; + + // The key of the entity to delete. The entity may or may not already exist. + // Must have a complete key path and must not be reserved/read-only. + Key delete = 7; + } +} + +// The result of applying a mutation. +message MutationResult { + // The automatically allocated key. + // Set only when the mutation allocated a key. + Key key = 3; +} + +// Options shared by read requests. +message ReadOptions { + // Read consistencies. + enum ReadConsistency { + // Unspecified. + READ_CONSISTENCY_UNSPECIFIED = 0; + + // Strong consistency. + STRONG = 1; + + // Eventual consistency. + EVENTUAL = 2; + } + + // If not specified, lookups and ancestor queries default to + // `read_consistency`=`STRONG`, global queries default to + // `read_consistency`=`EVENTUAL`. + oneof consistency_type { + // The non-transactional read consistency to use. + // Cannot be set to `STRONG` for global queries. + ReadConsistency read_consistency = 1; + + // The transaction identifier to use. + bytes transaction = 2; + } +} diff --git a/proto/google/datastore/v1beta3/entity.proto b/proto/google/datastore/v1beta3/entity.proto new file mode 100644 index 000000000000..8406bb86d1bc --- /dev/null +++ b/proto/google/datastore/v1beta3/entity.proto @@ -0,0 +1,189 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.datastore.v1beta3; + +import "google/api/annotations.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/timestamp.proto"; +import "google/type/latlng.proto"; + +option java_multiple_files = true; +option java_outer_classname = "EntityProto"; +option java_package = "com.google.datastore.v1beta3"; + + +// A partition ID identifies a grouping of entities. The grouping is always +// by project and namespace, however the namespace ID may be empty. +// +// A partition ID contains several dimensions: +// project ID and namespace ID. +// Partition dimensions: +// A dimension may be `""`. +// A dimension must be valid UTF-8 bytes. +// A dimension's value must match regex `[A-Za-z\d\.\-_]{1,100}` +// If the value of any dimension matches regex `__.*__`, the partition is +// reserved/read-only. +// A reserved/read-only partition ID is forbidden in certain documented +// contexts. +message PartitionId { + // Project ID. + string project_id = 2; + + // Namespace ID. + string namespace_id = 4; +} + +// A unique identifier for an entity. +// If a key's partition id or any of its path kinds or names are +// reserved/read-only, the key is reserved/read-only. +// A reserved/read-only key is forbidden in certain documented contexts. +message Key { + // A (kind, ID/name) pair used to construct a key path. + // + // If either name nor ID is set, the element is complete. + // If neither is set, the element is incomplete. + message PathElement { + // The kind of the entity. + // A kind matching regex `__.*__` is reserved/read-only. + // A kind must not contain more than 1500 bytes when UTF-8 encoded. + // Cannot be `""`. + string kind = 1; + + // The type of id. + oneof id_type { + // The auto allocated ID of the entity. + // Never equal to zero. Values less than zero are discouraged and may not + // be supported in the future. + int64 id = 2; + + // The name of the entity. + // A name matching regex `__.*__` is reserved/read-only. + // A name must not be more than 1500 bytes when UTF-8 encoded. + // Cannot be `""`. + string name = 3; + } + } + + // Entities are partitioned into subsets, currently identified by a dataset + // (usually implicitly specified by the project) and namespace ID. + // Queries are scoped to a single partition. + PartitionId partition_id = 1; + + // The entity path. + // An entity path consists of one or more elements composed of a kind and a + // string or numerical identifier, which identify entities. The first + // element identifies a _root entity_, the second element identifies + // a _child_ of the root entity, the third element a child of the + // second entity, and so forth. The entities identified by all prefixes of + // the path are called the element's _ancestors_. + // An entity path is always fully complete: *all* of the entity's ancestors + // are required to be in the path along with the entity identifier itself. + // The only exception is that in some documented cases, the identifier in the + // last path element (for the entity) itself may be omitted. A path can never + // be empty. The path can have at most 100 elements. + repeated PathElement path = 2; +} + +// An array value. +message ArrayValue { + // Values in the array. + repeated Value values = 1; +} + +// A message that can hold any of the supported value types and associated +// metadata. +message Value { + // Must have a value set. + oneof value_type { + // A null value. + google.protobuf.NullValue null_value = 11; + + // A boolean value. + bool boolean_value = 1; + + // An integer value. + int64 integer_value = 2; + + // A double value. + double double_value = 3; + + // A timestamp value. + // When stored in the Datastore, precise only to microseconds; + // any additional precision is rounded down. + google.protobuf.Timestamp timestamp_value = 10; + + // A key value. + Key key_value = 5; + + // A UTF-8 encoded string value. + // When `exclude_from_indexes` is false (it is indexed) and meaning is not + // 2, may have at most 1500 bytes. + // When meaning is 2, may have at most 2083 bytes. + // Otherwise, may be set to at least 1,000,000 bytes + string string_value = 17; + + // A blob value. + // May have at most 1,000,000 bytes. + // When `exclude_from_indexes` is false, may have at most 1500 bytes. + bytes blob_value = 18; + + // A geo point value representing a point on the surface of Earth. + google.type.LatLng geo_point_value = 8; + + // An entity value. + // May have no key. + // May have a key with an incomplete key path. + // May have a reserved/read-only key. + Entity entity_value = 6; + + // An array value. + // Cannot contain another array value. + // A `Value` instance that sets field `array_value` must not set fields + // `meaning` or `exclude_from_indexes`. + ArrayValue array_value = 9; + } + + // The `meaning` field should only be populated for backwards compatibility. + int32 meaning = 14; + + // If the value should be excluded from all indexes including those defined + // explicitly. + bool exclude_from_indexes = 19; +} + +// An entity. +// +// An entity is limited to 1 megabyte when stored. That _roughly_ +// corresponds to a limit of 1 megabyte for the serialized form of this +// message. +message Entity { + // The entity's key. + // + // An entity must have a key, unless otherwise documented (for example, + // an entity in `Value.entity_value` may have no key). + // An entity's kind is its key's path's last element's kind, + // or null if it has no key. + Key key = 1; + + // The entity's properties. + // The map's keys are property names. + // A property name matching regex `__.*__` is reserved. + // A reserved property name is forbidden in certain documented contexts. + // The name must not contain more than 500 characters. + // The name cannot be `""`. + map properties = 3; +} diff --git a/proto/google/datastore/v1beta3/query.proto b/proto/google/datastore/v1beta3/query.proto new file mode 100644 index 000000000000..b95ff63e3231 --- /dev/null +++ b/proto/google/datastore/v1beta3/query.proto @@ -0,0 +1,281 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.datastore.v1beta3; + +import "google/api/annotations.proto"; +import "google/datastore/v1beta3/entity.proto"; +import "google/protobuf/wrappers.proto"; + +option java_multiple_files = true; +option java_outer_classname = "QueryProto"; +option java_package = "com.google.datastore.v1beta3"; + + +// The result of fetching an entity from the datastore. +message EntityResult { + // Specifies what data the 'entity' field contains. + // A `ResultType` is either implied (for example, in `LookupResponse.found` + // from `datastore.proto`, it is always `FULL`) or specified by context (for + // example, in message `QueryResultBatch`, field `entity_result_type` + // specifies a `ResultType` for all the values in field `entity_results`). + enum ResultType { + // Unspecified. + RESULT_TYPE_UNSPECIFIED = 0; + + // The entire entity. + FULL = 1; + + // A projected subset of properties. The entity may have no key. A property + // value may have meaning 18. + PROJECTION = 2; + + // Only the key. + KEY_ONLY = 3; + } + + // The resulting entity. + Entity entity = 1; + + // A cursor that points to the position after the result entity. + // Set only when the `EntityResult` is part of a `QueryResultBatch` message. + bytes cursor = 3; +} + +// A query. +message Query { + // The projection to return. Defaults to returning all properties. + repeated Projection projection = 2; + + // The kinds to query (if empty, returns entities of all kinds). + // Currently at most 1 kind may be specified. + repeated KindExpression kind = 3; + + // The filter to apply. + Filter filter = 4; + + // The order to apply to the query results (if empty, order is unspecified). + repeated PropertyOrder order = 5; + + // The properties to make distinct. The query results will contain the first + // result for each distinct combination of values for the given properties + // (if empty, all results are returned). + repeated PropertyReference distinct_on = 6; + + // A starting point for the query results. Query cursors are + // returned in query result batches. + bytes start_cursor = 7; + + // An ending point for the query results. Query cursors are + // returned in query result batches. + bytes end_cursor = 8; + + // The number of results to skip. Applies before limit, but after all other + // constraints. + // Must be >= 0. + int32 offset = 10; + + // The maximum number of results to return. Applies after all other + // constraints. + // Unspecified is interpreted as no limit. + // Must be >= 0. + google.protobuf.Int32Value limit = 12; +} + +// A representation of a kind. +message KindExpression { + // The name of the kind. + string name = 1; +} + +// A reference to a property relative to the kind expressions. +message PropertyReference { + // The name of the property. + string name = 2; +} + +// A representation of a property in a projection. +message Projection { + // The property to project. + PropertyReference property = 1; +} + +// The desired order for a specific property. +message PropertyOrder { + // Direction. + enum Direction { + // Unspecified. + DIRECTION_UNSPECIFIED = 0; + + // Ascending. + ASCENDING = 1; + + // Descending. + DESCENDING = 2; + } + + // The property to order by. + PropertyReference property = 1; + + // The direction to order by. Defaults to `ASCENDING`. + Direction direction = 2; +} + +// A holder for any type of filter. +message Filter { + // The type of filter. + oneof filter_type { + // A composite filter. + CompositeFilter composite_filter = 1; + + // A filter on a property. + PropertyFilter property_filter = 2; + } +} + +// A filter that merges the multiple other filters using the given operator. +message CompositeFilter { + // Composite filter operator. + enum Operator { + // Unspecified. This value must not be used. + OPERATOR_UNSPECIFIED = 0; + + // And. + AND = 1; + } + + // The operator for combining multiple filters. + Operator op = 1; + + // The list of filters to combine. + // Must contain at least one filter. + repeated Filter filters = 2; +} + +// A filter on a specific property. +message PropertyFilter { + // Property filter operator. + enum Operator { + // Unspecified. This value must not be used. + OPERATOR_UNSPECIFIED = 0; + + // Less than. + LESS_THAN = 1; + + // Less than or equal. + LESS_THAN_OR_EQUAL = 2; + + // Greater than. + GREATER_THAN = 3; + + // Greater than or equal. + GREATER_THAN_OR_EQUAL = 4; + + // Equal. + EQUAL = 5; + + // Has ancestor. + HAS_ANCESTOR = 11; + } + + // The property to filter by. + PropertyReference property = 1; + + // The operator to filter by. + Operator op = 2; + + // The value to compare the property to. + Value value = 3; +} + +// A GQL query. +message GqlQuery { + // A string of the format described + // [here](https://developers.google.com/datastore/docs/concepts/gql). + string query_string = 1; + + // When false, the query string must not contain any literals and instead + // must bind all values. For example, + // `SELECT * FROM Kind WHERE a = 'string literal'` is not allowed, while + // `SELECT * FROM Kind WHERE a = @value` is. + bool allow_literals = 2; + + // For each non-reserved named binding site in the query string, + // there must be a named parameter with that name, + // but not necessarily the inverse. + // Key must match regex `[A-Za-z_$][A-Za-z_$0-9]*`, must not match regex + // `__.*__`, and must not be `""`. + map named_bindings = 5; + + // Numbered binding site @1 references the first numbered parameter, + // effectively using 1-based indexing, rather than the usual 0. + // For each binding site numbered i in `query_string`, + // there must be an i-th numbered parameter. + // The inverse must also be true. + repeated GqlQueryParameter positional_bindings = 4; +} + +// A binding parameter for a GQL query. +message GqlQueryParameter { + // The type of parameter. + oneof parameter_type { + // Value. + Value value = 2; + + // Cursor. + bytes cursor = 3; + } +} + +// A batch of results produced by a query. +message QueryResultBatch { + // The possible values for the `more_results` field. + enum MoreResultsType { + // Unspecified. This value is never used. + MORE_RESULTS_TYPE_UNSPECIFIED = 0; + + // There are additional batches to fetch from this query. + NOT_FINISHED = 1; + + // The query is finished, but there may be more results after the limit. + MORE_RESULTS_AFTER_LIMIT = 2; + + // The query is finished, but there may be more results after the end cursor. + MORE_RESULTS_AFTER_CURSOR = 4; + + // The query has been exhausted. + NO_MORE_RESULTS = 3; + } + + // The number of results skipped, typically because of an offset. + int32 skipped_results = 6; + + // A cursor that points to the position after the last skipped result. + // Will be set when `skipped_results` != 0. + bytes skipped_cursor = 3; + + // The result type for every entity in `entity_results`. + EntityResult.ResultType entity_result_type = 1; + + // The results for this batch. + repeated EntityResult entity_results = 2; + + // A cursor that points to the position after the last result in the batch. + bytes end_cursor = 4; + + // The state of the query after the current batch. + MoreResultsType more_results = 5; +} diff --git a/proto/google/longrunning/README.md b/proto/google/longrunning/README.md new file mode 100644 index 000000000000..f9869e9c6eb5 --- /dev/null +++ b/proto/google/longrunning/README.md @@ -0,0 +1,4 @@ +# Google Long Running Operations API +This package contains the definition of an abstract interface that +manages long running operations with API services. See +[google.longrunning.Operations][] for details. diff --git a/proto/google/longrunning/operations.proto b/proto/google/longrunning/operations.proto new file mode 100644 index 000000000000..a358d0a38787 --- /dev/null +++ b/proto/google/longrunning/operations.proto @@ -0,0 +1,144 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.longrunning; + +import "google/api/annotations.proto"; +import "google/protobuf/any.proto"; +import "google/protobuf/empty.proto"; +import "google/rpc/status.proto"; + +option java_multiple_files = true; +option java_outer_classname = "OperationsProto"; +option java_package = "com.google.longrunning"; + + +// Manages long-running operations with an API service. +// +// When an API method normally takes long time to complete, it can be designed +// to return [Operation][google.longrunning.Operation] to the client, and the client can use this +// interface to receive the real response asynchronously by polling the +// operation resource, or using `google.watcher.v1.Watcher` interface to watch +// the response, or pass the operation resource to another API (such as Google +// Cloud Pub/Sub API) to receive the response. Any API service that returns +// long-running operations should implement the `Operations` interface so +// developers can have a consistent client experience. +service Operations { + // Gets the latest state of a long-running operation. Clients may use this + // method to poll the operation result at intervals as recommended by the API + // service. + rpc GetOperation(GetOperationRequest) returns (Operation) { + option (google.api.http) = { get: "/v1/{name=operations/**}" }; + } + + // Lists operations that match the specified filter in the request. If the + // server doesn't support this method, it returns + // `google.rpc.Code.UNIMPLEMENTED`. + rpc ListOperations(ListOperationsRequest) returns (ListOperationsResponse) { + option (google.api.http) = { get: "/v1/{name=operations}" }; + } + + // Starts asynchronous cancellation on a long-running operation. The server + // makes a best effort to cancel the operation, but success is not + // guaranteed. If the server doesn't support this method, it returns + // `google.rpc.Code.UNIMPLEMENTED`. Clients may use + // [Operations.GetOperation] or other methods to check whether the + // cancellation succeeded or the operation completed despite cancellation. + rpc CancelOperation(CancelOperationRequest) returns (google.protobuf.Empty) { + option (google.api.http) = { post: "/v1/{name=operations/**}:cancel" body: "*" }; + } + + // Deletes a long-running operation. It indicates the client is no longer + // interested in the operation result. It does not cancel the operation. + rpc DeleteOperation(DeleteOperationRequest) returns (google.protobuf.Empty) { + option (google.api.http) = { delete: "/v1/{name=operations/**}" }; + } +} + +// This resource represents a long-running operation that is the result of a +// network API call. +message Operation { + // The name of the operation resource, which is only unique within the same + // service that originally returns it. + string name = 1; + + // Some service-specific metadata associated with the operation. It typically + // contains progress information and common metadata such as create time. + // Some services may not provide such metadata. Any method that returns a + // long-running operation should document the metadata type, if any. + google.protobuf.Any metadata = 2; + + // If the value is false, it means the operation is still in progress. + // If true, the operation is completed and the `result` is available. + bool done = 3; + + oneof result { + // The error result of the operation in case of failure. + google.rpc.Status error = 4; + + // The normal response of the operation in case of success. If the original + // method returns no data on success, such as `Delete`, the response will be + // `google.protobuf.Empty`. If the original method is standard + // `Get`/`Create`/`Update`, the response should be the resource. For other + // methods, the response should have the type `XxxResponse`, where `Xxx` + // is the original method name. For example, if the original method name + // is `TakeSnapshot()`, the inferred response type will be + // `TakeSnapshotResponse`. + google.protobuf.Any response = 5; + } +} + +// The request message for [Operations.GetOperation][google.longrunning.Operations.GetOperation]. +message GetOperationRequest { + // The name of the operation resource. + string name = 1; +} + +// The request message for [Operations.ListOperations][google.longrunning.Operations.ListOperations]. +message ListOperationsRequest { + // The name of the operation collection. + string name = 4; + + // The standard List filter. + string filter = 1; + + // The standard List page size. + int32 page_size = 2; + + // The standard List page token. + string page_token = 3; +} + +// The response message for [Operations.ListOperations][google.longrunning.Operations.ListOperations]. +message ListOperationsResponse { + // A list of operations that match the specified filter in the request. + repeated Operation operations = 1; + + // The standard List next-page token. + string next_page_token = 2; +} + +// The request message for [Operations.CancelOperation][google.longrunning.Operations.CancelOperation]. +message CancelOperationRequest { + // The name of the operation resource to be cancelled. + string name = 1; +} + +// The request message for [Operations.DeleteOperation][google.longrunning.Operations.DeleteOperation]. +message DeleteOperationRequest { + // The name of the operation resource to be deleted. + string name = 1; +} diff --git a/proto/google/protobuf/any.proto b/proto/google/protobuf/any.proto new file mode 100644 index 000000000000..423699beb8e0 --- /dev/null +++ b/proto/google/protobuf/any.proto @@ -0,0 +1,98 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; + +package google.protobuf; + +option java_generate_equals_and_hash = true; +option java_multiple_files = true; +option java_outer_classname = "AnyProto"; +option java_package = "com.google.protobuf"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option objc_class_prefix = "GPB"; + + +// `Any` contains an arbitrary serialized message along with a URL +// that describes the type of the serialized message. +// +// JSON +// ==== +// The JSON representation of an `Any` value uses the regular +// representation of the deserialized, embedded message, with an +// additional field `@type` which contains the type URL. Example: +// +// package google.profile; +// message Person { +// string first_name = 1; +// string last_name = 2; +// } +// +// { +// "@type": "type.googleapis.com/google.profile.Person", +// "firstName": , +// "lastName": +// } +// +// If the embedded message type is well-known and has a custom JSON +// representation, that representation will be embedded adding a field +// `value` which holds the custom JSON in addition to the the `@type` +// field. Example (for message [google.protobuf.Duration][google.protobuf.Duration]): +// +// { +// "@type": "type.googleapis.com/google.protobuf.Duration", +// "value": "1.212s" +// } +// +message Any { + // A URL/resource name whose content describes the type of the + // serialized message. + // + // For URLs which use the schema `http`, `https`, or no schema, the + // following restrictions and interpretations apply: + // + // * If no schema is provided, `https` is assumed. + // * The last segment of the URL's path must represent the fully + // qualified name of the type (as in `path/google.protobuf.Duration`). + // * An HTTP GET on the URL must yield a [google.protobuf.Type][google.protobuf.Type] + // value in binary format, or produce an error. + // * Applications are allowed to cache lookup results based on the + // URL, or have them precompiled into a binary to avoid any + // lookup. Therefore, binary compatibility needs to be preserved + // on changes to types. (Use versioned type names to manage + // breaking changes.) + // + // Schemas other than `http`, `https` (or the empty schema) might be + // used with implementation specific semantics. + // + string type_url = 1; + + // Must be valid serialized data of the above specified type. + bytes value = 2; +} diff --git a/proto/google/protobuf/any_test.proto b/proto/google/protobuf/any_test.proto new file mode 100644 index 000000000000..0c5b30ba3e4a --- /dev/null +++ b/proto/google/protobuf/any_test.proto @@ -0,0 +1,41 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package protobuf_unittest; + +import "google/protobuf/any.proto"; + +message TestAny { + int32 int32_value = 1; + google.protobuf.Any any_value = 2; + repeated google.protobuf.Any repeated_any_value = 3; +} diff --git a/proto/google/protobuf/api.proto b/proto/google/protobuf/api.proto new file mode 100644 index 000000000000..597a64973017 --- /dev/null +++ b/proto/google/protobuf/api.proto @@ -0,0 +1,201 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; + +package google.protobuf; + +import "google/protobuf/source_context.proto"; +import "google/protobuf/type.proto"; + +option java_package = "com.google.protobuf"; +option java_outer_classname = "ApiProto"; +option java_multiple_files = true; +option java_generate_equals_and_hash = true; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option objc_class_prefix = "GPB"; + +// Api is a light-weight descriptor for a protocol buffer service. +message Api { + + // The fully qualified name of this api, including package name + // followed by the api's simple name. + string name = 1; + + // The methods of this api, in unspecified order. + repeated Method methods = 2; + + // Any metadata attached to the API. + repeated Option options = 3; + + // A version string for this api. If specified, must have the form + // `major-version.minor-version`, as in `1.10`. If the minor version + // is omitted, it defaults to zero. If the entire version field is + // empty, the major version is derived from the package name, as + // outlined below. If the field is not empty, the version in the + // package name will be verified to be consistent with what is + // provided here. + // + // The versioning schema uses [semantic + // versioning](http://semver.org) where the major version number + // indicates a breaking change and the minor version an additive, + // non-breaking change. Both version numbers are signals to users + // what to expect from different versions, and should be carefully + // chosen based on the product plan. + // + // The major version is also reflected in the package name of the + // API, which must end in `v`, as in + // `google.feature.v1`. For major versions 0 and 1, the suffix can + // be omitted. Zero major versions must only be used for + // experimental, none-GA apis. + // + string version = 4; + + // Source context for the protocol buffer service represented by this + // message. + SourceContext source_context = 5; + + // Included APIs. See [Mixin][]. + repeated Mixin mixins = 6; + + // The source syntax of the service. + Syntax syntax = 7; +} + +// Method represents a method of an api. +message Method { + + // The simple name of this method. + string name = 1; + + // A URL of the input message type. + string request_type_url = 2; + + // If true, the request is streamed. + bool request_streaming = 3; + + // The URL of the output message type. + string response_type_url = 4; + + // If true, the response is streamed. + bool response_streaming = 5; + + // Any metadata attached to the method. + repeated Option options = 6; + + // The source syntax of this method. + Syntax syntax = 7; +} + +// Declares an API to be included in this API. The including API must +// redeclare all the methods from the included API, but documentation +// and options are inherited as follows: +// +// - If after comment and whitespace stripping, the documentation +// string of the redeclared method is empty, it will be inherited +// from the original method. +// +// - Each annotation belonging to the service config (http, +// visibility) which is not set in the redeclared method will be +// inherited. +// +// - If an http annotation is inherited, the path pattern will be +// modified as follows. Any version prefix will be replaced by the +// version of the including API plus the [root][] path if specified. +// +// Example of a simple mixin: +// +// package google.acl.v1; +// service AccessControl { +// // Get the underlying ACL object. +// rpc GetAcl(GetAclRequest) returns (Acl) { +// option (google.api.http).get = "/v1/{resource=**}:getAcl"; +// } +// } +// +// package google.storage.v2; +// service Storage { +// // (-- see AccessControl.GetAcl --) +// rpc GetAcl(GetAclRequest) returns (Acl); +// +// // Get a data record. +// rpc GetData(GetDataRequest) returns (Data) { +// option (google.api.http).get = "/v2/{resource=**}"; +// } +// } +// +// Example of a mixin configuration: +// +// apis: +// - name: google.storage.v2.Storage +// mixins: +// - name: google.acl.v1.AccessControl +// +// The mixin construct implies that all methods in `AccessControl` are +// also declared with same name and request/response types in +// `Storage`. A documentation generator or annotation processor will +// see the effective `Storage.GetAcl` method after inherting +// documentation and annotations as follows: +// +// service Storage { +// // Get the underlying ACL object. +// rpc GetAcl(GetAclRequest) returns (Acl) { +// option (google.api.http).get = "/v2/{resource=**}:getAcl"; +// } +// ... +// } +// +// Note how the version in the path pattern changed from `v1` to `v2`. +// +// If the `root` field in the mixin is specified, it should be a +// relative path under which inherited HTTP paths are placed. Example: +// +// apis: +// - name: google.storage.v2.Storage +// mixins: +// - name: google.acl.v1.AccessControl +// root: acls +// +// This implies the following inherited HTTP annotation: +// +// service Storage { +// // Get the underlying ACL object. +// rpc GetAcl(GetAclRequest) returns (Acl) { +// option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; +// } +// ... +// } +message Mixin { + // The fully qualified name of the API which is included. + string name = 1; + + // If non-empty specifies a path under which inherited HTTP paths + // are rooted. + string root = 2; +} diff --git a/proto/google/protobuf/arena_nc_test.py b/proto/google/protobuf/arena_nc_test.py new file mode 100644 index 000000000000..87a69b2afd76 --- /dev/null +++ b/proto/google/protobuf/arena_nc_test.py @@ -0,0 +1,61 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Negative compilation unit tests for arena API.""" + +import unittest + +from google3.testing.pybase import fake_target_util +import unittest + + +class ArenaNcTest(unittest.TestCase): + + def testCompilerErrors(self): + """Runs a list of tests to verify compiler error messages.""" + + # Defines a list of test specs, where each element is a tuple + # (test name, list of regexes for matching the compiler errors). + test_specs = [ + ('ARENA_PRIVATE_CONSTRUCTOR', + [r'calling a protected constructor']), + ('SANITY', None)] + + fake_target_util.AssertCcCompilerErrors( + self, # The current test case. + 'google3/google/protobuf/arena_nc', # The fake target file. + 'arena_nc.o', # The sub-target to build. + test_specs # List of test specifications. + ) + +if __name__ == '__main__': + unittest.main() diff --git a/proto/google/protobuf/descriptor.proto b/proto/google/protobuf/descriptor.proto new file mode 100644 index 000000000000..8f90a956cf92 --- /dev/null +++ b/proto/google/protobuf/descriptor.proto @@ -0,0 +1,774 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + + +syntax = "proto2"; + +package google.protobuf; +option go_package = "descriptor"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; +// Re-enable this once the tools have picked up the csharp_namespace option. +// option csharp_namespace = "Google.ProtocolBuffers.DescriptorProtos"; +option objc_class_prefix = "GPB"; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + // Indexes of the public imported files in the dependency list above. + repeated int32 public_dependency = 10; + // Indexes of the weak imported files in the dependency list. + // For Google-internal migration only. Do not use. + repeated int32 weak_dependency = 11; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field without harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; + + // The syntax of the proto file. + // The supported values are "proto2" and "proto3". + optional string syntax = 12; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; + optional int32 end = 2; + } + repeated ExtensionRange extension_range = 5; + + repeated OneofDescriptorProto oneof_decl = 8; + + optional MessageOptions options = 7; + + // Range of reserved tag numbers. Reserved tag numbers may not be used by + // fields or extension ranges in the same message. Reserved ranges may + // not overlap. + message ReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. + } + repeated ReservedRange reserved_range = 9; + // Reserved field names, which may not be used by fields in the same message. + // A given name may only be reserved once. + repeated string reserved_name = 10; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + // negative values are likely. + TYPE_INT64 = 3; + TYPE_UINT64 = 4; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + // negative values are likely. + TYPE_INT32 = 5; + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + TYPE_GROUP = 10; // Tag-delimited aggregate. + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + }; + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + // TODO(sanjay): Should we add LABEL_MAP? + }; + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + // TODO(kenton): Base-64 encode? + optional string default_value = 7; + + // If set, gives the index of a oneof in the containing type's oneof_decl + // list. This field is a member of that oneof. + optional int32 oneof_index = 9; + + optional FieldOptions options = 8; +} + +// Describes a oneof. +message OneofDescriptorProto { + optional string name = 1; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; + + // Identifies if client streams multiple client messages + optional bool client_streaming = 5 [default=false]; + // Identifies if server streams multiple server messages + optional bool server_streaming = 6 [default=false]; +} + + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail protobuf-global-extension-registry@google.com +// to reserve extension numbers. Simply provide your project name (e.g. +// Objective-C plugin) and your project website (if available) -- there's no +// need to explain how you intend to use them. Usually you only need one +// extension number. You can declare multiple options with only one extension +// number by putting them in a sub-message. See the Custom Options section of +// the docs for examples: +// https://developers.google.com/protocol-buffers/docs/proto#options +// If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + + // If set, all the classes from the .proto file are wrapped in a single + // outer class with the given name. This applies to both Proto1 + // (equivalent to the old "--one_java_file" option) and Proto2 (where + // a .proto always translates to a single class, but you may want to + // explicitly choose the class name). + optional string java_outer_classname = 8; + + // If set true, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the outer class + // named by java_outer_classname. However, the outer class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [default=false]; + + // If set true, then the Java code generator will generate equals() and + // hashCode() methods for all messages defined in the .proto file. + // This increases generated code size, potentially substantially for large + // protos, which may harm a memory-constrained application. + // - In the full runtime this is a speed optimization, as the + // AbstractMessage base class includes reflection-based implementations of + // these methods. + // - In the lite runtime, setting this option changes the semantics of + // equals() and hashCode() to more closely match those of the full runtime; + // the generated methods compute their results based on field values rather + // than object identity. (Implementations should not assume that hashcodes + // will be consistent across runtimes or versions of the protocol compiler.) + optional bool java_generate_equals_and_hash = 20 [default=false]; + + // If set true, then the Java2 code generator will generate code that + // throws an exception whenever an attempt is made to assign a non-UTF-8 + // byte sequence to a string field. + // Message reflection will do the same. + // However, an extension field still accepts non-UTF-8 byte sequences. + // This option has no effect on when used with the lite runtime. + optional bool java_string_check_utf8 = 27 [default=false]; + + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default=SPEED]; + + // Sets the Go package where structs generated from this .proto will be + // placed. If omitted, the Go package will be derived from the following: + // - The basename of the package import path, if provided. + // - Otherwise, the package statement in the .proto file, if present. + // - Otherwise, the basename of the .proto file, without extension. + optional string go_package = 11; + + + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of google.protobuf. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default=false]; + optional bool java_generic_services = 17 [default=false]; + optional bool py_generic_services = 18 [default=false]; + + // Is this file deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for everything in the file, or it will be completely ignored; in the very + // least, this is a formalization for deprecating files. + optional bool deprecated = 23 [default=false]; + + // Enables the use of arenas for the proto messages in this file. This applies + // only to generated classes for C++. + optional bool cc_enable_arenas = 31 [default=false]; + + + // Sets the objective c class prefix which is prepended to all objective c + // generated classes from this .proto. There is no default. + optional string objc_class_prefix = 36; + + // Namespace for generated classes; defaults to the package. + optional string csharp_namespace = 37; + + // Whether the nano proto compiler should generate in the deprecated non-nano + // suffixed package. + optional bool javanano_use_deprecated_package = 38; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default=false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default=false]; + + // Is this message deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the message, or it will be completely ignored; in the very least, + // this is a formalization for deprecating messages. + optional bool deprecated = 3 [default=false]; + + // Whether the message is an automatically generated map entry type for the + // maps field. + // + // For maps fields: + // map map_field = 1; + // The parsed descriptor looks like: + // message MapFieldEntry { + // option map_entry = true; + // optional KeyType key = 1; + // optional ValueType value = 2; + // } + // repeated MapFieldEntry map_field = 1; + // + // Implementations may choose not to generate the map_entry=true message, but + // use a native map in the target language to hold the keys and values. + // The reflection APIs in such implementions still need to work as + // if the field is a repeated message field. + // + // NOTE: Do not set the option in .proto files. Always use the maps syntax + // instead. The option should only be implicitly set by the proto compiler + // parser. + optional bool map_entry = 7; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + optional CType ctype = 1 [default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. In proto3, only explicit setting it to + // false will avoid using packed encoding. + optional bool packed = 2; + + + // The jstype option determines the JavaScript type used for values of the + // field. The option is permitted only for 64 bit integral and fixed types + // (int64, uint64, sint64, fixed64, sfixed64). By default these types are + // represented as JavaScript strings. This avoids loss of precision that can + // happen when a large value is converted to a floating point JavaScript + // numbers. Specifying JS_NUMBER for the jstype causes the generated + // JavaScript code to use the JavaScript "number" type instead of strings. + // This option is an enum to permit additional types to be added, + // e.g. goog.math.Integer. + optional JSType jstype = 6 [default = JS_NORMAL]; + enum JSType { + // Use the default type. + JS_NORMAL = 0; + + // Use JavaScript strings. + JS_STRING = 1; + + // Use JavaScript numbers. + JS_NUMBER = 2; + } + + // Should this field be parsed lazily? Lazy applies only to message-type + // fields. It means that when the outer message is initially parsed, the + // inner message's contents will not be parsed but instead stored in encoded + // form. The inner message will actually be parsed when it is first accessed. + // + // This is only a hint. Implementations are free to choose whether to use + // eager or lazy parsing regardless of the value of this option. However, + // setting this option true suggests that the protocol author believes that + // using lazy parsing on this field is worth the additional bookkeeping + // overhead typically needed to implement it. + // + // This option does not affect the public interface of any generated code; + // all method signatures remain the same. Furthermore, thread-safety of the + // interface is not affected by this option; const methods remain safe to + // call from multiple threads concurrently, while non-const methods continue + // to require exclusive access. + // + // + // Note that implementations may choose not to check required fields within + // a lazy sub-message. That is, calling IsInitialized() on the outher message + // may return true even if the inner message has missing required fields. + // This is necessary because otherwise the inner message would have to be + // parsed in order to perform the check, defeating the purpose of lazy + // parsing. An implementation which chooses not to check required fields + // must be consistent about it. That is, for any particular sub-message, the + // implementation must either *always* check its required fields, or *never* + // check its required fields, regardless of whether or not the message has + // been parsed. + optional bool lazy = 5 [default=false]; + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default=false]; + + // For Google-internal migration only. Do not use. + optional bool weak = 10 [default=false]; + + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // Set this option to true to allow mapping different tag names to the same + // value. + optional bool allow_alias = 2; + + // Is this enum deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum, or it will be completely ignored; in the very least, this + // is a formalization for deprecating enums. + optional bool deprecated = 3 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // Is this enum value deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum value, or it will be completely ignored; in the very least, + // this is a formalization for deprecating enum values. + optional bool deprecated = 1 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this service deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the service, or it will be completely ignored; in the very least, + // this is a formalization for deprecating services. + optional bool deprecated = 33 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this method deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the method, or it will be completely ignored; in the very least, + // this is a formalization for deprecating methods. + optional bool deprecated = 33 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + // "foo.(bar.baz).qux". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed=true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed=true]; + + // If this SourceCodeInfo represents a complete declaration, these are any + // comments appearing before and after the declaration which appear to be + // attached to the declaration. + // + // A series of line comments appearing on consecutive lines, with no other + // tokens appearing on those lines, will be treated as a single comment. + // + // leading_detached_comments will keep paragraphs of comments that appear + // before (but not connected to) the current element. Each paragraph, + // separated by empty lines, will be one comment element in the repeated + // field. + // + // Only the comment content is provided; comment markers (e.g. //) are + // stripped out. For block comments, leading whitespace and an asterisk + // will be stripped from the beginning of each line other than the first. + // Newlines are included in the output. + // + // Examples: + // + // optional int32 foo = 1; // Comment attached to foo. + // // Comment attached to bar. + // optional int32 bar = 2; + // + // optional string baz = 3; + // // Comment attached to baz. + // // Another line attached to baz. + // + // // Comment attached to qux. + // // + // // Another line attached to qux. + // optional double qux = 4; + // + // // Detached comment for corge. This is not leading or trailing comments + // // to qux or corge because there are blank lines separating it from + // // both. + // + // // Detached comment for corge paragraph 2. + // + // optional string corge = 5; + // /* Block comment attached + // * to corge. Leading asterisks + // * will be removed. */ + // /* Block comment attached to + // * grault. */ + // optional int32 grault = 6; + // + // // ignored detached comments. + optional string leading_comments = 3; + optional string trailing_comments = 4; + repeated string leading_detached_comments = 6; + } +} diff --git a/proto/google/protobuf/duration.proto b/proto/google/protobuf/duration.proto new file mode 100644 index 000000000000..7f172aa6ef6b --- /dev/null +++ b/proto/google/protobuf/duration.proto @@ -0,0 +1,95 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; + +package google.protobuf; + +option java_generate_equals_and_hash = true; +option java_multiple_files = true; +option java_outer_classname = "DurationProto"; +option java_package = "com.google.protobuf"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option objc_class_prefix = "GPB"; + +// A Duration represents a signed, fixed-length span of time represented +// as a count of seconds and fractions of seconds at nanosecond +// resolution. It is independent of any calendar and concepts like "day" +// or "month". It is related to Timestamp in that the difference between +// two Timestamp values is a Duration and it can be added or subtracted +// from a Timestamp. Range is approximately +-10,000 years. +// +// Example 1: Compute Duration from two Timestamps in pseudo code. +// +// Timestamp start = ...; +// Timestamp end = ...; +// Duration duration = ...; +// +// duration.seconds = end.seconds - start.seconds; +// duration.nanos = end.nanos - start.nanos; +// +// if (duration.seconds < 0 && duration.nanos > 0) { +// duration.seconds += 1; +// duration.nanos -= 1000000000; +// } else if (durations.seconds > 0 && duration.nanos < 0) { +// duration.seconds -= 1; +// duration.nanos += 1000000000; +// } +// +// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. +// +// Timestamp start = ...; +// Duration duration = ...; +// Timestamp end = ...; +// +// end.seconds = start.seconds + duration.seconds; +// end.nanos = start.nanos + duration.nanos; +// +// if (end.nanos < 0) { +// end.seconds -= 1; +// end.nanos += 1000000000; +// } else if (end.nanos >= 1000000000) { +// end.seconds += 1; +// end.nanos -= 1000000000; +// } +// +message Duration { + + // Signed seconds of the span of time. Must be from -315,576,000,000 + // to +315,576,000,000 inclusive. + int64 seconds = 1; + + // Signed fractions of a second at nanosecond resolution of the span + // of time. Durations less than one second are represented with a 0 + // `seconds` field and a positive or negative `nanos` field. For durations + // of one second or more, a non-zero value for the `nanos` field must be + // of the same sign as the `seconds` field. Must be from -999,999,999 + // to +999,999,999 inclusive. + int32 nanos = 2; +} diff --git a/proto/google/protobuf/empty.proto b/proto/google/protobuf/empty.proto new file mode 100644 index 000000000000..9dddc6c5a4e2 --- /dev/null +++ b/proto/google/protobuf/empty.proto @@ -0,0 +1,50 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; + +package google.protobuf; + +option java_multiple_files = true; +option java_outer_classname = "EmptyProto"; +option java_package = "com.google.protobuf"; +option java_generate_equals_and_hash = true; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option objc_class_prefix = "GPB"; + +// A generic empty message that you can re-use to avoid defining duplicated +// empty messages in your APIs. A typical example is to use it as the request +// or the response type of an API method. For instance: +// +// service Foo { +// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); +// } +// +// The JSON representation for `Empty` is empty JSON object `{}`. +message Empty {} diff --git a/proto/google/protobuf/field_mask.proto b/proto/google/protobuf/field_mask.proto new file mode 100644 index 000000000000..8b21c692d10a --- /dev/null +++ b/proto/google/protobuf/field_mask.proto @@ -0,0 +1,167 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; + +package google.protobuf; + +option java_generate_equals_and_hash = true; +option java_multiple_files = true; +option java_outer_classname = "FieldMaskProto"; +option java_package = "com.google.protobuf"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option objc_class_prefix = "GPB"; + +// `FieldMask` represents a set of symbolic field paths, for example: +// +// paths: "f.a" +// paths: "f.b.d" +// +// Here `f` represents a field in some root message, `a` and `b` +// fields in the message found in `f`, and `d` a field found in the +// message in `f.b`. +// +// Field masks are used to specify a subset of fields that should be +// returned by a get operation or modified by an update operation. +// Field masks also have a custom JSON encoding (see below). +// +// # Field Masks in Projections +// +// When used in the context of a projection, a response message or +// sub-message is filtered by the API to only contain those fields as +// specified in the mask. For example, if the mask in the previous +// example is applied to a response message as follows: +// +// f { +// a : 22 +// b { +// d : 1 +// x : 2 +// } +// y : 13 +// } +// z: 8 +// +// The result will not contain specific values for fields x,y and z +// (there value will be set to the default, and omitted in proto text +// output): +// +// +// f { +// a : 22 +// b { +// d : 1 +// } +// } +// +// A repeated field is not allowed except at the last position of a +// field mask. +// +// If a FieldMask object is not present in a get operation, the +// operation applies to all fields (as if a FieldMask of all fields +// had been specified). +// +// Note that a field mask does not necessarily applies to the +// top-level response message. In case of a REST get operation, the +// field mask applies directly to the response, but in case of a REST +// list operation, the mask instead applies to each individual message +// in the returned resource list. In case of a REST custom method, +// other definitions may be used. Where the mask applies will be +// clearly documented together with its declaration in the API. In +// any case, the effect on the returned resource/resources is required +// behavior for APIs. +// +// # Field Masks in Update Operations +// +// A field mask in update operations specifies which fields of the +// targeted resource are going to be updated. The API is required +// to only change the values of the fields as specified in the mask +// and leave the others untouched. If a resource is passed in to +// describe the updated values, the API ignores the values of all +// fields not covered by the mask. +// +// In order to reset a field's value to the default, the field must +// be in the mask and set to the default value in the provided resource. +// Hence, in order to reset all fields of a resource, provide a default +// instance of the resource and set all fields in the mask, or do +// not provide a mask as described below. +// +// If a field mask is not present on update, the operation applies to +// all fields (as if a field mask of all fields has been specified). +// Note that in the presence of schema evolution, this may mean that +// fields the client does not know and has therefore not filled into +// the request will be reset to their default. If this is unwanted +// behavior, a specific service may require a client to always specify +// a field mask, producing an error if not. +// +// As with get operations, the location of the resource which +// describes the updated values in the request message depends on the +// operation kind. In any case, the effect of the field mask is +// required to be honored by the API. +// +// ## Considerations for HTTP REST +// +// The HTTP kind of an update operation which uses a field mask must +// be set to PATCH instead of PUT in order to satisfy HTTP semantics +// (PUT must only be used for full updates). +// +// # JSON Encoding of Field Masks +// +// In JSON, a field mask is encoded as a single string where paths are +// separated by a comma. Fields name in each path are converted +// to/from lower-camel naming conventions. +// +// As an example, consider the following message declarations: +// +// message Profile { +// User user = 1; +// Photo photo = 2; +// } +// message User { +// string display_name = 1; +// string address = 2; +// } +// +// In proto a field mask for `Profile` may look as such: +// +// mask { +// paths: "user.display_name" +// paths: "photo" +// } +// +// In JSON, the same mask is represented as below: +// +// { +// mask: "user.displayName,photo" +// } +// +message FieldMask { + // The set of field mask paths. + repeated string paths = 1; +} diff --git a/proto/google/protobuf/source_context.proto b/proto/google/protobuf/source_context.proto new file mode 100644 index 000000000000..e9a27d654b5e --- /dev/null +++ b/proto/google/protobuf/source_context.proto @@ -0,0 +1,47 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; + +package google.protobuf; + +option java_multiple_files = true; +option java_outer_classname = "SourceContextProto"; +option java_package = "com.google.protobuf"; +option java_generate_equals_and_hash = true; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option objc_class_prefix = "GPB"; + +// `SourceContext` represents information about the source of a +// protobuf element, like the file in which it is defined. +message SourceContext { + // The path-qualified name of the .proto file that contained the associated + // protobuf element. For example: `"google/protobuf/source.proto"`. + string file_name = 1; +} diff --git a/proto/google/protobuf/struct.proto b/proto/google/protobuf/struct.proto new file mode 100644 index 000000000000..b3e9e69954e2 --- /dev/null +++ b/proto/google/protobuf/struct.proto @@ -0,0 +1,94 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; + +package google.protobuf; + +option java_generate_equals_and_hash = true; +option java_multiple_files = true; +option java_outer_classname = "StructProto"; +option java_package = "com.google.protobuf"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option objc_class_prefix = "GPB"; + + +// `Struct` represents a structured data value, consisting of fields +// which map to dynamically typed values. In some languages, `Struct` +// might be supported by a native representation. For example, in +// scripting languages like JS a struct is represented as an +// object. The details of that representation are described together +// with the proto support for the language. +// +// The JSON representation for `Struct` is JSON object. +message Struct { + // Map of dynamically typed values. + map fields = 1; +} + +// `Value` represents a dynamically typed value which can be either +// null, a number, a string, a boolean, a recursive struct value, or a +// list of values. A producer of value is expected to set one of that +// variants, absence of any variant indicates an error. +// +// The JSON representation for `Value` is JSON value. +message Value { + // The kind of value. + oneof kind { + // Represents a null value. + NullValue null_value = 1; + // Represents a double value. + double number_value = 2; + // Represents a string value. + string string_value = 3; + // Represents a boolean value. + bool bool_value = 4; + // Represents a structured value. + Struct struct_value = 5; + // Represents a repeated `Value`. + ListValue list_value = 6; + } +} + +// `NullValue` is a singleton enumeration to represent the null value for the +// `Value` type union. +// +// The JSON representation for `NullValue` is JSON `null`. +enum NullValue { + // Null value. + NULL_VALUE = 0; +} + +// `ListValue` is a wrapper around a repeated field of values. +// +// The JSON representation for `ListValue` is JSON array. +message ListValue { + // Repeated field of dynamically typed values. + repeated Value values = 1; +} diff --git a/proto/google/protobuf/timestamp.proto b/proto/google/protobuf/timestamp.proto new file mode 100644 index 000000000000..06b60e6f305d --- /dev/null +++ b/proto/google/protobuf/timestamp.proto @@ -0,0 +1,107 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; + +package google.protobuf; + +option java_generate_equals_and_hash = true; +option java_multiple_files = true; +option java_outer_classname = "TimestampProto"; +option java_package = "com.google.protobuf"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option objc_class_prefix = "GPB"; + +// A Timestamp represents a point in time independent of any time zone +// or calendar, represented as seconds and fractions of seconds at +// nanosecond resolution in UTC Epoch time. It is encoded using the +// Proleptic Gregorian Calendar which extends the Gregorian calendar +// backwards to year one. It is encoded assuming all minutes are 60 +// seconds long, i.e. leap seconds are "smeared" so that no leap second +// table is needed for interpretation. Range is from +// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. +// By restricting to that range, we ensure that we can convert to +// and from RFC 3339 date strings. +// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). +// +// Example 1: Compute Timestamp from POSIX `time()`. +// +// Timestamp timestamp; +// timestamp.set_seconds(time(NULL)); +// timestamp.set_nanos(0); +// +// Example 2: Compute Timestamp from POSIX `gettimeofday()`. +// +// struct timeval tv; +// gettimeofday(&tv, NULL); +// +// Timestamp timestamp; +// timestamp.set_seconds(tv.tv_sec); +// timestamp.set_nanos(tv.tv_usec * 1000); +// +// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. +// +// FILETIME ft; +// GetSystemTimeAsFileTime(&ft); +// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; +// +// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z +// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. +// Timestamp timestamp; +// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); +// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); +// +// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. +// +// long millis = System.currentTimeMillis(); +// +// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) +// .setNanos((int) ((millis % 1000) * 1000000)).build(); +// +// +// Example 5: Compute Timestamp from current time in Python. +// +// now = time.time() +// seconds = int(now) +// nanos = int((now - seconds) * 10**9) +// timestamp = Timestamp(seconds=seconds, nanos=nanos) +// +message Timestamp { + + // Represents seconds of UTC time since Unix epoch + // 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to + // 9999-12-31T23:59:59Z inclusive. + int64 seconds = 1; + + // Non-negative fractions of a second at nanosecond resolution. Negative + // second values with fractions must still have non-negative nanos values + // that count forward in time. Must be from 0 to 999,999,999 + // inclusive. + int32 nanos = 2; +} diff --git a/proto/google/protobuf/type.proto b/proto/google/protobuf/type.proto new file mode 100644 index 000000000000..4df95762c2a7 --- /dev/null +++ b/proto/google/protobuf/type.proto @@ -0,0 +1,176 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +syntax = "proto3"; + +package google.protobuf; + +import "google/protobuf/any.proto"; +import "google/protobuf/source_context.proto"; + +option java_package = "com.google.protobuf"; +option java_outer_classname = "TypeProto"; +option java_multiple_files = true; +option java_generate_equals_and_hash = true; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option objc_class_prefix = "GPB"; + +// A light-weight descriptor for a proto message type. +message Type { + // The fully qualified message name. + string name = 1; + // The list of fields. + repeated Field fields = 2; + // The list of oneof definitions. + repeated string oneofs = 3; // The list of oneofs declared in this Type + // The proto options. + repeated Option options = 4; + // The source context. + SourceContext source_context = 5; + // The source syntax. + Syntax syntax = 6; +} + +// Field represents a single field of a message type. +message Field { + // Kind represents a basic field type. + enum Kind { + // Field type unknown. + TYPE_UNKNOWN = 0; + // Field type double. + TYPE_DOUBLE = 1; + // Field type float. + TYPE_FLOAT = 2; + // Field type int64. + TYPE_INT64 = 3; + // Field type uint64. + TYPE_UINT64 = 4; + // Field type int32. + TYPE_INT32 = 5; + // Field type fixed64. + TYPE_FIXED64 = 6; + // Field type fixed32. + TYPE_FIXED32 = 7; + // Field type bool. + TYPE_BOOL = 8; + // Field type string. + TYPE_STRING = 9; + // Field type group (deprecated proto2 type) + TYPE_GROUP = 10; + // Field type message. + TYPE_MESSAGE = 11; + // Field type bytes. + TYPE_BYTES = 12; + // Field type uint32. + TYPE_UINT32 = 13; + // Field type enum. + TYPE_ENUM = 14; + // Field type sfixed32. + TYPE_SFIXED32 = 15; + // Field type sfixed64. + TYPE_SFIXED64 = 16; + // Field type sint32. + TYPE_SINT32 = 17; + // Field type sint64. + TYPE_SINT64 = 18; + }; + + // Cardinality represents whether a field is optional, required, or + // repeated. + enum Cardinality { + // The field cardinality is unknown. Typically an error condition. + CARDINALITY_UNKNOWN = 0; + // For optional fields. + CARDINALITY_OPTIONAL = 1; + // For required fields. Not used for proto3. + CARDINALITY_REQUIRED = 2; + // For repeated fields. + CARDINALITY_REPEATED = 3; + }; + + // The field kind. + Kind kind = 1; + // The field cardinality, i.e. optional/required/repeated. + Cardinality cardinality = 2; + // The proto field number. + int32 number = 3; + // The field name. + string name = 4; + // The type URL (without the scheme) when the type is MESSAGE or ENUM, + // such as `type.googleapis.com/google.protobuf.Empty`. + string type_url = 6; + // Index in Type.oneofs. Starts at 1. Zero means no oneof mapping. + int32 oneof_index = 7; + // Whether to use alternative packed wire representation. + bool packed = 8; + // The proto options. + repeated Option options = 9; + // The JSON name for this field. + string json_name = 10; +} + +// Enum type definition. +message Enum { + // Enum type name. + string name = 1; + // Enum value definitions. + repeated EnumValue enumvalue = 2; + // Proto options for the enum type. + repeated Option options = 3; + // The source context. + SourceContext source_context = 4; + // The source syntax. + Syntax syntax = 5; +} + +// Enum value definition. +message EnumValue { + // Enum value name. + string name = 1; + // Enum value number. + int32 number = 2; + // Proto options for the enum value. + repeated Option options = 3; +} + +// Proto option attached to messages/fields/enums etc. +message Option { + // Proto option name. + string name = 1; + // Proto option value. + Any value = 2; +} + +// Syntax specifies the syntax in which a service element was defined. +enum Syntax { + // Syntax "proto2" + SYNTAX_PROTO2 = 0; + // Syntax "proto3" + SYNTAX_PROTO3 = 1; +} diff --git a/proto/google/protobuf/unknown_enum_test.proto b/proto/google/protobuf/unknown_enum_test.proto new file mode 100644 index 000000000000..3c549cc78003 --- /dev/null +++ b/proto/google/protobuf/unknown_enum_test.proto @@ -0,0 +1,62 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Definitions of protos for testing cross-version compatibility. The +// UpRevision message acts as if it were a newer version of the DownRevision +// message. That is, UpRevision shares all the same fields as DownRevision, +// but UpRevision can add fields and add enum values. +syntax = "proto2"; + +package google.protobuf.util; + +option csharp_namespace = "Google.ProtocolBuffers.TestProtos"; + +message DownRevision { + enum Enum { + DEFAULT_VALUE = 2; + NONDEFAULT_VALUE = 3; + } + + optional Enum value = 1 [default = DEFAULT_VALUE]; + repeated Enum values = 2; +} + +message UpRevision { + enum Enum { + DEFAULT_VALUE = 2; + NONDEFAULT_VALUE = 3; + NEW_VALUE = 4; + NEW_VALUE_2 = 5; + NEW_VALUE_3 = 6; + } + + optional Enum value = 1 [default = DEFAULT_VALUE]; + repeated Enum values = 2; +} diff --git a/proto/google/protobuf/wrappers.proto b/proto/google/protobuf/wrappers.proto new file mode 100644 index 000000000000..a1d6e4461419 --- /dev/null +++ b/proto/google/protobuf/wrappers.proto @@ -0,0 +1,117 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Wrappers for primitive (non-message) types. These types are useful +// for embedding primitives in the `google.protobuf.Any` type and for places +// where we need to distinguish between the absence of a primitive +// typed field and its default value. + +syntax = "proto3"; + +package google.protobuf; + +option java_generate_equals_and_hash = true; +option java_multiple_files = true; +option java_outer_classname = "WrappersProto"; +option java_package = "com.google.protobuf"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option objc_class_prefix = "GPB"; + +// Wrapper message for `double`. +// +// The JSON representation for `DoubleValue` is JSON number. +message DoubleValue { + // The double value. + double value = 1; +} + +// Wrapper message for `float`. +// +// The JSON representation for `FloatValue` is JSON number. +message FloatValue { + // The float value. + float value = 1; +} + +// Wrapper message for `int64`. +// +// The JSON representation for `Int64Value` is JSON string. +message Int64Value { + // The int64 value. + int64 value = 1; +} + +// Wrapper message for `uint64`. +// +// The JSON representation for `UInt64Value` is JSON string. +message UInt64Value { + // The uint64 value. + uint64 value = 1; +} + +// Wrapper message for `int32`. +// +// The JSON representation for `Int32Value` is JSON number. +message Int32Value { + // The int32 value. + int32 value = 1; +} + +// Wrapper message for `uint32`. +// +// The JSON representation for `UInt32Value` is JSON number. +message UInt32Value { + // The uint32 value. + uint32 value = 1; +} + +// Wrapper message for `bool`. +// +// The JSON representation for `BoolValue` is JSON `true` and `false`. +message BoolValue { + // The bool value. + bool value = 1; +} + +// Wrapper message for `string`. +// +// The JSON representation for `StringValue` is JSON string. +message StringValue { + // The string value. + string value = 1; +} + +// Wrapper message for `bytes`. +// +// The JSON representation for `BytesValue` is JSON string. +message BytesValue { + // The bytes value. + bytes value = 1; +} diff --git a/proto/google/rpc/code.proto b/proto/google/rpc/code.proto new file mode 100644 index 000000000000..f9ceddcbc103 --- /dev/null +++ b/proto/google/rpc/code.proto @@ -0,0 +1,190 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.rpc; + +option java_multiple_files = true; +option java_outer_classname = "CodeProto"; +option java_package = "com.google.rpc"; + + +// The canonical error codes for Google APIs. +// Warnings: +// +// - Do not change any numeric assignments. +// - Changes to this list should be made only if there is a compelling +// need that can't be satisfied in another way. +// +// Sometimes multiple error codes may apply. Services should return +// the most specific error code that applies. For example, prefer +// `OUT_OF_RANGE` over `FAILED_PRECONDITION` if both codes apply. +// Similarly prefer `NOT_FOUND` or `ALREADY_EXISTS` over `FAILED_PRECONDITION`. +enum Code { + // Not an error; returned on success + // + // HTTP Mapping: 200 OK + OK = 0; + + // The operation was cancelled, typically by the caller. + // + // HTTP Mapping: 499 Client Closed Request + CANCELLED = 1; + + // Unknown error. For example, this error may be returned when + // a `Status` value received from another address space belongs to + // an error space that is not known in this address space. Also + // errors raised by APIs that do not return enough error information + // may be converted to this error. + // + // HTTP Mapping: 500 Internal Server Error + UNKNOWN = 2; + + // The client specified an invalid argument. Note that this differs + // from `FAILED_PRECONDITION`. `INVALID_ARGUMENT` indicates arguments + // that are problematic regardless of the state of the system + // (e.g., a malformed file name). + // + // HTTP Mapping: 400 Bad Request + INVALID_ARGUMENT = 3; + + // The deadline expired before the operation could complete. For operations + // that change the state of the system, this error may be returned + // even if the operation has completed successfully. For example, a + // successful response from a server could have been delayed long + // enough for the deadline to expire. + // + // HTTP Mapping: 504 Gateway Timeout + DEADLINE_EXCEEDED = 4; + + // Some requested entity (e.g., file or directory) was not found. + // For privacy reasons, this code *might* be returned when the client + // does not have the access rights to the entity. + // + // HTTP Mapping: 404 Not Found + NOT_FOUND = 5; + + // The entity that a client attempted to create (e.g., file or directory) + // already exists. + // + // HTTP Mapping: 409 Conflict + ALREADY_EXISTS = 6; + + // The caller does not have permission to execute the specified + // operation. `PERMISSION_DENIED` must not be used for rejections + // caused by exhausting some resource (use `RESOURCE_EXHAUSTED` + // instead for those errors). `PERMISSION_DENIED` must not be + // used if the caller can not be identified (use `UNAUTHENTICATED` + // instead for those errors). + // + // HTTP Mapping: 403 Forbidden + PERMISSION_DENIED = 7; + + // The request does not have valid authentication credentials for the + // operation. + // + // HTTP Mapping: 401 Unauthorized + UNAUTHENTICATED = 16; + + // Some resource has been exhausted, perhaps a per-user quota, or + // perhaps the entire file system is out of space. + // + // HTTP Mapping: 429 Too Many Requests + RESOURCE_EXHAUSTED = 8; + + // The operation was rejected because the system is not in a state + // required for the operation's execution. For example, the directory + // to be deleted is non-empty, an rmdir operation is applied to + // a non-directory, etc. + // + // Service implementors can use the following guidelines to decide + // between `FAILED_PRECONDITION`, `ABORTED`, and `UNAVAILABLE`: + // (a) Use `UNAVAILABLE` if the client can retry just the failing call. + // (b) Use `ABORTED` if the client should retry at a higher level + // (e.g., restarting a read-modify-write sequence). + // (c) Use `FAILED_PRECONDITION` if the client should not retry until + // the system state has been explicitly fixed. E.g., if an "rmdir" + // fails because the directory is non-empty, `FAILED_PRECONDITION` + // should be returned since the client should not retry unless + // the files are deleted from the directory. + // (d) Use `FAILED_PRECONDITION` if the client performs conditional + // REST Get/Update/Delete on a resource and the resource on the + // server does not match the condition. E.g., conflicting + // read-modify-write on the same resource. + // + // HTTP Mapping: 400 Bad Request + // + // NOTE: HTTP spec says `412 Precondition Failed` should be used only if + // the request contains Etag-related headers. So if the server does see + // Etag-related headers in the request, it may choose to return 412 + // instead of 400 for this error code. + FAILED_PRECONDITION = 9; + + // The operation was aborted, typically due to a concurrency issue such as + // a sequencer check failure or transaction abort. + // + // See the guidelines above for deciding between `FAILED_PRECONDITION`, + // `ABORTED`, and `UNAVAILABLE`. + // + // HTTP Mapping: 409 Conflict + ABORTED = 10; + + // The operation was attempted past the valid range. E.g., seeking or + // reading past end-of-file. + // + // Unlike `INVALID_ARGUMENT`, this error indicates a problem that may + // be fixed if the system state changes. For example, a 32-bit file + // system will generate `INVALID_ARGUMENT` if asked to read at an + // offset that is not in the range [0,2^32-1], but it will generate + // `OUT_OF_RANGE` if asked to read from an offset past the current + // file size. + // + // There is a fair bit of overlap between `FAILED_PRECONDITION` and + // `OUT_OF_RANGE`. We recommend using `OUT_OF_RANGE` (the more specific + // error) when it applies so that callers who are iterating through + // a space can easily look for an `OUT_OF_RANGE` error to detect when + // they are done. + // + // HTTP Mapping: 400 Bad Request + OUT_OF_RANGE = 11; + + // The operation is not implemented or is not supported/enabled in this + // service. + // + // HTTP Mapping: 501 Not Implemented + UNIMPLEMENTED = 12; + + // Internal errors. This means that some invariants expected by the + // underlying system have been broken. This error code is reserved + // for serious errors. + // + // HTTP Mapping: 500 Internal Server Error + INTERNAL = 13; + + // The service is currently unavailable. This is most likely a + // transient condition, which can be corrected by retrying with + // a backoff. + // + // See the guidelines above for deciding between `FAILED_PRECONDITION`, + // `ABORTED`, and `UNAVAILABLE`. + // + // HTTP Mapping: 503 Service Unavailable + UNAVAILABLE = 14; + + // Unrecoverable data loss or corruption. + // + // HTTP Mapping: 500 Internal Server Error + DATA_LOSS = 15; +} diff --git a/proto/google/rpc/error_details.proto b/proto/google/rpc/error_details.proto new file mode 100644 index 000000000000..82472b8b2e64 --- /dev/null +++ b/proto/google/rpc/error_details.proto @@ -0,0 +1,157 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.rpc; + +import "google/protobuf/duration.proto"; + +option java_multiple_files = true; +option java_outer_classname = "ErrorDetailsProto"; +option java_package = "com.google.rpc"; + + +// Describes when the clients can retry a failed request. Clients could ignore +// the recommendation here or retry when this information is missing from error +// responses. +// +// It's always recommended that clients should use exponential backoff when +// retrying. +// +// Clients should wait until `retry_delay` amount of time has passed since +// receiving the error response before retrying. If retrying requests also +// fail, clients should use an exponential backoff scheme to gradually increase +// the delay between retries based on `retry_delay`, until either a maximum +// number of retires have been reached or a maximum retry delay cap has been +// reached. +message RetryInfo { + // Clients should wait at least this long between retrying the same request. + google.protobuf.Duration retry_delay = 1; +} + +// Describes additional debugging info. +message DebugInfo { + // The stack trace entries indicating where the error occurred. + repeated string stack_entries = 1; + + // Additional debugging information provided by the server. + string detail = 2; +} + +// Describes how a quota check failed. +// +// For example if a daily limit was exceeded for the calling project, +// a service could respond with a QuotaFailure detail containing the project +// id and the description of the quota limit that was exceeded. If the +// calling project hasn't enabled the service in the developer console, then +// a service could respond with the project id and set `service_disabled` +// to true. +// +// Also see RetryDetail and Help types for other details about handling a +// quota failure. +message QuotaFailure { + // A message type used to describe a single quota violation. For example, a + // daily quota or a custom quota that was exceeded. + message Violation { + // The subject on which the quota check failed. + // For example, "clientip:" or "project:". + string subject = 1; + + // A description of how the quota check failed. Clients can use this + // description to find more about the quota configuration in the service's + // public documentation, or find the relevant quota limit to adjust through + // developer console. + // + // For example: "Service disabled" or "Daily Limit for read operations + // exceeded". + string description = 2; + } + + // Describes all quota violations. + repeated Violation violations = 1; +} + +// Describes violations in a client request. This error type focuses on the +// syntactic aspects of the request. +message BadRequest { + // A message type used to describe a single bad request field. + message FieldViolation { + // A path leading to a field in the request body. The value will be a + // sequence of dot-separated identifiers that identify a protocol buffer + // field. E.g., "violations.field" would identify this field. + string field = 1; + + // A description of why the request element is bad. + string description = 2; + } + + // Describes all violations in a client request. + repeated FieldViolation field_violations = 1; +} + +// Contains metadata about the request that clients can attach when filing a bug +// or providing other forms of feedback. +message RequestInfo { + // An opaque string that should only be interpreted by the service generating + // it. For example, it can be used to identify requests in the service's logs. + string request_id = 1; + + // Any data that was used to serve this request. For example, an encrypted + // stack trace that can be sent back to the service provider for debugging. + string serving_data = 2; +} + +// Describes the resource that is being accessed. +message ResourceInfo { + // A name for the type of resource being accessed, e.g. "sql table", + // "cloud storage bucket", "file", "Google calendar"; or the type URL + // of the resource: e.g. "type.googleapis.com/google.pubsub.v1.Topic". + string resource_type = 1; + + // The name of the resource being accessed. For example, a shared calendar + // name: "example.com_4fghdhgsrgh@group.calendar.google.com", if the current + // error is [google.rpc.Code.PERMISSION_DENIED][google.rpc.Code.PERMISSION_DENIED]. + string resource_name = 2; + + // The owner of the resource (optional). + // For example, "user:" or "project:". + string owner = 3; + + // Describes what error is encountered when accessing this resource. + // For example, updating a cloud project may require the `writer` permission + // on the developer console project. + string description = 4; +} + +// Provides links to documentation or for performing an out of band action. +// +// For example, if a quota check failed with an error indicating the calling +// project hasn't enabled the accessed service, this can contain a URL pointing +// directly to the right place in the developer console to flip the bit. +message Help { + // Describes a URL link. + message Link { + // Describes what the link offers. + string description = 1; + + // The URL of the link. + string url = 2; + } + + // URL(s) pointing to additional information on handling the current error. + repeated Link links = 1; +} diff --git a/proto/google/rpc/status.proto b/proto/google/rpc/status.proto new file mode 100644 index 000000000000..8fca6ab22d9e --- /dev/null +++ b/proto/google/rpc/status.proto @@ -0,0 +1,90 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.rpc; + +import "google/protobuf/any.proto"; + +option java_multiple_files = true; +option java_outer_classname = "StatusProto"; +option java_package = "com.google.rpc"; + + +// The `Status` type defines a logical error model that is suitable for different +// programming environments, including REST APIs and RPC APIs. It is used by +// [gRPC](https://github.com/grpc). The error model is designed to be: +// +// - Simple to use and understand for most users +// - Flexible enough to meet unexpected needs +// +// # Overview +// +// The `Status` message contains three pieces of data: error code, error message, +// and error details. The error code should be an enum value of +// [google.rpc.Code][google.rpc.Code], but it may accept additional error codes if needed. The +// error message should be a developer-facing English message that helps +// developers *understand* and *resolve* the error. If a localized user-facing +// error message is needed, put the localized message in the error details or +// localize it in the client. The optional error details may contain arbitrary +// information about the error. There is a predefined set of error detail types +// in the package `google.rpc` which can be used for common error conditions. +// +// # Language mapping +// +// The `Status` message is the logical representation of the error model, but it +// is not necessarily the actual wire format. When the `Status` message is +// exposed in different client libraries and different wire protocols, it can be +// mapped differently. For example, it will likely be mapped to some exceptions +// in Java, but more likely mapped to some error codes in C. +// +// # Other uses +// +// The error model and the `Status` message can be used in a variety of +// environments, either with or without APIs, to provide a +// consistent developer experience across different environments. +// +// Example uses of this error model include: +// +// - Partial errors. If a service needs to return partial errors to the client, +// it may embed the `Status` in the normal response to indicate the partial +// errors. +// +// - Workflow errors. A typical workflow has multiple steps. Each step may +// have a `Status` message for error reporting purpose. +// +// - Batch operations. If a client uses batch request and batch response, the +// `Status` message should be used directly inside batch response, one for +// each error sub-response. +// +// - Asynchronous operations. If an API call embeds asynchronous operation +// results in its response, the status of those operations should be +// represented directly using the `Status` message. +// +// - Logging. If some API errors are stored in logs, the message `Status` could +// be used directly after any stripping needed for security/privacy reasons. +message Status { + // The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. + int32 code = 1; + + // A developer-facing error message, which should be in English. Any + // user-facing error message should be localized and sent in the + // [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client. + string message = 2; + + // A list of messages that carry the error details. There will be a + // common set of message types for APIs to use. + repeated google.protobuf.Any details = 3; +} diff --git a/proto/google/type/color.proto b/proto/google/type/color.proto new file mode 100644 index 000000000000..3e200230d82b --- /dev/null +++ b/proto/google/type/color.proto @@ -0,0 +1,163 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +import "google/protobuf/wrappers.proto"; + +option java_multiple_files = true; +option java_outer_classname = "ColorProto"; +option java_package = "com.google.type"; + + +// Represents a color in the RGBA color space. This representation is designed +// for simplicity of conversion to/from color representations in various +// languages over compactness; for example, the fields of this representation +// can be trivially provided to the constructor of "java.awt.Color" in Java; it +// can also be trivially provided to UIColor's "+colorWithRed:green:blue:alpha" +// method in iOS; and, with just a little work, it can be easily formatted into +// a CSS "rgba()" string in JavaScript, as well. Here are some examples: +// +// Example (Java): +// +// import com.google.type.Color; +// +// // ... +// public static java.awt.Color fromProto(Color protocolor) { +// float alpha = protocolor.hasAlpha() +// ? protocolor.getAlpha().getValue() +// : 1.0; +// +// return new java.awt.Color( +// protocolor.getRed(), +// protocolor.getGreen(), +// protocolor.getBlue(), +// alpha); +// } +// +// public static Color toProto(java.awt.Color color) { +// float red = (float) color.getRed(); +// float green = (float) color.getGreen(); +// float blue = (float) color.getBlue(); +// float denominator = 255.0; +// Color.Builder resultBuilder = +// Color +// .newBuilder() +// .setRed(red / denominator) +// .setGreen(green / denominator) +// .setBlue(blue / denominator); +// int alpha = color.getAlpha(); +// if (alpha != 255) { +// result.setAlpha( +// FloatValue +// .newBuilder() +// .setValue(((float) alpha) / denominator) +// .build()); +// } +// return resultBuilder.build(); +// } +// // ... +// +// Example (iOS / Obj-C): +// +// // ... +// static UIColor* fromProto(Color* protocolor) { +// float red = [protocolor red]; +// float green = [protocolor green]; +// float blue = [protocolor blue]; +// FloatValue* alpha_wrapper = [protocolor alpha]; +// float alpha = 1.0; +// if (alpha_wrapper != nil) { +// alpha = [alpha_wrapper value]; +// } +// return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; +// } +// +// static Color* toProto(UIColor* color) { +// CGFloat red, green, blue, alpha; +// if (![color getRed:&red green:&green blue:&blue alpha:&alpha]) { +// return nil; +// } +// Color* result = [Color alloc] init]; +// [result setRed:red]; +// [result setGreen:green]; +// [result setBlue:blue]; +// if (alpha <= 0.9999) { +// [result setAlpha:floatWrapperWithValue(alpha)]; +// } +// [result autorelease]; +// return result; +// } +// // ... +// +// Example (JavaScript): +// +// // ... +// +// var protoToCssColor = function(rgb_color) { +// var redFrac = rgb_color.red || 0.0; +// var greenFrac = rgb_color.green || 0.0; +// var blueFrac = rgb_color.blue || 0.0; +// var red = Math.floor(redFrac * 255); +// var green = Math.floor(greenFrac * 255); +// var blue = Math.floor(blueFrac * 255); +// +// if (!('alpha' in rgb_color)) { +// return rgbToCssColor_(red, green, blue); +// } +// +// var alphaFrac = rgb_color.alpha.value || 0.0; +// var rgbParams = [red, green, blue].join(','); +// return ['rgba(', rgbParams, ',', alphaFrac, ')'].join(''); +// }; +// +// var rgbToCssColor_ = function(red, green, blue) { +// var rgbNumber = new Number((red << 16) | (green << 8) | blue); +// var hexString = rgbNumber.toString(16); +// var missingZeros = 6 - hexString.length; +// var resultBuilder = ['#']; +// for (var i = 0; i < missingZeros; i++) { +// resultBuilder.push('0'); +// } +// resultBuilder.push(hexString); +// return resultBuilder.join(''); +// }; +// +// // ... +// +message Color { + // The amount of red in the color as a value in the interval [0, 1]. + float red = 1; + + // The amount of green in the color as a value in the interval [0, 1]. + float green = 2; + + // The amount of blue in the color as a value in the interval [0, 1]. + float blue = 3; + + // The fraction of this color that should be applied to the pixel. That is, + // the final pixel color is defined by the equation: + // + // pixel color = alpha * (this color) + (1.0 - alpha) * (background color) + // + // This means that a value of 1.0 corresponds to a solid color, whereas + // a value of 0.0 corresponds to a completely transparent color. This + // uses a wrapper message rather than a simple float scalar so that it is + // possible to distinguish between a default value and the value being unset. + // If omitted, this color object is to be rendered as a solid color + // (as if the alpha value had been explicitly given with a value of 1.0). + google.protobuf.FloatValue alpha = 4; +} diff --git a/proto/google/type/date.proto b/proto/google/type/date.proto new file mode 100644 index 000000000000..a12090b8a4eb --- /dev/null +++ b/proto/google/type/date.proto @@ -0,0 +1,43 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option java_generate_equals_and_hash = true; +option java_multiple_files = true; +option java_outer_classname = "DateProto"; +option java_package = "com.google.type"; + + +// Represents a whole calendar date, e.g. date of birth. The time of day and +// time zone are either specified elsewhere or are not significant. The date +// is relative to the Proleptic Gregorian Calendar. The day may be 0 to +// represent a year and month where the day is not significant, e.g. credit card +// expiration date. The year may be 0 to represent a month and day independent +// of year, e.g. anniversary date. Related types are [google.type.TimeOfDay][google.type.TimeOfDay] +// and [google.protobuf.Timestamp][google.protobuf.Timestamp]. +message Date { + // Year of date. Must be from 1 to 9,999, or 0 if specifying a date without + // a year. + int32 year = 1; + + // Month of year of date. Must be from 1 to 12. + int32 month = 2; + + // Day of month. Must be from 1 to 31 and valid for the year and month, or 0 + // if specifying a year/month where the day is not sigificant. + int32 day = 3; +} diff --git a/proto/google/type/dayofweek.proto b/proto/google/type/dayofweek.proto new file mode 100644 index 000000000000..df09f69912be --- /dev/null +++ b/proto/google/type/dayofweek.proto @@ -0,0 +1,50 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option java_generate_equals_and_hash = true; +option java_multiple_files = true; +option java_outer_classname = "DayOfWeekProto"; +option java_package = "com.google.type"; + + +// Represents a day of week. +enum DayOfWeek { + // The unspecified day-of-week. + DAY_OF_WEEK_UNSPECIFIED = 0; + + // The day-of-week of Monday. + MONDAY = 1; + + // The day-of-week of Tuesday. + TUESDAY = 2; + + // The day-of-week of Wednesday. + WEDNESDAY = 3; + + // The day-of-week of Thursday. + THURSDAY = 4; + + // The day-of-week of Friday. + FRIDAY = 5; + + // The day-of-week of Saturday. + SATURDAY = 6; + + // The day-of-week of Sunday. + SUNDAY = 7; +} diff --git a/proto/google/type/latlng.proto b/proto/google/type/latlng.proto new file mode 100644 index 000000000000..198decc0e76d --- /dev/null +++ b/proto/google/type/latlng.proto @@ -0,0 +1,36 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option java_generate_equals_and_hash = true; +option java_multiple_files = true; +option java_outer_classname = "LatLngProto"; +option java_package = "com.google.type"; + + +// An object representing a latitude/longitude pair. This is expressed as a pair +// of doubles representing degrees latitude and degrees longitude. Unless +// specified otherwise, this must conform to the +// WGS84 +// standard. Values must be within normalized ranges. +message LatLng { + // The latitude in degrees. It must be in the range [-90.0, +90.0]. + double latitude = 1; + + // The longitude in degrees. It must be in the range [-180.0, +180.0]. + double longitude = 2; +} diff --git a/proto/google/type/money.proto b/proto/google/type/money.proto new file mode 100644 index 000000000000..041454a23a7a --- /dev/null +++ b/proto/google/type/money.proto @@ -0,0 +1,40 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option java_multiple_files = true; +option java_outer_classname = "MoneyProto"; +option java_package = "com.google.type"; + + +// Represents an amount of money with its currency type. +message Money { + // The 3-letter currency code defined in ISO 4217. + string currency_code = 1; + + // The whole units of the amount. + // For example if `currencyCode` is `"USD"`, then 1 unit is one US dollar. + int64 units = 2; + + // Number of nano (10^-9) units of the amount. + // The value must be between -999,999,999 and +999,999,999 inclusive. + // If `units` is positive, `nanos` must be positive or zero. + // If `units` is zero, `nanos` can be positive, zero, or negative. + // If `units` is negative, `nanos` must be negative or zero. + // For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000. + int32 nanos = 3; +} diff --git a/proto/google/type/timeofday.proto b/proto/google/type/timeofday.proto new file mode 100644 index 000000000000..f39266e00cf1 --- /dev/null +++ b/proto/google/type/timeofday.proto @@ -0,0 +1,42 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option java_generate_equals_and_hash = true; +option java_multiple_files = true; +option java_outer_classname = "TimeOfDayProto"; +option java_package = "com.google.type"; + + +// Represents a time of day. The date and time zone are either not significant +// or are specified elsewhere. An API may chose to allow leap seconds. Related +// types are [google.type.Date][google.type.Date] and [google.protobuf.Timestamp][google.protobuf.Timestamp]. +message TimeOfDay { + // Hours of day in 24 hour format. Should be from 0 to 23. An API may choose + // to allow the value "24:00:00" for scenarios like business closing time. + int32 hours = 1; + + // Minutes of hour of day. Must be from 0 to 59. + int32 minutes = 2; + + // Seconds of minutes of the time. Must normally be from 0 to 59. An API may + // allow the value 60 if it allows leap-seconds. + int32 seconds = 3; + + // Fractions of seconds in nanoseconds. Must be from 0 to 999,999,999. + int32 nanos = 4; +} diff --git a/proto/index.js b/proto/index.js new file mode 100644 index 000000000000..d9a4eec5594b --- /dev/null +++ b/proto/index.js @@ -0,0 +1,30 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @private + * @module proto + */ + +'use strict'; + +var protobufjs = require('protobufjs'); +protobufjs.convertFieldsToCamelCase = true; + +module.exports = protobufjs.loadProtoFile({ + root: __dirname, + file: '/google/datastore/v1beta3/datastore.proto' +}).build().google; diff --git a/system-test/datastore.js b/system-test/datastore.js index d7e7fd3e649b..fc699034db8e 100644 --- a/system-test/datastore.js +++ b/system-test/datastore.js @@ -28,8 +28,8 @@ describe('datastore', function() { it('should allocate IDs', function(done) { ds.allocateIds(ds.key('Kind'), 10, function(err, keys) { assert.ifError(err); - assert.equal(keys.length, 10); - assert.equal(entity.isKeyComplete(keys[0]), true); + assert.strictEqual(keys.length, 10); + assert.strictEqual(entity.isKeyComplete(keys[0]), true); done(); }); }); @@ -47,6 +47,7 @@ describe('datastore', function() { it('should save/get/delete with a key name', function(done) { var postKey = ds.key(['Post', 'post1']); + ds.save({ key: postKey, data: post }, function(err) { assert.ifError(err); @@ -77,7 +78,7 @@ describe('datastore', function() { }); it('should save/get/delete a buffer', function(done) { - var postKey = ds.key('Post'); + var postKey = ds.key(['Post']); var data = { buf: new Buffer('010100000000000000000059400000000000006940', 'hex') }; @@ -127,7 +128,7 @@ describe('datastore', function() { assert(postKey.path[1]); ds.save({ key: postKey, method: 'insert', data: post }, function(err) { - assert.notEqual(err, null); // should fail insert + assert.notStrictEqual(err, null); // should fail insert ds.get(postKey, function(err, entity) { assert.ifError(err); @@ -144,7 +145,7 @@ describe('datastore', function() { var postKey = ds.key('Post'); ds.save({ key: postKey, method: 'update', data: post }, function(err) { - assert.notEqual(err, null); + assert.notStrictEqual(err, null); done(); }); }); @@ -159,6 +160,7 @@ describe('datastore', function() { wordCount: 450, rating: 4.5, }; + var key1 = ds.key('Post'); var key2 = ds.key('Post'); @@ -168,15 +170,11 @@ describe('datastore', function() { ], function(err) { assert.ifError(err); - var firstKey = ds.key(['Post', key1.path[1]]); - var secondKey = ds.key(['Post', key2.path[1]]); - - ds.get([firstKey, secondKey], function(err, entities) { + ds.get([key1, key2], function(err, entities) { assert.ifError(err); + assert.strictEqual(entities.length, 2); - assert.equal(entities.length, 2); - - ds.delete([firstKey, secondKey], done); + ds.delete([key1, key2], done); }); }); }); @@ -208,25 +206,29 @@ describe('datastore', function() { }); }); }); - }); - it('should save keys as a part of entity and query by key', function(done) { - var personKey = ds.key(['Person', 'name']); - ds.save({ - key: personKey, - data: { - fullName: 'Full name', - linkedTo: personKey // himself - } - }, function(err) { - assert.ifError(err); - var q = ds.createQuery('Person') - .filter('linkedTo =', personKey); - ds.runQuery(q, function(err, results) { + it('should save keys as a part of entity and query by key', function(done) { + var personKey = ds.key(['Person', 'name']); + + ds.save({ + key: personKey, + data: { + fullName: 'Full name', + linkedTo: personKey // himself + } + }, function(err) { assert.ifError(err); - assert.strictEqual(results[0].data.fullName, 'Full name'); - assert.deepEqual(results[0].data.linkedTo, personKey); - ds.delete(personKey, done); + + var query = ds.createQuery('Person').filter('linkedTo =', personKey); + + ds.runQuery(query, function(err, results) { + assert.ifError(err); + + assert.strictEqual(results[0].data.fullName, 'Full name'); + assert.deepEqual(results[0].data.linkedTo, personKey); + + ds.delete(personKey, done); + }); }); }); }); @@ -235,90 +237,102 @@ describe('datastore', function() { var ancestor = ds.key(['Book', 'GoT']); var keys = [ - ds.key(['Book', 'GoT', 'Character', 'Rickard']), - ds.key(['Book', 'GoT', 'Character', 'Rickard', 'Character', 'Eddard']), - ds.key(['Book', 'GoT', 'Character', 'Catelyn']), - ds.key(['Book', 'GoT', 'Character', 'Rickard', 'Character', 'Eddard', - 'Character', 'Arya']), - ds.key(['Book', 'GoT', 'Character', 'Rickard', 'Character', 'Eddard', - 'Character', 'Sansa']), - ds.key(['Book', 'GoT', 'Character', 'Rickard', 'Character', 'Eddard', - 'Character', 'Robb']), - ds.key(['Book', 'GoT', 'Character', 'Rickard', 'Character', 'Eddard', - 'Character', 'Bran']), - ds.key(['Book', 'GoT', 'Character', 'Rickard', 'Character', 'Eddard', - 'Character', 'Jon Snow']) - ]; + // Paths: + ['Rickard'], + ['Rickard', 'Character', 'Eddard'], + ['Catelyn'], + ['Rickard', 'Character', 'Eddard', 'Character', 'Arya'], + ['Rickard', 'Character', 'Eddard', 'Character', 'Sansa'], + ['Rickard', 'Character', 'Eddard', 'Character', 'Robb'], + ['Rickard', 'Character', 'Eddard', 'Character', 'Bran'], + ['Rickard', 'Character', 'Eddard', 'Character', 'Jon Snow'] + ].map(function(path) { + return ds.key(['Book', 'GoT', 'Character'].concat(path)); + }); - var characters = [{ - name: 'Rickard', - family: 'Stark', - appearances: 0, - alive: false - }, { - name: 'Eddard', - family: 'Stark', - appearances: 9, - alive: false - }, { - name: 'Catelyn', - family: ['Stark', 'Tully'], - appearances: 26, - alive: false - }, { - name: 'Arya', - family: 'Stark', - appearances: 33, - alive: true - }, { - name: 'Sansa', - family: 'Stark', - appearances: 31, - alive: true - }, { - name: 'Robb', - family: 'Stark', - appearances: 22, - alive: false - }, { - name: 'Bran', - family: 'Stark', - appearances: 25, - alive: true - }, { - name: 'Jon Snow', - family: 'Stark', - appearances: 32, - alive: true - }]; + var characters = [ + { + name: 'Rickard', + family: 'Stark', + appearances: 9, + alive: false + }, + { + name: 'Eddard', + family: 'Stark', + appearances: 9, + alive: false + }, + { + name: 'Catelyn', + family: ['Stark', 'Tully'], + appearances: 26, + alive: false + }, + { + name: 'Arya', + family: 'Stark', + appearances: 33, + alive: true + }, + { + name: 'Sansa', + family: 'Stark', + appearances: 31, + alive: true + }, + { + name: 'Robb', + family: 'Stark', + appearances: 22, + alive: false + }, + { + name: 'Bran', + family: 'Stark', + appearances: 25, + alive: true + }, + { + name: 'Jon Snow', + family: 'Stark', + appearances: 32, + alive: true + } + ]; before(function(done) { - ds.save(keys.map(function(key, index) { + var keysToSave = keys.map(function(key, index) { return { key: key, data: characters[index] }; - }), function(err) { - assert.ifError(err); - done(); }); + + ds.save(keysToSave, done); + }); + + after(function(done) { + ds.delete(keys, done); }); it('should limit queries', function(done) { - var q = ds.createQuery('Character').hasAncestor(ancestor).limit(5) - .autoPaginate(false); + var firstQuery = ds.createQuery('Character') + .hasAncestor(ancestor) + .limit(5) + .autoPaginate(false); - ds.runQuery(q, function(err, firstEntities, secondQuery) { + ds.runQuery(firstQuery, function(err, firstEntities, secondQuery) { assert.ifError(err); - assert.equal(firstEntities.length, 5); + assert.strictEqual(firstEntities.length, 5); ds.runQuery(secondQuery, function(err, secondEntities, thirdQuery) { assert.ifError(err); - assert.equal(secondEntities.length, 3); + assert.strictEqual(secondEntities.length, 3); ds.runQuery(thirdQuery, function(err, thirdEntities) { assert.ifError(err); - assert.equal(thirdEntities.length, 0); + assert.strictEqual(thirdEntities.length, 0); done(); }); }); @@ -328,13 +342,11 @@ describe('datastore', function() { it('should not go over a limit', function(done) { var limit = 3; - var q = ds.createQuery('Character') - .hasAncestor(ancestor) - .limit(limit); + var q = ds.createQuery('Character').hasAncestor(ancestor).limit(limit); ds.runQuery(q, function(err, results) { assert.ifError(err); - assert.equal(results.length, limit); + assert.strictEqual(results.length, limit); done(); }); }); @@ -348,7 +360,7 @@ describe('datastore', function() { .on('error', done) .on('data', function() { resultsReturned++; }) .on('end', function() { - assert.equal(resultsReturned, characters.length); + assert.strictEqual(resultsReturned, characters.length); done(); }); }); @@ -363,76 +375,90 @@ describe('datastore', function() { .on('error', done) .on('data', function() { resultsReturned++; }) .on('end', function() { - assert.equal(resultsReturned, limit); + assert.strictEqual(resultsReturned, limit); done(); }); }); it('should filter queries with simple indexes', function(done) { - var q = ds.createQuery('Character').hasAncestor(ancestor) - .filter('appearances >=', 20); + var q = ds.createQuery('Character') + .hasAncestor(ancestor) + .filter('appearances >=', 20); + ds.runQuery(q, function(err, entities) { assert.ifError(err); - assert.equal(entities.length, 6); + assert.strictEqual(entities.length, 6); done(); }); }); it('should filter queries with defined indexes', function(done) { var q = ds.createQuery('Character').hasAncestor(ancestor) - .filter('family =', 'Stark') - .filter('appearances >=', 20); + .filter('family =', 'Stark') + .filter('appearances >=', 20); + ds.runQuery(q, function(err, entities) { assert.ifError(err); - assert.equal(entities.length, 6); + assert.strictEqual(entities.length, 6); done(); }); }); it('should filter by ancestor', function(done) { - var q = ds.createQuery('Character') - .hasAncestor(ancestor); + var q = ds.createQuery('Character').hasAncestor(ancestor); + ds.runQuery(q, function(err, entities) { assert.ifError(err); - assert.equal(entities.length, 8); + assert.strictEqual(entities.length, characters.length); done(); }); }); it('should filter by key', function(done) { - var q = ds.createQuery('Character').hasAncestor(ancestor) - .filter('__key__ =', ds.key(['Book', 'GoT', 'Character', 'Rickard'])); + var q = ds.createQuery('Character') + .hasAncestor(ancestor) + .filter('__key__ =', ds.key(['Book', 'GoT', 'Character', 'Rickard'])); + ds.runQuery(q, function(err, entities) { assert.ifError(err); - assert.equal(entities.length, 1); + assert.strictEqual(entities.length, 1); done(); }); }); it('should order queries', function(done) { - var q = ds.createQuery('Character').hasAncestor(ancestor) - .order('appearances'); + var q = ds.createQuery('Character') + .hasAncestor(ancestor) + .order('appearances'); + ds.runQuery(q, function(err, entities) { assert.ifError(err); - assert.equal(entities[0].data.name, characters[0].name); - assert.equal(entities[7].data.name, characters[3].name); + + assert.strictEqual(entities[0].data.name, characters[0].name); + assert.strictEqual(entities[7].data.name, characters[3].name); + done(); }); }); it('should select projections', function(done) { - var q = ds.createQuery('Character').hasAncestor(ancestor) - .select(['name', 'family']); + var q = ds.createQuery('Character') + .hasAncestor(ancestor) + .select(['name', 'family']); + ds.runQuery(q, function(err, entities) { assert.ifError(err); + assert.deepEqual(entities[0].data, { name: 'Arya', family: 'Stark' }); + assert.deepEqual(entities[8].data, { name: 'Sansa', family: 'Stark' }); + done(); }); }); @@ -448,16 +474,17 @@ describe('datastore', function() { ds.runQuery(q, function(err, entities, secondQuery) { assert.ifError(err); - assert.equal(entities.length, 3); - assert.equal(entities[0].data.name, 'Robb'); - assert.equal(entities[2].data.name, 'Catelyn'); + assert.strictEqual(entities.length, 3); + assert.strictEqual(entities[0].data.name, 'Robb'); + assert.strictEqual(entities[2].data.name, 'Catelyn'); ds.runQuery(secondQuery.offset(0), function(err, secondEntities) { assert.ifError(err); - assert.equal(secondEntities.length, 3); - assert.equal(secondEntities[0].data.name, 'Sansa'); - assert.equal(secondEntities[2].data.name, 'Arya'); + assert.strictEqual(secondEntities.length, 3); + assert.strictEqual(secondEntities[0].data.name, 'Sansa'); + assert.strictEqual(secondEntities[2].data.name, 'Arya'); + done(); }); }); @@ -476,27 +503,24 @@ describe('datastore', function() { ds.runQuery(nextQuery.limit(-1), function(err, secondEntities) { assert.ifError(err); - assert.equal(secondEntities.length, 4); - assert.equal(secondEntities[0].data.name, 'Catelyn'); - assert.equal(secondEntities[3].data.name, 'Arya'); + + assert.strictEqual(secondEntities.length, 4); + assert.strictEqual(secondEntities[0].data.name, 'Catelyn'); + assert.strictEqual(secondEntities[3].data.name, 'Arya'); + done(); }); }); }); it('should group queries', function(done) { - var q = ds.createQuery('Character').hasAncestor(ancestor) - .groupBy('alive'); - ds.runQuery(q, function(err, entities) { - assert.ifError(err); - assert.equal(entities.length, 2); - done(); - }); - }); + var q = ds.createQuery('Character') + .hasAncestor(ancestor) + .groupBy('appearances'); - after(function(done) { - ds.delete(keys, function(err) { + ds.runQuery(q, function(err, entities) { assert.ifError(err); + assert.strictEqual(entities.length, characters.length - 1); done(); }); }); @@ -553,14 +577,14 @@ describe('datastore', function() { assert.ifError(err); // Incomplete key should have been given an ID. - assert.equal(incompleteKey.path.length, 2); + assert.strictEqual(incompleteKey.path.length, 2); async.parallel([ // The key queued for deletion should have been deleted. function(done) { ds.get(deleteKey, function(err, entity) { assert.ifError(err); - assert.equal(typeof entity, 'undefined'); + assert.strictEqual(typeof entity, 'undefined'); done(); }); }, @@ -569,11 +593,14 @@ describe('datastore', function() { function(done) { ds.get(key, function(err, entity) { assert.ifError(err); - assert.equal(entity.data.rating, 10); + assert.strictEqual(entity.data.rating, 10); done(); }); } - ], done); + ], function(err) { + assert.ifError(err); + ds.delete([key, incompleteKey], done); + }); }); }); @@ -585,11 +612,15 @@ describe('datastore', function() { t.save([ { key: key, - data: { rating: 10 } + data: { + rating: 10 + } }, { key: incompleteKey, - data: { rating: 100 } + data: { + rating: 100 + } } ]); @@ -605,7 +636,7 @@ describe('datastore', function() { assert.strictEqual(entity, undefined); // Incomplete key should have been given an id. - assert.equal(incompleteKey.path.length, 2); + assert.strictEqual(incompleteKey.path.length, 2); done(); }); }); diff --git a/test/datastore/request.js b/test/datastore/request.js index 88786e9d5a8f..a8d7973181d6 100644 --- a/test/datastore/request.js +++ b/test/datastore/request.js @@ -25,7 +25,7 @@ var format = require('string-format-obj'); var is = require('is'); var mockery = require('mockery'); var mockRespGet = require('../testdata/response_get.json'); -var pb = require('../../lib/datastore/pb.js'); +var pb = require('../../lib/datastore/proto/index.js'); var Query = require('../../lib/datastore/query.js'); var requestModule = require('request'); var stream = require('stream');