@peabody-soft/mbs-model-ts 1.0.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/LICENCE +661 -0
- package/dist/Address.d.ts +33 -0
- package/dist/Address.js +97 -0
- package/dist/Attachment.d.ts +16 -0
- package/dist/Attachment.js +49 -0
- package/dist/AttachmentBaseUrl.d.ts +11 -0
- package/dist/AttachmentBaseUrl.js +41 -0
- package/dist/AuthTokens.d.ts +13 -0
- package/dist/AuthTokens.js +30 -0
- package/dist/Business.d.ts +44 -0
- package/dist/Business.js +87 -0
- package/dist/BusinessIdentifier.d.ts +8 -0
- package/dist/BusinessIdentifier.js +14 -0
- package/dist/BusinessLink.d.ts +21 -0
- package/dist/BusinessLink.js +61 -0
- package/dist/BusinessProfile.d.ts +11 -0
- package/dist/BusinessProfile.js +27 -0
- package/dist/CartEditor.d.ts +59 -0
- package/dist/CartEditor.js +324 -0
- package/dist/Catalog.d.ts +28 -0
- package/dist/Catalog.js +115 -0
- package/dist/Constants.d.ts +10 -0
- package/dist/Constants.js +43 -0
- package/dist/ContainerNames.d.ts +2 -0
- package/dist/ContainerNames.js +21 -0
- package/dist/Database.d.ts +15 -0
- package/dist/Database.js +1 -0
- package/dist/Entity.d.ts +27 -0
- package/dist/Entity.js +69 -0
- package/dist/Enums.d.ts +16 -0
- package/dist/Enums.js +18 -0
- package/dist/Exceptions.d.ts +4 -0
- package/dist/Exceptions.js +8 -0
- package/dist/GeneralSettings.d.ts +46 -0
- package/dist/GeneralSettings.js +99 -0
- package/dist/HttpStatusCodes.d.ts +2 -0
- package/dist/HttpStatusCodes.js +34 -0
- package/dist/Ids.d.ts +17 -0
- package/dist/Ids.js +78 -0
- package/dist/Item.d.ts +12 -0
- package/dist/Item.js +30 -0
- package/dist/LatLong.d.ts +7 -0
- package/dist/LatLong.js +17 -0
- package/dist/LiveData.d.ts +30 -0
- package/dist/LiveData.js +76 -0
- package/dist/Measures.d.ts +20 -0
- package/dist/Measures.js +34 -0
- package/dist/Message.d.ts +16 -0
- package/dist/Message.js +32 -0
- package/dist/MockDatabase.d.ts +19 -0
- package/dist/MockDatabase.js +73 -0
- package/dist/Model.d.ts +63 -0
- package/dist/Model.js +629 -0
- package/dist/Order.d.ts +31 -0
- package/dist/Order.js +70 -0
- package/dist/Package.d.ts +25 -0
- package/dist/Package.js +52 -0
- package/dist/PackageIdentifier.d.ts +8 -0
- package/dist/PackageIdentifier.js +14 -0
- package/dist/PaymentMethodDetail.d.ts +8 -0
- package/dist/PaymentMethodDetail.js +17 -0
- package/dist/Photo.d.ts +11 -0
- package/dist/Photo.js +29 -0
- package/dist/Price.d.ts +17 -0
- package/dist/Price.js +52 -0
- package/dist/PriceList.d.ts +3 -0
- package/dist/PriceList.js +5 -0
- package/dist/Product.d.ts +33 -0
- package/dist/Product.js +84 -0
- package/dist/ProductCategory.d.ts +10 -0
- package/dist/ProductCategory.js +18 -0
- package/dist/Profile.d.ts +20 -0
- package/dist/Profile.js +55 -0
- package/dist/ProtoMap.d.ts +71 -0
- package/dist/ProtoMap.js +1126 -0
- package/dist/Routes.d.ts +7 -0
- package/dist/Routes.js +12 -0
- package/dist/Service.d.ts +16 -0
- package/dist/Service.js +1 -0
- package/dist/ServiceExceptions.d.ts +40 -0
- package/dist/ServiceExceptions.js +84 -0
- package/dist/ServiceProxy.d.ts +25 -0
- package/dist/ServiceProxy.js +117 -0
- package/dist/ShoppingList.d.ts +64 -0
- package/dist/ShoppingList.js +188 -0
- package/dist/SyncCache.d.ts +28 -0
- package/dist/SyncCache.js +137 -0
- package/dist/SyncKeys.d.ts +5 -0
- package/dist/SyncKeys.js +41 -0
- package/dist/SyncState.d.ts +8 -0
- package/dist/SyncState.js +30 -0
- package/dist/Tax.d.ts +10 -0
- package/dist/Tax.js +30 -0
- package/dist/UserProfile.d.ts +16 -0
- package/dist/UserProfile.js +40 -0
- package/dist/WorkingDays.d.ts +33 -0
- package/dist/WorkingDays.js +121 -0
- package/dist/generated/Address.d.ts +77 -0
- package/dist/generated/Address.js +110 -0
- package/dist/generated/AddressList.d.ts +39 -0
- package/dist/generated/AddressList.js +60 -0
- package/dist/generated/AddressType.d.ts +15 -0
- package/dist/generated/AddressType.js +20 -0
- package/dist/generated/Attachment.d.ts +66 -0
- package/dist/generated/Attachment.js +89 -0
- package/dist/generated/AttachmentType.d.ts +154 -0
- package/dist/generated/AttachmentType.js +159 -0
- package/dist/generated/AuthTokens.d.ts +56 -0
- package/dist/generated/AuthTokens.js +74 -0
- package/dist/generated/AuthenticationMethod.d.ts +24 -0
- package/dist/generated/AuthenticationMethod.js +29 -0
- package/dist/generated/Business.d.ts +54 -0
- package/dist/generated/Business.js +75 -0
- package/dist/generated/BusinessIdentifier.d.ts +36 -0
- package/dist/generated/BusinessIdentifier.js +60 -0
- package/dist/generated/BusinessIdentifierType.d.ts +49 -0
- package/dist/generated/BusinessIdentifierType.js +54 -0
- package/dist/generated/BusinessLink.d.ts +76 -0
- package/dist/generated/BusinessLink.js +99 -0
- package/dist/generated/BusinessSyncInRequest.d.ts +42 -0
- package/dist/generated/BusinessSyncInRequest.js +60 -0
- package/dist/generated/BusinessSyncInResponse.d.ts +42 -0
- package/dist/generated/BusinessSyncInResponse.js +60 -0
- package/dist/generated/BusinessSyncOutRequest.d.ts +82 -0
- package/dist/generated/BusinessSyncOutRequest.js +107 -0
- package/dist/generated/BusinessSyncOutResponse.d.ts +106 -0
- package/dist/generated/BusinessSyncOutResponse.js +139 -0
- package/dist/generated/Configuration.d.ts +48 -0
- package/dist/generated/Configuration.js +63 -0
- package/dist/generated/Constants.d.ts +474 -0
- package/dist/generated/Constants.js +479 -0
- package/dist/generated/CreateUserRequest.d.ts +37 -0
- package/dist/generated/CreateUserRequest.js +59 -0
- package/dist/generated/DimensionUnit.d.ts +28 -0
- package/dist/generated/DimensionUnit.js +33 -0
- package/dist/generated/Dimensions.d.ts +41 -0
- package/dist/generated/Dimensions.js +76 -0
- package/dist/generated/Entity.d.ts +62 -0
- package/dist/generated/Entity.js +83 -0
- package/dist/generated/FulfillmentMode.d.ts +32 -0
- package/dist/generated/FulfillmentMode.js +37 -0
- package/dist/generated/GeneralSettings.d.ts +141 -0
- package/dist/generated/GeneralSettings.js +186 -0
- package/dist/generated/Item.d.ts +54 -0
- package/dist/generated/Item.js +82 -0
- package/dist/generated/LatLong.d.ts +36 -0
- package/dist/generated/LatLong.js +59 -0
- package/dist/generated/Message.d.ts +80 -0
- package/dist/generated/Message.js +114 -0
- package/dist/generated/MessageType.d.ts +34 -0
- package/dist/generated/MessageType.js +39 -0
- package/dist/generated/OrderStatus.d.ts +50 -0
- package/dist/generated/OrderStatus.js +55 -0
- package/dist/generated/Package.d.ts +63 -0
- package/dist/generated/Package.js +92 -0
- package/dist/generated/PackageIdentifier.d.ts +36 -0
- package/dist/generated/PackageIdentifier.js +60 -0
- package/dist/generated/PackageIdentifierType.d.ts +49 -0
- package/dist/generated/PackageIdentifierType.js +54 -0
- package/dist/generated/PartyPreferencesPayload.d.ts +41 -0
- package/dist/generated/PartyPreferencesPayload.js +60 -0
- package/dist/generated/PaymentMethod.d.ts +20 -0
- package/dist/generated/PaymentMethod.js +25 -0
- package/dist/generated/PaymentMethodDetail.d.ts +37 -0
- package/dist/generated/PaymentMethodDetail.js +59 -0
- package/dist/generated/Price.d.ts +52 -0
- package/dist/generated/Price.js +75 -0
- package/dist/generated/PriceList.d.ts +34 -0
- package/dist/generated/PriceList.js +51 -0
- package/dist/generated/Product.d.ts +77 -0
- package/dist/generated/Product.js +106 -0
- package/dist/generated/ProductCategory.d.ts +32 -0
- package/dist/generated/ProductCategory.js +51 -0
- package/dist/generated/ProductType.d.ts +42 -0
- package/dist/generated/ProductType.js +47 -0
- package/dist/generated/ProfileSyncOutRequest.d.ts +51 -0
- package/dist/generated/ProfileSyncOutRequest.js +75 -0
- package/dist/generated/ProfileSyncOutResponse.d.ts +56 -0
- package/dist/generated/ProfileSyncOutResponse.js +77 -0
- package/dist/generated/ReservedPackage.d.ts +34 -0
- package/dist/generated/ReservedPackage.js +39 -0
- package/dist/generated/Role.d.ts +71 -0
- package/dist/generated/Role.js +76 -0
- package/dist/generated/SalesOrderPayload.d.ts +85 -0
- package/dist/generated/SalesOrderPayload.js +123 -0
- package/dist/generated/ShoppingList.d.ts +99 -0
- package/dist/generated/ShoppingList.js +132 -0
- package/dist/generated/ShoppingListItem.d.ts +102 -0
- package/dist/generated/ShoppingListItem.js +139 -0
- package/dist/generated/TaskStatus.d.ts +20 -0
- package/dist/generated/TaskStatus.js +25 -0
- package/dist/generated/Tax.d.ts +37 -0
- package/dist/generated/Tax.js +60 -0
- package/dist/generated/TaxType.d.ts +25 -0
- package/dist/generated/TaxType.js +30 -0
- package/dist/generated/UrlAndToken.d.ts +54 -0
- package/dist/generated/UrlAndToken.js +67 -0
- package/dist/generated/User.d.ts +63 -0
- package/dist/generated/User.js +89 -0
- package/dist/generated/Weight.d.ts +33 -0
- package/dist/generated/Weight.js +60 -0
- package/dist/generated/WeightUnit.d.ts +28 -0
- package/dist/generated/WeightUnit.js +33 -0
- package/dist/generated/WorkingDays.d.ts +42 -0
- package/dist/generated/WorkingDays.js +68 -0
- package/dist/generated/WorkingHours.d.ts +33 -0
- package/dist/generated/WorkingHours.js +52 -0
- package/dist/generated/WorkingHoursRange.d.ts +42 -0
- package/dist/generated/WorkingHoursRange.js +59 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.js +60 -0
- package/package.json +55 -0
package/dist/Routes.d.ts
ADDED
package/dist/Routes.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// The last path segment of each call this library makes, appended to the base url a ServiceProxy is
|
|
2
|
+
// built with. Named after the server method the segment reaches, in the kebab case Java Routes.java
|
|
3
|
+
// uses, and prefixed to keep the storefront methods clear of the merchant ones that share the host.
|
|
4
|
+
// No route takes an id: every one of these calls says everything it needs to in its request message.
|
|
5
|
+
class Routes {
|
|
6
|
+
}
|
|
7
|
+
Routes.BUSINESS_SYNC_OUT = "shop-business-sync-out";
|
|
8
|
+
Routes.BUSINESS_SYNC_IN = "shop-business-sync-in";
|
|
9
|
+
Routes.PROFILE_SYNC_OUT = "shop-profile-sync-out";
|
|
10
|
+
Routes.CREATE_USER = "shop-create-user";
|
|
11
|
+
Routes.UPDATE_USER = "shop-update-user";
|
|
12
|
+
export default Routes;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AuthTokens as proto_AuthTokens } from "./generated/AuthTokens";
|
|
2
|
+
import { BusinessSyncInRequest as proto_BusinessSyncInRequest } from "./generated/BusinessSyncInRequest";
|
|
3
|
+
import { BusinessSyncInResponse as proto_BusinessSyncInResponse } from "./generated/BusinessSyncInResponse";
|
|
4
|
+
import { BusinessSyncOutRequest as proto_BusinessSyncOutRequest } from "./generated/BusinessSyncOutRequest";
|
|
5
|
+
import { BusinessSyncOutResponse as proto_BusinessSyncOutResponse } from "./generated/BusinessSyncOutResponse";
|
|
6
|
+
import { CreateUserRequest as proto_CreateUserRequest } from "./generated/CreateUserRequest";
|
|
7
|
+
import { ProfileSyncOutRequest as proto_ProfileSyncOutRequest } from "./generated/ProfileSyncOutRequest";
|
|
8
|
+
import { ProfileSyncOutResponse as proto_ProfileSyncOutResponse } from "./generated/ProfileSyncOutResponse";
|
|
9
|
+
import { User as proto_User } from "./generated/User";
|
|
10
|
+
export default interface Service {
|
|
11
|
+
businessSyncOut(request: proto_BusinessSyncOutRequest, authTokens: proto_AuthTokens | null): Promise<proto_BusinessSyncOutResponse>;
|
|
12
|
+
businessSyncIn(request: proto_BusinessSyncInRequest, authTokens: proto_AuthTokens): Promise<proto_BusinessSyncInResponse>;
|
|
13
|
+
profileSyncOut(request: proto_ProfileSyncOutRequest, authTokens: proto_AuthTokens): Promise<proto_ProfileSyncOutResponse>;
|
|
14
|
+
createUser(request: proto_CreateUserRequest, authTokens: proto_AuthTokens): Promise<proto_ProfileSyncOutResponse>;
|
|
15
|
+
updateUser(user: proto_User, authTokens: proto_AuthTokens): Promise<proto_ProfileSyncOutResponse>;
|
|
16
|
+
}
|
package/dist/Service.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export declare class ServiceException extends Error {
|
|
2
|
+
readonly httpStatusCode: number;
|
|
3
|
+
constructor(httpStatusCode: number, message?: string);
|
|
4
|
+
}
|
|
5
|
+
export declare class BadRequestException extends ServiceException {
|
|
6
|
+
constructor(message?: string);
|
|
7
|
+
static readonly STATUS_CODE: number;
|
|
8
|
+
}
|
|
9
|
+
export declare class UnauthorizedException extends ServiceException {
|
|
10
|
+
constructor(message?: string);
|
|
11
|
+
static readonly STATUS_CODE: number;
|
|
12
|
+
}
|
|
13
|
+
export declare class NotFoundException extends ServiceException {
|
|
14
|
+
constructor(message?: string);
|
|
15
|
+
static readonly STATUS_CODE: number;
|
|
16
|
+
}
|
|
17
|
+
export declare class MethodNotAllowedException extends ServiceException {
|
|
18
|
+
constructor(message?: string);
|
|
19
|
+
static readonly STATUS_CODE: number;
|
|
20
|
+
}
|
|
21
|
+
export declare class ConflictException extends ServiceException {
|
|
22
|
+
constructor(message?: string);
|
|
23
|
+
static readonly STATUS_CODE: number;
|
|
24
|
+
}
|
|
25
|
+
export declare class UpgradeRequiredException extends ServiceException {
|
|
26
|
+
constructor(message?: string);
|
|
27
|
+
static readonly STATUS_CODE: number;
|
|
28
|
+
}
|
|
29
|
+
export declare class InternalServerException extends ServiceException {
|
|
30
|
+
constructor(message?: string);
|
|
31
|
+
static readonly STATUS_CODE: number;
|
|
32
|
+
}
|
|
33
|
+
export declare class ServiceUnavailableException extends ServiceException {
|
|
34
|
+
constructor(message?: string);
|
|
35
|
+
static readonly STATUS_CODE: number;
|
|
36
|
+
}
|
|
37
|
+
export declare class NetworkConnectionException extends Error {
|
|
38
|
+
readonly reason?: unknown;
|
|
39
|
+
constructor(message?: string, reason?: unknown);
|
|
40
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// What a Service call fails with. Unlike the two in Exceptions.ts these are not programming errors:
|
|
2
|
+
// a caller is expected to catch them and decide what to do - sign in again, retry, or show the shop
|
|
3
|
+
// it already has cached. They mirror Java com.merabills.repository.client.exception so that the two
|
|
4
|
+
// clients of this server describe the same failure the same way.
|
|
5
|
+
// Each carries the status code rather than being told apart by a string, and the derived classes
|
|
6
|
+
// exist so a caller can catch the one case it can actually handle without testing a number.
|
|
7
|
+
// A call reached the server and the server refused it. Thrown directly for a status code none of the
|
|
8
|
+
// classes below names, so an unrecognised failure is still a ServiceException and not something else.
|
|
9
|
+
export class ServiceException extends Error {
|
|
10
|
+
constructor(httpStatusCode, message) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.httpStatusCode = httpStatusCode;
|
|
13
|
+
// Otherwise every one of these reports itself as a bare "Error" when logged
|
|
14
|
+
this.name = new.target.name;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
// HTTP 400 - the request was not one the server could act on
|
|
18
|
+
export class BadRequestException extends ServiceException {
|
|
19
|
+
constructor(message) {
|
|
20
|
+
super(BadRequestException.STATUS_CODE, message);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
BadRequestException.STATUS_CODE = 400;
|
|
24
|
+
// HTTP 401 - the credentials were missing, expired or not the caller's to present
|
|
25
|
+
export class UnauthorizedException extends ServiceException {
|
|
26
|
+
constructor(message) {
|
|
27
|
+
super(UnauthorizedException.STATUS_CODE, message);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
UnauthorizedException.STATUS_CODE = 401;
|
|
31
|
+
// HTTP 404 - no such business, user or route
|
|
32
|
+
export class NotFoundException extends ServiceException {
|
|
33
|
+
constructor(message) {
|
|
34
|
+
super(NotFoundException.STATUS_CODE, message);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
NotFoundException.STATUS_CODE = 404;
|
|
38
|
+
// HTTP 405 - the route exists but not for this method
|
|
39
|
+
export class MethodNotAllowedException extends ServiceException {
|
|
40
|
+
constructor(message) {
|
|
41
|
+
super(MethodNotAllowedException.STATUS_CODE, message);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
MethodNotAllowedException.STATUS_CODE = 405;
|
|
45
|
+
// HTTP 409 - the change collided with one the server already had
|
|
46
|
+
export class ConflictException extends ServiceException {
|
|
47
|
+
constructor(message) {
|
|
48
|
+
super(ConflictException.STATUS_CODE, message);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
ConflictException.STATUS_CODE = 409;
|
|
52
|
+
// HTTP 426 - this client is too old for the server to answer
|
|
53
|
+
export class UpgradeRequiredException extends ServiceException {
|
|
54
|
+
constructor(message) {
|
|
55
|
+
super(UpgradeRequiredException.STATUS_CODE, message);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
UpgradeRequiredException.STATUS_CODE = 426;
|
|
59
|
+
// HTTP 500 - the server failed while answering. Worth retrying, unlike the 4xx cases above.
|
|
60
|
+
export class InternalServerException extends ServiceException {
|
|
61
|
+
constructor(message) {
|
|
62
|
+
super(InternalServerException.STATUS_CODE, message);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
InternalServerException.STATUS_CODE = 500;
|
|
66
|
+
// HTTP 503 - the server is up but cannot answer yet
|
|
67
|
+
export class ServiceUnavailableException extends ServiceException {
|
|
68
|
+
constructor(message) {
|
|
69
|
+
super(ServiceUnavailableException.STATUS_CODE, message);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
ServiceUnavailableException.STATUS_CODE = 503;
|
|
73
|
+
// The call never got an answer at all - offline, DNS, TLS, a refused connection or one cut short.
|
|
74
|
+
// Not a ServiceException, because there is no status code and the server may well have acted on the
|
|
75
|
+
// request: a caller that retries has to be prepared for the first attempt to have succeeded.
|
|
76
|
+
export class NetworkConnectionException extends Error {
|
|
77
|
+
constructor(message, reason) {
|
|
78
|
+
super(message);
|
|
79
|
+
this.reason = reason;
|
|
80
|
+
this.name = new.target.name;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Which status code each of these stands for is HttpStatusCodes.ts, the way Java keeps the classes
|
|
84
|
+
// in its exception package and the mapping in HttpStatusCodes.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AuthTokens as proto_AuthTokens } from "./generated/AuthTokens";
|
|
2
|
+
import { BusinessSyncInRequest as proto_BusinessSyncInRequest } from "./generated/BusinessSyncInRequest";
|
|
3
|
+
import { BusinessSyncInResponse as proto_BusinessSyncInResponse } from "./generated/BusinessSyncInResponse";
|
|
4
|
+
import { BusinessSyncOutRequest as proto_BusinessSyncOutRequest } from "./generated/BusinessSyncOutRequest";
|
|
5
|
+
import { BusinessSyncOutResponse as proto_BusinessSyncOutResponse } from "./generated/BusinessSyncOutResponse";
|
|
6
|
+
import { CreateUserRequest as proto_CreateUserRequest } from "./generated/CreateUserRequest";
|
|
7
|
+
import { ProfileSyncOutRequest as proto_ProfileSyncOutRequest } from "./generated/ProfileSyncOutRequest";
|
|
8
|
+
import { ProfileSyncOutResponse as proto_ProfileSyncOutResponse } from "./generated/ProfileSyncOutResponse";
|
|
9
|
+
import { User as proto_User } from "./generated/User";
|
|
10
|
+
import Service from "./Service";
|
|
11
|
+
export type FetchFunction = (url: string, init: RequestInit) => Promise<Response>;
|
|
12
|
+
export default class ServiceProxy implements Service {
|
|
13
|
+
constructor(serviceBaseUrl: string, fetchFunction?: FetchFunction | null);
|
|
14
|
+
businessSyncOut(request: proto_BusinessSyncOutRequest, authTokens: proto_AuthTokens | null): Promise<proto_BusinessSyncOutResponse>;
|
|
15
|
+
businessSyncIn(request: proto_BusinessSyncInRequest, authTokens: proto_AuthTokens): Promise<proto_BusinessSyncInResponse>;
|
|
16
|
+
profileSyncOut(request: proto_ProfileSyncOutRequest, authTokens: proto_AuthTokens): Promise<proto_ProfileSyncOutResponse>;
|
|
17
|
+
createUser(request: proto_CreateUserRequest, authTokens: proto_AuthTokens): Promise<proto_ProfileSyncOutResponse>;
|
|
18
|
+
updateUser(user: proto_User, authTokens: proto_AuthTokens): Promise<proto_ProfileSyncOutResponse>;
|
|
19
|
+
private post;
|
|
20
|
+
private send;
|
|
21
|
+
private getFetchFunction;
|
|
22
|
+
private static readErrorMessage;
|
|
23
|
+
private readonly _serviceBaseUrl;
|
|
24
|
+
private readonly _fetchFunction;
|
|
25
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { BusinessSyncInRequest as proto_BusinessSyncInRequest } from "./generated/BusinessSyncInRequest";
|
|
2
|
+
import { BusinessSyncInResponse as proto_BusinessSyncInResponse } from "./generated/BusinessSyncInResponse";
|
|
3
|
+
import { BusinessSyncOutRequest as proto_BusinessSyncOutRequest } from "./generated/BusinessSyncOutRequest";
|
|
4
|
+
import { BusinessSyncOutResponse as proto_BusinessSyncOutResponse } from "./generated/BusinessSyncOutResponse";
|
|
5
|
+
import { CreateUserRequest as proto_CreateUserRequest } from "./generated/CreateUserRequest";
|
|
6
|
+
import { ProfileSyncOutRequest as proto_ProfileSyncOutRequest } from "./generated/ProfileSyncOutRequest";
|
|
7
|
+
import { ProfileSyncOutResponse as proto_ProfileSyncOutResponse } from "./generated/ProfileSyncOutResponse";
|
|
8
|
+
import { User as proto_User } from "./generated/User";
|
|
9
|
+
import { IllegalOperationException } from "./Exceptions";
|
|
10
|
+
import { isError, throwOnError } from "./HttpStatusCodes";
|
|
11
|
+
import { buildAuthTokensBytes } from "./ProtoMap";
|
|
12
|
+
import Routes from "./Routes";
|
|
13
|
+
import { NetworkConnectionException } from "./ServiceExceptions";
|
|
14
|
+
// A Service that reaches a real MeraBills server. Every call is one POST to the route named after
|
|
15
|
+
// it, carrying its request message encoded, and answering with the response message encoded - so
|
|
16
|
+
// this class translates nothing and reads no field of either.
|
|
17
|
+
// One call is one page: a sync out is paged, and the loop belongs to whoever is caching what comes
|
|
18
|
+
// back, so that each page is written as it arrives - see Model.businessSyncIn.
|
|
19
|
+
export default class ServiceProxy {
|
|
20
|
+
// The base url is everything before the route, with or without a trailing slash and with or
|
|
21
|
+
// without a path of its own - both are joined onto rather than replaced, so a server reached
|
|
22
|
+
// under a prefix works without the caller having to know how a route is built.
|
|
23
|
+
constructor(serviceBaseUrl, fetchFunction = null) {
|
|
24
|
+
this._serviceBaseUrl = serviceBaseUrl.replace(TRAILING_SLASHES, "");
|
|
25
|
+
this._fetchFunction = fetchFunction;
|
|
26
|
+
}
|
|
27
|
+
async businessSyncOut(request, authTokens) {
|
|
28
|
+
return this.post(Routes.BUSINESS_SYNC_OUT, proto_BusinessSyncOutRequest, request, proto_BusinessSyncOutResponse, authTokens);
|
|
29
|
+
}
|
|
30
|
+
async businessSyncIn(request, authTokens) {
|
|
31
|
+
return this.post(Routes.BUSINESS_SYNC_IN, proto_BusinessSyncInRequest, request, proto_BusinessSyncInResponse, authTokens);
|
|
32
|
+
}
|
|
33
|
+
async profileSyncOut(request, authTokens) {
|
|
34
|
+
return this.post(Routes.PROFILE_SYNC_OUT, proto_ProfileSyncOutRequest, request, proto_ProfileSyncOutResponse, authTokens);
|
|
35
|
+
}
|
|
36
|
+
async createUser(request, authTokens) {
|
|
37
|
+
return this.post(Routes.CREATE_USER, proto_CreateUserRequest, request, proto_ProfileSyncOutResponse, authTokens);
|
|
38
|
+
}
|
|
39
|
+
// The User is the whole request, there being no wrapper message for one
|
|
40
|
+
async updateUser(user, authTokens) {
|
|
41
|
+
return this.post(Routes.UPDATE_USER, proto_User, user, proto_ProfileSyncOutResponse, authTokens);
|
|
42
|
+
}
|
|
43
|
+
// One call: encode, send, turn a refusal into the exception it stands for, decode. The message
|
|
44
|
+
// types are passed in rather than named per call so that every route is sent and read identically.
|
|
45
|
+
async post(route, requestType, request, responseType, authTokens) {
|
|
46
|
+
const response = await this.send(route, requestType.toBinary(request), authTokens);
|
|
47
|
+
// The body of a failure is not a response message, so it has to be dealt with before decoding
|
|
48
|
+
if (isError(response.status))
|
|
49
|
+
throwOnError(response.status, await ServiceProxy.readErrorMessage(route, response));
|
|
50
|
+
return responseType.fromBinary(new Uint8Array(await response.arrayBuffer()));
|
|
51
|
+
}
|
|
52
|
+
async send(route, body, authTokens) {
|
|
53
|
+
const headers = { [CONTENT_TYPE_HEADER]: CONTENT_TYPE_PROTOBUF };
|
|
54
|
+
// An anonymous visitor is given no header at all rather than an empty one - the protocol has no
|
|
55
|
+
// anonymous form of the message, so the absence is what says nobody is claiming to be calling.
|
|
56
|
+
if (authTokens !== null)
|
|
57
|
+
headers[AUTHORIZATION_HEADER] = toBase64(buildAuthTokensBytes(authTokens));
|
|
58
|
+
try {
|
|
59
|
+
return await this.getFetchFunction()(`${this._serviceBaseUrl}/${route}`, {
|
|
60
|
+
method: POST,
|
|
61
|
+
headers: headers,
|
|
62
|
+
body: body,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
catch (reason) {
|
|
66
|
+
// fetch rejects only when no answer arrived at all; a server that refused the call answers
|
|
67
|
+
// with a status code and resolves. So the request may still have been acted on, and a caller
|
|
68
|
+
// that retries has to be prepared for the first attempt to have succeeded.
|
|
69
|
+
throw new NetworkConnectionException(`The call to ${route} could not be completed`, reason);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Resolved per call rather than at construction, so a platform that installs fetch after this
|
|
73
|
+
// object is built still works and an absent one fails where it is actually needed.
|
|
74
|
+
getFetchFunction() {
|
|
75
|
+
const supplied = this._fetchFunction;
|
|
76
|
+
if (supplied !== null)
|
|
77
|
+
return supplied;
|
|
78
|
+
const platform = globalThis.fetch;
|
|
79
|
+
if (platform === undefined)
|
|
80
|
+
throw new IllegalOperationException("This platform has no fetch, so a ServiceProxy cannot reach a server");
|
|
81
|
+
// Bound, because fetch called detached from globalThis is refused by browsers
|
|
82
|
+
return platform.bind(globalThis);
|
|
83
|
+
}
|
|
84
|
+
// What the response says went wrong, if anything. This protocol has no error message of its own
|
|
85
|
+
// yet, so the body of a failure can be anything at all - a stack trace, an HTML page - and only
|
|
86
|
+
// the start of one is worth carrying; a body that cannot be read says nothing the status code
|
|
87
|
+
// does not already.
|
|
88
|
+
static async readErrorMessage(route, response) {
|
|
89
|
+
let body;
|
|
90
|
+
try {
|
|
91
|
+
body = (await response.text()).trim();
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
body = "";
|
|
95
|
+
}
|
|
96
|
+
if (body.length > MAX_ERROR_MESSAGE_LENGTH)
|
|
97
|
+
body = `${body.slice(0, MAX_ERROR_MESSAGE_LENGTH)}...`;
|
|
98
|
+
return body.length === 0 ? route : `${route}: ${body}`;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// A header carries text, so the encoded credentials travel as base64. No scheme prefix: the server
|
|
102
|
+
// reads the whole value as one encoded AuthTokens, exactly as the Java client sends the whole value
|
|
103
|
+
// as one serialized AuthTokens.
|
|
104
|
+
function toBase64(bytes) {
|
|
105
|
+
// Built a character at a time rather than by spreading the array into String.fromCharCode, which
|
|
106
|
+
// passes it as an argument list and overflows the stack once it is long enough
|
|
107
|
+
let binary = "";
|
|
108
|
+
for (const byte of bytes)
|
|
109
|
+
binary += String.fromCharCode(byte);
|
|
110
|
+
return btoa(binary);
|
|
111
|
+
}
|
|
112
|
+
const AUTHORIZATION_HEADER = "authorization";
|
|
113
|
+
const CONTENT_TYPE_HEADER = "content-type";
|
|
114
|
+
const CONTENT_TYPE_PROTOBUF = "application/octet-stream";
|
|
115
|
+
const POST = "POST";
|
|
116
|
+
const MAX_ERROR_MESSAGE_LENGTH = 512;
|
|
117
|
+
const TRAILING_SLASHES = /\/+$/;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import Tax from "./Tax";
|
|
2
|
+
export default class ShoppingList {
|
|
3
|
+
private readonly _isFinal;
|
|
4
|
+
private readonly _autoAddDeliveryCharge;
|
|
5
|
+
private readonly _autoAddServiceCharge;
|
|
6
|
+
private readonly _inventoryLocationId;
|
|
7
|
+
private readonly _priceListId;
|
|
8
|
+
private readonly _totalAmountBeforeDiscount;
|
|
9
|
+
private readonly _discount;
|
|
10
|
+
private readonly _existingItemCount;
|
|
11
|
+
private readonly _deletedItemCount;
|
|
12
|
+
private readonly _existingItems;
|
|
13
|
+
private readonly _deletedItems;
|
|
14
|
+
static fromScaledValues(isFinal: boolean, autoAddDeliveryCharge: boolean, autoAddServiceCharge: boolean, inventoryLocationId: number, priceListId: bigint, scaledTotalAmountBeforeDiscount: bigint, scaledDiscount: bigint, existingItemCount: number, deletedItemCount: number, existingItems: ReadonlyArray<ShoppingListItem>, deletedItems: ReadonlyArray<ShoppingListItem>): ShoppingList;
|
|
15
|
+
constructor(_isFinal: boolean, _autoAddDeliveryCharge: boolean, _autoAddServiceCharge: boolean, _inventoryLocationId: number, _priceListId: bigint, _totalAmountBeforeDiscount: number, _discount: number, _existingItemCount: number, _deletedItemCount: number, _existingItems: ReadonlyArray<ShoppingListItem>, _deletedItems: ReadonlyArray<ShoppingListItem>);
|
|
16
|
+
get isFinal(): boolean;
|
|
17
|
+
get autoAddDeliveryCharge(): boolean;
|
|
18
|
+
get autoAddServiceCharge(): boolean;
|
|
19
|
+
get inventoryLocationId(): number;
|
|
20
|
+
get priceListId(): bigint;
|
|
21
|
+
get totalAmountBeforeDiscount(): number;
|
|
22
|
+
get discount(): number;
|
|
23
|
+
get totalAmount(): number;
|
|
24
|
+
get existingItemCount(): number;
|
|
25
|
+
get deletedItemCount(): number;
|
|
26
|
+
get itemCount(): number;
|
|
27
|
+
get existingItems(): ReadonlyArray<ShoppingListItem>;
|
|
28
|
+
get deletedItems(): ReadonlyArray<ShoppingListItem>;
|
|
29
|
+
get computedTotal(): number;
|
|
30
|
+
get computedTotalTax(): number;
|
|
31
|
+
static readonly EMPTY: ShoppingList;
|
|
32
|
+
}
|
|
33
|
+
export declare class ShoppingListItem {
|
|
34
|
+
private readonly _packageId;
|
|
35
|
+
private readonly _quantity;
|
|
36
|
+
private readonly _unitPrice;
|
|
37
|
+
private readonly _shoppingListOrder;
|
|
38
|
+
private readonly _isOriginal;
|
|
39
|
+
private readonly _isModified;
|
|
40
|
+
private readonly _isStockKeepingRequired;
|
|
41
|
+
private readonly _priceDiscount;
|
|
42
|
+
private readonly _discount;
|
|
43
|
+
private readonly _taxes;
|
|
44
|
+
private readonly _expiryMinutes;
|
|
45
|
+
private readonly _description;
|
|
46
|
+
static fromScaledValues(packageId: bigint, scaledQuantity: number, scaledUnitPrice: bigint, shoppingListOrder: number, isOriginal: boolean, isModified: boolean, isStockKeepingRequired: boolean, scaledPriceDiscount: bigint, scaledDiscount: bigint, taxes: ReadonlyArray<Tax>, expiryMinutes: number, description: string | null): ShoppingListItem;
|
|
47
|
+
constructor(_packageId: bigint, _quantity: number, _unitPrice: number, _shoppingListOrder: number, _isOriginal: boolean, _isModified: boolean, _isStockKeepingRequired: boolean, _priceDiscount: number, _discount: number, _taxes: ReadonlyArray<Tax>, _expiryMinutes: number, _description: string | null);
|
|
48
|
+
get packageId(): bigint;
|
|
49
|
+
get isReservedPackage(): boolean;
|
|
50
|
+
get quantity(): number;
|
|
51
|
+
get unitPrice(): number;
|
|
52
|
+
get shoppingListOrder(): number;
|
|
53
|
+
get isOriginal(): boolean;
|
|
54
|
+
get isModified(): boolean;
|
|
55
|
+
get isStockKeepingRequired(): boolean;
|
|
56
|
+
get priceDiscount(): number;
|
|
57
|
+
get discount(): number;
|
|
58
|
+
get taxes(): ReadonlyArray<Tax>;
|
|
59
|
+
get expiryMinutes(): number;
|
|
60
|
+
get description(): string | null;
|
|
61
|
+
get amount(): number;
|
|
62
|
+
get totalTax(): number;
|
|
63
|
+
get finalPrice(): number;
|
|
64
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { MERABILLS_ONLINE_PRICE_LIST_ID, amountFromScaledValue, quantityFromScaledValue, } from "./Constants";
|
|
2
|
+
import Ids from "./Ids";
|
|
3
|
+
// A list of packages being bought: a shopping cart, or what an order contains.
|
|
4
|
+
// Wire totals are authoritative; computed ones (below) use different rounding than Java
|
|
5
|
+
// PriceCalculation, so a UI shows totalAmount, not computedTotal.
|
|
6
|
+
class ShoppingList {
|
|
7
|
+
// Only ProtoMap calls this: it is the one place that sees a total still multiplied by
|
|
8
|
+
// Constants.AMOUNT_FACTOR.
|
|
9
|
+
static fromScaledValues(isFinal, autoAddDeliveryCharge, autoAddServiceCharge, inventoryLocationId, priceListId, scaledTotalAmountBeforeDiscount, scaledDiscount, existingItemCount, deletedItemCount, existingItems, deletedItems) {
|
|
10
|
+
return new ShoppingList(isFinal, autoAddDeliveryCharge, autoAddServiceCharge, inventoryLocationId, priceListId, amountFromScaledValue(scaledTotalAmountBeforeDiscount), amountFromScaledValue(scaledDiscount), existingItemCount, deletedItemCount, existingItems, deletedItems);
|
|
11
|
+
}
|
|
12
|
+
constructor(_isFinal, _autoAddDeliveryCharge, _autoAddServiceCharge, _inventoryLocationId, _priceListId, _totalAmountBeforeDiscount, _discount, _existingItemCount, _deletedItemCount, _existingItems, _deletedItems) {
|
|
13
|
+
this._isFinal = _isFinal;
|
|
14
|
+
this._autoAddDeliveryCharge = _autoAddDeliveryCharge;
|
|
15
|
+
this._autoAddServiceCharge = _autoAddServiceCharge;
|
|
16
|
+
this._inventoryLocationId = _inventoryLocationId;
|
|
17
|
+
this._priceListId = _priceListId;
|
|
18
|
+
this._totalAmountBeforeDiscount = _totalAmountBeforeDiscount;
|
|
19
|
+
this._discount = _discount;
|
|
20
|
+
this._existingItemCount = _existingItemCount;
|
|
21
|
+
this._deletedItemCount = _deletedItemCount;
|
|
22
|
+
this._existingItems = _existingItems;
|
|
23
|
+
this._deletedItems = _deletedItems;
|
|
24
|
+
}
|
|
25
|
+
// True once the customer is done editing, after which the business may edit it instead. Only a
|
|
26
|
+
// final list can have deleted items, and this is never unset.
|
|
27
|
+
get isFinal() {
|
|
28
|
+
return this._isFinal;
|
|
29
|
+
}
|
|
30
|
+
// True when the delivery charge is a line of its own, carrying the reserved package id
|
|
31
|
+
// ReservedPackage.DELIVERY_CHARGE_PACKAGE, rather than being added to the total
|
|
32
|
+
get autoAddDeliveryCharge() {
|
|
33
|
+
return this._autoAddDeliveryCharge;
|
|
34
|
+
}
|
|
35
|
+
// The same, for ReservedPackage.SERVICE_CHARGE_PACKAGE
|
|
36
|
+
get autoAddServiceCharge() {
|
|
37
|
+
return this._autoAddServiceCharge;
|
|
38
|
+
}
|
|
39
|
+
// Zero is the default location
|
|
40
|
+
get inventoryLocationId() {
|
|
41
|
+
return this._inventoryLocationId;
|
|
42
|
+
}
|
|
43
|
+
// The price list these prices came from, which is the one a storefront sells from: a cart with
|
|
44
|
+
// none uses Constants.MERABILLS_ONLINE_PRICE_LIST_ID, the list Catalog.priceList holds.
|
|
45
|
+
get priceListId() {
|
|
46
|
+
return this._priceListId;
|
|
47
|
+
}
|
|
48
|
+
get totalAmountBeforeDiscount() {
|
|
49
|
+
return this._totalAmountBeforeDiscount;
|
|
50
|
+
}
|
|
51
|
+
// The discount on the whole list, as opposed to a discount on one line of it
|
|
52
|
+
get discount() {
|
|
53
|
+
return this._discount;
|
|
54
|
+
}
|
|
55
|
+
// What the customer owes. Derived rather than sent, but derived from the authoritative totals
|
|
56
|
+
// above, so this is the number to display.
|
|
57
|
+
get totalAmount() {
|
|
58
|
+
return this._totalAmountBeforeDiscount - this._discount;
|
|
59
|
+
}
|
|
60
|
+
// Read from the wire and not from the length of the array below, because the protocol sends the
|
|
61
|
+
// count even when it does not send the items themselves
|
|
62
|
+
get existingItemCount() {
|
|
63
|
+
return this._existingItemCount;
|
|
64
|
+
}
|
|
65
|
+
get deletedItemCount() {
|
|
66
|
+
return this._deletedItemCount;
|
|
67
|
+
}
|
|
68
|
+
get itemCount() {
|
|
69
|
+
return this._existingItemCount + this._deletedItemCount;
|
|
70
|
+
}
|
|
71
|
+
get existingItems() {
|
|
72
|
+
return this._existingItems;
|
|
73
|
+
}
|
|
74
|
+
// The items that were in this list when it was made final and have since been deleted or
|
|
75
|
+
// replaced. Always empty until then.
|
|
76
|
+
get deletedItems() {
|
|
77
|
+
return this._deletedItems;
|
|
78
|
+
}
|
|
79
|
+
// Sum of finalPrice over existingItems. Not authoritative (rounded here, not by the server), and
|
|
80
|
+
// only covers the whole list when existingItems.length equals existingItemCount.
|
|
81
|
+
get computedTotal() {
|
|
82
|
+
let result = 0;
|
|
83
|
+
for (const item of this._existingItems)
|
|
84
|
+
result += item.finalPrice;
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
// The sum of the taxes of the items that are here, with the same caveat as computedTotal
|
|
88
|
+
get computedTotalTax() {
|
|
89
|
+
let result = 0;
|
|
90
|
+
for (const item of this._existingItems)
|
|
91
|
+
result += item.totalTax;
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// An empty cart, for a customer who has not put anything in one yet
|
|
96
|
+
ShoppingList.EMPTY = new ShoppingList(false, false, false, 0, MERABILLS_ONLINE_PRICE_LIST_ID, 0, 0, 0, 0, Object.freeze([]), Object.freeze([]));
|
|
97
|
+
export default ShoppingList;
|
|
98
|
+
// One line of a shopping list: the package being bought, how much of it, and at what price.
|
|
99
|
+
export class ShoppingListItem {
|
|
100
|
+
// Only ProtoMap calls this: it is the one place that sees a quantity multiplied by
|
|
101
|
+
// Constants.QUANTITY_FACTOR and prices multiplied by Constants.AMOUNT_FACTOR.
|
|
102
|
+
static fromScaledValues(packageId, scaledQuantity, scaledUnitPrice, shoppingListOrder, isOriginal, isModified, isStockKeepingRequired, scaledPriceDiscount, scaledDiscount, taxes, expiryMinutes, description) {
|
|
103
|
+
return new ShoppingListItem(packageId, quantityFromScaledValue(scaledQuantity), amountFromScaledValue(scaledUnitPrice), shoppingListOrder, isOriginal, isModified, isStockKeepingRequired, amountFromScaledValue(scaledPriceDiscount), amountFromScaledValue(scaledDiscount), taxes, expiryMinutes, description);
|
|
104
|
+
}
|
|
105
|
+
constructor(_packageId, _quantity, _unitPrice, _shoppingListOrder, _isOriginal, _isModified, _isStockKeepingRequired, _priceDiscount, _discount, _taxes, _expiryMinutes, _description) {
|
|
106
|
+
this._packageId = _packageId;
|
|
107
|
+
this._quantity = _quantity;
|
|
108
|
+
this._unitPrice = _unitPrice;
|
|
109
|
+
this._shoppingListOrder = _shoppingListOrder;
|
|
110
|
+
this._isOriginal = _isOriginal;
|
|
111
|
+
this._isModified = _isModified;
|
|
112
|
+
this._isStockKeepingRequired = _isStockKeepingRequired;
|
|
113
|
+
this._priceDiscount = _priceDiscount;
|
|
114
|
+
this._discount = _discount;
|
|
115
|
+
this._taxes = _taxes;
|
|
116
|
+
this._expiryMinutes = _expiryMinutes;
|
|
117
|
+
this._description = _description;
|
|
118
|
+
}
|
|
119
|
+
// The package being bought. Four ids are reserved for charge and summary lines rather than
|
|
120
|
+
// catalog packages and will not be found in the catalog - see isReservedPackage below.
|
|
121
|
+
get packageId() {
|
|
122
|
+
return this._packageId;
|
|
123
|
+
}
|
|
124
|
+
// True when this line is a charge/summary (delivery, service charge, discount, or total) rather
|
|
125
|
+
// than a catalog package. A UI must label such lines itself.
|
|
126
|
+
get isReservedPackage() {
|
|
127
|
+
return Ids.isReservedPackageId(this._packageId);
|
|
128
|
+
}
|
|
129
|
+
get quantity() {
|
|
130
|
+
return this._quantity;
|
|
131
|
+
}
|
|
132
|
+
// What one unit costs, which is the offer price when the package is on offer
|
|
133
|
+
get unitPrice() {
|
|
134
|
+
return this._unitPrice;
|
|
135
|
+
}
|
|
136
|
+
// Where this line sits in the list, from zero
|
|
137
|
+
get shoppingListOrder() {
|
|
138
|
+
return this._shoppingListOrder;
|
|
139
|
+
}
|
|
140
|
+
// True when this line was created before the list was made final
|
|
141
|
+
get isOriginal() {
|
|
142
|
+
return this._isOriginal;
|
|
143
|
+
}
|
|
144
|
+
// True when this line has been deleted or replaced since the list was made final
|
|
145
|
+
get isModified() {
|
|
146
|
+
return this._isModified;
|
|
147
|
+
}
|
|
148
|
+
get isStockKeepingRequired() {
|
|
149
|
+
return this._isStockKeepingRequired;
|
|
150
|
+
}
|
|
151
|
+
// What the offer takes off the unit price - the regular price of the package less its offer
|
|
152
|
+
// price - and not a discount on this line
|
|
153
|
+
get priceDiscount() {
|
|
154
|
+
return this._priceDiscount;
|
|
155
|
+
}
|
|
156
|
+
// The discount on this whole line, taxes included
|
|
157
|
+
get discount() {
|
|
158
|
+
return this._discount;
|
|
159
|
+
}
|
|
160
|
+
get taxes() {
|
|
161
|
+
return this._taxes;
|
|
162
|
+
}
|
|
163
|
+
// Minutes after purchase when this item expires, and zero when it does not
|
|
164
|
+
get expiryMinutes() {
|
|
165
|
+
return this._expiryMinutes;
|
|
166
|
+
}
|
|
167
|
+
get description() {
|
|
168
|
+
return this._description;
|
|
169
|
+
}
|
|
170
|
+
// What this line costs before tax and before its discount
|
|
171
|
+
get amount() {
|
|
172
|
+
return this._unitPrice * this._quantity;
|
|
173
|
+
}
|
|
174
|
+
// Tax on this line at the rates it was bought with. Computed here since the protocol sends
|
|
175
|
+
// rates, not amounts, and left unrounded (unlike the server's authoritative total).
|
|
176
|
+
get totalTax() {
|
|
177
|
+
const amount = this.amount;
|
|
178
|
+
let result = 0;
|
|
179
|
+
for (const tax of this._taxes)
|
|
180
|
+
result += (amount * tax.rate) / 100;
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
// What this line adds to the list: what it costs, plus the tax on it, less its discount. This is
|
|
184
|
+
// the definition ShoppingListItem.proto gives.
|
|
185
|
+
get finalPrice() {
|
|
186
|
+
return this.amount + this.totalTax - this._discount;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { BusinessSyncOutResponse as proto_BusinessSyncOutResponse } from "./generated/BusinessSyncOutResponse";
|
|
2
|
+
import { Message as proto_Message } from "./generated/Message";
|
|
3
|
+
import { ProfileSyncOutResponse as proto_ProfileSyncOutResponse } from "./generated/ProfileSyncOutResponse";
|
|
4
|
+
import AuthTokens from "./AuthTokens";
|
|
5
|
+
import Database from "./Database";
|
|
6
|
+
export default class SyncCache {
|
|
7
|
+
private readonly _database;
|
|
8
|
+
constructor(_database: Database);
|
|
9
|
+
readBusiness(containerName: string): Promise<proto_BusinessSyncOutResponse | null>;
|
|
10
|
+
writeBusiness(containerName: string, response: proto_BusinessSyncOutResponse): Promise<number>;
|
|
11
|
+
readProfile(containerName: string): Promise<proto_ProfileSyncOutResponse | null>;
|
|
12
|
+
writeProfile(containerName: string, response: proto_ProfileSyncOutResponse): Promise<number>;
|
|
13
|
+
readAuthTokens(containerName: string): Promise<AuthTokens | null>;
|
|
14
|
+
writeAuthTokens(containerName: string, authTokens: AuthTokens): Promise<void>;
|
|
15
|
+
readOrders(containerName: string): Promise<ReadonlyArray<proto_Message>>;
|
|
16
|
+
readMessageUpdateNumber(containerName: string): Promise<bigint>;
|
|
17
|
+
writeOrder(containerName: string, order: proto_Message): Promise<number>;
|
|
18
|
+
readCart(containerName: string): Promise<proto_Message | null>;
|
|
19
|
+
writeCart(containerName: string, cart: proto_Message): Promise<number>;
|
|
20
|
+
deleteCart(containerName: string): Promise<number>;
|
|
21
|
+
writeMessages(containerName: string, messages: ReadonlyArray<proto_Message>): Promise<number>;
|
|
22
|
+
private readAll;
|
|
23
|
+
private writeBlobs;
|
|
24
|
+
private write;
|
|
25
|
+
private getContainer;
|
|
26
|
+
private readonly _containers;
|
|
27
|
+
}
|
|
28
|
+
export declare const NO_DELETES: ReadonlyArray<bigint>;
|