@peabody-soft/mbs-protos 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Attachment.proto +7 -21
- package/AuthTokens.proto +10 -32
- package/AuthenticationMethod.proto +2 -4
- package/Business.proto +5 -9
- package/BusinessLink.proto +14 -32
- package/BusinessSyncInRequest.proto +9 -29
- package/BusinessSyncInResponse.proto +13 -15
- package/BusinessSyncOutRequest.proto +19 -77
- package/BusinessSyncOutResponse.proto +29 -80
- package/Configuration.proto +4 -7
- package/Constants.proto +29 -59
- package/CreateUserRequest.proto +16 -0
- package/Entity.proto +13 -27
- package/GeneralSettings.proto +2 -3
- package/Item.proto +2 -4
- package/Message.proto +5 -7
- package/Package.proto +4 -6
- package/PartyPreferencesPayload.proto +1 -1
- package/Price.proto +3 -6
- package/PriceList.proto +4 -19
- package/Product.proto +4 -6
- package/ProductCategory.proto +2 -4
- package/ProfileSyncOutRequest.proto +10 -29
- package/ProfileSyncOutResponse.proto +13 -48
- package/ReservedPackage.proto +3 -15
- package/Role.proto +3 -12
- package/SalesOrderPayload.proto +3 -4
- package/ShoppingList.proto +6 -12
- package/ShoppingListItem.proto +5 -6
- package/UrlAndToken.proto +14 -42
- package/User.proto +3 -8
- package/WorkingDays.proto +5 -10
- package/WorkingHours.proto +2 -6
- package/WorkingHoursRange.proto +5 -7
- package/package.json +1 -1
package/Attachment.proto
CHANGED
|
@@ -7,33 +7,19 @@ import "AttachmentType.proto";
|
|
|
7
7
|
import "Entity.proto";
|
|
8
8
|
|
|
9
9
|
// A file (a photo of a business, product or package, for example) attached to an entity.
|
|
10
|
-
// Excluded: isPublic, isReadyForSync
|
|
11
|
-
// Not included because it is derived: storageFileName,
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
// "%04d-%02d-%02d-%016X-%s.%s" (Java Attachment.ATTACHMENT_FILE_NAME_FORMAT)
|
|
16
|
-
//
|
|
17
|
-
// year, month and day the createdAt of this entity, read in UTC. The month is the one
|
|
18
|
-
// java.util.Calendar gives and is therefore zero based: January is 00 and
|
|
19
|
-
// December is 11, so a file created in September 2026 is stored under
|
|
20
|
-
// "2026-08-...". Both ends of the protocol do this, so a client must too.
|
|
21
|
-
// id Entity.id, 16 upper case hex digits, zero padded, with no 0x prefix
|
|
22
|
-
// fileHash the 16 bytes of fileHash as 32 upper case hex digits
|
|
23
|
-
// fileExtension appended after a dot, as it is
|
|
24
|
-
//
|
|
25
|
-
// The case matters: a blob name is case sensitive. The whole name is one flat name, not a path -
|
|
26
|
-
// see UrlAndToken for how a url is built from it.
|
|
10
|
+
// Excluded: isPublic, isReadyForSync, isProcessingComplete.
|
|
11
|
+
// Not included because it is derived: storageFileName, built as "%04d-%02d-%02d-%016X-%s.%s" from
|
|
12
|
+
// this entity's createdAt (UTC, zero based month - September is 08), id (16 upper case hex digits),
|
|
13
|
+
// fileHash (32 upper case hex digits) and fileExtension. Case sensitive; see UrlAndToken for the url.
|
|
27
14
|
message Attachment {
|
|
28
15
|
|
|
29
16
|
Entity entity = 1;
|
|
30
17
|
|
|
31
|
-
//
|
|
18
|
+
// The type id, exposed instead of the raw value packed into this attachment's category.
|
|
32
19
|
AttachmentType attachmentType = 2;
|
|
33
20
|
|
|
34
|
-
// Id of the entity this file is attached to - a business,
|
|
35
|
-
//
|
|
36
|
-
// entity type of the owner is the most significant byte of this id (see Constants).
|
|
21
|
+
// Id of the entity this file is attached to - a business, product or package. The most
|
|
22
|
+
// significant byte of this id is the owner's entity type (see Constants).
|
|
37
23
|
int64 owningEntityId = 3;
|
|
38
24
|
|
|
39
25
|
// MD5 hash of the attached file, exactly Constants.ATTACHMENT_FILE_HASH_SIZE_BYTES bytes long.
|
package/AuthTokens.proto
CHANGED
|
@@ -5,47 +5,25 @@ option java_package = "com.merabills.server.core.generated";
|
|
|
5
5
|
|
|
6
6
|
import "AuthenticationMethod.proto";
|
|
7
7
|
|
|
8
|
-
// The tokens that prove who is making a request.
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// The three tokens answer different questions: authenticationToken says which person is calling,
|
|
13
|
-
// userToken says which MeraBills user that person is, and linkToken says which business they may
|
|
14
|
-
// act against. They are parsed in that order and the first is a prerequisite for the second, so a
|
|
15
|
-
// userToken is never trusted on its own (Authority.parseUserToken parses the authentication token
|
|
16
|
-
// first). A storefront acquires them in that order too - it signs in with an identity provider,
|
|
17
|
-
// exchanges that for a user token by calling the profile sync out, and gets a link token per
|
|
18
|
-
// business from the BusinessLinks that call returns.
|
|
19
|
-
//
|
|
20
|
-
// Not included because the server derives it: the subject id, and the phone number, which
|
|
21
|
-
// Authority.parseAuthenticationToken reads out of authenticationToken rather than trusting a field.
|
|
22
|
-
// A client that knows its own subject id has no reason to send it, and no way to be believed if it
|
|
23
|
-
// did.
|
|
24
|
-
//
|
|
25
|
-
// Every value here is a bearer credential: never log one, never put one in a url, and hold them
|
|
26
|
-
// only for as long as the session lasts.
|
|
8
|
+
// The tokens that prove who is making a request. Serialized into the authorization header of every
|
|
9
|
+
// request, never into a body; every value is a bearer credential - never log or url-encode one.
|
|
10
|
+
// Not included because the server derives it: the subject id and phone number, parsed by the server
|
|
11
|
+
// out of authenticationToken rather than trusted from a field.
|
|
27
12
|
message AuthTokens {
|
|
28
13
|
|
|
29
14
|
// Which identity provider issued authenticationToken, and so how the server parses it. Always
|
|
30
|
-
// set
|
|
31
|
-
// unspecified value, because zero is FIREBASE.
|
|
15
|
+
// set; there is no unspecified value because zero is FIREBASE.
|
|
32
16
|
AuthenticationMethod authenticationMethod = 1;
|
|
33
17
|
|
|
34
18
|
// The credential from that identity provider - a Firebase id token when the method is FIREBASE.
|
|
35
|
-
// Always set
|
|
36
|
-
// message. This is not issued by this server, and this server does not renew it; a client
|
|
37
|
-
// refreshes it with its identity provider.
|
|
19
|
+
// Always set. Not issued or renewed by this server; refreshed with the identity provider.
|
|
38
20
|
string authenticationToken = 2;
|
|
39
21
|
|
|
40
|
-
// Token proving which MeraBills user the subject is, issued and signed by this server
|
|
41
|
-
//
|
|
42
|
-
// once, and again once it expires, at which point a client calls that again to be given another
|
|
43
|
-
// rather than deriving one.
|
|
22
|
+
// Token proving which MeraBills user the subject is, issued and signed by this server. Absent
|
|
23
|
+
// until the profile sync out has been called once, and again once it expires.
|
|
44
24
|
optional string userToken = 3;
|
|
45
25
|
|
|
46
|
-
// Token authorizing the caller
|
|
47
|
-
// business
|
|
48
|
-
// required for one that does. It is per business, so a client that shows two businesses holds one
|
|
49
|
-
// of these for each and sends the one that matches the request.
|
|
26
|
+
// Token authorizing the caller against one business - the BusinessLink.linkToken of that
|
|
27
|
+
// business. Absent for a request that names no business, required for one that does.
|
|
50
28
|
optional string linkToken = 4;
|
|
51
29
|
}
|
|
@@ -10,10 +10,8 @@ option java_package = "com.merabills.server.core.generated";
|
|
|
10
10
|
// always set, so a client never needs one.
|
|
11
11
|
enum AuthenticationMethod {
|
|
12
12
|
|
|
13
|
-
// The authentication token is a Firebase id token
|
|
14
|
-
//
|
|
15
|
-
// of an AuthTokens is not a Firebase token - it is issued by this server, whatever method
|
|
16
|
-
// authenticated the subject.
|
|
13
|
+
// The authentication token is a Firebase id token; the subject id parsed from it is a Firebase
|
|
14
|
+
// uid, not the same thing as User.entity.id.
|
|
17
15
|
FIREBASE = 0;
|
|
18
16
|
|
|
19
17
|
// Reserved for internal administrative callers. A storefront never uses this method.
|
package/Business.proto
CHANGED
|
@@ -5,15 +5,11 @@ option java_package = "com.merabills.server.core.generated";
|
|
|
5
5
|
|
|
6
6
|
import "Entity.proto";
|
|
7
7
|
|
|
8
|
-
// A business that a customer can buy from.
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
// the caller is linked to. A BusinessSyncOutResponse carries it as well, for the one business it is
|
|
14
|
-
// about, because a client that has not signed in has no profile sync out to read it from.
|
|
15
|
-
// Excluded: category (and the BusinessType derived from it), displayNameOld,
|
|
16
|
-
// allowJoinWithoutInvitation, forTraining and all Translations fields.
|
|
8
|
+
// A business that a customer can buy from. Contains no other entity: settings arrive as a
|
|
9
|
+
// Configuration, photos as Attachments whose owningEntityId is this business, and the catalog as
|
|
10
|
+
// the item entities of a BusinessSyncOutResponse.
|
|
11
|
+
// Excluded: category (and the derived BusinessType), displayNameOld, allowJoinWithoutInvitation,
|
|
12
|
+
// forTraining, all Translations fields.
|
|
17
13
|
message Business {
|
|
18
14
|
|
|
19
15
|
Entity entity = 1;
|
package/BusinessLink.proto
CHANGED
|
@@ -6,32 +6,21 @@ option java_package = "com.merabills.server.core.generated";
|
|
|
6
6
|
import "Entity.proto";
|
|
7
7
|
import "Role.proto";
|
|
8
8
|
|
|
9
|
-
// Associates an entity - a user or a business - with a business, in a
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
// so it is carried by a ProfileSyncOutResponse and never by a BusinessSyncOutResponse.
|
|
15
|
-
//
|
|
16
|
-
// Excluded: invitationDetails - the name of the inviter, the note they wrote and the rest of it are
|
|
17
|
-
// about accepting an invitation, which is not part of a storefront.
|
|
18
|
-
// Not included because they are derived from expiry: isExpirySet and hasExpired.
|
|
9
|
+
// Associates an entity - a user or a business - with a business, in a role, and carries the token
|
|
10
|
+
// that lets it act against that business. Lives in a profile database; carried by a
|
|
11
|
+
// ProfileSyncOutResponse, never by a BusinessSyncOutResponse.
|
|
12
|
+
// Excluded: invitationDetails.
|
|
13
|
+
// Not included because it is derived from expiry: isExpirySet, hasExpired.
|
|
19
14
|
message BusinessLink {
|
|
20
15
|
|
|
21
16
|
Entity entity = 1;
|
|
22
17
|
|
|
23
|
-
// Id of the entity this link is for
|
|
24
|
-
//
|
|
25
|
-
// Constants.BUSINESS_ENTITY_TYPE_ID), which is how a client tells the two apart. For a storefront
|
|
26
|
-
// this is the User of the caller.
|
|
18
|
+
// Id of the entity this link is for - a user or a business. The most significant byte of this id
|
|
19
|
+
// (Constants.USER_ENTITY_TYPE_ID or Constants.BUSINESS_ENTITY_TYPE_ID) says which.
|
|
27
20
|
int64 linkedEntityId = 2;
|
|
28
21
|
|
|
29
|
-
// Id of the business this link is to.
|
|
30
|
-
//
|
|
31
|
-
// This is an entity id, so it matches Business.entity.id - not Business.businessId, which is the
|
|
32
|
-
// lower case url friendly string a storefront is reached by. The Java accessors are both called
|
|
33
|
-
// getBusinessId and return different things (a long here, a String on Business), so this is easy to
|
|
34
|
-
// get wrong.
|
|
22
|
+
// Id of the business this link is to - an entity id, matching Business.entity.id, not
|
|
23
|
+
// Business.businessId (the url friendly string).
|
|
35
24
|
int64 businessId = 3;
|
|
36
25
|
|
|
37
26
|
// What the linked entity may do with the business. A storefront customer is normally
|
|
@@ -39,21 +28,14 @@ message BusinessLink {
|
|
|
39
28
|
Role role = 4;
|
|
40
29
|
|
|
41
30
|
// Id of the party record of the linked entity within that business, or Constants.ENTITY_ID_NULL
|
|
42
|
-
// when there is none.
|
|
43
|
-
// a storefront; it is here because it is a field of the Java class and because the server needs it.
|
|
44
|
-
// Every role outside the partner group has one.
|
|
31
|
+
// when there is none. Not resolvable by a storefront - Party is not generated by this protocol.
|
|
45
32
|
int64 partyId = 5;
|
|
46
33
|
|
|
47
|
-
//
|
|
48
|
-
// AuthTokens.linkToken of every later request
|
|
49
|
-
//
|
|
50
|
-
// It is a bearer credential: never log it, never put it in a URL, and never show it to anyone but
|
|
51
|
-
// the entity it was issued to. It is not one of the stored attributes of the entity - the server
|
|
52
|
-
// issues it - so a link that arrives without one cannot be used to reach the business.
|
|
34
|
+
// Bearer credential proving the linked entity may act against this business - goes into
|
|
35
|
+
// AuthTokens.linkToken of every later request naming it. Never log it or put it in a url.
|
|
53
36
|
optional string linkToken = 6;
|
|
54
37
|
|
|
55
|
-
// Time
|
|
56
|
-
// BusinessLink.NO_EXPIRY
|
|
57
|
-
// clock, so allow for Constants.MAX_CLOCK_SKEW before deciding a link has expired.
|
|
38
|
+
// Time this link stops being valid, in milliseconds since Jan 1, 1970 00:00:00 UTC.
|
|
39
|
+
// 0 (BusinessLink.NO_EXPIRY) means it never expires; allow for Constants.MAX_CLOCK_SKEW.
|
|
58
40
|
int64 expiry = 7;
|
|
59
41
|
}
|
|
@@ -5,38 +5,18 @@ option java_package = "com.merabills.server.core.generated";
|
|
|
5
5
|
|
|
6
6
|
import "Message.proto";
|
|
7
7
|
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
// This writes one business database, which is what it is named after. A message is a business entity
|
|
14
|
-
// even though the customer sent it, so the cart and the orders belong here; the profile of the
|
|
15
|
-
// customer does not, and is written by a sync in of its own.
|
|
16
|
-
//
|
|
17
|
-
// Who is asking is not part of this message: it is in the AuthTokens of the authorization header. The
|
|
18
|
-
// server authorizes each array against the rights of that caller - messages against
|
|
19
|
-
// Right.MESSAGES_MODIFY - so a client cannot push an entity type it has no right to, and a
|
|
20
|
-
// storefront customer may push only their own messages.
|
|
21
|
-
//
|
|
22
|
-
// An entity being synced in carries the id it already has, or Constants.ENTITY_ID_NULL when the
|
|
23
|
-
// client is creating it and the server is to assign one. The update numbers of the incoming
|
|
24
|
-
// entities are the client's own and are not comparable with the server's: the server assigns new
|
|
25
|
-
// ones and returns them in the BusinessSyncInResponse.
|
|
8
|
+
// Pushes the business entities a customer has changed - their shopping cart and the orders placed
|
|
9
|
+
// from it - to one business database, named the same way a BusinessSyncOutRequest names it.
|
|
10
|
+
// An entity being synced in carries the id it already has, or Constants.ENTITY_ID_NULL if the
|
|
11
|
+
// caller is creating it and the server is to assign one; incoming update numbers are the caller's
|
|
12
|
+
// own and are replaced by the server, which returns the new ones in the BusinessSyncInResponse.
|
|
26
13
|
message BusinessSyncInRequest {
|
|
27
14
|
|
|
28
|
-
// The business these entities belong to
|
|
29
|
-
//
|
|
30
|
-
// (Constants.BUSINESS_ID_MIN_LENGTH to Constants.BUSINESS_ID_MAX_LENGTH)
|
|
15
|
+
// The business these entities belong to - its unique, lower case, url friendly id
|
|
16
|
+
// (Constants.BUSINESS_ID_MIN_LENGTH to Constants.BUSINESS_ID_MAX_LENGTH).
|
|
31
17
|
string businessId = 1;
|
|
32
18
|
|
|
33
|
-
// The shopping cart
|
|
34
|
-
//
|
|
35
|
-
// Constants.MESSAGE_ENTITY_TYPE_ID.
|
|
36
|
-
//
|
|
37
|
-
// This is the only entity type a storefront may push. A customer does not edit the business, its
|
|
38
|
-
// settings, its catalog or its photos, and their own User lives in a profile database that this
|
|
39
|
-
// call does not touch - so there is deliberately no field for any of those types here, rather
|
|
40
|
-
// than a field the server would reject.
|
|
19
|
+
// The shopping cart (a PartyPreferencesPayload) and orders (a SalesOrderPayload) of the customer -
|
|
20
|
+
// entity type Constants.MESSAGE_ENTITY_TYPE_ID, the only entity type a customer may push.
|
|
41
21
|
repeated Message messages = 2;
|
|
42
22
|
}
|
|
@@ -3,21 +3,19 @@ package com.merabills.storefront;
|
|
|
3
3
|
option java_multiple_files = true;
|
|
4
4
|
option java_package = "com.merabills.server.core.generated";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// was accepted, which is what a request that carried none of them gets back.
|
|
13
|
-
//
|
|
14
|
-
// This response carries no entities. A client that needs the server's view of what it pushed - the
|
|
15
|
-
// id assigned to an entity the server created, or the authoritative totals of a shopping list,
|
|
16
|
-
// which are computed with the rounding rules of PriceCalculation - syncs out again afterwards.
|
|
6
|
+
import "AuthTokens.proto";
|
|
7
|
+
|
|
8
|
+
// The answer to a BusinessSyncInRequest: the update number the server assigned to the pushed
|
|
9
|
+
// entities, one per entity type. Raise the matching cursor to this value so the next sync out does
|
|
10
|
+
// not fetch back what was just sent; 0 means nothing of that type was accepted. Carries no entities
|
|
11
|
+
// - sync out again to see the server's view of what was pushed.
|
|
17
12
|
message BusinessSyncInResponse {
|
|
18
13
|
|
|
19
|
-
// The
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
// The tokens to send with the next request, when the server has renewed one of them. Absent means
|
|
15
|
+
// what the client already holds still works - never a signal to drop the tokens it has.
|
|
16
|
+
optional AuthTokens authTokens = 1;
|
|
17
|
+
|
|
18
|
+
// Highest update number assigned to the messages of the request - entity type
|
|
19
|
+
// Constants.MESSAGE_ENTITY_TYPE_ID, the only entity field this response carries.
|
|
20
|
+
int64 messageUpdateNumber = 2;
|
|
23
21
|
}
|
|
@@ -3,98 +3,40 @@ package com.merabills.storefront;
|
|
|
3
3
|
option java_multiple_files = true;
|
|
4
4
|
option java_package = "com.merabills.server.core.generated";
|
|
5
5
|
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// This reads one business database, which is why there is no cursor for the User of the caller and no
|
|
12
|
-
// User in the response: a user lives in a profile database and is read by a ProfileSyncOutRequest, the
|
|
13
|
-
// way Java splits Service.businessSyncOut from Service.profileSyncOut.
|
|
14
|
-
//
|
|
15
|
-
// A Business is a profile database entity too, but it is carried here as well, because a client that
|
|
16
|
-
// has not signed in has no profile sync out to read it from and would otherwise not know the name or
|
|
17
|
-
// the country of the business it is showing. So businessUpdateNumber below and
|
|
18
|
-
// ProfileSyncOutRequest.businessUpdateNumber are cursors over the same entity type kept by two
|
|
19
|
-
// different calls: a client keeps one per call and must not carry a number from one over to the other.
|
|
20
|
-
//
|
|
21
|
-
// Who is asking is not part of this message: it is in the AuthTokens of the authorization header,
|
|
22
|
-
// whose linkToken is the BusinessLink.linkToken of the business named below.
|
|
23
|
-
//
|
|
24
|
-
// The store it is asking on behalf of is, in clientDatabaseId below. A storefront keeps a
|
|
25
|
-
// persistent store, so it is a database in the sync topology and has an id of its own, and the
|
|
26
|
-
// server needs that id to know which changes not to send back. This is the requestingDbId argument
|
|
27
|
-
// of Service.businessSyncOut, which the Java clients pass as the db-id query parameter
|
|
28
|
-
// (HttpQueryParameters.DATABASE_ID) rather than in the body; a storefront carries it here instead,
|
|
29
|
-
// so that one protobuf message says everything a sync out needs.
|
|
30
|
-
//
|
|
31
|
-
// Each cursor below is the highest Entity.updateNumber of that entity type that this client has
|
|
32
|
-
// already synced out. The server sends back the entities of that type whose updateNumber is
|
|
33
|
-
// greater, so a client stores the highest updateNumber it receives per type and sends it back on
|
|
34
|
-
// the next call. Zero, the default, means this client has nothing yet and asks for everything -
|
|
35
|
-
// a first sync therefore leaves every cursor unset.
|
|
36
|
-
//
|
|
37
|
-
// One field below is not a cursor: attachmentBaseUrlExpiry is a time, and it asks for a value rather
|
|
38
|
-
// than for entities. It is here because the files of the attachments of a business are read from a
|
|
39
|
-
// url that expires, and renewing it in this call costs nothing, where a call of its own would cost a
|
|
40
|
-
// round trip on every sync.
|
|
41
|
-
//
|
|
42
|
-
// Sync out is bounded: one call returns at most Constants.SYNC_OUT_LIMIT entities across all types
|
|
43
|
-
// together. On receiving that many, a client must call again with its updated cursors until it
|
|
44
|
-
// receives fewer.
|
|
45
|
-
//
|
|
46
|
-
// There is one cursor per entity type that has a table of its own, which is how updateNumbers are
|
|
47
|
-
// kept, and not one per class: the product categories, products, packages, price lists and prices
|
|
48
|
-
// of a catalog are all item entities and all share itemUpdateNumber. Update numbers are only
|
|
49
|
-
// comparable within one entity type, and only against the same server.
|
|
6
|
+
// Reads everything a storefront needs of one business: the Business, its settings, catalog and
|
|
7
|
+
// messages, flat for the client to reassemble. Incremental and bounded: each cursor is the highest
|
|
8
|
+
// Entity.updateNumber of that type already synced (0 asks for everything), and a response of
|
|
9
|
+
// Constants.SYNC_OUT_LIMIT entities means call again with the updated cursors. The caller and the
|
|
10
|
+
// business's link token are in the AuthTokens of the authorization header, not in this message.
|
|
50
11
|
message BusinessSyncOutRequest {
|
|
51
12
|
|
|
52
|
-
// The business to sync out,
|
|
53
|
-
//
|
|
54
|
-
// (Constants.BUSINESS_ID_MIN_LENGTH to Constants.BUSINESS_ID_MAX_LENGTH)
|
|
13
|
+
// The business to sync out, by its unique, lower case, url friendly id (Constants.BUSINESS_ID_MIN_LENGTH
|
|
14
|
+
// to Constants.BUSINESS_ID_MAX_LENGTH).
|
|
55
15
|
string businessId = 1;
|
|
56
16
|
|
|
57
|
-
// Id of the store this client keeps
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
// A client generates this once and keeps it for the life of its store. It is never
|
|
62
|
-
// Constants.MASTER_DB_ID, which is the server, and never a reserved id, so a client that sends
|
|
63
|
-
// zero is claiming to be the server and will be sent its own writes back on every sync.
|
|
64
|
-
//
|
|
65
|
-
// The same value goes into the Entity.updateInfo of everything this client pushes in a
|
|
66
|
-
// BusinessSyncInRequest. There is no such field on that request, because there the id arrives on
|
|
67
|
-
// each entity instead.
|
|
17
|
+
// Id of the store this client keeps; never Constants.MASTER_DB_ID or another reserved id. The
|
|
18
|
+
// server leaves out entities whose Entity.updateInfo matches this, so a client does not get its
|
|
19
|
+
// own writes back, and this same id goes into every entity a client pushes in a BusinessSyncInRequest.
|
|
68
20
|
int64 clientDatabaseId = 2;
|
|
69
21
|
|
|
70
|
-
//
|
|
22
|
+
// Cursor for the Business entity (Constants.BUSINESS_ENTITY_TYPE_ID). Separate from, and never
|
|
23
|
+
// mixed with, ProfileSyncOutRequest.businessUpdateNumber.
|
|
71
24
|
int64 businessUpdateNumber = 3;
|
|
72
25
|
|
|
73
|
-
//
|
|
74
|
-
// Constants.ATTACHMENT_ENTITY_TYPE_ID
|
|
26
|
+
// Cursor for photos of the business, its products and its packages (Constants.ATTACHMENT_ENTITY_TYPE_ID).
|
|
75
27
|
int64 attachmentUpdateNumber = 4;
|
|
76
28
|
|
|
77
|
-
// The expiry of the attachment base url
|
|
78
|
-
//
|
|
79
|
-
// the default, means this client holds none and is asking for one, which is what a first sync
|
|
80
|
-
// does.
|
|
81
|
-
//
|
|
82
|
-
// The server answers with a new attachmentBaseUrl when this is zero, or within
|
|
83
|
-
// Constants.ATTACHMENT_BASE_URL_EXPIRY_MARGIN of the time it reads the request, and leaves it
|
|
84
|
-
// absent otherwise. This is a time and not an update number: it is not comparable with the cursors
|
|
85
|
-
// around it, it does not rise monotonically, and a client must never derive it from anything but
|
|
86
|
-
// the UrlAndToken it holds.
|
|
29
|
+
// The UrlAndToken.expiry of the attachment base url this client is holding, sent back unchanged;
|
|
30
|
+
// 0 means it holds none. A time, not a cursor - it does not rise monotonically.
|
|
87
31
|
int64 attachmentBaseUrlExpiry = 5;
|
|
88
32
|
|
|
89
|
-
//
|
|
90
|
-
// Constants.CONFIGURATION_ENTITY_TYPE_ID
|
|
33
|
+
// Cursor for the business's settings (Constants.CONFIGURATION_ENTITY_TYPE_ID).
|
|
91
34
|
int64 configurationUpdateNumber = 6;
|
|
92
35
|
|
|
93
|
-
//
|
|
94
|
-
// Constants.MESSAGE_ENTITY_TYPE_ID
|
|
36
|
+
// Cursor for the customer's orders and shopping cart (Constants.MESSAGE_ENTITY_TYPE_ID).
|
|
95
37
|
int64 messageUpdateNumber = 7;
|
|
96
38
|
|
|
97
|
-
//
|
|
98
|
-
// all
|
|
39
|
+
// Cursor for the whole catalog - product categories, products, packages, price lists and prices,
|
|
40
|
+
// which all share this one cursor (Constants.ITEM_ENTITY_TYPE_ID).
|
|
99
41
|
int64 itemUpdateNumber = 8;
|
|
100
42
|
}
|
|
@@ -4,6 +4,7 @@ option java_multiple_files = true;
|
|
|
4
4
|
option java_package = "com.merabills.server.core.generated";
|
|
5
5
|
|
|
6
6
|
import "Attachment.proto";
|
|
7
|
+
import "AuthTokens.proto";
|
|
7
8
|
import "Business.proto";
|
|
8
9
|
import "Configuration.proto";
|
|
9
10
|
import "Message.proto";
|
|
@@ -14,96 +15,44 @@ import "Product.proto";
|
|
|
14
15
|
import "ProductCategory.proto";
|
|
15
16
|
import "UrlAndToken.proto";
|
|
16
17
|
|
|
17
|
-
// The answer to a BusinessSyncOutRequest: the entities of one business that
|
|
18
|
-
// update numbers
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
// keeps in a business database (EntityType with DbType.BUSINESS). The Business below is not: like the
|
|
25
|
-
// User and the BusinessLink, it is a profile database entity. It is carried here anyway, because a
|
|
26
|
-
// client that has not signed in has no profile sync out to read it from and would otherwise not know
|
|
27
|
-
// the name or the country of the business it is showing. The User and the BusinessLink are not, because
|
|
28
|
-
// an anonymous client has neither.
|
|
29
|
-
//
|
|
30
|
-
// A type of which there can only ever be one is a single message rather than an array, so that its
|
|
31
|
-
// presence carries the same "changed or not" information an array carries by being empty: the
|
|
32
|
-
// request names one business.
|
|
33
|
-
//
|
|
34
|
-
// Every field below is an entity of that business except one: attachmentBaseUrl is a value, and the
|
|
35
|
-
// only thing here that a client does not put in its cache and does not count against
|
|
36
|
-
// Constants.SYNC_OUT_LIMIT. It answers BusinessSyncOutRequest.attachmentBaseUrlExpiry rather than an
|
|
37
|
-
// update number, it can never be a tombstone, and it says where the files of the attachments are
|
|
38
|
-
// rather than what has changed.
|
|
39
|
-
//
|
|
40
|
-
// A client reconstructs the hierarchy itself, from the ids the entities carry:
|
|
41
|
-
// Business the business the request named
|
|
42
|
-
// Configuration its settings, by Entity.id
|
|
43
|
-
// Attachment its owner is owningEntityId - a business, a product or a package. Its
|
|
44
|
-
// file is under attachmentBaseUrl, under the storage file name that
|
|
45
|
-
// Attachment says how to build.
|
|
46
|
-
// Message its sender is senderId, which names a User of the profile database
|
|
47
|
-
// ProductCategory a category of the catalog
|
|
48
|
-
// Product its category is Item.parentItemId, or none when that is 0
|
|
49
|
-
// Package its product is Item.parentItemId
|
|
50
|
-
// PriceList the price list the business sells from. It has no parent, and there is
|
|
51
|
-
// only ever one of it in a response.
|
|
52
|
-
// Price its package is packageId; its price list is Item.parentItemId
|
|
53
|
-
// Process the arrays in the order they are declared below: a parent always arrives in an earlier
|
|
54
|
-
// array than its children, so nothing has to be resolved twice.
|
|
55
|
-
//
|
|
56
|
-
// An entity may be a tombstone rather than a value: when
|
|
57
|
-
// (updateNumber & Constants.UPDATE_TYPE_MASK) == Constants.UPDATE_TYPE_DELETED the entity has been
|
|
58
|
-
// deleted and the client must drop it and everything it owned. Only the Entity of a tombstone is
|
|
59
|
-
// meaningful.
|
|
60
|
-
//
|
|
61
|
-
// An entity type that has not changed is simply absent - an empty array, or an unset business.
|
|
62
|
-
// Absence says nothing about the entities of that type a client already holds; only an entity that
|
|
63
|
-
// arrives, or a tombstone, changes anything. So a client keeps its previous update number for an
|
|
64
|
-
// absent type.
|
|
65
|
-
//
|
|
66
|
-
// One response carries at most Constants.SYNC_OUT_LIMIT entities across all arrays together. On
|
|
67
|
-
// receiving that many, a client raises each update number to the highest it has seen for that type
|
|
68
|
-
// and requests again, until it receives fewer.
|
|
69
|
-
//
|
|
70
|
-
// Java keys its array of arrays by table entity type id. The five item types below share the item
|
|
71
|
-
// table, and therefore BusinessSyncOutRequest.itemUpdateNumber, but are separate arrays here because a
|
|
72
|
-
// protobuf repeated field cannot hold a mixture of types.
|
|
18
|
+
// The answer to a BusinessSyncOutRequest: the entities of one business that changed since the
|
|
19
|
+
// request's update numbers, one field per entity type, flat - a client rebuilds the hierarchy from
|
|
20
|
+
// Item.parentItemId, Attachment.owningEntityId and Price.packageId, processing the arrays below in
|
|
21
|
+
// order (parent before child). An absent/empty field means that type has not changed; a tombstone
|
|
22
|
+
// (updateNumber's update-type bits = Constants.UPDATE_TYPE_DELETED) means the entity, and what it
|
|
23
|
+
// owned, was deleted. At most Constants.SYNC_OUT_LIMIT entities arrive together - that many means
|
|
24
|
+
// call again with the raised cursors.
|
|
73
25
|
message BusinessSyncOutResponse {
|
|
74
26
|
|
|
75
|
-
// The
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
Business business = 1;
|
|
27
|
+
// The tokens to send with the next request, when the server has renewed one of them. Absent means
|
|
28
|
+
// what the client already holds still works - never a signal to drop the tokens it has.
|
|
29
|
+
optional AuthTokens authTokens = 1;
|
|
79
30
|
|
|
80
|
-
//
|
|
81
|
-
|
|
31
|
+
// The business named by the request. Absent unless it has changed. Also carried by a
|
|
32
|
+
// ProfileSyncOutResponse, with its own separate cursor - keep the two update numbers apart.
|
|
33
|
+
Business business = 2;
|
|
82
34
|
|
|
83
|
-
//
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
// so one of these serves the whole response and every attachment already cached. A client
|
|
92
|
-
// therefore stores it once, against the business, and not against a photo.
|
|
93
|
-
UrlAndToken attachmentBaseUrl = 3;
|
|
35
|
+
// Photos of the business, its products and its packages.
|
|
36
|
+
repeated Attachment attachments = 3;
|
|
37
|
+
|
|
38
|
+
// Where the files of every attachment of the business are, and the token that authorizes reading
|
|
39
|
+
// them - one value for the whole business, not per photo. Absent means what the client already
|
|
40
|
+
// holds still works; a client holding none sends 0 and always gets one back. Never a tombstone and
|
|
41
|
+
// never counted against Constants.SYNC_OUT_LIMIT.
|
|
42
|
+
UrlAndToken attachmentBaseUrl = 4;
|
|
94
43
|
|
|
95
44
|
// The settings of the business. An array because a business can have more than one public
|
|
96
45
|
// configuration, even though only the general settings are typed today.
|
|
97
|
-
repeated Configuration configurations =
|
|
46
|
+
repeated Configuration configurations = 5;
|
|
98
47
|
|
|
99
48
|
// The orders of the customer, and their shopping cart
|
|
100
|
-
repeated Message messages =
|
|
49
|
+
repeated Message messages = 6;
|
|
101
50
|
|
|
102
51
|
// Item entities, in the order a client needs them: a category before its products, a product
|
|
103
52
|
// before its packages, and both a package and a price list before the prices that name them
|
|
104
|
-
repeated ProductCategory productCategories =
|
|
105
|
-
repeated Product products =
|
|
106
|
-
repeated Package packages =
|
|
107
|
-
repeated PriceList priceLists =
|
|
108
|
-
repeated Price prices =
|
|
53
|
+
repeated ProductCategory productCategories = 7;
|
|
54
|
+
repeated Product products = 8;
|
|
55
|
+
repeated Package packages = 9;
|
|
56
|
+
repeated PriceList priceLists = 10;
|
|
57
|
+
repeated Price prices = 11;
|
|
109
58
|
}
|
package/Configuration.proto
CHANGED
|
@@ -6,13 +6,10 @@ option java_package = "com.merabills.server.core.generated";
|
|
|
6
6
|
import "Entity.proto";
|
|
7
7
|
import "GeneralSettings.proto";
|
|
8
8
|
|
|
9
|
-
// A setting of a business,
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
// above Configuration.MIN_PUBLIC_CONFIGURATION_ID - are ever sent to a storefront, and of those
|
|
14
|
-
// only the general settings, whose id is 0x0D10000000000000 (941252322120433664). A client does not
|
|
15
|
-
// need that id: it switches on which member of data is set.
|
|
9
|
+
// A setting of a business, identified by Entity.id, with its value typed here rather than left as
|
|
10
|
+
// the serialized string Java stores. Only public configurations (id at or above
|
|
11
|
+
// Configuration.MIN_PUBLIC_CONFIGURATION_ID) are ever sent; a client switches on which member of
|
|
12
|
+
// data is set rather than checking the id.
|
|
16
13
|
message Configuration {
|
|
17
14
|
|
|
18
15
|
Entity entity = 1;
|