@peabody-soft/mbs-model-ts 1.4.0 → 1.6.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/dist/Address.js +8 -11
- package/dist/Attachment.js +7 -8
- package/dist/AttachmentBaseUrl.js +10 -10
- package/dist/AuthTokens.js +12 -7
- package/dist/Business.js +19 -19
- package/dist/BusinessIdentifier.js +2 -2
- package/dist/BusinessLink.js +16 -16
- package/dist/BusinessProfile.js +4 -4
- package/dist/CartEditor.d.ts +10 -5
- package/dist/CartEditor.js +258 -180
- package/dist/Catalog.js +31 -29
- package/dist/Constants.js +10 -10
- package/dist/ContainerNames.js +10 -11
- package/dist/Entity.js +11 -9
- package/dist/Enums.d.ts +1 -1
- package/dist/Enums.js +4 -3
- package/dist/Exceptions.js +2 -2
- package/dist/GeneralSettings.d.ts +4 -2
- package/dist/GeneralSettings.js +30 -18
- package/dist/HttpStatusCodes.js +10 -11
- package/dist/Ids.d.ts +2 -0
- package/dist/Ids.js +28 -24
- package/dist/Item.js +6 -7
- package/dist/LatLong.js +3 -3
- package/dist/LiveData.js +6 -6
- package/dist/Measures.js +2 -2
- package/dist/Message.js +6 -5
- package/dist/MockDatabase.js +2 -2
- package/dist/Model.d.ts +5 -0
- package/dist/Model.js +400 -254
- package/dist/Order.js +20 -17
- package/dist/Package.js +7 -8
- package/dist/PackageIdentifier.js +2 -2
- package/dist/PaymentMethodDetail.js +4 -4
- package/dist/Photo.js +6 -7
- package/dist/Price.js +9 -6
- package/dist/PriceList.js +2 -2
- package/dist/Product.d.ts +5 -3
- package/dist/Product.js +26 -19
- package/dist/ProductCategory.js +3 -4
- package/dist/Profile.d.ts +1 -0
- package/dist/Profile.js +94 -8
- package/dist/ProtoMap.d.ts +18 -8
- package/dist/ProtoMap.js +451 -331
- package/dist/Routes.js +3 -3
- package/dist/ServiceExceptions.js +11 -12
- package/dist/ServiceProxy.js +19 -23
- package/dist/ShoppingList.d.ts +30 -1
- package/dist/ShoppingList.js +339 -47
- package/dist/SyncCache.d.ts +12 -0
- package/dist/SyncCache.js +136 -56
- package/dist/SyncKeys.js +8 -8
- package/dist/SyncState.js +5 -5
- package/dist/Tax.d.ts +12 -4
- package/dist/Tax.js +37 -13
- package/dist/TaxHelper.d.ts +12 -0
- package/dist/TaxHelper.js +85 -0
- package/dist/TaxType.d.ts +7 -0
- package/dist/TaxType.js +31 -0
- package/dist/UserProfile.js +4 -4
- package/dist/WorkingDays.js +15 -15
- package/dist/generated/AttachmentType.d.ts +19 -1
- package/dist/generated/AttachmentType.js +18 -0
- package/dist/generated/AuthTokens.d.ts +3 -1
- package/dist/generated/BusinessLink.d.ts +4 -1
- package/dist/generated/BusinessSyncInRequest.d.ts +11 -3
- package/dist/generated/BusinessSyncInResponse.d.ts +5 -4
- package/dist/generated/BusinessSyncOutRequest.d.ts +37 -10
- package/dist/generated/BusinessSyncOutRequest.js +42 -29
- package/dist/generated/BusinessSyncOutResponse.d.ts +14 -1
- package/dist/generated/Configuration.d.ts +2 -1
- package/dist/generated/CreateUserRequest.d.ts +8 -2
- package/dist/generated/Entity.d.ts +7 -3
- package/dist/generated/GeneralSettings.d.ts +14 -4
- package/dist/generated/GeneralSettings.js +9 -1
- package/dist/generated/Message.d.ts +4 -2
- package/dist/generated/Product.d.ts +10 -1
- package/dist/generated/Product.js +9 -1
- package/dist/generated/ProfileSyncOutRequest.d.ts +17 -1
- package/dist/generated/ProfileSyncOutResponse.d.ts +8 -3
- package/dist/generated/SalesOrderPayload.d.ts +7 -2
- package/dist/generated/ShoppingList.d.ts +6 -3
- package/dist/generated/ShoppingListItem.d.ts +21 -6
- package/dist/generated/Tax.d.ts +4 -4
- package/dist/generated/Tax.js +7 -8
- package/dist/generated/WorkingHoursRange.d.ts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +11 -10
- package/package.json +55 -55
- package/dist/generated/TaxType.d.ts +0 -25
- package/dist/generated/TaxType.js +0 -30
package/dist/Catalog.js
CHANGED
|
@@ -1,39 +1,40 @@
|
|
|
1
1
|
import { Constants as proto_Constants } from "./generated/Constants";
|
|
2
2
|
import { EntityHeader } from "./Entity";
|
|
3
3
|
import ProductCategory from "./ProductCategory";
|
|
4
|
-
// The catalog of a business: its categories
|
|
5
|
-
//
|
|
4
|
+
// The catalog of a business: its categories and the products in them. Not an entity and not on the
|
|
5
|
+
// wire. The sync layer rebuilds it from the flat item entities of a sync response.
|
|
6
6
|
class Catalog {
|
|
7
7
|
constructor(categories, products, _priceList) {
|
|
8
8
|
this._priceList = _priceList;
|
|
9
9
|
this._categoryMap = new Map();
|
|
10
10
|
this._productMap = new Map();
|
|
11
11
|
this._packageMap = new Map();
|
|
12
|
-
// A dummy category
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
// category, when nothing buyable ends up in it.
|
|
12
|
+
// A dummy category for products whose parentItemId is Constants.ENTITY_ID_NULL. Its id is also
|
|
13
|
+
// ENTITY_ID_NULL, so getCategory(product.productCategoryId) resolves it like a real category.
|
|
14
|
+
// It is left out below like any other category when it has no products.
|
|
16
15
|
const uncategorized = new ProductCategory(new EntityHeader(BigInt(proto_Constants.ENTITY_ID_NULL), 0n, 0n, 0n, 0n), "", null, BigInt(proto_Constants.ENTITY_ID_NULL), false);
|
|
17
|
-
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
16
|
+
// Only a buyable product is part of a catalog: enabled, not sold only offline, with at least one
|
|
17
|
+
// buyable package. Any other is left out of products, getProduct and its categories, and its
|
|
18
|
+
// packages are unreachable by id. Enforced here so no builder can expose a product that cannot
|
|
19
|
+
// be bought.
|
|
20
|
+
const buyableProducts = [];
|
|
21
21
|
const productsByCategory = new Map();
|
|
22
|
-
for (const product of
|
|
22
|
+
for (const product of products) {
|
|
23
|
+
if (!product.isBuyable)
|
|
24
|
+
continue;
|
|
25
|
+
buyableProducts.push(product);
|
|
23
26
|
this._productMap.set(product.id, product);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
productsOfCategory.push(product);
|
|
30
|
-
}
|
|
27
|
+
const productsOfCategory = productsByCategory.get(product.productCategoryId);
|
|
28
|
+
if (productsOfCategory === undefined)
|
|
29
|
+
productsByCategory.set(product.productCategoryId, [product]);
|
|
30
|
+
else
|
|
31
|
+
productsOfCategory.push(product);
|
|
31
32
|
for (const pkg of product.packages)
|
|
32
33
|
this._packageMap.set(pkg.id, pkg);
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
-
//
|
|
36
|
-
//
|
|
35
|
+
this._products = Object.freeze(buyableProducts);
|
|
36
|
+
// A category that no buyable product reached is left out rather than shown empty. This covers
|
|
37
|
+
// the dummy too.
|
|
37
38
|
const nonEmptyCategories = [];
|
|
38
39
|
for (const category of [...categories, uncategorized]) {
|
|
39
40
|
const categoryProducts = productsByCategory.get(category.id);
|
|
@@ -50,13 +51,13 @@ class Catalog {
|
|
|
50
51
|
get categories() {
|
|
51
52
|
return this._categories;
|
|
52
53
|
}
|
|
53
|
-
// Every product of the business,
|
|
54
|
+
// Every buyable product of the business, in a category or not, in no particular order
|
|
54
55
|
get products() {
|
|
55
56
|
return this._products;
|
|
56
57
|
}
|
|
57
|
-
// The one price list a storefront sells from
|
|
58
|
-
//
|
|
59
|
-
//
|
|
58
|
+
// The one price list a storefront sells from (MeraBills Online). Null until it arrives. Every
|
|
59
|
+
// price in this catalog belongs to it, and prices in other lists are left out. A shopping list
|
|
60
|
+
// names this list, or falls back to its id when it has none set.
|
|
60
61
|
get priceList() {
|
|
61
62
|
return this._priceList;
|
|
62
63
|
}
|
|
@@ -69,16 +70,17 @@ class Catalog {
|
|
|
69
70
|
getCategory(productCategoryId) {
|
|
70
71
|
return this._categoryMap.get(productCategoryId) ?? null;
|
|
71
72
|
}
|
|
73
|
+
// Null for an unknown id, and for a product that is not buyable, which this catalog does not hold
|
|
72
74
|
getProduct(productId) {
|
|
73
75
|
return this._productMap.get(productId) ?? null;
|
|
74
76
|
}
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
+
// Null for the four reserved package ids a shopping list uses for its charge and summary lines
|
|
78
|
+
// (see Ids.isReservedPackageId), and for a package whose product was deleted or is not buyable
|
|
77
79
|
getPackage(packageId) {
|
|
78
80
|
return this._packageMap.get(packageId) ?? null;
|
|
79
81
|
}
|
|
80
|
-
// Display comparator for packages, matching the merchant app's PackageComparator
|
|
81
|
-
// a storefront
|
|
82
|
+
// Display comparator for packages, matching the merchant app's PackageComparator minus the
|
|
83
|
+
// clauses a storefront cannot exercise (disabled packages and the purchase price list, neither sent)
|
|
82
84
|
static comparePackages(left, right) {
|
|
83
85
|
const byName = Catalog.compareNames(left.name, right.name);
|
|
84
86
|
if (byName !== 0)
|
package/dist/Constants.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { Constants as proto_Constants } from "./generated/Constants";
|
|
2
2
|
import Ids from "./Ids";
|
|
3
3
|
// The protocol's limits and scaling factors, and the wire-to-UI value conversions.
|
|
4
|
-
// Limits are re-exported
|
|
4
|
+
// Limits are re-exported so a Java constant has only one place to be wrong.
|
|
5
5
|
export { Constants } from "./generated/Constants";
|
|
6
6
|
// The id of a built-in price list, from the low part Constants carries for it:
|
|
7
7
|
// DEFAULT_SALE_PRICE_LIST, DEFAULT_PURCHASE_PRICE_LIST, MERABILLS_ONLINE_PRICE_LIST,
|
|
8
8
|
// AMAZON_SELLER_PRICE_LIST, FACEBOOK_MARKETPLACE_PRICE_LIST or WHATSAPP_BUSINESS_PRICE_LIST. These
|
|
9
|
-
// are the six ids of Java PriceListIds, built the way
|
|
10
|
-
//
|
|
9
|
+
// are the six ids of Java PriceListIds, built the same way. Only the low part is a protocol
|
|
10
|
+
// constant, since a 64-bit id does not fit a protobuf enum value.
|
|
11
11
|
export function buildPriceListId(priceList) {
|
|
12
12
|
return Ids.buildId(proto_Constants.PRICE_LIST_ENTITY_TYPE_ID, BigInt(priceList));
|
|
13
13
|
}
|
|
14
|
-
// The only price list this library reads. A business prices
|
|
15
|
-
//
|
|
16
|
-
//
|
|
14
|
+
// The only price list this library reads. A business prices a package in several lists (over the
|
|
15
|
+
// counter, on a marketplace), and only this one is the storefront's. Prices in other lists are
|
|
16
|
+
// skipped, see ProtoMap.buildBusiness.
|
|
17
17
|
export const MERABILLS_ONLINE_PRICE_LIST_ID = buildPriceListId(proto_Constants.MERABILLS_ONLINE_PRICE_LIST);
|
|
18
|
-
// The largest amount the protocol can carry (Java Transaction.MAX_AMOUNT)
|
|
19
|
-
// a protobuf enum value. Unscaled it
|
|
18
|
+
// The largest amount the protocol can carry (Java Transaction.MAX_AMOUNT). Kept here because it does
|
|
19
|
+
// not fit a protobuf enum value. Unscaled it is well below 2^53, so an amount is safe as a number.
|
|
20
20
|
export const MAX_SCALED_AMOUNT = 17592186044415n;
|
|
21
21
|
// An amount, price or discount travels multiplied by Constants.AMOUNT_FACTOR, bounded by
|
|
22
22
|
// MAX_SCALED_AMOUNT, so it's safe as a number even though it arrives as an int64.
|
|
@@ -33,8 +33,8 @@ export function quantityFromScaledValue(scaledQuantity) {
|
|
|
33
33
|
export function quantityToScaledValue(quantity) {
|
|
34
34
|
return Math.round(quantity * proto_Constants.QUANTITY_FACTOR);
|
|
35
35
|
}
|
|
36
|
-
// A tax rate travels multiplied by Constants.TAX_RATE_FACTOR, so 18% arrives as 1800.
|
|
37
|
-
//
|
|
36
|
+
// A tax rate travels multiplied by Constants.TAX_RATE_FACTOR, so 18% arrives as 1800. The result is
|
|
37
|
+
// a percentage (18, not 0.18).
|
|
38
38
|
export function taxRateFromScaledValue(scaledTaxRate) {
|
|
39
39
|
return scaledTaxRate / (proto_Constants.TAX_RATE_FACTOR / 100);
|
|
40
40
|
}
|
package/dist/ContainerNames.js
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
1
|
+
// Names of the local store's containers. A business container prefixes Business.businessId, a
|
|
2
|
+
// profile container the subject id. The prefixes keep the two id spaces from colliding.
|
|
3
3
|
// One business, holding that business and everything in its business database
|
|
4
4
|
export function forBusiness(nameSuffix) {
|
|
5
5
|
return `${VERSION_PREFIX}${BUSINESS_PREFIX}${nameSuffix}`;
|
|
6
6
|
}
|
|
7
|
-
// One signed in subject
|
|
8
|
-
//
|
|
7
|
+
// One signed in subject: their profile database and the tokens that sign their requests. Several
|
|
8
|
+
// can coexist, so signing back in after a sign-out is incremental.
|
|
9
9
|
export function forProfile(nameSuffix) {
|
|
10
10
|
return `${VERSION_PREFIX}${PROFILE_PREFIX}${nameSuffix}`;
|
|
11
11
|
}
|
|
12
|
-
// Every name carries the layout version of
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
// clear a store it did not know had changed, and a half-understood container is worse than no cache.
|
|
12
|
+
// Every name carries the layout version of its contents, so a change in how a container is stored
|
|
13
|
+
// needs no migration: the new version uses names nothing has written, and the old containers stay
|
|
14
|
+
// inert until deleted. Bump it whenever a stored blob changes meaning, since callers cannot be
|
|
15
|
+
// relied on to clear a store and a half-understood container is worse than no cache.
|
|
17
16
|
const VERSION_PREFIX = "V1.";
|
|
18
|
-
// Neither id space is this library's to constrain, so a subject id
|
|
19
|
-
// id would
|
|
17
|
+
// Neither id space is this library's to constrain, so without a prefix a subject id equal to a
|
|
18
|
+
// business id would put a profile and a catalog in one container
|
|
20
19
|
const BUSINESS_PREFIX = "b.";
|
|
21
20
|
const PROFILE_PREFIX = "p.";
|
package/dist/Entity.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Constants as proto_Constants } from "./generated/Constants";
|
|
2
2
|
import Ids from "./Ids";
|
|
3
|
-
// Something the protocol syncs one at a time: an id, create
|
|
4
|
-
// the database it was last updated in. Rebuilt from the wire
|
|
5
|
-
//
|
|
3
|
+
// Something the protocol syncs one at a time: an id, create and update times, an update number, and
|
|
4
|
+
// the database it was last updated in. Rebuilt from the wire, never edited in place. The only
|
|
5
|
+
// mutable field is parent, set once containment is rebuilt after a sync (nothing nests on the wire).
|
|
6
6
|
class Entity {
|
|
7
7
|
constructor(header) {
|
|
8
8
|
this._parent = null;
|
|
@@ -17,12 +17,13 @@ class Entity {
|
|
|
17
17
|
get updatedAt() {
|
|
18
18
|
return new Date(Number(this._header.updatedAt));
|
|
19
19
|
}
|
|
20
|
-
//
|
|
20
|
+
// Increases monotonically, comparable only within one entity type and database. Basis of a sync cursor.
|
|
21
21
|
get updateNumber() {
|
|
22
22
|
return this._header.updateNumber;
|
|
23
23
|
}
|
|
24
|
-
// The database this entity was last updated in (Constants.MASTER_DB_ID
|
|
25
|
-
// to avoid echoing a store's own changes back. Business entities only
|
|
24
|
+
// The database this entity was last updated in (Constants.MASTER_DB_ID is the server). Sync out
|
|
25
|
+
// uses it to avoid echoing a store's own changes back. Business entities only; always
|
|
26
|
+
// ENTITY_ID_NULL on profile entities.
|
|
26
27
|
get updateInfo() {
|
|
27
28
|
return this._header.updateInfo;
|
|
28
29
|
}
|
|
@@ -34,7 +35,8 @@ class Entity {
|
|
|
34
35
|
get updateType() {
|
|
35
36
|
return Number(this._header.updateNumber & Entity.UPDATE_TYPE_MASK);
|
|
36
37
|
}
|
|
37
|
-
// A deleted entity is a tombstone:
|
|
38
|
+
// A deleted entity is a tombstone: it carries what the entity was when deleted. A UI never reaches
|
|
39
|
+
// one, except an order whose message is deleted, which is an order the business has completed.
|
|
38
40
|
get isDeleted() {
|
|
39
41
|
return this.updateType === proto_Constants.UPDATE_TYPE_DELETED;
|
|
40
42
|
}
|
|
@@ -49,8 +51,8 @@ class Entity {
|
|
|
49
51
|
}
|
|
50
52
|
Entity.UPDATE_TYPE_MASK = BigInt(proto_Constants.UPDATE_TYPE_MASK);
|
|
51
53
|
export default Entity;
|
|
52
|
-
// The fields of the Entity message every entity carries
|
|
53
|
-
// bigint and
|
|
54
|
+
// The fields of the Entity message every entity carries. Passed as one value because they are all
|
|
55
|
+
// bigint and could be transposed silently at a call site.
|
|
54
56
|
export class EntityHeader {
|
|
55
57
|
constructor(id, createdAt, updatedAt, updateNumber, updateInfo) {
|
|
56
58
|
this.id = id;
|
package/dist/Enums.d.ts
CHANGED
|
@@ -12,5 +12,5 @@ export { ProductType } from "./generated/ProductType";
|
|
|
12
12
|
export { ReservedPackage } from "./generated/ReservedPackage";
|
|
13
13
|
export { Role } from "./generated/Role";
|
|
14
14
|
export { TaskStatus } from "./generated/TaskStatus";
|
|
15
|
-
export { TaxType } from "./
|
|
15
|
+
export { TaxType } from "./TaxType";
|
|
16
16
|
export { WeightUnit } from "./generated/WeightUnit";
|
package/dist/Enums.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
// Every enum of the protocol, re-exported
|
|
2
|
-
//
|
|
1
|
+
// Every enum of the protocol, re-exported so their Java-defined numeric ids have only one place to
|
|
2
|
+
// be wrong. The list also records which enums are part of the library's surface.
|
|
3
|
+
// TaxType is the exception: the protocol does not carry it, so it is defined in TaxType.ts.
|
|
3
4
|
export { AddressType } from "./generated/AddressType";
|
|
4
5
|
export { AttachmentType } from "./generated/AttachmentType";
|
|
5
6
|
export { AuthenticationMethod } from "./generated/AuthenticationMethod";
|
|
@@ -14,5 +15,5 @@ export { ProductType } from "./generated/ProductType";
|
|
|
14
15
|
export { ReservedPackage } from "./generated/ReservedPackage";
|
|
15
16
|
export { Role } from "./generated/Role";
|
|
16
17
|
export { TaskStatus } from "./generated/TaskStatus";
|
|
17
|
-
export { TaxType } from "./
|
|
18
|
+
export { TaxType } from "./TaxType";
|
|
18
19
|
export { WeightUnit } from "./generated/WeightUnit";
|
package/dist/Exceptions.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// The two failures this library raises
|
|
2
|
-
// from
|
|
1
|
+
// The two failures this library raises. Both are programming errors that a UI does not recover
|
|
2
|
+
// from. A sync failure surfaces as a rejected promise.
|
|
3
3
|
// A caller passed something this library cannot work with
|
|
4
4
|
export class InvalidArgumentException extends Error {
|
|
5
5
|
}
|
|
@@ -23,8 +23,9 @@ export default class GeneralSettings {
|
|
|
23
23
|
private readonly _googleBusinessCategoryId;
|
|
24
24
|
private readonly _googleBusinessCategoryName;
|
|
25
25
|
private readonly _onlineStoreThemeId;
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
private readonly _onlineShoppingEnabled;
|
|
27
|
+
static fromScaledValues(paymentMethodDetails: ReadonlyArray<PaymentMethodDetail>, customerServicePhone: string | null, isWhatsAppSupported: boolean, isSmsSupported: boolean, businessAddresses: AddressList, businessIdentifiers: ReadonlyArray<BusinessIdentifier>, fulfillmentModes: ReadonlyArray<proto_FulfillmentMode>, scaledDeliveryCharge: bigint, deliveryChargeTaxes: ReadonlyArray<Tax>, scaledFreeDeliveryTotal: bigint, deliveryRadiusKilometres: number, storeTagline: string | null, workingDays: WorkingDays, primaryStoreLocation: LatLong | null, googleBusinessCategoryId: string | null, googleBusinessCategoryName: string | null, onlineStoreThemeId: string | null, onlineShoppingEnabled: boolean): GeneralSettings;
|
|
28
|
+
constructor(_paymentMethodDetails: ReadonlyArray<PaymentMethodDetail>, _customerServicePhone: string | null, _isWhatsAppSupported: boolean, _isSmsSupported: boolean, _businessAddresses: AddressList, _businessIdentifiers: ReadonlyArray<BusinessIdentifier>, _fulfillmentModes: ReadonlyArray<proto_FulfillmentMode>, _deliveryCharge: number, _deliveryChargeTaxes: ReadonlyArray<Tax>, _freeDeliveryTotal: number, _deliveryRadiusKilometres: number, _storeTagline: string | null, _workingDays: WorkingDays, _primaryStoreLocation: LatLong | null, _googleBusinessCategoryId: string | null, _googleBusinessCategoryName: string | null, _onlineStoreThemeId: string | null, _onlineShoppingEnabled: boolean);
|
|
28
29
|
get paymentMethodDetails(): ReadonlyArray<PaymentMethodDetail>;
|
|
29
30
|
get customerServicePhone(): string | null;
|
|
30
31
|
get isWhatsAppSupported(): boolean;
|
|
@@ -42,5 +43,6 @@ export default class GeneralSettings {
|
|
|
42
43
|
get googleBusinessCategoryId(): string | null;
|
|
43
44
|
get googleBusinessCategoryName(): string | null;
|
|
44
45
|
get onlineStoreThemeId(): string | null;
|
|
46
|
+
get onlineShoppingEnabled(): boolean;
|
|
45
47
|
static readonly EMPTY: GeneralSettings;
|
|
46
48
|
}
|
package/dist/GeneralSettings.js
CHANGED
|
@@ -3,14 +3,14 @@ import { amountFromScaledValue } from "./Constants";
|
|
|
3
3
|
import WorkingDays from "./WorkingDays";
|
|
4
4
|
// The publicly visible settings of a business: tagline, contact info, location, fulfillment,
|
|
5
5
|
// payment and delivery options, and how its online store is presented.
|
|
6
|
-
// Not an entity
|
|
6
|
+
// Not an entity: it is unwrapped from the one public Configuration a storefront is sent, so
|
|
7
|
+
// merchant-only fields are absent.
|
|
7
8
|
class GeneralSettings {
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return new GeneralSettings(paymentMethodDetails, customerServicePhone, isWhatsAppSupported, isSmsSupported, businessAddresses, businessIdentifiers, fulfillmentModes, amountFromScaledValue(scaledDeliveryCharge), deliveryChargeTaxes, amountFromScaledValue(scaledFreeDeliveryTotal), deliveryRadiusKilometres, storeTagline, workingDays, primaryStoreLocation, googleBusinessCategoryId, googleBusinessCategoryName, onlineStoreThemeId);
|
|
9
|
+
// For ProtoMap, which sees amounts still multiplied by Constants.AMOUNT_FACTOR.
|
|
10
|
+
static fromScaledValues(paymentMethodDetails, customerServicePhone, isWhatsAppSupported, isSmsSupported, businessAddresses, businessIdentifiers, fulfillmentModes, scaledDeliveryCharge, deliveryChargeTaxes, scaledFreeDeliveryTotal, deliveryRadiusKilometres, storeTagline, workingDays, primaryStoreLocation, googleBusinessCategoryId, googleBusinessCategoryName, onlineStoreThemeId, onlineShoppingEnabled) {
|
|
11
|
+
return new GeneralSettings(paymentMethodDetails, customerServicePhone, isWhatsAppSupported, isSmsSupported, businessAddresses, businessIdentifiers, fulfillmentModes, amountFromScaledValue(scaledDeliveryCharge), deliveryChargeTaxes, amountFromScaledValue(scaledFreeDeliveryTotal), deliveryRadiusKilometres, storeTagline, workingDays, primaryStoreLocation, googleBusinessCategoryId, googleBusinessCategoryName, onlineStoreThemeId, onlineShoppingEnabled);
|
|
12
12
|
}
|
|
13
|
-
constructor(_paymentMethodDetails, _customerServicePhone, _isWhatsAppSupported, _isSmsSupported, _businessAddresses, _businessIdentifiers, _fulfillmentModes, _deliveryCharge, _deliveryChargeTaxes, _freeDeliveryTotal, _deliveryRadiusKilometres, _storeTagline, _workingDays, _primaryStoreLocation, _googleBusinessCategoryId, _googleBusinessCategoryName, _onlineStoreThemeId) {
|
|
13
|
+
constructor(_paymentMethodDetails, _customerServicePhone, _isWhatsAppSupported, _isSmsSupported, _businessAddresses, _businessIdentifiers, _fulfillmentModes, _deliveryCharge, _deliveryChargeTaxes, _freeDeliveryTotal, _deliveryRadiusKilometres, _storeTagline, _workingDays, _primaryStoreLocation, _googleBusinessCategoryId, _googleBusinessCategoryName, _onlineStoreThemeId, _onlineShoppingEnabled) {
|
|
14
14
|
this._paymentMethodDetails = _paymentMethodDetails;
|
|
15
15
|
this._customerServicePhone = _customerServicePhone;
|
|
16
16
|
this._isWhatsAppSupported = _isWhatsAppSupported;
|
|
@@ -28,6 +28,7 @@ class GeneralSettings {
|
|
|
28
28
|
this._googleBusinessCategoryId = _googleBusinessCategoryId;
|
|
29
29
|
this._googleBusinessCategoryName = _googleBusinessCategoryName;
|
|
30
30
|
this._onlineStoreThemeId = _onlineStoreThemeId;
|
|
31
|
+
this._onlineShoppingEnabled = _onlineShoppingEnabled;
|
|
31
32
|
}
|
|
32
33
|
get paymentMethodDetails() {
|
|
33
34
|
return this._paymentMethodDetails;
|
|
@@ -52,15 +53,18 @@ class GeneralSettings {
|
|
|
52
53
|
get fulfillmentModes() {
|
|
53
54
|
return this._fulfillmentModes;
|
|
54
55
|
}
|
|
56
|
+
// What delivery costs, including the taxes in deliveryChargeTaxes, as a package price includes
|
|
57
|
+
// its product's taxes. CartEditor takes them out when it puts the charge in a list.
|
|
55
58
|
get deliveryCharge() {
|
|
56
59
|
return this._deliveryCharge;
|
|
57
60
|
}
|
|
58
|
-
// The taxes
|
|
59
|
-
// Constants.MAX_TAXES
|
|
61
|
+
// The taxes included in the delivery charge. They are the business's own, at most
|
|
62
|
+
// Constants.MAX_TAXES. Empty means the charge includes no tax.
|
|
60
63
|
get deliveryChargeTaxes() {
|
|
61
64
|
return this._deliveryChargeTaxes;
|
|
62
65
|
}
|
|
63
|
-
// Order total at or above which delivery is free.
|
|
66
|
+
// Order total at or above which delivery is free. Measured on the goods including taxes, without
|
|
67
|
+
// the delivery charge. Zero means delivery is never free.
|
|
64
68
|
get freeDeliveryTotal() {
|
|
65
69
|
return this._freeDeliveryTotal;
|
|
66
70
|
}
|
|
@@ -71,29 +75,37 @@ class GeneralSettings {
|
|
|
71
75
|
get storeTagline() {
|
|
72
76
|
return this._storeTagline;
|
|
73
77
|
}
|
|
74
|
-
// Absent working days default to WorkingDays.ALL_DAYS (Java's default), never
|
|
78
|
+
// Absent working days default to WorkingDays.ALL_DAYS (Java's default), so this is never null.
|
|
75
79
|
get workingDays() {
|
|
76
80
|
return this._workingDays;
|
|
77
81
|
}
|
|
78
|
-
// Where this business is: the coordinates of the first of businessAddresses. Null when
|
|
79
|
-
//
|
|
82
|
+
// Where this business is: the coordinates of the first of businessAddresses. Null when not
|
|
83
|
+
// published.
|
|
80
84
|
get primaryStoreLocation() {
|
|
81
85
|
return this._primaryStoreLocation;
|
|
82
86
|
}
|
|
83
|
-
// What kind of business this is, as its Google Business Profile category
|
|
84
|
-
//
|
|
87
|
+
// What kind of business this is, as its Google Business Profile category (for example "Bakery").
|
|
88
|
+
// Show the name, match on the stable id.
|
|
85
89
|
get googleBusinessCategoryId() {
|
|
86
90
|
return this._googleBusinessCategoryId;
|
|
87
91
|
}
|
|
88
92
|
get googleBusinessCategoryName() {
|
|
89
93
|
return this._googleBusinessCategoryName;
|
|
90
94
|
}
|
|
91
|
-
// Which of
|
|
92
|
-
//
|
|
95
|
+
// Which of the storefront's own themes this business picked. What an id means is up to the
|
|
96
|
+
// storefront, not this library. Null when none was picked.
|
|
93
97
|
get onlineStoreThemeId() {
|
|
94
98
|
return this._onlineStoreThemeId;
|
|
95
99
|
}
|
|
100
|
+
// Whether the business has turned online shopping on. The server does not refuse a business that
|
|
101
|
+
// has not. Model does, with a NotFoundException, after reading everything it is sent, when the
|
|
102
|
+
// settings it holds do not say so or it holds none (see Model.setBusinessId). Also false for
|
|
103
|
+
// GeneralSettings.EMPTY.
|
|
104
|
+
get onlineShoppingEnabled() {
|
|
105
|
+
return this._onlineShoppingEnabled;
|
|
106
|
+
}
|
|
96
107
|
}
|
|
97
|
-
// A business with no published public settings
|
|
98
|
-
|
|
108
|
+
// A business with no published public settings. Used instead of null so every field is already
|
|
109
|
+
// the protocol's empty value.
|
|
110
|
+
GeneralSettings.EMPTY = new GeneralSettings(Object.freeze([]), null, false, false, AddressList.EMPTY, Object.freeze([]), Object.freeze([]), 0, Object.freeze([]), 0, 0, null, WorkingDays.ALL_DAYS, null, null, null, null, false);
|
|
99
111
|
export default GeneralSettings;
|
package/dist/HttpStatusCodes.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { BadRequestException, ConflictException, InternalServerException, MethodNotAllowedException, NotFoundException, ServiceException, ServiceUnavailableException, UnauthorizedException, UpgradeRequiredException, } from "./ServiceExceptions";
|
|
2
|
-
// Which failure a status code stands for
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// Everything from 300 up
|
|
6
|
-
//
|
|
7
|
-
// means the call did not happen.
|
|
2
|
+
// Which failure a status code stands for. The classes are in ServiceExceptions.ts. The split matches
|
|
3
|
+
// Java's HttpStatusCodes and exception package, so the table of what each code means has one home
|
|
4
|
+
// in each client.
|
|
5
|
+
// Everything from 300 up (Java's HttpURLConnection.HTTP_MULT_CHOICE). A redirect counts as a
|
|
6
|
+
// failure because this client follows none, so being sent elsewhere means the call did not happen.
|
|
8
7
|
export function isError(httpStatusCode) {
|
|
9
8
|
return httpStatusCode >= LOWEST_ERROR_STATUS_CODE;
|
|
10
9
|
}
|
|
11
|
-
// Raises the failure a status code stands for, and does nothing
|
|
12
|
-
// A code with no class of its own
|
|
13
|
-
//
|
|
10
|
+
// Raises the failure a status code stands for, and does nothing for a code that is not an error.
|
|
11
|
+
// A code with no class of its own becomes a ServiceException carrying the code, so a new server
|
|
12
|
+
// response cannot pass as a success.
|
|
14
13
|
export function throwOnError(httpStatusCode, message) {
|
|
15
14
|
if (!isError(httpStatusCode))
|
|
16
15
|
return;
|
|
@@ -20,8 +19,8 @@ export function throwOnError(httpStatusCode, message) {
|
|
|
20
19
|
throw create(message);
|
|
21
20
|
}
|
|
22
21
|
const LOWEST_ERROR_STATUS_CODE = 300;
|
|
23
|
-
// Java builds this by reflection over a map of classes
|
|
24
|
-
//
|
|
22
|
+
// Java builds this by reflection over a map of classes. Here each entry constructs its own class,
|
|
23
|
+
// which keeps it checked at compile time.
|
|
25
24
|
const EXCEPTIONS = new Map([
|
|
26
25
|
[BadRequestException.STATUS_CODE, (message) => new BadRequestException(message)],
|
|
27
26
|
[UnauthorizedException.STATUS_CODE, (message) => new UnauthorizedException(message)],
|
package/dist/Ids.d.ts
CHANGED
|
@@ -7,11 +7,13 @@ export default class Ids {
|
|
|
7
7
|
static isReservedPackageId(packageId: bigint): boolean;
|
|
8
8
|
static toStorageHexString(id: bigint): string;
|
|
9
9
|
static toOrderNumberString(orderId: bigint): string;
|
|
10
|
+
static getSyncCursorBlobId(key: number): bigint;
|
|
10
11
|
static readonly ENTITY_TYPE_BIT_SHIFT: bigint;
|
|
11
12
|
static readonly ID_MASK: bigint;
|
|
12
13
|
static readonly GENERAL_SETTINGS_CONFIGURATION_ID: bigint;
|
|
13
14
|
static readonly ATTACHMENT_BASE_URL_BLOB_ID: bigint;
|
|
14
15
|
static readonly AUTH_TOKENS_BLOB_ID: bigint;
|
|
16
|
+
private static readonly SYNC_CURSOR_BLOB_ID_BASE;
|
|
15
17
|
private static readonly UNSIGNED_64_BIT_MASK;
|
|
16
18
|
private static readonly UNSIGNED_32_BIT_MASK;
|
|
17
19
|
}
|
package/dist/Ids.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Constants as proto_Constants } from "./generated/Constants";
|
|
2
2
|
import { ReservedPackage as proto_ReservedPackage } from "./generated/ReservedPackage";
|
|
3
|
-
//
|
|
4
|
-
// Some ids below are
|
|
3
|
+
// All knowledge of entity id layout lives here, since a 64-bit shift in number arithmetic silently loses the entity type.
|
|
4
|
+
// Some ids below are negative local-store blob ids, which cannot collide with a real id (its sign bit is clear).
|
|
5
5
|
class Ids {
|
|
6
6
|
// The most significant byte of an id: one of the *_ENTITY_TYPE_ID values of Constants.
|
|
7
7
|
static getEntityTypeId(id) {
|
|
@@ -14,20 +14,16 @@ class Ids {
|
|
|
14
14
|
static buildId(entityTypeId, lowPart) {
|
|
15
15
|
return (BigInt(entityTypeId) << Ids.ENTITY_TYPE_BIT_SHIFT) | (lowPart & Ids.ID_MASK);
|
|
16
16
|
}
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
// sync in answers with an update number and no id, so a cart the server named could not be stored
|
|
21
|
-
// here at all. One link therefore has one cart, and creating it twice is impossible by
|
|
22
|
-
// construction rather than by a check.
|
|
17
|
+
// The cart's message id: the business link id with the entity type swapped for the message one
|
|
18
|
+
// (Java Message.getPartyPreferencesMessageId). Derived because a sync in answers with an update
|
|
19
|
+
// number and no id, so a cart the server named could not be stored. One link has one cart.
|
|
23
20
|
static getPartyPreferencesMessageId(businessLinkId) {
|
|
24
21
|
return Ids.buildId(proto_Constants.MESSAGE_ENTITY_TYPE_ID, Ids.getLowPart(businessLinkId));
|
|
25
22
|
}
|
|
26
|
-
// A fresh id for an entity this client
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
// is a thing a caller could be handed.
|
|
23
|
+
// A fresh id for an entity this client creates (Java Entity.getRandomLongForId): random, never
|
|
24
|
+
// in 0-255, which every entity type reserves. Only the low part is drawn, as buildId masks the
|
|
25
|
+
// rest off. It uses the cryptographic generator because a Math.random id is guessable and a
|
|
26
|
+
// message id can be handed to a caller.
|
|
31
27
|
static getNewId(entityTypeId) {
|
|
32
28
|
for (;;) {
|
|
33
29
|
const bytes = new Uint8Array(8);
|
|
@@ -50,29 +46,37 @@ class Ids {
|
|
|
50
46
|
static toStorageHexString(id) {
|
|
51
47
|
return (id & Ids.UNSIGNED_64_BIT_MASK).toString(16).toUpperCase().padStart(16, "0");
|
|
52
48
|
}
|
|
53
|
-
// The number an order is shown under: the
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
// twos complement; masking here answers the same string without the sign getting in the way.
|
|
60
|
-
// The merchant app prefixes the word "Order"; whether to do that is a UI's decision, not this one.
|
|
49
|
+
// The number an order is shown under: the low 32 bits of the id of the message carrying it, as
|
|
50
|
+
// upper-case hex without padding. Must match Java MessageBuilder.formatId character for
|
|
51
|
+
// character, since the merchant app shows the same number and a customer may quote it by phone.
|
|
52
|
+
// Derived, not a protocol field. Java casts to signed int and formats with %X, which prints the
|
|
53
|
+
// unsigned 32-bit two's complement, so masking gives the same string.
|
|
54
|
+
// The "Order" prefix the merchant app adds is a UI decision.
|
|
61
55
|
static toOrderNumberString(orderId) {
|
|
62
56
|
return (orderId & Ids.UNSIGNED_32_BIT_MASK).toString(16).toUpperCase();
|
|
63
57
|
}
|
|
58
|
+
// Where a container keeps how far its reads of one entity type have got. The blob's eTag is the
|
|
59
|
+
// cursor the next read sends, and the blob holds nothing else. The store keeps the greater eTag,
|
|
60
|
+
// so a cursor never drops on a stale or repeated page or a write from another tab. Written in
|
|
61
|
+
// the batch of the page that moved it, so it cannot get ahead of the entities it describes. key
|
|
62
|
+
// is one of SyncKeys.
|
|
63
|
+
static getSyncCursorBlobId(key) {
|
|
64
|
+
return Ids.SYNC_CURSOR_BLOB_ID_BASE - BigInt(key);
|
|
65
|
+
}
|
|
64
66
|
}
|
|
65
67
|
Ids.ENTITY_TYPE_BIT_SHIFT = BigInt(proto_Constants.ENTITY_TYPE_BIT_SHIFT);
|
|
66
68
|
// Everything an id holds below its entity type; not in Constants.proto since 64 bits don't fit an enum value.
|
|
67
69
|
Ids.ID_MASK = (1n << BigInt(proto_Constants.ENTITY_TYPE_BIT_SHIFT)) - 1n;
|
|
68
70
|
// The configuration holding a business's public settings - the only one sent to a storefront (Java Configuration.MIN_PUBLIC_CONFIGURATION_ID).
|
|
69
71
|
Ids.GENERAL_SETTINGS_CONFIGURATION_ID = 0x0d10000000000000n;
|
|
70
|
-
// A price list id is built by Constants.buildPriceListId
|
|
71
|
-
//
|
|
72
|
+
// A price list id is built by Constants.buildPriceListId, not named here. Only the low parts of
|
|
73
|
+
// the built-in lists are protocol constants.
|
|
72
74
|
// Where a business container keeps that business's attachment base url; its eTag is that url's expiry.
|
|
73
75
|
Ids.ATTACHMENT_BASE_URL_BLOB_ID = -1n;
|
|
74
|
-
// Where a container keeps the credentials that sign its calls
|
|
76
|
+
// Where a container keeps the credentials that sign its calls (see AuthTokens). Written with a null eTag, since a reissued token is not a later version of the earlier one. The latest wins.
|
|
75
77
|
Ids.AUTH_TOKENS_BLOB_ID = -2n;
|
|
78
|
+
// The first of a block of fixed blob ids, one per key (see getSyncCursorBlobId). A key is an entity type id, below 0x80, so the block runs from -0x100 down to -0x17F and cannot meet the fixed blobs at -1 and -2.
|
|
79
|
+
Ids.SYNC_CURSOR_BLOB_ID_BASE = -0x100n;
|
|
76
80
|
Ids.UNSIGNED_64_BIT_MASK = (1n << 64n) - 1n;
|
|
77
81
|
Ids.UNSIGNED_32_BIT_MASK = (1n << 32n) - 1n;
|
|
78
82
|
export default Ids;
|
package/dist/Item.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import Entity from "./Entity";
|
|
2
|
-
// Something a business buys or sells, or a category or
|
|
3
|
-
// parentItemId is the wire parent (
|
|
2
|
+
// Something a business buys or sells, or a category or price of one. Mirrors the protocol's Item, embedded in each of the five real types.
|
|
3
|
+
// parentItemId is the wire parent (a product's category). Entity.parent is the sync layer's containment parent (the business).
|
|
4
4
|
export default class Item extends Entity {
|
|
5
|
-
// Public
|
|
5
|
+
// Public because ProductCategory and PriceList add nothing of their own. The class is still abstract.
|
|
6
6
|
constructor(header, _name, _description, _parentItemId, _isDisabled) {
|
|
7
7
|
super(header);
|
|
8
8
|
this._name = _name;
|
|
@@ -20,10 +20,9 @@ export default class Item extends Entity {
|
|
|
20
20
|
get parentItemId() {
|
|
21
21
|
return this._parentItemId;
|
|
22
22
|
}
|
|
23
|
-
// True when the business has disabled this item. Unlike isPublic and Product.isDraft,
|
|
24
|
-
// change after an item exists, so it is sent rather than filtered out
|
|
25
|
-
//
|
|
26
|
-
// every package of an otherwise visible product is itself enabled.
|
|
23
|
+
// True when the business has disabled this item. Unlike isPublic and Product.isDraft, it can
|
|
24
|
+
// change after an item exists, so it is sent rather than filtered out. A product-level check does
|
|
25
|
+
// not guarantee that every package of an otherwise visible product is enabled.
|
|
27
26
|
get isDisabled() {
|
|
28
27
|
return this._isDisabled;
|
|
29
28
|
}
|
package/dist/LatLong.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// A point on Earth. Not an entity
|
|
2
|
-
// location.
|
|
3
|
-
//
|
|
1
|
+
// A point on Earth, in degrees. Not an entity: a value on GeneralSettings, where it is the
|
|
2
|
+
// business's own location. Converting or formatting it (a map pin, a distance, a link) is a UI
|
|
3
|
+
// decision.
|
|
4
4
|
export default class LatLong {
|
|
5
5
|
constructor(_latitude, _longitude) {
|
|
6
6
|
this._latitude = _latitude;
|