chore: add typed ESLint checks #18
Refs WealthLedger/main#18. Keep Biome; add no Prettier dependencies.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
export { AuthProvider, useAuth } from "./model/auth";
|
||||
export { AuthProvider } from "./model/auth";
|
||||
export { useAuth } from "./model/auth-context";
|
||||
export { AuthPageLayout } from "./ui/AuthPageLayout/AuthPageLayout";
|
||||
export { LoginForm } from "./ui/LoginForm";
|
||||
export { RegisterForm } from "./ui/RegisterForm";
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { createContext, useContext } from "react";
|
||||
import type { paths } from "@/shared/api";
|
||||
|
||||
type User =
|
||||
paths["/api/v1/auth/me"]["get"]["responses"][200]["content"]["application/json"];
|
||||
type AuthContextValue = {
|
||||
user: User | null;
|
||||
accessToken: string | null;
|
||||
ready: boolean;
|
||||
login: (email: string, password: string) => Promise<void>;
|
||||
register: (email: string, password: string) => Promise<void>;
|
||||
logout: () => Promise<void>;
|
||||
refresh: () => Promise<boolean>;
|
||||
};
|
||||
const AuthContext = createContext<AuthContextValue | null>(null);
|
||||
|
||||
function useAuth() {
|
||||
const context = useContext(AuthContext);
|
||||
if (!context) throw new Error("AuthProvider is required");
|
||||
return context;
|
||||
}
|
||||
|
||||
export { AuthContext, type User, useAuth };
|
||||
@@ -7,7 +7,8 @@ import { apiClient, apiQueryClient, useAuthenticatedQuery } from "@/shared/api";
|
||||
import { createTestQueryClient } from "@/test/query";
|
||||
import { resource } from "@/test/resource";
|
||||
import { server } from "@/test/server";
|
||||
import { AuthProvider, useAuth } from "./auth";
|
||||
import { AuthProvider } from "./auth";
|
||||
import { useAuth } from "./auth-context";
|
||||
|
||||
const bankCardsKey = apiQueryClient.queryOptions("get", "/api/v1/bank-cards", {
|
||||
params: { query: { includeArchived: "false" } },
|
||||
|
||||
@@ -1,32 +1,13 @@
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import type { FC, PropsWithChildren } from "react";
|
||||
import {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { apiClient, configureAuthClient, type paths } from "@/shared/api";
|
||||
import { AuthContext, type User } from "./auth-context";
|
||||
|
||||
type User =
|
||||
paths["/api/v1/auth/me"]["get"]["responses"][200]["content"]["application/json"];
|
||||
type Authentication =
|
||||
paths["/api/v1/auth/login"]["post"]["responses"][200]["content"]["application/json"];
|
||||
type Credentials =
|
||||
paths["/api/v1/auth/login"]["post"]["requestBody"]["content"]["application/json"];
|
||||
type AuthContextValue = {
|
||||
user: User | null;
|
||||
accessToken: string | null;
|
||||
ready: boolean;
|
||||
login: (email: string, password: string) => Promise<void>;
|
||||
register: (email: string, password: string) => Promise<void>;
|
||||
logout: () => Promise<void>;
|
||||
refresh: () => Promise<boolean>;
|
||||
};
|
||||
const AuthContext = createContext<AuthContextValue | null>(null);
|
||||
|
||||
async function request(
|
||||
path: "/api/v1/auth/login" | "/api/v1/auth/register",
|
||||
email: string,
|
||||
@@ -35,8 +16,9 @@ async function request(
|
||||
const { data, error } = await apiClient.POST(path, {
|
||||
body: { email, password },
|
||||
} satisfies { body: Credentials });
|
||||
// eslint-disable-next-line @typescript-eslint/only-throw-error -- Preserve generated ProblemDetails for apiErrorCode and field-error consumers.
|
||||
if (error) throw error;
|
||||
return data as Authentication;
|
||||
return data;
|
||||
}
|
||||
|
||||
const AuthProvider: FC<PropsWithChildren> = (props) => {
|
||||
@@ -165,10 +147,4 @@ const AuthProvider: FC<PropsWithChildren> = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
function useAuth() {
|
||||
const context = useContext(AuthContext);
|
||||
if (!context) throw new Error("AuthProvider is required");
|
||||
return context;
|
||||
}
|
||||
|
||||
export { AuthProvider, useAuth };
|
||||
export { AuthProvider };
|
||||
|
||||
@@ -27,8 +27,6 @@ describe("AuthForm", () => {
|
||||
fireEvent.click(screen.getByRole("button", { name: "Регистрация" }));
|
||||
|
||||
await waitFor(() => expect(onSubmit).not.toHaveBeenCalled());
|
||||
await waitFor(() =>
|
||||
expect(screen.getByText("Пароли не совпадают")).toBeInTheDocument(),
|
||||
);
|
||||
expect(await screen.findByText("Пароли не совпадают")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { FC } from "react";
|
||||
import { useLocation, useNavigate } from "react-router";
|
||||
import { useAuth } from "../model/auth";
|
||||
import { useAuth } from "../model/auth-context";
|
||||
import { AuthForm } from "./AuthForm/AuthForm";
|
||||
|
||||
const LoginForm: FC = () => {
|
||||
@@ -14,7 +14,7 @@ const LoginForm: FC = () => {
|
||||
<AuthForm
|
||||
onSubmit={async (email, password) => {
|
||||
await login(email, password);
|
||||
navigate(returnTo, { replace: true });
|
||||
await navigate(returnTo, { replace: true });
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { FC } from "react";
|
||||
import { useLocation, useNavigate } from "react-router";
|
||||
import { useAuth } from "../model/auth";
|
||||
import { useAuth } from "../model/auth-context";
|
||||
import { AuthForm } from "./AuthForm/AuthForm";
|
||||
|
||||
const RegisterForm: FC = () => {
|
||||
@@ -15,7 +15,7 @@ const RegisterForm: FC = () => {
|
||||
register
|
||||
onSubmit={async (email, password) => {
|
||||
await register(email, password);
|
||||
navigate(returnTo, { replace: true });
|
||||
await navigate(returnTo, { replace: true });
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user