Repository: pyscript/pyscript
File: pyscriptjs/src/plugin.ts (TypeScript)

Code before:
export function validateConfigParameter(options: {
    config: AppConfig;
    name: string;
    validator: (b: BaseConfigObject) => boolean;
    defaultValue: BaseConfigObject;
    hintMessage?: string;
}) {
    //Validate that the default value is acceptable, at runtime
    if (!options.validator(options.defaultValue)) {
        throw Error(
            `Default value ${JSON.stringify(options.defaultValue)} for ${options.name} is not a valid argument, ` +
                `according to the provided validator function. ${options.hintMessage ? options.hintMessage : ''}`,
        );
    }

    const value = options.config[options.name] as BaseConfigObject;
    if (value !== undefined && !options.validator(value)) {
        //Use default hint message if none is provided:
        const hintOutput = `Invalid value ${JSON.stringify(value)} for config.${options.name}. ${
            options.hintMessage ? options.hintMessage : ''
        }`;
        throw new UserError(ErrorCode.BAD_CONFIG, hintOutput);
    }
    if (value === undefined) {
        options.config[options.name] = options.defaultValue;
    }
}

/**
 * Validate that parameter the user provided to py-config is one of the acceptable values in
 * the given Array; if not, throw an error explaining the bad value
 * @param options.config - The (extended) AppConfig object from py-config
 * @param {string} options.name - The name of the key in py-config to be checked
 * @param {Array<BaseConfigObject>} options.possibleValues: The acceptable values for this parameter
 * @param {BaseConfigObject} options.defaultValue: The default value for this parameter, if none is provided
 */
export function validateConfigParameterFromArray(options: {
    config: AppConfig;
    name: string;
    possibleValues: Array<BaseConfigObject>;
    defaultValue: BaseConfigObject;
}) {
    const validator = (b: BaseConfigObject) => options.possibleValues.includes(b);
    const hint = `The only accepted values are: [${options.possibleValues
        .map(item => JSON.stringify(item))
        .join(', ')}]`;

    validateConfigParameter({
        config: options.config,
        name: options.name,
        validator: validator,

Review comment (bug):
Hi, just wondering why do we fill the default value here?
I mean, the purpose is just validation right? If value extracted is `undefined`.
Then, shouldn't we throw an error here as well? Since we are trying to validate an `undefined` value.

Code after:
 */
export function validateConfigParameter(options: {
    config: AppConfig;
    name: string;
    validator: (b: BaseConfigObject) => boolean;
    defaultValue: BaseConfigObject;
    hintMessage?: string;
}) {
    //Validate that the default value is acceptable, at runtime
    if (!options.validator(options.defaultValue)) {
        throw Error(
            `Default value ${JSON.stringify(options.defaultValue)} for ${options.name} is not a valid argument, ` +
                `according to the provided validator function. ${options.hintMessage ? options.hintMessage : ''}`,
        );
    }

    const value = options.config[options.name] as BaseConfigObject;
    if (value !== undefined && !options.validator(value)) {
        //Use default hint message if none is provided:
        const hintOutput = `Invalid value ${JSON.stringify(value)} for config.${options.name}. ${
            options.hintMessage ? options.hintMessage : ''
        }`;
        throw new UserError(ErrorCode.BAD_CONFIG, hintOutput);
    }
    if (value === undefined) {
        options.config[options.name] = options.defaultValue;
    }
}

/**
 * Validate that parameter the user provided to py-config is one of the acceptable values in
 * the given Array; if not, throw an error explaining the bad value. If no value is provided,
 * set the parameter to the provided default value
 * @param options.config - The (extended) AppConfig object from py-config
 * @param {string} options.name - The name of the key in py-config to be checked
 * @param {Array<BaseConfigObject>} options.possibleValues: The acceptable values for this parameter
 * @param {BaseConfigObject} options.defaultValue: The default value for this parameter, if none is provided
 */
export function validateConfigParameterFromArray(options: {
    config: AppConfig;
    name: string;
    possibleValues: Array<BaseConfigObject>;
    defaultValue: BaseConfigObject;
}) {
    const validator = (b: BaseConfigObject) => options.possibleValues.includes(b);
    const hint = `The only accepted values are: [${options.possibleValues
        .map(item => JSON.stringify(item))
        .join(', ')}]`;

    validateConfigParameter({
        config: options.config,