@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
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AddressType as proto_AddressType } from "./generated/AddressType";
|
|
2
|
+
export default class Address {
|
|
3
|
+
readonly id: bigint;
|
|
4
|
+
private readonly _addressType;
|
|
5
|
+
private readonly _unitNumber;
|
|
6
|
+
private readonly _community;
|
|
7
|
+
private readonly _line2;
|
|
8
|
+
private readonly _city;
|
|
9
|
+
private readonly _state;
|
|
10
|
+
private readonly _pinCode;
|
|
11
|
+
private readonly _countryCode;
|
|
12
|
+
constructor(id: bigint, _addressType: proto_AddressType, _unitNumber: string | null, _community: string | null, _line2: string | null, _city: string | null, _state: string | null, _pinCode: string | null, _countryCode: number);
|
|
13
|
+
get addressType(): proto_AddressType;
|
|
14
|
+
get unitNumber(): string | null;
|
|
15
|
+
get community(): string | null;
|
|
16
|
+
get line2(): string | null;
|
|
17
|
+
get city(): string | null;
|
|
18
|
+
get state(): string | null;
|
|
19
|
+
get pinCode(): string | null;
|
|
20
|
+
get countryCode(): number;
|
|
21
|
+
get formattedAddress(): string;
|
|
22
|
+
}
|
|
23
|
+
export declare class AddressList {
|
|
24
|
+
private readonly _defaultAddressId;
|
|
25
|
+
private readonly _addresses;
|
|
26
|
+
constructor(_defaultAddressId: bigint, _addresses: ReadonlyArray<Address>);
|
|
27
|
+
get defaultAddressId(): bigint;
|
|
28
|
+
get addresses(): ReadonlyArray<Address>;
|
|
29
|
+
get size(): number;
|
|
30
|
+
get defaultAddress(): Address | null;
|
|
31
|
+
getAddress(addressId: bigint): Address | null;
|
|
32
|
+
static readonly EMPTY: AddressList;
|
|
33
|
+
}
|
package/dist/Address.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// A postal address: a delivery address of a customer, or an address of a business. Not an entity -
|
|
2
|
+
// its id is unique only within the AddressList that holds it.
|
|
3
|
+
export default class Address {
|
|
4
|
+
constructor(
|
|
5
|
+
// Unique only within the list that holds it, unlike an entity id
|
|
6
|
+
id, _addressType, _unitNumber, _community, _line2, _city, _state, _pinCode, _countryCode) {
|
|
7
|
+
this.id = id;
|
|
8
|
+
this._addressType = _addressType;
|
|
9
|
+
this._unitNumber = _unitNumber;
|
|
10
|
+
this._community = _community;
|
|
11
|
+
this._line2 = _line2;
|
|
12
|
+
this._city = _city;
|
|
13
|
+
this._state = _state;
|
|
14
|
+
this._pinCode = _pinCode;
|
|
15
|
+
this._countryCode = _countryCode;
|
|
16
|
+
}
|
|
17
|
+
get addressType() {
|
|
18
|
+
return this._addressType;
|
|
19
|
+
}
|
|
20
|
+
// Flat, house or building number
|
|
21
|
+
get unitNumber() {
|
|
22
|
+
return this._unitNumber;
|
|
23
|
+
}
|
|
24
|
+
// Street, locality or neighbourhood
|
|
25
|
+
get community() {
|
|
26
|
+
return this._community;
|
|
27
|
+
}
|
|
28
|
+
get line2() {
|
|
29
|
+
return this._line2;
|
|
30
|
+
}
|
|
31
|
+
get city() {
|
|
32
|
+
return this._city;
|
|
33
|
+
}
|
|
34
|
+
get state() {
|
|
35
|
+
return this._state;
|
|
36
|
+
}
|
|
37
|
+
// Postal code / PIN code
|
|
38
|
+
get pinCode() {
|
|
39
|
+
return this._pinCode;
|
|
40
|
+
}
|
|
41
|
+
// ISO 3166-1 numeric
|
|
42
|
+
get countryCode() {
|
|
43
|
+
return this._countryCode;
|
|
44
|
+
}
|
|
45
|
+
// The set parts, in envelope order, joined with commas; empty when none are set. Country is
|
|
46
|
+
// deliberately excluded - turning a code into a name is a UI decision, not this library's.
|
|
47
|
+
get formattedAddress() {
|
|
48
|
+
const parts = [];
|
|
49
|
+
for (const part of [
|
|
50
|
+
this._unitNumber,
|
|
51
|
+
this._community,
|
|
52
|
+
this._line2,
|
|
53
|
+
this._city,
|
|
54
|
+
this._state,
|
|
55
|
+
this._pinCode,
|
|
56
|
+
])
|
|
57
|
+
if (part !== null && part.length > 0)
|
|
58
|
+
parts.push(part);
|
|
59
|
+
return parts.join(", ");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// The addresses of a user or of a business, one of which is the default.
|
|
63
|
+
export class AddressList {
|
|
64
|
+
constructor(_defaultAddressId, _addresses) {
|
|
65
|
+
this._defaultAddressId = _defaultAddressId;
|
|
66
|
+
this._addresses = _addresses;
|
|
67
|
+
}
|
|
68
|
+
get defaultAddressId() {
|
|
69
|
+
return this._defaultAddressId;
|
|
70
|
+
}
|
|
71
|
+
get addresses() {
|
|
72
|
+
return this._addresses;
|
|
73
|
+
}
|
|
74
|
+
// Computed here rather than sent
|
|
75
|
+
get size() {
|
|
76
|
+
return this._addresses.length;
|
|
77
|
+
}
|
|
78
|
+
// The address named by defaultAddressId, or the first address if that id names none (default was
|
|
79
|
+
// deleted). Null only when the list is empty.
|
|
80
|
+
get defaultAddress() {
|
|
81
|
+
if (this._addresses.length === 0)
|
|
82
|
+
return null;
|
|
83
|
+
for (const address of this._addresses)
|
|
84
|
+
if (address.id === this._defaultAddressId)
|
|
85
|
+
return address;
|
|
86
|
+
return this._addresses[0];
|
|
87
|
+
}
|
|
88
|
+
getAddress(addressId) {
|
|
89
|
+
for (const address of this._addresses)
|
|
90
|
+
if (address.id === addressId)
|
|
91
|
+
return address;
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// An empty list, for a user or a business that has no addresses at all. Frozen and shared,
|
|
96
|
+
// because an AddressList holds nothing that can change.
|
|
97
|
+
AddressList.EMPTY = new AddressList(0n, Object.freeze([]));
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AttachmentType as proto_AttachmentType } from "./generated/AttachmentType";
|
|
2
|
+
import Entity, { EntityHeader } from "./Entity";
|
|
3
|
+
export default class Attachment extends Entity {
|
|
4
|
+
private readonly _attachmentType;
|
|
5
|
+
private readonly _owningEntityId;
|
|
6
|
+
private readonly _fileHash;
|
|
7
|
+
private readonly _fileExtension;
|
|
8
|
+
private readonly _fileName;
|
|
9
|
+
constructor(header: EntityHeader, _attachmentType: proto_AttachmentType, _owningEntityId: bigint, _fileHash: Uint8Array | null, _fileExtension: string | null, _fileName: string | null);
|
|
10
|
+
get attachmentType(): proto_AttachmentType;
|
|
11
|
+
get owningEntityId(): bigint;
|
|
12
|
+
get fileName(): string | null;
|
|
13
|
+
get storageFileName(): string | null;
|
|
14
|
+
private static pad;
|
|
15
|
+
private static toUpperCaseHexString;
|
|
16
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import Entity from "./Entity";
|
|
2
|
+
import Ids from "./Ids";
|
|
3
|
+
// A file attached to an entity - a photo of a business, a product or a package. Not part of this
|
|
4
|
+
// library's public surface; a UI is given a Photo (attachment type + url) built from this instead.
|
|
5
|
+
export default class Attachment extends Entity {
|
|
6
|
+
constructor(header, _attachmentType, _owningEntityId, _fileHash, _fileExtension, _fileName) {
|
|
7
|
+
super(header);
|
|
8
|
+
this._attachmentType = _attachmentType;
|
|
9
|
+
this._owningEntityId = _owningEntityId;
|
|
10
|
+
this._fileHash = _fileHash;
|
|
11
|
+
this._fileExtension = _fileExtension;
|
|
12
|
+
this._fileName = _fileName;
|
|
13
|
+
}
|
|
14
|
+
// Which photo of the owning entity this is: the main catalog image, one of the lifestyle images,
|
|
15
|
+
// a photo of the store, and so on
|
|
16
|
+
get attachmentType() {
|
|
17
|
+
return this._attachmentType;
|
|
18
|
+
}
|
|
19
|
+
// The business, product or package this file is attached to. Nothing nests on the wire, so this
|
|
20
|
+
// is how the sync layer finds which entity a photo belongs to.
|
|
21
|
+
get owningEntityId() {
|
|
22
|
+
return this._owningEntityId;
|
|
23
|
+
}
|
|
24
|
+
get fileName() {
|
|
25
|
+
return this._fileName;
|
|
26
|
+
}
|
|
27
|
+
// Storage file name, or null if this attachment has no file (deleted). Must exactly match Java
|
|
28
|
+
// Attachment.getStorageFileName: UTC date with zero-based month, upper-hex id/hash, no 0x prefix.
|
|
29
|
+
get storageFileName() {
|
|
30
|
+
if (this._fileHash === null || this._fileExtension === null)
|
|
31
|
+
return null;
|
|
32
|
+
const createdAt = this.createdAt;
|
|
33
|
+
const year = Attachment.pad(createdAt.getUTCFullYear(), 4);
|
|
34
|
+
const month = Attachment.pad(createdAt.getUTCMonth(), 2); // Zero based, as in Java
|
|
35
|
+
const day = Attachment.pad(createdAt.getUTCDate(), 2);
|
|
36
|
+
const id = Ids.toStorageHexString(this.id);
|
|
37
|
+
const fileHash = Attachment.toUpperCaseHexString(this._fileHash);
|
|
38
|
+
return `${year}-${month}-${day}-${id}-${fileHash}.${this._fileExtension}`;
|
|
39
|
+
}
|
|
40
|
+
static pad(value, length) {
|
|
41
|
+
return value.toString().padStart(length, "0");
|
|
42
|
+
}
|
|
43
|
+
static toUpperCaseHexString(bytes) {
|
|
44
|
+
let result = "";
|
|
45
|
+
for (const byte of bytes)
|
|
46
|
+
result += byte.toString(16).toUpperCase().padStart(2, "0");
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default class AttachmentBaseUrl {
|
|
2
|
+
private readonly _resourceUrl;
|
|
3
|
+
private readonly _sasToken;
|
|
4
|
+
constructor(_resourceUrl: string, _sasToken: string, expiry: bigint);
|
|
5
|
+
get resourceUrl(): string;
|
|
6
|
+
get expiry(): Date;
|
|
7
|
+
get hasExpired(): boolean;
|
|
8
|
+
createFileUrl(storageFileName: string): URL;
|
|
9
|
+
toString(): string;
|
|
10
|
+
private readonly _expiry;
|
|
11
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Constants as proto_Constants } from "./generated/Constants";
|
|
2
|
+
import { InvalidArgumentException } from "./Exceptions";
|
|
3
|
+
// Where a business's attachment files live, the signature that reads them, and when both expire.
|
|
4
|
+
// Signature has no getter (only createFileUrl exposes it) - safe in a url only because it is
|
|
5
|
+
// scoped, read-only and short-lived, unlike AuthTokens' userToken/linkToken.
|
|
6
|
+
export default class AttachmentBaseUrl {
|
|
7
|
+
constructor(_resourceUrl, _sasToken, expiry) {
|
|
8
|
+
this._resourceUrl = _resourceUrl;
|
|
9
|
+
this._sasToken = _sasToken;
|
|
10
|
+
// The protobuf promises no trailing slash and no query string; checked rather than trusted,
|
|
11
|
+
// since violating either silently produces a url that fetches nothing.
|
|
12
|
+
if (_resourceUrl.length === 0 || _resourceUrl.endsWith("/"))
|
|
13
|
+
throw new InvalidArgumentException(`Not a container url: ${_resourceUrl}`);
|
|
14
|
+
if (_resourceUrl.includes("?"))
|
|
15
|
+
throw new InvalidArgumentException("A container url cannot carry a query string");
|
|
16
|
+
this._expiry = Number(expiry);
|
|
17
|
+
}
|
|
18
|
+
// The url of the container the files are in, always https and never with a trailing slash
|
|
19
|
+
get resourceUrl() {
|
|
20
|
+
return this._resourceUrl;
|
|
21
|
+
}
|
|
22
|
+
get expiry() {
|
|
23
|
+
return new Date(this._expiry);
|
|
24
|
+
}
|
|
25
|
+
// True once too close to expiry to be worth using (margin: ATTACHMENT_BASE_URL_EXPIRY_MARGIN),
|
|
26
|
+
// compared against the client's own clock so a url can't expire between being built and fetched.
|
|
27
|
+
get hasExpired() {
|
|
28
|
+
return Date.now() + proto_Constants.ATTACHMENT_BASE_URL_EXPIRY_MARGIN >= this._expiry;
|
|
29
|
+
}
|
|
30
|
+
// The url of one file: storage file name as the path, signature as the query string. Name must
|
|
31
|
+
// be a flat path segment - a container is not a directory tree.
|
|
32
|
+
createFileUrl(storageFileName) {
|
|
33
|
+
if (storageFileName.length === 0 || storageFileName.includes("/"))
|
|
34
|
+
throw new InvalidArgumentException(`Not a storage file name: ${storageFileName}`);
|
|
35
|
+
return new URL(`${this._resourceUrl}/${storageFileName}?${this._sasToken}`);
|
|
36
|
+
}
|
|
37
|
+
// Redacts the signature, so that logging one of these cannot leak it
|
|
38
|
+
toString() {
|
|
39
|
+
return `AttachmentBaseUrl(resourceUrl=${this._resourceUrl}, expiry=${this.expiry.toISOString()}, sasToken=<redacted>)`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AuthenticationMethod as proto_AuthenticationMethod } from "./generated/AuthenticationMethod";
|
|
2
|
+
export default class AuthTokens {
|
|
3
|
+
private readonly _authenticationMethod;
|
|
4
|
+
private readonly _authenticationToken;
|
|
5
|
+
private readonly _userToken;
|
|
6
|
+
private readonly _linkToken;
|
|
7
|
+
constructor(_authenticationMethod: proto_AuthenticationMethod, _authenticationToken: string, _userToken: string | null, _linkToken: string | null);
|
|
8
|
+
get authenticationMethod(): proto_AuthenticationMethod;
|
|
9
|
+
get authenticationToken(): string;
|
|
10
|
+
get userToken(): string | null;
|
|
11
|
+
get linkToken(): string | null;
|
|
12
|
+
toString(): string;
|
|
13
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// The credentials one request is signed with: exactly the fields of the AuthTokens message and nothing derived, so that what this library holds and what the wire carries cannot drift.
|
|
2
|
+
// A class of its own rather than the generated message because these are held and cached rather than only sent; ProtoMap turns one into the message a Service is handed. Every value is a bearer credential - never log one.
|
|
3
|
+
export default class AuthTokens {
|
|
4
|
+
constructor(_authenticationMethod, _authenticationToken, _userToken, _linkToken) {
|
|
5
|
+
this._authenticationMethod = _authenticationMethod;
|
|
6
|
+
this._authenticationToken = _authenticationToken;
|
|
7
|
+
this._userToken = _userToken;
|
|
8
|
+
this._linkToken = _linkToken;
|
|
9
|
+
}
|
|
10
|
+
// Which identity provider issued the authentication token, and so how a server parses it. Always set: zero is FIREBASE, not "unspecified".
|
|
11
|
+
get authenticationMethod() {
|
|
12
|
+
return this._authenticationMethod;
|
|
13
|
+
}
|
|
14
|
+
// Which person is calling, as their identity provider says. Empty on one read back out of the cache, which deliberately keeps no copy of it - see ProtoMap.authTokensToBlob.
|
|
15
|
+
get authenticationToken() {
|
|
16
|
+
return this._authenticationToken;
|
|
17
|
+
}
|
|
18
|
+
// Which MeraBills user that person is, issued by this server. Null until a profile sync out has been made once, which is the call that earns one.
|
|
19
|
+
get userToken() {
|
|
20
|
+
return this._userToken;
|
|
21
|
+
}
|
|
22
|
+
// Which business the caller may act against, from the BusinessLink of that business. Null on a call that names none, which the protocol allows.
|
|
23
|
+
get linkToken() {
|
|
24
|
+
return this._linkToken;
|
|
25
|
+
}
|
|
26
|
+
// Redacts all three, so that logging one of these cannot leak a credential
|
|
27
|
+
toString() {
|
|
28
|
+
return `AuthTokens(authenticationMethod=${this._authenticationMethod}, authenticationToken=<redacted>, userToken=<${this._userToken === null ? "none" : "redacted"}>, linkToken=<${this._linkToken === null ? "none" : "redacted"}>)`;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import AttachmentBaseUrl from "./AttachmentBaseUrl";
|
|
2
|
+
import CartEditor from "./CartEditor";
|
|
3
|
+
import Catalog from "./Catalog";
|
|
4
|
+
import Entity, { EntityHeader } from "./Entity";
|
|
5
|
+
import GeneralSettings from "./GeneralSettings";
|
|
6
|
+
import Order from "./Order";
|
|
7
|
+
import Photo from "./Photo";
|
|
8
|
+
import ShoppingList from "./ShoppingList";
|
|
9
|
+
export default class Business extends Entity implements UpdatableBusiness {
|
|
10
|
+
private readonly _businessId;
|
|
11
|
+
private readonly _displayName;
|
|
12
|
+
private readonly _countryCode;
|
|
13
|
+
constructor(header: EntityHeader, _businessId: string, _displayName: string, _countryCode: number);
|
|
14
|
+
get businessId(): string;
|
|
15
|
+
get displayName(): string;
|
|
16
|
+
get countryCode(): number;
|
|
17
|
+
get settings(): GeneralSettings;
|
|
18
|
+
private set settings(value);
|
|
19
|
+
get photos(): ReadonlyArray<Photo>;
|
|
20
|
+
private set photos(value);
|
|
21
|
+
get orders(): ReadonlyArray<Order>;
|
|
22
|
+
private set orders(value);
|
|
23
|
+
get cart(): ShoppingList | null;
|
|
24
|
+
private set cart(value);
|
|
25
|
+
get catalog(): Catalog;
|
|
26
|
+
private set catalog(value);
|
|
27
|
+
createCartEditor(): CartEditor;
|
|
28
|
+
get attachmentBaseUrl(): AttachmentBaseUrl | null;
|
|
29
|
+
private set attachmentBaseUrl(value);
|
|
30
|
+
private _settings;
|
|
31
|
+
private _photos;
|
|
32
|
+
private _orders;
|
|
33
|
+
private _cart;
|
|
34
|
+
private _catalog;
|
|
35
|
+
private _attachmentBaseUrl;
|
|
36
|
+
}
|
|
37
|
+
export interface UpdatableBusiness {
|
|
38
|
+
set settings(value: GeneralSettings);
|
|
39
|
+
set photos(value: ReadonlyArray<Photo>);
|
|
40
|
+
set orders(value: ReadonlyArray<Order>);
|
|
41
|
+
set cart(value: ShoppingList | null);
|
|
42
|
+
set catalog(value: Catalog);
|
|
43
|
+
set attachmentBaseUrl(value: AttachmentBaseUrl | null);
|
|
44
|
+
}
|
package/dist/Business.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import CartEditor from "./CartEditor";
|
|
2
|
+
import Catalog from "./Catalog";
|
|
3
|
+
import Entity from "./Entity";
|
|
4
|
+
import GeneralSettings from "./GeneralSettings";
|
|
5
|
+
// The business a customer is browsing: its name, settings, photos, catalog, orders, and cart.
|
|
6
|
+
// Rebuilt by the sync layer from flat wire entities and set via UpdatableBusiness, not a public
|
|
7
|
+
// setter - a UI holding a Business can read all of it and change none of it.
|
|
8
|
+
export default class Business extends Entity {
|
|
9
|
+
constructor(header, _businessId, _displayName, _countryCode) {
|
|
10
|
+
super(header);
|
|
11
|
+
this._businessId = _businessId;
|
|
12
|
+
this._displayName = _displayName;
|
|
13
|
+
this._countryCode = _countryCode;
|
|
14
|
+
this._settings = GeneralSettings.EMPTY;
|
|
15
|
+
this._photos = Object.freeze([]);
|
|
16
|
+
this._orders = Object.freeze([]);
|
|
17
|
+
this._cart = null;
|
|
18
|
+
this._catalog = Catalog.EMPTY;
|
|
19
|
+
this._attachmentBaseUrl = null;
|
|
20
|
+
}
|
|
21
|
+
// The unique, lower case, url friendly id this storefront was reached by - not the entity id
|
|
22
|
+
// (see the warning on BusinessLink.businessId, which is this business's entity id)
|
|
23
|
+
get businessId() {
|
|
24
|
+
return this._businessId;
|
|
25
|
+
}
|
|
26
|
+
// The name shown to customers
|
|
27
|
+
get displayName() {
|
|
28
|
+
return this._displayName;
|
|
29
|
+
}
|
|
30
|
+
// ISO 3166-1 numeric; the only source of currency for amounts in this business
|
|
31
|
+
get countryCode() {
|
|
32
|
+
return this._countryCode;
|
|
33
|
+
}
|
|
34
|
+
// GeneralSettings.EMPTY until the business's public configuration arrives
|
|
35
|
+
get settings() {
|
|
36
|
+
return this._settings;
|
|
37
|
+
}
|
|
38
|
+
set settings(value) {
|
|
39
|
+
this._settings = value;
|
|
40
|
+
}
|
|
41
|
+
// Photos of the store itself, as opposed to a product's or package's
|
|
42
|
+
get photos() {
|
|
43
|
+
return this._photos;
|
|
44
|
+
}
|
|
45
|
+
set photos(value) {
|
|
46
|
+
this._photos = value;
|
|
47
|
+
}
|
|
48
|
+
// The orders this customer has placed
|
|
49
|
+
get orders() {
|
|
50
|
+
return this._orders;
|
|
51
|
+
}
|
|
52
|
+
set orders(value) {
|
|
53
|
+
this._orders = value;
|
|
54
|
+
}
|
|
55
|
+
// What this customer has picked and not yet ordered. Null until they have put something in a
|
|
56
|
+
// cart, and null again once they have ordered what was in it - the message the cart travels in
|
|
57
|
+
// outlives being emptied, but nothing of it is a customer's business, so what is exposed is the
|
|
58
|
+
// list alone. The fulfillment mode is not part of it: that is chosen when an order is placed, and
|
|
59
|
+
// is a field of the Order.
|
|
60
|
+
get cart() {
|
|
61
|
+
return this._cart;
|
|
62
|
+
}
|
|
63
|
+
set cart(value) {
|
|
64
|
+
this._cart = value;
|
|
65
|
+
}
|
|
66
|
+
// Catalog.EMPTY until the catalog of this business arrives
|
|
67
|
+
get catalog() {
|
|
68
|
+
return this._catalog;
|
|
69
|
+
}
|
|
70
|
+
set catalog(value) {
|
|
71
|
+
this._catalog = value;
|
|
72
|
+
}
|
|
73
|
+
// A scratch copy of the cart to edit, priced off this business's catalog and charged to its
|
|
74
|
+
// settings - see CartEditor. It reads all three once, here, so a Business republished mid-edit
|
|
75
|
+
// needs a fresh one; nothing an editor does touches this business until its built list reaches
|
|
76
|
+
// Model.updateCartLocalOnly.
|
|
77
|
+
createCartEditor() {
|
|
78
|
+
return new CartEditor(this._catalog, this._settings, this._cart);
|
|
79
|
+
}
|
|
80
|
+
// Where this business's photo files live; renewed on its own schedule independent of the rest
|
|
81
|
+
get attachmentBaseUrl() {
|
|
82
|
+
return this._attachmentBaseUrl;
|
|
83
|
+
}
|
|
84
|
+
set attachmentBaseUrl(value) {
|
|
85
|
+
this._attachmentBaseUrl = value;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BusinessIdentifierType as proto_BusinessIdentifierType } from "./generated/BusinessIdentifierType";
|
|
2
|
+
export default class BusinessIdentifier {
|
|
3
|
+
private readonly _type;
|
|
4
|
+
private readonly _value;
|
|
5
|
+
constructor(_type: proto_BusinessIdentifierType, _value: string);
|
|
6
|
+
get type(): proto_BusinessIdentifierType;
|
|
7
|
+
get value(): string;
|
|
8
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// An identifier of a business - a GSTIN, for example - and its kind. Same pair-not-a-map reason as
|
|
2
|
+
// PackageIdentifier: Java identifies kinds by string id, so this numbering is protocol-only.
|
|
3
|
+
export default class BusinessIdentifier {
|
|
4
|
+
constructor(_type, _value) {
|
|
5
|
+
this._type = _type;
|
|
6
|
+
this._value = _value;
|
|
7
|
+
}
|
|
8
|
+
get type() {
|
|
9
|
+
return this._type;
|
|
10
|
+
}
|
|
11
|
+
get value() {
|
|
12
|
+
return this._value;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Role as proto_Role } from "./generated/Role";
|
|
2
|
+
import Entity, { EntityHeader } from "./Entity";
|
|
3
|
+
export default class BusinessLink extends Entity {
|
|
4
|
+
private readonly _linkedEntityId;
|
|
5
|
+
private readonly _businessId;
|
|
6
|
+
private readonly _role;
|
|
7
|
+
private readonly _partyId;
|
|
8
|
+
private readonly _linkToken;
|
|
9
|
+
constructor(header: EntityHeader, _linkedEntityId: bigint, _businessId: bigint, _role: proto_Role, _partyId: bigint, _linkToken: string | null, expiry: bigint);
|
|
10
|
+
get linkedEntityId(): bigint;
|
|
11
|
+
get businessId(): bigint;
|
|
12
|
+
get role(): proto_Role;
|
|
13
|
+
get partyId(): bigint;
|
|
14
|
+
get linkToken(): string | null;
|
|
15
|
+
get expiry(): Date;
|
|
16
|
+
get isExpirySet(): boolean;
|
|
17
|
+
get hasExpired(): boolean;
|
|
18
|
+
toString(): string;
|
|
19
|
+
private static readonly NO_EXPIRY;
|
|
20
|
+
private readonly _expiry;
|
|
21
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Constants as proto_Constants } from "./generated/Constants";
|
|
2
|
+
import Entity from "./Entity";
|
|
3
|
+
// What links a customer to a business and authorizes them to act against it. businessId is an
|
|
4
|
+
// entity id (not the url-friendly Business.businessId); never log or url-embed linkToken.
|
|
5
|
+
class BusinessLink extends Entity {
|
|
6
|
+
constructor(header, _linkedEntityId, _businessId, _role, _partyId, _linkToken, expiry) {
|
|
7
|
+
super(header);
|
|
8
|
+
this._linkedEntityId = _linkedEntityId;
|
|
9
|
+
this._businessId = _businessId;
|
|
10
|
+
this._role = _role;
|
|
11
|
+
this._partyId = _partyId;
|
|
12
|
+
this._linkToken = _linkToken;
|
|
13
|
+
this._expiry = Number(expiry);
|
|
14
|
+
}
|
|
15
|
+
// The entity this link is for - the User of the customer, in a storefront. Its entity type is
|
|
16
|
+
// the most significant byte of the id, which is how a client tells a user from a business.
|
|
17
|
+
get linkedEntityId() {
|
|
18
|
+
return this._linkedEntityId;
|
|
19
|
+
}
|
|
20
|
+
// The entity id of the business, matching Business.entity.id - see the comment on this class
|
|
21
|
+
get businessId() {
|
|
22
|
+
return this._businessId;
|
|
23
|
+
}
|
|
24
|
+
// What the customer may do, normally Role.CUSTOMER. Group is (role >> 6); actual permissions are
|
|
25
|
+
// not on the wire, so a UI cannot grey out disallowed actions.
|
|
26
|
+
get role() {
|
|
27
|
+
return this._role;
|
|
28
|
+
}
|
|
29
|
+
// The party record of this customer, or Constants.ENTITY_ID_NULL when none. Party is not part of
|
|
30
|
+
// this protocol, so a storefront cannot resolve it - exposed only because the server needs it.
|
|
31
|
+
get partyId() {
|
|
32
|
+
return this._partyId;
|
|
33
|
+
}
|
|
34
|
+
// The credential that goes into AuthTokens.linkToken of every later request naming this
|
|
35
|
+
// business. Never log this and never put it in a url.
|
|
36
|
+
get linkToken() {
|
|
37
|
+
return this._linkToken;
|
|
38
|
+
}
|
|
39
|
+
get expiry() {
|
|
40
|
+
return new Date(this._expiry);
|
|
41
|
+
}
|
|
42
|
+
// False when this link never expires, which is what BusinessLink.NO_EXPIRY means. That constant
|
|
43
|
+
// is not in Constants.proto - it is zero, and it is the only meaning zero has for this field.
|
|
44
|
+
get isExpirySet() {
|
|
45
|
+
return this._expiry !== BusinessLink.NO_EXPIRY;
|
|
46
|
+
}
|
|
47
|
+
// True once past expiry by more than Constants.MAX_CLOCK_SKEW - applied opposite to
|
|
48
|
+
// AttachmentBaseUrl.hasExpired, so a false positive can't lock out a still-entitled customer.
|
|
49
|
+
get hasExpired() {
|
|
50
|
+
if (!this.isExpirySet)
|
|
51
|
+
return false;
|
|
52
|
+
return Date.now() - proto_Constants.MAX_CLOCK_SKEW > this._expiry;
|
|
53
|
+
}
|
|
54
|
+
// Redacts the link token, so that logging a link cannot leak it
|
|
55
|
+
toString() {
|
|
56
|
+
return `BusinessLink(id=${this.id}, businessId=${this._businessId}, role=${this._role}, linkToken=<redacted>)`;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Java BusinessLink.NO_EXPIRY
|
|
60
|
+
BusinessLink.NO_EXPIRY = 0;
|
|
61
|
+
export default BusinessLink;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import Entity, { EntityHeader } from "./Entity";
|
|
2
|
+
export default class BusinessProfile extends Entity {
|
|
3
|
+
private readonly _businessId;
|
|
4
|
+
private readonly _displayName;
|
|
5
|
+
private readonly _countryCode;
|
|
6
|
+
constructor(header: EntityHeader, _businessId: string, _displayName: string, _countryCode: number);
|
|
7
|
+
get businessId(): string;
|
|
8
|
+
get displayName(): string;
|
|
9
|
+
get countryCode(): number;
|
|
10
|
+
toString(): string;
|
|
11
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import Entity from "./Entity";
|
|
2
|
+
// One business the customer is linked to, as the profile database holds it: url-friendly id, name
|
|
3
|
+
// and country only - deliberately not a Business, which carries data a profile sync can't provide.
|
|
4
|
+
export default class BusinessProfile extends Entity {
|
|
5
|
+
constructor(header, _businessId, _displayName, _countryCode) {
|
|
6
|
+
super(header);
|
|
7
|
+
this._businessId = _businessId;
|
|
8
|
+
this._displayName = _displayName;
|
|
9
|
+
this._countryCode = _countryCode;
|
|
10
|
+
}
|
|
11
|
+
// The unique, lower case, url-friendly id a storefront is reached by; what Model.setBusinessId
|
|
12
|
+
// takes. Not the entity id - BusinessLink.businessId is the entity id of the same business.
|
|
13
|
+
get businessId() {
|
|
14
|
+
return this._businessId;
|
|
15
|
+
}
|
|
16
|
+
// The name shown to customers
|
|
17
|
+
get displayName() {
|
|
18
|
+
return this._displayName;
|
|
19
|
+
}
|
|
20
|
+
// ISO 3166-1 numeric; the only thing that says what currency this business's amounts are in
|
|
21
|
+
get countryCode() {
|
|
22
|
+
return this._countryCode;
|
|
23
|
+
}
|
|
24
|
+
toString() {
|
|
25
|
+
return `BusinessProfile(id=${this.id}, businessId=${this._businessId}, displayName=${this._displayName})`;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import Catalog from "./Catalog";
|
|
2
|
+
import GeneralSettings from "./GeneralSettings";
|
|
3
|
+
import Package from "./Package";
|
|
4
|
+
import Product from "./Product";
|
|
5
|
+
import ShoppingList, { ShoppingListItem } from "./ShoppingList";
|
|
6
|
+
import Tax from "./Tax";
|
|
7
|
+
export default class CartEditor {
|
|
8
|
+
private readonly _catalog;
|
|
9
|
+
private readonly _settings;
|
|
10
|
+
constructor(_catalog: Catalog, _settings: GeneralSettings, cart: ShoppingList | null);
|
|
11
|
+
get lines(): ReadonlyArray<CartLine>;
|
|
12
|
+
get unavailableItems(): ReadonlyArray<ShoppingListItem>;
|
|
13
|
+
get isEmpty(): boolean;
|
|
14
|
+
get lineCount(): number;
|
|
15
|
+
get totalQuantity(): number;
|
|
16
|
+
getQuantity(item: Package): number;
|
|
17
|
+
setQuantity(item: Package, quantity: number): CartEditor;
|
|
18
|
+
add(item: Package, quantity?: number): CartEditor;
|
|
19
|
+
remove(item: Package): CartEditor;
|
|
20
|
+
clear(): CartEditor;
|
|
21
|
+
get itemsTotal(): number;
|
|
22
|
+
get savings(): number;
|
|
23
|
+
get itemsTax(): number;
|
|
24
|
+
get itemsFinalTotal(): number;
|
|
25
|
+
get isDeliveryOffered(): boolean;
|
|
26
|
+
get deliveryCharge(): number;
|
|
27
|
+
get regularDeliveryCharge(): number;
|
|
28
|
+
get isDeliveryFree(): boolean;
|
|
29
|
+
get amountToFreeDelivery(): number | null;
|
|
30
|
+
get deliveryTax(): number;
|
|
31
|
+
total(withDeliveryCharge?: boolean): number;
|
|
32
|
+
build(withDeliveryCharge?: boolean): ShoppingList;
|
|
33
|
+
private buildDeliveryChargeItem;
|
|
34
|
+
private getDeliveryCharge;
|
|
35
|
+
private static getTax;
|
|
36
|
+
private getBuyablePackage;
|
|
37
|
+
private static readonly MAX_QUANTITY;
|
|
38
|
+
private readonly _inventoryLocationId;
|
|
39
|
+
private readonly _unavailableItems;
|
|
40
|
+
private readonly _quantities;
|
|
41
|
+
}
|
|
42
|
+
export declare class CartLine {
|
|
43
|
+
private readonly _package;
|
|
44
|
+
private readonly _product;
|
|
45
|
+
private readonly _quantity;
|
|
46
|
+
constructor(_package: Package, _product: Product | null, _quantity: number);
|
|
47
|
+
get package(): Package;
|
|
48
|
+
get product(): Product | null;
|
|
49
|
+
get quantity(): number;
|
|
50
|
+
get unitPrice(): number;
|
|
51
|
+
get regularUnitPrice(): number;
|
|
52
|
+
get isOnOffer(): boolean;
|
|
53
|
+
get taxes(): ReadonlyArray<Tax>;
|
|
54
|
+
get amount(): number;
|
|
55
|
+
get savings(): number;
|
|
56
|
+
get totalTax(): number;
|
|
57
|
+
get finalPrice(): number;
|
|
58
|
+
toShoppingListItem(shoppingListOrder: number): ShoppingListItem;
|
|
59
|
+
}
|