Prevent some empty name sheganigans
Some checks are pending
Tests and checks on push / run-checks-and-tests (push) Waiting to run
Updates translation progress / update-translation-progress-issue (push) Waiting to run

This commit is contained in:
Kalle 2025-03-08 10:21:42 +02:00
parent 0cb5f09def
commit d7109eff47
5 changed files with 33 additions and 20 deletions

View File

@ -3,16 +3,10 @@ import type { BuildAbilitiesTupleWithUnknown } from "./modules/in-game-lists";
export const TWEET_LENGTH_MAX_LENGTH = 280;
export const DISCORD_MESSAGE_MAX_LENGTH = 2000;
const EMPTY_CHARACTERS = ["\u200B", "\u200C", "\u200D", "\u200E", "\u200F"];
export const notAllEmptyCharactersRegExp = new RegExp(
`^(?!(${EMPTY_CHARACTERS.join("|")})+$).*$`,
);
export const USER = {
BIO_MAX_LENGTH: DISCORD_MESSAGE_MAX_LENGTH,
CUSTOM_URL_MAX_LENGTH: 32,
CUSTOM_NAME_MAX_LENGTH: 32,
CUSTOM_NAME_REGEXP: notAllEmptyCharactersRegExp,
BATTLEFY_MAX_LENGTH: 32,
IN_GAME_NAME_TEXT_MAX_LENGTH: 20,
IN_GAME_NAME_DISCRIMINATOR_MAX_LENGTH: 5,

View File

@ -1,11 +1,20 @@
import { z } from "zod";
import { _action, customCssVarObject, falsyToNull, id } from "~/utils/zod";
import {
_action,
actuallyNonEmptyStringOrNull,
customCssVarObject,
falsyToNull,
id,
} from "~/utils/zod";
import { TEAM, TEAM_MEMBER_ROLES } from "./team-constants";
export const teamParamsSchema = z.object({ customUrl: z.string() });
export const createTeamSchema = z.object({
name: z.string().min(TEAM.NAME_MIN_LENGTH).max(TEAM.NAME_MAX_LENGTH),
name: z.preprocess(
actuallyNonEmptyStringOrNull,
z.string().min(TEAM.NAME_MIN_LENGTH).max(TEAM.NAME_MAX_LENGTH),
),
});
export const teamProfilePageActionSchema = z.union([

View File

@ -1,6 +1,7 @@
import { z } from "zod";
import {
_action,
actuallyNonEmptyStringOrNull,
checkboxValueToBoolean,
id,
modeShort,
@ -11,11 +12,10 @@ import {
import { bracketIdx } from "../tournament-bracket/tournament-bracket-schemas.server";
import { TOURNAMENT } from "./tournament-constants";
export const teamName = z
.string()
.trim()
.min(1)
.max(TOURNAMENT.TEAM_NAME_MAX_LENGTH);
export const teamName = z.preprocess(
actuallyNonEmptyStringOrNull,
z.string().max(TOURNAMENT.TEAM_NAME_MAX_LENGTH),
);
export const registerSchema = z.union([
z.object({

View File

@ -41,6 +41,7 @@ import { rawSensToString } from "~/utils/strings";
import { FAQ_PAGE, isCustomUrl, userPage } from "~/utils/urls";
import {
actualNumber,
actuallyNonEmptyStringOrNull,
checkboxValueToDbBoolean,
customCssVarObject,
dbBoolean,
@ -87,13 +88,8 @@ export const userEditActionSchema = z
.nullable(),
),
customName: z.preprocess(
falsyToNull,
z
.string()
.trim()
.regex(USER.CUSTOM_NAME_REGEXP)
.max(USER.CUSTOM_NAME_MAX_LENGTH)
.nullable(),
actuallyNonEmptyStringOrNull,
z.string().max(USER.CUSTOM_NAME_MAX_LENGTH).nullable(),
),
battlefy: z.preprocess(
falsyToNull,

View File

@ -120,6 +120,20 @@ export function safeJSONParse(value: unknown): unknown {
}
}
const EMPTY_CHARACTERS = ["\u200B", "\u200C", "\u200D", "\u200E", "\u200F"];
const EMPTY_CHARACTERS_REGEX = new RegExp(EMPTY_CHARACTERS.join("|"), "g");
/**
* Processes the input value and returns a non-empty string with invisible characters cleaned out or null.
*/
export function actuallyNonEmptyStringOrNull(value: unknown) {
if (typeof value !== "string") return value;
const trimmed = value.replace(EMPTY_CHARACTERS_REGEX, "").trim();
return trimmed === "" ? null : trimmed;
}
/**
* Safely splits a string by a specified delimiter as Zod preprocess function.
*