# Source: index.js

    // #region  F I L E
    // <copyright file="mcode-data/index.js" company="MicroCODE Incorporated">Copyright © 2022-2024 MicroCODE, Inc. Troy, MI</copyright><author>Timothy J. McGuire</author>
    // #region  M O D U L E
    // #region  D O C U M E N T A T I O N
    /**
     *      Project:  MicroCODE MERN Applications
     *      Customer: Internal + MIT xPRO Course
     *      @module   'mcode-data.js'
     *      @memberof mcode
     *      @created  January 2022-2024
     *      @author   Timothy McGuire, MicroCODE, Inc.
     *      @description >
     *      MicroCODE Common Data Utitlities
     *
     *      LICENSE:
     *      --------
     *      MIT License: MicroCODE.mcode-data
     *
     *      Copyright (c) 2022-2025 Timothy McGuire, MicroCODE, Inc.
     *
     *      Permission is hereby granted, free of charge, to any person obtaining a copy
     *      of this software and associated documentation files (the "Software"), to deal
     *      in the Software without restriction, including without limitation the rights
     *      to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     *      copies of the Software, and to permit persons to whom the Software is
     *      furnished to do so, subject to the following conditions:
     *
     *      The above copyright notice and this permission notice shall be included in all
     *      copies or substantial portions of the Software.
     *
     *      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     *      IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     *      FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     *      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     *      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     *      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     *      SOFTWARE.
     *
     *
     *      DESCRIPTION:
     *      ------------
     *      This module implements the MicroCODE's Common JavaScript functions for data handling.
     *
     *
     *      REFERENCES:
     *      -----------
     *      1. MIT xPRO Course: Professional Certificate in Coding: Full Stack Development with MERN.
     *
     *      2. LADDERS® source code: MACRO-11, MACRO-32, C#, and JavaScript.
     *
     *
     *
     *
     *      MODIFICATIONS:
     *      --------------
     *      Date:         By-Group:   Rev:    Description:
     *
     *      30-Jan-2024   TJM-MCODE  {0001}   New module for common reusable JavaScript data handling functions.
     *      01-Feb-2024   TJM-MCODE  {0002}   Changed to the Universal Module Definition (UMD) pattern to support AMD,
     *                                        CommonJS/Node.js, and browser global in our exported module.
     *      01-Feb-2024   TJM-MCODE  {0003}   Swap() and Call() now throw an error if the 'keys' and 'values' lists are not the same length,
     *                                        instead of logging the error and returning a default value.
     *      22-Aug-2024   TJM-MCODE  {0004}   Corrected isJson() to rely on 1st character being '{' to determine JSON string
     *                                        it was returning true for any string that contained a '{' character,
     *                                        this was signaling 'true' for HTMX templates that contained '{{variable}}'.
     *      05-Oct-2024   TJM-MCODE  {0005}   Added 'uuidDecode()' function to decode UUID strings into their component parts.
     *
     *      19-Feb-2025   TJM-MCODE  {0006}   v0.5.08 - updated 'httpStatus()' to use a STATIC copy of HTTP codes JSON for speed.
     *                                                - updated all UUID string lists to STATIC as well.
     *      17-Apr-2025   TJM-MCODE  {0007}   v0.5.09 - added 'isHtml()' function to check if a string is HTML,
     *                                                  updated 'isJson()' to use same check.
     *      23-Oct-2025   TJM-MCODE  {0008}   v0.6.03 - added 'classExport()' to return the created class constructor to support SSR
     *                                                  and ESM module loading, especially in HTMX applications.
     *                                                  Also added: sleep(), ifNumber(), encodeJson(), generateRandomId().
     *
     *
     *
     * NOTE: This module follows MicroCODE's JavaScript Style Guide and Template JS file, see:
     *
     *       o  https://github.com/MicroCODEIncorporated/JavaScriptSG
     *       o  https://github.com/MicroCODEIncorporated/TemplatesJS
     *
     */

    // #endregion

    // #region  I M P O R T S

    // #endregion

    // #region  T Y P E S

    // #endregion

    // #region  I N T E R F A C E S

    // #endregion

    // #region  C O N S T A N T S, F U N C T I O N S – P U B L I C

    // MicroCODE: define this module's name for our 'mcode-log' package
    const MODULE_NAME = 'mcode-data.js';

    // Static copy of HTTP codes for httpStatus() function for speed - {0006}
    const HTTP_CODES =
    {
        //1xx: Informational responses (CYAN)
        "100": "Continue",
        "101": "Switching Protocols",
        "102": "Processing",
        "103": "Early Hints",
        "104": "Checkpoint (WebDAV)",
        "105": "Switch Proxy (WebDAV)",
        "106": "Processing (WebDAV)",
        "107": "Handoff (WebDAV)",

        //2xx: Success responses (GREEN)
        "200": "OK",  // for READ
        "201": "Created",  //for CREATE
        "202": "Accepted",  // for PUT/PATCH/DELETE
        "203": "Non-Authoritative Information",
        "204": "No Content",
        "205": "Reset Content",
        "206": "Partial Content",
        "207": "Multi-Status",
        "208": "Already Reported",
        "226": "IM Used",

        //3xx: Redirection responses (YELLOW)
        "300": "Multiple Choices",
        "301": "Moved Permanently",
        "302": "Found",
        "303": "See Other",
        "304": "Not Modified",
        "305": "Use Proxy",
        "307": "Temporary Redirect",
        "308": "Permanent Redirect",
        "309": "Resume Incomplete (WebDAV)",
        "310": "Too Many Redirects",

        //4xx: Client error responses (RED)
        "400": "Bad Request",  // missing Record Fields during CREATE or PUT
        "401": "Unauthorized",
        "402": "Payment Required",
        "403": "Forbidden",
        "404": "Not Found",  // no record to update during PATCH or PUT
        "405": "Method Not Allowed",
        "406": "Not Acceptable",
        "407": "Proxy Authentication Required",
        "408": "Request Timeout",
        "409": "Conflict",
        "410": "Gone",
        "411": "Length Required",
        "412": "Precondition Failed",
        "413": "Payload Too Large",
        "414": "URI Too Long",
        "415": "Unsupported Media Type",
        "416": "Range Not Satisfiable",
        "417": "Expectation Failed",
        "418": "I'm a Teapot", // indicates that the server refuses to brew coffee because it is a teapot. (An April fool’s joke from 1998)
        "419": "Page Expired (Laravel)",
        "421": "Misdirected Request",
        "422": "Unprocessable Entity",
        "423": "Locked",
        "424": "Failed Dependency",
        "425": "Too Early",
        "426": "Upgrade Required",
        "428": "Precondition Required",
        "429": "Too Many Requests",
        "431": "Request Header Fields Too Large",
        "440": "Login Timeout (Microsoft)",
        "444": "Connection Closed Without Response (NGINX)",
        "449": "Retry With (Microsoft - IIS specific)",
        "450": "Blocked by Windows Parental Controls (Microsoft)",
        "451": "Unavailable For Legal Reasons",
        "499": "Client Closed Request (NGINX)",

        //5xx: Server error responses (MAGENTA)
        "500": "Internal Server Error",  // unexpected Code Exceptions
        "501": "Not Implemented",  // hit stubs or calls to non-existent endpoints
        "502": "Bad Gateway",
        "503": "Service Unavailable",
        "504": "Gateway Timeout",
        "505": "HTTP Version Not Supported",
        "506": "Variant Also Negotiates",
        "507": "Insufficient Storage",
        "508": "Loop Detected",
        "509": "Bandwidth Limit Exceeded (Apache/cPanel)",
        "510": "Not Extended",
        "511": "Network Authentication Required",
        "520": "Unknown Error (Cloudflare)",
        "521": "Web Server Is Down (Cloudflare)",
        "522": "Connection Timed Out (Cloudflare)",
        "523": "Origin Is Unreachable (Cloudflare)",
        "524": "A Timeout Occurred (Cloudflare)",
        "525": "SSL Handshake Failed (Cloudflare)",
        "526": "Invalid SSL Certificate (Cloudflare)",
        "527": "Railgun Error (Cloudflare)",
        "530": "Origin DNS Error (Cloudflare-FTP)",
        "598": "Network Read Timeout Error (Unofficial)",
        "599": "Network Connect Timeout Error (Azure/AWS)",
    };

    // U U I D - V A R I A N T S

    const UUID_VARIANTS = [
        "NCS compatibility",
        "NCS compatibility",
        "RFC 4122, RFC 9562",
        "Microsoft GUIDs",
    ];

    // U U I D - V E R S I O N S

    // NCS compatibility (variant 0, 1)
    const UUID_VAR1_VERSIONS = [
        "Undefined / Reserved / NIL",     // 0
        " NCS Security Version",          // 1
        " NCS Security Version",          // 2
        " NCS Security Version",          // 3
        " NCS Security Version",          // 4
        " NCS Security Version",          // 5
        " NCS Security Version",          // 6
        " NCS Security Version",          // 7
        " NCS Security Version",          // 8
        " NCS Security Version",          // 9
        " NCS Security Version",          // 10
        " NCS Security Version",          // 11
        " NCS Security Version",          // 12
        " NCS Security Version",          // 13
        " NCS Security Version",          // 14
        "Undefined / Reserved / MAX",     // 15
    ];

    // RFC 4122 (Leach-Salz) (variant 2)
    const UUID_VAR2_VERSIONS = [
        "Undefined / Reserved / NIL",     // 0
        "Gregorian Unordered Timestamp",  // 1
        "DCE Security (POSIX)",           // 2
        "Name-Based (MD5 Hash)",          // 3
        "Random-Based Number",            // 4
        "Name Based (SHA-1 Hash)",        // 5
        "Gregorian Ordered Timestamp",    // 6
        "Unix Epoch Timestamp",           // 7
        "Custom Encoding Format",         // 8
        "Reserved for future defnition",  // 9
        "Reserved for future defnition",  // 10
        "Reserved for future defnition",  // 11
        "Reserved for future defnition",  // 12
        "Reserved for future defnition",  // 13
        "Reserved for future defnition",  // 14
        "Undefined / Reserved / MAX",     // 15
    ];

    // Microsoft GUIDs (variant 3)
    const UUID_VAR3_VERSIONS = [
        "Undefined / Reserved / NIL",     // 0
        "Microsoft GUID Version 1",       // 1
        "Microsoft GUID Version 2",       // 2
        "Microsoft GUID Version 3",       // 3
        "Microsoft GUID Version 4",       // 4
        "Microsoft GUID Version 5",       // 5
        "Microsoft GUID Version 6",       // 6
        "Microsoft GUID Version 7",       // 7
        "Microsoft GUID Version 8",       // 8
        "Microsoft GUID Version 9",       // 9
        "Microsoft GUID Version 10",      // 10
        "Microsoft GUID Version 11",      // 11
        "Microsoft GUID Version 12",      // 12
        "Microsoft GUID Version 13",      // 13
        "Microsoft GUID Version 14",      // 14
        "Undefined / Reserved / MAX",     // 15
    ];

    /**
     * @namespace mcode
     * @desc mcode namespace containing functions and constants.
     */
    const mcode = {

        /**
         * @func property
         * @memberof mcode
         * @desc Creates a property with get, set methods, validator, and on change events.
         * @api public
         * @param {object} options optional params to define the property
         * {initial: value, readonly: boolean, immutable: boolean, validator: function, onChange: function}.
         * @returns {object} a property object with get, set, type, reset, isReadOnly, and isImmutable methods.
         */
        property: function (options = {})
        {
            // internal variables
            const _initial = options?.initial;
            const _readonly = options.readonly || false;
            const _immutable = options.immutable || false;

            // optional functions
            const _validator = options.validator || function () {return true;};
            const _onChange = options.onChange || function () {};

            // the actual value of the property
            let _value = options.initial || undefined;

            return {
                get: function ()
                {
                    return _value;
                },
                set: function (value)
                {
                    if (_immutable && (_value !== undefined))
                    {
                        throw new Error('｢mcode.property｣ This property is immutable.');
                    }
                    if (_readonly)
                    {
                        throw new Error('｢mcode.property｣ This property is read-only.');
                    }
                    if (_validator(value))
                    {
                        const _last = _value;
                        _value = value;
                        _onChange(_last, _value);
                    }
                    else
                    {
                        throw new Error('｢mcode.property｣ Invalid property value.');
                    }
                },
                type: function ()
                {
                    return typeof _value;
                },
                reset: function ()
                {
                    const _last = _value;
                    _value = _initial;
                    _onChange(_last, _value);
                },
                isReadOnly: function ()
                {
                    return _readonly;
                },
                isImmutable: function ()
                {
                    return _immutable;
                },
                hasChanged: function ()
                {
                    return _value !== _initial;
                }
            };
        },

        /**
         * @func getProperty
         * @memberof mcode
         * @api private
         * @desc Safely resolve a nested property using an array of keys.
         * @param {object} source - Root object from which to read.
         * @param {Array<string>} path - Ordered list of keys to traverse.
         * @returns {any} Resolved value or undefined when not found.
         */
        getProperty: function (source, path)
        {
            return path.reduce((keyPath, key) =>
            {
                if (keyPath && Object.prototype.hasOwnProperty.call(keyPath, key))
                {
                    return keyPath[key];
                }
                return undefined;
            }, source);
        },

        /**
         * @func setProperty
         * @memberof mcode
         * @desc Assign a nested property on the target object, creating scopes as needed.
         * @api private
         * @param {object} target - Object receiving the assignment.
         * @param {Array<string>} path - Ordered list of keys to reach the leaf property.
         * @param {any} value - Value to assign at the terminal path segment.
         * @returns {void}
         */
        setProperty: function (target, path, value)
        {
            let current = target;

            for (let index = 0; index < path.length - 1; index += 1)
            {
                const key = path[index];

                if (!current[key] || typeof current[key] !== 'object')
                {
                    current[key] = {};
                }

                current = current[key];
            }

            current[path[path.length - 1]] = value;
        },

        /**
         * @func contextProperty
         * @memberof mcode
         * @desc Define a getter/setter proxy that syncs instance properties to context paths.
         * @api public
         * @param {Class} instance - Class instance being updated, must have a 'context' object and 'syncDomContext()' method.
         * @param {string} property - Property name exposed on the instance.
         * @param {Array<string>} path - Path segments within the context object.
         * @param {object} [options] - Optional configuration flags.
         * @param {boolean} [options.sync=true] - Whether to resync the DOM context when setting.
         * @returns {void}
         */
        contextProperty: function (instance, property, path, options = {})
        {
            const {sync = true} = options;

            if (!instance || typeof instance !== 'object')
            {
                throw new Error('[mcode] Invalid instance provided to contextProperty.');
            }
            if (!instance.syncDomContext || typeof instance.syncDomContext !== 'function')
            {
                throw new Error('[mcode] Invalid syncDomContext() method provided to contextProperty.');
            }
            if (!instance.context || typeof instance.context !== 'object')
            {
                throw new Error('[mcode] Invalid context object provided to contextProperty.');
            }

            Object.defineProperty(instance, property, {
                configurable: true,
                enumerable: false,
                get()
                {
                    return mcode.getProperty(instance?.context, path);
                },
                set(value)
                {
                    mcode.setProperty(instance?.context, path, value);
                    if (sync)
                    {
                        instance?.syncDomContext();
                    }
                }
            });
        },

        /**
         * @func isString
         * @memberof mcode
         * @desc Checks whether or not a object is a JS String.
         * @api public
         * @param {object} jsObject JavaScript object to be tested
         * @returns {boolean} a value indicating whether or not the object is a STRING.
         */
        isString: function (jsObject)
        {
            return Object.prototype.toString.call(jsObject) === '[object String]';
        },

        /**
         * @method isObject
         * @memberof mcode
         * @desc Checks whether or not a object is a JS Object.
         * @api public
         * @param {object} jsObject JavaScript object to be tested
         * @returns {boolean} a value indicating whether or not the object is an OBJECT.
         */
        isObject: function (jsObject)
        {
            if (mcode.isString(jsObject)) return false;

            return typeof jsObject === 'object' && jsObject !== null && !Array.isArray(jsObject) && typeof jsObject !== 'function';
        },

        /**
         * @method isArray
         * @memberof mcode
         * @desc Checks whether or not an object is a JS Array.
         * @api public
         * @param {object} jsObject JavaScript object to be tested
         * @returns {boolean} a value indicating whether or not the object is an ARRAY.
         */
        isArray: function (jsObject)
        {
            return Array.isArray(jsObject);
        },

        /**
         * @method isFunction
         * @memberof mcode
         * @desc Checks whether or not an object is a JS Function.
         * @api public
         * @param {object} jsObject JavaScript object to be tested
         * @returns {boolean} a value indicating whether or not the object is a FUNCTION.
         */
        isFunction: function (jsObject)
        {
            if (mcode.isString(jsObject)) return false;

            return typeof jsObject === 'function';
        },

        /**
         * @func isNumber
         * @memberof mcode
         * @desc Checks whether or not an object is a JS Number and *not* NaN.
         * @api public
         * @param {any} numberToCheck as a number of some type
         * @returns {boolean} a value indicating whether or not the object is valid Number.
         */
        isNumber: function (numberToCheck)
        {
            // NOTE: this compare will fail for NaN
            // eslint-disable-next-line no-self-compare
            return (typeof numberToCheck === 'number') && (numberToCheck === numberToCheck);
        },

        /**
         * @function ifNumber
         * @memberof mcode
         * @desc Checks if a value is a valid number; if not, returns a default value.
         * @param {number} value The value to check.
         * @param {number} defaultValue The default value to return if the check fails.
         * @returns {number} The original value if valid, otherwise the default value.
         */
        ifNumber: function (value, defaultValue = 0)
        {
            return Number.isFinite(value) ? value : defaultValue;
        },

        /**
         * @func isNaN
         * @memberof mcode
         * @desc Checks whether or not an object is a double-precision 'Not-a-Number (Nan)'.
         * @api public
         * @param {any} numberToCheck as a number of some type
         * @returns {boolean} a value indicating whether or not the object is NaN.
         */
        isNaN: function (numberToCheck)
        {
            // NOTE: this compare will always be true for NaN, and only for NaN
            // eslint-disable-next-line no-self-compare
            return (numberToCheck !== numberToCheck);
        },

        /**
         * @func isJson
         * @memberof mcode
         * @desc Quickly checks a string for embedded JSON data.
         * @api public
         * @param {object} object string to be tested
         * @returns {boolean} a value indicating whether or not the object is a JSON string.
         */
        isJson: function (object)
        {
            try
            {
                if (typeof object !== 'string') return false;

                // if this string begins with '{' and ends with '}' its very likely legal JSON code
                const trimmed = object.trim();

                return trimmed.startsWith('{') && trimmed.endsWith('}');
            }
            catch
            {
                return false;  // *not* JSON and not parsable
            }
        },

        /**
         * @func isHtml
         * @memberof mcode
         * @desc Quickly checks a string for HTML content.
         * @api public
         * @param {object} object string to be tested
         * @returns {boolean} a value indicating whether or not the object is HTML string.
         */
        isHtml: function (object)
        {
            try
            {
                if (typeof object !== 'string') return false;

                // if this string begins with '<' and ends with '>' its very likely legal HTML code
                const trimmed = object.trim();

                return trimmed.startsWith('<') && trimmed.endsWith('>');
            }
            catch
            {
                return false;  // *not* HTML and not parsable
            }
        },

        /**
         * @func isDomAvailable
         * @memberof mcode
         * @desc Determine whether DOM APIs are available in the current environment.
         * @api public
         * @returns {boolean} True when document access is supported.
         */
        isDomAvailable: function ()
        {
            return typeof document !== 'undefined' && typeof document.getElementById === 'function';
        },

        /**
         * @func isUndefined
         * @memberof mcode
         * @desc Checks whether or not an object is a 'undefined'.
         * @api public
         * @param {any} objectToCheck as a variable of some type
         * @returns {boolean} a value indicating whether or not the object is UNDEFINED.
         */
        isUndefined: function (objectToCheck)
        {
            // return true if 'objectToCheck' is UNDEFINED or NULL
            return ((typeof objectToCheck === 'undefined') || (objectToCheck === null));
        },

        /**
         * @func isDate
         * @memberof mcode
         * @desc Checks whether or not an object is a JS Date.
         * @param {object} objectToCheck
         * @returns {boolean} a value indicating whether or not the object is a DATE.
         */
        isDate: function (objectToCheck)
        {
            // return true if 'objectToCheck' is DATE Value
            return (objectToCheck instanceof Date);
        },

        /**
         * @func isTimeStamp
         * @memberof mcode
         * @desc Checks whether or not an object is a Timestampe, i.e.: a JS Date.
         * @param {object} objectToCheck
         * @returns {boolean} a value indicating whether or not the object is a TIMESTAMP.
         */
        isTimeStamp: function (objectToCheck)
        {
            // return true if 'objectToCheck' is DATE/TIMESTAMP Value
            return (objectToCheck instanceof Date);
        },

        /**
         * @func octify
         * @memberof mcode
         * @desc Converts a string to an octal string.
         * @api public
         * @param {string} text - The string to be converted to an octal string of bytes.
         * @returns {string} The octal string.
         * @example
         *           mcode.octify('Hello, World!');  // returns: "110 145 154 154 157 54 40 127 157 162 154 144 41"
         */
        octify(text)
        {
            const buffer = Buffer.from(text, 'utf8');

            // Convert each byte to its octal representation
            const octArray = [...buffer].map((byte) => byte.toString(8).padStart(3, '0'));

            // Join the octal values into a string separated by spaces
            return octArray.join(' ');
        },

        /**
         * @func hexify
         * @memberof mcode
         * @desc Converts a string to a hexadecinal string of bytes.
         * @api public
         * @param {string} text the string to be converted to a hex string.
         * @returns {string} the hex string.
         * @example
         *           mcode.hexify('Hello, World!');  // returns: "48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21"
         */
        hexify(text)
        {
            const buffer = Buffer.from(text, 'utf8');
            const hex = buffer.toString('hex');

            // Format the hex string into groups of 2 characters (1 byte)
            return hex.match(/.{1,2}/g).join(' ');
        },

        /**
         * @func default
         * @memberof mcode
         * @desc Evaluates a param and returns a default if the param is null, undefined,
         * or empty (strings, arrays, objects, or primitives).
         * @api public
         * @param {any} anyItem The JavaScript entity being tested.
         * @param {any} defaultItem The item to be returned if 'anyItem' is null, undefined, or empty.
         * @returns {any} The original item or the default if empty/null/undefined.
         * @example
         *     err = mcode.default(err, 'Undefined error occurred');  // default to recognizable message
         *     data = mcode.default(data, []); // Default to empty array
         *     config = mcode.default(config, {}); // Default to empty object
         *     count = mcode.default(count, 1); // Default to 1 if count is 0
         *
         *     log(mcode.default(undefined, 'Default'));   // 'Default'
         *     log(mcode.default(null, 'Default'));        // 'Default'
         *     log(mcode.default('', 'Default'));          // 'Default'
         *     log(mcode.default(0, 1));                   // 1 (0 is 'empty', returns default)
         *     log(mcode.default(42, 1));                  // 42 (non-zero number, returns original)
         *     log(mcode.default([], []));                 // []
         *     log(mcode.default(['item'], ['default']));  // ['item']
         *     log(mcode.default({}, {}));                 // {}
         *     log(mcode.default({ key: 'value' }, { def: 'default' }));
         *                                                        // { key: 'value' }
         *     log(mcode.default(true, false));            // true
         *     log(mcode.default('Hello', 'Default'));     // 'Hello'
         */
        default(anyItem, defaultItem)
        {
            // handle null, undefined, or empty values
            if (anyItem === null || anyItem === undefined)
            {
                return defaultItem;
            }

            // handle empty strings
            if (typeof anyItem === 'string' && anyItem === '')
            {
                return defaultItem;
            }

            // handle unassigned values (0 is treated as 'unassigned')
            if (typeof anyItem === 'number' && anyItem === 0)
            {
                return defaultItem;
            }

            // handle empty arrays
            if (Array.isArray(anyItem) && anyItem.length === 0)
            {
                return defaultItem;
            }

            // Handle empty objects (excluding null prototypes or non-object types)
            if (typeof anyItem === 'object' && anyItem !== null && Object.keys(anyItem).length === 0)
            {
                return defaultItem;
            }

            // return the original item for all other cases (primitives, non-empty arrays/objects, etc.)
            return anyItem;
        },

        /**
         * @func extractId
         * @memberof mcode
         * @desc Extracts an alpha-numberic ID Field from a string, intended to be a unique portion of a common string.
         * @param {string} objectName typically a file name, but can be any string, to extract an ID Field from.
         * @returns {string} the extracted ID Field.
         *
         * @example
        *
         *  Rules for extracting the ID Field:
         *
         *  1. The ID Field is assumed to be the first alpha-numeric field in the string.
         *  2. The ID Field is assumed to be Letters + Numbers, with no spaces or special characters.
         *  3. The ID Field is assumed to be either at the beginning or end of the string, or separated by non-alpha-numeric characters.
         *  4. The ID Field could have lowercase 'placeholders' for numbers, like 'PxCy' or 'PnCn' for 'P1C2'.
         *
         * const str1 = "CG_BRKE01_20231116.L5K";
         * const str2 = "CG_BRKE03_20231116.L5K";
         *
         *  log(extractIdField(str1));     // Expected output: "BRKE01"
         *  log(extractIdField(str2));     // Expected output: "BRKE03"
         *
         * const str1 = "EP_GPT13TZ1_20231115_0800.L5K";
         * const str2 = "EP_GPT13TZ2_20231113_1600.L5K";
         *
         *  log(extractIdField(str1));     // Expected output: "GPT13TZ1"
         *  log(extractIdField(str2));     // Expected output: "GPT13TZ2"
         *
         * const str1 = "SEP_P1C2_GMP_ARL.L5K";
         * const str2 = "SEP_P3C0_GMP_ARL.L5K";
         *
         *  log(extractIdField(str1));     // Expected output: "P1C2"
         *  log(extractIdField(str2));     // Expected output: "P3C0"
         *
         * const str1 = "SEP_P1C2_GMP_ARL.L5K";
         * const str2 = "SEP_PxCy_GMP.L5K";
         *
         *  log(extractIdField(str1));     // Expected output: "P1C2"
         *  log(extractIdField(str2));     // Expected output: "PxCy"
         *
         */
        extractId: function (objectName)
        {
            let idField = '';
            let inAlphaNumeric = false;
            let isLetter = false;
            let isLowerL = false;
            let isNumber = false;
            let hasLetters = false;
            let hasNumbers = false;
            let si = 0;

            // ƒ to check for upper case letter
            const isUpper = (objectName, i) =>
            {
                // if 'i' is outside 'objectName' return false
                if (i < 0 || i >= objectName.length)
                {
                    return false;
                }
                return (objectName[i] >= 'A' && objectName[i] <= 'Z');
            };

            // scan the string for the first alpha-numeric field
            for (let i = 0; i < objectName.length; i++)
            {
                isNumber = (objectName[i] >= '0' && objectName[i] <= '9');
                isLetter = (objectName[i] >= 'A' && objectName[i] <= 'Z');
                isLowerL = (objectName[i] >= 'a' && objectName[i] <= 'z');

                if (isNumber || isLetter || isLowerL)
                {
                    if (!inAlphaNumeric)
                    {
                        inAlphaNumeric = true;
                        si = i;
                    }
                    idField += objectName[i];
                    hasLetters = hasLetters || isLetter || isLowerL;
                    hasNumbers = hasNumbers || isNumber;

                    // Check for 'lower case numeric placeholder' like 'PxCy' or 'PnCn' for 'P1C2'
                    if (isUpper(objectName, i - 1) && isUpper(objectName, i + 1) && isLowerL)
                    {
                        hasNumbers = true;  // treat the single lower case letter between upper case letters as a number placeholder
                    }
                }
                else
                {
                    // hit non Alpha-Numeric character
                    if (inAlphaNumeric && hasLetters && hasNumbers)
                    {
                        idField = objectName.substring(si, i);
                        break;  // we have the field we want, exit to return it
                    }
                    else
                    {
                        // current field does not meet criteria, reset and continue
                        si = 0;
                        idField = '';
                        inAlphaNumeric = false;
                        hasLetters = false;
                        hasNumbers = false;
                    }
                }
            }

            return idField || '';
        },

        /**
         * @func httpStatus
         * @memberof mcode
         * @desc Returns the text for a given HTTP status code.
         * @param {var} httpCode the HTTP status code to translate.
         * @returns {string} a value representing the English meaning of a HTTP status code, formatted for display.
         */
        httpStatus: function (httpCode)
        {
            // return the translated HTTP status code
            // example: `[HTTP] 404: Not Found`
            return (`[HTTP] ${httpCode}: ` + HTTP_CODES[httpCode] || 'Unknown HTTP Status');
        },

        /**
         * @func httpSeverity
         * @memberof mcode
         * @desc Returns the mcode.log() severity (as text) for a given HTTP status code.
         * @param {var} httpCode the HTTP status code to translate.
         * @returns {string} a value representing the text name for logging the proper severity.
         */
        httpSeverity: function (httpCode)
        {
            if (httpCode >= 500)
            {
                return 'fatal';  // these severity must match mcode.log() definitions and app-banner.module.css
            }
            else if (httpCode >= 400)
            {
                return 'error';
            }
            else if (httpCode >= 300)
            {
                return 'warning';
            }
            else if (httpCode >= 200)
            {
                return 'success';
            }
            else if (httpCode >= 100)
            {
                return 'info';
            }
            return 'none';
        },

        /**
         * @func uuidDecode
         * @memberof mcode
         * @desc Decodes a UUID string into its component parts, this supports RFC 4122 and RFC 9562 UUIDs.
         * @param {string} uuid a UUID string in the format 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
         * @param {boolean} localTime a flag to indicate if the timestamp should be converted to local time for display.
         * @returns {string} a JSON object containing the decoded UUID parts.
         */
        uuidDecode: function (uuid, localTime = false)
        {
            // L I S T S - by UUID Variant and their Versions

            // ƒ Table of UUID Variants
            const uuidVariants = [
                uuidvar1,  // NCS compatibility
                uuidvar1,  // NCS compatibility
                uuidvar2,  // RFC 4122, RFC 9562
                uuidvar3,  // Microsoft GUIDs
            ];

            // ƒ Table of UUID Layouts for Variant #0/1 (NCS compatibility)
            const uuidvar1Layouts = [
                uuidvarNIL,
                uuidvar1reserved,
                uuidvar1reserved,
                uuidvar1reserved,
                uuidvar1reserved,
                uuidvar1reserved,
                uuidvar1reserved,
                uuidvar1reserved,
                uuidvar1reserved,
                uuidvar1reserved,
                uuidvar1reserved,
                uuidvar1reserved,
                uuidvar1reserved,
                uuidvar1reserved,
                uuidvar1reserved,
                uuidvarMAX,
            ];

            // ƒ Table of UUID Layouts for Variant #2 (RFC 4122, RFC 9562)
            const uuidvar2Layouts = [
                uuidvarNIL,
                uuidvar2v1,
                uuidvar2v2,
                uuidvar2v3,
                uuidvar2v4,
                uuidvar2v5,
                uuidvar2v6,
                uuidvar2v7,
                uuidvar2v8,
                uuidvar2reserved,
                uuidvar2reserved,
                uuidvar2reserved,
                uuidvar2reserved,
                uuidvar2reserved,
                uuidvar2reserved,
                uuidvarMAX
            ];

            // ƒ Table of UUID Layouts for Variant #3 (GUID)
            const uuidvar3Layouts = [
                uuidvarNIL,
                uuidvar3reserved,
                uuidvar3reserved,
                uuidvar3reserved,
                uuidvar3reserved,
                uuidvar3reserved,
                uuidvar3reserved,
                uuidvar3reserved,
                uuidvar3reserved,
                uuidvar3reserved,
                uuidvar3reserved,
                uuidvar3reserved,
                uuidvar3reserved,
                uuidvar3reserved,
                uuidvar3reserved,
                uuidvarMAX,
            ];

            // L A Y O U T S - by UUID Variant and their Versions

            // ƒ UUID Variant #0 and #1 - NCS compatibility
            function uuidvar1()
            {
                versionText = UUID_VAR1_VERSIONS[version];
                return uuidvar1Layouts[version]();
            }

            // ƒ UUID Variant #2 - RFC 4122 (Leach-Salz)
            function uuidvar2()
            {
                versionText = UUID_VAR2_VERSIONS[version];
                return uuidvar2Layouts[version]();
            }

            // ƒ UUID Variant #3 - Microsoft GUIDs
            function uuidvar3()
            {
                versionText = UUID_VAR3_VERSIONS[version];
                return uuidvar3Layouts[version]();
            }

            // V E R S I O N S - by UUID Variant

            // ƒ UUIDvar*v0 - Unused / Reserved for 00000000-0000-0000-0000-000000000000
            function uuidvarNIL()
            {
                // decoded by default as a generic UUID

                return uuidGenericLayout();
            }

            // ƒ UUIDvar*v15 - Unused / Reserved for FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF
            function uuidvarMAX()
            {
                // decoded by default as a generic UUID

                return uuidGenericLayout();
            }

            // ƒ UUIDv1, UUIDv1 - 14 - Unused /  reserved UUID variants
            function uuidvar1reserved()
            {
                // decoded by default as a generic UUID

                return uuidGenericLayout();
            }

            // ƒ UUIDv2, UUIDv9-15 - Unused /  reserved UUID variants
            function uuidvar2reserved()
            {
                // decoded by default as a generic UUID

                return uuidGenericLayout();
            }

            // D E C O D E R S - by UUID Variant and their Versions

            // ƒ to build a timestamp string in the format "YYYY-MMM-DD HH:MM:SS.mmm.uuu UTC"
            function makeTimestamp(time_high, time_mid, time_low, epochInMs, localTime, version)
            {
                try
                {
                    // Handle UUID version 1 (time-based)
                    const timeHigh = BigInt(parseInt(time_high, 16));
                    const timeMid = BigInt(parseInt(time_mid, 16));
                    const timeLow = BigInt(parseInt(time_low, 16));
                    let timeValue, timeValueInMs, millisecondsSinceEpoch, timeDate;

                    switch (version)
                    {
                        case 1:
                            // Combine the time fields into a 60-bit value using BigInt
                            timeValue = (timeHigh << 48n) | (timeMid << 32n) | timeLow;
                            // UUID uses 100-nanosecond intervals, so we convert the timeValue to milliseconds
                            timeValueInMs = timeValue / 10000n;
                            // Add time since UUID epoch to the precomputed epoch offset
                            millisecondsSinceEpoch = Number(timeValueInMs + epochInMs);
                            // Convert to a JavaScript Date object
                            timeDate = new Date(millisecondsSinceEpoch);
                            break;
                        case 6:
                            // Combine the time fields into a 60-bit value using BigInt
                            timeValue = (timeHigh << 28n) | (timeMid << 12n) | timeLow;
                            // UUID uses 100-nanosecond intervals, so we convert the timeValue to milliseconds
                            timeValueInMs = timeValue / 10000n;
                            // Add time since UUID epoch to the precomputed epoch offset
                            millisecondsSinceEpoch = Number(timeValueInMs + epochInMs);
                            // Convert to a JavaScript Date object
                            timeDate = new Date(millisecondsSinceEpoch);
                            break;
                        case 7:
                            // Combine the 48-bit timestamp from the first two fields
                            timeValue = (timeHigh << 16n) | timeLow;
                            // Convert the Unix timestamp (milliseconds since Unix epoch)
                            timeDate = new Date(Number(timeValue));
                            break;
                        default:
                            // Combine the time fields into a 60-bit value using BigInt
                            timeValue = 0;
                            break;
                    }

                    // Extract milliseconds and microseconds
                    const milliseconds = timeDate.getMilliseconds();
                    const microseconds = (version === 7) ? 0 : Number((timeValue % 10000n) / 10n);

                    if (localTime)
                    {
                        // Format the value to "YYYY-MMM-DD HH:MM:SS.mmm.uuu AM/PM"
                        const datePart = timeDate.toLocaleDateString('en-US', {year: 'numeric', month: 'short', day: '2-digit'});
                        const timePart = timeDate.toLocaleTimeString('en-US', {
                            hour: '2-digit',
                            minute: '2-digit',
                            second: '2-digit',
                            hour12: true
                        });
                        const ampm = timePart.slice(-2); // AM/PM part
                        const timeNoMeridian = timePart.slice(0, -3); // Time without AM/PM
                        timestampText = `${datePart} ${timeNoMeridian}.${milliseconds.toString().padStart(3, '0')}.${microseconds.toString().padStart(3, '0')} ${ampm}`;
                    }
                    else
                    {
                        // Format the value to "YYYY-MMM-DD HH:MM:SS.mmm.uuu UTC"
                        timestampText = timeDate.toISOString()
                            .replace('T', ' ')
                            .replace('Z', '')
                            .replace(/\.\d{3}/, `.${milliseconds.toString().padStart(3, '0')}.${microseconds.toString().padStart(3, '0')} UTC`);
                    }
                }
                catch
                {
                    // If there is an error, return the raw timestamp
                    timestampText = `${time_high}${time_mid}${time_low} - decode error`;
                }
                return timestampText;
            }

            // ƒ UUIDv1 - Unordered Time-based UUID
            function uuidvar2v1()
            {
                /*
                 UUIDv1 Field and Bit Layout - Gregorian Unordered Time-based UUID:
                 3             2               1               0               0
                 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
                +---------------+---------------+---------------+---------------+
                |                         time_low                              |
                +---------------+---------------+--------+------+---------------+
                |            time_mid           |   ver  |     time_high        |
                ----+-----------+---------------+--------+------+---------------+
                |var|        clock_seq          |            node               |
                +---+-----------+---------------+---------------+---------------+
                |                            node                               |
                +---------------+---------------+---------------+---------------+
                */

                const time_low = part_a1;
                const time_mid = part_a0;
                const time_high = part_b;
                const time = `${time_high}${time_mid}${time_low}`;
                const clock_seq = part_c2;
                const clockSeq = BigInt(parseInt(clock_seq, 16));
                const node = part_c1 + part_c0;

                // Determine if the node is multicast based on the first bit of 'node'
                const multicastBit = parseInt(node.substring(0, 1), 16) >> 3;  // Extract multicast flag (1 bit) from node
                const multicast = multicastBit === 1;
                const multicastText = multicast ? 'Multicast' : 'Unicast';

                // The reset is based on UUID Variant and the Version of that Variant...
                let nodeType;
                let nodeValue;

                // Multicast or Unicast Addressed node
                nodeType = multicast ? 'MAC Address (Multicast)' : 'MAC Address (Unicast)';
                nodeValue = node.match(/.{2}/g).join(':');

                // The epoch is October 15, 1582 (start of UUID time)
                const epochInMs = BigInt(Date.UTC(1582, 9, 15));

                // Get 'YYYY-MMM-DD HH:MM:SS.mmm.uuu UTC'
                const timestampText = makeTimestamp(time_high, time_mid, time_low, epochInMs, localTime, 1);

                // Return Variant 2 UUIDv1 Decoded
                return {

                    UUID: uuid,

                    Variant: variant,
                    VariantText: variantText,

                    Version: version,
                    VersionText: versionText,

                    Value1Name: "Timestamp",
                    Value1: timestampText,

                    Value2Name: "Clock Sequence",
                    Value2: clockSeq,

                    Value3Name: "",
                    Value3: "",

                    Value4Name: "Node Type",
                    Value4: nodeType,

                    Value5Name: "Node Address",
                    Value5: `${nodeValue}`,

                    Value6Name: "",
                    Value6: "",

                    NumberName: "Random Number",
                    NumberText: `0x${time_high}${time_mid}${time_low}`,

                    time_low: time_low,
                    time_mid: time_mid,
                    time_high: time_high,
                    time: time,
                    clock_seq: clock_seq,
                    multicast: multicast,
                    multicastText: multicastText,
                    node: node,
                    macid: nodeValue
                };
            }

            // ƒ UUIDv2 - DCE Security (POSIX) UUID
            function uuidvar2v2()
            {
                /*
                 UUIDv2 Field and Bit Layout -  DCE Security (POSIX) UUID:
                 3             2               1               0               0
                 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
                +---------------+---------------+---------------+---------------+
                |                         part_a1                               |
                +---------------+---------------+--------+------+---------------+
                |            part_a0            |   ver  |     part_b           |
                ----+-----------+---------------+--------+------+---------------+
                |var|        part_c2            |            part_c1            |
                +---+-----------+---------------+---------------+---------------+
                |                            part_c0                            |
                +---------------+---------------+---------------+---------------+
                */

                // {TBD} - not documented in RFC 9562

                return uuidGenericLayout();
            }

            // ƒ UUIDv3 - Name-Based (MD5 Hash) UUID
            function uuidvar2v3()
            {
                /*
                 UUIDv3 Field and Bit Layout - Name-Based (MD5 Hash) UUID:
                 3             2               1               0               0
                 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
                +---------------+---------------+---------------+---------------+
                |                         md5_high_1                            |
                +---------------+---------------+--------+------+---------------+
                |            md5_high_0         |   ver  |     md5_mid          |
                ----+-----------+---------------+--------+------+---------------+
                |var|        md5_low_2          |            md5_low_1          |
                +---+-----------+---------------+---------------+---------------+
                |                            md5_low_0                          |
                +---------------+---------------+---------------+---------------+
                */

                const md5_high_1 = part_a1;
                const md5_high_0 = part_a0;
                const md5_high = `${md5_high_1}${md5_high_0}`;
                const md5_mid = part_b;
                const md5_low_2 = part_c2;
                const md5_low_1 = part_c1;
                const md5_low_0 = part_c0;
                const md5_low = `${md5_low_2}${md5_low_1}${md5_low_0}`;

                const md5 = `${md5_high}${md5_mid}${md5_low}`;

                // Return Variant 2 UUIDv1 Decoded
                return {

                    UUID: uuid,

                    Variant: variant,
                    VariantText: variantText,

                    Version: version,
                    VersionText: versionText,

                    Value1Name: "md5_high",
                    Value1: md5_high,

                    Value2Name: "md5_mid",
                    Value2: md5_mid,

                    Value3Name: "md5_low",
                    Value3: md5_low,

                    Value4Name: "",
                    Value4: '',

                    Value5Name: "",
                    Value5: '',

                    Value6Name: "",
                    Value6: '',

                    NumberName: "MD5 Hash",
                    NumberText: `0x${md5}`,

                    md5_high: md5_high,
                    md5_mid: md5_mid,
                    md5_low: md5_low,

                    MD5: md5
                };
            }

            // ƒ UUIDv4 - Random-Based Number UUID
            function uuidvar2v4()
            {
                /*
                 UUIDv4 Field and Bit Layout - Random-Based Number UUID:
                 3             2               1               0               0
                 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
                +---------------+---------------+---------------+---------------+
                |                        random_a1                              |
                +---------------+---------------+--------+------+---------------+
                |            random_a0          |   ver  |     random_b         |
                ----+-----------+---------------+--------+------+---------------+
                |var|        random_c2          |            random_c1          |
                +---+-----------+---------------+---------------+---------------+
                |                            part_c0                            |
                +---------------+---------------+---------------+---------------+
                */

                const random_a1 = part_a1;
                const random_a0 = part_a0;
                const random_a = `${random_a1}${random_a0}`;
                const random_b = part_b;
                const random_c2 = part_c2;
                const random_c1 = part_c1;
                const random_c0 = part_c0;
                const random_c = `${random_c2}${random_c1}${random_c0}`;

                const random = `${random_a}${random_b}${random_c}`;

                // Return Variant 2 UUIDv1 Decoded
                return {

                    UUID: uuid,

                    Variant: variant,
                    VariantText: variantText,

                    Version: version,
                    VersionText: versionText,

                    Value1Name: "random_a",
                    Value1: random_a,

                    Value2Name: "random_b",
                    Value2: random_b,

                    Value3Name: "random_c",
                    Value3: random_c,

                    Value4Name: "",
                    Value4: '',

                    Value5Name: "",
                    Value5: '',

                    Value6Name: "",
                    Value6: '',

                    NumberName: "Random Number",
                    NumberText: `0x${random}`,

                    random_a: random_a,
                    random_b: random_b,
                    random_c: random_c,

                    Random: random
                };
            }

            // ƒ UUIDv5 - Name Based (SHA-1 Hash) UUID
            function uuidvar2v5()
            {
                /*
                 UUIDv5 Field and Bit Layout -  Name Based (SHA-1 Hash) UUID:
                 3             2               1               0               0
                 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
                +---------------+---------------+---------------+---------------+
                |                         sha1_high_1                           |
                +---------------+---------------+--------+------+---------------+
                |            sha1_high_0        |   ver  |     sha1_mid         |
                ----+-----------+---------------+--------+------+---------------+
                |var|        sha1_low_2         |            sha1_low_1         |
                +---+-----------+---------------+---------------+---------------+
                |                            sha1_low_0                         |
                +---------------+---------------+---------------+---------------+
                */

                const sha1_high_1 = part_a1;
                const sha1_high_0 = part_a0;
                const sha1_high = `${sha1_high_1}${sha1_high_0}`;
                const sha1_mid = part_b;
                const sha1_low_2 = part_c2;
                const sha1_low_1 = part_c1;
                const sha1_low_0 = part_c0;
                const sha1_low = `${sha1_low_2}${sha1_low_1}${sha1_low_0}`;

                const sha1 = `${sha1_high}${sha1_mid}${sha1_low}`;

                // Return Variant 2 UUIDv1 Decoded
                return {

                    UUID: uuid,

                    Variant: variant,
                    VariantText: variantText,

                    Version: version,
                    VersionText: versionText,

                    Value1Name: "sha1_high",
                    Value1: sha1_high,

                    Value2Name: "sha1_mid",
                    Value2: sha1_mid,

                    Value3Name: "sha1_low",
                    Value3: sha1_low,

                    Value4Name: "",
                    Value4: '',

                    Value5Name: "",
                    Value5: '',

                    Value6Name: "",
                    Value6: '',

                    NumberName: "SHA-1 Hash",
                    NumberText: `0x${sha1}`,

                    sha1_high: sha1_high,
                    sha1_mid: sha1_mid,
                    sha1_low: sha1_low,

                    "SHA-1": sha1
                };
            }

            // ƒ UUIDv6 - Gregorian Ordered Timestamp UUID
            function uuidvar2v6()
            {
                /*
                 UUIDv6 Field and Bit Layout - Gregorian Ordered Timestamp UUID:
                 3             2               1               0               0
                 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
                +---------------+---------------+---------------+---------------+
                |                         time_high                             |
                +---------------+---------------+--------+------+---------------+
                |            time_mid           |   ver  |     time_low         |
                ----+-----------+---------------+--------+------+---------------+
                |var|        clock_seq          |            node               |
                +---+-----------+---------------+---------------+---------------+
                |                            node                               |
                +---------------+---------------+---------------+---------------+
                */

                const time_high = part_a1;
                const time_mid = part_a0;
                const time_low = part_b;
                const time = `${time_high}${time_mid}${time_low}`;
                const clock_seq = part_c2;
                const clockSeq = BigInt(parseInt(clock_seq, 16));
                const node = part_c1 + part_c0;

                // Determine if the node is multicast based on the first bit of 'node'
                const multicastBit = parseInt(node.substring(0, 1), 16) >> 3;  // Extract multicast flag (1 bit) from node
                const multicast = multicastBit === 1;
                const multicastText = multicast ? 'Multicast' : 'Unicast';

                // The reset is based on UUID Variant and the Version of that Variant...
                let nodeType;
                let nodeValue;

                // Multicast or Unicast Addressed node
                nodeType = multicast ? 'MAC Address (Multicast)' : 'MAC Address (Unicast)';
                nodeValue = node.match(/.{2}/g).join(':');

                // The epoch is October 15, 1582 (start of UUID time)
                const epochInMs = BigInt(Date.UTC(1582, 9, 15));

                // Get 'YYYY-MMM-DD HH:MM:SS.mmm.uuu UTC'
                const timestampText = makeTimestamp(time_high, time_mid, time_low, epochInMs, localTime, 6);

                // Return Variant 2 UUIDv1 Decoded
                return {

                    UUID: uuid,

                    Variant: variant,
                    VariantText: variantText,

                    Version: version,
                    VersionText: versionText,

                    Value1Name: "Timestamp",
                    Value1: timestampText,

                    Value2Name: "Clock Sequence",
                    Value2: clockSeq,

                    Value3Name: "",
                    Value3: "",

                    Value4Name: "Node Type",
                    Value4: nodeType,

                    Value5Name: "Node Address",
                    Value5: `${nodeValue}`,

                    Value6Name: "",
                    Value6: "",

                    NumberName: "Random Number",
                    NumberText: `0x${time_high}${time_mid}${time_low}`,

                    time_low: time_low,
                    time_mid: time_mid,
                    time_high: time_high,
                    time: time,
                    clock_seq: clock_seq,
                    multicast: multicast,
                    multicastText: multicastText,
                    node: node,
                };
            }

            // ƒ UUIDv7 - Unix Epoch Timestamp UUID
            function uuidvar2v7()
            {
                /*
                 UUIDv7 Field and Bit Layout - Unix Epoch Timestamp UUID:
                 3             2               1               0               0
                 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
                +---------------+---------------+---------------+---------------+
                |                         unix_ts1_ms                           |
                +---------------+---------------+--------+------+---------------+
                |            unix_ts0_ms        |   ver  |     rand_a           |
                ----+-----------+---------------+--------+------+---------------+
                |var|        rand_b2            |            rand_b1            |
                +---+-----------+---------------+---------------+---------------+
                |                            rand_b0                            |
                +---------------+---------------+---------------+---------------+
                */

                const unix_ts1_ms = part_a1;
                const unix_ts0_ms = part_a0;
                const unix_ts_ms = `${unix_ts1_ms}${unix_ts0_ms}`;
                const rand_a = part_b;
                const rand_b2 = part_c2;
                const rand_b1 = part_c1;
                const rand_b0 = part_c0;
                const rand_b = `${rand_b2}${rand_b1}${rand_b0}`;
                const rand = `${rand_a}${rand_b}`;

                // The epoch is January 1, 1970 (start of UNIX time)
                const epochInMs = BigInt(Date.UTC(1970, 1, 1));

                // Get 'YYYY-MMM-DD HH:MM:SS.mmm.uuu UTC' - v7 onlt has a High and Low, no Mid
                const timestampText = makeTimestamp(unix_ts1_ms, 0, unix_ts0_ms, epochInMs, localTime, 7);

                // Return Variant 2 UUIDv1 Decoded
                return {

                    UUID: uuid,

                    Variant: variant,
                    VariantText: variantText,

                    Version: version,
                    VersionText: versionText,

                    Value1Name: "Timestamp",
                    Value1: timestampText,

                    Value2Name: "",
                    Value2: "",

                    Value3Name: "",
                    Value3: "",

                    Value4Name: "rand_a",
                    Value4: rand_a,

                    Value5Name: "rand_b",
                    Value5: rand_b,

                    Value6Name: "",
                    Value6: '',

                    NumberName: "Random Number",
                    NumberText: `0x${rand}`,

                    rand_a: rand_a,
                    rand_b: rand_b,
                    rand: rand,

                    unix_ts_ms: unix_ts_ms,

                    Random: rand
                };
            }

            // ƒ UUIDv8 - Custom Encoding Format UUID
            function uuidvar2v8()
            {
                /*
                 UUIDv8 Field and Bit Layout - Custom Encoding Format UUID:
                 3             2               1               0               0
                 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
                +---------------+---------------+---------------+---------------+
                |                         custom_a1                             |
                +---------------+---------------+--------+------+---------------+
                |            custom_a0          |   ver  |     custom_b         |
                ----+-----------+---------------+--------+------+---------------+
                |var|        custom_c2          |            custom_c1          |
                +---+-----------+---------------+---------------+---------------+
                |                            custom_c0                          |
                +---------------+---------------+---------------+---------------+
                */

                const custom_a1 = part_a1;
                const custom_a0 = part_a0;
                const custom_a = `${custom_a1}${custom_a0}`;
                const custom_b = part_b;
                const custom_c2 = part_c2;
                const custom_c1 = part_c1;
                const custom_c0 = part_c0;
                const custom_c = `${custom_c2}${custom_c1}${custom_c0}`;

                const custom = `${custom_a}${custom_b}${custom_c}`;

                // Return Variant 2 UUIDv1 Decoded
                return {

                    UUID: uuid,

                    Variant: variant,
                    VariantText: variantText,

                    Version: version,
                    VersionText: versionText,

                    Value1Name: "custom_a",
                    Value1: custom_a,

                    Value2Name: "custom_b",
                    Value2: custom_b,

                    Value3Name: "custom_c",
                    Value3: custom_c,

                    Value4Name: "",
                    Value4: '',

                    Value5Name: "",
                    Value5: '',

                    Value6Name: "",
                    Value6: '',

                    NumberName: "Custom Encoding",
                    NumberText: `0x${custom}`,

                    custom_a: custom_a,
                    custom_b: custom_b,
                    custom_c: custom_c,

                    Custom: custom
                };
            }

            // ƒ UUIDv3, Microsoft GUID, UUIDv1 - 14 - Unused /  reserved UUID variants
            function uuidvar3reserved()
            {
                // decoded by default as a generic UUID

                return uuidGenericLayout();
            }

            /*
             UUID Generic Structure:
             3             2               1               0               0
             1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
            +---------------+---------------+---------------+---------------+
            |                         part_a1                               |
            +---------------+---------------+--------+------+---------------+
            |            part_a0            |   ver  |     part_b           |
            ----+-----------+---------------+--------+------+---------------+
            |var|        part_c2            |            part_c1            |
            +---+-----------+---------------+---------------+---------------+
            |                            part_c0                            |
            +---------------+---------------+---------------+---------------+
            */

            // ƒ uuidGenericLayout - Generic UUID Layout
            function uuidGenericLayout()
            {
                const random = `${part_a1}${part_a0}${part_b}${part_c2}${part_c1}${part_c0}`;

                // Return Generic UUID Decoded
                return {

                    UUID: uuid,

                    Variant: variant,
                    VariantText: variantText,

                    Version: version,
                    VersionText: versionText,

                    Value1Name: "part_a",
                    Value1: part_a,

                    Value2Name: "part_b",
                    Value2: part_b,

                    Value3Name: "part_c",
                    Value3: part_c,

                    Value4Name: "",
                    Value4: '',

                    Value5Name: "",
                    Value5: '',

                    Value6Name: "",
                    Value6: '',

                    NumberName: "Random Number",
                    NumberText: `0x${random}`,

                    part_a: part_a,
                    part_b: part_b,
                    part_c: part_c,

                    Random: random
                };
            }

            // M A I N - D E C O D E R

            // Split the UUID into parts: aaaaaaaa-aaaa-vbbb-Vccc-cccccccccccc
            //                            11111111 0000       222 111100000000
            if (!uuid)
            {
                // return NIL for a missing UUID
                return {
                    UUID: uuid,
                    Variant: variant,
                    VariantText: "NIL Value",

                    Version: version,
                    VersionText: "Reserved / NIL",

                    Value1Name: "",
                    Value1: "",
                    Value2Name: "",
                    Value2: "",
                    Value3Name: "",
                    Value3: "",
                    Value4Name: "",
                    Value4: "",
                    Value5Name: "",
                    Value5: "",
                    Value6Name: "",
                    Value6: "",

                    NumberName: "",
                    NumberText: "",

                    NIL: true,
                    NILText: "00000000-0000-0000-0000-000000000000"
                };
            }

            // These pieces are common divisions of all UUIDs and they are interpreted
            // based on the UUID variant and version.
            uuid = uuid.toLowerCase();
            const UUID = uuid.toUpperCase();
            const [part_a1, part_a0, ver_part_b, var_part_c1, part_c1_c0] = uuid.split('-');
            const part_a = `${part_a1}${part_a0}`;
            const version = parseInt(ver_part_b.substring(0, 1), 16);
            const part_b = ver_part_b.substring(1);
            const variant = (parseInt(var_part_c1.substring(0, 1), 16) >> 2) & 0b11;
            const part_c2 = (parseInt(var_part_c1.substring(0, 1), 16) & 0b11).toString(16) + var_part_c1.substring(1);
            const part_c1 = part_c1_c0.substring(0, 4);
            const part_c0 = part_c1_c0.substring(4);
            const part_c = `${part_c2}${part_c1}${part_c0}`;

            // How to interpret the UUID...
            const variantText = UUID_VARIANTS[variant];
            let versionText = '<undetermined>';
            let variantValue1Name = 'part_a1';
            let variantValue1 = part_a1;
            let variantValue2Name = 'part_a0';
            let variantValue2 = part_a0;
            let variantValue3Name = 'part_b';
            let variantValue3 = part_b;
            let variantValue4Name = 'part_c2';
            let variantValue4 = part_c2;
            let variantValue5Name = 'part_c1';
            let variantValue5 = part_c1;
            let variantValue6Name = 'part_c0';
            let variantValue6 = part_c0;

            // If every thing is "0" then it's a NIL Value
            if (UUID === "00000000-0000-0000-0000-000000000000")
            {
                return {
                    UUID: uuid,
                    Variant: variant,
                    VariantText: "NIL Value",

                    Version: version,
                    VersionText: "Reserved / NIL",

                    Value1Name: "",
                    Value1: "",
                    Value2Name: "",
                    Value2: "",
                    Value3Name: "",
                    Value3: "",
                    Value4Name: "",
                    Value4: "",
                    Value5Name: "",
                    Value5: "",
                    Value6Name: "",
                    Value6: "",

                    NumberName: "",
                    NumberText: "",

                    NIL: true,
                    NILText: "00000000-0000-0000-0000-000000000000"
                };
            }
            else if (UUID === "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF")
            {
                return {
                    UUID: uuid,
                    Variant: variant,
                    VariantText: "MAX Value",

                    Version: version,
                    VersionText: "Reserved / MAX",

                    Value1Name: "",
                    Value1: "",
                    Value2Name: "",
                    Value2: "",
                    Value3Name: "",
                    Value3: "",
                    Value4Name: "",
                    Value4: "",
                    Value5Name: "",
                    Value5: "",
                    Value6Name: "",
                    Value6: "",

                    NumberName: "",
                    NumberText: "",

                    MAX: true,
                    MAXText: "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"
                };
            }
            else
            {
                // Decode the UUID based on the variant and version
                return uuidVariants[variant]();
            }
        },

        /**
         * @func toSnakeCase
         * @memberof mcode
         * @desc Returns a lowercase-snake-case-name by converting a string's spaces to hyphens and discarding non-alphanumeric characters.
         * @param {string} str the string to convert to snake case.
         * @returns {string} a value representing the snake case version of the string.
         */
        toSnakeCase: function (str)
        {
            return str
                .toLowerCase()            // convert the entire string to lowercase
                .replace(/[^\w\s]/g, '')  // remove any non-alphanumeric characters except spaces
                .replace(/\s+/g, '-')     // replace spaces with hyphens
                .replace(/^-+|-+$/g, ''); // remove any leading or trailing hyphens
        },

        /**
         * @func fromSnakeCase
         * @memberof mcode
         * @desc Returns a text string by converting a snake-case-name to Title Case Name sentence.
         * @param {string} str the string to convert from snake case.
         * @returns {string} a value representing the Title Case version of the string.
         */
        fromSnakeCase: function (str)
        {
            return str
                .split('-')               // split the string at hyphens
                .map(word => word.charAt(0).toUpperCase() + word.slice(1)) // capitalize the first letter of each word
                .join(' ');               // join the words with spaces
        },

        /**
         * @function sleep
         * @memberof mcode
         * @desc Pauses execution for a specified duration.
         * @param {number} ms The duration to sleep in milliseconds.
         * @returns {Promise} A promise that resolves after the specified duration.
         */
        sleep: function (ms)
        {
            return new Promise(resolve => setTimeout(resolve, ms));
        },

        /**
         * @function generateRandomId
         * @memberof mcode
         * @desc Generates a random identifier in hexadecimal format, useful for creating unique IDs in the UI.
         * The number generated is a random 6-digit hexadecimal string (e.g., '3F5A9C') which can be used as a suffix or part of an identifier.
         * This number will be in the range of 000000 to FFFFFF (0 to 16,777,215 in decimal).
         * @param {string} prefix A prefix to prepend to the time for a complete identifier.
         * @returns {string} A unique random identifier, optionally prefixed for better scope control and identifcation.
         */
        generateRandomId: function (prefix)
        {
            // Generate a random 6-digit hexadecimal string
            const id = Math.floor(Math.random() * 0x1000000).toString(16).padStart(6, '0').toUpperCase();
            return prefix ? `${prefix}-${id}` : id;
        },

        /**
         * @function encodeJson
         * @memberof mcode
         * @desc Encodes a value as a JSON string with special character replacements.
         * @param {any} value The value to encode.
         * @returns {string} The encoded JSON string.
         */
        encodeJson: function (value)
        {
            if (value === undefined || value === null) return '';

            // Use JSON.stringify, then escape critical HTML-breaking and XSS (Cross Site Scripting) characters
            return JSON.stringify(value)
                .replace(/</g, '\\u003C')
                .replace(/>/g, '\\u003E')
                .replace(/&/g, '\\u0026')
                .replace(/'/g, '\\u0027')
                .replace(/"/g, '\\u0022');
        },

        /**
         * @function encodeAttr
         * @memberof backend.uic.grafx
         * @desc Encodes special HTML characters in a string for safe inclusion in HTML attributes.
         * @param {string} value - The value to escape
         * @returns {string} The escaped value
         */
        encodeAttr: function (value)
        {
            if (value === undefined || value === null) return '';

            return String(value)
                .replace(/&/g, '&amp;')
                .replace(/"/g, '&quot;')
                .replace(/'/g, '&#39;')
                .replace(/</g, '&lt;')
                .replace(/>/g, '&gt;');
        },

        /**
         * @function classExport
         * @memberof mcode
         * @desc >
         * Safely registers a class in the global namespace or a specified namespace if it is not already defined.
         * If Namespace.ClassName already exists and has bootstrapPending(), it is called, and the existing value is returned.
         * See GitHub Repo 'MicroCODEIncorporated/TemplateJS' for a Class Template designed for this invocation.
         * When this is used as a module wrapper, it becomes an Immediately Invoked Function Expression (IIFE) invoked on 'this' which
         * represents the global object (window in a browser, global in Node.js).
         * That IIFE returns the 'Class' object to be assigned to the global object.
         * The Universal Module Definition (UMD) pattern supports Asynchronous Module Definition (AMD),
         * CommonJS / Node.js, and Browser 'global' usage. {0008}
         * @param {string|null} namespaceName - [Optional] global namespace (e.g., "MyApp"), if you want
         * your Class available directly on the Global/Root namespace pass an empty string "".
         * @param {string} className - Name of the class to export.
         * @param {Function} factory - A function (root: any) that returns the class constructor.
         * @returns {Function|any} The class constructor or the existing class if it already exists.
         * @example
         *
         *    mcode.classExport('Namespace', 'ClassName', function (root)
         *    {
         *        class ClassName...  // the entire class is declared within 'function (root) { * }'.
         *    });
         *
         */
        classExport: function (namespaceName, className, factory)
        {
            if (typeof className !== 'string' || !className.trim()) throw new Error('mcode.classExport() requires a Class Name.');
            if (typeof factory !== 'function') throw new Error('mcode.classExport() requires a function to define the Class.');

            const root = (typeof globalThis !== 'undefined')
                ? globalThis
                : (typeof self !== 'undefined' ? self : this);

            const namespace = namespaceName
                ? (root[namespaceName] = root[namespaceName] || {})
                : root;

            if (!namespace[className])
            {
                namespace[className] = factory(root);
            }
            else if (typeof namespace[className].bootstrapPending === 'function')
            {
                namespace[className].bootstrapPending();
            }

            return namespace[className];
        }
    };

    // #endregion

    // #region  M E T H O D - E X P O R T S

    // Immediately Invoked Function Expression (IIFE) invoked on 'this' which
    // represents the global object (window in a browser, global in Node.js).
    // This IIFE returns the 'mcode' object to be assigned to the global object.
    // The Universal Module Definition (UMD) pattern supports Asynchronous Module Definition (AMD),
    // CommonJS / Node.js, and Browser 'global' usage. {0008}
    (
        /**
         * @function (IIFE)
         * @desc Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, and browser global
         * @param {any} root the global object (window, self, global, etc.) being updated.
         * @param {any} factory a function that returns the exports of the module. This function is invoked in
         * the context of the global object when the module is loaded. The return value of this function is used
         * as the exported value of the module when it's not being used with AMD or Node.js module systems.
         * This function is where you define what your module exports.
         */
        function (root, factory)
        {
            if (typeof define === 'function' && define.amd)
            {
                // AMD. Register as an anonymous module.
                define([], factory);
            }
            else if (typeof module === 'object' && module.exports)
            {
                // Node. Does not work with strict CommonJS, but
                // only CommonJS-like environments that support module.exports, like Node.
                module.exports = factory();
            }
            else
            {
                // Browser globals (root is 'window')
                root.mcode = factory();
            }

        }(  // root: the global object (window, self, global, etc.)
            (typeof self !== 'undefined') ? self : this,

            // factory: a function that returns the exports of the module
            function () {return mcode;})
    );

    // #endregion

    // #endregion
    // #endregion