dce-reactkit 3.4.0 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -5640,6 +5640,246 @@ const compareArraysByProp = (a, b, prop) => {
5640
5640
  });
5641
5641
  };
5642
5642
 
5643
+ /**
5644
+ * Given an array of strings, create a single comma-separated string that includes
5645
+ * 'and' as well as an oxford comma.
5646
+ * Ex: ['apples'] => 'apples'
5647
+ * Ex: ['apples', 'bananas'] => 'apples and bananas'
5648
+ * Ex: ['apples', 'bananas', 'grapes'] => 'apples, bananas, and grapes'
5649
+ * @author Austen Money
5650
+ * @param list an array of elements to be made into a single comma-separated string.
5651
+ * @returns a comma-separated string.
5652
+ */
5653
+ const genCommaList = (list) => {
5654
+ const { length } = list;
5655
+ return (length < 2
5656
+ ? list.join('')
5657
+ : `${list.slice(0, length - 1).join(', ')}${length < 3 ? ' and ' : ', and '}${list[length - 1]}`);
5658
+ };
5659
+
5660
+ /*------------------------------------------------------------------------*/
5661
+ /* ------------------------------ Constants ----------------------------- */
5662
+ /*------------------------------------------------------------------------*/
5663
+ const INVALID_REGEX_ERROR = 'input does not follow the requested format';
5664
+ const INVALID_EMAIL_ERROR = 'Please provide a valid email address.';
5665
+ const INVALID_PHONE_ERROR = 'Please provide a valid phone number.';
5666
+ const INVALID_STRING_ERRORS = {
5667
+ MIN_LEN: (minLen) => {
5668
+ return `input must not be under ${minLen} character(s)`;
5669
+ },
5670
+ MAX_LEN: (maxLen) => {
5671
+ return `input must not be over ${maxLen} character(s)`;
5672
+ },
5673
+ LETTERS_ONLY: 'input must only contain letters',
5674
+ NUMBERS_ONLY: 'input must only contain numbers',
5675
+ MESSAGE_INTRO: 'The following error(s) occurred: ',
5676
+ };
5677
+
5678
+ // Import constants
5679
+ /**
5680
+ * Determines whether a given input string is considered valid based on
5681
+ * the provided regex.
5682
+ * @author Austen Money
5683
+ * @param opts object containing all args
5684
+ * @param opts.input user-provided input to validate
5685
+ * @param opts.regex regular expression to check against input
5686
+ * @param [opts.regexDescription] description of what regexString is checking
5687
+ * for, used to customize error message
5688
+ * @returns the unchanged input if valid, or a customized error message if
5689
+ * invalid
5690
+ */
5691
+ const validateRegex = (opts) => {
5692
+ // customize error message in case of invalid input
5693
+ const errorMessage = `${INVALID_REGEX_ERROR}${opts.regexDescription
5694
+ ? ': '
5695
+ : ''}${opts.regexDescription}`;
5696
+ // return error message if test is invalid, or input string if valid
5697
+ return (opts.regex.test(opts.input)
5698
+ ? {
5699
+ isValid: true,
5700
+ cleanedValue: opts.input,
5701
+ }
5702
+ : {
5703
+ isValid: false,
5704
+ errorMessage,
5705
+ });
5706
+ };
5707
+
5708
+ // Import helpers
5709
+ /**
5710
+ * Determines whether a given email address is valid.
5711
+ * @author Austen Money
5712
+ * @param email email address to validate
5713
+ * @returns whether email fulfills proper formatting requirements, includes a
5714
+ * cleaned version of the address without leading or trailing
5715
+ * whitespace if valid or an error message if invalid.
5716
+ */
5717
+ const validateEmail = (email) => {
5718
+ // validation regex, sourced from HTML living standard: http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email)
5719
+ // eslint-disable-next-line max-len
5720
+ const emailRegex = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
5721
+ // remove leading and trailing whitespace
5722
+ const cleanedValue = email.replace(/^\s+|\s+$/g, '');
5723
+ // validate email with regex, and return error if not valid
5724
+ return (validateRegex({
5725
+ input: cleanedValue,
5726
+ regex: emailRegex,
5727
+ }).isValid
5728
+ ? {
5729
+ isValid: true,
5730
+ cleanedValue,
5731
+ }
5732
+ : {
5733
+ isValid: false,
5734
+ errorMessage: INVALID_EMAIL_ERROR,
5735
+ });
5736
+ };
5737
+
5738
+ // Import helpers
5739
+ /**
5740
+ * Determines whether a given phone number is valid.
5741
+ * @author Austen Money
5742
+ * @param phoneNumber phone number to validate
5743
+ * @returns whether phone number is considered valid - if valid, also returns
5744
+ * a cleaned version of the number without any formatting. If invalid,
5745
+ * returns an error message.
5746
+ */
5747
+ const validatePhoneNumber = (phoneNumber) => {
5748
+ // regex to validate phone number
5749
+ const validationRegex = /^\s*(?:\+?(\d{1,3}))?[-. (]*(\d{3})[-. )]*(\d{3})[-. ]*(\d{4})(?: *x(\d+))?\s*$/;
5750
+ // validate phone number with regex
5751
+ const validationResponse = validateRegex({
5752
+ input: phoneNumber,
5753
+ regex: validationRegex,
5754
+ });
5755
+ // remove all non-digits from number
5756
+ const cleanedValue = phoneNumber.replace(/\D/g, '');
5757
+ // return cleaned value if valid, or error message if invalid
5758
+ return (validationResponse.isValid
5759
+ ? {
5760
+ isValid: true,
5761
+ cleanedValue,
5762
+ }
5763
+ : {
5764
+ isValid: false,
5765
+ errorMessage: INVALID_PHONE_ERROR,
5766
+ });
5767
+ };
5768
+
5769
+ // Import helpers
5770
+ /*------------------------------------------------------------------------*/
5771
+ /* ------------------------------ Constants ----------------------------- */
5772
+ /*------------------------------------------------------------------------*/
5773
+ // define minimum and maximum range for lowercase ASCII chars
5774
+ const LOWERCASE_MIN = 65;
5775
+ const LOWERCASE_MAX = 90;
5776
+ // define minimum and maximum range for uppercase ASCII chars
5777
+ const UPPERCASE_MIN = 97;
5778
+ const UPPERCASE_MAX = 122;
5779
+ // define minimum and maximum range for ASCII digits
5780
+ const DIGIT_MIN = 48;
5781
+ const DIGIT_MAX = 57;
5782
+ /*------------------------------------------------------------------------*/
5783
+ /* ---------------------------- Main Function --------------------------- */
5784
+ /*------------------------------------------------------------------------*/
5785
+ /**
5786
+ * Determines whether a given input string is considered valid based on
5787
+ * the provided requirements.
5788
+ * @author Austen Money
5789
+ * @param input input string
5790
+ * @param opts options for validation
5791
+ * @returns whether input is considered valid according to reqs - if
5792
+ * valid, returns a cleaned version of input; if invalid, returns
5793
+ * a string containing error messages describing which requirements
5794
+ * were not met.
5795
+ */
5796
+ const validateString = (input, opts) => {
5797
+ // stores all invalid input errors
5798
+ const errorMessages = [];
5799
+ // contains version of input that will be returned
5800
+ let cleanedValue = input;
5801
+ // remove whitespace if required
5802
+ if (opts.ignoreWhitespace) {
5803
+ cleanedValue = input.replace(/\s+/g, '');
5804
+ }
5805
+ // apply max char requirement
5806
+ if (opts.minLen) {
5807
+ if (cleanedValue.length < opts.minLen) {
5808
+ errorMessages.push(INVALID_STRING_ERRORS.MIN_LEN(opts.minLen));
5809
+ }
5810
+ }
5811
+ // apply max char requirement
5812
+ if (opts.maxLen) {
5813
+ if (cleanedValue.length > opts.maxLen) {
5814
+ errorMessages.push(INVALID_STRING_ERRORS.MAX_LEN(opts.maxLen));
5815
+ }
5816
+ }
5817
+ // apply alphabetical requirement
5818
+ if (opts.lettersOnly) {
5819
+ // remove diacritics
5820
+ cleanedValue = cleanedValue.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
5821
+ const containsNonLetters = (cleanedValue
5822
+ // split into characters
5823
+ .split('')
5824
+ // convert into character codes
5825
+ .map((curr) => {
5826
+ return curr.charCodeAt(0);
5827
+ })
5828
+ // check for non-letters
5829
+ .some((currCode) => {
5830
+ return (!(currCode >= LOWERCASE_MIN && currCode <= LOWERCASE_MAX)
5831
+ && !(currCode >= UPPERCASE_MIN && currCode <= UPPERCASE_MAX));
5832
+ }));
5833
+ if (containsNonLetters) {
5834
+ errorMessages.push(INVALID_STRING_ERRORS.LETTERS_ONLY);
5835
+ }
5836
+ }
5837
+ // apply numerical requirement
5838
+ if (opts.numbersOnly) {
5839
+ const containsNonNumbers = (cleanedValue
5840
+ // split into characters
5841
+ .split('')
5842
+ // convert into character codes
5843
+ .map((curr) => {
5844
+ return curr.charCodeAt(0);
5845
+ })
5846
+ // check for non-numbers
5847
+ .some((currCode) => {
5848
+ return (!(currCode >= DIGIT_MIN && currCode <= DIGIT_MAX));
5849
+ }));
5850
+ if (containsNonNumbers) {
5851
+ errorMessages.push(INVALID_STRING_ERRORS.NUMBERS_ONLY);
5852
+ }
5853
+ }
5854
+ // apply regex requirement
5855
+ if (opts.regexTest) {
5856
+ const regex = opts.regexTest;
5857
+ // validate and create customized error message if description is provided
5858
+ const result = validateRegex({
5859
+ input: cleanedValue,
5860
+ regex,
5861
+ regexDescription: opts.regexDescription,
5862
+ });
5863
+ // if string did not pass regex validation, add error message
5864
+ if (result.isValid === false) {
5865
+ errorMessages.push(result.errorMessage);
5866
+ }
5867
+ }
5868
+ // combine all error messages into one string to return
5869
+ const errorMessage = `${INVALID_STRING_ERRORS.MESSAGE_INTRO}${genCommaList(errorMessages)}.`;
5870
+ return (
5871
+ // if no error messages, string is valid; if not, it is invalid
5872
+ errorMessages.length === 0
5873
+ ? {
5874
+ isValid: true,
5875
+ cleanedValue,
5876
+ }
5877
+ : {
5878
+ isValid: false,
5879
+ errorMessage,
5880
+ });
5881
+ };
5882
+
5643
5883
  /**
5644
5884
  * Get current time info in local time
5645
5885
  * @author Gabe Abrams
@@ -5749,6 +5989,7 @@ exports.extractProp = extractProp;
5749
5989
  exports.floorToNumDecimals = floorToNumDecimals;
5750
5990
  exports.forceNumIntoBounds = forceNumIntoBounds;
5751
5991
  exports.genCSV = genCSV;
5992
+ exports.genCommaList = genCommaList;
5752
5993
  exports.genRouteHandler = genRouteHandler;
5753
5994
  exports.getHumanReadableDate = getHumanReadableDate;
5754
5995
  exports.getLocalTimeInfo = getLocalTimeInfo;
@@ -5773,6 +6014,9 @@ exports.startMinWait = startMinWait;
5773
6014
  exports.stringsToHumanReadableList = stringsToHumanReadableList;
5774
6015
  exports.stubServerEndpoint = stubServerEndpoint;
5775
6016
  exports.sum = sum;
6017
+ exports.validateEmail = validateEmail;
6018
+ exports.validatePhoneNumber = validatePhoneNumber;
6019
+ exports.validateString = validateString;
5776
6020
  exports.visitServerEndpoint = visitServerEndpoint;
5777
6021
  exports.waitMs = waitMs;
5778
6022
  //# sourceMappingURL=index.js.map