mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-03-10 05:35:05 +08:00
Some Config Validation Fixes (#2558) by Ferotiq
* config validation fix * isConfigValueValid doesn't need to be async, can just return promise * split isConfigValueValid into a sync and an async function * Hopefully change layoutfluid message * fix * fix again * Update config.ts * fix * fix message thing and add validity enum * fixed custom theme not changing * Lots of changes * renamed to config-validation * added possible type async Co-authored-by: Miodec <bartnikjack@gmail.com>
This commit is contained in:
parent
0d6b58d56e
commit
fbea553fbf
5 changed files with 657 additions and 557 deletions
150
frontend/src/scripts/config-validation.ts
Normal file
150
frontend/src/scripts/config-validation.ts
Normal file
|
@ -0,0 +1,150 @@
|
|||
import * as Misc from "./misc";
|
||||
import * as Notifications from "./elements/notifications";
|
||||
|
||||
type PossibleType =
|
||||
| "string"
|
||||
| "number"
|
||||
| "numberArray"
|
||||
| "boolean"
|
||||
| "undefined"
|
||||
| "null"
|
||||
| "stringArray"
|
||||
| string[]
|
||||
| number[];
|
||||
|
||||
type PossibleTypeAsync = "layoutfluid";
|
||||
|
||||
export function isConfigKeyValid(name: string): boolean {
|
||||
if (name === null || name === undefined || name === "") return false;
|
||||
if (name.length > 30) return false;
|
||||
return /^[0-9a-zA-Z_.\-#+]+$/.test(name);
|
||||
}
|
||||
|
||||
function invalid(key: string, val: unknown, customMessage?: string): void {
|
||||
if (customMessage === undefined) {
|
||||
Notifications.add(
|
||||
`Invalid value for ${key} (${val}). Please try to change this setting again.`,
|
||||
-1
|
||||
);
|
||||
} else {
|
||||
Notifications.add(
|
||||
`Invalid value for ${key} (${val}). ${customMessage}`,
|
||||
-1
|
||||
);
|
||||
}
|
||||
|
||||
console.error(`Invalid value key ${key} value ${val} type ${typeof val}`);
|
||||
}
|
||||
|
||||
function isArray(val: unknown): val is unknown[] {
|
||||
return val instanceof Array;
|
||||
}
|
||||
|
||||
export function isConfigValueValid(
|
||||
key: string,
|
||||
val: unknown,
|
||||
possibleTypes: PossibleType[]
|
||||
): boolean {
|
||||
let isValid = false;
|
||||
|
||||
// might be used in the future
|
||||
// eslint-disable-next-line
|
||||
let customMessage: string | undefined = undefined;
|
||||
|
||||
for (const possibleType of possibleTypes) {
|
||||
switch (possibleType) {
|
||||
case "boolean":
|
||||
if (typeof val === "boolean") isValid = true;
|
||||
break;
|
||||
|
||||
case "null":
|
||||
if (val === null) isValid = true;
|
||||
break;
|
||||
|
||||
case "number":
|
||||
if (typeof val === "number") isValid = true;
|
||||
break;
|
||||
|
||||
case "numberArray":
|
||||
if (isArray(val) && val.every((v) => typeof v === "number"))
|
||||
isValid = true;
|
||||
break;
|
||||
|
||||
case "string":
|
||||
if (typeof val === "string") isValid = true;
|
||||
break;
|
||||
|
||||
case "stringArray":
|
||||
if (isArray(val) && val.every((v) => typeof v === "string"))
|
||||
isValid = true;
|
||||
break;
|
||||
|
||||
case "undefined":
|
||||
if (typeof val === "undefined" || val === undefined) isValid = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isArray(possibleType)) {
|
||||
if (possibleType.includes(<never>val)) isValid = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isValid) invalid(key, val, customMessage);
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
export async function isConfigValueValidAsync(
|
||||
key: string,
|
||||
val: unknown,
|
||||
possibleTypes: PossibleTypeAsync[]
|
||||
): Promise<boolean> {
|
||||
let isValid = false;
|
||||
|
||||
let customMessage: string | undefined = undefined;
|
||||
|
||||
for (const possibleType of possibleTypes) {
|
||||
switch (possibleType) {
|
||||
case "layoutfluid": {
|
||||
if (typeof val !== "string") break;
|
||||
|
||||
const layoutNames = val.split(/[# ]+/);
|
||||
|
||||
if (layoutNames.length < 2 || layoutNames.length > 5) break;
|
||||
|
||||
// convert the layout names to layouts
|
||||
const layouts = await Promise.all(
|
||||
layoutNames.map((layoutName) => Misc.getLayout(layoutName))
|
||||
);
|
||||
|
||||
// check if all layouts exist
|
||||
if (!layouts.every((layout) => layout !== undefined)) {
|
||||
const invalidLayoutNames = layoutNames.map((layoutName, index) => [
|
||||
layoutName,
|
||||
layouts[index],
|
||||
]);
|
||||
|
||||
const invalidLayouts = invalidLayoutNames
|
||||
.filter(([_, layout]) => layout === undefined)
|
||||
.map(([layoutName]) => layoutName);
|
||||
|
||||
customMessage = `The following inputted layouts do not exist: ${invalidLayouts.join(
|
||||
", "
|
||||
)}`;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
isValid = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isValid) invalid(key, val, customMessage);
|
||||
|
||||
return isValid;
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -2456,31 +2456,31 @@ const commandsMonkeyPowerLevel: MonkeyTypes.CommandsGroup = {
|
|||
id: "monkeyPowerLevelOff",
|
||||
display: "off",
|
||||
configValue: "off",
|
||||
exec: (): void => UpdateConfig.setMonkeyPowerLevel("off"),
|
||||
exec: () => UpdateConfig.setMonkeyPowerLevel("off"),
|
||||
},
|
||||
{
|
||||
id: "monkeyPowerLevel1",
|
||||
display: "mellow",
|
||||
configValue: "1",
|
||||
exec: (): void => UpdateConfig.setMonkeyPowerLevel("1"),
|
||||
exec: () => UpdateConfig.setMonkeyPowerLevel("1"),
|
||||
},
|
||||
{
|
||||
id: "monkeyPowerLevel2",
|
||||
display: "high",
|
||||
configValue: "2",
|
||||
exec: (): void => UpdateConfig.setMonkeyPowerLevel("2"),
|
||||
exec: () => UpdateConfig.setMonkeyPowerLevel("2"),
|
||||
},
|
||||
{
|
||||
id: "monkeyPowerLevel3",
|
||||
display: "ultra",
|
||||
configValue: "3",
|
||||
exec: (): void => UpdateConfig.setMonkeyPowerLevel("3"),
|
||||
exec: () => UpdateConfig.setMonkeyPowerLevel("3"),
|
||||
},
|
||||
{
|
||||
id: "monkeyPowerLevel4",
|
||||
display: "over 9000",
|
||||
configValue: "4",
|
||||
exec: (): void => UpdateConfig.setMonkeyPowerLevel("4"),
|
||||
exec: () => UpdateConfig.setMonkeyPowerLevel("4"),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
@ -2935,7 +2935,7 @@ export const defaultCommands: MonkeyTypes.CommandsGroup = {
|
|||
input: true,
|
||||
icon: "fa-tint",
|
||||
exec: (input): void => {
|
||||
if (!input) return;
|
||||
if (input === undefined) return;
|
||||
UpdateConfig.setCustomLayoutfluid(
|
||||
input as MonkeyTypes.CustomLayoutFluidSpaces
|
||||
);
|
||||
|
|
|
@ -196,7 +196,7 @@ export async function getLayoutsList(): Promise<MonkeyTypes.Layouts> {
|
|||
}
|
||||
|
||||
export async function getLayout(
|
||||
layoutName: keyof MonkeyTypes.Layouts & string
|
||||
layoutName: string
|
||||
): Promise<MonkeyTypes.Layout> {
|
||||
if (Object.keys(layoutsList).length === 0) {
|
||||
await getLayoutsList();
|
||||
|
|
|
@ -982,8 +982,11 @@ $(".pageSettings .section.customLayoutfluid .inputAndButton .save").on(
|
|||
$(
|
||||
".pageSettings .section.customLayoutfluid .inputAndButton input"
|
||||
).val() as MonkeyTypes.CustomLayoutFluidSpaces
|
||||
);
|
||||
Notifications.add("Custom layoutfluid saved", 1);
|
||||
).then(bool => {
|
||||
if (bool) {
|
||||
Notifications.add("Custom layoutfluid saved", 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -994,8 +997,11 @@ $(".pageSettings .section.customLayoutfluid .inputAndButton .input").keypress(
|
|||
$(
|
||||
".pageSettings .section.customLayoutfluid .inputAndButton input"
|
||||
).val() as MonkeyTypes.CustomLayoutFluidSpaces
|
||||
);
|
||||
Notifications.add("Custom layoutfluid saved", 1);
|
||||
).then(bool => {
|
||||
if (bool) {
|
||||
Notifications.add("Custom layoutfluid saved", 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue