@twin.org/core 0.0.2-next.3 → 0.0.2-next.4

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.
@@ -863,1055 +863,1066 @@ class GeneralError extends BaseError {
863
863
  }
864
864
  }
865
865
 
866
- // Copyright 2024 IOTA Stiftung.
867
- // SPDX-License-Identifier: Apache-2.0.
868
- /* eslint-disable no-bitwise */
869
866
  /**
870
- * Class to help with base63 Encoding/Decoding.
867
+ * Class to handle errors which are triggered by data guards.
871
868
  */
872
- class Base32 {
869
+ class GuardError extends BaseError {
873
870
  /**
874
871
  * Runtime name for the class.
875
- * @internal
876
- */
877
- static _CLASS_NAME = "Base32";
878
- /**
879
- * Alphabet table for encoding.
880
- * @internal
881
- */
882
- static _ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
883
- /**
884
- * Convert the base 32 string to a byte array.
885
- * @param base32 The base32 string to convert.
886
- * @returns The byte array.
887
- * @throws If the input string contains a character not in the Base32 alphabet.
888
872
  */
889
- static decode(base32) {
890
- let bits = 0;
891
- let value = 0;
892
- base32 = base32.replace(/=+$/, "");
893
- let index = 0;
894
- const output = new Uint8Array(Math.trunc((base32.length * 5) / 8));
895
- for (let i = 0; i < base32.length; i++) {
896
- const idx = Base32._ALPHABET.indexOf(base32[i]);
897
- if (idx === -1) {
898
- throw new GeneralError(Base32._CLASS_NAME, "invalidCharacter", {
899
- invalidCharacter: base32[i]
900
- });
901
- }
902
- value = (value << 5) | idx;
903
- bits += 5;
904
- if (bits >= 8) {
905
- output[index++] = (value >>> (bits - 8)) & 255;
906
- bits -= 8;
907
- }
908
- }
909
- return output;
910
- }
873
+ static CLASS_NAME = "GuardError";
911
874
  /**
912
- * Convert a byte array to base 32.
913
- * @param bytes The byte array to convert.
914
- * @returns The data as base32 string.
875
+ * Create a new instance of GuardError.
876
+ * @param source The source of the error.
877
+ * @param message The message as a code.
878
+ * @param propertyName The property which triggered the guard error for the item.
879
+ * @param propertyValue The property value which triggered the guard error for the item.
880
+ * @param propertyOptions The property options which might be allowed.
915
881
  */
916
- static encode(bytes) {
917
- let bits = 0;
918
- let value = 0;
919
- let output = "";
920
- for (let i = 0; i < bytes.byteLength; i++) {
921
- value = (value << 8) | bytes[i];
922
- bits += 8;
923
- while (bits >= 5) {
924
- output += Base32._ALPHABET[(value >>> (bits - 5)) & 31];
925
- bits -= 5;
926
- }
927
- }
928
- if (bits > 0) {
929
- output += Base32._ALPHABET[(value << (5 - bits)) & 31];
930
- }
931
- while (output.length % 8 !== 0) {
932
- output += "=";
933
- }
934
- return output;
882
+ constructor(source, message, propertyName, propertyValue, propertyOptions) {
883
+ super(GuardError.CLASS_NAME, source, message, {
884
+ property: propertyName ?? "property",
885
+ value: Is.undefined(propertyValue) ? "undefined" : propertyValue,
886
+ options: propertyOptions
887
+ });
935
888
  }
936
889
  }
937
890
 
938
891
  /**
939
- * Class to help with base58 Encoding/Decoding.
892
+ * Class to help with arrays.
940
893
  */
941
- class Base58 {
942
- /**
943
- * Runtime name for the class.
944
- * @internal
945
- */
946
- static _CLASS_NAME = "Base58";
947
- /**
948
- * Alphabet table for encoding.
949
- * @internal
950
- */
951
- static _ALPHABET =
952
- // cspell:disable-next-line
953
- "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
954
- /**
955
- * Reverse map for decoding.
956
- * @internal
957
- */
958
- static _ALPHABET_REVERSE = [
959
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
960
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
961
- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, 9, 10, 11, 12, 13, 14, 15, 16, -1,
962
- 17, 18, 19, 20, 21, -1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, 33,
963
- 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
964
- 57, -1, -1, -1, -1, -1
965
- ];
894
+ class ArrayHelper {
966
895
  /**
967
- * Convert the base 58 string to a byte array.
968
- * @param base58 The base58 string to convert.
969
- * @returns The byte array.
970
- * @throws If the input string contains a character not in the Base58 alphabet.
896
+ * Do the two arrays match.
897
+ * @param arr1 The first array.
898
+ * @param arr2 The second array.
899
+ * @returns True if both arrays are empty of have the same values.
971
900
  */
972
- static decode(base58) {
973
- let zeroes = 0;
974
- for (let i = 0; i < base58.length; i++) {
975
- if (base58[i] !== "1") {
976
- break;
977
- }
978
- zeroes += 1;
901
+ static matches(arr1, arr2) {
902
+ if (Is.empty(arr1) && Is.empty(arr2)) {
903
+ return true;
979
904
  }
980
- const size = Math.trunc((base58.length * 733) / 1000) + 1;
981
- const b256 = new Uint8Array(size).fill(0);
982
- let length = 0;
983
- for (let i = zeroes; i < base58.length; i++) {
984
- const ch = base58.charCodeAt(i);
985
- if (ch & 0xff80) {
986
- throw new GeneralError(Base58._CLASS_NAME, "invalidCharacter", { invalidCharacter: ch });
987
- }
988
- const val = Base58._ALPHABET_REVERSE[ch];
989
- if (val === -1) {
990
- throw new GeneralError(Base58._CLASS_NAME, "invalidCharacter", { invalidCharacter: ch });
991
- }
992
- let carry = val;
993
- let j = 0;
994
- for (let k = size - 1; k >= 0; k--, j++) {
995
- if (carry === 0 && j >= length) {
996
- break;
997
- }
998
- carry += b256[k] * 58;
999
- b256[k] = carry;
1000
- carry >>>= 8;
1001
- }
1002
- length = j;
905
+ if (!((Is.array(arr1) && Is.array(arr2)) || (Is.typedArray(arr1) && Is.typedArray(arr2)))) {
906
+ return false;
1003
907
  }
1004
- const out = new Uint8Array(zeroes + length);
1005
- let j;
1006
- for (j = 0; j < zeroes; j++) {
1007
- out[j] = 0;
908
+ if (arr1.length !== arr2.length) {
909
+ return false;
1008
910
  }
1009
- let i = size - length;
1010
- while (i < size) {
1011
- out[j++] = b256[i++];
911
+ for (let i = 0; i < arr1.length; i++) {
912
+ if (arr1[i] !== arr2[i]) {
913
+ return false;
914
+ }
1012
915
  }
1013
- return out;
916
+ return true;
1014
917
  }
1015
918
  /**
1016
- * Convert a byte array to base 58.
1017
- * @param bytes The byte array to encode.
1018
- * @returns The data as base58 string.
919
+ * Convert an object or array to an array.
920
+ * @param value The object or array to convert.
921
+ * @returns The array.
1019
922
  */
1020
- static encode(bytes) {
1021
- let zeroes = 0;
1022
- for (let i = 0; i < bytes.length; i++) {
1023
- if (bytes[i] !== 0) {
1024
- break;
1025
- }
1026
- zeroes += 1;
1027
- }
1028
- const size = Math.trunc(((bytes.length - zeroes) * 138) / 100) + 1;
1029
- const b58 = new Uint8Array(size).fill(0);
1030
- let length = 0;
1031
- for (let i = zeroes; i < bytes.length; i++) {
1032
- let carry = bytes[i];
1033
- let j = 0;
1034
- for (let k = size - 1; k >= 0; k--, j++) {
1035
- if (carry === 0 && j >= length) {
1036
- break;
1037
- }
1038
- carry += b58[k] * 256;
1039
- b58[k] = carry % 58;
1040
- carry = Math.trunc(carry / 58);
1041
- }
1042
- length = j;
1043
- }
1044
- let i = size - length;
1045
- while (i < size && b58[i] === 0) {
1046
- i += 1;
1047
- }
1048
- let str = "";
1049
- for (let j = 0; j < zeroes; j++) {
1050
- str += "1";
923
+ static fromObjectOrArray(value) {
924
+ if (Is.empty(value)) {
925
+ return undefined;
1051
926
  }
1052
- while (i < size) {
1053
- str += Base58._ALPHABET[b58[i++]];
927
+ if (Is.array(value)) {
928
+ return value;
1054
929
  }
1055
- return str;
930
+ return [value];
1056
931
  }
1057
932
  }
1058
933
 
1059
934
  // Copyright 2024 IOTA Stiftung.
1060
935
  // SPDX-License-Identifier: Apache-2.0.
1061
- /* eslint-disable no-bitwise */
1062
- /* eslint-disable no-mixed-operators */
1063
936
  /**
1064
- * Class to help with base64 Encoding/Decoding.
1065
- * Sourced from https://github.com/beatgammit/base64-js.
937
+ * Class to handle guard operations for parameters.
1066
938
  */
1067
- class Base64 {
939
+ class Guards {
1068
940
  /**
1069
- * Runtime name for the class.
1070
- * @internal
941
+ * Is the property defined.
942
+ * @param source The source of the error.
943
+ * @param property The name of the property.
944
+ * @param value The value to test.
945
+ * @throws GuardError If the value does not match the assertion.
1071
946
  */
1072
- static _CLASS_NAME = "Base64";
947
+ static defined(source, property, value) {
948
+ if (Is.undefined(value)) {
949
+ throw new GuardError(source, "guard.undefined", property, value);
950
+ }
951
+ }
1073
952
  /**
1074
- * Alphabet table for encoding.
1075
- * @internal
953
+ * Is the property a string.
954
+ * @param source The source of the error.
955
+ * @param property The name of the property.
956
+ * @param value The value to test.
957
+ * @throws GuardError If the value does not match the assertion.
1076
958
  */
1077
- static _LOOKUP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
959
+ static string(source, property, value) {
960
+ if (!Is.string(value)) {
961
+ throw new GuardError(source, "guard.string", property, value);
962
+ }
963
+ }
1078
964
  /**
1079
- * Alphabet table for decoding.
1080
- * @internal
965
+ * Is the property a string with a value.
966
+ * @param source The source of the error.
967
+ * @param property The name of the property.
968
+ * @param value The value to test.
969
+ * @throws GuardError If the value does not match the assertion.
1081
970
  */
1082
- static _REVERSE_LOOKUP = {
1083
- "43": 62,
1084
- "45": 62,
1085
- "47": 63,
1086
- "48": 52,
1087
- "49": 53,
1088
- "50": 54,
1089
- "51": 55,
1090
- "52": 56,
1091
- "53": 57,
1092
- "54": 58,
1093
- "55": 59,
1094
- "56": 60,
1095
- "57": 61,
1096
- "65": 0,
1097
- "66": 1,
1098
- "67": 2,
1099
- "68": 3,
1100
- "69": 4,
1101
- "70": 5,
1102
- "71": 6,
1103
- "72": 7,
1104
- "73": 8,
1105
- "74": 9,
1106
- "75": 10,
1107
- "76": 11,
1108
- "77": 12,
1109
- "78": 13,
1110
- "79": 14,
1111
- "80": 15,
1112
- "81": 16,
1113
- "82": 17,
1114
- "83": 18,
1115
- "84": 19,
1116
- "85": 20,
1117
- "86": 21,
1118
- "87": 22,
1119
- "88": 23,
1120
- "89": 24,
1121
- "90": 25,
1122
- "95": 63,
1123
- "97": 26,
1124
- "98": 27,
1125
- "99": 28,
1126
- "100": 29,
1127
- "101": 30,
1128
- "102": 31,
1129
- "103": 32,
1130
- "104": 33,
1131
- "105": 34,
1132
- "106": 35,
1133
- "107": 36,
1134
- "108": 37,
1135
- "109": 38,
1136
- "110": 39,
1137
- "111": 40,
1138
- "112": 41,
1139
- "113": 42,
1140
- "114": 43,
1141
- "115": 44,
1142
- "116": 45,
1143
- "117": 46,
1144
- "118": 47,
1145
- "119": 48,
1146
- "120": 49,
1147
- "121": 50,
1148
- "122": 51
1149
- };
971
+ static stringValue(source, property, value) {
972
+ if (!Is.string(value)) {
973
+ throw new GuardError(source, "guard.string", property, value);
974
+ }
975
+ if (value.length === 0) {
976
+ throw new GuardError(source, "guard.stringEmpty", property, value);
977
+ }
978
+ }
1150
979
  /**
1151
- * Get the byte length of the data.
1152
- * @param base64 The base64 string.
1153
- * @returns The byte length of the data.
980
+ * Is the property a JSON value.
981
+ * @param source The source of the error.
982
+ * @param property The name of the property.
983
+ * @param value The value to test.
984
+ * @throws GuardError If the value does not match the assertion.
1154
985
  */
1155
- static byteLength(base64) {
1156
- const lens = Base64.getLengths(base64);
1157
- return Base64.calcByteLength(lens[0], lens[1]);
986
+ static json(source, property, value) {
987
+ if (!Is.json(value)) {
988
+ throw new GuardError(source, "guard.stringJson", property, value);
989
+ }
1158
990
  }
1159
991
  /**
1160
- * Convert the base 64 string to a byte array.
1161
- * @param base64 The base64 string to convert.
1162
- * @returns The byte array.
992
+ * Is the property a base64 string.
993
+ * @param source The source of the error.
994
+ * @param property The name of the property.
995
+ * @param value The value to test.
996
+ * @throws GuardError If the value does not match the assertion.
1163
997
  */
1164
- static decode(base64) {
1165
- let tmp;
1166
- const lens = Base64.getLengths(base64);
1167
- const validLen = lens[0];
1168
- const placeHoldersLen = lens[1];
1169
- const arr = new Uint8Array(Base64.calcByteLength(validLen, placeHoldersLen));
1170
- let curByte = 0;
1171
- // if there are placeholders, only get up to the last complete 4 chars
1172
- const len = placeHoldersLen > 0 ? validLen - 4 : validLen;
1173
- let i;
1174
- for (i = 0; i < len; i += 4) {
1175
- tmp =
1176
- (Base64._REVERSE_LOOKUP[base64.charCodeAt(i)] << 18) |
1177
- (Base64._REVERSE_LOOKUP[base64.charCodeAt(i + 1)] << 12) |
1178
- (Base64._REVERSE_LOOKUP[base64.charCodeAt(i + 2)] << 6) |
1179
- Base64._REVERSE_LOOKUP[base64.charCodeAt(i + 3)];
1180
- arr[curByte++] = (tmp >> 16) & 0xff;
1181
- arr[curByte++] = (tmp >> 8) & 0xff;
1182
- arr[curByte++] = tmp & 0xff;
1183
- }
1184
- if (placeHoldersLen === 2) {
1185
- tmp =
1186
- (Base64._REVERSE_LOOKUP[base64.charCodeAt(i)] << 2) |
1187
- (Base64._REVERSE_LOOKUP[base64.charCodeAt(i + 1)] >> 4);
1188
- arr[curByte++] = tmp & 0xff;
998
+ static stringBase64(source, property, value) {
999
+ if (!Is.stringBase64(value)) {
1000
+ throw new GuardError(source, "guard.base64", property, value);
1189
1001
  }
1190
- if (placeHoldersLen === 1) {
1191
- tmp =
1192
- (Base64._REVERSE_LOOKUP[base64.charCodeAt(i)] << 10) |
1193
- (Base64._REVERSE_LOOKUP[base64.charCodeAt(i + 1)] << 4) |
1194
- (Base64._REVERSE_LOOKUP[base64.charCodeAt(i + 2)] >> 2);
1195
- arr[curByte++] = (tmp >> 8) & 0xff;
1196
- arr[curByte++] = tmp & 0xff;
1002
+ }
1003
+ /**
1004
+ * Is the property a base64 url string.
1005
+ * @param source The source of the error.
1006
+ * @param property The name of the property.
1007
+ * @param value The value to test.
1008
+ * @throws GuardError If the value does not match the assertion.
1009
+ */
1010
+ static stringBase64Url(source, property, value) {
1011
+ if (!Is.stringBase64Url(value)) {
1012
+ throw new GuardError(source, "guard.base64Url", property, value);
1197
1013
  }
1198
- return arr;
1199
1014
  }
1200
1015
  /**
1201
- * Convert a byte array to base 64.
1202
- * @param bytes The byte array to convert.
1203
- * @returns The data as base64 string.
1016
+ * Is the property a base58 string.
1017
+ * @param source The source of the error.
1018
+ * @param property The name of the property.
1019
+ * @param value The value to test.
1020
+ * @throws GuardError If the value does not match the assertion.
1204
1021
  */
1205
- static encode(bytes) {
1206
- let tmp;
1207
- const len = bytes.length;
1208
- const extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes
1209
- const parts = [];
1210
- const maxChunkLength = 16383; // must be multiple of 3
1211
- // go through the array every three bytes, we'll deal with trailing stuff later
1212
- for (let i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
1213
- parts.push(Base64.encodeChunk(bytes, i, Math.min(i + maxChunkLength, len2)));
1022
+ static stringBase58(source, property, value) {
1023
+ if (!Is.stringBase58(value)) {
1024
+ throw new GuardError(source, "guard.base58", property, value);
1214
1025
  }
1215
- // pad the end with zeros, but make sure to not forget the extra bytes
1216
- if (extraBytes === 1) {
1217
- tmp = bytes[len - 1];
1218
- parts.push(`${Base64._LOOKUP[tmp >> 2] + Base64._LOOKUP[(tmp << 4) & 0x3f]}==`);
1026
+ }
1027
+ /**
1028
+ * Is the property a string with a hex value.
1029
+ * @param source The source of the error.
1030
+ * @param property The name of the property.
1031
+ * @param value The value to test.
1032
+ * @param allowPrefix Allow the hex to have the 0x prefix.
1033
+ * @throws GuardError If the value does not match the assertion.
1034
+ */
1035
+ static stringHex(source, property, value, allowPrefix = false) {
1036
+ Guards.stringValue(source, property, value);
1037
+ if (!HexHelper.isHex(value, allowPrefix)) {
1038
+ throw new GuardError(source, "guard.stringHex", property, value);
1219
1039
  }
1220
- else if (extraBytes === 2) {
1221
- tmp = (bytes[len - 2] << 8) + bytes[len - 1];
1222
- parts.push(`${Base64._LOOKUP[tmp >> 10] + Base64._LOOKUP[(tmp >> 4) & 0x3f] + Base64._LOOKUP[(tmp << 2) & 0x3f]}=`);
1040
+ }
1041
+ /**
1042
+ * Is the property a string with a hex value with fixed length.
1043
+ * @param source The source of the error.
1044
+ * @param property The name of the property.
1045
+ * @param value The value to test.
1046
+ * @param length The length of the string to match.
1047
+ * @param allowPrefix Allow the hex to have the 0x prefix.
1048
+ * @throws GuardError If the value does not match the assertion.
1049
+ */
1050
+ static stringHexLength(source, property, value, length, allowPrefix = false) {
1051
+ Guards.stringHex(source, property, value, allowPrefix);
1052
+ if (HexHelper.stripPrefix(value).length !== length) {
1053
+ throw new GuardError(source, "guard.stringHexLength", property, value.length, length.toString());
1223
1054
  }
1224
- return parts.join("");
1225
1055
  }
1226
1056
  /**
1227
- * Calculate the byte length.
1228
- * @param validLen The valid length.
1229
- * @param placeHoldersLen The placeholder length.
1230
- * @returns The length.
1231
- * @internal
1057
+ * Is the property a number.
1058
+ * @param source The source of the error.
1059
+ * @param property The name of the property.
1060
+ * @param value The value to test.
1061
+ * @throws GuardError If the value does not match the assertion.
1232
1062
  */
1233
- static calcByteLength(validLen, placeHoldersLen) {
1234
- return ((validLen + placeHoldersLen) * 3) / 4 - placeHoldersLen;
1063
+ static number(source, property, value) {
1064
+ if (!Is.number(value)) {
1065
+ throw new GuardError(source, "guard.number", property, value);
1066
+ }
1235
1067
  }
1236
1068
  /**
1237
- * Get the valid and placeholder lengths from a bas64 string.
1238
- * @param base64 The base64 string.
1239
- * @returns The lengths.
1240
- * @internal
1069
+ * Is the property an integer.
1070
+ * @param source The source of the error.
1071
+ * @param property The name of the property.
1072
+ * @param value The value to test.
1073
+ * @throws GuardError If the value does not match the assertion.
1241
1074
  */
1242
- static getLengths(base64) {
1243
- const len = base64.length;
1244
- if (len % 4 > 0) {
1245
- throw new GeneralError(Base64._CLASS_NAME, "length4Multiple", { value: len });
1075
+ static integer(source, property, value) {
1076
+ if (!Is.integer(value)) {
1077
+ throw new GuardError(source, "guard.integer", property, value);
1246
1078
  }
1247
- // Trim off extra bytes after placeholder bytes are found
1248
- // See: https://github.com/beatgammit/base64-js/issues/42
1249
- let validLen = base64.indexOf("=");
1250
- if (validLen === -1) {
1251
- validLen = len;
1079
+ }
1080
+ /**
1081
+ * Is the property a bigint.
1082
+ * @param source The source of the error.
1083
+ * @param property The name of the property.
1084
+ * @param value The value to test.
1085
+ * @throws GuardError If the value does not match the assertion.
1086
+ */
1087
+ static bigint(source, property, value) {
1088
+ if (!Is.bigint(value)) {
1089
+ throw new GuardError(source, "guard.bigint", property, value);
1252
1090
  }
1253
- const placeHoldersLen = validLen === len ? 0 : 4 - (validLen % 4);
1254
- return [validLen, placeHoldersLen];
1255
1091
  }
1256
1092
  /**
1257
- * Convert the triplet to base 64.
1258
- * @param num The number to convert.
1259
- * @returns The base64 encoding.
1260
- * @internal
1093
+ * Is the property a boolean.
1094
+ * @param source The source of the error.
1095
+ * @param property The name of the property.
1096
+ * @param value The value to test.
1097
+ * @throws GuardError If the value does not match the assertion.
1261
1098
  */
1262
- static tripletToBase64(num) {
1263
- return (Base64._LOOKUP[(num >> 18) & 0x3f] +
1264
- Base64._LOOKUP[(num >> 12) & 0x3f] +
1265
- Base64._LOOKUP[(num >> 6) & 0x3f] +
1266
- Base64._LOOKUP[num & 0x3f]);
1099
+ static boolean(source, property, value) {
1100
+ if (!Is.boolean(value)) {
1101
+ throw new GuardError(source, "guard.boolean", property, value);
1102
+ }
1267
1103
  }
1268
1104
  /**
1269
- * Encode a chunk.
1270
- * @param bytes The byte array.
1271
- * @param start The start index in the buffer.
1272
- * @param end The end index in the buffer.
1273
- * @returns The encoded chunk.
1274
- * @internal
1105
+ * Is the property a date.
1106
+ * @param source The source of the error.
1107
+ * @param property The name of the property.
1108
+ * @param value The value to test.
1109
+ * @throws GuardError If the value does not match the assertion.
1275
1110
  */
1276
- static encodeChunk(bytes, start, end) {
1277
- let tmp;
1278
- const output = [];
1279
- for (let i = start; i < end; i += 3) {
1280
- tmp = ((bytes[i] << 16) & 0xff0000) + ((bytes[i + 1] << 8) & 0xff00) + (bytes[i + 2] & 0xff);
1281
- output.push(Base64.tripletToBase64(tmp));
1111
+ static date(source, property, value) {
1112
+ if (!Is.date(value)) {
1113
+ throw new GuardError(source, "guard.date", property, value);
1282
1114
  }
1283
- return output.join("");
1284
1115
  }
1285
- }
1286
-
1287
- // Copyright 2024 IOTA Stiftung.
1288
- // SPDX-License-Identifier: Apache-2.0.
1289
- /**
1290
- * Class to help with base64 URL Encoding/Decoding.
1291
- * https://www.rfc-editor.org/rfc/rfc4648#section-5.
1292
- */
1293
- class Base64Url {
1294
1116
  /**
1295
- * Convert the base 64 string to a byte array.
1296
- * @param base64Url The base64 url string to convert.
1297
- * @returns The byte array.
1117
+ * Is the property a timestamp in milliseconds.
1118
+ * @param source The source of the error.
1119
+ * @param property The name of the property.
1120
+ * @param value The value to test.
1121
+ * @throws GuardError If the value does not match the assertion.
1298
1122
  */
1299
- static decode(base64Url) {
1300
- let base64 = base64Url;
1301
- // Base 64 url can have padding removed, so add it back if it is missing.
1302
- if (base64.length > 0 && !base64.endsWith("=")) {
1303
- const placeHoldersLen = 4 - (base64.length % 4);
1304
- if (placeHoldersLen > 0 && placeHoldersLen < 4) {
1305
- base64 = base64.padEnd(base64.length + placeHoldersLen, "=");
1306
- }
1123
+ static timestampMilliseconds(source, property, value) {
1124
+ if (!Is.timestampMilliseconds(value)) {
1125
+ throw new GuardError(source, "guard.timestampMilliseconds", property, value);
1307
1126
  }
1308
- base64 = base64.replace(/-/g, "+").replace(/_/g, "/");
1309
- return Base64.decode(base64);
1310
1127
  }
1311
1128
  /**
1312
- * Convert a byte array to base 64 url.
1313
- * @param bytes The byte array to convert.
1314
- * @returns The data as base64 url string.
1129
+ * Is the property a timestamp in seconds.
1130
+ * @param source The source of the error.
1131
+ * @param property The name of the property.
1132
+ * @param value The value to test.
1133
+ * @throws GuardError If the value does not match the assertion.
1315
1134
  */
1316
- static encode(bytes) {
1317
- const base64 = Base64.encode(bytes);
1318
- // Base 64 url can have padding removed, so remove it.
1319
- return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
1135
+ static timestampSeconds(source, property, value) {
1136
+ if (!Is.timestampSeconds(value)) {
1137
+ throw new GuardError(source, "guard.timestampSeconds", property, value);
1138
+ }
1320
1139
  }
1321
- }
1322
-
1323
- /**
1324
- * Class to handle errors which are triggered by data already existing.
1325
- */
1326
- class AlreadyExistsError extends BaseError {
1327
1140
  /**
1328
- * Runtime name for the class.
1141
+ * Is the property an object.
1142
+ * @param source The source of the error.
1143
+ * @param property The name of the property.
1144
+ * @param value The value to test.
1145
+ * @throws GuardError If the value does not match the assertion.
1329
1146
  */
1330
- static CLASS_NAME = "AlreadyExistsError";
1147
+ static object(source, property, value) {
1148
+ if (Is.undefined(value)) {
1149
+ throw new GuardError(source, "guard.objectUndefined", property, value);
1150
+ }
1151
+ if (!Is.object(value)) {
1152
+ throw new GuardError(source, "guard.object", property, value);
1153
+ }
1154
+ }
1331
1155
  /**
1332
- * Create a new instance of AlreadyExistsError.
1156
+ * Is the property is an object with at least one property.
1333
1157
  * @param source The source of the error.
1334
- * @param message The message as a code.
1335
- * @param existingId The id for the item.
1336
- * @param inner The inner error if we have wrapped another error.
1158
+ * @param property The name of the property.
1159
+ * @param value The value to test.
1160
+ * @throws GuardError If the value does not match the assertion.
1337
1161
  */
1338
- constructor(source, message, existingId, inner) {
1339
- super(AlreadyExistsError.CLASS_NAME, source, message, { existingId }, inner);
1162
+ static objectValue(source, property, value) {
1163
+ if (Is.undefined(value)) {
1164
+ throw new GuardError(source, "guard.objectUndefined", property, value);
1165
+ }
1166
+ if (!Is.object(value)) {
1167
+ throw new GuardError(source, "guard.object", property, value);
1168
+ }
1169
+ if (Object.keys(value || {}).length === 0) {
1170
+ throw new GuardError(source, "guard.objectValue", property, value);
1171
+ }
1340
1172
  }
1341
- }
1342
-
1343
- /**
1344
- * Class to handle errors which are triggered by conflicting data.
1345
- */
1346
- class ConflictError extends BaseError {
1347
- /**
1348
- * Runtime name for the class.
1349
- */
1350
- static CLASS_NAME = "ConflictError";
1351
1173
  /**
1352
- * Create a new instance of ConflictError.
1174
+ * Is the property is an array.
1353
1175
  * @param source The source of the error.
1354
- * @param message The message as a code.
1355
- * @param conflictId The id that has conflicts.
1356
- * @param conflicts The conflicts that occurred.
1357
- * @param inner The inner error if we have wrapped another error.
1176
+ * @param property The name of the property.
1177
+ * @param value The value to test.
1178
+ * @throws GuardError If the value does not match the assertion.
1358
1179
  */
1359
- constructor(source, message, conflictId, conflicts, inner) {
1360
- super(ConflictError.CLASS_NAME, source, message, { conflictId, conflicts }, inner);
1180
+ static array(source, property, value) {
1181
+ if (!Is.array(value)) {
1182
+ throw new GuardError(source, "guard.array", property, value);
1183
+ }
1361
1184
  }
1362
- }
1363
-
1364
- /**
1365
- * Class to handle errors which are triggered by data guards.
1366
- */
1367
- class GuardError extends BaseError {
1368
1185
  /**
1369
- * Runtime name for the class.
1370
- */
1371
- static CLASS_NAME = "GuardError";
1372
- /**
1373
- * Create a new instance of GuardError.
1186
+ * Is the property is an array with at least one item.
1374
1187
  * @param source The source of the error.
1375
- * @param message The message as a code.
1376
- * @param propertyName The property which triggered the guard error for the item.
1377
- * @param propertyValue The property value which triggered the guard error for the item.
1378
- * @param propertyOptions The property options which might be allowed.
1188
+ * @param property The name of the property.
1189
+ * @param value The value to test.
1190
+ * @throws GuardError If the value does not match the assertion.
1379
1191
  */
1380
- constructor(source, message, propertyName, propertyValue, propertyOptions) {
1381
- super(GuardError.CLASS_NAME, source, message, {
1382
- property: propertyName ?? "property",
1383
- value: Is.undefined(propertyValue) ? "undefined" : propertyValue,
1384
- options: propertyOptions
1385
- });
1192
+ static arrayValue(source, property, value) {
1193
+ if (!Is.array(value)) {
1194
+ throw new GuardError(source, "guard.array", property, value);
1195
+ }
1196
+ if (value.length === 0) {
1197
+ throw new GuardError(source, "guard.arrayValue", property, value);
1198
+ }
1386
1199
  }
1387
- }
1388
-
1389
- /**
1390
- * Class to handle errors which are triggered by data not being found.
1391
- */
1392
- class NotFoundError extends BaseError {
1393
1200
  /**
1394
- * Runtime name for the class.
1201
+ * Is the property one of a list of items.
1202
+ * @param source The source of the error.
1203
+ * @param property The name of the property.
1204
+ * @param value The value to test.
1205
+ * @param options The options the value must be one of.
1206
+ * @throws GuardError If the value does not match the assertion.
1395
1207
  */
1396
- static CLASS_NAME = "NotFoundError";
1208
+ static arrayOneOf(source, property, value, options) {
1209
+ if (!Is.array(options)) {
1210
+ throw new GuardError(source, "guard.array", property, value);
1211
+ }
1212
+ if (!options.includes(value)) {
1213
+ throw new GuardError(source, "guard.arrayOneOf", property, value, options.join(", "));
1214
+ }
1215
+ }
1397
1216
  /**
1398
- * Create a new instance of NotFoundError.
1217
+ * Does the array start with the specified data.
1399
1218
  * @param source The source of the error.
1400
- * @param message The message as a code.
1401
- * @param notFoundId The id for the item.
1402
- * @param inner The inner error if we have wrapped another error.
1219
+ * @param property The name of the property.
1220
+ * @param value The value to test.
1221
+ * @param startValues The values that must start the array.
1222
+ * @throws GuardError If the value does not match the assertion.
1403
1223
  */
1404
- constructor(source, message, notFoundId, inner) {
1405
- super(NotFoundError.CLASS_NAME, source, message, { notFoundId }, inner);
1224
+ static arrayStartsWith(source, property, value, startValues) {
1225
+ if (!Is.arrayValue(value)) {
1226
+ throw new GuardError(source, "guard.array", property, value);
1227
+ }
1228
+ const startValuesArray = ArrayHelper.fromObjectOrArray(startValues);
1229
+ if (!Is.arrayValue(startValuesArray)) {
1230
+ throw new GuardError(source, "guard.array", property, startValuesArray);
1231
+ }
1232
+ for (let i = 0; i < startValuesArray.length; i++) {
1233
+ if (value[i] !== startValuesArray[i]) {
1234
+ throw new GuardError(source, "guard.arrayStartsWith", property, value, startValuesArray.join(", "));
1235
+ }
1236
+ }
1406
1237
  }
1407
- }
1408
-
1409
- /**
1410
- * Class to handle errors.
1411
- */
1412
- class NotImplementedError extends BaseError {
1413
1238
  /**
1414
- * Runtime name for the class.
1239
+ * Does the array end with the specified data.
1240
+ * @param source The source of the error.
1241
+ * @param property The name of the property.
1242
+ * @param value The value to test.
1243
+ * @param endValues The values that must end the array.
1244
+ * @throws GuardError If the value does not match the assertion.
1415
1245
  */
1416
- static CLASS_NAME = "NotImplementedError";
1246
+ static arrayEndsWith(source, property, value, endValues) {
1247
+ if (!Is.arrayValue(value)) {
1248
+ throw new GuardError(source, "guard.array", property, value);
1249
+ }
1250
+ const endValuesArray = ArrayHelper.fromObjectOrArray(endValues);
1251
+ if (!Is.arrayValue(endValuesArray)) {
1252
+ throw new GuardError(source, "guard.array", property, endValuesArray);
1253
+ }
1254
+ for (let i = 0; i < endValuesArray.length; i++) {
1255
+ if (value[value.length - i - 1] !== endValuesArray[endValuesArray.length - i - 1]) {
1256
+ throw new GuardError(source, "guard.arrayEndsWith", property, value, endValuesArray.join(", "));
1257
+ }
1258
+ }
1259
+ }
1417
1260
  /**
1418
- * Create a new instance of NotImplementedError.
1261
+ * Is the property a Uint8Array.
1419
1262
  * @param source The source of the error.
1420
- * @param method The method for the error.
1263
+ * @param property The name of the property.
1264
+ * @param value The value to test.
1265
+ * @throws GuardError If the value does not match the assertion.
1421
1266
  */
1422
- constructor(source, method) {
1423
- super(NotImplementedError.CLASS_NAME, source, "common.notImplementedMethod", {
1424
- method
1425
- });
1267
+ static uint8Array(source, property, value) {
1268
+ if (!Is.uint8Array(value)) {
1269
+ throw new GuardError(source, "guard.uint8Array", property, value);
1270
+ }
1426
1271
  }
1427
- }
1428
-
1429
- /**
1430
- * Class to handle errors when a feature is unsupported.
1431
- */
1432
- class NotSupportedError extends BaseError {
1433
1272
  /**
1434
- * Runtime name for the class.
1273
+ * Is the property a function.
1274
+ * @param source The source of the error.
1275
+ * @param property The name of the property.
1276
+ * @param value The value to test.
1277
+ * @returns True if the value is a function.
1278
+ * @throws GuardError If the value does not match the assertion.
1435
1279
  */
1436
- static CLASS_NAME = "NotSupportedError";
1280
+ static function(source, property, value) {
1281
+ if (!Is.function(value)) {
1282
+ throw new GuardError(source, "guard.function", property, value);
1283
+ }
1284
+ return true;
1285
+ }
1437
1286
  /**
1438
- * Create a new instance of NotSupportedError.
1287
+ * Is the property a string formatted as an email address.
1439
1288
  * @param source The source of the error.
1440
- * @param message The message as a code.
1441
- * @param inner The inner error if we have wrapped another error.
1289
+ * @param property The name of the property.
1290
+ * @param value The value to test.
1291
+ * @throws GuardError If the value does not match the assertion.
1442
1292
  */
1443
- constructor(source, message, inner) {
1444
- super(NotSupportedError.CLASS_NAME, source, message, undefined, inner);
1293
+ static email(source, property, value) {
1294
+ if (!Is.email(value)) {
1295
+ throw new GuardError(source, "guard.email", property, value);
1296
+ }
1445
1297
  }
1446
1298
  }
1447
1299
 
1300
+ // Copyright 2024 IOTA Stiftung.
1301
+ // SPDX-License-Identifier: Apache-2.0.
1302
+ /* eslint-disable no-bitwise */
1448
1303
  /**
1449
- * Class to handle errors which are triggered by access not being unauthorized.
1304
+ * Class to help with base63 Encoding/Decoding.
1450
1305
  */
1451
- class UnauthorizedError extends BaseError {
1306
+ class Base32 {
1452
1307
  /**
1453
1308
  * Runtime name for the class.
1309
+ * @internal
1454
1310
  */
1455
- static CLASS_NAME = "UnauthorizedError";
1311
+ static _CLASS_NAME = "Base32";
1456
1312
  /**
1457
- * Create a new instance of UnauthorizedError.
1458
- * @param source The source of the error.
1459
- * @param message The message as a code.
1460
- * @param inner The inner error if we have wrapped another error.
1313
+ * Alphabet table for encoding.
1314
+ * @internal
1461
1315
  */
1462
- constructor(source, message, inner) {
1463
- super(UnauthorizedError.CLASS_NAME, source, message, undefined, inner);
1464
- }
1465
- }
1466
-
1467
- /**
1468
- * Class to handle errors when some data can not be processed.
1469
- */
1470
- class UnprocessableError extends BaseError {
1316
+ static _ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
1471
1317
  /**
1472
- * Runtime name for the class.
1318
+ * Convert the base 32 string to a byte array.
1319
+ * @param base32 The base32 string to convert.
1320
+ * @returns The byte array.
1321
+ * @throws If the input string contains a character not in the Base32 alphabet.
1473
1322
  */
1474
- static CLASS_NAME = "UnprocessableError";
1323
+ static decode(base32) {
1324
+ Guards.string(Base32._CLASS_NAME, "base32", base32);
1325
+ let bits = 0;
1326
+ let value = 0;
1327
+ base32 = base32.replace(/=+$/, "");
1328
+ let index = 0;
1329
+ const output = new Uint8Array(Math.trunc((base32.length * 5) / 8));
1330
+ for (let i = 0; i < base32.length; i++) {
1331
+ const idx = Base32._ALPHABET.indexOf(base32[i]);
1332
+ if (idx === -1) {
1333
+ throw new GeneralError(Base32._CLASS_NAME, "invalidCharacter", {
1334
+ invalidCharacter: base32[i]
1335
+ });
1336
+ }
1337
+ value = (value << 5) | idx;
1338
+ bits += 5;
1339
+ if (bits >= 8) {
1340
+ output[index++] = (value >>> (bits - 8)) & 255;
1341
+ bits -= 8;
1342
+ }
1343
+ }
1344
+ return output;
1345
+ }
1475
1346
  /**
1476
- * Create a new instance of UnprocessableError.
1477
- * @param source The source of the error.
1478
- * @param message The message as a code.
1479
- * @param properties Any additional information for the error.
1480
- * @param inner The inner error if we have wrapped another error.
1347
+ * Convert a byte array to base 32.
1348
+ * @param bytes The byte array to convert.
1349
+ * @returns The data as base32 string.
1481
1350
  */
1482
- constructor(source, message, properties, inner) {
1483
- super(UnprocessableError.CLASS_NAME, source, message, properties, inner);
1351
+ static encode(bytes) {
1352
+ Guards.uint8Array(Base32._CLASS_NAME, "bytes", bytes);
1353
+ let bits = 0;
1354
+ let value = 0;
1355
+ let output = "";
1356
+ for (let i = 0; i < bytes.byteLength; i++) {
1357
+ value = (value << 8) | bytes[i];
1358
+ bits += 8;
1359
+ while (bits >= 5) {
1360
+ output += Base32._ALPHABET[(value >>> (bits - 5)) & 31];
1361
+ bits -= 5;
1362
+ }
1363
+ }
1364
+ if (bits > 0) {
1365
+ output += Base32._ALPHABET[(value << (5 - bits)) & 31];
1366
+ }
1367
+ while (output.length % 8 !== 0) {
1368
+ output += "=";
1369
+ }
1370
+ return output;
1484
1371
  }
1485
1372
  }
1486
1373
 
1487
1374
  /**
1488
- * Class to handle errors which are triggered by entity validation.
1375
+ * Class to help with base58 Encoding/Decoding.
1489
1376
  */
1490
- class ValidationError extends BaseError {
1377
+ class Base58 {
1491
1378
  /**
1492
- * Runtime name for the class.s
1379
+ * Runtime name for the class.
1380
+ * @internal
1493
1381
  */
1494
- static CLASS_NAME = "ValidationError";
1382
+ static _CLASS_NAME = "Base58";
1495
1383
  /**
1496
- * Create a new instance of ValidationError.
1497
- * @param source The source of the error.
1498
- * @param validationObject The object that failed validation.
1499
- * @param validationFailures The validation failures.
1384
+ * Alphabet table for encoding.
1385
+ * @internal
1500
1386
  */
1501
- constructor(source, validationObject, validationFailures) {
1502
- super(ValidationError.CLASS_NAME, source, "common.validation", {
1503
- validationObject,
1504
- validationFailures
1505
- });
1506
- }
1507
- }
1508
-
1509
- /**
1510
- * Class to help with arrays.
1511
- */
1512
- class ArrayHelper {
1387
+ static _ALPHABET =
1388
+ // cspell:disable-next-line
1389
+ "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
1513
1390
  /**
1514
- * Do the two arrays match.
1515
- * @param arr1 The first array.
1516
- * @param arr2 The second array.
1517
- * @returns True if both arrays are empty of have the same values.
1391
+ * Reverse map for decoding.
1392
+ * @internal
1518
1393
  */
1519
- static matches(arr1, arr2) {
1520
- if (Is.empty(arr1) && Is.empty(arr2)) {
1521
- return true;
1394
+ static _ALPHABET_REVERSE = [
1395
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1396
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1397
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1, 9, 10, 11, 12, 13, 14, 15, 16, -1,
1398
+ 17, 18, 19, 20, 21, -1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, 33,
1399
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
1400
+ 57, -1, -1, -1, -1, -1
1401
+ ];
1402
+ /**
1403
+ * Convert the base 58 string to a byte array.
1404
+ * @param base58 The base58 string to convert.
1405
+ * @returns The byte array.
1406
+ * @throws If the input string contains a character not in the Base58 alphabet.
1407
+ */
1408
+ static decode(base58) {
1409
+ Guards.string(Base58._CLASS_NAME, "base58", base58);
1410
+ let zeroes = 0;
1411
+ for (let i = 0; i < base58.length; i++) {
1412
+ if (base58[i] !== "1") {
1413
+ break;
1414
+ }
1415
+ zeroes += 1;
1522
1416
  }
1523
- if (!((Is.array(arr1) && Is.array(arr2)) || (Is.typedArray(arr1) && Is.typedArray(arr2)))) {
1524
- return false;
1417
+ const size = Math.trunc((base58.length * 733) / 1000) + 1;
1418
+ const b256 = new Uint8Array(size).fill(0);
1419
+ let length = 0;
1420
+ for (let i = zeroes; i < base58.length; i++) {
1421
+ const ch = base58.charCodeAt(i);
1422
+ if (ch & 0xff80) {
1423
+ throw new GeneralError(Base58._CLASS_NAME, "invalidCharacter", { invalidCharacter: ch });
1424
+ }
1425
+ const val = Base58._ALPHABET_REVERSE[ch];
1426
+ if (val === -1) {
1427
+ throw new GeneralError(Base58._CLASS_NAME, "invalidCharacter", { invalidCharacter: ch });
1428
+ }
1429
+ let carry = val;
1430
+ let j = 0;
1431
+ for (let k = size - 1; k >= 0; k--, j++) {
1432
+ if (carry === 0 && j >= length) {
1433
+ break;
1434
+ }
1435
+ carry += b256[k] * 58;
1436
+ b256[k] = carry;
1437
+ carry >>>= 8;
1438
+ }
1439
+ length = j;
1525
1440
  }
1526
- if (arr1.length !== arr2.length) {
1527
- return false;
1441
+ const out = new Uint8Array(zeroes + length);
1442
+ let j;
1443
+ for (j = 0; j < zeroes; j++) {
1444
+ out[j] = 0;
1528
1445
  }
1529
- for (let i = 0; i < arr1.length; i++) {
1530
- if (arr1[i] !== arr2[i]) {
1531
- return false;
1532
- }
1446
+ let i = size - length;
1447
+ while (i < size) {
1448
+ out[j++] = b256[i++];
1533
1449
  }
1534
- return true;
1450
+ return out;
1535
1451
  }
1536
1452
  /**
1537
- * Convert an object or array to an array.
1538
- * @param value The object or array to convert.
1539
- * @returns The array.
1453
+ * Convert a byte array to base 58.
1454
+ * @param bytes The byte array to encode.
1455
+ * @returns The data as base58 string.
1540
1456
  */
1541
- static fromObjectOrArray(value) {
1542
- if (Is.empty(value)) {
1543
- return undefined;
1457
+ static encode(bytes) {
1458
+ Guards.uint8Array(Base58._CLASS_NAME, "bytes", bytes);
1459
+ let zeroes = 0;
1460
+ for (let i = 0; i < bytes.length; i++) {
1461
+ if (bytes[i] !== 0) {
1462
+ break;
1463
+ }
1464
+ zeroes += 1;
1544
1465
  }
1545
- if (Is.array(value)) {
1546
- return value;
1466
+ const size = Math.trunc(((bytes.length - zeroes) * 138) / 100) + 1;
1467
+ const b58 = new Uint8Array(size).fill(0);
1468
+ let length = 0;
1469
+ for (let i = zeroes; i < bytes.length; i++) {
1470
+ let carry = bytes[i];
1471
+ let j = 0;
1472
+ for (let k = size - 1; k >= 0; k--, j++) {
1473
+ if (carry === 0 && j >= length) {
1474
+ break;
1475
+ }
1476
+ carry += b58[k] * 256;
1477
+ b58[k] = carry % 58;
1478
+ carry = Math.trunc(carry / 58);
1479
+ }
1480
+ length = j;
1547
1481
  }
1548
- return [value];
1482
+ let i = size - length;
1483
+ while (i < size && b58[i] === 0) {
1484
+ i += 1;
1485
+ }
1486
+ let str = "";
1487
+ for (let j = 0; j < zeroes; j++) {
1488
+ str += "1";
1489
+ }
1490
+ while (i < size) {
1491
+ str += Base58._ALPHABET[b58[i++]];
1492
+ }
1493
+ return str;
1549
1494
  }
1550
1495
  }
1551
1496
 
1552
1497
  // Copyright 2024 IOTA Stiftung.
1553
1498
  // SPDX-License-Identifier: Apache-2.0.
1499
+ /* eslint-disable no-bitwise */
1500
+ /* eslint-disable no-mixed-operators */
1554
1501
  /**
1555
- * Class to handle guard operations for parameters.
1502
+ * Class to help with base64 Encoding/Decoding.
1503
+ * Sourced from https://github.com/beatgammit/base64-js.
1556
1504
  */
1557
- class Guards {
1505
+ class Base64 {
1558
1506
  /**
1559
- * Is the property defined.
1560
- * @param source The source of the error.
1561
- * @param property The name of the property.
1562
- * @param value The value to test.
1563
- * @throws GuardError If the value does not match the assertion.
1507
+ * Runtime name for the class.
1508
+ * @internal
1564
1509
  */
1565
- static defined(source, property, value) {
1566
- if (Is.undefined(value)) {
1567
- throw new GuardError(source, "guard.undefined", property, value);
1568
- }
1569
- }
1510
+ static _CLASS_NAME = "Base64";
1570
1511
  /**
1571
- * Is the property a string.
1572
- * @param source The source of the error.
1573
- * @param property The name of the property.
1574
- * @param value The value to test.
1575
- * @throws GuardError If the value does not match the assertion.
1512
+ * Alphabet table for encoding.
1513
+ * @internal
1514
+ */
1515
+ static _LOOKUP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1516
+ /**
1517
+ * Alphabet table for decoding.
1518
+ * @internal
1519
+ */
1520
+ static _REVERSE_LOOKUP = {
1521
+ "43": 62,
1522
+ "45": 62,
1523
+ "47": 63,
1524
+ "48": 52,
1525
+ "49": 53,
1526
+ "50": 54,
1527
+ "51": 55,
1528
+ "52": 56,
1529
+ "53": 57,
1530
+ "54": 58,
1531
+ "55": 59,
1532
+ "56": 60,
1533
+ "57": 61,
1534
+ "65": 0,
1535
+ "66": 1,
1536
+ "67": 2,
1537
+ "68": 3,
1538
+ "69": 4,
1539
+ "70": 5,
1540
+ "71": 6,
1541
+ "72": 7,
1542
+ "73": 8,
1543
+ "74": 9,
1544
+ "75": 10,
1545
+ "76": 11,
1546
+ "77": 12,
1547
+ "78": 13,
1548
+ "79": 14,
1549
+ "80": 15,
1550
+ "81": 16,
1551
+ "82": 17,
1552
+ "83": 18,
1553
+ "84": 19,
1554
+ "85": 20,
1555
+ "86": 21,
1556
+ "87": 22,
1557
+ "88": 23,
1558
+ "89": 24,
1559
+ "90": 25,
1560
+ "95": 63,
1561
+ "97": 26,
1562
+ "98": 27,
1563
+ "99": 28,
1564
+ "100": 29,
1565
+ "101": 30,
1566
+ "102": 31,
1567
+ "103": 32,
1568
+ "104": 33,
1569
+ "105": 34,
1570
+ "106": 35,
1571
+ "107": 36,
1572
+ "108": 37,
1573
+ "109": 38,
1574
+ "110": 39,
1575
+ "111": 40,
1576
+ "112": 41,
1577
+ "113": 42,
1578
+ "114": 43,
1579
+ "115": 44,
1580
+ "116": 45,
1581
+ "117": 46,
1582
+ "118": 47,
1583
+ "119": 48,
1584
+ "120": 49,
1585
+ "121": 50,
1586
+ "122": 51
1587
+ };
1588
+ /**
1589
+ * Get the byte length of the data.
1590
+ * @param base64 The base64 string.
1591
+ * @returns The byte length of the data.
1576
1592
  */
1577
- static string(source, property, value) {
1578
- if (!Is.string(value)) {
1579
- throw new GuardError(source, "guard.string", property, value);
1580
- }
1593
+ static byteLength(base64) {
1594
+ const lens = Base64.getLengths(base64);
1595
+ return Base64.calcByteLength(lens[0], lens[1]);
1581
1596
  }
1582
1597
  /**
1583
- * Is the property a string with a value.
1584
- * @param source The source of the error.
1585
- * @param property The name of the property.
1586
- * @param value The value to test.
1587
- * @throws GuardError If the value does not match the assertion.
1598
+ * Convert the base 64 string to a byte array.
1599
+ * @param base64 The base64 string to convert.
1600
+ * @returns The byte array.
1588
1601
  */
1589
- static stringValue(source, property, value) {
1590
- if (!Is.string(value)) {
1591
- throw new GuardError(source, "guard.string", property, value);
1602
+ static decode(base64) {
1603
+ Guards.string(Base64._CLASS_NAME, "base64", base64);
1604
+ let tmp;
1605
+ const lens = Base64.getLengths(base64);
1606
+ const validLen = lens[0];
1607
+ const placeHoldersLen = lens[1];
1608
+ const arr = new Uint8Array(Base64.calcByteLength(validLen, placeHoldersLen));
1609
+ let curByte = 0;
1610
+ // if there are placeholders, only get up to the last complete 4 chars
1611
+ const len = placeHoldersLen > 0 ? validLen - 4 : validLen;
1612
+ let i;
1613
+ for (i = 0; i < len; i += 4) {
1614
+ tmp =
1615
+ (Base64._REVERSE_LOOKUP[base64.charCodeAt(i)] << 18) |
1616
+ (Base64._REVERSE_LOOKUP[base64.charCodeAt(i + 1)] << 12) |
1617
+ (Base64._REVERSE_LOOKUP[base64.charCodeAt(i + 2)] << 6) |
1618
+ Base64._REVERSE_LOOKUP[base64.charCodeAt(i + 3)];
1619
+ arr[curByte++] = (tmp >> 16) & 0xff;
1620
+ arr[curByte++] = (tmp >> 8) & 0xff;
1621
+ arr[curByte++] = tmp & 0xff;
1592
1622
  }
1593
- if (value.length === 0) {
1594
- throw new GuardError(source, "guard.stringEmpty", property, value);
1623
+ if (placeHoldersLen === 2) {
1624
+ tmp =
1625
+ (Base64._REVERSE_LOOKUP[base64.charCodeAt(i)] << 2) |
1626
+ (Base64._REVERSE_LOOKUP[base64.charCodeAt(i + 1)] >> 4);
1627
+ arr[curByte++] = tmp & 0xff;
1628
+ }
1629
+ if (placeHoldersLen === 1) {
1630
+ tmp =
1631
+ (Base64._REVERSE_LOOKUP[base64.charCodeAt(i)] << 10) |
1632
+ (Base64._REVERSE_LOOKUP[base64.charCodeAt(i + 1)] << 4) |
1633
+ (Base64._REVERSE_LOOKUP[base64.charCodeAt(i + 2)] >> 2);
1634
+ arr[curByte++] = (tmp >> 8) & 0xff;
1635
+ arr[curByte++] = tmp & 0xff;
1595
1636
  }
1637
+ return arr;
1596
1638
  }
1597
1639
  /**
1598
- * Is the property a JSON value.
1599
- * @param source The source of the error.
1600
- * @param property The name of the property.
1601
- * @param value The value to test.
1602
- * @throws GuardError If the value does not match the assertion.
1640
+ * Convert a byte array to base 64.
1641
+ * @param bytes The byte array to convert.
1642
+ * @returns The data as base64 string.
1603
1643
  */
1604
- static json(source, property, value) {
1605
- if (!Is.json(value)) {
1606
- throw new GuardError(source, "guard.stringJson", property, value);
1644
+ static encode(bytes) {
1645
+ Guards.uint8Array(Base64._CLASS_NAME, "bytes", bytes);
1646
+ let tmp;
1647
+ const len = bytes.length;
1648
+ const extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes
1649
+ const parts = [];
1650
+ const maxChunkLength = 16383; // must be multiple of 3
1651
+ // go through the array every three bytes, we'll deal with trailing stuff later
1652
+ for (let i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
1653
+ parts.push(Base64.encodeChunk(bytes, i, Math.min(i + maxChunkLength, len2)));
1654
+ }
1655
+ // pad the end with zeros, but make sure to not forget the extra bytes
1656
+ if (extraBytes === 1) {
1657
+ tmp = bytes[len - 1];
1658
+ parts.push(`${Base64._LOOKUP[tmp >> 2] + Base64._LOOKUP[(tmp << 4) & 0x3f]}==`);
1659
+ }
1660
+ else if (extraBytes === 2) {
1661
+ tmp = (bytes[len - 2] << 8) + bytes[len - 1];
1662
+ parts.push(`${Base64._LOOKUP[tmp >> 10] + Base64._LOOKUP[(tmp >> 4) & 0x3f] + Base64._LOOKUP[(tmp << 2) & 0x3f]}=`);
1607
1663
  }
1664
+ return parts.join("");
1608
1665
  }
1609
1666
  /**
1610
- * Is the property a base64 string.
1611
- * @param source The source of the error.
1612
- * @param property The name of the property.
1613
- * @param value The value to test.
1614
- * @throws GuardError If the value does not match the assertion.
1667
+ * Calculate the byte length.
1668
+ * @param validLen The valid length.
1669
+ * @param placeHoldersLen The placeholder length.
1670
+ * @returns The length.
1671
+ * @internal
1615
1672
  */
1616
- static stringBase64(source, property, value) {
1617
- if (!Is.stringBase64(value)) {
1618
- throw new GuardError(source, "guard.base64", property, value);
1619
- }
1673
+ static calcByteLength(validLen, placeHoldersLen) {
1674
+ return ((validLen + placeHoldersLen) * 3) / 4 - placeHoldersLen;
1620
1675
  }
1621
1676
  /**
1622
- * Is the property a base64 url string.
1623
- * @param source The source of the error.
1624
- * @param property The name of the property.
1625
- * @param value The value to test.
1626
- * @throws GuardError If the value does not match the assertion.
1677
+ * Get the valid and placeholder lengths from a bas64 string.
1678
+ * @param base64 The base64 string.
1679
+ * @returns The lengths.
1680
+ * @internal
1627
1681
  */
1628
- static stringBase64Url(source, property, value) {
1629
- if (!Is.stringBase64Url(value)) {
1630
- throw new GuardError(source, "guard.base64Url", property, value);
1682
+ static getLengths(base64) {
1683
+ const len = base64.length;
1684
+ if (len % 4 > 0) {
1685
+ throw new GeneralError(Base64._CLASS_NAME, "length4Multiple", { value: len });
1686
+ }
1687
+ // Trim off extra bytes after placeholder bytes are found
1688
+ // See: https://github.com/beatgammit/base64-js/issues/42
1689
+ let validLen = base64.indexOf("=");
1690
+ if (validLen === -1) {
1691
+ validLen = len;
1631
1692
  }
1693
+ const placeHoldersLen = validLen === len ? 0 : 4 - (validLen % 4);
1694
+ return [validLen, placeHoldersLen];
1632
1695
  }
1633
1696
  /**
1634
- * Is the property a base58 string.
1635
- * @param source The source of the error.
1636
- * @param property The name of the property.
1637
- * @param value The value to test.
1638
- * @throws GuardError If the value does not match the assertion.
1697
+ * Convert the triplet to base 64.
1698
+ * @param num The number to convert.
1699
+ * @returns The base64 encoding.
1700
+ * @internal
1639
1701
  */
1640
- static stringBase58(source, property, value) {
1641
- if (!Is.stringBase58(value)) {
1642
- throw new GuardError(source, "guard.base58", property, value);
1643
- }
1702
+ static tripletToBase64(num) {
1703
+ return (Base64._LOOKUP[(num >> 18) & 0x3f] +
1704
+ Base64._LOOKUP[(num >> 12) & 0x3f] +
1705
+ Base64._LOOKUP[(num >> 6) & 0x3f] +
1706
+ Base64._LOOKUP[num & 0x3f]);
1644
1707
  }
1645
1708
  /**
1646
- * Is the property a string with a hex value.
1647
- * @param source The source of the error.
1648
- * @param property The name of the property.
1649
- * @param value The value to test.
1650
- * @param allowPrefix Allow the hex to have the 0x prefix.
1651
- * @throws GuardError If the value does not match the assertion.
1709
+ * Encode a chunk.
1710
+ * @param bytes The byte array.
1711
+ * @param start The start index in the buffer.
1712
+ * @param end The end index in the buffer.
1713
+ * @returns The encoded chunk.
1714
+ * @internal
1652
1715
  */
1653
- static stringHex(source, property, value, allowPrefix = false) {
1654
- Guards.stringValue(source, property, value);
1655
- if (!HexHelper.isHex(value, allowPrefix)) {
1656
- throw new GuardError(source, "guard.stringHex", property, value);
1716
+ static encodeChunk(bytes, start, end) {
1717
+ let tmp;
1718
+ const output = [];
1719
+ for (let i = start; i < end; i += 3) {
1720
+ tmp = ((bytes[i] << 16) & 0xff0000) + ((bytes[i + 1] << 8) & 0xff00) + (bytes[i + 2] & 0xff);
1721
+ output.push(Base64.tripletToBase64(tmp));
1657
1722
  }
1723
+ return output.join("");
1658
1724
  }
1725
+ }
1726
+
1727
+ /**
1728
+ * Class to help with base64 URL Encoding/Decoding.
1729
+ * https://www.rfc-editor.org/rfc/rfc4648#section-5.
1730
+ */
1731
+ class Base64Url {
1659
1732
  /**
1660
- * Is the property a string with a hex value with fixed length.
1661
- * @param source The source of the error.
1662
- * @param property The name of the property.
1663
- * @param value The value to test.
1664
- * @param length The length of the string to match.
1665
- * @param allowPrefix Allow the hex to have the 0x prefix.
1666
- * @throws GuardError If the value does not match the assertion.
1733
+ * Runtime name for the class.
1734
+ * @internal
1667
1735
  */
1668
- static stringHexLength(source, property, value, length, allowPrefix = false) {
1669
- Guards.stringHex(source, property, value, allowPrefix);
1670
- if (HexHelper.stripPrefix(value).length !== length) {
1671
- throw new GuardError(source, "guard.stringHexLength", property, value.length, length.toString());
1672
- }
1673
- }
1736
+ static _CLASS_NAME = "Base64";
1674
1737
  /**
1675
- * Is the property a number.
1676
- * @param source The source of the error.
1677
- * @param property The name of the property.
1678
- * @param value The value to test.
1679
- * @throws GuardError If the value does not match the assertion.
1738
+ * Convert the base 64 string to a byte array.
1739
+ * @param base64Url The base64 url string to convert.
1740
+ * @returns The byte array.
1680
1741
  */
1681
- static number(source, property, value) {
1682
- if (!Is.number(value)) {
1683
- throw new GuardError(source, "guard.number", property, value);
1742
+ static decode(base64Url) {
1743
+ Guards.string(Base64Url._CLASS_NAME, "base64Url", base64Url);
1744
+ let base64 = base64Url;
1745
+ // Base 64 url can have padding removed, so add it back if it is missing.
1746
+ if (base64.length > 0 && !base64.endsWith("=")) {
1747
+ const placeHoldersLen = 4 - (base64.length % 4);
1748
+ if (placeHoldersLen > 0 && placeHoldersLen < 4) {
1749
+ base64 = base64.padEnd(base64.length + placeHoldersLen, "=");
1750
+ }
1684
1751
  }
1752
+ base64 = base64.replace(/-/g, "+").replace(/_/g, "/");
1753
+ return Base64.decode(base64);
1685
1754
  }
1686
1755
  /**
1687
- * Is the property an integer.
1688
- * @param source The source of the error.
1689
- * @param property The name of the property.
1690
- * @param value The value to test.
1691
- * @throws GuardError If the value does not match the assertion.
1756
+ * Convert a byte array to base 64 url.
1757
+ * @param bytes The byte array to convert.
1758
+ * @returns The data as base64 url string.
1692
1759
  */
1693
- static integer(source, property, value) {
1694
- if (!Is.integer(value)) {
1695
- throw new GuardError(source, "guard.integer", property, value);
1696
- }
1760
+ static encode(bytes) {
1761
+ Guards.uint8Array(Base64Url._CLASS_NAME, "bytes", bytes);
1762
+ const base64 = Base64.encode(bytes);
1763
+ // Base 64 url can have padding removed, so remove it.
1764
+ return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
1697
1765
  }
1766
+ }
1767
+
1768
+ /**
1769
+ * Class to handle errors which are triggered by data already existing.
1770
+ */
1771
+ class AlreadyExistsError extends BaseError {
1698
1772
  /**
1699
- * Is the property a bigint.
1700
- * @param source The source of the error.
1701
- * @param property The name of the property.
1702
- * @param value The value to test.
1703
- * @throws GuardError If the value does not match the assertion.
1773
+ * Runtime name for the class.
1704
1774
  */
1705
- static bigint(source, property, value) {
1706
- if (!Is.bigint(value)) {
1707
- throw new GuardError(source, "guard.bigint", property, value);
1708
- }
1709
- }
1775
+ static CLASS_NAME = "AlreadyExistsError";
1710
1776
  /**
1711
- * Is the property a boolean.
1777
+ * Create a new instance of AlreadyExistsError.
1712
1778
  * @param source The source of the error.
1713
- * @param property The name of the property.
1714
- * @param value The value to test.
1715
- * @throws GuardError If the value does not match the assertion.
1779
+ * @param message The message as a code.
1780
+ * @param existingId The id for the item.
1781
+ * @param inner The inner error if we have wrapped another error.
1716
1782
  */
1717
- static boolean(source, property, value) {
1718
- if (!Is.boolean(value)) {
1719
- throw new GuardError(source, "guard.boolean", property, value);
1720
- }
1783
+ constructor(source, message, existingId, inner) {
1784
+ super(AlreadyExistsError.CLASS_NAME, source, message, { existingId }, inner);
1721
1785
  }
1786
+ }
1787
+
1788
+ /**
1789
+ * Class to handle errors which are triggered by conflicting data.
1790
+ */
1791
+ class ConflictError extends BaseError {
1722
1792
  /**
1723
- * Is the property a date.
1724
- * @param source The source of the error.
1725
- * @param property The name of the property.
1726
- * @param value The value to test.
1727
- * @throws GuardError If the value does not match the assertion.
1793
+ * Runtime name for the class.
1728
1794
  */
1729
- static date(source, property, value) {
1730
- if (!Is.date(value)) {
1731
- throw new GuardError(source, "guard.date", property, value);
1732
- }
1733
- }
1795
+ static CLASS_NAME = "ConflictError";
1734
1796
  /**
1735
- * Is the property a timestamp in milliseconds.
1797
+ * Create a new instance of ConflictError.
1736
1798
  * @param source The source of the error.
1737
- * @param property The name of the property.
1738
- * @param value The value to test.
1739
- * @throws GuardError If the value does not match the assertion.
1799
+ * @param message The message as a code.
1800
+ * @param conflictId The id that has conflicts.
1801
+ * @param conflicts The conflicts that occurred.
1802
+ * @param inner The inner error if we have wrapped another error.
1740
1803
  */
1741
- static timestampMilliseconds(source, property, value) {
1742
- if (!Is.timestampMilliseconds(value)) {
1743
- throw new GuardError(source, "guard.timestampMilliseconds", property, value);
1744
- }
1804
+ constructor(source, message, conflictId, conflicts, inner) {
1805
+ super(ConflictError.CLASS_NAME, source, message, { conflictId, conflicts }, inner);
1745
1806
  }
1807
+ }
1808
+
1809
+ /**
1810
+ * Class to handle errors which are triggered by data not being found.
1811
+ */
1812
+ class NotFoundError extends BaseError {
1746
1813
  /**
1747
- * Is the property a timestamp in seconds.
1748
- * @param source The source of the error.
1749
- * @param property The name of the property.
1750
- * @param value The value to test.
1751
- * @throws GuardError If the value does not match the assertion.
1814
+ * Runtime name for the class.
1752
1815
  */
1753
- static timestampSeconds(source, property, value) {
1754
- if (!Is.timestampSeconds(value)) {
1755
- throw new GuardError(source, "guard.timestampSeconds", property, value);
1756
- }
1757
- }
1816
+ static CLASS_NAME = "NotFoundError";
1758
1817
  /**
1759
- * Is the property an object.
1818
+ * Create a new instance of NotFoundError.
1760
1819
  * @param source The source of the error.
1761
- * @param property The name of the property.
1762
- * @param value The value to test.
1763
- * @throws GuardError If the value does not match the assertion.
1820
+ * @param message The message as a code.
1821
+ * @param notFoundId The id for the item.
1822
+ * @param inner The inner error if we have wrapped another error.
1764
1823
  */
1765
- static object(source, property, value) {
1766
- if (Is.undefined(value)) {
1767
- throw new GuardError(source, "guard.objectUndefined", property, value);
1768
- }
1769
- if (!Is.object(value)) {
1770
- throw new GuardError(source, "guard.object", property, value);
1771
- }
1824
+ constructor(source, message, notFoundId, inner) {
1825
+ super(NotFoundError.CLASS_NAME, source, message, { notFoundId }, inner);
1772
1826
  }
1827
+ }
1828
+
1829
+ /**
1830
+ * Class to handle errors.
1831
+ */
1832
+ class NotImplementedError extends BaseError {
1773
1833
  /**
1774
- * Is the property is an object with at least one property.
1775
- * @param source The source of the error.
1776
- * @param property The name of the property.
1777
- * @param value The value to test.
1778
- * @throws GuardError If the value does not match the assertion.
1834
+ * Runtime name for the class.
1779
1835
  */
1780
- static objectValue(source, property, value) {
1781
- if (Is.undefined(value)) {
1782
- throw new GuardError(source, "guard.objectUndefined", property, value);
1783
- }
1784
- if (!Is.object(value)) {
1785
- throw new GuardError(source, "guard.object", property, value);
1786
- }
1787
- if (Object.keys(value || {}).length === 0) {
1788
- throw new GuardError(source, "guard.objectValue", property, value);
1789
- }
1790
- }
1836
+ static CLASS_NAME = "NotImplementedError";
1791
1837
  /**
1792
- * Is the property is an array.
1838
+ * Create a new instance of NotImplementedError.
1793
1839
  * @param source The source of the error.
1794
- * @param property The name of the property.
1795
- * @param value The value to test.
1796
- * @throws GuardError If the value does not match the assertion.
1840
+ * @param method The method for the error.
1797
1841
  */
1798
- static array(source, property, value) {
1799
- if (!Is.array(value)) {
1800
- throw new GuardError(source, "guard.array", property, value);
1801
- }
1842
+ constructor(source, method) {
1843
+ super(NotImplementedError.CLASS_NAME, source, "common.notImplementedMethod", {
1844
+ method
1845
+ });
1802
1846
  }
1847
+ }
1848
+
1849
+ /**
1850
+ * Class to handle errors when a feature is unsupported.
1851
+ */
1852
+ class NotSupportedError extends BaseError {
1803
1853
  /**
1804
- * Is the property is an array with at least one item.
1805
- * @param source The source of the error.
1806
- * @param property The name of the property.
1807
- * @param value The value to test.
1808
- * @throws GuardError If the value does not match the assertion.
1854
+ * Runtime name for the class.
1809
1855
  */
1810
- static arrayValue(source, property, value) {
1811
- if (!Is.array(value)) {
1812
- throw new GuardError(source, "guard.array", property, value);
1813
- }
1814
- if (value.length === 0) {
1815
- throw new GuardError(source, "guard.arrayValue", property, value);
1816
- }
1817
- }
1856
+ static CLASS_NAME = "NotSupportedError";
1818
1857
  /**
1819
- * Is the property one of a list of items.
1858
+ * Create a new instance of NotSupportedError.
1820
1859
  * @param source The source of the error.
1821
- * @param property The name of the property.
1822
- * @param value The value to test.
1823
- * @param options The options the value must be one of.
1824
- * @throws GuardError If the value does not match the assertion.
1860
+ * @param message The message as a code.
1861
+ * @param inner The inner error if we have wrapped another error.
1825
1862
  */
1826
- static arrayOneOf(source, property, value, options) {
1827
- if (!Is.array(options)) {
1828
- throw new GuardError(source, "guard.array", property, value);
1829
- }
1830
- if (!options.includes(value)) {
1831
- throw new GuardError(source, "guard.arrayOneOf", property, value, options.join(", "));
1832
- }
1863
+ constructor(source, message, inner) {
1864
+ super(NotSupportedError.CLASS_NAME, source, message, undefined, inner);
1833
1865
  }
1866
+ }
1867
+
1868
+ /**
1869
+ * Class to handle errors which are triggered by access not being unauthorized.
1870
+ */
1871
+ class UnauthorizedError extends BaseError {
1834
1872
  /**
1835
- * Does the array start with the specified data.
1836
- * @param source The source of the error.
1837
- * @param property The name of the property.
1838
- * @param value The value to test.
1839
- * @param startValues The values that must start the array.
1840
- * @throws GuardError If the value does not match the assertion.
1873
+ * Runtime name for the class.
1841
1874
  */
1842
- static arrayStartsWith(source, property, value, startValues) {
1843
- if (!Is.arrayValue(value)) {
1844
- throw new GuardError(source, "guard.array", property, value);
1845
- }
1846
- const startValuesArray = ArrayHelper.fromObjectOrArray(startValues);
1847
- if (!Is.arrayValue(startValuesArray)) {
1848
- throw new GuardError(source, "guard.array", property, startValuesArray);
1849
- }
1850
- for (let i = 0; i < startValuesArray.length; i++) {
1851
- if (value[i] !== startValuesArray[i]) {
1852
- throw new GuardError(source, "guard.arrayStartsWith", property, value, startValuesArray.join(", "));
1853
- }
1854
- }
1855
- }
1875
+ static CLASS_NAME = "UnauthorizedError";
1856
1876
  /**
1857
- * Does the array end with the specified data.
1877
+ * Create a new instance of UnauthorizedError.
1858
1878
  * @param source The source of the error.
1859
- * @param property The name of the property.
1860
- * @param value The value to test.
1861
- * @param endValues The values that must end the array.
1862
- * @throws GuardError If the value does not match the assertion.
1879
+ * @param message The message as a code.
1880
+ * @param inner The inner error if we have wrapped another error.
1863
1881
  */
1864
- static arrayEndsWith(source, property, value, endValues) {
1865
- if (!Is.arrayValue(value)) {
1866
- throw new GuardError(source, "guard.array", property, value);
1867
- }
1868
- const endValuesArray = ArrayHelper.fromObjectOrArray(endValues);
1869
- if (!Is.arrayValue(endValuesArray)) {
1870
- throw new GuardError(source, "guard.array", property, endValuesArray);
1871
- }
1872
- for (let i = 0; i < endValuesArray.length; i++) {
1873
- if (value[value.length - i - 1] !== endValuesArray[endValuesArray.length - i - 1]) {
1874
- throw new GuardError(source, "guard.arrayEndsWith", property, value, endValuesArray.join(", "));
1875
- }
1876
- }
1882
+ constructor(source, message, inner) {
1883
+ super(UnauthorizedError.CLASS_NAME, source, message, undefined, inner);
1877
1884
  }
1885
+ }
1886
+
1887
+ /**
1888
+ * Class to handle errors when some data can not be processed.
1889
+ */
1890
+ class UnprocessableError extends BaseError {
1878
1891
  /**
1879
- * Is the property a Uint8Array.
1880
- * @param source The source of the error.
1881
- * @param property The name of the property.
1882
- * @param value The value to test.
1883
- * @throws GuardError If the value does not match the assertion.
1892
+ * Runtime name for the class.
1884
1893
  */
1885
- static uint8Array(source, property, value) {
1886
- if (!Is.uint8Array(value)) {
1887
- throw new GuardError(source, "guard.uint8Array", property, value);
1888
- }
1889
- }
1894
+ static CLASS_NAME = "UnprocessableError";
1890
1895
  /**
1891
- * Is the property a function.
1896
+ * Create a new instance of UnprocessableError.
1892
1897
  * @param source The source of the error.
1893
- * @param property The name of the property.
1894
- * @param value The value to test.
1895
- * @returns True if the value is a function.
1896
- * @throws GuardError If the value does not match the assertion.
1898
+ * @param message The message as a code.
1899
+ * @param properties Any additional information for the error.
1900
+ * @param inner The inner error if we have wrapped another error.
1897
1901
  */
1898
- static function(source, property, value) {
1899
- if (!Is.function(value)) {
1900
- throw new GuardError(source, "guard.function", property, value);
1901
- }
1902
- return true;
1902
+ constructor(source, message, properties, inner) {
1903
+ super(UnprocessableError.CLASS_NAME, source, message, properties, inner);
1903
1904
  }
1905
+ }
1906
+
1907
+ /**
1908
+ * Class to handle errors which are triggered by entity validation.
1909
+ */
1910
+ class ValidationError extends BaseError {
1904
1911
  /**
1905
- * Is the property a string formatted as an email address.
1912
+ * Runtime name for the class.s
1913
+ */
1914
+ static CLASS_NAME = "ValidationError";
1915
+ /**
1916
+ * Create a new instance of ValidationError.
1906
1917
  * @param source The source of the error.
1907
- * @param property The name of the property.
1908
- * @param value The value to test.
1909
- * @throws GuardError If the value does not match the assertion.
1918
+ * @param validationObject The object that failed validation.
1919
+ * @param validationFailures The validation failures.
1910
1920
  */
1911
- static email(source, property, value) {
1912
- if (!Is.email(value)) {
1913
- throw new GuardError(source, "guard.email", property, value);
1914
- }
1921
+ constructor(source, validationObject, validationFailures) {
1922
+ super(ValidationError.CLASS_NAME, source, "common.validation", {
1923
+ validationObject,
1924
+ validationFailures
1925
+ });
1915
1926
  }
1916
1927
  }
1917
1928