refactor: migrate from ESLint to Biome and extract SQL queries to data.ts

- Replace ESLint with Biome for linting and formatting
- Configure Biome with tabs, double quotes, and organized imports
- Move all SQL/Drizzle queries from page.tsx files to data.ts files
- Create new data.ts files for: ajustes, dashboard, relatorios/categorias
- Update existing data.ts files: extrato, fatura (add lancamentos queries)
- Remove all drizzle-orm imports from page.tsx files
- Update README.md with new tooling info

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Felipe Coutinho
2026-01-27 13:15:37 +00:00
parent 8ffe61c59b
commit a7f63fb77a
442 changed files with 66141 additions and 69292 deletions

View File

@@ -1,6 +1,6 @@
import { getUser } from "@/lib/auth/server";
import { revalidatePath } from "next/cache";
import { z } from "zod";
import { getUser } from "@/lib/auth/server";
import type { ActionResult } from "./types";
import { errorResult } from "./types";
@@ -10,29 +10,29 @@ import { errorResult } from "./types";
* @returns ActionResult with error message
*/
export function handleActionError(error: unknown): ActionResult {
if (error instanceof z.ZodError) {
return errorResult(error.issues[0]?.message ?? "Dados inválidos.");
}
if (error instanceof z.ZodError) {
return errorResult(error.issues[0]?.message ?? "Dados inválidos.");
}
if (error instanceof Error) {
return errorResult(error.message);
}
if (error instanceof Error) {
return errorResult(error.message);
}
return errorResult("Erro inesperado.");
return errorResult("Erro inesperado.");
}
/**
* Configuration for revalidation after mutations
*/
export const revalidateConfig = {
cartoes: ["/cartoes"],
contas: ["/contas", "/lancamentos"],
categorias: ["/categorias"],
orcamentos: ["/orcamentos"],
pagadores: ["/pagadores"],
anotacoes: ["/anotacoes", "/anotacoes/arquivadas"],
lancamentos: ["/lancamentos", "/contas"],
inbox: ["/pre-lancamentos", "/lancamentos", "/dashboard"],
cartoes: ["/cartoes"],
contas: ["/contas", "/lancamentos"],
categorias: ["/categorias"],
orcamentos: ["/orcamentos"],
pagadores: ["/pagadores"],
anotacoes: ["/anotacoes", "/anotacoes/arquivadas"],
lancamentos: ["/lancamentos", "/contas"],
inbox: ["/pre-lancamentos", "/lancamentos", "/dashboard"],
} as const;
/**
@@ -40,19 +40,19 @@ export const revalidateConfig = {
* @param entity - The entity type
*/
export function revalidateForEntity(
entity: keyof typeof revalidateConfig
entity: keyof typeof revalidateConfig,
): void {
revalidateConfig[entity].forEach((path) => revalidatePath(path));
revalidateConfig[entity].forEach((path) => revalidatePath(path));
}
/**
* Options for action handler
*/
interface ActionHandlerOptions {
/** Paths to revalidate after successful execution */
revalidatePaths?: string[];
/** Entity to revalidate (uses predefined config) */
revalidateEntity?: keyof typeof revalidateConfig;
/** Paths to revalidate after successful execution */
revalidatePaths?: string[];
/** Entity to revalidate (uses predefined config) */
revalidateEntity?: keyof typeof revalidateConfig;
}
/**
@@ -76,36 +76,40 @@ interface ActionHandlerOptions {
* ```
*/
export function createActionHandler<TInput, TResult = string>(
schema: z.ZodSchema<TInput>,
handler: (data: TInput, userId: string) => Promise<TResult>,
options?: ActionHandlerOptions
schema: z.ZodSchema<TInput>,
handler: (data: TInput, userId: string) => Promise<TResult>,
options?: ActionHandlerOptions,
) {
return async (input: unknown): Promise<ActionResult<TResult>> => {
try {
// Get authenticated user
const user = await getUser();
return async (input: unknown): Promise<ActionResult<TResult>> => {
try {
// Get authenticated user
const user = await getUser();
// Validate input
const data = schema.parse(input);
// Validate input
const data = schema.parse(input);
// Execute handler
const result = await handler(data, user.id);
// Execute handler
const result = await handler(data, user.id);
// Revalidate paths if configured
if (options?.revalidateEntity) {
revalidateForEntity(options.revalidateEntity);
} else if (options?.revalidatePaths) {
options.revalidatePaths.forEach((path) => revalidatePath(path));
}
// Revalidate paths if configured
if (options?.revalidateEntity) {
revalidateForEntity(options.revalidateEntity);
} else if (options?.revalidatePaths) {
options.revalidatePaths.forEach((path) => revalidatePath(path));
}
// Return success with message (if result is string) or data
if (typeof result === "string") {
return { success: true, message: result };
}
// Return success with message (if result is string) or data
if (typeof result === "string") {
return { success: true, message: result };
}
return { success: true, message: "Operação realizada com sucesso.", data: result };
} catch (error) {
return handleActionError(error);
}
};
return {
success: true,
message: "Operação realizada com sucesso.",
data: result,
};
} catch (error) {
return handleActionError(error);
}
};
}

View File

@@ -2,22 +2,22 @@
* Standard action result type
*/
export type ActionResult<TData = void> =
| { success: true; message: string; data?: TData }
| { success: false; error: string };
| { success: true; message: string; data?: TData }
| { success: false; error: string };
/**
* Success result helper
*/
export function successResult<TData = void>(
message: string,
data?: TData
message: string,
data?: TData,
): ActionResult<TData> {
return { success: true, message, data };
return { success: true, message, data };
}
/**
* Error result helper
*/
export function errorResult(error: string): ActionResult {
return { success: false, error };
return { success: false, error };
}