Index: frontend/node_modules/@humanwhocodes/object-schema/CHANGELOG.md
===================================================================
--- frontend/node_modules/@humanwhocodes/object-schema/CHANGELOG.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/@humanwhocodes/object-schema/CHANGELOG.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,40 @@
+# Changelog
+
+## [2.0.3](https://github.com/humanwhocodes/object-schema/compare/v2.0.2...v2.0.3) (2024-04-01)
+
+
+### Bug Fixes
+
+* Ensure test files are not including in package ([6eeb32c](https://github.com/humanwhocodes/object-schema/commit/6eeb32cc76a3e37d76b2990bd603d72061c816e0)), closes [#19](https://github.com/humanwhocodes/object-schema/issues/19)
+
+## [2.0.2](https://github.com/humanwhocodes/object-schema/compare/v2.0.1...v2.0.2) (2024-01-10)
+
+
+### Bug Fixes
+
+* WrapperError should be an actual error ([2523f01](https://github.com/humanwhocodes/object-schema/commit/2523f014168167e5a40bb63e0cc03231b2c0f1bf))
+
+## [2.0.1](https://github.com/humanwhocodes/object-schema/compare/v2.0.0...v2.0.1) (2023-10-20)
+
+
+### Bug Fixes
+
+* Custom properties should be available on thrown errors ([6ca80b0](https://github.com/humanwhocodes/object-schema/commit/6ca80b001a4ffb678b9b5544fc53322117374376))
+
+## [2.0.0](https://github.com/humanwhocodes/object-schema/compare/v1.2.1...v2.0.0) (2023-10-18)
+
+
+### ⚠ BREAKING CHANGES
+
+* Throw custom errors instead of generics.
+
+### Features
+
+* Throw custom errors instead of generics. ([c6c01d7](https://github.com/humanwhocodes/object-schema/commit/c6c01d71eb354bf7b1fb3e883c40f7bd9b61647c))
+
+### [1.2.1](https://www.github.com/humanwhocodes/object-schema/compare/v1.2.0...v1.2.1) (2021-11-02)
+
+
+### Bug Fixes
+
+* Never return original object from individual config ([5463c5c](https://www.github.com/humanwhocodes/object-schema/commit/5463c5c6d2cb35a7b7948dffc37c899a41d1775f))
Index: frontend/node_modules/@humanwhocodes/object-schema/LICENSE
===================================================================
--- frontend/node_modules/@humanwhocodes/object-schema/LICENSE	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/@humanwhocodes/object-schema/LICENSE	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2019, Human Who Codes
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* Neither the name of the copyright holder nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Index: frontend/node_modules/@humanwhocodes/object-schema/README.md
===================================================================
--- frontend/node_modules/@humanwhocodes/object-schema/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/@humanwhocodes/object-schema/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,234 @@
+# JavaScript ObjectSchema Package
+
+by [Nicholas C. Zakas](https://humanwhocodes.com)
+
+If you find this useful, please consider supporting my work with a [donation](https://humanwhocodes.com/donate).
+
+## Overview
+
+A JavaScript object merge/validation utility where you can define a different merge and validation strategy for each key. This is helpful when you need to validate complex data structures and then merge them in a way that is more complex than `Object.assign()`.
+
+## Installation
+
+You can install using either npm:
+
+```
+npm install @humanwhocodes/object-schema
+```
+
+Or Yarn:
+
+```
+yarn add @humanwhocodes/object-schema
+```
+
+## Usage
+
+Use CommonJS to get access to the `ObjectSchema` constructor:
+
+```js
+const { ObjectSchema } = require("@humanwhocodes/object-schema");
+
+const schema = new ObjectSchema({
+
+    // define a definition for the "downloads" key
+    downloads: {
+        required: true,
+        merge(value1, value2) {
+            return value1 + value2;
+        },
+        validate(value) {
+            if (typeof value !== "number") {
+                throw new Error("Expected downloads to be a number.");
+            }
+        }
+    },
+
+    // define a strategy for the "versions" key
+    version: {
+        required: true,
+        merge(value1, value2) {
+            return value1.concat(value2);
+        },
+        validate(value) {
+            if (!Array.isArray(value)) {
+                throw new Error("Expected versions to be an array.");
+            }
+        }
+    }
+});
+
+const record1 = {
+    downloads: 25,
+    versions: [
+        "v1.0.0",
+        "v1.1.0",
+        "v1.2.0"
+    ]
+};
+
+const record2 = {
+    downloads: 125,
+    versions: [
+        "v2.0.0",
+        "v2.1.0",
+        "v3.0.0"
+    ]
+};
+
+// make sure the records are valid
+schema.validate(record1);
+schema.validate(record2);
+
+// merge together (schema.merge() accepts any number of objects)
+const result = schema.merge(record1, record2);
+
+// result looks like this:
+
+const result = {
+    downloads: 75,
+    versions: [
+        "v1.0.0",
+        "v1.1.0",
+        "v1.2.0",
+        "v2.0.0",
+        "v2.1.0",
+        "v3.0.0"
+    ]
+};
+```
+
+## Tips and Tricks
+
+### Named merge strategies
+
+Instead of specifying a `merge()` method, you can specify one of the following strings to use a default merge strategy:
+
+* `"assign"` - use `Object.assign()` to merge the two values into one object.
+* `"overwrite"` - the second value always replaces the first.
+* `"replace"` - the second value replaces the first if the second is not `undefined`.
+
+For example:
+
+```js
+const schema = new ObjectSchema({
+    name: {
+        merge: "replace",
+        validate() {}
+    }
+});
+```
+
+### Named validation strategies
+
+Instead of specifying a `validate()` method, you can specify one of the following strings to use a default validation strategy:
+
+* `"array"` - value must be an array.
+* `"boolean"` - value must be a boolean.
+* `"number"` - value must be a number.
+* `"object"` - value must be an object.
+* `"object?"` - value must be an object or null.
+* `"string"` - value must be a string.
+* `"string!"` - value must be a non-empty string.
+
+For example:
+
+```js
+const schema = new ObjectSchema({
+    name: {
+        merge: "replace",
+        validate: "string"
+    }
+});
+```
+
+### Subschemas
+
+If you are defining a key that is, itself, an object, you can simplify the process by using a subschema. Instead of defining `merge()` and `validate()`, assign a `schema` key that contains a schema definition, like this:
+
+```js
+const schema = new ObjectSchema({
+    name: {
+        schema: {
+            first: {
+                merge: "replace",
+                validate: "string"
+            },
+            last: {
+                merge: "replace",
+                validate: "string"
+            }
+        }
+    }
+});
+
+schema.validate({
+    name: {
+        first: "n",
+        last: "z"
+    }
+});
+```
+
+### Remove Keys During Merge
+
+If the merge strategy for a key returns `undefined`, then the key will not appear in the final object. For example:
+
+```js
+const schema = new ObjectSchema({
+    date: {
+        merge() {
+            return undefined;
+        },
+        validate(value) {
+            Date.parse(value);  // throws an error when invalid
+        }
+    }
+});
+
+const object1 = { date: "5/5/2005" };
+const object2 = { date: "6/6/2006" };
+
+const result = schema.merge(object1, object2);
+
+console.log("date" in result);  // false
+```
+
+### Requiring Another Key Be Present
+
+If you'd like the presence of one key to require the presence of another key, you can use the `requires` property to specify an array of other properties that any key requires. For example:
+
+```js
+const schema = new ObjectSchema();
+
+const schema = new ObjectSchema({
+    date: {
+        merge() {
+            return undefined;
+        },
+        validate(value) {
+            Date.parse(value);  // throws an error when invalid
+        }
+    },
+    time: {
+        requires: ["date"],
+        merge(first, second) {
+            return second;
+        },
+        validate(value) {
+            // ...
+        }
+    }
+});
+
+// throws error: Key "time" requires keys "date"
+schema.validate({
+    time: "13:45"
+});
+```
+
+In this example, even though `date` is an optional key, it is required to be present whenever `time` is present.
+
+## License
+
+BSD 3-Clause
Index: frontend/node_modules/@humanwhocodes/object-schema/package.json
===================================================================
--- frontend/node_modules/@humanwhocodes/object-schema/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/@humanwhocodes/object-schema/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,38 @@
+{
+  "name": "@humanwhocodes/object-schema",
+  "version": "2.0.3",
+  "description": "An object schema merger/validator",
+  "main": "src/index.js",
+  "files": [
+    "src",
+    "LICENSE",
+    "README.md"
+  ],
+  "directories": {
+    "test": "tests"
+  },
+  "scripts": {
+    "test": "mocha tests/"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/humanwhocodes/object-schema.git"
+  },
+  "keywords": [
+    "object",
+    "validation",
+    "schema",
+    "merge"
+  ],
+  "author": "Nicholas C. Zakas",
+  "license": "BSD-3-Clause",
+  "bugs": {
+    "url": "https://github.com/humanwhocodes/object-schema/issues"
+  },
+  "homepage": "https://github.com/humanwhocodes/object-schema#readme",
+  "devDependencies": {
+    "chai": "^4.2.0",
+    "eslint": "^5.13.0",
+    "mocha": "^5.2.0"
+  }
+}
Index: frontend/node_modules/@humanwhocodes/object-schema/src/index.js
===================================================================
--- frontend/node_modules/@humanwhocodes/object-schema/src/index.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/@humanwhocodes/object-schema/src/index.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,7 @@
+/**
+ * @filedescription Object Schema Package
+ */
+
+exports.ObjectSchema = require("./object-schema").ObjectSchema;
+exports.MergeStrategy = require("./merge-strategy").MergeStrategy;
+exports.ValidationStrategy = require("./validation-strategy").ValidationStrategy;
Index: frontend/node_modules/@humanwhocodes/object-schema/src/merge-strategy.js
===================================================================
--- frontend/node_modules/@humanwhocodes/object-schema/src/merge-strategy.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/@humanwhocodes/object-schema/src/merge-strategy.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,53 @@
+/**
+ * @filedescription Merge Strategy
+ */
+
+"use strict";
+
+//-----------------------------------------------------------------------------
+// Class
+//-----------------------------------------------------------------------------
+
+/**
+ * Container class for several different merge strategies.
+ */
+class MergeStrategy {
+
+    /**
+     * Merges two keys by overwriting the first with the second.
+     * @param {*} value1 The value from the first object key. 
+     * @param {*} value2 The value from the second object key.
+     * @returns {*} The second value.
+     */
+    static overwrite(value1, value2) {
+        return value2;
+    }
+
+    /**
+     * Merges two keys by replacing the first with the second only if the
+     * second is defined.
+     * @param {*} value1 The value from the first object key. 
+     * @param {*} value2 The value from the second object key.
+     * @returns {*} The second value if it is defined.
+     */
+    static replace(value1, value2) {
+        if (typeof value2 !== "undefined") {
+            return value2;
+        }
+
+        return value1;
+    }
+
+    /**
+     * Merges two properties by assigning properties from the second to the first.
+     * @param {*} value1 The value from the first object key.
+     * @param {*} value2 The value from the second object key.
+     * @returns {*} A new object containing properties from both value1 and
+     *      value2.
+     */
+    static assign(value1, value2) {
+        return Object.assign({}, value1, value2);
+    }
+}
+
+exports.MergeStrategy = MergeStrategy;
Index: frontend/node_modules/@humanwhocodes/object-schema/src/object-schema.js
===================================================================
--- frontend/node_modules/@humanwhocodes/object-schema/src/object-schema.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/@humanwhocodes/object-schema/src/object-schema.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,301 @@
+/**
+ * @filedescription Object Schema
+ */
+
+"use strict";
+
+//-----------------------------------------------------------------------------
+// Requirements
+//-----------------------------------------------------------------------------
+
+const { MergeStrategy } = require("./merge-strategy");
+const { ValidationStrategy } = require("./validation-strategy");
+
+//-----------------------------------------------------------------------------
+// Private
+//-----------------------------------------------------------------------------
+
+const strategies = Symbol("strategies");
+const requiredKeys = Symbol("requiredKeys");
+
+/**
+ * Validates a schema strategy.
+ * @param {string} name The name of the key this strategy is for.
+ * @param {Object} strategy The strategy for the object key.
+ * @param {boolean} [strategy.required=true] Whether the key is required.
+ * @param {string[]} [strategy.requires] Other keys that are required when
+ *      this key is present.
+ * @param {Function} strategy.merge A method to call when merging two objects
+ *      with the same key.
+ * @param {Function} strategy.validate A method to call when validating an
+ *      object with the key.
+ * @returns {void}
+ * @throws {Error} When the strategy is missing a name.
+ * @throws {Error} When the strategy is missing a merge() method.
+ * @throws {Error} When the strategy is missing a validate() method.
+ */
+function validateDefinition(name, strategy) {
+
+    let hasSchema = false;
+    if (strategy.schema) {
+        if (typeof strategy.schema === "object") {
+            hasSchema = true;
+        } else {
+            throw new TypeError("Schema must be an object.");
+        }
+    }
+
+    if (typeof strategy.merge === "string") {
+        if (!(strategy.merge in MergeStrategy)) {
+            throw new TypeError(`Definition for key "${name}" missing valid merge strategy.`);
+        }
+    } else if (!hasSchema && typeof strategy.merge !== "function") {
+        throw new TypeError(`Definition for key "${name}" must have a merge property.`);
+    }
+
+    if (typeof strategy.validate === "string") {
+        if (!(strategy.validate in ValidationStrategy)) {
+            throw new TypeError(`Definition for key "${name}" missing valid validation strategy.`);
+        }
+    } else if (!hasSchema && typeof strategy.validate !== "function") {
+        throw new TypeError(`Definition for key "${name}" must have a validate() method.`);
+    }
+}
+
+//-----------------------------------------------------------------------------
+// Errors
+//-----------------------------------------------------------------------------
+
+/**
+ * Error when an unexpected key is found.
+ */
+class UnexpectedKeyError extends Error {
+
+    /**
+     * Creates a new instance.
+     * @param {string} key The key that was unexpected. 
+     */
+    constructor(key) {
+        super(`Unexpected key "${key}" found.`);
+    }
+}
+
+/**
+ * Error when a required key is missing.
+ */
+class MissingKeyError extends Error {
+
+    /**
+     * Creates a new instance.
+     * @param {string} key The key that was missing. 
+     */
+    constructor(key) {
+        super(`Missing required key "${key}".`);
+    }
+}
+
+/**
+ * Error when a key requires other keys that are missing.
+ */
+class MissingDependentKeysError extends Error {
+
+    /**
+     * Creates a new instance.
+     * @param {string} key The key that was unexpected.
+     * @param {Array<string>} requiredKeys The keys that are required.
+     */
+    constructor(key, requiredKeys) {
+        super(`Key "${key}" requires keys "${requiredKeys.join("\", \"")}".`);
+    }
+}
+
+/**
+ * Wrapper error for errors occuring during a merge or validate operation.
+ */
+class WrapperError extends Error {
+
+    /**
+     * Creates a new instance.
+     * @param {string} key The object key causing the error. 
+     * @param {Error} source The source error. 
+     */
+    constructor(key, source) {
+        super(`Key "${key}": ${source.message}`, { cause: source });
+
+        // copy over custom properties that aren't represented
+        for (const key of Object.keys(source)) {
+            if (!(key in this)) {
+                this[key] = source[key];
+            }
+        }
+    }
+}
+
+//-----------------------------------------------------------------------------
+// Main
+//-----------------------------------------------------------------------------
+
+/**
+ * Represents an object validation/merging schema.
+ */
+class ObjectSchema {
+
+    /**
+     * Creates a new instance.
+     */
+    constructor(definitions) {
+
+        if (!definitions) {
+            throw new Error("Schema definitions missing.");
+        }
+
+        /**
+         * Track all strategies in the schema by key.
+         * @type {Map}
+         * @property strategies
+         */
+        this[strategies] = new Map();
+
+        /**
+         * Separately track any keys that are required for faster validation.
+         * @type {Map}
+         * @property requiredKeys
+         */
+        this[requiredKeys] = new Map();
+
+        // add in all strategies
+        for (const key of Object.keys(definitions)) {
+            validateDefinition(key, definitions[key]);
+
+            // normalize merge and validate methods if subschema is present
+            if (typeof definitions[key].schema === "object") {
+                const schema = new ObjectSchema(definitions[key].schema);
+                definitions[key] = {
+                    ...definitions[key],
+                    merge(first = {}, second = {}) {
+                        return schema.merge(first, second);
+                    },
+                    validate(value) {
+                        ValidationStrategy.object(value);
+                        schema.validate(value);
+                    }
+                };
+            }
+
+            // normalize the merge method in case there's a string
+            if (typeof definitions[key].merge === "string") {
+                definitions[key] = {
+                    ...definitions[key],
+                    merge: MergeStrategy[definitions[key].merge]
+                };
+            };
+
+            // normalize the validate method in case there's a string
+            if (typeof definitions[key].validate === "string") {
+                definitions[key] = {
+                    ...definitions[key],
+                    validate: ValidationStrategy[definitions[key].validate]
+                };
+            };
+
+            this[strategies].set(key, definitions[key]);
+
+            if (definitions[key].required) {
+                this[requiredKeys].set(key, definitions[key]);
+            }
+        }
+    }
+
+    /**
+     * Determines if a strategy has been registered for the given object key.
+     * @param {string} key The object key to find a strategy for.
+     * @returns {boolean} True if the key has a strategy registered, false if not. 
+     */
+    hasKey(key) {
+        return this[strategies].has(key);
+    }
+
+    /**
+     * Merges objects together to create a new object comprised of the keys
+     * of the all objects. Keys are merged based on the each key's merge
+     * strategy.
+     * @param {...Object} objects The objects to merge.
+     * @returns {Object} A new object with a mix of all objects' keys.
+     * @throws {Error} If any object is invalid.
+     */
+    merge(...objects) {
+
+        // double check arguments
+        if (objects.length < 2) {
+            throw new TypeError("merge() requires at least two arguments.");
+        }
+
+        if (objects.some(object => (object == null || typeof object !== "object"))) {
+            throw new TypeError("All arguments must be objects.");
+        }
+
+        return objects.reduce((result, object) => {
+            
+            this.validate(object);
+            
+            for (const [key, strategy] of this[strategies]) {
+                try {
+                    if (key in result || key in object) {
+                        const value = strategy.merge.call(this, result[key], object[key]);
+                        if (value !== undefined) {
+                            result[key] = value;
+                        }
+                    }
+                } catch (ex) {
+                    throw new WrapperError(key, ex);
+                }
+            }
+            return result;
+        }, {});
+    }
+
+    /**
+     * Validates an object's keys based on the validate strategy for each key.
+     * @param {Object} object The object to validate.
+     * @returns {void}
+     * @throws {Error} When the object is invalid. 
+     */
+    validate(object) {
+
+        // check existing keys first
+        for (const key of Object.keys(object)) {
+
+            // check to see if the key is defined
+            if (!this.hasKey(key)) {
+                throw new UnexpectedKeyError(key);
+            }
+
+            // validate existing keys
+            const strategy = this[strategies].get(key);
+
+            // first check to see if any other keys are required
+            if (Array.isArray(strategy.requires)) {
+                if (!strategy.requires.every(otherKey => otherKey in object)) {
+                    throw new MissingDependentKeysError(key, strategy.requires);
+                }
+            }
+
+            // now apply remaining validation strategy
+            try {
+                strategy.validate.call(strategy, object[key]);
+            } catch (ex) {
+                throw new WrapperError(key, ex);
+            }
+        }
+
+        // ensure required keys aren't missing
+        for (const [key] of this[requiredKeys]) {
+            if (!(key in object)) {
+                throw new MissingKeyError(key);
+            }
+        }
+
+    }
+}
+
+exports.ObjectSchema = ObjectSchema;
Index: frontend/node_modules/@humanwhocodes/object-schema/src/validation-strategy.js
===================================================================
--- frontend/node_modules/@humanwhocodes/object-schema/src/validation-strategy.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/@humanwhocodes/object-schema/src/validation-strategy.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,102 @@
+/**
+ * @filedescription Validation Strategy
+ */
+
+"use strict";
+
+//-----------------------------------------------------------------------------
+// Class
+//-----------------------------------------------------------------------------
+
+/**
+ * Container class for several different validation strategies.
+ */
+class ValidationStrategy {
+
+    /**
+     * Validates that a value is an array.
+     * @param {*} value The value to validate.
+     * @returns {void}
+     * @throws {TypeError} If the value is invalid. 
+     */
+    static array(value) {
+        if (!Array.isArray(value)) {
+            throw new TypeError("Expected an array.");
+        }
+    }
+
+    /**
+     * Validates that a value is a boolean.
+     * @param {*} value The value to validate.
+     * @returns {void}
+     * @throws {TypeError} If the value is invalid. 
+     */
+    static boolean(value) {
+        if (typeof value !== "boolean") {
+            throw new TypeError("Expected a Boolean.");
+        }
+    }
+
+    /**
+     * Validates that a value is a number.
+     * @param {*} value The value to validate.
+     * @returns {void}
+     * @throws {TypeError} If the value is invalid. 
+     */
+    static number(value) {
+        if (typeof value !== "number") {
+            throw new TypeError("Expected a number.");
+        }
+    }
+
+    /**
+     * Validates that a value is a object.
+     * @param {*} value The value to validate.
+     * @returns {void}
+     * @throws {TypeError} If the value is invalid. 
+     */
+    static object(value) {
+        if (!value || typeof value !== "object") {
+            throw new TypeError("Expected an object.");
+        }
+    }
+
+    /**
+     * Validates that a value is a object or null.
+     * @param {*} value The value to validate.
+     * @returns {void}
+     * @throws {TypeError} If the value is invalid. 
+     */
+    static "object?"(value) {
+        if (typeof value !== "object") {
+            throw new TypeError("Expected an object or null.");
+        }
+    }
+
+    /**
+     * Validates that a value is a string.
+     * @param {*} value The value to validate.
+     * @returns {void}
+     * @throws {TypeError} If the value is invalid. 
+     */
+    static string(value) {
+        if (typeof value !== "string") {
+            throw new TypeError("Expected a string.");
+        }
+    }
+
+    /**
+     * Validates that a value is a non-empty string.
+     * @param {*} value The value to validate.
+     * @returns {void}
+     * @throws {TypeError} If the value is invalid. 
+     */
+    static "string!"(value) {
+        if (typeof value !== "string" || value.length === 0) {
+            throw new TypeError("Expected a non-empty string.");
+        }
+    }
+
+}
+
+exports.ValidationStrategy = ValidationStrategy;
