style: clean up code formatting and remove trailing whitespace
refactor: reorganize imports and fix type imports
This commit is contained in:
1 parent
d3704602fd
commit
47c04de6fe
232 files changed
+7140
-4798
No files matched your search
+185
-163
@@ -1,7 +1,7 @@
|
||||
import { z } from "zod";
|
||||
import validator from "validator";
|
||||
import { isValidDocument } from "./validators/document-validator";
|
||||
import sanitizeHtml from "sanitize-html";
|
||||
import validator from "validator";
|
||||
import { z } from "zod";
|
||||
import { isValidDocument } from "./validators/document-validator";
|
||||
|
||||
/**
|
||||
* Schemas de validação usando Zod
|
||||
@@ -59,7 +59,7 @@ export const nameSchema = z
|
||||
.max(100, "Nome deve ter no máximo 100 caracteres")
|
||||
.refine(
|
||||
(name) => /^[A-Za-zÀ-ÿ\s'-]+$/.test(name.trim()),
|
||||
"Nome deve conter apenas letras, espaços e acentos"
|
||||
"Nome deve conter apenas letras, espaços e acentos",
|
||||
)
|
||||
.transform((name) => name.trim());
|
||||
|
||||
@@ -82,7 +82,7 @@ export const donationTierSchema = z.enum(
|
||||
["coffee", "snack", "lunch", "custom"],
|
||||
{
|
||||
message: "Tier de doação inválido",
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Schema para valor customizado
|
||||
@@ -123,7 +123,7 @@ export const createDonationSchema = z
|
||||
{
|
||||
message: "customAmount é obrigatório quando tier é 'custom'",
|
||||
path: ["customAmount"],
|
||||
}
|
||||
},
|
||||
)
|
||||
.refine(
|
||||
(data) => {
|
||||
@@ -136,7 +136,7 @@ export const createDonationSchema = z
|
||||
{
|
||||
message: "Valor deve estar entre R$ 5,00 e R$ 100.000,00",
|
||||
path: ["customAmount"],
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Schema para verificação de status
|
||||
@@ -160,7 +160,7 @@ export const usernameSchema = z
|
||||
.max(50, "Username deve ter no máximo 50 caracteres")
|
||||
.regex(
|
||||
/^[a-zA-Z0-9_]+$/,
|
||||
"Username deve conter apenas letras, números e underscore"
|
||||
"Username deve conter apenas letras, números e underscore",
|
||||
)
|
||||
.transform((username) => username.toLowerCase().trim());
|
||||
|
||||
@@ -181,7 +181,7 @@ export const passwordSchema = z
|
||||
{
|
||||
message:
|
||||
"Senha deve conter pelo menos 1 letra maiúscula, 1 letra minúscula e 1 número",
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Schema para servidor/personagem no registro
|
||||
@@ -211,7 +211,10 @@ const subscriptionTierFeatureSchema = z.object({
|
||||
.string()
|
||||
.min(2, "featureKey deve ter no mínimo 2 caracteres")
|
||||
.max(100, "featureKey deve ter no máximo 100 caracteres")
|
||||
.regex(featureKeyRegex, "featureKey deve conter apenas letras, números, ponto, hífen ou underscore")
|
||||
.regex(
|
||||
featureKeyRegex,
|
||||
"featureKey deve conter apenas letras, números, ponto, hífen ou underscore",
|
||||
)
|
||||
.transform((key) => key.trim().toLowerCase()),
|
||||
label: z
|
||||
.string()
|
||||
@@ -238,7 +241,10 @@ export const createSubscriptionTierSchema = z
|
||||
.string()
|
||||
.min(2, "Slug deve ter no mínimo 2 caracteres")
|
||||
.max(50, "Slug deve ter no máximo 50 caracteres")
|
||||
.regex(tierSlugRegex, "Slug deve conter apenas letras minúsculas, números e hífen")
|
||||
.regex(
|
||||
tierSlugRegex,
|
||||
"Slug deve conter apenas letras minúsculas, números e hífen",
|
||||
)
|
||||
.transform((value) => value.trim().toLowerCase()),
|
||||
description: z
|
||||
.string()
|
||||
@@ -267,7 +273,7 @@ export const createSubscriptionTierSchema = z
|
||||
{
|
||||
message: "Preço anual deve ser maior ou igual ao mensal",
|
||||
path: ["priceYearly"],
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
export const updateSubscriptionTierSchema = createSubscriptionTierSchema
|
||||
@@ -277,7 +283,10 @@ export const updateSubscriptionTierSchema = createSubscriptionTierSchema
|
||||
.string()
|
||||
.min(2, "Slug deve ter no mínimo 2 caracteres")
|
||||
.max(50, "Slug deve ter no máximo 50 caracteres")
|
||||
.regex(tierSlugRegex, "Slug deve conter apenas letras minúsculas, números e hífen")
|
||||
.regex(
|
||||
tierSlugRegex,
|
||||
"Slug deve conter apenas letras minúsculas, números e hífen",
|
||||
)
|
||||
.transform((value) => value.trim().toLowerCase())
|
||||
.optional(),
|
||||
features: z
|
||||
@@ -285,7 +294,7 @@ export const updateSubscriptionTierSchema = createSubscriptionTierSchema
|
||||
subscriptionTierFeatureSchema.extend({
|
||||
featureId: z.number().int().positive().optional(),
|
||||
_delete: z.boolean().optional(),
|
||||
})
|
||||
}),
|
||||
)
|
||||
.max(50)
|
||||
.optional(),
|
||||
@@ -299,17 +308,17 @@ export const assignSubscriptionTierSchema = z
|
||||
.string()
|
||||
.min(2, "Slug deve ter no mínimo 2 caracteres")
|
||||
.max(50, "Slug deve ter no máximo 50 caracteres")
|
||||
.regex(tierSlugRegex, "Slug deve conter apenas letras minúsculas, números e hífen")
|
||||
.regex(
|
||||
tierSlugRegex,
|
||||
"Slug deve conter apenas letras minúsculas, números e hífen",
|
||||
)
|
||||
.transform((value) => value.trim().toLowerCase())
|
||||
.optional(),
|
||||
})
|
||||
.refine(
|
||||
(data) => data.tierId !== undefined || data.tierSlug !== undefined,
|
||||
{
|
||||
message: "Informe tierId ou tierSlug",
|
||||
path: ["tierId"],
|
||||
}
|
||||
);
|
||||
.refine((data) => data.tierId !== undefined || data.tierSlug !== undefined, {
|
||||
message: "Informe tierId ou tierSlug",
|
||||
path: ["tierId"],
|
||||
});
|
||||
|
||||
// Schema para registro de usuário
|
||||
export const registerSchema = z.object({
|
||||
@@ -361,159 +370,172 @@ export const characterSchema = z.object({
|
||||
// ============================================
|
||||
|
||||
// Schema para criar anúncio (listing)
|
||||
export const createListingSchema = z.object({
|
||||
item_id: z.number().int().positive("ID do item deve ser positivo").optional(), // ID legado (SQLite) - opcional
|
||||
item_id_unified: z.number().int().positive("ID unificado do item deve ser positivo").optional(), // ID unificado da tabela items - preferido
|
||||
item_name: z
|
||||
.string()
|
||||
.min(1, "Nome do item é obrigatório")
|
||||
.max(255, "Nome do item deve ter no máximo 255 caracteres")
|
||||
.transform((name) => name.trim()),
|
||||
quantity: z
|
||||
.number()
|
||||
.int()
|
||||
.positive("Quantidade deve ser maior que zero")
|
||||
.default(1),
|
||||
server_name: z
|
||||
.string()
|
||||
.min(1, "Nome do servidor é obrigatório")
|
||||
.max(50, "Nome do servidor deve ter no máximo 50 caracteres")
|
||||
.transform((name) => name.trim()),
|
||||
price_pix: z
|
||||
.number()
|
||||
.positive("Preço PIX deve ser positivo")
|
||||
.optional()
|
||||
.nullable(),
|
||||
price_tibia_coins: z
|
||||
.number()
|
||||
.int()
|
||||
.min(0, "Preço em Tibia Coins deve ser não negativo")
|
||||
.optional()
|
||||
.nullable(),
|
||||
price_gold_coins: z
|
||||
.number()
|
||||
.int()
|
||||
.min(0, "Preço em Gold Coins deve ser não negativo")
|
||||
.optional()
|
||||
.nullable(),
|
||||
is_auction: z.boolean().optional().default(false),
|
||||
auction_ends_at: z
|
||||
.string()
|
||||
.datetime("Data de término do leilão inválida")
|
||||
.optional()
|
||||
.nullable()
|
||||
.transform((val) => (val ? new Date(val) : null)),
|
||||
description: z
|
||||
.string()
|
||||
.max(5000, "Descrição deve ter no máximo 5000 caracteres")
|
||||
.optional()
|
||||
.nullable()
|
||||
.transform((val) => val?.trim() || null),
|
||||
// Campos para troca por item
|
||||
trade_item_id: z
|
||||
.number()
|
||||
.int()
|
||||
.positive("ID do item de troca deve ser positivo")
|
||||
.optional()
|
||||
.nullable(),
|
||||
trade_item_name: z
|
||||
.string()
|
||||
.min(1, "Nome do item de troca é obrigatório se trade_item_id for fornecido")
|
||||
.max(255, "Nome do item de troca deve ter no máximo 255 caracteres")
|
||||
.optional()
|
||||
.nullable()
|
||||
.transform((name) => name?.trim() || null),
|
||||
trade_item_quantity: z
|
||||
.number()
|
||||
.int()
|
||||
.positive("Quantidade do item de troca deve ser maior que zero")
|
||||
.optional()
|
||||
.nullable()
|
||||
.default(1),
|
||||
})
|
||||
.refine(
|
||||
(data) => {
|
||||
// Pelo menos um ID (item_id ou item_id_unified) deve ser fornecido
|
||||
if (!data.item_id && !data.item_id_unified) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
{
|
||||
message: "Pelo menos um ID do item (item_id ou item_id_unified) deve ser fornecido",
|
||||
path: ["item_id"],
|
||||
}
|
||||
)
|
||||
.refine(
|
||||
(data) => {
|
||||
// Se trade_item_id for fornecido, trade_item_name também deve ser
|
||||
if (data.trade_item_id && !data.trade_item_name) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
{
|
||||
message: "Nome do item de troca é obrigatório quando ID é fornecido",
|
||||
path: ["trade_item_name"],
|
||||
}
|
||||
)
|
||||
.refine(
|
||||
(data) => {
|
||||
// Pelo menos um preço ou troca por item deve ser fornecido
|
||||
return (
|
||||
data.price_pix !== null ||
|
||||
data.price_tibia_coins !== null ||
|
||||
data.price_gold_coins !== null ||
|
||||
data.trade_item_id !== null
|
||||
);
|
||||
},
|
||||
{
|
||||
message: "Pelo menos um método de pagamento (PIX, Tibia Coins ou Gold Coins) deve ser especificado",
|
||||
path: ["price_pix"],
|
||||
}
|
||||
).refine(
|
||||
(data) => {
|
||||
// Se for leilão, deve ter data de término
|
||||
if (data.is_auction && !data.auction_ends_at) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
{
|
||||
message: "Data de término do leilão é obrigatória quando is_auction é true",
|
||||
path: ["auction_ends_at"],
|
||||
}
|
||||
);
|
||||
export const createListingSchema = z
|
||||
.object({
|
||||
item_id: z
|
||||
.number()
|
||||
.int()
|
||||
.positive("ID do item deve ser positivo")
|
||||
.optional(), // ID legado (SQLite) - opcional
|
||||
item_id_unified: z
|
||||
.number()
|
||||
.int()
|
||||
.positive("ID unificado do item deve ser positivo")
|
||||
.optional(), // ID unificado da tabela items - preferido
|
||||
item_name: z
|
||||
.string()
|
||||
.min(1, "Nome do item é obrigatório")
|
||||
.max(255, "Nome do item deve ter no máximo 255 caracteres")
|
||||
.transform((name) => name.trim()),
|
||||
quantity: z
|
||||
.number()
|
||||
.int()
|
||||
.positive("Quantidade deve ser maior que zero")
|
||||
.default(1),
|
||||
server_name: z
|
||||
.string()
|
||||
.min(1, "Nome do servidor é obrigatório")
|
||||
.max(50, "Nome do servidor deve ter no máximo 50 caracteres")
|
||||
.transform((name) => name.trim()),
|
||||
price_pix: z
|
||||
.number()
|
||||
.positive("Preço PIX deve ser positivo")
|
||||
.optional()
|
||||
.nullable(),
|
||||
price_tibia_coins: z
|
||||
.number()
|
||||
.int()
|
||||
.min(0, "Preço em Tibia Coins deve ser não negativo")
|
||||
.optional()
|
||||
.nullable(),
|
||||
price_gold_coins: z
|
||||
.number()
|
||||
.int()
|
||||
.min(0, "Preço em Gold Coins deve ser não negativo")
|
||||
.optional()
|
||||
.nullable(),
|
||||
is_auction: z.boolean().optional().default(false),
|
||||
auction_ends_at: z
|
||||
.string()
|
||||
.datetime("Data de término do leilão inválida")
|
||||
.optional()
|
||||
.nullable()
|
||||
.transform((val) => (val ? new Date(val) : null)),
|
||||
description: z
|
||||
.string()
|
||||
.max(5000, "Descrição deve ter no máximo 5000 caracteres")
|
||||
.optional()
|
||||
.nullable()
|
||||
.transform((val) => val?.trim() || null),
|
||||
// Campos para troca por item
|
||||
trade_item_id: z
|
||||
.number()
|
||||
.int()
|
||||
.positive("ID do item de troca deve ser positivo")
|
||||
.optional()
|
||||
.nullable(),
|
||||
trade_item_name: z
|
||||
.string()
|
||||
.min(
|
||||
1,
|
||||
"Nome do item de troca é obrigatório se trade_item_id for fornecido",
|
||||
)
|
||||
.max(255, "Nome do item de troca deve ter no máximo 255 caracteres")
|
||||
.optional()
|
||||
.nullable()
|
||||
.transform((name) => name?.trim() || null),
|
||||
trade_item_quantity: z
|
||||
.number()
|
||||
.int()
|
||||
.positive("Quantidade do item de troca deve ser maior que zero")
|
||||
.optional()
|
||||
.nullable()
|
||||
.default(1),
|
||||
})
|
||||
.refine(
|
||||
(data) => {
|
||||
// Pelo menos um ID (item_id ou item_id_unified) deve ser fornecido
|
||||
if (!data.item_id && !data.item_id_unified) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
{
|
||||
message:
|
||||
"Pelo menos um ID do item (item_id ou item_id_unified) deve ser fornecido",
|
||||
path: ["item_id"],
|
||||
},
|
||||
)
|
||||
.refine(
|
||||
(data) => {
|
||||
// Se trade_item_id for fornecido, trade_item_name também deve ser
|
||||
if (data.trade_item_id && !data.trade_item_name) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
{
|
||||
message: "Nome do item de troca é obrigatório quando ID é fornecido",
|
||||
path: ["trade_item_name"],
|
||||
},
|
||||
)
|
||||
.refine(
|
||||
(data) => {
|
||||
// Pelo menos um preço ou troca por item deve ser fornecido
|
||||
return (
|
||||
data.price_pix !== null ||
|
||||
data.price_tibia_coins !== null ||
|
||||
data.price_gold_coins !== null ||
|
||||
data.trade_item_id !== null
|
||||
);
|
||||
},
|
||||
{
|
||||
message:
|
||||
"Pelo menos um método de pagamento (PIX, Tibia Coins ou Gold Coins) deve ser especificado",
|
||||
path: ["price_pix"],
|
||||
},
|
||||
)
|
||||
.refine(
|
||||
(data) => {
|
||||
// Se for leilão, deve ter data de término
|
||||
if (data.is_auction && !data.auction_ends_at) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
{
|
||||
message:
|
||||
"Data de término do leilão é obrigatória quando is_auction é true",
|
||||
path: ["auction_ends_at"],
|
||||
},
|
||||
);
|
||||
|
||||
// Schema para atualizar anúncio
|
||||
export const updateListingSchema = z.object({
|
||||
quantity: z.number().int().positive().optional(),
|
||||
price_pix: z.number().positive().optional().nullable(),
|
||||
price_tibia_coins: z.number().int().min(0).optional().nullable(),
|
||||
price_gold_coins: z.number().int().min(0).optional().nullable(),
|
||||
description: z.string().max(5000).optional().nullable(),
|
||||
listing_status: z
|
||||
.enum(["active", "sold", "cancelled", "in_escrow", "expired"])
|
||||
.optional(),
|
||||
}).refine(
|
||||
(data) => {
|
||||
export const updateListingSchema = z
|
||||
.object({
|
||||
quantity: z.number().int().positive().optional(),
|
||||
price_pix: z.number().positive().optional().nullable(),
|
||||
price_tibia_coins: z.number().int().min(0).optional().nullable(),
|
||||
price_gold_coins: z.number().int().min(0).optional().nullable(),
|
||||
description: z.string().max(5000).optional().nullable(),
|
||||
listing_status: z
|
||||
.enum(["active", "sold", "cancelled", "in_escrow", "expired"])
|
||||
.optional(),
|
||||
})
|
||||
.refine((data) => {
|
||||
// Se atualizando preços, pelo menos um deve ser fornecido ou manter existentes
|
||||
const hasPrice =
|
||||
const _hasPrice =
|
||||
data.price_pix !== undefined ||
|
||||
data.price_tibia_coins !== undefined ||
|
||||
data.price_gold_coins !== undefined;
|
||||
return true; // Permite atualizar sem especificar preços (mantém existentes)
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Schema para criar lance (bid)
|
||||
export const bidSchema = z.object({
|
||||
listing_id: z.number().int().positive("ID do anúncio deve ser positivo"),
|
||||
bid_amount: z.number().positive("Valor do lance deve ser positivo"),
|
||||
bid_type: z
|
||||
.enum(["pix", "tibia_coins", "gold_coins"])
|
||||
.optional()
|
||||
.nullable(),
|
||||
bid_type: z.enum(["pix", "tibia_coins", "gold_coins"]).optional().nullable(),
|
||||
});
|
||||
|
||||
// ============================================
|
||||
|
||||
Reference in new issue
Block a user